diff options
| author | Bernard Xiong <[email protected]> | 2023-04-04 15:02:56 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-04-04 15:02:56 +0800 |
| commit | 23955edf53422c20127ef0138b889016a1ba2341 (patch) | |
| tree | c9035207dc66d1df690308c7cac9058fc6fc09b5 /components/dfs/src | |
| parent | accab17fa5eafc800c4ba464a0f6fcc1d1e008eb (diff) | |
[DFS] add Kconfig for dfs-v2.0 (#7156)
* [DFS] add Kconfig for dfs-v2.0
* [DFS] Optimize the SConscript.
* [dfs] move old dfs to dfs/dfs_v1
Diffstat (limited to 'components/dfs/src')
| -rw-r--r-- | components/dfs/src/dfs.c | 971 | ||||
| -rw-r--r-- | components/dfs/src/dfs_file.c | 1095 | ||||
| -rw-r--r-- | components/dfs/src/dfs_fs.c | 657 | ||||
| -rw-r--r-- | components/dfs/src/dfs_posix.c | 982 |
4 files changed, 0 insertions, 3705 deletions
diff --git a/components/dfs/src/dfs.c b/components/dfs/src/dfs.c deleted file mode 100644 index e2928f5e1b..0000000000 --- a/components/dfs/src/dfs.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - * 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open(). - * 2018-03-20 Heyuanjie dynamic allocation FD - */ - -#include <dfs.h> -#include <dfs_fs.h> -#include <dfs_file.h> -#include "dfs_private.h" -#ifdef RT_USING_SMART -#include <lwp.h> -#endif - -#ifdef RT_USING_POSIX_STDIO -#include <libc.h> -#endif /* RT_USING_POSIX_STDIO */ - -/* Global variables */ -const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; -struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX]; - -/* device filesystem lock */ -static struct rt_mutex fslock; -static struct rt_mutex fdlock; - -#ifdef DFS_USING_WORKDIR -char working_directory[DFS_PATH_MAX] = {"/"}; -#endif - -static struct dfs_fdtable _fdtab; -static int fd_alloc(struct dfs_fdtable *fdt, int startfd); - -/** - * @addtogroup DFS - */ - -/*@{*/ - -/** - * this function will initialize device file system. - */ -int dfs_init(void) -{ - static rt_bool_t init_ok = RT_FALSE; - - if (init_ok) - { - rt_kprintf("dfs already init.\n"); - return 0; - } - - /* init vnode hash table */ - dfs_fnode_mgr_init(); - - /* clear filesystem operations table */ - rt_memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table)); - /* clear filesystem table */ - rt_memset(filesystem_table, 0, sizeof(filesystem_table)); - /* clean fd table */ - rt_memset(&_fdtab, 0, sizeof(_fdtab)); - - /* create device filesystem lock */ - rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_PRIO); - rt_mutex_init(&fdlock, "fdlock", RT_IPC_FLAG_PRIO); - -#ifdef DFS_USING_WORKDIR - /* set current working directory */ - rt_memset(working_directory, 0, sizeof(working_directory)); - working_directory[0] = '/'; -#endif - -#ifdef RT_USING_DFS_TMPFS - { - extern int dfs_tmpfs_init(void); - dfs_tmpfs_init(); - } -#endif - -#ifdef RT_USING_DFS_DEVFS - { - extern int devfs_init(void); - - /* if enable devfs, initialize and mount it as soon as possible */ - devfs_init(); - - dfs_mount(NULL, "/dev", "devfs", 0, 0); - } -#if defined(RT_USING_DEV_BUS) && defined(RT_USING_DFS_TMPFS) - mkdir("/dev/shm", 0x777); - if (dfs_mount(RT_NULL, "/dev/shm", "tmp", 0, 0) != 0) - { - rt_kprintf("Dir /dev/shm mount failed!\n"); - } -#endif -#endif - - init_ok = RT_TRUE; - - return 0; -} -INIT_PREV_EXPORT(dfs_init); - -/** - * this function will lock device file system. - * - * @note please don't invoke it on ISR. - */ -void dfs_lock(void) -{ - rt_err_t result = -RT_EBUSY; - - while (result == -RT_EBUSY) - { - result = rt_mutex_take(&fslock, RT_WAITING_FOREVER); - } - - if (result != RT_EOK) - { - RT_ASSERT(0); - } -} - -void dfs_fd_lock(void) -{ - rt_err_t result = -RT_EBUSY; - - while (result == -RT_EBUSY) - { - result = rt_mutex_take(&fdlock, RT_WAITING_FOREVER); - } - - if (result != RT_EOK) - { - RT_ASSERT(0); - } -} - -/** - * this function will lock device file system. - * - * @note please don't invoke it on ISR. - */ -void dfs_unlock(void) -{ - rt_mutex_release(&fslock); -} - -#ifdef DFS_USING_POSIX - -void dfs_fd_unlock(void) -{ - rt_mutex_release(&fdlock); -} - -static int fd_slot_expand(struct dfs_fdtable *fdt, int fd) -{ - int nr; - int index; - struct dfs_fd **fds = NULL; - - if (fd < fdt->maxfd) - { - return fd; - } - if (fd >= DFS_FD_MAX) - { - return -1; - } - - nr = ((fd + 4) & ~3); - if (nr > DFS_FD_MAX) - { - nr = DFS_FD_MAX; - } - fds = (struct dfs_fd **)rt_realloc(fdt->fds, nr * sizeof(struct dfs_fd *)); - if (!fds) - { - return -1; - } - - /* clean the new allocated fds */ - for (index = fdt->maxfd; index < nr; index++) - { - fds[index] = NULL; - } - fdt->fds = fds; - fdt->maxfd = nr; - - return fd; -} - -static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd) -{ - int idx; - - /* find an empty fd slot */ - for (idx = startfd; idx < (int)fdt->maxfd; idx++) - { - if (fdt->fds[idx] == RT_NULL) - { - return idx; - } - } - - idx = fdt->maxfd; - if (idx < startfd) - { - idx = startfd; - } - if (fd_slot_expand(fdt, idx) < 0) - { - return -1; - } - return idx; -} -static int fd_alloc(struct dfs_fdtable *fdt, int startfd) -{ - int idx; - struct dfs_fd *fd = NULL; - - idx = fd_slot_alloc(fdt, startfd); - - /* allocate 'struct dfs_fd' */ - if (idx < 0) - { - return -1; - } - fd = (struct dfs_fd *)rt_calloc(1, sizeof(struct dfs_fd)); - if (!fd) - { - return -1; - } - fd->ref_count = 1; - fd->magic = DFS_FD_MAGIC; - fd->vnode = NULL; - fdt->fds[idx] = fd; - - return idx; -} - -/** - * @ingroup Fd - * This function will allocate a file descriptor. - * - * @return -1 on failed or the allocated file descriptor. - */ -int fdt_fd_new(struct dfs_fdtable *fdt) -{ - int idx; - - /* lock filesystem */ - dfs_fd_lock(); - - /* find an empty fd entry */ - idx = fd_alloc(fdt, DFS_STDIO_OFFSET); - - /* can't find an empty fd entry */ - if (idx < 0) - { - LOG_E("DFS fd new is failed! Could not found an empty fd entry."); - } - - dfs_fd_unlock(); - return idx; -} - -int fd_new(void) -{ - struct dfs_fdtable *fdt = NULL; - - fdt = dfs_fdtable_get(); - return fdt_fd_new(fdt); -} - -/** - * @ingroup Fd - * - * This function will return a file descriptor structure according to file - * descriptor. - * - * @return NULL on on this file descriptor or the file descriptor structure - * pointer. - */ - -struct dfs_fd *fdt_fd_get(struct dfs_fdtable* fdt, int fd) -{ - struct dfs_fd *d; - - if (fd < 0 || fd >= (int)fdt->maxfd) - { - return NULL; - } - - dfs_fd_lock(); - d = fdt->fds[fd]; - - /* check dfs_fd valid or not */ - if ((d == NULL) || (d->magic != DFS_FD_MAGIC)) - { - dfs_fd_unlock(); - return NULL; - } - - dfs_fd_unlock(); - - return d; -} - -struct dfs_fd *fd_get(int fd) -{ - struct dfs_fdtable *fdt; - - fdt = dfs_fdtable_get(); - return fdt_fd_get(fdt, fd); -} - -/** - * @ingroup Fd - * - * This function will put the file descriptor. - */ -void fdt_fd_release(struct dfs_fdtable* fdt, int fd) -{ - struct dfs_fd *fd_slot = NULL; - - RT_ASSERT(fdt != NULL); - - dfs_fd_lock(); - - if ((fd < 0) || (fd >= fdt->maxfd)) - { - dfs_fd_unlock(); - return; - } - - fd_slot = fdt->fds[fd]; - if (fd_slot == NULL) - { - dfs_fd_unlock(); - return; - } - fdt->fds[fd] = NULL; - - /* check fd */ - RT_ASSERT(fd_slot->magic == DFS_FD_MAGIC); - - fd_slot->ref_count--; - - /* clear this fd entry */ - if (fd_slot->ref_count == 0) - { - struct dfs_fnode *vnode = fd_slot->vnode; - if (vnode) - { - vnode->ref_count--; - } - rt_free(fd_slot); - } - dfs_fd_unlock(); -} - -void fd_release(int fd) -{ - struct dfs_fdtable *fdt; - - fdt = dfs_fdtable_get(); - fdt_fd_release(fdt, fd); -} - -rt_err_t sys_dup(int oldfd) -{ - int newfd = -1; - struct dfs_fdtable *fdt = NULL; - - dfs_fd_lock(); - /* check old fd */ - fdt = dfs_fdtable_get(); - if ((oldfd < 0) || (oldfd >= fdt->maxfd)) - { - goto exit; - } - if (!fdt->fds[oldfd]) - { - goto exit; - } - /* get a new fd */ - newfd = fd_slot_alloc(fdt, DFS_STDIO_OFFSET); - if (newfd >= 0) - { - fdt->fds[newfd] = fdt->fds[oldfd]; - /* inc ref_count */ - fdt->fds[newfd]->ref_count++; - } -exit: - dfs_fd_unlock(); - return newfd; -} - -#endif /* DFS_USING_POSIX */ - -/** - * @ingroup Fd - * - * This function will return whether this file has been opend. - * - * @param pathname the file path name. - * - * @return 0 on file has been open successfully, -1 on open failed. - */ -int fd_is_open(const char *pathname) -{ - char *fullpath; - unsigned int index; - struct dfs_filesystem *fs; - struct dfs_fd *fd; - struct dfs_fdtable *fdt; - - fdt = dfs_fdtable_get(); - fullpath = dfs_normalize_path(NULL, pathname); - if (fullpath != NULL) - { - char *mountpath; - fs = dfs_filesystem_lookup(fullpath); - if (fs == NULL) - { - /* can't find mounted file system */ - rt_free(fullpath); - - return -1; - } - - /* get file path name under mounted file system */ - if (fs->path[0] == '/' && fs->path[1] == '\0') - mountpath = fullpath; - else - mountpath = fullpath + strlen(fs->path); - - dfs_lock(); - - for (index = 0; index < fdt->maxfd; index++) - { - fd = fdt->fds[index]; - if (fd == NULL || fd->vnode->fops == NULL || fd->vnode->path == NULL) continue; - - if (fd->vnode->fs == fs && strcmp(fd->vnode->path, mountpath) == 0) - { - /* found file in file descriptor table */ - rt_free(fullpath); - dfs_unlock(); - - return 0; - } - } - dfs_unlock(); - - rt_free(fullpath); - } - - return -1; -} - -rt_err_t sys_dup2(int oldfd, int newfd) -{ - struct dfs_fdtable *fdt = NULL; - int ret = 0; - int retfd = -1; - - dfs_fd_lock(); - /* check old fd */ - fdt = dfs_fdtable_get(); - if ((oldfd < 0) || (oldfd >= fdt->maxfd)) - { - goto exit; - } - if (!fdt->fds[oldfd]) - { - goto exit; - } - if (newfd < 0) - { - goto exit; - } - if (newfd >= fdt->maxfd) - { - newfd = fd_slot_expand(fdt, newfd); - if (newfd < 0) - { - goto exit; - } - } - if (fdt->fds[newfd] == fdt->fds[oldfd]) - { - /* ok, return newfd */ - retfd = newfd; - goto exit; - } - - if (fdt->fds[newfd]) - { - ret = dfs_file_close(fdt->fds[newfd]); - if (ret < 0) - { - goto exit; - } - fd_release(newfd); - } - - fdt->fds[newfd] = fdt->fds[oldfd]; - /* inc ref_count */ - fdt->fds[newfd]->ref_count++; - retfd = newfd; -exit: - dfs_fd_unlock(); - return retfd; -} - -static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_fd *file) -{ - int fd = -1; - - if (file == RT_NULL) - { - return -1; - } - - dfs_fd_lock(); - - for(int index = 0; index < (int)fdt->maxfd; index++) - { - if(fdt->fds[index] == file) - { - fd = index; - break; - } - } - - dfs_fd_unlock(); - - return fd; -} - -int fd_get_fd_index(struct dfs_fd *file) -{ - struct dfs_fdtable *fdt; - - fdt = dfs_fdtable_get(); - return fd_get_fd_index_form_fdt(fdt, file); -} - -int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_fd *file) -{ - int retfd = -1; - - if (!file) - { - return retfd; - } - if (!fdt) - { - return retfd; - } - - dfs_fd_lock(); - /* check old fd */ - if ((fd < 0) || (fd >= fdt->maxfd)) - { - goto exit; - } - - if (fdt->fds[fd]) - { - goto exit; - } - /* inc ref_count */ - file->ref_count++; - fdt->fds[fd] = file; - retfd = fd; -exit: - dfs_fd_unlock(); - return retfd; -} - -void fd_init(struct dfs_fd *fd) -{ - if (fd) - { - fd->magic = DFS_FD_MAGIC; - fd->ref_count = 1; - fd->pos = 0; - fd->vnode = NULL; - fd->data = NULL; - } -} - -/** - * this function will return a sub-path name under directory. - * - * @param directory the parent directory. - * @param filename the filename. - * - * @return the subdir pointer in filename - */ -const char *dfs_subdir(const char *directory, const char *filename) -{ - const char *dir; - - if (strlen(directory) == strlen(filename)) /* it's a same path */ - return NULL; - - dir = filename + strlen(directory); - if ((*dir != '/') && (dir != filename)) - { - dir --; - } - - return dir; -} -RTM_EXPORT(dfs_subdir); - -/** - * this function will normalize a path according to specified parent directory - * and file name. - * - * @param directory the parent path - * @param filename the file name - * - * @return the built full file path (absolute path) - */ -char *dfs_normalize_path(const char *directory, const char *filename) -{ - char *fullpath; - char *dst0, *dst, *src; - - /* check parameters */ - RT_ASSERT(filename != NULL); - -#ifdef DFS_USING_WORKDIR - if (directory == NULL) /* shall use working directory */ - { -#ifdef RT_USING_SMART - directory = lwp_getcwd(); -#else - directory = &working_directory[0]; -#endif - } -#else - if ((directory == NULL) && (filename[0] != '/')) - { - rt_kprintf(NO_WORKING_DIR); - - return NULL; - } -#endif - - if (filename[0] != '/') /* it's a absolute path, use it directly */ - { - fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2); - - if (fullpath == NULL) - return NULL; - - /* join path and file name */ - rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2, - "%s/%s", directory, filename); - } - else - { - fullpath = rt_strdup(filename); /* copy string */ - - if (fullpath == NULL) - return NULL; - } - - src = fullpath; - dst = fullpath; - - dst0 = dst; - while (1) - { - char c = *src; - - if (c == '.') - { - if (!src[1]) src++; /* '.' and ends */ - else if (src[1] == '/') - { - /* './' case */ - src += 2; - - while ((*src == '/') && (*src != '\0')) - src++; - continue; - } - else if (src[1] == '.') - { - if (!src[2]) - { - /* '..' and ends case */ - src += 2; - goto up_one; - } - else if (src[2] == '/') - { - /* '../' case */ - src += 3; - - while ((*src == '/') && (*src != '\0')) - src++; - goto up_one; - } - } - } - - /* copy up the next '/' and erase all '/' */ - while ((c = *src++) != '\0' && c != '/') - *dst++ = c; - - if (c == '/') - { - *dst++ = '/'; - while (c == '/') - c = *src++; - - src--; - } - else if (!c) - break; - - continue; - -up_one: - /* keep the topmost root directory */ - if (dst - dst0 != 1 || dst[-1] != '/') - { - dst--; - - if (dst < dst0) - { - rt_free(fullpath); - return NULL; - } - } - while (dst0 < dst && dst[-1] != '/') - dst--; - } - - *dst = '\0'; - - /* remove '/' in the end of path if exist */ - dst--; - if ((dst != fullpath) && (*dst == '/')) - *dst = '\0'; - - /* final check fullpath is not empty, for the special path of lwext "/.." */ - if ('\0' == fullpath[0]) - { - fullpath[0] = '/'; - fullpath[1] = '\0'; - } - - return fullpath; -} -RTM_EXPORT(dfs_normalize_path); - -/** - * This function will get the file descriptor table of current process. - */ -struct dfs_fdtable *dfs_fdtable_get(void) -{ - struct dfs_fdtable *fdt; -#ifdef RT_USING_SMART - struct rt_lwp *lwp; - - lwp = (struct rt_lwp *)rt_thread_self()->lwp; - if (lwp) - fdt = &lwp->fdt; - else - fdt = &_fdtab; -#else - fdt = &_fdtab; -#endif - - return fdt; -} - -#ifdef RT_USING_SMART -struct dfs_fdtable *dfs_fdtable_get_pid(int pid) -{ - struct rt_lwp *lwp = RT_NULL; - struct dfs_fdtable *fdt = RT_NULL; - - lwp = lwp_from_pid(pid); - if (lwp) - { - fdt = &lwp->fdt; - } - - return fdt; -} -#endif - -struct dfs_fdtable *dfs_fdtable_get_global(void) -{ - return &_fdtab; -} - -#ifdef RT_USING_FINSH -int list_fd(void) -{ - int index; - struct dfs_fdtable *fd_table; - - fd_table = dfs_fdtable_get(); - if (!fd_table) return -1; - - dfs_lock(); - - rt_kprintf("fd type ref magic path\n"); - rt_kprintf("-- ------ --- ----- ------\n"); - for (index = 0; index < (int)fd_table->maxfd; index++) - { - struct dfs_fd *fd = fd_table->fds[index]; - - if (fd && fd->vnode->fops) - { - rt_kprintf("%2d ", index); - if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir"); - else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file"); - else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket"); - else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user"); - else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device"); - else rt_kprintf("%-8.8s ", "unknown"); - rt_kprintf("%3d ", fd->vnode->ref_count); - rt_kprintf("%04x ", fd->magic); - if (fd->vnode->path) - { - rt_kprintf("%s\n", fd->vnode->path); - } - else - { - rt_kprintf("\n"); - } - } - } - dfs_unlock(); - - return 0; -} - -#ifdef RT_USING_SMART -static int lsofp(int pid) -{ - int index; - struct dfs_fdtable *fd_table = RT_NULL; - - if (pid == (-1)) - { - fd_table = dfs_fdtable_get(); - if (!fd_table) return -1; - } - else - { - fd_table = dfs_fdtable_get_pid(pid); - if (!fd_table) - { - rt_kprintf("PID %s is not a applet(lwp)\n", pid); - return -1; - } - } - - rt_kprintf("--- -- ------ ------ ----- ---------- ---------- ---------- ------\n"); - - rt_enter_critical(); - for (index = 0; index < (int)fd_table->maxfd; index++) - { - struct dfs_fd *fd = fd_table->fds[index]; - - if (fd && fd->vnode->fops) - { - if(pid == (-1)) - { - rt_kprintf(" K "); - } - else - { - rt_kprintf("%3d ", pid); - } - - rt_kprintf("%2d ", index); - if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir"); - else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file"); - else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket"); - else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user"); - else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device"); - else rt_kprintf("%-8.8s ", "unknown"); - rt_kprintf("%6d ", fd->vnode->ref_count); - rt_kprintf("%04x 0x%.8x ", fd->magic, (int)(size_t)fd->vnode); - - if(fd->vnode == RT_NULL) - { - rt_kprintf("0x%.8x 0x%.8x ", (int)0x00000000, (int)(size_t)fd); - } - else - { - rt_kprintf("0x%.8x 0x%.8x ", (int)(size_t)(fd->vnode->data), (int)(size_t)fd); - } - - if (fd->vnode->path) - { - rt_kprintf("%s \n", fd->vnode->path); - } - else - { - rt_kprintf("\n"); - } - } - } - rt_exit_critical(); - - return 0; -} - -int lsof(int argc, char *argv[]) -{ - rt_kprintf("PID fd type fd-ref magic vnode vnode/data addr path \n"); - - if (argc == 1) - { - struct rt_list_node *node, *list; - struct lwp_avl_struct *pids = lwp_get_pid_ary(); - - lsofp(-1); - - for (int index = 0; index < RT_LWP_MAX_NR; index++) - { - struct rt_lwp *lwp = (struct rt_lwp *)pids[index].data; - - if (lwp) - { - list = &lwp->t_grp; - for (node = list->next; node != list; node = node->next) - { - lsofp(lwp_to_pid(lwp)); - } - } - } - } - else if (argc == 3) - { - if (argv[1][0] == '-' && argv[1][1] == 'p') - { - int pid = atoi(argv[2]); - lsofp(pid); - } - } - - return 0; -} -MSH_CMD_EXPORT(lsof, list open files); -#endif /* RT_USING_SMART */ - -#endif -/*@}*/ - diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c deleted file mode 100644 index 56a28f5331..0000000000 --- a/components/dfs/src/dfs_file.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - * 2011-12-08 Bernard Merges rename patch from iamcacy. - * 2015-05-27 Bernard Fix the fd clear issue. - * 2019-01-24 Bernard Remove file repeatedly open check. - */ - -#include <dfs.h> -#include <dfs_file.h> -#include <dfs_private.h> -#include <unistd.h> - -#define DFS_FNODE_HASH_NR 128 - -struct dfs_fnode_mgr -{ - struct rt_mutex lock; - rt_list_t head[DFS_FNODE_HASH_NR]; -}; - -static struct dfs_fnode_mgr dfs_fm; - -void dfs_fm_lock(void) -{ - rt_mutex_take(&dfs_fm.lock, RT_WAITING_FOREVER); -} - -void dfs_fm_unlock(void) -{ - rt_mutex_release(&dfs_fm.lock); -} - -void dfs_fnode_mgr_init(void) -{ - int i = 0; - - rt_mutex_init(&dfs_fm.lock, "dfs_mgr", RT_IPC_FLAG_PRIO); - for (i = 0; i < DFS_FNODE_HASH_NR; i++) - { - rt_list_init(&dfs_fm.head[i]); - } -} - -/* BKDR Hash Function */ -static unsigned int bkdr_hash(const char *str) -{ - unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. - unsigned int hash = 0; - - while (*str) - { - hash = hash * seed + (*str++); - } - - return (hash % DFS_FNODE_HASH_NR); -} - -static struct dfs_fnode *dfs_fnode_find(const char *path, rt_list_t **hash_head) -{ - struct dfs_fnode *vnode = NULL; - int hash = bkdr_hash(path); - rt_list_t *hh; - - hh = dfs_fm.head[hash].next; - - if (hash_head) - { - *hash_head = &dfs_fm.head[hash]; - } - - while (hh != &dfs_fm.head[hash]) - { - vnode = rt_container_of(hh, struct dfs_fnode, list); - if (rt_strcmp(path, vnode->fullpath) == 0) - { - /* found */ - return vnode; - } - hh = hh->next; - } - return NULL; -} - -/** - * @addtogroup FileApi - */ - -/*@{*/ - -/** - * This function will return whether this file has been opend. - * - * @param pathname the file path name. - * - * @return 0 on file has been open successfully, -1 on open failed. - */ -int dfs_file_is_open(const char *pathname) -{ - char *fullpath = NULL; - struct dfs_fnode *vnode = NULL; - int ret = 0; - - fullpath = dfs_normalize_path(NULL, pathname); - - dfs_fm_lock(); - vnode = dfs_fnode_find(fullpath, NULL); - if (vnode) - { - ret = 1; - } - dfs_fm_unlock(); - - rt_free(fullpath); - return ret; -} - - -/** - * this function will open a file which specified by path with specified flags. - * - * @param fd the file descriptor pointer to return the corresponding result. - * @param path the specified file path. - * @param flags the flags for open operator. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_open(struct dfs_fd *fd, const char *path, int flags) -{ - struct dfs_filesystem *fs; - char *fullpath; - int result; - struct dfs_fnode *vnode = NULL; - rt_list_t *hash_head; - - /* parameter check */ - if (fd == NULL) - return -EINVAL; - - /* make sure we have an absolute path */ - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == NULL) - { - return -ENOMEM; - } - - LOG_D("open file:%s", fullpath); - - dfs_fm_lock(); - /* vnode find */ - vnode = dfs_fnode_find(fullpath, &hash_head); - if (vnode) - { - vnode->ref_count++; - fd->pos = 0; - fd->vnode = vnode; - dfs_fm_unlock(); - rt_free(fullpath); /* release path */ - } - else - { - /* find filesystem */ - fs = dfs_filesystem_lookup(fullpath); - if (fs == NULL) - { - dfs_fm_unlock(); - rt_free(fullpath); /* release path */ - return -ENOENT; - } - - vnode = rt_calloc(1, sizeof(struct dfs_fnode)); - if (!vnode) - { - dfs_fm_unlock(); - rt_free(fullpath); /* release path */ - return -ENOMEM; - } - vnode->ref_count = 1; - - LOG_D("open in filesystem:%s", fs->ops->name); - vnode->fs = fs; /* set file system */ - vnode->fops = fs->ops->fops; /* set file ops */ - - /* initialize the fd item */ - vnode->type = FT_REGULAR; - vnode->flags = 0; - - if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH)) - { - if (dfs_subdir(fs->path, fullpath) == NULL) - vnode->path = rt_strdup("/"); - else - vnode->path = rt_strdup(dfs_subdir(fs->path, fullpath)); - LOG_D("Actual file path: %s", vnode->path); - } - else - { - vnode->path = fullpath; - } - vnode->fullpath = fullpath; - - /* specific file system open routine */ - if (vnode->fops->open == NULL) - { - dfs_fm_unlock(); - /* clear fd */ - if (vnode->path != vnode->fullpath) - { - rt_free(vnode->fullpath); - } - rt_free(vnode->path); - rt_free(vnode); - - return -ENOSYS; - } - - fd->pos = 0; - fd->vnode = vnode; - - /* insert vnode to hash */ - rt_list_insert_after(hash_head, &vnode->list); - } - - fd->flags = flags; - - if ((result = vnode->fops->open(fd)) < 0) - { - vnode->ref_count--; - if (vnode->ref_count == 0) - { - /* remove from hash */ - rt_list_remove(&vnode->list); - /* clear fd */ - if (vnode->path != vnode->fullpath) - { - rt_free(vnode->fullpath); - } - rt_free(vnode->path); - fd->vnode = NULL; - rt_free(vnode); - } - - dfs_fm_unlock(); - LOG_D("%s open failed", fullpath); - - return result; - } - - fd->flags |= DFS_F_OPEN; - if (flags & O_DIRECTORY) - { - fd->vnode->type = FT_DIRECTORY; - fd->flags |= DFS_F_DIRECTORY; - } - dfs_fm_unlock(); - - LOG_D("open successful"); - return 0; -} - -/** - * this function will close a file descriptor. - * - * @param fd the file descriptor to be closed. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_close(struct dfs_fd *fd) -{ - struct dfs_fnode *vnode = NULL; - int result = 0; - - if (fd == NULL) - { - return -ENXIO; - } - - if (fd->ref_count == 1) - { - dfs_fm_lock(); - vnode = fd->vnode; - - if (vnode->ref_count <= 0) - { - dfs_fm_unlock(); - return -ENXIO; - } - - if (vnode->fops->close != NULL) - { - result = vnode->fops->close(fd); - } - - /* close fd error, return */ - if (result < 0) - { - dfs_fm_unlock(); - return result; - } - - if (vnode->ref_count == 1) - { - /* remove from hash */ - rt_list_remove(&vnode->list); - fd->vnode = NULL; - - if (vnode->path != vnode->fullpath) - { - rt_free(vnode->fullpath); - } - rt_free(vnode->path); - rt_free(vnode); - } - dfs_fm_unlock(); - } - - return result; -} - -/** - * this function will perform a io control on a file descriptor. - * - * @param fd the file descriptor. - * @param cmd the command to send to file descriptor. - * @param args the argument to send to file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_ioctl(struct dfs_fd *fd, int cmd, void *args) -{ - if (fd == NULL) - { - return -EINVAL; - } - - /* regular file system fd */ - if (fd->vnode->type == FT_REGULAR || fd->vnode->type == FT_DEVICE) - { - switch (cmd) - { - case F_GETFL: - return fd->flags; /* return flags */ - case F_SETFL: - { - int flags = (int)(rt_base_t)args; - int mask = O_NONBLOCK | O_APPEND; - - flags &= mask; - fd->flags &= ~mask; - fd->flags |= flags; - } - return 0; - } - } - - if (fd->vnode->fops->ioctl != NULL) - { - return fd->vnode->fops->ioctl(fd, cmd, args); - } - - return -ENOSYS; -} - -/** - * this function will read specified length data from a file descriptor to a - * buffer. - * - * @param fd the file descriptor. - * @param buf the buffer to save the read data. - * @param len the length of data buffer to be read. - * - * @return the actual read data bytes or 0 on end of file or failed. - */ -int dfs_file_read(struct dfs_fd *fd, void *buf, size_t len) -{ - int result = 0; - - if (fd == NULL) - { - return -EINVAL; - } - - if (fd->vnode->fops->read == NULL) - { - return -ENOSYS; - } - - if ((result = fd->vnode->fops->read(fd, buf, len)) < 0) - { - fd->flags |= DFS_F_EOF; - } - - return result; -} - -/** - * this function will fetch directory entries from a directory descriptor. - * - * @param fd the directory descriptor. - * @param dirp the dirent buffer to save result. - * @param nbytes the available room in the buffer. - * - * @return the read dirent, others on failed. - */ -int dfs_file_getdents(struct dfs_fd *fd, struct dirent *dirp, size_t nbytes) -{ - /* parameter check */ - if (fd == NULL) - { - return -EINVAL; - } - - if (fd->vnode->type != FT_DIRECTORY) - { - return -EINVAL; - } - - if (fd->vnode->fops->getdents != NULL) - { - return fd->vnode->fops->getdents(fd, dirp, nbytes); - } - - return -ENOSYS; -} - -/** - * this function will unlink (remove) a specified path file from file system. - * - * @param path the specified path file to be unlinked. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_unlink(const char *path) -{ - int result; - char *fullpath; - struct dfs_filesystem *fs; - - /* Make sure we have an absolute path */ - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == NULL) - { - return -EINVAL; - } - - /* Check whether file is already open */ - if (dfs_file_is_open(fullpath)) - { - result = -EBUSY; - goto __exit; - } - - /* get filesystem */ - if ((fs = dfs_filesystem_lookup(fullpath)) == NULL) - { - result = -ENOENT; - goto __exit; - } - - if (fs->ops->unlink != NULL) - { - if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH)) - { - if (dfs_subdir(fs->path, fullpath) == NULL) - result = fs->ops->unlink(fs, "/"); - else - result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath)); - } - else - result = fs->ops->unlink(fs, fullpath); - } - else result = -ENOSYS; - -__exit: - rt_free(fullpath); - return result; -} - -/** - * this function will write some specified length data to file system. - * - * @param fd the file descriptor. - * @param buf the data buffer to be written. - * @param len the data buffer length - * - * @return the actual written data length. - */ -int dfs_file_write(struct dfs_fd *fd, const void *buf, size_t len) -{ - if (fd == NULL) - { - return -EINVAL; - } - - if (fd->vnode->fops->write == NULL) - { - return -ENOSYS; - } - - return fd->vnode->fops->write(fd, buf, len); -} - -/** - * this function will flush buffer on a file descriptor. - * - * @param fd the file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_flush(struct dfs_fd *fd) -{ - if (fd == NULL) - return -EINVAL; - - if (fd->vnode->fops->flush == NULL) - return -ENOSYS; - - return fd->vnode->fops->flush(fd); -} - -/** - * this function will seek the offset for specified file descriptor. - * - * @param fd the file descriptor. - * @param offset the offset to be sought. - * - * @return the current position after seek. - */ -int dfs_file_lseek(struct dfs_fd *fd, off_t offset) -{ - int result; - - if (fd == NULL) - return -EINVAL; - - if (fd->vnode->fops->lseek == NULL) - return -ENOSYS; - - result = fd->vnode->fops->lseek(fd, offset); - - /* update current position */ - if (result >= 0) - fd->pos = result; - - return result; -} - -/** - * this function will get file information. - * - * @param path the file path. - * @param buf the data buffer to save stat description. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_stat(const char *path, struct stat *buf) -{ - int result; - char *fullpath; - struct dfs_filesystem *fs; - - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == NULL) - { - return -1; - } - - if ((fs = dfs_filesystem_lookup(fullpath)) == NULL) - { - LOG_E("can't find mounted filesystem on this path:%s", fullpath); - rt_free(fullpath); - - return -ENOENT; - } - - if ((fullpath[0] == '/' && fullpath[1] == '\0') || - (dfs_subdir(fs->path, fullpath) == NULL)) - { - /* it's the root directory */ - buf->st_dev = 0; - - buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; - - buf->st_size = 0; - buf->st_mtime = 0; - - /* release full path */ - rt_free(fullpath); - - return RT_EOK; - } - else - { - if (fs->ops->stat == NULL) - { - rt_free(fullpath); - LOG_E("the filesystem didn't implement this function"); - - return -ENOSYS; - } - - /* get the real file path and get file stat */ - if (fs->ops->flags & DFS_FS_FLAG_FULLPATH) - result = fs->ops->stat(fs, fullpath, buf); - else - result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf); - } - - rt_free(fullpath); - - return result; -} - -/** - * this function will rename an old path name to a new path name. - * - * @param oldpath the old path name. - * @param newpath the new path name. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_rename(const char *oldpath, const char *newpath) -{ - int result = RT_EOK; - struct dfs_filesystem *oldfs = NULL, *newfs = NULL; - char *oldfullpath = NULL, *newfullpath = NULL; - - newfullpath = NULL; - oldfullpath = NULL; - - oldfullpath = dfs_normalize_path(NULL, oldpath); - if (oldfullpath == NULL) - { - result = -ENOENT; - goto __exit; - } - - if (dfs_file_is_open((const char *)oldfullpath)) - { - result = -EBUSY; - goto __exit; - } - - newfullpath = dfs_normalize_path(NULL, newpath); - if (newfullpath == NULL) - { - result = -ENOENT; - goto __exit; - } - - oldfs = dfs_filesystem_lookup(oldfullpath); - newfs = dfs_filesystem_lookup(newfullpath); - - if (oldfs == newfs) - { - if (oldfs->ops->rename == NULL) - { - result = -ENOSYS; - } - else - { - if (oldfs->ops->flags & DFS_FS_FLAG_FULLPATH) - result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath); - else - /* use sub directory to rename in file system */ - result = oldfs->ops->rename(oldfs, - dfs_subdir(oldfs->path, oldfullpath), - dfs_subdir(newfs->path, newfullpath)); - } - } - else - { - result = -EXDEV; - } - -__exit: - if (oldfullpath) - { - rt_free(oldfullpath); - } - if (newfullpath) - { - rt_free(newfullpath); - } - - /* not at same file system, return EXDEV */ - return result; -} - -/** - * this function is will cause the regular file referenced by fd - * to be truncated to a size of precisely length bytes. - * - * @param fd the file descriptor. - * @param length the length to be truncated. - * - * @return the status of truncated. - */ -int dfs_file_ftruncate(struct dfs_fd *fd, off_t length) -{ - int result; - - /* fd is null or not a regular file system fd, or length is invalid */ - if (fd == NULL || fd->vnode->type != FT_REGULAR || length < 0) - return -EINVAL; - - if (fd->vnode->fops->ioctl == NULL) - return -ENOSYS; - - result = fd->vnode->fops->ioctl(fd, RT_FIOFTRUNCATE, (void*)&length); - - /* update current size */ - if (result == 0) - fd->vnode->size = length; - - return result; -} - -int dfs_file_mmap2(struct dfs_fd *fd, struct dfs_mmap2_args *mmap2) -{ - int ret = 0; - - if (fd && mmap2) - { - if (fd->vnode->type != FT_DEVICE || !fd->vnode->fops->ioctl) - { - rt_set_errno(EINVAL); - } - else if (fd->vnode->type == FT_DEVICE && fd->vnode->fops->ioctl) - { - ret = fd->vnode->fops->ioctl(fd, RT_FIOMMAP2, mmap2); - if (ret != 0) - { - ret = ret > 0? ret : -ret; - rt_set_errno(ret); - } - } - } - - return ret; -} - -#ifdef RT_USING_FINSH -#include <finsh.h> - -void ls(const char *pathname) -{ - struct dfs_fd fd; - struct dirent dirent; - struct stat stat; - int length; - char *fullpath, *path; - - fullpath = NULL; - if (pathname == NULL) - { -#ifdef DFS_USING_WORKDIR - /* open current working directory */ - path = rt_strdup(working_directory); -#else - path = rt_strdup("/"); -#endif - if (path == NULL) - return ; /* out of memory */ - } - else - { - path = (char *)pathname; - } - - fd_init(&fd); - /* list directory */ - if (dfs_file_open(&fd, path, O_DIRECTORY) == 0) - { - rt_kprintf("Directory %s:\n", path); - do - { - rt_memset(&dirent, 0, sizeof(struct dirent)); - length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent)); - if (length > 0) - { - rt_memset(&stat, 0, sizeof(struct stat)); - - /* build full path for each file */ - fullpath = dfs_normalize_path(path, dirent.d_name); - if (fullpath == NULL) - break; - - if (dfs_file_stat(fullpath, &stat) == 0) - { - rt_kprintf("%-20s", dirent.d_name); - if (S_ISDIR(stat.st_mode)) - { - rt_kprintf("%-25s\n", "<DIR>"); - } - else - { - rt_kprintf("%-25lu\n", (unsigned long)stat.st_size); - } - } - else - rt_kprintf("BAD file: %s\n", dirent.d_name); - rt_free(fullpath); - } - } - while (length > 0); - - dfs_file_close(&fd); - } - else - { - rt_kprintf("No such directory\n"); - } - if (pathname == NULL) - rt_free(path); -} -FINSH_FUNCTION_EXPORT(ls, list directory contents); - -void rm(const char *filename) -{ - if (dfs_file_unlink(filename) < 0) - { - rt_kprintf("Delete %s failed\n", filename); - } -} -FINSH_FUNCTION_EXPORT(rm, remove files or directories); - -void cat(const char *filename) -{ - struct dfs_fd fd; - int length = 0; - char buffer[81]; - - fd_init(&fd); - if (dfs_file_open(&fd, filename, O_RDONLY) < 0) - { - rt_kprintf("Open %s failed\n", filename); - - return; - } - - do - { - rt_memset(buffer, 0x0, sizeof(buffer)); - length = dfs_file_read(&fd, (void *)buffer, sizeof(buffer) - 1); - if (length > 0) - { - buffer[length] = '\0'; - rt_device_t out_device = rt_console_get_device(); - rt_device_write(out_device, 0, (void *)buffer, sizeof(buffer)); - } - } while (length > 0); - rt_kprintf("\n"); - - dfs_file_close(&fd); -} -FINSH_FUNCTION_EXPORT(cat, print file); - -#ifdef DFS_USING_POSIX -#define BUF_SZ 4096 -static void copyfile(const char *src, const char *dst) -{ - struct dfs_fd fd; - struct dfs_fd src_fd; - rt_uint8_t *block_ptr; - rt_int32_t read_bytes; - - block_ptr = (rt_uint8_t *)rt_malloc(BUF_SZ); - if (block_ptr == NULL) - { - rt_kprintf("out of memory\n"); - - return; - } - - fd_init(&src_fd); - if (dfs_file_open(&src_fd, src, O_RDONLY) < 0) - { - rt_free(block_ptr); - rt_kprintf("Read %s failed\n", src); - - return; - } - fd_init(&fd); - if (dfs_file_open(&fd, dst, O_WRONLY | O_CREAT) < 0) - { - rt_free(block_ptr); - dfs_file_close(&src_fd); - - rt_kprintf("Write %s failed\n", dst); - - return; - } - - do - { - read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ); - if (read_bytes > 0) - { - int length; - - length = dfs_file_write(&fd, block_ptr, read_bytes); - if (length != read_bytes) - { - /* write failed. */ - rt_kprintf("Write file data failed, errno=%d\n", length); - break; - } - } - } - while (read_bytes > 0); - - dfs_file_close(&src_fd); - dfs_file_close(&fd); - rt_free(block_ptr); -} - -extern int mkdir(const char *path, mode_t mode); -static void copydir(const char *src, const char *dst) -{ - struct dirent dirent; - struct stat stat; - int length; - struct dfs_fd cpfd; - if (dfs_file_open(&cpfd, src, O_DIRECTORY) < 0) - { - rt_kprintf("open %s failed\n", src); - return ; - } - - do - { - rt_memset(&dirent, 0, sizeof(struct dirent)); - - length = dfs_file_getdents(&cpfd, &dirent, sizeof(struct dirent)); - if (length > 0) - { - char *src_entry_full = NULL; - char *dst_entry_full = NULL; - - if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0) - continue; - - /* build full path for each file */ - if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == NULL) - { - rt_kprintf("out of memory!\n"); - break; - } - if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == NULL) - { - rt_kprintf("out of memory!\n"); - rt_free(src_entry_full); - break; - } - - rt_memset(&stat, 0, sizeof(struct stat)); - if (dfs_file_stat(src_entry_full, &stat) != 0) - { - rt_kprintf("open file: %s failed\n", dirent.d_name); - continue; - } - - if (S_ISDIR(stat.st_mode)) - { - mkdir(dst_entry_full, 0); - copydir(src_entry_full, dst_entry_full); - } - else - { - copyfile(src_entry_full, dst_entry_full); - } - rt_free(src_entry_full); - rt_free(dst_entry_full); - } - } - while (length > 0); - - dfs_file_close(&cpfd); -} - -static const char *_get_path_lastname(const char *path) -{ - char *ptr; - if ((ptr = (char *)strrchr(path, '/')) == NULL) - return path; - - /* skip the '/' then return */ - return ++ptr; -} - -void copy(const char *src, const char *dst) -{ -#define FLAG_SRC_TYPE 0x03 -#define FLAG_SRC_IS_DIR 0x01 -#define FLAG_SRC_IS_FILE 0x02 -#define FLAG_SRC_NON_EXSIT 0x00 - -#define FLAG_DST_TYPE 0x0C -#define FLAG_DST_IS_DIR 0x04 -#define FLAG_DST_IS_FILE 0x08 -#define FLAG_DST_NON_EXSIT 0x00 - - struct stat stat; - uint32_t flag = 0; - - /* check the staus of src and dst */ - if (dfs_file_stat(src, &stat) < 0) - { - rt_kprintf("copy failed, bad %s\n", src); - return; - } - if (S_ISDIR(stat.st_mode)) - flag |= FLAG_SRC_IS_DIR; - else - flag |= FLAG_SRC_IS_FILE; - - if (dfs_file_stat(dst, &stat) < 0) - { - flag |= FLAG_DST_NON_EXSIT; - } - else - { - if (S_ISDIR(stat.st_mode)) - flag |= FLAG_DST_IS_DIR; - else - flag |= FLAG_DST_IS_FILE; - } - - //2. check status - if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE)) - { - rt_kprintf("cp faild, cp dir to file is not permitted!\n"); - return ; - } - - //3. do copy - if (flag & FLAG_SRC_IS_FILE) - { - if (flag & FLAG_DST_IS_DIR) - { - char *fdst; - fdst = dfs_normalize_path(dst, _get_path_lastname(src)); - if (fdst == NULL) - { - rt_kprintf("out of memory\n"); - return; - } - copyfile(src, fdst); - rt_free(fdst); - } - else - { - copyfile(src, dst); - } - } - else //flag & FLAG_SRC_IS_DIR - { - if (flag & FLAG_DST_IS_DIR) - { - char *fdst; - fdst = dfs_normalize_path(dst, _get_path_lastname(src)); - if (fdst == NULL) - { - rt_kprintf("out of memory\n"); - return; - } - mkdir(fdst, 0); - copydir(src, fdst); - rt_free(fdst); - } - else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT) - { - mkdir(dst, 0); - copydir(src, dst); - } - else - { - copydir(src, dst); - } - } -} -FINSH_FUNCTION_EXPORT(copy, copy file or dir) -#endif /* DFS_USING_POSIX */ - -#endif /* RT_USING_FINSH */ -/* @} */ - diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c deleted file mode 100644 index 7724afc7bc..0000000000 --- a/components/dfs/src/dfs_fs.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - * 2010-06-30 Bernard Optimize for RT-Thread RTOS - * 2011-03-12 Bernard fix the filesystem lookup issue. - * 2017-11-30 Bernard fix the filesystem_operation_table issue. - * 2017-12-05 Bernard fix the fs type search issue in mkfs. - */ - -#include <dfs_fs.h> -#include <dfs_file.h> -#include "dfs_private.h" - -/** - * @addtogroup FsApi - */ -/*@{*/ - -/** - * this function will register a file system instance to device file system. - * - * @param ops the file system instance to be registered. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_register(const struct dfs_filesystem_ops *ops) -{ - int ret = RT_EOK; - const struct dfs_filesystem_ops **empty = NULL; - const struct dfs_filesystem_ops **iter; - - /* lock filesystem */ - dfs_lock(); - /* check if this filesystem was already registered */ - for (iter = &filesystem_operation_table[0]; - iter < &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; iter ++) - { - /* find out an empty filesystem type entry */ - if (*iter == NULL) - (empty == NULL) ? (empty = iter) : 0; - else if (strcmp((*iter)->name, ops->name) == 0) - { - rt_set_errno(-EEXIST); - ret = -1; - break; - } - } - - /* save the filesystem's operations */ - if (empty == NULL) - { - rt_set_errno(-ENOSPC); - LOG_E("There is no space to register this file system (%s).", ops->name); - ret = -1; - } - else if (ret == RT_EOK) - { - *empty = ops; - } - - dfs_unlock(); - return ret; -} - -/** - * this function will return the file system mounted on specified path. - * - * @param path the specified path string. - * - * @return the found file system or NULL if no file system mounted on - * specified path - */ -struct dfs_filesystem *dfs_filesystem_lookup(const char *path) -{ - struct dfs_filesystem *iter; - struct dfs_filesystem *fs = NULL; - uint32_t fspath, prefixlen; - - prefixlen = 0; - - RT_ASSERT(path); - - /* lock filesystem */ - dfs_lock(); - - /* lookup it in the filesystem table */ - for (iter = &filesystem_table[0]; - iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++) - { - if ((iter->path == NULL) || (iter->ops == NULL)) - continue; - - fspath = strlen(iter->path); - if ((fspath < prefixlen) - || (strncmp(iter->path, path, fspath) != 0)) - continue; - - /* check next path separator */ - if (fspath > 1 && (strlen(path) > fspath) && (path[fspath] != '/')) - continue; - - fs = iter; - prefixlen = fspath; - } - - dfs_unlock(); - - return fs; -} - -/** - * this function will return the mounted path for specified device. - * - * @param device the device object which is mounted. - * - * @return the mounted path or NULL if none device mounted. - */ -const char *dfs_filesystem_get_mounted_path(struct rt_device *device) -{ - const char *path = NULL; - struct dfs_filesystem *iter; - - dfs_lock(); - for (iter = &filesystem_table[0]; - iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++) - { - /* find the mounted device */ - if (iter->ops == NULL) continue; - else if (iter->dev_id == device) - { - path = iter->path; - break; - } - } - - /* release filesystem_table lock */ - dfs_unlock(); - - return path; -} - -/** - * this function will fetch the partition table on specified buffer. - * - * @param part the returned partition structure. - * @param buf the buffer contains partition table. - * @param pindex the index of partition table to fetch. - * - * @return RT_EOK on successful or -RT_ERROR on failed. - */ -int dfs_filesystem_get_partition(struct dfs_partition *part, - uint8_t *buf, - uint32_t pindex) -{ -#define DPT_ADDRESS 0x1be /* device partition offset in Boot Sector */ -#define DPT_ITEM_SIZE 16 /* partition item size */ - - uint8_t *dpt; - uint8_t type; - - RT_ASSERT(part != NULL); - RT_ASSERT(buf != NULL); - - dpt = buf + DPT_ADDRESS + pindex * DPT_ITEM_SIZE; - - /* check if it is a valid partition table */ - if ((*dpt != 0x80) && (*dpt != 0x00)) - return -EIO; - - /* get partition type */ - type = *(dpt + 4); - if (type == 0) - return -EIO; - - /* set partition information - * size is the number of 512-Byte */ - part->type = type; - part->offset = *(dpt + 8) | *(dpt + 9) << 8 | *(dpt + 10) << 16 | *(dpt + 11) << 24; - part->size = *(dpt + 12) | *(dpt + 13) << 8 | *(dpt + 14) << 16 | *(dpt + 15) << 24; - - rt_kprintf("found part[%d], begin: %d, size: ", - pindex, part->offset * 512); - if ((part->size >> 11) == 0) - rt_kprintf("%d%s", part->size >> 1, "KB\n"); /* KB */ - else - { - unsigned int part_size; - part_size = part->size >> 11; /* MB */ - if ((part_size >> 10) == 0) - rt_kprintf("%d.%d%s", part_size, (part->size >> 1) & 0x3FF, "MB\n"); - else - rt_kprintf("%d.%d%s", part_size >> 10, part_size & 0x3FF, "GB\n"); - } - - return RT_EOK; -} - -/** - * this function will mount a file system on a specified path. - * - * @param device_name the name of device which includes a file system. - * @param path the path to mount a file system - * @param filesystemtype the file system type - * @param rwflag the read/write etc. flag. - * @param data the private data(parameter) for this file system. - * - * @return 0 on successful or -1 on failed. - */ -int dfs_mount(const char *device_name, - const char *path, - const char *filesystemtype, - unsigned long rwflag, - const void *data) -{ - const struct dfs_filesystem_ops **ops; - struct dfs_filesystem *iter; - struct dfs_filesystem *fs = NULL; - char *fullpath = NULL; - rt_device_t dev_id; - - /* open specific device */ - if (device_name == NULL) - { - /* which is a non-device filesystem mount */ - dev_id = NULL; - } - else if ((dev_id = rt_device_find(device_name)) == NULL) - { - /* no this device */ - rt_set_errno(-ENODEV); - return -1; - } - - /* find out the specific filesystem */ - dfs_lock(); - - for (ops = &filesystem_operation_table[0]; - ops < &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; ops++) - if ((*ops != NULL) && (strncmp((*ops)->name, filesystemtype, strlen((*ops)->name)) == 0)) - break; - - dfs_unlock(); - - if (ops == &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]) - { - /* can't find filesystem */ - rt_set_errno(-ENODEV); - return -1; - } - - /* check if there is mount implementation */ - if ((*ops == NULL) || ((*ops)->mount == NULL)) - { - rt_set_errno(-ENOSYS); - return -1; - } - - /* make full path for special file */ - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == NULL) /* not an abstract path */ - { - rt_set_errno(-ENOTDIR); - return -1; - } - - /* Check if the path exists or not, raw APIs call, fixme */ - if ((strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0)) - { - struct dfs_fd fd; - - fd_init(&fd); - if (dfs_file_open(&fd, fullpath, O_RDONLY | O_DIRECTORY) < 0) - { - rt_free(fullpath); - rt_set_errno(-ENOTDIR); - - return -1; - } - dfs_file_close(&fd); - } - - /* check whether the file system mounted or not in the filesystem table - * if it is unmounted yet, find out an empty entry */ - dfs_lock(); - - for (iter = &filesystem_table[0]; - iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++) - { - /* check if it is an empty filesystem table entry? if it is, save fs */ - if (iter->ops == NULL) - (fs == NULL) ? (fs = iter) : 0; - /* check if the PATH is mounted */ - else if (strcmp(iter->path, path) == 0) - { - rt_set_errno(-EINVAL); - goto err1; - } - } - - if ((fs == NULL) && (iter == &filesystem_table[DFS_FILESYSTEMS_MAX])) - { - rt_set_errno(-ENOSPC); - LOG_E("There is no space to mount this file system (%s).", filesystemtype); - goto err1; - } - - /* register file system */ - fs->path = fullpath; - fs->ops = *ops; - fs->dev_id = dev_id; - /* For UFS, record the real filesystem name */ - fs->data = (void *) filesystemtype; - - /* release filesystem_table lock */ - dfs_unlock(); - - /* open device, but do not check the status of device */ - if (dev_id != NULL) - { - if (rt_device_open(fs->dev_id, - RT_DEVICE_OFLAG_RDWR) != RT_EOK) - { - /* The underlying device has error, clear the entry. */ - dfs_lock(); - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - - goto err1; - } - } - - /* call mount of this filesystem */ - if ((*ops)->mount(fs, rwflag, data) < 0) - { - /* close device */ - if (dev_id != NULL) - rt_device_close(fs->dev_id); - - /* mount failed */ - dfs_lock(); - /* clear filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - - goto err1; - } - - return 0; - -err1: - dfs_unlock(); - rt_free(fullpath); - - return -1; -} - -/** - * this function will unmount a file system on specified path. - * - * @param specialfile the specified path which mounted a file system. - * - * @return 0 on successful or -1 on failed. - */ -int dfs_unmount(const char *specialfile) -{ - char *fullpath; - struct dfs_filesystem *iter; - struct dfs_filesystem *fs = NULL; - - fullpath = dfs_normalize_path(NULL, specialfile); - if (fullpath == NULL) - { - rt_set_errno(-ENOTDIR); - - return -1; - } - - /* lock filesystem */ - dfs_lock(); - - for (iter = &filesystem_table[0]; - iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++) - { - /* check if the PATH is mounted */ - if ((iter->path != NULL) && (strcmp(iter->path, fullpath) == 0)) - { - fs = iter; - break; - } - } - - if (fs == NULL || - fs->ops->unmount == NULL || - fs->ops->unmount(fs) < 0) - { - goto err1; - } - - /* close device, but do not check the status of device */ - if (fs->dev_id != NULL) - rt_device_close(fs->dev_id); - - if (fs->path != NULL) - rt_free(fs->path); - - /* clear this filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - - dfs_unlock(); - rt_free(fullpath); - - return 0; - -err1: - dfs_unlock(); - rt_free(fullpath); - - return -1; -} - -/** - * make a file system on the special device - * - * @param fs_name the file system name - * @param device_name the special device name - * - * @return 0 on successful, otherwise failed. - */ -int dfs_mkfs(const char *fs_name, const char *device_name) -{ - int index; - rt_device_t dev_id = NULL; - - /* check device name, and it should not be NULL */ - if (device_name != NULL) - dev_id = rt_device_find(device_name); - - if (dev_id == NULL) - { - rt_set_errno(-ENODEV); - LOG_E("Device (%s) was not found", device_name); - return -1; - } - - /* lock file system */ - dfs_lock(); - /* find the file system operations */ - for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index ++) - { - if (filesystem_operation_table[index] != NULL && - strncmp(filesystem_operation_table[index]->name, fs_name, - strlen(filesystem_operation_table[index]->name)) == 0) - break; - } - dfs_unlock(); - - if (index < DFS_FILESYSTEM_TYPES_MAX) - { - /* find file system operation */ - const struct dfs_filesystem_ops *ops = filesystem_operation_table[index]; - if (ops->mkfs == NULL) - { - LOG_E("The file system (%s) mkfs function was not implement", fs_name); - rt_set_errno(-ENOSYS); - return -1; - } - - return ops->mkfs(dev_id, fs_name); - } - - LOG_E("File system (%s) was not found.", fs_name); - - return -1; -} - -/** - * this function will return the information about a mounted file system. - * - * @param path the path which mounted file system. - * @param buffer the buffer to save the returned information. - * - * @return 0 on successful, others on failed. - */ -int dfs_statfs(const char *path, struct statfs *buffer) -{ - struct dfs_filesystem *fs; - - fs = dfs_filesystem_lookup(path); - if (fs != NULL) - { - if (fs->ops->statfs != NULL) - return fs->ops->statfs(fs, buffer); - } - - rt_set_errno(-ENOSYS); - return -1; -} - -#ifdef RT_USING_DFS_MNTTABLE -int dfs_mount_table(void) -{ - int index = 0; - - while (1) - { - if (mount_table[index].path == NULL) break; - - if (dfs_mount(mount_table[index].device_name, - mount_table[index].path, - mount_table[index].filesystemtype, - mount_table[index].rwflag, - mount_table[index].data) != 0) - { - LOG_E("mount fs[%s] on %s failed.\n", mount_table[index].filesystemtype, - mount_table[index].path); - return -RT_ERROR; - } - - index ++; - } - return 0; -} -INIT_ENV_EXPORT(dfs_mount_table); - -int dfs_mount_device(rt_device_t dev) -{ - int index = 0; - - if(dev == RT_NULL) { - rt_kprintf("the device is NULL to be mounted.\n"); - return -RT_ERROR; - } - - while (1) - { - if (mount_table[index].path == NULL) break; - - if(strcmp(mount_table[index].device_name, dev->parent.name) == 0) { - if (dfs_mount(mount_table[index].device_name, - mount_table[index].path, - mount_table[index].filesystemtype, - mount_table[index].rwflag, - mount_table[index].data) != 0) - { - LOG_E("mount fs[%s] device[%s] to %s failed.\n", mount_table[index].filesystemtype, dev->parent.name, - mount_table[index].path); - return -RT_ERROR; - } else { - LOG_D("mount fs[%s] device[%s] to %s ok.\n", mount_table[index].filesystemtype, dev->parent.name, - mount_table[index].path); - return RT_EOK; - } - } - - index ++; - } - - rt_kprintf("can't find device:%s to be mounted.\n", dev->parent.name); - return -RT_ERROR; -} - -int dfs_unmount_device(rt_device_t dev) -{ - struct dfs_filesystem *iter; - struct dfs_filesystem *fs = NULL; - - /* lock filesystem */ - dfs_lock(); - - for (iter = &filesystem_table[0]; - iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++) - { - /* check if the PATH is mounted */ - if (strcmp(iter->dev_id->parent.name, dev->parent.name) == 0) - { - fs = iter; - break; - } - } - - if (fs == NULL || - fs->ops->unmount == NULL || - fs->ops->unmount(fs) < 0) - { - goto err1; - } - - /* close device, but do not check the status of device */ - if (fs->dev_id != NULL) - rt_device_close(fs->dev_id); - - if (fs->path != NULL) - rt_free(fs->path); - - /* clear this filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - - dfs_unlock(); - - return 0; - -err1: - dfs_unlock(); - - return -1; -} - -#endif - -#ifdef RT_USING_FINSH -#include <finsh.h> -void mkfs(const char *fs_name, const char *device_name) -{ - dfs_mkfs(fs_name, device_name); -} -FINSH_FUNCTION_EXPORT(mkfs, make a file system); - -int df(const char *path) -{ - int result; - int minor = 0; - long long cap; - struct statfs buffer; - - int unit_index = 0; - char *unit_str[] = {"KB", "MB", "GB"}; - - result = dfs_statfs(path ? path : NULL, &buffer); - if (result != 0) - { - if (rt_get_errno() == -ENOSYS) - rt_kprintf("The function is not implemented.\n"); - else - rt_kprintf("statfs failed: errno=%d.\n", rt_get_errno()); - return -1; - } - - cap = ((long long)buffer.f_bsize) * ((long long)buffer.f_bfree) / 1024LL; - for (unit_index = 0; unit_index < 2; unit_index ++) - { - if (cap < 1024) break; - - minor = (cap % 1024) * 10 / 1024; /* only one decimal point */ - cap = cap / 1024; - } - - rt_kprintf("disk free: %d.%d %s [ %d block, %d bytes per block ]\n", - (unsigned long)cap, minor, unit_str[unit_index], buffer.f_bfree, buffer.f_bsize); - return 0; -} -FINSH_FUNCTION_EXPORT(df, get disk free); -#endif - -/* @} */ diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c deleted file mode 100644 index ce1a3329d3..0000000000 --- a/components/dfs/src/dfs_posix.c +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2009-05-27 Yi.qiu The first version - * 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...' - * 2022-01-19 Meco Man add creat() - */ - -#include <dfs_file.h> -#include <dfs_private.h> -#include <sys/errno.h> - -#ifdef RT_USING_SMART -#include <lwp.h> -#endif - -/** - * @addtogroup FsPosixApi - */ - -/*@{*/ - -/** - * this function is a POSIX compliant version, which will open a file and - * return a file descriptor according specified flags. - * - * @param file the path name of file. - * @param flags the file open flags. - * - * @return the non-negative integer on successful open, others for failed. - */ -int open(const char *file, int flags, ...) -{ - int fd, result; - struct dfs_fd *d; - - /* allocate a fd */ - fd = fd_new(); - if (fd < 0) - { - rt_set_errno(-ENOMEM); - - return -1; - } - d = fd_get(fd); - - result = dfs_file_open(d, file, flags); - if (result < 0) - { - /* release the ref-count of fd */ - fd_release(fd); - - rt_set_errno(result); - - return -1; - } - - return fd; -} -RTM_EXPORT(open); - -/** - * this function is a POSIX compliant version, - * which will create a new file or rewrite an existing one - * - * @param path the path name of file. - * @param mode the file permission bits to be used in creating the file (not used, can be 0) - * - * @return the non-negative integer on successful open, others for failed. - */ -int creat(const char *path, mode_t mode) -{ - return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); -} -RTM_EXPORT(creat); - -/** - * this function is a POSIX compliant version, which will close the open - * file descriptor. - * - * @param fd the file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int close(int fd) -{ - int result; - struct dfs_fd *d; - - d = fd_get(fd); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - result = dfs_file_close(d); - - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - fd_release(fd); - - return 0; -} -RTM_EXPORT(close); - -/** - * this function is a POSIX compliant version, which will read specified data - * buffer length for an open file descriptor. - * - * @param fd the file descriptor. - * @param buf the buffer to save the read data. - * @param len the maximal length of data buffer - * - * @return the actual read data buffer length. If the returned value is 0, it - * may be reach the end of file, please check errno. - */ -#ifdef _READ_WRITE_RETURN_TYPE -_READ_WRITE_RETURN_TYPE read(int fd, void *buf, size_t len) /* some gcc tool chains will use different data structure */ -#else -ssize_t read(int fd, void *buf, size_t len) -#endif -{ - int result; - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fd); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - result = dfs_file_read(d, buf, len); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return result; -} -RTM_EXPORT(read); - -/** - * this function is a POSIX compliant version, which will write specified data - * buffer length for an open file descriptor. - * - * @param fd the file descriptor - * @param buf the data buffer to be written. - * @param len the data buffer length. - * - * @return the actual written data buffer length. - */ -#ifdef _READ_WRITE_RETURN_TYPE -_READ_WRITE_RETURN_TYPE write(int fd, const void *buf, size_t len) /* some gcc tool chains will use different data structure */ -#else -ssize_t write(int fd, const void *buf, size_t len) -#endif -{ - int result; - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fd); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - result = dfs_file_write(d, buf, len); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return result; -} -RTM_EXPORT(write); - -/** - * this function is a POSIX compliant version, which will seek the offset for - * an open file descriptor. - * - * @param fd the file descriptor. - * @param offset the offset to be seeked. - * @param whence the directory of seek. - * - * @return the current read/write position in the file, or -1 on failed. - */ -off_t lseek(int fd, off_t offset, int whence) -{ - int result; - struct dfs_fd *d; - - d = fd_get(fd); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - switch (whence) - { - case SEEK_SET: - break; - - case SEEK_CUR: - offset += d->pos; - break; - - case SEEK_END: - offset += d->vnode->size; - break; - - default: - rt_set_errno(-EINVAL); - - return -1; - } - - if (offset < 0) - { - rt_set_errno(-EINVAL); - - return -1; - } - result = dfs_file_lseek(d, offset); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return offset; -} -RTM_EXPORT(lseek); - -#ifndef _WIN32 -/** - * this function is a POSIX compliant version, which will rename old file name - * to new file name. - * - * @param old the old file name. - * @param new the new file name. - * - * @return 0 on successful, -1 on failed. - * - * note: the old and new file name must be belong to a same file system. - */ -int rename(const char *old_file, const char *new_file) -{ - int result; - - result = dfs_file_rename(old_file, new_file); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return 0; -} -RTM_EXPORT(rename); -#endif - -/** - * this function is a POSIX compliant version, which will unlink (remove) a - * specified path file from file system. - * - * @param pathname the specified path name to be unlinked. - * - * @return 0 on successful, -1 on failed. - */ -int unlink(const char *pathname) -{ - int result; - - result = dfs_file_unlink(pathname); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return 0; -} -RTM_EXPORT(unlink); - -/** - * this function is a POSIX compliant version, which will get file information. - * - * @param file the file name - * @param buf the data buffer to save stat description. - * - * @return 0 on successful, -1 on failed. - */ -int stat(const char *file, struct stat *buf) -{ - int result; - - result = dfs_file_stat(file, buf); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return result; -} -RTM_EXPORT(stat); - -/** - * this function is a POSIX compliant version, which will get file status. - * - * @param fildes the file description - * @param buf the data buffer to save stat description. - * - * @return 0 on successful, -1 on failed. - */ -int fstat(int fildes, struct stat *buf) -{ - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fildes); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - return stat(d->vnode->fullpath, buf); -} -RTM_EXPORT(fstat); - -/** - * this function is a POSIX compliant version, which shall request that all data - * for the open file descriptor named by fildes is to be transferred to the storage - * device associated with the file described by fildes. - * - * @param fildes the file description - * - * @return 0 on successful completion. Otherwise, -1 shall be returned and errno - * set to indicate the error. - */ -int fsync(int fildes) -{ - int ret; - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fildes); - if (d == NULL) - { - rt_set_errno(-EBADF); - return -1; - } - - ret = dfs_file_flush(d); - - return ret; -} -RTM_EXPORT(fsync); - -/** - * this function is a POSIX compliant version, which shall perform a variety of - * control functions on devices. - * - * @param fildes the file description - * @param cmd the specified command - * @param data represents the additional information that is needed by this - * specific device to perform the requested function. - * - * @return 0 on successful completion. Otherwise, -1 shall be returned and errno - * set to indicate the error. - */ -int fcntl(int fildes, int cmd, ...) -{ - int ret = -1; - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fildes); - if (d) - { - void *arg; - va_list ap; - - va_start(ap, cmd); - arg = va_arg(ap, void *); - va_end(ap); - - ret = dfs_file_ioctl(d, cmd, arg); - } - else ret = -EBADF; - - if (ret < 0) - { - rt_set_errno(ret); - ret = -1; - } - - return ret; -} -RTM_EXPORT(fcntl); - -/** - * this function is a POSIX compliant version, which shall perform a variety of - * control functions on devices. - * - * @param fildes the file description - * @param cmd the specified command - * @param data represents the additional information that is needed by this - * specific device to perform the requested function. - * - * @return 0 on successful completion. Otherwise, -1 shall be returned and errno - * set to indicate the error. - */ -int ioctl(int fildes, int cmd, ...) -{ - void *arg; - va_list ap; - - va_start(ap, cmd); - arg = va_arg(ap, void *); - va_end(ap); - - /* we use fcntl for this API. */ - return fcntl(fildes, cmd, arg); -} -RTM_EXPORT(ioctl); - -/** - * - * this function is a POSIX compliant version, which cause the regular file - * referenced by fd to be truncated to a size of precisely length bytes. - * @param fd the file descriptor. - * @param length the length to be truncated. - * - * @return Upon successful completion, ftruncate() shall return 0; - * otherwise, -1 shall be returned and errno set to indicate the error. - */ -int ftruncate(int fd, off_t length) -{ - int result; - struct dfs_fd *d; - - d = fd_get(fd); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - if (length < 0) - { - rt_set_errno(-EINVAL); - - return -1; - } - result = dfs_file_ftruncate(d, length); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return 0; -} -RTM_EXPORT(ftruncate); - -/** - * this function is a POSIX compliant version, which will return the - * information about a mounted file system. - * - * @param path the path which mounted file system. - * @param buf the buffer to save the returned information. - * - * @return 0 on successful, others on failed. - */ -int statfs(const char *path, struct statfs *buf) -{ - int result; - - result = dfs_statfs(path, buf); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return result; -} -RTM_EXPORT(statfs); - -/** - * this function is a POSIX compliant version, which will return the - * information about a mounted file system. - * - * @param fildes the file description. - * @param buf the buffer to save the returned information. - * - * @return 0 on successful, others on failed. - */ -int fstatfs(int fildes, struct statfs *buf) -{ - struct dfs_fd *d; - - /* get the fd */ - d = fd_get(fildes); - if (d == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - return statfs(d->vnode->fullpath, buf); -} -RTM_EXPORT(fstatfs); - -/** - * this function is a POSIX compliant version, which will make a directory - * - * @param path the directory path to be made. - * @param mode - * - * @return 0 on successful, others on failed. - */ -int mkdir(const char *path, mode_t mode) -{ - int fd; - struct dfs_fd *d; - int result; - - fd = fd_new(); - if (fd == -1) - { - rt_set_errno(-ENOMEM); - - return -1; - } - - d = fd_get(fd); - - result = dfs_file_open(d, path, O_DIRECTORY | O_CREAT); - - if (result < 0) - { - fd_release(fd); - rt_set_errno(result); - - return -1; - } - - dfs_file_close(d); - fd_release(fd); - - return 0; -} -RTM_EXPORT(mkdir); - -/** - * this function is a POSIX compliant version, which will remove a directory. - * - * @param pathname the path name to be removed. - * - * @return 0 on successful, others on failed. - */ -int rmdir(const char *pathname) -{ - int result; - - result = dfs_file_unlink(pathname); - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - - return 0; -} -RTM_EXPORT(rmdir); - -/** - * this function is a POSIX compliant version, which will open a directory. - * - * @param name the path name to be open. - * - * @return the DIR pointer of directory, NULL on open directory failed. - */ -DIR *opendir(const char *name) -{ - struct dfs_fd *d; - int fd, result; - DIR *t; - - t = NULL; - - /* allocate a fd */ - fd = fd_new(); - if (fd == -1) - { - rt_set_errno(-ENOMEM); - - return NULL; - } - d = fd_get(fd); - - result = dfs_file_open(d, name, O_RDONLY | O_DIRECTORY); - if (result >= 0) - { - /* open successfully */ - t = (DIR *) rt_malloc(sizeof(DIR)); - if (t == NULL) - { - dfs_file_close(d); - fd_release(fd); - } - else - { - rt_memset(t, 0, sizeof(DIR)); - - t->fd = fd; - } - - return t; - } - - /* open failed */ - fd_release(fd); - rt_set_errno(result); - - return NULL; -} -RTM_EXPORT(opendir); - -/** - * this function is a POSIX compliant version, which will return a pointer - * to a dirent structure representing the next directory entry in the - * directory stream. - * - * @param d the directory stream pointer. - * - * @return the next directory entry, NULL on the end of directory or failed. - */ -struct dirent *readdir(DIR *d) -{ - int result; - struct dfs_fd *fd; - - fd = fd_get(d->fd); - if (fd == NULL) - { - rt_set_errno(-EBADF); - return NULL; - } - - if (d->num) - { - struct dirent *dirent_ptr; - dirent_ptr = (struct dirent *)&d->buf[d->cur]; - d->cur += dirent_ptr->d_reclen; - } - - if (!d->num || d->cur >= d->num) - { - /* get a new entry */ - result = dfs_file_getdents(fd, - (struct dirent *)d->buf, - sizeof(d->buf) - 1); - if (result <= 0) - { - rt_set_errno(result); - - return NULL; - } - - d->num = result; - d->cur = 0; /* current entry index */ - } - - return (struct dirent *)(d->buf + d->cur); -} -RTM_EXPORT(readdir); - -/** - * this function is a POSIX compliant version, which will return current - * location in directory stream. - * - * @param d the directory stream pointer. - * - * @return the current location in directory stream. - */ -long telldir(DIR *d) -{ - struct dfs_fd *fd; - long result; - - fd = fd_get(d->fd); - if (fd == NULL) - { - rt_set_errno(-EBADF); - - return 0; - } - - result = fd->pos - d->num + d->cur; - - return result; -} -RTM_EXPORT(telldir); - -/** - * this function is a POSIX compliant version, which will set position of - * next directory structure in the directory stream. - * - * @param d the directory stream. - * @param offset the offset in directory stream. - */ -void seekdir(DIR *d, long offset) -{ - struct dfs_fd *fd; - - fd = fd_get(d->fd); - if (fd == NULL) - { - rt_set_errno(-EBADF); - - return ; - } - - /* seek to the offset position of directory */ - if (dfs_file_lseek(fd, offset) >= 0) - d->num = d->cur = 0; -} -RTM_EXPORT(seekdir); - -/** - * this function is a POSIX compliant version, which will reset directory - * stream. - * - * @param d the directory stream. - */ -void rewinddir(DIR *d) -{ - struct dfs_fd *fd; - - fd = fd_get(d->fd); - if (fd == NULL) - { - rt_set_errno(-EBADF); - - return ; - } - - /* seek to the beginning of directory */ - if (dfs_file_lseek(fd, 0) >= 0) - d->num = d->cur = 0; -} -RTM_EXPORT(rewinddir); - -/** - * this function is a POSIX compliant version, which will close a directory - * stream. - * - * @param d the directory stream. - * - * @return 0 on successful, -1 on failed. - */ -int closedir(DIR *d) -{ - int result; - struct dfs_fd *fd; - - fd = fd_get(d->fd); - if (fd == NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - result = dfs_file_close(fd); - fd_release(d->fd); - - rt_free(d); - - if (result < 0) - { - rt_set_errno(result); - - return -1; - } - else - return 0; -} -RTM_EXPORT(closedir); - -#ifdef DFS_USING_WORKDIR -/** - * this function is a POSIX compliant version, which will change working - * directory. - * - * @param path the path name to be changed to. - * - * @return 0 on successful, -1 on failed. - */ -int chdir(const char *path) -{ - char *fullpath; - DIR *d; - - if (path == NULL) - { - dfs_lock(); -#ifdef DFS_USING_WORKDIR - rt_kprintf("%s\n", working_directory); -#endif - dfs_unlock(); - - return 0; - } - - if (strlen(path) > DFS_PATH_MAX) - { - rt_set_errno(-ENOTDIR); - - return -1; - } - - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == NULL) - { - rt_set_errno(-ENOTDIR); - - return -1; /* build path failed */ - } - - dfs_lock(); - d = opendir(fullpath); - if (d == NULL) - { - rt_free(fullpath); - /* this is a not exist directory */ - dfs_unlock(); - - return -1; - } - - /* close directory stream */ - closedir(d); -#ifdef RT_USING_SMART - /* copy full path to working directory */ - lwp_setcwd(fullpath); -#else - rt_strncpy(working_directory, fullpath, DFS_PATH_MAX); -#endif - /* release normalize directory path name */ - rt_free(fullpath); - - dfs_unlock(); - - return 0; -} -RTM_EXPORT(chdir); - -#ifdef RT_USING_FINSH -FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory); -#endif -#endif - -/** - * this function is a POSIX compliant version, which shall check the file named - * by the pathname pointed to by the path argument for accessibility according - * to the bit pattern contained in amode. - * - * @param path the specified file/dir path. - * @param amode the value is either the bitwise-inclusive OR of the access - * permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK). - */ -int access(const char *path, int amode) -{ - struct stat sb; - if (stat(path, &sb) < 0) - return -1; /* already sets errno */ - - /* ignore R_OK,W_OK,X_OK condition */ - return 0; -} -/** - * this function is a POSIX compliant version, which will set current - * working directory. - * - * @param buf the current directory. - * - * @return null. - */ -void setcwd(char *buf) -{ -#ifdef DFS_USING_WORKDIR - dfs_lock(); -#ifdef RT_USING_SMART - lwp_setcwd(buf); -#else - rt_strncpy(working_directory, buf, DFS_PATH_MAX); -#endif - dfs_unlock(); -#else - rt_kprintf(NO_WORKING_DIR); -#endif - - return ; -} -RTM_EXPORT(setcwd); - -/** - * this function is a POSIX compliant version, which will return current - * working directory. - * - * @param buf the returned current directory. - * @param size the buffer size. - * - * @return the returned current directory. - */ -char *getcwd(char *buf, size_t size) -{ -#ifdef DFS_USING_WORKDIR - char *dir_buf = RT_NULL; - - dfs_lock(); - -#ifdef RT_USING_SMART - dir_buf = lwp_getcwd(); -#else - dir_buf = &working_directory[0]; -#endif - - /* copy to buf parameter */ - if (buf) - { - rt_strncpy(buf, dir_buf, size); - } - - dfs_unlock(); -#else - rt_kprintf(NO_WORKING_DIR); -#endif - - return buf; -} -RTM_EXPORT(getcwd); - -/* @} */ |
