mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(vfs): add syscall argument validation in VFS layer
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -80,27 +80,27 @@ typedef struct {
|
||||
esp_err_t esp_vfs_register_common(const char *base_path, size_t len, const esp_vfs_t *vfs, void *ctx, int *vfs_index);
|
||||
|
||||
/**
|
||||
* Get vfs fd with given path.
|
||||
* Resolve which registered VFS should handle the given absolute path.
|
||||
*
|
||||
* @param path file path prefix associated with the filesystem.
|
||||
* @param path Zero-terminated absolute path. Must not be NULL when calling
|
||||
* `strlen` internally; callers should reject NULL paths first
|
||||
* (typically with `EINVAL`) before invoking this helper.
|
||||
*
|
||||
* @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL.
|
||||
* @return Matching `vfs_entry_t`, or NULL if @p path is NULL or no VFS matches.
|
||||
*/
|
||||
const vfs_entry_t *get_vfs_for_path(const char *path);
|
||||
|
||||
/**
|
||||
* Get vfs fd with given vfs index.
|
||||
* Get VFS entry for a given VFS table index.
|
||||
*
|
||||
* @param index VFS index.
|
||||
* @param index VFS index (as stored on FDs / DIR handles).
|
||||
*
|
||||
* @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL.
|
||||
* @return Pointer to the `vfs_entry_t` for @p index, or NULL if invalid / unused.
|
||||
*/
|
||||
const vfs_entry_t *get_vfs_for_index(int index);
|
||||
|
||||
const char* translate_path(const vfs_entry_t* vfs, const char* src_path);
|
||||
|
||||
const vfs_entry_t* get_vfs_for_path(const char* path);
|
||||
|
||||
const vfs_entry_t *get_vfs_for_fd(int fd);
|
||||
|
||||
int register_fd(int vfs_index, int local_fd, bool permanent);
|
||||
|
||||
@@ -5,6 +5,43 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Early-return helpers for VFS syscalls (errno via reent).
|
||||
* `r` must be a struct _reent * in scope, as for CHECK_AND_CALL macros.
|
||||
*/
|
||||
#define VFS_RETURN_ERR(r, err, ret) \
|
||||
do { \
|
||||
__errno_r(r) = (err); \
|
||||
return (ret); \
|
||||
} while (0)
|
||||
|
||||
#define VFS_RETURN_ON_NULL_PTR(r, ptr, err, ret) \
|
||||
do { \
|
||||
if ((ptr) == NULL) { \
|
||||
VFS_RETURN_ERR(r, err, ret); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFS_RETURN_ON_NULL_IOBUF(r, buf, size, ret) \
|
||||
do { \
|
||||
if ((size) != 0 && (buf) == NULL) { \
|
||||
VFS_RETURN_ERR(r, EINVAL, ret); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFS_RETURNV_ERR(r, err) \
|
||||
do { \
|
||||
__errno_r(r) = (err); \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
#define VFS_RETURNV_ON_NULL_PTR(r, ptr, err) \
|
||||
do { \
|
||||
if ((ptr) == NULL) { \
|
||||
VFS_RETURNV_ERR(r, err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Using huge multi-line macros is never nice, but in this case
|
||||
* the only alternative is to repeat this chunk of code (with different function names)
|
||||
@@ -19,8 +56,7 @@
|
||||
*/
|
||||
#define CHECK_AND_CALL(ret, r, pvfs, func, ...) \
|
||||
if (pvfs->vfs->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return -1; \
|
||||
VFS_RETURN_ERR(r, ENOSYS, -1); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
ret = (*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -30,8 +66,7 @@
|
||||
|
||||
#define CHECK_AND_CALL_SUBCOMPONENT(ret, r, pvfs, component, func, ...) \
|
||||
if (pvfs->vfs->component == NULL || pvfs->vfs->component->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return -1; \
|
||||
VFS_RETURN_ERR(r, ENOSYS, -1); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
ret = (*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -41,8 +76,7 @@
|
||||
|
||||
#define CHECK_AND_CALLV(r, pvfs, func, ...) \
|
||||
if (pvfs->vfs->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return; \
|
||||
VFS_RETURNV_ERR(r, ENOSYS); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
(*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -52,8 +86,7 @@
|
||||
|
||||
#define CHECK_AND_CALL_SUBCOMPONENTV(r, pvfs, component, func, ...) \
|
||||
if (pvfs->vfs->component == NULL || pvfs->vfs->component->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return; \
|
||||
VFS_RETURNV_ERR(r, ENOSYS); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
(*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -63,8 +96,7 @@
|
||||
|
||||
#define CHECK_AND_CALLP(ret, r, pvfs, func, ...) \
|
||||
if (pvfs->vfs->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return NULL; \
|
||||
VFS_RETURN_ERR(r, ENOSYS, NULL); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
ret = (*pvfs->vfs->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -74,8 +106,7 @@
|
||||
|
||||
#define CHECK_AND_CALL_SUBCOMPONENTP(ret, r, pvfs, component, func, ...) \
|
||||
if (pvfs->vfs->component == NULL || pvfs->vfs->component->func ## _p == NULL) { \
|
||||
__errno_r(r) = ENOSYS; \
|
||||
return NULL; \
|
||||
VFS_RETURN_ERR(r, ENOSYS, NULL); \
|
||||
} \
|
||||
if (pvfs->flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
|
||||
ret = (*pvfs->vfs->component->func ## _p)(pvfs->ctx, __VA_ARGS__); \
|
||||
@@ -85,6 +116,5 @@
|
||||
|
||||
#define CHECK_VFS_READONLY_FLAG(flags) \
|
||||
if (flags & ESP_VFS_FLAG_READONLY_FS) { \
|
||||
__errno_r(r) = EROFS; \
|
||||
return -1; \
|
||||
VFS_RETURN_ERR(r, EROFS, -1); \
|
||||
}
|
||||
|
||||
@@ -833,6 +833,9 @@ const char* translate_path(const vfs_entry_t* vfs, const char* src_path)
|
||||
|
||||
const vfs_entry_t* get_vfs_for_path(const char* path)
|
||||
{
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
const vfs_entry_t* best_match = NULL;
|
||||
ssize_t best_match_prefix_len = -1;
|
||||
size_t len = strlen(path);
|
||||
|
||||
@@ -31,17 +31,16 @@ static const char __attribute__((unused)) *TAG = "vfs_calls";
|
||||
|
||||
int esp_vfs_open(struct _reent *r, const char *path, int flags, int mode)
|
||||
{
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
int acc_mode = flags & O_ACCMODE;
|
||||
int ro_filesystem = vfs->flags & ESP_VFS_FLAG_READONLY_FS;
|
||||
if (acc_mode != O_RDONLY && ro_filesystem) {
|
||||
__errno_r(r) = EROFS;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EROFS, -1);
|
||||
}
|
||||
|
||||
const char *path_within_vfs = translate_path(vfs, path);
|
||||
@@ -49,8 +48,7 @@ int esp_vfs_open(struct _reent *r, const char *path, int flags, int mode)
|
||||
CHECK_AND_CALL(fd_within_vfs, r, vfs, open, path_within_vfs, flags, mode);
|
||||
|
||||
if (fd_within_vfs < 0) {
|
||||
__errno_r(r) = errno;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, errno, -1);
|
||||
}
|
||||
|
||||
int fd = register_fd(vfs->offset, fd_within_vfs, false);
|
||||
@@ -61,8 +59,7 @@ int esp_vfs_open(struct _reent *r, const char *path, int flags, int mode)
|
||||
int ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, close, fd_within_vfs);
|
||||
(void) ret; // remove "set but not used" warning
|
||||
__errno_r(r) = ENFILE;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENFILE, -1);
|
||||
}
|
||||
|
||||
ssize_t esp_vfs_write(struct _reent *r, int fd, const void *data, size_t size)
|
||||
@@ -70,9 +67,9 @@ ssize_t esp_vfs_write(struct _reent *r, int fd, const void *data, size_t size)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_IOBUF(r, data, size, -1);
|
||||
ssize_t ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, write, local_fd, data, size);
|
||||
return ret;
|
||||
@@ -83,8 +80,7 @@ off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
off_t ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, lseek, local_fd, size, mode);
|
||||
@@ -96,9 +92,9 @@ ssize_t esp_vfs_read(struct _reent *r, int fd, void *dst, size_t size)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_IOBUF(r, dst, size, -1);
|
||||
ssize_t ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, read, local_fd, dst, size);
|
||||
return ret;
|
||||
@@ -110,9 +106,9 @@ ssize_t esp_vfs_pread(int fd, void *dst, size_t size, off_t offset)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_IOBUF(r, dst, size, -1);
|
||||
ssize_t ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, pread, local_fd, dst, size, offset);
|
||||
return ret;
|
||||
@@ -124,9 +120,9 @@ ssize_t esp_vfs_pwrite(int fd, const void *src, size_t size, off_t offset)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_IOBUF(r, src, size, -1);
|
||||
ssize_t ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, pwrite, local_fd, src, size, offset);
|
||||
return ret;
|
||||
@@ -137,8 +133,7 @@ int esp_vfs_close(struct _reent *r, int fd)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, close, local_fd);
|
||||
@@ -153,9 +148,9 @@ int esp_vfs_fstat(struct _reent *r, int fd, struct stat *st)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_PTR(r, st, EINVAL, -1);
|
||||
int ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, fstat, local_fd, st);
|
||||
return ret;
|
||||
@@ -166,8 +161,7 @@ int esp_vfs_fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||
const vfs_entry_t *vfs = get_vfs_for_fd(fd);
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, arg);
|
||||
@@ -180,13 +174,11 @@ int esp_vfs_ioctl(int fd, int cmd, ...)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
|
||||
if (vfs->vfs->ioctl == NULL) {
|
||||
__errno_r(r) = ENOSYS;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOSYS, -1);
|
||||
}
|
||||
|
||||
int ret;
|
||||
@@ -209,8 +201,7 @@ int esp_vfs_fsync(int fd)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL(ret, r, vfs, fsync, local_fd);
|
||||
@@ -221,10 +212,11 @@ int esp_vfs_fsync(int fd)
|
||||
|
||||
int esp_vfs_stat(struct _reent *r, const char *path, struct stat *st)
|
||||
{
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
VFS_RETURN_ON_NULL_PTR(r, st, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
const char *path_within_vfs = translate_path(vfs, path);
|
||||
int ret;
|
||||
@@ -235,11 +227,11 @@ int esp_vfs_stat(struct _reent *r, const char *path, struct stat *st)
|
||||
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
||||
{
|
||||
int ret;
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
const char *path_within_vfs = translate_path(vfs, path);
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, utime, path_within_vfs, times);
|
||||
@@ -248,15 +240,15 @@ int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
||||
|
||||
int esp_vfs_link(struct _reent *r, const char *n1, const char *n2)
|
||||
{
|
||||
VFS_RETURN_ON_NULL_PTR(r, n1, EINVAL, -1);
|
||||
VFS_RETURN_ON_NULL_PTR(r, n2, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(n1);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
const vfs_entry_t *vfs2 = get_vfs_for_path(n2);
|
||||
if (vfs != vfs2) {
|
||||
__errno_r(r) = EXDEV;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EXDEV, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs2->flags);
|
||||
@@ -270,10 +262,10 @@ int esp_vfs_link(struct _reent *r, const char *n1, const char *n2)
|
||||
|
||||
int esp_vfs_unlink(struct _reent *r, const char *path)
|
||||
{
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
@@ -286,18 +278,18 @@ int esp_vfs_unlink(struct _reent *r, const char *path)
|
||||
|
||||
int esp_vfs_rename(struct _reent *r, const char *src, const char *dst)
|
||||
{
|
||||
VFS_RETURN_ON_NULL_PTR(r, src, EINVAL, -1);
|
||||
VFS_RETURN_ON_NULL_PTR(r, dst, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(src);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
|
||||
const vfs_entry_t *vfs_dst = get_vfs_for_path(dst);
|
||||
if (vfs != vfs_dst) {
|
||||
__errno_r(r) = EXDEV;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EXDEV, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs_dst->flags);
|
||||
@@ -311,11 +303,11 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst)
|
||||
|
||||
DIR *esp_vfs_opendir(const char *name)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, name, EINVAL, NULL);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return NULL;
|
||||
VFS_RETURN_ERR(r, ENOENT, NULL);
|
||||
}
|
||||
const char *path_within_vfs = translate_path(vfs, name);
|
||||
DIR *ret;
|
||||
@@ -328,11 +320,11 @@ DIR *esp_vfs_opendir(const char *name)
|
||||
|
||||
struct dirent *esp_vfs_readdir(DIR *pdir)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, pdir, EBADF, NULL);
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = EBADF;
|
||||
return NULL;
|
||||
VFS_RETURN_ERR(r, EBADF, NULL);
|
||||
}
|
||||
struct dirent *ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENTP(ret, r, vfs, dir, readdir, pdir);
|
||||
@@ -341,11 +333,13 @@ struct dirent *esp_vfs_readdir(DIR *pdir)
|
||||
|
||||
int esp_vfs_readdir_r(DIR *pdir, struct dirent *entry, struct dirent* *out_dirent)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, pdir, EINVAL, -1);
|
||||
VFS_RETURN_ON_NULL_PTR(r, entry, EINVAL, -1);
|
||||
VFS_RETURN_ON_NULL_PTR(r, out_dirent, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
if (vfs == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, readdir_r, pdir, entry, out_dirent);
|
||||
@@ -354,11 +348,11 @@ int esp_vfs_readdir_r(DIR *pdir, struct dirent *entry, struct dirent* *out_diren
|
||||
|
||||
long esp_vfs_telldir(DIR *pdir)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, pdir, EBADF, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
if (vfs == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
long ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, telldir, pdir);
|
||||
@@ -367,11 +361,11 @@ long esp_vfs_telldir(DIR *pdir)
|
||||
|
||||
void esp_vfs_seekdir(DIR *pdir, long loc)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURNV_ON_NULL_PTR(r, pdir, EBADF);
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
if (vfs == NULL) {
|
||||
errno = EBADF;
|
||||
return;
|
||||
VFS_RETURNV_ERR(r, EBADF);
|
||||
}
|
||||
CHECK_AND_CALL_SUBCOMPONENTV(r, vfs, dir, seekdir, pdir, loc);
|
||||
}
|
||||
@@ -383,11 +377,11 @@ void esp_vfs_rewinddir(DIR *pdir)
|
||||
|
||||
int esp_vfs_closedir(DIR *pdir)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, pdir, EBADF, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||
if (vfs == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, closedir, pdir);
|
||||
@@ -396,11 +390,11 @@ int esp_vfs_closedir(DIR *pdir)
|
||||
|
||||
int esp_vfs_mkdir(const char *name, mode_t mode)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, name, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
@@ -413,11 +407,11 @@ int esp_vfs_mkdir(const char *name, mode_t mode)
|
||||
|
||||
int esp_vfs_rmdir(const char *name)
|
||||
{
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, name, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(name);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
@@ -431,11 +425,11 @@ int esp_vfs_rmdir(const char *name)
|
||||
int esp_vfs_access(const char *path, int amode)
|
||||
{
|
||||
int ret;
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
const char *path_within_vfs = translate_path(vfs, path);
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, dir, access, path_within_vfs, amode);
|
||||
@@ -445,11 +439,11 @@ int esp_vfs_access(const char *path, int amode)
|
||||
int esp_vfs_truncate(const char *path, off_t length)
|
||||
{
|
||||
int ret;
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
VFS_RETURN_ON_NULL_PTR(r, path, EINVAL, -1);
|
||||
const vfs_entry_t *vfs = get_vfs_for_path(path);
|
||||
if (vfs == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOENT, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
@@ -465,8 +459,7 @@ int esp_vfs_ftruncate(int fd, off_t length)
|
||||
int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
|
||||
CHECK_VFS_READONLY_FLAG(vfs->flags);
|
||||
@@ -561,8 +554,7 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
|
||||
if (nfds > MAX_FDS || nfds < 0) {
|
||||
ESP_LOGD(TAG, "incorrect nfds");
|
||||
__errno_r(r) = EINVAL;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EINVAL, -1);
|
||||
}
|
||||
|
||||
// Capture s_vfs_count to a local variable in case a new driver is registered or removed during this actual select()
|
||||
@@ -571,9 +563,8 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
const size_t vfs_count = get_vfs_count();
|
||||
fds_triple_t *vfs_fds_triple;
|
||||
if ((vfs_fds_triple = heap_caps_calloc(vfs_count, sizeof(fds_triple_t), VFS_MALLOC_FLAGS)) == NULL) {
|
||||
__errno_r(r) = ENOMEM;
|
||||
ESP_LOGD(TAG, "calloc is unsuccessful");
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOMEM, -1);
|
||||
}
|
||||
|
||||
esp_vfs_select_sem_t sel_sem = {
|
||||
@@ -637,9 +628,8 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
sel_sem.is_sem_local = true;
|
||||
if ((sel_sem.sem = xSemaphoreCreateBinary()) == NULL) {
|
||||
free(vfs_fds_triple);
|
||||
__errno_r(r) = ENOMEM;
|
||||
ESP_LOGD(TAG, "cannot create select semaphore");
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOMEM, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,9 +637,8 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
|
||||
if (driver_args == NULL) {
|
||||
free(vfs_fds_triple);
|
||||
__errno_r(r) = ENOMEM;
|
||||
ESP_LOGD(TAG, "calloc is unsuccessful for driver args");
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, ENOMEM, -1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < vfs_count; ++i) {
|
||||
@@ -685,9 +674,8 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
|
||||
}
|
||||
free(vfs_fds_triple);
|
||||
free(driver_args);
|
||||
__errno_r(r) = EINTR;
|
||||
ESP_LOGD(TAG, "start_select failed: %s", esp_err_to_name(err));
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EINTR, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,9 +803,9 @@ int tcgetattr(int fd, struct termios *p)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_PTR(r, p, EINVAL, -1);
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcgetattr, local_fd, p);
|
||||
return ret;
|
||||
@@ -829,9 +817,9 @@ int tcsetattr(int fd, int optional_actions, const struct termios *p)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
VFS_RETURN_ON_NULL_PTR(r, p, EINVAL, -1);
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcsetattr, local_fd, optional_actions, p);
|
||||
return ret;
|
||||
@@ -843,8 +831,7 @@ int tcdrain(int fd)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcdrain, local_fd);
|
||||
@@ -857,8 +844,7 @@ int tcflush(int fd, int select)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcflush, local_fd, select);
|
||||
@@ -871,8 +857,7 @@ int tcflow(int fd, int action)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcflow, local_fd, action);
|
||||
@@ -885,8 +870,7 @@ pid_t tcgetsid(int fd)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcgetsid, local_fd);
|
||||
@@ -899,8 +883,7 @@ int tcsendbreak(int fd, int duration)
|
||||
const int local_fd = get_local_fd(vfs, fd);
|
||||
struct _reent __attribute__((unused)) *r = __getreent();
|
||||
if (vfs == NULL || local_fd < 0) {
|
||||
__errno_r(r) = EBADF;
|
||||
return -1;
|
||||
VFS_RETURN_ERR(r, EBADF, -1);
|
||||
}
|
||||
int ret;
|
||||
CHECK_AND_CALL_SUBCOMPONENT(ret, r, vfs, termios, tcsendbreak, local_fd, duration);
|
||||
|
||||
Reference in New Issue
Block a user