rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
storage_list.c File Reference

Listing the mounted card: storage_walk(), storage_walk_counted(), storage_stat(), storage_dir_open() and its reads, and storage_path(). More...

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "storage.h"
#include "storage_priv.h"
#include "ff.h"
#include "esp_heap_caps.h"
#include "esp_log.h"

Data Structures

struct  walk_buf_t
struct  storage_dir
 An open folder: FatFs's handle, its entry, and the last read's answer for the close. More...

Functions

void storage_path (const char *dir, const char *name, char *out, size_t out_size)
static bool suffix_matches (const char *name, const char *suffixes)
 Whether name ends in one of suffixes, case folded.
static int walk_held (const char *dir, const char *suffixes, storage_visit_fn visit, void *ctx, storage_tick_fn tick, int *fr_out, unsigned *left_out)
 The walk itself, under a hold.
int storage_walk (const char *dir, const char *suffixes, storage_visit_fn visit, void *ctx, storage_tick_fn tick)
 Walk a directory, handing every matching entry to visit, with its size (0 for a directory) and its FAT stamp.
int storage_walk_counted (const char *dir, const char *suffixes, storage_visit_fn visit, void *ctx, storage_tick_fn tick, unsigned *left_out)
 storage_walk(), and the count of the entries its name filters left out: names starting with "." and names of STORAGE_NAME_MAX characters or more. Entries the suffix filter leaves out are not counted.
static int64_t fat_mtime (WORD fdate, WORD ftime)
 FAT's date and time stamp as local time, the way ESP-IDF's stat() reads it (components/fatfs/vfs/vfs_fat.c, update_stat_struct()): the date's bits 15..9 are years from 1980, 8..5 the month, 4..0 the day; the time's 15..11 the hour, 10..5 the minute, 4..0 seconds in steps of 2.
int64_t storage_stamp_mtime (uint32_t stamp)
 A storage_entry_t stamp as the time storage_stat() gives the same file: FAT's local date and time through mktime(), in the zone in force (TZ).
static esp_err_t stat_held (const char *rel, storage_stat_t *out, int *fr_out)
 storage_stat() under a hold, from the path below the mount point, "" or "/...".
esp_err_t storage_stat (const char *path, storage_stat_t *out)
 The size, kind and time of one file or folder, by its full path under STORAGE_MOUNT_POINT, e.g. "/sdcard/BENCH/RCBENCH.LOG".
storage_dir_t * storage_dir_open (const char *path)
 Open a folder by its full path under STORAGE_MOUNT_POINT, "/sdcard" for the root, to read it one entry at a time.
int storage_dir_read (storage_dir_t *d, char *name, size_t cap, storage_stat_t *out)
 The next entry of d.
void storage_dir_close (storage_dir_t *d)
 Close d and give its hold back. A failed read is weighed as storage_walk() weighs one, without mounting again.

Variables

static const char * TAG = "storage"
 The log tag of the storage component.

Detailed Description

Listing the mounted card: storage_walk(), storage_walk_counted(), storage_stat(), storage_dir_open() and its reads, and storage_path().

Each read is made under a hold (storage_priv.h), and its outcome goes back to storage.c, which decides whether the card is gone.

SPDX-License-Identifier: MIT

Function Documentation

◆ fat_mtime()

int64_t fat_mtime ( WORD fdate,
WORD ftime )
static

FAT's date and time stamp as local time, the way ESP-IDF's stat() reads it (components/fatfs/vfs/vfs_fat.c, update_stat_struct()): the date's bits 15..9 are years from 1980, 8..5 the month, 4..0 the day; the time's 15..11 the hour, 10..5 the minute, 4..0 seconds in steps of 2.

Parameters
fdateFAT's date
ftimeFAT's time
Returns
the time as mktime() gives it

◆ stat_held()

esp_err_t stat_held ( const char * rel,
storage_stat_t * out,
int * fr_out )
static

storage_stat() under a hold, from the path below the mount point, "" or "/...".

Parameters
relthe path below the mount point
outtakes the answer
fr_outtakes FatFs's answer
Returns
storage_stat()'s answers

◆ storage_dir_close()

void storage_dir_close ( storage_dir_t * d)

Close d and give its hold back. A failed read is weighed as storage_walk() weighs one, without mounting again.

Parameters
dthe folder; NULL does nothing

◆ storage_dir_open()

storage_dir_t * storage_dir_open ( const char * path)

Open a folder by its full path under STORAGE_MOUNT_POINT, "/sdcard" for the root, to read it one entry at a time.

FatFs's own f_opendir() and f_readdir(), as storage_walk() reads: each entry comes with its size, kind and time, so a listing costs one pass and no f_stat() per entry. The volume is held (storage_hold()) until storage_dir_close(). The handle is in PSRAM (pseudo-static random-access memory).

Parameters
paththe folder's full path
Returns
the folder, or NULL when nothing is mounted, path is not under the mount point or names no folder, or no memory is left

◆ storage_dir_read()

int storage_dir_read ( storage_dir_t * d,
char * name,
size_t cap,
storage_stat_t * out )

The next entry of d.

Parameters
dthe folder
nametakes the entry's name, NUL-terminated
capbytes of name
outtakes its size (0 for a folder), kind and time
Returns
1 for an entry, 0 at the end, -1 on a failed read or a name of cap bytes or more

