From 1df102ab939c732de37ccbe76d63215d7905885d Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Tue, 18 Jan 2022 07:44:30 +0000 Subject: [PATCH] Add Fat FS support --- docs/README.md | 2 ++ mongoose.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ mongoose.h | 10 +++++++ src/config.h | 4 +++ src/fs.h | 1 + src/fs_fat.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 175 insertions(+) create mode 100644 src/fs_fat.c diff --git a/docs/README.md b/docs/README.md index cdf67761..0bfa0d58 100644 --- a/docs/README.md +++ b/docs/README.md @@ -244,10 +244,12 @@ Here is a list of build constants and their default values: |MG_ENABLE_DIRLIST | 0 | Enable directory listing | |MG_ENABLE_CUSTOM_RANDOM | 0 | Provide custom RNG function `mg_random()` | |MG_ENABLE_PACKED_FS | 0 | Enable embedded FS support | +|MG_ENABLE_FATFS | 0 | Enable embedded FAT FS support | |MG_IO_SIZE | 2048 | Granularity of the send/recv IO buffer growth | |MG_MAX_RECV_BUF_SIZE | (3 * 1024 * 1024) | Maximum recv buffer size | |MG_MAX_HTTP_HEADERS | 40 | Maximum number of HTTP headers | |MG_HTTP_INDEX | "index.html" | Index file for HTML directory | +|MG_FATFS_ROOT | "/" | FAT FS root directory | |MG_ENABLE_LINES | undefined | If defined, show source file names in logs | NOTE: the `MG_IO_SIZE` constant also sets diff --git a/mongoose.c b/mongoose.c index 4db842f2..86e9cf43 100644 --- a/mongoose.c +++ b/mongoose.c @@ -433,6 +433,87 @@ void mg_fs_close(struct mg_fd *fd) { } } +#ifdef MG_ENABLE_LINES +#line 1 "src/fs_fat.c" +#endif +#if MG_ENABLE_FATFS +#include + +#if !defined(MG_FATFS_ROOT) +#define MG_FATFS_ROOT "/" +#endif + +static int ff_stat(const char *path, size_t *size, time_t *mtime) { + FILINFO fi; + if (path[0] == '\0' || strcmp(path, MG_FATFS_ROOT) == 0) { + if (size) *size = 0; + if (mtime) *mtime = 0; + return MG_FS_DIR; + } else if (f_stat(path, &fi) == 0) { + if (size) *size = (size_t) fi.fsize; + if (mtime) *mtime = (fi.fdate << 16) | fi.ftime; + return MG_FS_READ | MG_FS_WRITE | ((fi.fattrib & AM_DIR) ? MG_FS_DIR : 0); + } else { + return 0; + } +} + +static void ff_list(const char *dir, void (*fn)(const char *, void *), + void *userdata) { + DIR d; + FILINFO fi; + if (f_opendir(&d, dir) == FR_OK) { + while (f_readdir(&d, &fi) == FR_OK && fi.fname[0] != '\0') { + if (!strcmp(fi.fname, ".") || !strcmp(fi.fname, "..")) continue; + fn(fi.fname, userdata); + } + f_closedir(&d); + } +} + +static void *ff_open(const char *path, int flags) { + FIL f; + const char mode = flags == (MG_FS_READ | MG_FS_WRITE) ? FA_READ | FA_WRITE + : flags & MG_FS_READ ? FA_READ + : flags & MG_FS_WRITE ? FA_WRITE + : 0; + if (f_open(&f, path, mode) == 0) { + FIL *fp = calloc(1, sizeof(*fp)); + *fp = f; + return fp; + } else { + return NULL; + } +} + +static void ff_close(void *fp) { + if (fp != NULL) { + f_close((FIL *) fp); + free(fp); + } +} + +static size_t ff_read(void *fp, void *buf, size_t len) { + unsigned n = 0; + f_read((FIL *) fp, buf, len, &n); + return n; +} + +static size_t ff_write(void *fp, const void *buf, size_t len) { + unsigned n = 0; + f_write((FIL *) fp, buf, len, &n); + return n; +} + +static size_t ff_seek(void *fp, size_t offset) { + f_lseek((FIL *) fp, offset); + return offset; +} + +struct mg_fs mg_fs_fat = {ff_stat, ff_list, ff_open, ff_close, + ff_read, ff_write, ff_seek}; +#endif + #ifdef MG_ENABLE_LINES #line 1 "src/fs_packed.c" #endif diff --git a/mongoose.h b/mongoose.h index 60246657..9be79678 100644 --- a/mongoose.h +++ b/mongoose.h @@ -163,6 +163,11 @@ static __inline struct tm *localtime_r(const time_t *t, struct tm *tm) { #endif +#if defined(MG_ENABLE_FF) && MG_ENABLE_FF == 1 +#include +#endif + + #if MG_ARCH == MG_ARCH_FREERTOS_LWIP #include @@ -441,6 +446,10 @@ static __inline struct tm *localtime_r(const time_t *t, struct tm *tm) { #endif +#ifndef MG_ENABLE_FATFS +#define MG_ENABLE_FATFS 0 +#endif + #ifndef MG_ENABLE_SOCKET #define MG_ENABLE_SOCKET 1 #endif @@ -699,6 +708,7 @@ void mg_fs_close(struct mg_fd *fd); extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek extern struct mg_fs mg_fs_packed; // Packed FS, see examples/complete +extern struct mg_fs mg_fs_fat; // FAT FS diff --git a/src/config.h b/src/config.h index 8cad23eb..8fbeba60 100644 --- a/src/config.h +++ b/src/config.h @@ -1,5 +1,9 @@ #pragma once +#ifndef MG_ENABLE_FATFS +#define MG_ENABLE_FATFS 0 +#endif + #ifndef MG_ENABLE_SOCKET #define MG_ENABLE_SOCKET 1 #endif diff --git a/src/fs.h b/src/fs.h index efbe5275..a05f9438 100644 --- a/src/fs.h +++ b/src/fs.h @@ -28,3 +28,4 @@ void mg_fs_close(struct mg_fd *fd); extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek extern struct mg_fs mg_fs_packed; // Packed FS, see examples/complete +extern struct mg_fs mg_fs_fat; // FAT FS diff --git a/src/fs_fat.c b/src/fs_fat.c new file mode 100644 index 00000000..04079c55 --- /dev/null +++ b/src/fs_fat.c @@ -0,0 +1,77 @@ +#if MG_ENABLE_FATFS +#include + +#if !defined(MG_FATFS_ROOT) +#define MG_FATFS_ROOT "/" +#endif + +static int ff_stat(const char *path, size_t *size, time_t *mtime) { + FILINFO fi; + if (path[0] == '\0' || strcmp(path, MG_FATFS_ROOT) == 0) { + if (size) *size = 0; + if (mtime) *mtime = 0; + return MG_FS_DIR; + } else if (f_stat(path, &fi) == 0) { + if (size) *size = (size_t) fi.fsize; + if (mtime) *mtime = (fi.fdate << 16) | fi.ftime; + return MG_FS_READ | MG_FS_WRITE | ((fi.fattrib & AM_DIR) ? MG_FS_DIR : 0); + } else { + return 0; + } +} + +static void ff_list(const char *dir, void (*fn)(const char *, void *), + void *userdata) { + DIR d; + FILINFO fi; + if (f_opendir(&d, dir) == FR_OK) { + while (f_readdir(&d, &fi) == FR_OK && fi.fname[0] != '\0') { + if (!strcmp(fi.fname, ".") || !strcmp(fi.fname, "..")) continue; + fn(fi.fname, userdata); + } + f_closedir(&d); + } +} + +static void *ff_open(const char *path, int flags) { + FIL f; + const char mode = flags == (MG_FS_READ | MG_FS_WRITE) ? FA_READ | FA_WRITE + : flags & MG_FS_READ ? FA_READ + : flags & MG_FS_WRITE ? FA_WRITE + : 0; + if (f_open(&f, path, mode) == 0) { + FIL *fp = calloc(1, sizeof(*fp)); + *fp = f; + return fp; + } else { + return NULL; + } +} + +static void ff_close(void *fp) { + if (fp != NULL) { + f_close((FIL *) fp); + free(fp); + } +} + +static size_t ff_read(void *fp, void *buf, size_t len) { + unsigned n = 0; + f_read((FIL *) fp, buf, len, &n); + return n; +} + +static size_t ff_write(void *fp, const void *buf, size_t len) { + unsigned n = 0; + f_write((FIL *) fp, buf, len, &n); + return n; +} + +static size_t ff_seek(void *fp, size_t offset) { + f_lseek((FIL *) fp, offset); + return offset; +} + +struct mg_fs mg_fs_fat = {ff_stat, ff_list, ff_open, ff_close, + ff_read, ff_write, ff_seek}; +#endif