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 684d3e6d01
commit a1042c0cc2
No known key found for this signature in database
GPG Key ID: 1E050E141B280628

View File

@ -43,7 +43,7 @@ typedef struct {
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_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
char dir_path[FILENAME_MAX]; /* variable to store path of opened directory*/
struct cached_data cached_fileinfo;
@ -89,6 +89,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_fstat(void* ctx, int fd, struct stat * st);
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
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);
@ -174,6 +175,7 @@ static const esp_vfs_fs_ops_t s_vfs_fat = {
.open_p = &vfs_fat_open,
.close_p = &vfs_fat_close,
.fstat_p = &vfs_fat_fstat,
.fcntl_p = &vfs_fat_fcntl,
.fsync_p = &vfs_fat_fsync,
#ifdef CONFIG_VFS_SUPPORT_DIR
.dir = &s_vfs_fat_dir,
@ -203,19 +205,19 @@ esp_err_t esp_vfs_fat_register_cfg(const esp_vfs_fat_conf_t* conf, FATFS** out_f
return ESP_ERR_NO_MEM;
}
memset(fat_ctx, 0, ctx_size);
fat_ctx->o_append = ff_memalloc(max_files * sizeof(bool));
if (fat_ctx->o_append == NULL) {
fat_ctx->flags = ff_memalloc(max_files * sizeof(*fat_ctx->flags));
if (fat_ctx->flags == NULL) {
free(fat_ctx);
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;
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);
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) {
free(fat_ctx->o_append);
free(fat_ctx->flags);
free(fat_ctx);
return err;
}
@ -243,7 +245,7 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path)
return err;
}
_lock_close(&fat_ctx->lock);
free(fat_ctx->o_append);
free(fat_ctx->flags);
free(fat_ctx);
s_fat_ctxs[ctx] = NULL;
return ESP_OK;
@ -431,7 +433,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),
// therefore this flag is stored here (at this VFS level) in order to save
// 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);
return fd;
}
@ -442,7 +444,7 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size)
FIL* file = &fat_ctx->files[fd];
FRESULT res;
_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) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
errno = fresult_to_errno(res);
@ -676,6 +678,26 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
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
static inline mode_t get_stat_mode(bool is_dir)