Virtual File System (VFS) layer

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:

  • Provide implementations for all newlib “file” syscalls
  • Keep it simple, do not add every possible file operation from Linux VFS.
  • Easy to map existing file system implementations for resource constrained systems onto the VFS layer API
  • Avoid keeping a central enum of all file system drivers that has to be kept up to date with external packages etc.
  • Use POSIX <errno.h> numbers as negative return codes for errors, avoid the global errno variable.
  • Only absolute paths to files (no per-process working directory)
  • No dynamic memory allocation

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.

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

struct vfs_file_ops vfs_file_ops_t

struct vfs_file_ops typedef

struct vfs_dir_ops vfs_dir_ops_t

struct vfs_dir_ops typedef

struct vfs_file_system_ops vfs_file_system_ops_t

struct vfs_file_system_ops typedef

struct vfs_mount_struct vfs_mount_t

struct vfs_mount_struct typedef

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.

Parameters

fd:fd number to close

Return values

  • 0 on success
  • <0 on error
int vfs_fcntl(int fd, int cmd, int arg)

Query/set options on an open file.

Parameters

fd:fd number to operate on
cmd:fcntl command, see man 3p fcntl
arg:argument to fcntl command, see man 3p fcntl

Return values

  • 0 on success
  • <0 on error
int vfs_fstat(int fd, struct stat * buf)

Get status of an open file.

Parameters

fd:fd number obtained from vfs_open
buf:pointer to stat struct to fill

Return values

  • 0 on success
  • <0 on error
int vfs_fstatvfs(int fd, struct statvfs * buf)

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

Parameters

fd:fd number obtained from vfs_open
buf:pointer to statvfs struct to fill

Return values

  • 0 on success
  • <0 on error
