Virtual File System (VFS) layer

Provides an interface for accessing files and directories from different devices and file systems. More...

Detailed Description

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:

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.

Todo:
VFS layer reference counting and locking for open files and simultaneous access.

Files

file  vfs.h
 VFS layer API declarations.
 

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 VFS_MAX_OPEN_FILES   (16)
 Maximum number of simultaneous open files.
 
#define VFS_DIR_BUFFER_SIZE
 Size of buffer space in vfs_DIR. More...
 
#define VFS_FILE_BUFFER_SIZE
 Size of buffer space in vfs_file_t. More...
 
#define VFS_NAME_MAX   (31)
 Maximum length of the name in a vfs_dirent_t (not including terminating null) More...
 
#define VFS_ANY_FD   (-1)
 Used with vfs_bind to bind to any available fd number.
 

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. More...
 
int vfs_close (int fd)
 Close an open file. More...
 
int vfs_fcntl (int fd, int cmd, int arg)
 Query/set options on an open file. More...
 
int vfs_fstat (int fd, struct stat *buf)
 Get status of an open file. More...
 
int vfs_fstatvfs (int fd, struct statvfs *buf)
 Get file system status of the file system containing an open file. More...
 
off_t vfs_lseek (int fd, off_t off, int whence)
 Seek to position in file. More...
 
int vfs_open (const char *name, int flags, mode_t mode)
 Open a file. More...
 
ssize_t vfs_read (int fd, void *dest, size_t count)
 Read bytes from an open file. More...
 
ssize_t vfs_write (int fd, const void *src, size_t count)
 Write bytes to an open file. More...
 
int vfs_opendir (vfs_DIR *dirp, const char *dirname)
 Open a directory for reading with readdir. More...
 
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. More...
 
int vfs_closedir (vfs_DIR *dirp)
 Close an open directory. More...
 
int vfs_format (vfs_mount_t *mountp)
 Format a file system. More...
 
int vfs_mount (vfs_mount_t *mountp)
 Mount a file system. More...
 
int vfs_rename (const char *from_path, const char *to_path)
 Rename a file. More...
 
int vfs_umount (vfs_mount_t *mountp)
 Unmount a mounted file system. More...
 
int vfs_unlink (const char *name)
 Unlink (delete) a file from a mounted file system. More...
 
int vfs_mkdir (const char *name, mode_t mode)
 Create a directory on the file system. More...
 
int vfs_rmdir (const char *name)
 Remove a directory from the file system. More...
 
int vfs_stat (const char *restrict path, struct stat *restrict buf)
 Get file status. More...
 
int vfs_statvfs (const char *restrict path, struct statvfs *restrict buf)
 Get file system status. More...
 
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. More...
 
int vfs_normalize_path (char *buf, const char *path, size_t buflen)
 Normalize a path. More...
 
const vfs_mount_tvfs_iterate_mounts (const vfs_mount_t *cur)
 Iterate through all mounted file systems. More...
 
const vfs_file_tvfs_file_get (int fd)
 Get information about the file for internal purposes. More...
 
int vfs_sysop_stat_from_fstat (vfs_mount_t *mountp, const char *restrict path, struct stat *restrict buf)
 Implementation of stat using fstat More...
 
#define _MAX(a, b)   ((a) > (b) ? (a) : (b))
 MAX functions for internal use.
 
#define MAX4(a, b, c, d)   _MAX(_MAX((a), (b)), _MAX((c),(d)))
 
#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)
 

Macro Definition Documentation

◆ VFS_DIR_BUFFER_SIZE

#define VFS_DIR_BUFFER_SIZE
Value:

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.

Attention
File system developers: If your file system requires a buffer for DIR streams that is larger than a single pointer or 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):
#if VFS_DIR_BUFFER_SIZE < 123
#error VFS_DIR_BUFFER_SIZE is too small, at least 123 bytes is required
#endif
Put the check in the public header file (.h), do not put the check in the implementation (.c) file.

Definition at line 181 of file vfs.h.

◆ VFS_FILE_BUFFER_SIZE

