Add Fat FS support

This commit is contained in:
Sergey Lyubka 2022-01-18 07:44:30 +00:00
parent 02b3b780bb
commit 1df102ab93
6 changed files with 175 additions and 0 deletions

View File

@ -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 |
<span class="badge bg-danger">NOTE:</span> the `MG_IO_SIZE` constant also sets

View File

@ -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 <ff.h>
#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

View File

@ -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 <ff.h>
#endif
#if MG_ARCH == MG_ARCH_FREERTOS_LWIP
#include <stdarg.h>
@ -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

View File

@ -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

View File

@ -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

77
src/fs_fat.c Normal file
View File

@ -0,0 +1,77 @@
#if MG_ENABLE_FATFS
#include <ff.h>
#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