]> granicus.if.org Git - esp-idf/commitdiff
vfs: add directory APIs
authorIvan Grokhotkov <ivan@espressif.com>
Mon, 2 Jan 2017 19:26:25 +0000 (03:26 +0800)
committerIvan Grokhotkov <igrokhotkov@gmail.com>
Sun, 8 Jan 2017 20:51:24 +0000 (04:51 +0800)
components/newlib/include/sys/dirent.h [deleted file]
components/vfs/include/esp_vfs.h
components/vfs/include/sys/dirent.h [new file with mode: 0644]
components/vfs/vfs.c

diff --git a/components/newlib/include/sys/dirent.h b/components/newlib/include/sys/dirent.h
deleted file mode 100644 (file)
index a3fb5c0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* <dirent.h> includes <sys/dirent.h>, which is this file.  On a
-   system which supports <dirent.h>, this file is overridden by
-   dirent.h in the libc/sys/.../sys directory.  On a system which does
-   not support <dirent.h>, we will get this file which uses #error to force
-   an error.  */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#error "<dirent.h> not supported"
-#ifdef __cplusplus
-}
-#endif
index 5d9236b54c6e41026b0a46a5fe4ec76020f69ffd..304750aabd6193d5897cc6b93916202bf2c21046 100644 (file)
@@ -21,6 +21,8 @@
 #include <sys/types.h>
 #include <sys/reent.h>
 #include <sys/stat.h>
+#include <dirent.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -106,6 +108,38 @@ typedef struct
         int (*rename_p)(void* ctx, const char *src, const char *dst);
         int (*rename)(const char *src, const char *dst);
     };
+    union {
+        DIR* (*opendir_p)(void* ctx, const char* name);
+        DIR* (*opendir)(const char* name);
+    };
+    union {
+        struct dirent* (*readdir_p)(void* ctx, DIR* pdir);
+        struct dirent* (*readdir)(DIR* pdir);
+    };
+    union {
+        int (*readdir_r_p)(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent);
+        int (*readdir_r)(DIR* pdir, struct dirent* entry, struct dirent** out_dirent);
+    };
+    union {
+        long (*telldir_p)(void* ctx, DIR* pdir);
+        long (*telldir)(DIR* pdir);
+    };
+    union {
+        void (*seekdir_p)(void* ctx, DIR* pdir, long offset);
+        void (*seekdir)(DIR* pdir, long offset);
+    };
+    union {
+        int (*closedir_p)(void* ctx, DIR* pdir);
+        int (*closedir)(DIR* pdir);
+    };
+    union {
+        int (*mkdir_p)(void* ctx, const char* name, mode_t mode);
+        int (*mkdir)(const char* name, mode_t mode);
+    };
+    union {
+        int (*rmdir_p)(void* ctx, const char* name);
+        int (*rmdir)(const char* name);
+    };
 } esp_vfs_t;
 
 
diff --git a/components/vfs/include/sys/dirent.h b/components/vfs/include/sys/dirent.h
new file mode 100644 (file)
index 0000000..57b5be5
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * This header file provides POSIX-compatible definitions of directory
+ * access functions and related data types.
+ * See http://pubs.opengroup.org/onlinepubs/7908799/xsh/dirent.h.html
+ * for reference.
+ */
+
+/**
+ * @brief Opaque directory structure
+ */
+typedef struct {
+    uint16_t dd_vfs_idx; /*!< VFS index, not to be used by applications */
+    uint16_t dd_rsv;     /*!< field reserved for future extension */
+    /* remaining fields are defined by VFS implementation */
+} DIR;
+
+/**
+ * @brief Directory entry structure
+ */
+struct dirent {
+    int d_ino;          /*!< file number */
+    uint8_t d_type;     /*!< not defined in POSIX, but present in BSD and Linux */
+#define DT_UNKNOWN  0
+#define DT_REG      1
+#define DT_DIR      2
+    char d_name[256];   /*!< zero-terminated file name */
+};
+
+DIR* opendir(const char* name);
+struct dirent* readdir(DIR* pdir);
+long telldir(DIR* pdir);
+void seekdir(DIR* pdir, long loc);
+void rewinddir(DIR* pdir);
+int closedir(DIR* pdir);
+int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent);
+
index b166a427bb8dbb39313162f78f885b092580fdfa..d80972a533c58f297c78fd1e4105bb1a35e41864 100644 (file)
@@ -163,6 +163,28 @@ static const vfs_entry_t* get_vfs_for_path(const char* path)
     }
 
 