#define VFS_FILE_BUFFER_SIZE
Value:
MAX4(FATFS_VFS_FILE_BUFFER_SIZE, \
LITTLEFS_VFS_FILE_BUFFER_SIZE, \
LITTLEFS2_VFS_FILE_BUFFER_SIZE,\
SPIFFS_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:

Attention
#if VFS_FILE_BUFFER_SIZE < 123
#error VFS_FILE_BUFFER_SIZE is too small, at least 123 bytes is required
#endif
Put the check in the public header file (.h), do not put the check in the implementation (.c) file.

Definition at line 208 of file vfs.h.

◆ VFS_NAME_MAX

#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

Definition at line 223 of file vfs.h.

Function Documentation

◆ vfs_bind()

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.

Parameters
[in]fdDesired fd number, use VFS_ANY_FD for any available fd
[in]flagsnot implemented yet
[in]f_oppointer to file operations table
[in]private_dataopaque pointer to private data
Returns
fd number on success (>= 0)
<0 on error

◆ vfs_bind_stdio()

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.

◆ vfs_close()

int vfs_close ( int  fd)

Close an open file.

Parameters
[in]fdfd number to close
Returns
0 on success
<0 on error

◆ vfs_closedir()

int vfs_closedir ( vfs_DIR dirp)

Close an open directory.

Attention
Calling vfs_closedir on an uninitialized vfs_DIR is forbidden and may lead to file system corruption and random system failures.
Parameters
[in]dirppointer to open directory
Returns
0 on success
<0 on error, the directory stream dirp should be considered invalid

◆ vfs_fcntl()

int vfs_fcntl ( int  fd,
int  cmd,
int  arg 
)

Query/set options on an open file.

Parameters
[in]fdfd number to operate on
[in]cmdfcntl command, see man 3p fcntl
[in]argargument to fcntl command, see man 3p fcntl
Returns
0 on success
<0 on error

◆ vfs_file_get()

const vfs_file_t* vfs_file_get ( int  fd)

Get information about the file for internal purposes.

Attention
Not thread safe! Do not modify any of the fields in the returned struct.
Note
For file descriptor internal usage only.

◆ vfs_format()

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).

Precondition
mountp must not be mounted
Parameters
[in]mountppointer to the mount structure of the filesystem to format
Returns
0 on success
<0 on error

◆ vfs_fstat()

int vfs_fstat ( int  fd,
struct stat *  buf 
)

Get status of an open file.

Parameters
[in]fdfd number obtained from vfs_open
[out]bufpointer to stat struct to fill
Returns
0 on success
<0 on error

◆ vfs_fstatvfs()

int vfs_fstatvfs ( int  fd,
struct statvfs buf 
)

Get file system status of the file system containing an open file.

Parameters
[in]fdfd number obtained from vfs_open
[out]bufpointer to statvfs struct to fill
Returns
0 on success
<0 on error

◆ vfs_iterate_mounts()

const vfs_mount_t* vfs_iterate_mounts ( const vfs_mount_t cur)

Iterate through all mounted file systems.

Attention
Not thread safe! Do not mix calls to this function with other calls which modify the mount table, such as vfs_mount() and vfs_umount()

Set cur to NULL to start from the beginning

See also
sc_vfs.c (df command) for a usage example
Parameters
[in]curcurrent iterator value
Returns
Pointer to next mounted file system in list after cur
NULL if cur is the last element in the list

◆ vfs_lseek()

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
Parameters
[in]fdfd number obtained from vfs_open
[in]offseek offset
[in]whencedetermines the seek method, see detailed description
Returns
the new seek location in the file on success
<0 on error

◆ vfs_mkdir()

int vfs_mkdir ( const char *  name,
mode_t  mode 
)

Create a directory on the file system.

Parameters
[in]namename of the directory to create
[in]modefile creation mode bits
Returns
0 on success
<0 on error

◆ vfs_mount()

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).

Parameters
[in]mountppointer to the mount structure of the file system to mount
Returns
0 on success
<0 on error

◆ vfs_normalize_path()

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.