msp430_types.h::off_t vfs_lseek(int fd, msp430_types.h::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

fd:fd number obtained from vfs_open
off:seek offset
whence:determines the seek method, see detailed description

Return values

  • the new seek location in the file on success
  • <0 on error
int vfs_open(const char * name, int flags, msp430_types.h::mode_t mode)

Open a file.

Parameters

name:file name to open
flags:flags for opening, see man 3p open
mode:file mode

Return values

  • fd number on success (>= 0)
  • <0 on error
msp430_types.h::ssize_t vfs_read(int fd, void * dest, msp430_types.h::size_t count)

Read bytes from an open file.

Parameters

fd:fd number obtained from vfs_open
dest:destination buffer to hold the file contents
count:maximum number of bytes to read

Return values

  • number of bytes read on success
  • <0 on error
msp430_types.h::ssize_t vfs_write(int fd, const void * src, msp430_types.h::size_t count)

Write bytes to an open file.

Parameters

fd:fd number obtained from vfs_open
src:pointer to source buffer
count:maximum number of bytes to write

Return values

  • number of bytes written on success
  • <0 on error
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

dirp:pointer to directory stream struct for storing the state
dirname:null-terminated name of the dir to open, absolute file system path

Return values

  • 0 on success
  • <0 on error
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

Parameters

dirp:pointer to open directory
entry:directory entry information

Return values

  • 1 if entry was updated
  • 0 if dirp has reached the end of the directory index
  • <0 on error
int vfs_closedir(vfs_DIR * dirp)

Close an open directory.

Parameters

dirp:pointer to open directory

Return values

  • 0 on success
  • <0 on error, the directory stream dirp should be considered invalid
int vfs_format(vfs.h::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).

Parameters

mountp:pointer to the mount structure of the filesystem to format

Return values

  • 0 on success
  • <0 on error
int vfs_mount(vfs.h::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

mountp:pointer to the mount structure of the file system to mount

Return values

  • 0 on success
  • <0 on error
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

from_path:absolute path to existing file
to_path:absolute path to destination

Return values

  • 0 on success
  • <0 on error
int vfs_umount(vfs.h::vfs_mount_t * mountp)

Unmount a mounted file system.

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

Parameters

mountp:pointer to the mount structure of the file system to unmount

Return values

  • 0 on success
  • <0 on error
int vfs_unlink(const char * name)

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

Parameters

name:name of file to delete

Return values

  • 0 on success
  • <0 on error
int vfs_mkdir(const char * name, msp430_types.h::mode_t mode)

Create a directory on the file system.

Parameters

name:name of the directory to create
mode:file creation mode bits

Return values

  • 0 on success
  • <0 on error
int vfs_rmdir(const char * name)

Remove a directory from the file system.

Only empty directories may be removed.

Parameters

name:name of the directory to remove

Return values

  • 0 on success
  • <0 on error
int vfs_stat(const char *restrict path, struct stat *restrict buf)

Get file status.

Parameters

path:path to file being queried
buf:pointer to stat struct to fill

Return values

  • 0 on success
  • <0 on error
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

path:path to a file on the file system being queried
buf:pointer to statvfs struct to fill

Return values

  • 0 on success
  • <0 on error
int vfs_bind(int fd, int flags, const vfs.h::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

fd:Desired fd number, use VFS_ANY_FD for any available fd
flags:not implemented yet
f_op:pointer to file operations table
private_data:opaque pointer to private data

Return values

  • fd number on success (>= 0)
  • <0 on error
int vfs_normalize_path(char * buf, const char * path, msp430_types.h::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]

Parameters

buf:buffer to store normalized path
path:path to normalize
buflen:available space in buf

Return values

  • number of path components in the normalized path on success
  • <0 on error
const vfs.h::vfs_mount_t * vfs_iterate_mounts(const vfs.h::vfs_mount_t * cur)

Iterate through all mounted file systems.

Set cur to NULL to start from the beginning

See also

sc_vfs.c (df command) for a usage example

Parameters

cur:current iterator value

Return values

  • Pointer to next mounted file system in list after cur
  • NULL if cur is the last element in the list
VFS_MAX_OPEN_FILES

Maximum number of simultaneous open files.

1
(16)
VFS_DIR_BUFFER_SIZE

Size of buffer space in vfs_DIR.

1
(12)

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.

VFS_FILE_BUFFER_SIZE

Size of buffer space in vfs_file_t.

1
(1)

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:

VFS_NAME_MAX

Maximum length of the name in a vfs_dirent_t (not including terminating null)

1
(31)

Maximum number of bytes in a filename (not including terminating null).

Similar to the POSIX macro NAME_MAX

VFS_ANY_FD

Used with vfs_bind to bind to any available fd number.

1
(-1)
struct vfs_file_system_t

A file system driver.

const vfs.h::vfs_file_ops_t * f_op

File operations table.

const vfs.h::vfs_dir_ops_t * d_op

Directory operations table.

const vfs.h::vfs_file_system_ops_t * fs_op

File system operations table.

struct vfs_mount_struct

A mounted file system.

clist.h::clist_node_t list_entry

List entry for the _vfs_mount_list list.

const vfs_file_system_t * fs

The file system driver for the mount point.

const char * mount_point

Mount point, e.g.

“/mnt/cdrom”

msp430_types.h::size_t mount_point_len

Length of mount_point string (set by vfs_mount)

atomic_int open_files

Number of currently open files.

void * private_data

File system driver private data, implementation defined.

struct vfs_file_t

Information about an open file.

Similar to, but not equal to, struct file in Linux

const vfs.h::vfs_file_ops_t * f_op

File operations table.

vfs.h::vfs_mount_t * mp

Pointer to mount table entry.

int flags

File flags.

msp430_types.h::off_t pos

Current position in the file.

kernel_types.h::kernel_pid_t pid

PID of the process that opened the file.

void * ptr

pointer to private data

int value

alternatively, you can use private_data as an int

uint8_t buffer()

Buffer space, in case a single pointer is not enough.

union vfs_file_t::@203 private_data

File system driver private data, implementation defined.

struct vfs_DIR

Internal representation of a file system directory entry.

Used by opendir, readdir, closedir

const vfs.h::vfs_dir_ops_t * d_op

Directory operations table.

vfs.h::vfs_mount_t * mp

Pointer to mount table entry.

void * ptr

pointer to private data

int value

alternatively, you can use private_data as an int

uint8_t buffer()

Buffer space, in case a single pointer is not enough.

union vfs_DIR::@204 private_data

File system driver private data, implementation defined.

struct vfs_dirent_t

User facing directory entry.

Used to hold the output from readdir

Note

size, modification time, and other information is part of the file status, not the directory entry.

msp430_types.h::ino_t d_ino

file serial number, unique for the file system (“inode” in Linux)

char d_name()

file name, relative to its containing directory

struct vfs_file_ops

Operations on open files.

Similar, but not equal, to struct file_operations in Linux

int(* close()

Close an open file.

This function must perform any necessary clean ups and flush any internal buffers in the file system driver.

If an error occurs, the file will still be considered closed by the VFS layer. Therefore, the proper clean up must still be performed by the file system driver before returning any error code.

Note

This implementation does not consider -EINTR a special return code, the file is still considered closed.

Parameters

filp:pointer to open file

Return values

  • 0 on success
  • <0 on error, the file is considered closed anyway
int(* fcntl()

Query/set options on an open file.

Parameters

filp:pointer to open file
cmd:fcntl command, see man 3p fcntl
arg:argument to fcntl command, see man 3p fcntl

Return values

  • 0 on success
  • <0 on error
int(* fstat()

Get status of an open file.

Parameters

filp:pointer to open file
buf:pointer to stat struct to fill

Return values

  • 0 on success
  • <0 on error
msp430_types.h::off_t(* lseek()

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

filp:pointer to open file
off:seek offset
whence:determines the seek method, see detailed description

Return values

  • the new seek location in the file on success
  • <0 on error
int(* open()

Attempt to open a file in the file system at rel_path.

A file system driver should perform the necessary checks for file existence etc in this function.

The VFS layer will initialize the contents of *filp so that filp->f_op points to the mounted file system’s vfs_file_ops_t. filp->private_data.ptr will be initialized to NULL, filp->pos will be set to 0.

Note

name is an absolute path inside the file system, abs_path is the path to the file in the VFS, example: abs_path = “/mnt/hd/foo/bar”, name = “/foo/bar”

Note

name and abs_path may point to different locations within the same const char array and the strings may overlap

Parameters

filp:pointer to open file
name:null-terminated name of the file to open, relative to the file system root, including a leading slash
flags:flags for opening, see man 2 open, man 3p open
mode:mode for creating a new file, see man 2 open, man 3p open
abs_path:null-terminated name of the file to open, relative to the VFS root (“/”)

Return values

  • 0 on success
  • <0 on error
msp430_types.h::ssize_t(* read()

Read bytes from an open file.

Parameters

filp:pointer to open file
dest:pointer to destination buffer
nbytes:maximum number of bytes to read

Return values

  • number of bytes read on success
  • <0 on error
msp430_types.h::ssize_t(* write()

Write bytes to an open file.

Parameters

filp:pointer to open file
src:pointer to source buffer
nbytes:maximum number of bytes to write

Return values

  • number of bytes written on success
  • <0 on error
struct vfs_dir_ops

Operations on open directories.

int(* opendir()

Open a directory for reading with readdir.

Parameters

dirp:pointer to open directory
name:null-terminated name of the dir to open, relative to the file system root, including a leading slash
abs_path:null-terminated name of the dir to open, relative to the VFS root (“/”)

Return values

  • 0 on success
  • <0 on error
int(* readdir()

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

If entry was updated successfully, readdir shall return 1.

If the end of stream was reached, readdir shall return 0 and entry shall remain untouched.

Parameters

dirp:pointer to open directory
entry:directory entry information

Return values

  • 1 if entry was updated
  • 0 if dirp has reached the end of the directory index
  • <0 on error
int(* closedir()

Close an open directory.

Parameters

dirp:pointer to open directory

Return values

  • 0 on success
  • <0 on error, the directory stream dirp should be considered invalid
struct vfs_file_system_ops

Operations on mounted file systems.

Similar, but not equal, to struct super_operations in Linux

int(* format()

Format the file system on the given mount point.

Parameters

mountp:file system to format

Return values

  • 0 on success
  • <0 on error
int(* mount()

Perform any extra processing needed after mounting a file system.

If this call returns an error, the whole vfs_mount call will signal a failure.

All fields of mountp will be initialized by vfs_mount beforehand, private_data will be initialized to NULL.

Parameters

mountp:file system mount being mounted

Return values

  • 0 on success
  • <0 on error
int(* umount()

Perform the necessary clean up for unmounting a file system.

Parameters

mountp:file system mount being unmounted

Return values

  • 0 on success
  • <0 on error
int(* rename()

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

mountp:file system mount to operate on
from_path:absolute path to existing file
to_path:absolute path to destination

Return values

  • 0 on success
  • <0 on error
int(* unlink()

Unlink (delete) a file from the file system.

Parameters

mountp:file system mount to operate on
name:name of the file to delete

Return values

  • 0 on success
  • <0 on error
int(* mkdir()

Create a directory on the file system.

Parameters

mountp:file system mount to operate on
name:name of the directory to create
mode:file creation mode bits

Return values

  • 0 on success
  • <0 on error
int(* rmdir()

Remove a directory from the file system.

Only empty directories may be removed.

Parameters

mountp:file system mount to operate on
name:name of the directory to remove

Return values

  • 0 on success
  • <0 on error
int(* stat()

Get file status.

Parameters

mountp:file system mount to operate on
path:path to file being queried
buf:pointer to stat struct to fill

Return values

  • 0 on success
  • <0 on error
int(* statvfs()

Get file system status.

path is only passed for consistency against the POSIX statvfs function. vfs_statvfs calls this function only when it has determined that path belongs to this file system. path is a file system relative path and does not necessarily name an existing file.

Parameters

mountp:file system mount to operate on
path:path to a file on the file system being queried
buf:pointer to statvfs struct to fill

Return values

  • 0 on success
  • <0 on error
int(* fstatvfs()

Get file system status of an open file.

path is only passed for consistency against the POSIX statvfs function. vfs_statvfs calls this function only when it has determined that path belongs to this file system. path is a file system relative path and does not necessarily name an existing file.

Parameters

mountp:file system mount to operate on
filp:pointer to an open file on the file system being queried
buf:pointer to statvfs struct to fill

Return values

  • 0 on success
  • <0 on error