Provides an interface for accessing files and directories from different devices and file systems. More...
Provides an interface for accessing files and directories from different devices and file systems.
This layer is modeled as a mix between POSIX syscalls (e.g. open) and the Linux VFS layer implementation, with major reductions in the feature set, in order to fit the resource constrained platforms that RIOT targets.
The overall design goals are:
enum
of all file system drivers that has to be kept up to date with external packages etc.<errno.h>
numbers as negative return codes for errors, avoid the global errno
variable.The API should be easy to understand for users who are familiar with the POSIX file functions (open, close, read, write, fstat, lseek etc.)
The VFS layer keeps track of mounted file systems and open files, the vfs_open
function searches the array of mounted file systems and dispatches the call to the file system instance with the longest matching mount point prefix. Subsequent calls to vfs_read
, vfs_write
, etc will do a look up in the table of open files and dispatch the call to the correct file system driver for handling.
vfs_mount
takes a string containing the mount point, a file system driver specification (struct file_system
), and an opaque pointer that only the FS driver knows how to use, which can be used to keep driver parameters in order to allow dynamic handling of multiple devices.
Modules | |
VFS helper functions | |
Files | |
file | vfs.h |
VFS layer API declarations. | |
file | vfs_default.h |
VFS default mount points. | |
Data Structures | |
struct | vfs_file_system_t |
A file system driver. More... | |
struct | vfs_mount_struct |
A mounted file system. More... | |
struct | vfs_file_t |
Information about an open file. More... | |
struct | vfs_DIR |
Internal representation of a file system directory entry. More... | |
struct | vfs_dirent_t |
User facing directory entry. More... | |
struct | vfs_file_ops |
Operations on open files. More... | |
struct | vfs_dir_ops |
Operations on open directories. More... | |
struct | vfs_file_system_ops |
Operations on mounted file systems. More... | |
Macros | |
#define | MAX6(a, b, c, d, e, f) MAX(MAX(MAX(MAX((a), (b)), MAX((c), (d))), (e)), (f)) |
MAX6 Function to get the largest of 6 values. | |
#define | VFS_MAX_OPEN_FILES (16) |
Maximum number of simultaneous open files. | |
#define | VFS_DIR_BUFFER_SIZE |
Size of buffer space in vfs_DIR. | |
#define | VFS_FILE_BUFFER_SIZE |
Size of buffer space in vfs_file_t. | |
#define | VFS_NAME_MAX (31) |
Maximum length of the name in a vfs_dirent_t (not including terminating null) | |
#define | VFS_ANY_FD (-1) |
Used with vfs_bind to bind to any available fd number. | |
#define | VFS_MTD(mtd) { .dev = &mtd.base } |
Helper macro for VFS_AUTO_MOUNT. | |
#define | VFS_AUTO_MOUNT(type, mtd, path, idx) |
Define an automatic mountpoint. | |
#define | VFS_FS_FLAG_WANT_ABS_PATH (1 << 0) |
File system always wants the full VFS path. | |
Typedefs | |
typedef struct vfs_file_ops | vfs_file_ops_t |
struct vfs_file_ops typedef | |
typedef struct vfs_dir_ops | vfs_dir_ops_t |
struct vfs_dir_ops typedef | |
typedef struct vfs_file_system_ops | vfs_file_system_ops_t |
struct vfs_file_system_ops typedef | |
typedef struct vfs_mount_struct | vfs_mount_t |
struct vfs_mount_struct typedef | |
Functions | |
void | vfs_bind_stdio (void) |
Allocate and bind file descriptors for STDIN, STDERR, and STDOUT. | |
int | vfs_close (int fd) |
Close an open file. | |
int | vfs_fcntl (int fd, int cmd, int arg) |
Query/set options on an open file. | |
int | vfs_fstat (int fd, struct stat *buf) |
Get status of an open file. | |
int | vfs_fstatvfs (int fd, struct statvfs *buf) |
Get file system status of the file system containing an open file. | |
int | vfs_dstatvfs (vfs_DIR *dirp, struct statvfs *buf) |
Get file system status of the file system containing an open directory. | |
off_t | vfs_lseek (int fd, off_t off, int whence) |
Seek to position in file. | |
int | vfs_open (const char *name, int flags, mode_t mode) |
Open a file. | |
ssize_t | vfs_read (int fd, void *dest, size_t count) |
Read bytes from an open file. | |
ssize_t | vfs_readline (int fd, char *dest, size_t count) |
Read a line from an open text file. | |
ssize_t | vfs_write (int fd, const void *src, size_t count) |
Write bytes to an open file. | |
ssize_t | vfs_write_iol (int fd, const iolist_t *iolist) |
Write bytes from an iolist to an open file. | |
int | vfs_fsync (int fd) |
Synchronize a file on storage Any pending writes are written out to storage. | |
int | vfs_opendir (vfs_DIR *dirp, const char *dirname) |
Open a directory for reading with readdir. | |
int | vfs_readdir (vfs_DIR *dirp, vfs_dirent_t *entry) |
Read a single entry from the open directory dirp and advance the read position by one. | |
int | vfs_closedir (vfs_DIR *dirp) |
Close an open directory. | |
int | vfs_format (vfs_mount_t *mountp) |
Format a file system. | |
int | vfs_format_by_path (const char *path) |
Format a file system. | |
int | vfs_mount (vfs_mount_t *mountp) |
Mount a file system. | |
int | vfs_mount_by_path (const char *path) |
Mount a file system with a pre-configured mount path. | |
int | vfs_unmount_by_path (const char *path, bool force) |
Unmount a file system with a pre-configured mount path. | |
int | vfs_rename (const char *from_path, const char *to_path) |
Rename a file. | |
int | vfs_umount (vfs_mount_t *mountp, bool force) |
Unmount a mounted file system. | |
int | vfs_unlink (const char *name) |
Unlink (delete) a file from a mounted file system. | |
int | vfs_mkdir (const char *name, mode_t mode) |
Create a directory on the file system. | |
int | vfs_rmdir (const char *name) |
Remove a directory from the file system. | |
int | vfs_stat (const char *restrict path, struct stat *restrict buf) |
Get file status. | |
int | vfs_statvfs (const char *restrict path, struct statvfs *restrict buf) |
Get file system status. | |
int | vfs_bind (int fd, int flags, const vfs_file_ops_t *f_op, void *private_data) |
Allocate a new file descriptor and give it file operations. | |
int | vfs_normalize_path (char *buf, const char *path, size_t buflen) |
Normalize a path. | |
const vfs_mount_t * | vfs_iterate_mounts (const vfs_mount_t *cur) |
Iterate through all mounted file systems. | |
bool | vfs_iterate_mount_dirs (vfs_DIR *dir) |
Iterate through all mounted file systems by their root directories. | |
const vfs_file_t * | vfs_file_get (int fd) |
Get information about the file for internal purposes. | |
int | vfs_sysop_stat_from_fstat (vfs_mount_t *mountp, const char *restrict path, struct stat *restrict buf) |
Implementation of stat using fstat | |
Variables | |
const vfs_file_ops_t | mtd_vfs_ops |
MTD driver for VFS. | |
#define | FATFS_VFS_DIR_BUFFER_SIZE (1) |
VFS parameters for FAT. | |
#define | FATFS_VFS_FILE_BUFFER_SIZE (1) |
#define | LITTLEFS_VFS_DIR_BUFFER_SIZE (1) |
VFS parameters for littlefs. | |
#define | LITTLEFS_VFS_FILE_BUFFER_SIZE (1) |
#define | LITTLEFS2_VFS_DIR_BUFFER_SIZE (1) |
VFS parameters for littlefs2. | |
#define | LITTLEFS2_VFS_FILE_BUFFER_SIZE (1) |
#define | SPIFFS_VFS_DIR_BUFFER_SIZE (1) |
VFS parameters for spiffs. | |
#define | SPIFFS_VFS_FILE_BUFFER_SIZE (1) |
#define | LWEXT4_VFS_DIR_BUFFER_SIZE (308) |
VFS parameters for lwext4. | |
#define | LWEXT4_VFS_FILE_BUFFER_SIZE (32) |
sizeof(ext4_file) | |
#define | NANOCOAP_FS_VFS_DIR_BUFFER_SIZE (4 + CONFIG_SOCK_URLPATH_MAXLEN) |
VFS parameters for nanoCoAP FS. | |
#define | NANOCOAP_FS_VFS_FILE_BUFFER_SIZE (4 + CONFIG_SOCK_URLPATH_MAXLEN) |
sizeof(nanocoap_fs_file_t) | |
#define LITTLEFS2_VFS_DIR_BUFFER_SIZE (1) |
#define LITTLEFS_VFS_DIR_BUFFER_SIZE (1) |
#define LWEXT4_VFS_DIR_BUFFER_SIZE (308) |
#define NANOCOAP_FS_VFS_DIR_BUFFER_SIZE (4 + CONFIG_SOCK_URLPATH_MAXLEN) |
#define NANOCOAP_FS_VFS_FILE_BUFFER_SIZE (4 + CONFIG_SOCK_URLPATH_MAXLEN) |
#define SPIFFS_VFS_DIR_BUFFER_SIZE (1) |
#define VFS_ANY_FD (-1) |
#define VFS_AUTO_MOUNT | ( | type, | |
mtd, | |||
path, | |||
idx | |||
) |
Define an automatic mountpoint.
[in] | type | file system type Can be littlefs, littlefs2, spiffs or fatfs |
Internally, file systems supporting this must name their vfs_file_system_t ${TYPE}_file_system
, and must use a type named ${TYPE}_desc_t
for their private data
[in] | mtd | file system backed device configuration |
[in] | path | Mount path |
[in] | idx | Unique index of the mount point |
#define VFS_DIR_BUFFER_SIZE |
Size of buffer space in vfs_DIR.
This space is needed to avoid dynamic memory allocations for some file systems where a single pointer is not enough space for its directory stream state, e.g. SPIFFS.
Guidelines:
SPIFFS requires a sizeof(spiffs_DIR) (6-16 bytes, depending on target platform and configuration) buffer for its DIR struct.
int
variable, ensure that you have a preprocessor check in your header file (so that it is impossible to attempt to mount the file system without running into a compiler error):#define VFS_FILE_BUFFER_SIZE |
Size of buffer space in vfs_file_t.
Same as with VFS_DIR_BUFFER_SIZE some file systems (e.g. FatFs) require more space to store data about their files.
Guidelines are same as with VFS_DIR_BUFFER_SIZE, so add the following snippet to your fs header:
#define VFS_FS_FLAG_WANT_ABS_PATH (1 << 0) |
#define VFS_MAX_OPEN_FILES (16) |
#define VFS_MTD | ( | mtd | ) | { .dev = &mtd.base } |
#define VFS_NAME_MAX (31) |
Maximum length of the name in a vfs_dirent_t
(not including terminating null)
Maximum number of bytes in a filename (not including terminating null).
Similar to the POSIX macro NAME_MAX
typedef struct vfs_dir_ops vfs_dir_ops_t |
struct vfs_dir_ops
typedef
typedef struct vfs_file_ops vfs_file_ops_t |
struct vfs_file_ops
typedef
typedef struct vfs_file_system_ops vfs_file_system_ops_t |
struct vfs_file_system_ops
typedef
typedef struct vfs_mount_struct vfs_mount_t |
struct vfs_mount_struct
typedef
int vfs_bind | ( | int | fd, |
int | flags, | ||
const vfs_file_ops_t * | f_op, | ||
void * | private_data | ||
) |
Allocate a new file descriptor and give it file operations.
The new fd will be initialized with pointers to the given f_op
file operations table and private_data
.
This function can be used to give file-like functionality to devices, e.g. UART.
private_data
can be used for passing instance information to the file operation handlers in f_op
.
[in] | fd | Desired fd number, use VFS_ANY_FD for any available fd |
[in] | flags | not implemented yet |
[in] | f_op | pointer to file operations table |
[in] | private_data | opaque pointer to private data |
void vfs_bind_stdio | ( | void | ) |
Allocate and bind file descriptors for STDIN, STDERR, and STDOUT.
This function is meant to be called once during system initialization time. It is typically called from the initialization of the selected STDIO implementation.
int vfs_close | ( | int | fd | ) |
Close an open file.
[in] | fd | fd number to close |
int vfs_closedir | ( | vfs_DIR * | dirp | ) |
Close an open directory.
vfs_DIR
is forbidden and may lead to file system corruption and random system failures.[in] | dirp | pointer to open directory |
Get file system status of the file system containing an open directory.
[in] | dirp | pointer to open directory |
[out] | buf | pointer to statvfs struct to fill |
int vfs_fcntl | ( | int | fd, |
int | cmd, | ||
int | arg | ||
) |
Query/set options on an open file.
[in] | fd | fd number to operate on |
[in] | cmd | fcntl command, see man 3p fcntl |
[in] | arg | argument to fcntl command, see man 3p fcntl |
const vfs_file_t * vfs_file_get | ( | int | fd | ) |
Get information about the file for internal purposes.
int vfs_format | ( | vfs_mount_t * | mountp | ) |
Format a file system.
mountp
should have been populated in advance with a file system driver, a mount point, and private_data (if the file system driver uses one).
mountp
must not be mounted[in] | mountp | pointer to the mount structure of the filesystem to format |
int vfs_format_by_path | ( | const char * | path | ) |
Format a file system.
The file system must not be mounted in order to be formatted. Call vfs_unmount_by_path first if necessary.
[in] | path | Path of the pre-configured mount point |
int vfs_fstat | ( | int | fd, |
struct stat * | buf | ||
) |
Get status of an open file.
[in] | fd | fd number obtained from vfs_open |
[out] | buf | pointer to stat struct to fill |
int vfs_fstatvfs | ( | int | fd, |
struct statvfs * | buf | ||
) |
Get file system status of the file system containing an open file.
[in] | fd | fd number obtained from vfs_open |
[out] | buf | pointer to statvfs struct to fill |
int vfs_fsync | ( | int | fd | ) |
Synchronize a file on storage Any pending writes are written out to storage.
[in] | fd | fd number obtained from vfs_open |
bool vfs_iterate_mount_dirs | ( | vfs_DIR * | dir | ) |
Iterate through all mounted file systems by their root directories.
Unlike vfs_iterate_mounts, this is thread safe, and allows thread safe access to the mount point's stats through vfs_dstatvfs. If mounts or unmounts happen while iterating, this is guaranteed to report all file systems that stayed mounted, and may report any that are transiently mounted for up to as often as they are (re)mounted. Note that the volume being reported can not be unmounted as dir
is an open directory.
Zero-initialize dir
to start. As long as true
is returned, dir
is a valid directory on which the user can call vfs_readdir or vfs_dstatvfs (or even peek at its .mp
if they dare ignore the warning in vfs_DIR).
Users MUST NOT call vfs_closedir if they intend to keep iterating, but MUST call it when aborting iteration.
Note that this requires all enumerated file systems to support the opendir
vfs_dir_ops; any file system that does not support that will prematurely terminate the mount point enumeration.
sc_vfs.c
(df
command) for a usage example[in,out] | dir | The root directory of the discovered mount point |
true
if another file system is mounted; dir
then contains an open directory. false
if the file system list is exhausted; dir
is uninitialized then. const vfs_mount_t * vfs_iterate_mounts | ( | const vfs_mount_t * | cur | ) |
Iterate through all mounted file systems.
Set cur
to NULL
to start from the beginning
[in] | cur | current iterator value |
cur
cur
is the last element in the list off_t vfs_lseek | ( | int | fd, |
off_t | off, | ||
int | whence | ||
) |
Seek to position in file.
whence
determines the function of the seek and should be set to one of the following values:
SEEK_SET:
Seek to absolute offset off
SEEK_CUR:
Seek to current location + off
SEEK_END:
Seek to end of file + off
[in] | fd | fd number obtained from vfs_open |
[in] | off | seek offset |
[in] | whence | determines the seek method, see detailed description |
int vfs_mkdir | ( | const char * | name, |
mode_t | mode | ||
) |
Create a directory on the file system.
[in] | name | name of the directory to create |
[in] | mode | file creation mode bits |
int vfs_mount | ( | vfs_mount_t * | mountp | ) |
Mount a file system.
mountp
should have been populated in advance with a file system driver, a mount point, and private_data (if the file system driver uses one).
[in] | mountp | pointer to the mount structure of the file system to mount |
int vfs_mount_by_path | ( | const char * | path | ) |
Mount a file system with a pre-configured mount path.
[in] | path | Path of the pre-configured mount point |
int vfs_normalize_path | ( | char * | buf, |
const char * | path, | ||
size_t | buflen | ||
) |
Normalize a path.
Normalizing a path means to remove all relative components ("..", ".") and any double slashes.
buf
is allowed to overlap path
if &buf
[0] <= &path
[0]path
must be an absolute path (starting with /
)[out] | buf | buffer to store normalized path |
[in] | path | path to normalize |
[in] | buflen | available space in buf |
int vfs_open | ( | const char * | name, |
int | flags, | ||
mode_t | mode | ||
) |
Open a file.
[in] | name | file name to open |
[in] | flags | flags for opening, see man 3p open |
[in] | mode | file mode |
int vfs_opendir | ( | vfs_DIR * | dirp, |
const char * | dirname | ||
) |
Open a directory for reading with readdir.
The data in *dirp
will be initialized by vfs_opendir
[out] | dirp | pointer to directory stream struct for storing the state |
[in] | dirname | null-terminated name of the dir to open, absolute file system path |
ssize_t vfs_read | ( | int | fd, |
void * | dest, | ||
size_t | count | ||
) |
Read bytes from an open file.
[in] | fd | fd number obtained from vfs_open |
[out] | dest | destination buffer to hold the file contents |
[in] | count | maximum number of bytes to read |
For simple cases of only a single read from a file, the vfs_file_to_buffer function can be used.
int vfs_readdir | ( | vfs_DIR * | dirp, |
vfs_dirent_t * | entry | ||
) |
Read a single entry from the open directory dirp and advance the read position by one.
entry
will be populated with information about the next entry in the directory stream dirp
vfs_DIR
is forbidden and may lead to file system corruption and random system failures.[in] | dirp | pointer to open directory |
[out] | entry | directory entry information |
entry
was updated dirp
has reached the end of the directory index ssize_t vfs_readline | ( | int | fd, |
char * | dest, | ||
size_t | count | ||
) |
Read a line from an open text file.
Reads from a file until a \r
or \n
character is found.
[in] | fd | fd number obtained from vfs_open |
[out] | dest | destination buffer to hold the line |
[in] | count | maximum number of characters to read |
int vfs_rename | ( | const char * | from_path, |
const char * | to_path | ||
) |
Rename a file.
The file from_path
will be renamed to to_path
[in] | from_path | absolute path to existing file |
[in] | to_path | absolute path to destination |
int vfs_rmdir | ( | const char * | name | ) |
Remove a directory from the file system.
Only empty directories may be removed.
[in] | name | name of the directory to remove |
int vfs_stat | ( | const char *restrict | path, |
struct stat *restrict | buf | ||
) |
Get file status.
[in] | path | path to file being queried |
[out] | buf | pointer to stat struct to fill |
int vfs_statvfs | ( | const char *restrict | path, |
struct statvfs *restrict | buf | ||
) |
Get file system status.
path
can be any path that resolves to the file system being queried, it does not have to be an existing file.
[in] | path | path to a file on the file system being queried |
[out] | buf | pointer to statvfs struct to fill |
int vfs_sysop_stat_from_fstat | ( | vfs_mount_t * | mountp, |
const char *restrict | path, | ||
struct stat *restrict | buf | ||
) |
Implementation of stat
using fstat
This helper can be used by file system drivers that do not have any more efficient implementation of fs_op::stat
than opening the file and running f_op::fstat
on it.
It can be set as fs_op::stat
by a file system driver, provided it implements f_op::open
and f_op::fstat
and f_op::close
, and its open
accepts NULL
in the abs_path
position.
int vfs_umount | ( | vfs_mount_t * | mountp, |
bool | force | ||
) |
Unmount a mounted file system.
This will fail if there are any open files or directories on the mounted file system
[in] | mountp | pointer to the mount structure of the file system to unmount |
[in] | force | Unmount the filesystem even if there are still open files |
int vfs_unlink | ( | const char * | name | ) |
Unlink (delete) a file from a mounted file system.
[in] | name | name of file to delete |
int vfs_unmount_by_path | ( | const char * | path, |
bool | force | ||
) |
Unmount a file system with a pre-configured mount path.
[in] | path | Path of the pre-configured mount point |
[in] | force | Unmount the filesystem even if there are still open files |
ssize_t vfs_write | ( | int | fd, |
const void * | src, | ||
size_t | count | ||
) |
Write bytes to an open file.
[in] | fd | fd number obtained from vfs_open |
[in] | src | pointer to source buffer |
[in] | count | maximum number of bytes to write |
For simple cases of only a single write to a file, the vfs_file_from_buffer function can be used.
ssize_t vfs_write_iol | ( | int | fd, |
const iolist_t * | iolist | ||
) |
Write bytes from an iolist to an open file.
[in] | fd | fd number obtained from vfs_open |
[in] | iolist | iolist to read from |