Note
buf is allowed to overlap path if &buf[0] <= &path[0]
Attention
path must be an absolute path (starting with / )
Parameters
[out]bufbuffer to store normalized path
[in]pathpath to normalize
[in]buflenavailable space in buf
Returns
number of path components in the normalized path on success
<0 on error

◆ vfs_open()

int vfs_open ( const char *  name,
int  flags,
mode_t  mode 
)

Open a file.

Parameters
[in]namefile name to open
[in]flagsflags for opening, see man 3p open
[in]modefile mode
Returns
fd number on success (>= 0)
<0 on error

◆ vfs_opendir()

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

Parameters
[out]dirppointer to directory stream struct for storing the state
[in]dirnamenull-terminated name of the dir to open, absolute file system path
Returns
0 on success
<0 on error

◆ vfs_read()

ssize_t vfs_read ( int  fd,
void *  dest,
size_t  count 
)

Read bytes from an open file.

Parameters
[in]fdfd number obtained from vfs_open
[out]destdestination buffer to hold the file contents
[in]countmaximum number of bytes to read
Returns
number of bytes read on success
<0 on error

◆ vfs_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.

entry will be populated with information about the next entry in the directory stream dirp

Attention
Calling vfs_readdir on an uninitialized vfs_DIR is forbidden and may lead to file system corruption and random system failures.
Parameters
[in]dirppointer to open directory
[out]entrydirectory entry information
Returns
1 if entry was updated
0 if dirp has reached the end of the directory index
<0 on error

◆ vfs_rename()

int vfs_rename ( const char *  from_path,
const char *  to_path 
)

Rename a file.

The file from_path will be renamed to to_path

Note
it is not possible to rename files across different file system
Parameters
[in]from_pathabsolute path to existing file
[in]to_pathabsolute path to destination
Returns
0 on success
<0 on error

◆ vfs_rmdir()

int vfs_rmdir ( const char *  name)

Remove a directory from the file system.

Only empty directories may be removed.

Parameters
[in]namename of the directory to remove
Returns
0 on success
<0 on error

◆ vfs_stat()

int vfs_stat ( const char *restrict  path,
struct stat *restrict  buf 
)

Get file status.

Parameters
[in]pathpath to file being queried
[out]bufpointer to stat struct to fill
Returns
0 on success
<0 on error

◆ vfs_statvfs()

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.

Parameters
[in]pathpath to a file on the file system being queried
[out]bufpointer to statvfs struct to fill
Returns
0 on success
<0 on error

◆ vfs_sysop_stat_from_fstat()

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.

◆ vfs_umount()

int vfs_umount ( vfs_mount_t mountp)

Unmount a mounted file system.

This will fail if there are any open files on the mounted file system

Parameters
[in]mountppointer to the mount structure of the file system to unmount
Returns
0 on success
<0 on error

◆ vfs_unlink()

int vfs_unlink ( const char *  name)

Unlink (delete) a file from a mounted file system.

Parameters
[in]namename of file to delete
Returns
0 on success
<0 on error

◆ vfs_write()

ssize_t vfs_write ( int  fd,
const void *  src,
size_t  count 
)

Write bytes to an open file.

Parameters
[in]fdfd number obtained from vfs_open
[in]srcpointer to source buffer
[in]countmaximum number of bytes to write
Returns
number of bytes written on success
<0 on error
LITTLEFS2_VFS_DIR_BUFFER_SIZE
#define LITTLEFS2_VFS_DIR_BUFFER_SIZE
VFS parameters for littlefs2.
Definition: vfs.h:128
FATFS_VFS_DIR_BUFFER_SIZE
#define FATFS_VFS_DIR_BUFFER_SIZE
VFS parameters for FAT.
Definition: vfs.h:102
LITTLEFS_VFS_DIR_BUFFER_SIZE
#define LITTLEFS_VFS_DIR_BUFFER_SIZE
VFS parameters for littlefs.
Definition: vfs.h:115
SPIFFS_VFS_DIR_BUFFER_SIZE
#define SPIFFS_VFS_DIR_BUFFER_SIZE
VFS parameters for spiffs.
Definition: vfs.h:141