+#define CHECK_AND_CALLV(r, pvfs, func, ...) \
+    if (pvfs->vfs.func == NULL) { \
+        __errno_r(r) = ENOSYS; \
+        return; \
+    } \
+    if (pvfs->vfs.flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
+        (*pvfs->vfs.func ## _p)(pvfs->ctx, __VA_ARGS__); \
+    } else { \
+        (*pvfs->vfs.func)(__VA_ARGS__);\
+    }
+
+#define CHECK_AND_CALLP(ret, r, pvfs, func, ...) \
+    if (pvfs->vfs.func == NULL) { \
+        __errno_r(r) = ENOSYS; \
+        return NULL; \
+    } \
+    if (pvfs->vfs.flags & ESP_VFS_FLAG_CONTEXT_PTR) { \
+        ret = (*pvfs->vfs.func ## _p)(pvfs->ctx, __VA_ARGS__); \
+    } else { \
+        ret = (*pvfs->vfs.func)(__VA_ARGS__);\
+    }
+
 int esp_vfs_open(struct _reent *r, const char * path, int flags, int mode)
 {
     const vfs_entry_t* vfs = get_vfs_for_path(path);
@@ -309,3 +331,116 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst)
     CHECK_AND_CALL(ret, r, vfs, rename, src_within_vfs, dst_within_vfs);
     return ret;
 }
+
+DIR* opendir(const char* name)
+{
+    const vfs_entry_t* vfs = get_vfs_for_path(name);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        __errno_r(r) = ENOENT;
+        return NULL;
+    }
+    const char* path_within_vfs = translate_path(vfs, name);
+    DIR* ret;
+    CHECK_AND_CALLP(ret, r, vfs, opendir, path_within_vfs);
+    if (ret != NULL) {
+        ret->dd_vfs_idx = vfs->offset << VFS_INDEX_S;
+    }
+    return ret;
+}
+
+struct dirent* readdir(DIR* pdir)
+{
+    const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+       __errno_r(r) = EBADF;
+        return NULL;
+    }
+    struct dirent* ret;
+    CHECK_AND_CALLP(ret, r, vfs, readdir, pdir);
+    return ret;
+}
+
+int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
+{
+    const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+    int ret;
+    CHECK_AND_CALL(ret, r, vfs, readdir_r, pdir, entry, out_dirent);
+    return ret;
+}
+
+long telldir(DIR* pdir)
+{
+    const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+    long ret;
+    CHECK_AND_CALL(ret, r, vfs, telldir, pdir);
+    return ret;
+}
+
+void seekdir(DIR* pdir, long loc)
+{
+    const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        errno = EBADF;
+        return;
+    }
+    CHECK_AND_CALLV(r, vfs, seekdir, pdir, loc);
+}
+
+void rewinddir(DIR* pdir)
+{
+    seekdir(pdir, 0);
+}
+
+int closedir(DIR* pdir)
+{
+    const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+    int ret;
+    CHECK_AND_CALL(ret, r, vfs, closedir, pdir);
+    return ret;
+}
+
+int mkdir(const char* name, mode_t mode)
+{
+    const vfs_entry_t* vfs = get_vfs_for_path(name);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        __errno_r(r) = ENOENT;
+        return -1;
+    }
+    const char* path_within_vfs = translate_path(vfs, name);
+    int ret;
+    CHECK_AND_CALL(ret, r, vfs, mkdir, path_within_vfs, mode);
+    return ret;
+}
+
+int rmdir(const char* name)
+{
+    const vfs_entry_t* vfs = get_vfs_for_path(name);
+    struct _reent* r = __getreent();
+    if (vfs == NULL) {
+        __errno_r(r) = ENOENT;
+        return -1;
+    }
+    const char* path_within_vfs = translate_path(vfs, name);
+    int ret;
+    CHECK_AND_CALL(ret, r, vfs, rmdir, path_within_vfs);
+    return ret;
+}