feat(fatfs): add support for a few fcntl commands

This commit is contained in:
Ivan Grokhotkov 2024-10-24 18:03:13 +02:00
parent 7a214c1fab
commit 80d4c75b89
No known key found for this signature in database
GPG Key ID: 1E050E141B280628

View File

@ -39,7 +39,7 @@ typedef struct {
FATFS fs; /* fatfs library FS structure */ FATFS fs; /* fatfs library FS structure */
char tmp_path_buf[FILENAME_MAX+3]; /* temporary buffer used to prepend drive name to the path */ char tmp_path_buf[FILENAME_MAX+3]; /* temporary buffer used to prepend drive name to the path */
char tmp_path_buf2[FILENAME_MAX+3]; /* as above; used in functions which take two path arguments */ char tmp_path_buf2[FILENAME_MAX+3]; /* as above; used in functions which take two path arguments */
bool *o_append; /* O_APPEND is stored here for each max_files entries (because O_APPEND is not compatible with FA_OPEN_APPEND) */ uint32_t *flags; /* file descriptor flags, array of max_files size */
#ifdef CONFIG_VFS_SUPPORT_DIR #ifdef CONFIG_VFS_SUPPORT_DIR
char dir_path[FILENAME_MAX]; /* variable to store path of opened directory*/ char dir_path[FILENAME_MAX]; /* variable to store path of opened directory*/
struct cached_data cached_fileinfo; struct cached_data cached_fileinfo;
@ -85,6 +85,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode);
static int vfs_fat_close(void* ctx, int fd); static int vfs_fat_close(void* ctx, int fd);
static int vfs_fat_fstat(void* ctx, int fd, struct stat * st); static int vfs_fat_fstat(void* ctx, int fd, struct stat * st);
static int vfs_fat_fsync(void* ctx, int fd); static int vfs_fat_fsync(void* ctx, int fd);
static int vfs_fat_fcntl(void* ctx, int fd, int cmd, int arg);
#ifdef CONFIG_VFS_SUPPORT_DIR #ifdef CONFIG_VFS_SUPPORT_DIR
static int vfs_fat_stat(void* ctx, const char * path, struct stat * st); static int vfs_fat_stat(void* ctx, const char * path, struct stat * st);
static int vfs_fat_link(void* ctx, const char* n1, const char* n2); static int vfs_fat_link(void* ctx, const char* n1, const char* n2);
@ -170,6 +171,7 @@ static const esp_vfs_fs_ops_t s_vfs_fat = {
.open_p = &vfs_fat_open, .open_p = &vfs_fat_open,
.close_p = &vfs_fat_close, .close_p = &vfs_fat_close,
.fstat_p = &vfs_fat_fstat, .fstat_p = &vfs_fat_fstat,
.fcntl_p = &vfs_fat_fcntl,
.fsync_p = &vfs_fat_fsync, .fsync_p = &vfs_fat_fsync,
#ifdef CONFIG_VFS_SUPPORT_DIR #ifdef CONFIG_VFS_SUPPORT_DIR
.dir = &s_vfs_fat_dir, .dir = &s_vfs_fat_dir,
@ -199,19 +201,19 @@ esp_err_t esp_vfs_fat_register_cfg(const esp_vfs_fat_conf_t* conf, FATFS** out_f
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
memset(fat_ctx, 0, ctx_size); memset(fat_ctx, 0, ctx_size);
fat_ctx->o_append = ff_memalloc(max_files * sizeof(bool)); fat_ctx->flags = ff_memalloc(max_files * sizeof(*fat_ctx->flags));
if (fat_ctx->o_append == NULL) { if (fat_ctx->flags == NULL) {
free(fat_ctx); free(fat_ctx);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
memset(fat_ctx->o_append, 0, max_files * sizeof(bool)); memset(fat_ctx->flags, 0, max_files * sizeof(*fat_ctx->flags));
fat_ctx->max_files = max_files; fat_ctx->max_files = max_files;
strlcpy(fat_ctx->fat_drive, conf->fat_drive, sizeof(fat_ctx->fat_drive) - 1); strlcpy(fat_ctx->fat_drive, conf->fat_drive, sizeof(fat_ctx->fat_drive) - 1);
strlcpy(fat_ctx->base_path, conf->base_path, sizeof(fat_ctx->base_path) - 1); strlcpy(fat_ctx->base_path, conf->base_path, sizeof(fat_ctx->base_path) - 1);
esp_err_t err = esp_vfs_register_fs(conf->base_path, &s_vfs_fat, ESP_VFS_FLAG_CONTEXT_PTR | ESP_VFS_FLAG_STATIC, fat_ctx); esp_err_t err = esp_vfs_register_fs(conf->base_path, &s_vfs_fat, ESP_VFS_FLAG_CONTEXT_PTR | ESP_VFS_FLAG_STATIC, fat_ctx);
if (err != ESP_OK) { if (err != ESP_OK) {
free(fat_ctx->o_append); free(fat_ctx->flags);
free(fat_ctx); free(fat_ctx);
return err; return err;
} }
@ -239,7 +241,7 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path)
return err; return err;
} }
_lock_close(&fat_ctx->lock); _lock_close(&fat_ctx->lock);
free(fat_ctx->o_append); free(fat_ctx->flags);
free(fat_ctx); free(fat_ctx);
s_fat_ctxs[ctx] = NULL; s_fat_ctxs[ctx] = NULL;
return ESP_OK; return ESP_OK;
@ -427,7 +429,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
// Other VFS drivers handles O_APPEND well (to the best of my knowledge), // Other VFS drivers handles O_APPEND well (to the best of my knowledge),
// therefore this flag is stored here (at this VFS level) in order to save // therefore this flag is stored here (at this VFS level) in order to save
// memory. // memory.
fat_ctx->o_append[fd] = (flags & O_APPEND) == O_APPEND; fat_ctx->flags[fd] = (flags & (O_APPEND | O_ACCMODE));
_lock_release(&fat_ctx->lock); _lock_release(&fat_ctx->lock);
return fd; return fd;
} }
@ -438,7 +440,7 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size)
FIL* file = &fat_ctx->files[fd]; FIL* file = &fat_ctx->files[fd];
FRESULT res; FRESULT res;
_lock_acquire(&fat_ctx->lock); _lock_acquire(&fat_ctx->lock);
if (fat_ctx->o_append[fd]) { if (fat_ctx->flags[fd] & O_APPEND) {
if ((res = f_lseek(file, f_size(file))) != FR_OK) { if ((res = f_lseek(file, f_size(file))) != FR_OK) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
errno = fresult_to_errno(res); errno = fresult_to_errno(res);
@ -672,6 +674,26 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
return 0; return 0;
} }
static int vfs_fat_fcntl(void* ctx, int fd, int cmd, int arg)
{
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
switch (cmd) {
case F_GETFL:
return fat_ctx->flags[fd];
case F_SETFL:
fat_ctx->flags[fd] = arg;
return 0;
// no-ops:
case F_SETLK:
case F_SETLKW:
case F_GETLK:
return 0;
default:
errno = EINVAL;
return -1;
}
}
#ifdef CONFIG_VFS_SUPPORT_DIR #ifdef CONFIG_VFS_SUPPORT_DIR
static inline mode_t get_stat_mode(bool is_dir) static inline mode_t get_stat_mode(bool is_dir)