◆ storage_path()

void storage_path ( const char * dir,
const char * name,
char * out,
size_t out_size )

Full path for a name inside dir, ready for fopen().

◆ storage_stamp_mtime()

int64_t storage_stamp_mtime ( uint32_t stamp)

A storage_entry_t stamp as the time storage_stat() gives the same file: FAT's local date and time through mktime(), in the zone in force (TZ).

A stamp of 1980, which FatFs writes for a clock that was not set, comes back below WALL_STAMP_FLOOR_S (wall_clock.h), as a stamp of 0 does.

Parameters
stampthe entry's stamp
Returns
seconds since 1970-01-01 00:00:00 UTC

◆ storage_stat()

esp_err_t storage_stat ( const char * path,
storage_stat_t * out )

The size, kind and time of one file or folder, by its full path under STORAGE_MOUNT_POINT, e.g. "/sdcard/BENCH/RCBENCH.LOG".

FatFs's own f_stat(), for its 64-bit size. stat() through the VFS (virtual file system) puts the size in st_size, an off_t of 32 bits on the panel: a file of 4GiB and more comes back as its size less a multiple of 4GiB, and one of 2GiB and more as a negative number.

A failure that says the card is gone lets the volume go as storage_walk() does, without mounting again.

Returns
ESP_OK; ESP_ERR_NOT_FOUND when the volume has no such name; ESP_ERR_INVALID_STATE when nothing is mounted or path is not under the mount point; ESP_ERR_NO_MEM; ESP_FAIL when the card does not read.

◆ storage_walk()

int storage_walk ( const char * dir,
const char * suffixes,
storage_visit_fn visit,
void * ctx,
storage_tick_fn tick )

Walk a directory, handing every matching entry to visit, with its size (0 for a directory) and its FAT stamp.

One pass over the directory's entries and nothing else: the size and the stamp come with the entry, so a caller that keeps a few does not look each of them up again from the directory's start.

The whole directory is read, and nothing here decides what is worth keeping: a caller with room for fewer entries than the card holds chooses which ones as they arrive. It cannot be done by stopping the read early. FAT (File Allocation Table) hands entries back in the order its directory table holds them, which is creation order until a file is deleted and its slot filled again, so the first entries read are the oldest files and everything written after that is never seen.

Parameters
dirrelative to the mount point; "" or "/" for the root
suffixesspace-separated, lower case, e.g. ".csv .txt"; NULL takes everything. Applied to files; directories always match
visitcalled with a borrowed entry that does not outlive the call; NULL counts the matches without reporting them
ctxpassed to visit untouched
tickcalled once per directory entry read, before any filter, or NULL. A caller on a task with a deadline passes the thing that meets it: the filters reject dot-names, wrong suffixes and over-long names without reaching visit, so a root of unrelated files is read with nothing else running. It takes no argument and must be cheap. A read that fails the way a card taken out does (FatFs FR_DISK_ERR, FR_NOT_READY or FR_INVALID_OBJECT) is followed by one SEND_STATUS (CMD13). A card that does not answer is gone: the volume is let go, and with nothing else holding it the slot is mounted again once. A card that answers fails its reads on its own: CARD_STATE_UNREADABLE, the volume let go, and no second mount. Any other failure leaves the volume mounted.
Returns
the number of matching entries; STORAGE_WALK_NO_DIR (-2) when the volume is mounted and has no folder dir, or a file holds its name; STORAGE_WALK_REMOUNTED (-3) when the walk found the card gone and a card in the slot is mounted now; -1 when the directory cannot be opened or read to its end, or nothing is mounted.

◆ storage_walk_counted()

int storage_walk_counted ( const char * dir,
const char * suffixes,
storage_visit_fn visit,
void * ctx,
storage_tick_fn tick,
unsigned * left_out )

storage_walk(), and the count of the entries its name filters left out: names starting with "." and names of STORAGE_NAME_MAX characters or more. Entries the suffix filter leaves out are not counted.

The file manager's walk (fm_io.h) reads a folder with no suffix filter and needs every entry either visited or counted: a folder holding only .DS_Store is not empty, and is neither moved nor deleted as one.

Parameters
diras storage_walk()
suffixesas storage_walk()
visitas storage_walk()
ctxas storage_walk()
tickas storage_walk()
left_outtakes the count; may be NULL. 0 when nothing is read.
Returns
as storage_walk()

◆ suffix_matches()

bool suffix_matches ( const char * name,
const char * suffixes )
static

Whether name ends in one of suffixes, case folded.

Parameters
namea file's name
suffixesspace-separated, lower case; NULL or "" takes every name
Returns
true for a match

◆ walk_held()

int walk_held ( const char * dir,
const char * suffixes,
storage_visit_fn visit,
void * ctx,
storage_tick_fn tick,
int * fr_out,
unsigned * left_out )
static

The walk itself, under a hold.

Parameters
dirthe folder
suffixesthe files' suffixes, or NULL
visitthe visitor, or NULL
ctxpassed to visit
tickcalled per entry read, or NULL
fr_outtakes FatFs's answer when the walk answers -1
left_outcounts the entries the name filters left out, or NULL
Returns
storage_walk()'s answers