FileSystem
FileSystem class hierarchy
The file system API provides a common interface for implementing a file system on a block-based storage device. The file system API is a class-based interface, but implementing the file system API provides the standard POSIX file API familiar to C users.
The main purpose of a FileSystem is to be instantiated. The FileSystem's constructor can take in a BlockDevice and mount point specified as a string, as well as other implementation-specific configuration options. The mount point can then act as the first directory in any paths in Mbed OS when used with the POSIX API. This gives you access to files inside the file system. The mount point can be NULL
if you only need to use the FileSystem as a C++ object.
The FileSystem's file
and dir
functions are protected because you should not use the FileSystem file
and dir
functions directly. They are only a convenience for implementors. Instead, the File and Dir classes provide access to file and directory operations in a C++ class that respects RAII and other C++ conventions.
File system get default instance
The Mbed OS configuration allows you to add block devices as components using the targets.json
file or target overrides in the application configuration file.
For details regarding how to configure the default file system or override its implemetation, please refer to the storage configuration guide.
File system class reference
Public Member Functions | |
FileSystem (const char *name=NULL) | |
FileSystem lifetime. More... | |
virtual int | mount (BlockDevice *bd)=0 |
Mounts a filesystem to a block device. More... | |
virtual int | unmount ()=0 |
Unmounts a filesystem from the underlying block device. More... | |
virtual int | reformat (BlockDevice *bd=NULL) |
Reformats a filesystem, results in an empty and mounted filesystem. More... | |
virtual int | remove (const char *path) |
Remove a file from the filesystem. More... | |
virtual int | rename (const char *path, const char *newpath) |
Rename a file in the filesystem. More... | |
virtual int | stat (const char *path, struct stat *st) |
Store information about the file in a stat structure. More... | |
virtual int | mkdir (const char *path, mode_t mode) |
Create a directory in the filesystem. More... | |
virtual int | statvfs (const char *path, struct statvfs *buf) |
Store information about the mounted filesystem in a statvfs structure. More... | |
FileHandle * | open (const char *path, int flags) |
Open a file on the filesystem. More... | |
DirHandle * | opendir (const char *path) |
Open a directory on the filesystem. More... |
Static Public Member Functions | |
static FileSystem * | get_default_instance () |
Return the default filesystem. More... |
Protected Member Functions | |
virtual int | file_open (fs_file_t *file, const char *path, int flags)=0 |
Open a file on the filesystem. More... | |
virtual int | file_close (fs_file_t file)=0 |
Close a file. More... | |
virtual ssize_t | file_read (fs_file_t file, void *buffer, size_t size)=0 |
Read the contents of a file into a buffer. More... | |
virtual ssize_t | file_write (fs_file_t file, const void *buffer, size_t size)=0 |
Write the contents of a buffer to a file. More... | |
virtual int | file_sync (fs_file_t file) |
Flush any buffers associated with the file. More... | |
virtual int | file_isatty (fs_file_t file) |
Check if the file in an interactive terminal device If so, line buffered behaviour is used by default. More... | |
virtual off_t | file_seek (fs_file_t file, off_t offset, int whence)=0 |
Move the file position to a given offset from from a given location. More... | |
virtual off_t | file_tell (fs_file_t file) |
Get the file position of the file. More... | |
virtual void | file_rewind (fs_file_t file) |
Rewind the file position to the beginning of the file. More... | |
virtual off_t | file_size (fs_file_t file) |
Get the size of the file. More... | |
virtual int | dir_open (fs_dir_t *dir, const char *path) |
Open a directory on the filesystem. More... | |
virtual int | dir_close (fs_dir_t dir) |
Close a directory. More... | |
virtual ssize_t | dir_read (fs_dir_t dir, struct dirent *ent) |
Read the next directory entry. More... | |
virtual void | dir_seek (fs_dir_t dir, off_t offset) |
Set the current position of the directory. More... | |
virtual off_t | dir_tell (fs_dir_t dir) |
Get the current position of the directory. More... | |
virtual void | dir_rewind (fs_dir_t dir) |
Rewind the current position to the beginning of the directory. More... | |
virtual size_t | dir_size (fs_dir_t dir) |
Get the sizeof the directory. More... | |
virtual int | open (FileHandle **file, const char *path, int flags) |
Open a file on the filesystem. More... | |
virtual int | open (DirHandle **dir, const char *path) |
Open a directory on the filesystem. More... |
File system example
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include <stdio.h>
#include <errno.h>
#include "BlockDevice.h"
// This will take the system's default block device
BlockDevice *bd = BlockDevice::get_default_instance();
// Instead of the default block device, you can define your own block device.
// For example: HeapBlockDevice with size of 2048 bytes, read size 1, write size 1 and erase size 512.
// #include "HeapBlockDevice.h"
// BlockDevice *bd = new HeapBlockDevice(2048, 1, 1, 512);
// This example uses LittleFileSystem as the default file system
#include "LittleFileSystem.h"
LittleFileSystem fs("fs");
// Uncomment the following two lines and comment the previous two to use FAT file system.
// #include "FATFileSystem.h"
// FATFileSystem fs("fs");
// Set up the button to trigger an erase
InterruptIn irq(BUTTON1);
void erase() {
printf("Initializing the block device... ");
fflush(stdout);
int err = bd->init();
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Erasing the block device... ");
fflush(stdout);
err = bd->erase(0, bd->size());
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Deinitializing the block device... ");
fflush(stdout);
err = bd->deinit();
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
}
// Entry point for the example
int main() {
printf("--- Mbed OS filesystem example ---\n");
// Setup the erase event on button press, use the event queue
// to avoid running in interrupt context
irq.fall(mbed_event_queue()->event(erase));
// Try to mount the filesystem
printf("Mounting the filesystem... ");
fflush(stdout);
int err = fs.mount(bd);
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
// Reformat if we can't mount the filesystem
// this should only happen on the first boot
printf("No filesystem found, formatting... ");
fflush(stdout);
err = fs.reformat(bd);
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
}
// Open the numbers file
printf("Opening \"/fs/numbers.txt\"... ");
fflush(stdout);
FILE *f = fopen("/fs/numbers.txt", "r+");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
// Create the numbers file if it doesn't exist
printf("No file found, creating a new file... ");
fflush(stdout);
f = fopen("/fs/numbers.txt", "w+");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
for (int i = 0; i < 10; i++) {
printf("\rWriting numbers (%d/%d)... ", i, 10);
fflush(stdout);
err = fprintf(f, " %d\n", i);
if (err < 0) {
printf("Fail :(\n");
error("error: %s (%d)\n", strerror(errno), -errno);
}
}
printf("\rWriting numbers (%d/%d)... OK\n", 10, 10);
printf("Seeking file... ");
fflush(stdout);
err = fseek(f, 0, SEEK_SET);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
}
// Go through and increment the numbers
for (int i = 0; i < 10; i++) {
printf("\rIncrementing numbers (%d/%d)... ", i, 10);
fflush(stdout);
// Get current stream position
long pos = ftell(f);
// Parse out the number and increment
int32_t number;
fscanf(f, "%d", &number);
number += 1;
// Seek to beginning of number
fseek(f, pos, SEEK_SET);
// Store number
fprintf(f, " %d\n", number);
// Flush between write and read on same file
fflush(f);
}
printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10);
// Close the file which also flushes any cached writes
printf("Closing \"/fs/numbers.txt\"... ");
fflush(stdout);
err = fclose(f);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Display the root directory
printf("Opening the root directory... ");
fflush(stdout);
DIR *d = opendir("/fs/");
printf("%s\n", (!d ? "Fail :(" : "OK"));
if (!d) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
printf("root directory:\n");
while (true) {
struct dirent *e = readdir(d);
if (!e) {
break;
}
printf(" %s\n", e->d_name);
}
printf("Closing the root directory... ");
fflush(stdout);
err = closedir(d);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Display the numbers file
printf("Opening \"/fs/numbers.txt\"... ");
fflush(stdout);
f = fopen("/fs/numbers.txt", "r");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
printf("numbers:\n");
while (!feof(f)) {
int c = fgetc(f);
printf("%c", c);
}
printf("\rClosing \"/fs/numbers.txt\"... ");
fflush(stdout);
err = fclose(f);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Tidy up
printf("Unmounting... ");
fflush(stdout);
err = fs.unmount();
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Mbed OS filesystem example done!\n");
}
Sector requirements
LittleFS requirements:
- 4 blocks root dir.
- 2 blocks per dir.
- 1 block per file.
FATFS requirements:
- Hard minimum: 256 blocks.
- 128 blocks for FAT table.
- 1 block per dir.
- 1 block per file.