From 5646189b29cb552654387ee7eac22f1299e35347 Mon Sep 17 00:00:00 2001 From: prife Date: Tue, 8 Jan 2013 18:58:45 +0800 Subject: [PATCH 1/3] elm fatfs support mkfs with no need to run dfs_mount elm first; and can mount/umount/mkfs without reset any more --- components/dfs/filesystems/elmfat/dfs_elm.c | 169 +++++++++++++------- components/dfs/include/dfs_fs.h | 2 +- components/dfs/src/dfs_fs.c | 15 +- 3 files changed, 122 insertions(+), 64 deletions(-) diff --git a/components/dfs/filesystems/elmfat/dfs_elm.c b/components/dfs/filesystems/elmfat/dfs_elm.c index 376e1ba07..b4b25fbf9 100644 --- a/components/dfs/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/filesystems/elmfat/dfs_elm.c @@ -75,34 +75,46 @@ static int elm_result_to_dfs(FRESULT result) return status; } +/* results: + * -1, no space to install fatfs driver + * >= 0, there is an space to install fatfs driver + */ +static int get_disk(rt_device_t id) +{ + int index; + + for (index = 0; index < _VOLUMES; index ++) + { + if (disk[index] == id) + return index; + } + + return -1; +} + int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data) { FATFS *fat; FRESULT result; - BYTE index; + int index; - /* handle RT-Thread device routine */ - for (index = 0; index < _VOLUMES; index ++) - { - if (disk[index] == RT_NULL) - { - break; - } - } - if (index == _VOLUMES) + /* get an empty position */ + index = get_disk(RT_NULL); + if (index == -1) return -DFS_STATUS_ENOSPC; - /* get device */ + /* save device */ disk[index] = fs->dev_id; fat = (FATFS *)rt_malloc(sizeof(FATFS)); if (fat == RT_NULL) { + disk[index] = RT_NULL; return -1; } /* mount fatfs, always 0 logic driver */ - result = f_mount(index, fat); + result = f_mount((BYTE)index, fat); if (result == FR_OK) { char drive[8]; @@ -116,81 +128,113 @@ int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *d /* open the root directory to test whether the fatfs is valid */ result = f_opendir(dir, drive); if (result != FR_OK) - { - rt_free(dir); - return elm_result_to_dfs(result); - } - rt_free(dir); + goto __err; + /* mount succeed! */ fs->data = fat; - } - else - { - rt_free(fat); - return elm_result_to_dfs(result); + rt_free(dir); + return 0; } - return 0; +__err: + disk[index] = RT_NULL; + rt_free(fat); + return elm_result_to_dfs(result); } int dfs_elm_unmount(struct dfs_filesystem *fs) { FATFS *fat; FRESULT result; - BYTE index; + int index; fat = (FATFS *)fs->data; RT_ASSERT(fat != RT_NULL); /* find the device index and then umount it */ - for (index = 0; index < _VOLUMES; index ++) - { - if (disk[index] == fs->dev_id) - { - result = f_mount(index, RT_NULL); + index = get_disk(fs->dev_id); + if (index == -1) /* not found */ + return -DFS_STATUS_ENOENT; - if (result == FR_OK) - { - fs->data = RT_NULL; - disk[index] = RT_NULL; - rt_free(fat); - return DFS_STATUS_OK; - } - } - } + result = f_mount((BYTE)index, RT_NULL); + if (result != FR_OK) + return elm_result_to_dfs(result); - return -DFS_STATUS_ENOENT; + fs->data = RT_NULL; + disk[index] = RT_NULL; + rt_free(fat); + + return DFS_STATUS_OK; } -int dfs_elm_mkfs(const char *device_name) +int dfs_elm_mkfs(rt_device_t dev_id) { - BYTE drv; - rt_device_t dev; +#define FSM_STATUS_INIT 0 +#define FSM_STATUS_USE_TEMP_DRIVER 1 + FATFS *fat; + int flag; FRESULT result; + int index; - /* find device name */ - for (drv = 0; drv < _VOLUMES; drv ++) + if (dev_id == RT_NULL) + return -DFS_STATUS_EINVAL; + + /* if the device is already mounted, then just do mkfs to the drv, + * while if it is not mounted yet, then find an empty drive to do mkfs + */ + + flag = FSM_STATUS_INIT; + index = get_disk(dev_id); + if (index == -1) + { + /* not found the device id */ + index = get_disk(RT_NULL); + if (index == -1) + { + /* no space to store an temp driver */ + rt_kprintf("sorry, there is no space to do mkfs! \n"); + return -DFS_STATUS_ENOSPC; + } + else + { + fat = rt_malloc(sizeof(FATFS)); + if (fat == RT_NULL) + return -DFS_STATUS_ENOMEM; + + flag = FSM_STATUS_USE_TEMP_DRIVER; + + disk[index] = dev_id; + + /* just fill the FatFs[vol] in ff.c, or mkfs will failded! + * consider this condition: you just umount the elm fat, + * then the space in FatFs[index] is released, and now do mkfs + * on the disk, you will get a failure. so we need f_mount here, + * just fill the FatFS[index] in elm fatfs to make mkfs work. + */ + f_mount((BYTE)index, fat); + } + } + + /* 1: no partition table */ + /* 0: auto selection of cluster size */ + result = f_mkfs((BYTE)index, 1, 0); + + /* check flag status, we need clear the temp driver stored in disk[] */ + if (flag == FSM_STATUS_USE_TEMP_DRIVER) + { + rt_free(fat); + f_mount((BYTE)index, RT_NULL); + disk[index] = RT_NULL; + } + + if (result != FR_OK) { - dev = disk[drv]; - if (dev != RT_NULL && rt_strncmp(dev->parent.name, device_name, RT_NAME_MAX) == 0) - { - /* 1: no partition table */ - /* 0: auto selection of cluster size */ - result = f_mkfs(drv, 1, 0); - if (result != FR_OK) - { - rt_kprintf("format error\n"); - return elm_result_to_dfs(result); - } - - return DFS_STATUS_OK; - } + rt_kprintf("format error\n"); + return elm_result_to_dfs(result); } - /* can't find device driver */ - rt_kprintf("can not find device driver: %s\n", device_name); - return -DFS_STATUS_EIO; + return DFS_STATUS_OK; } int dfs_elm_statfs(struct dfs_filesystem *fs, struct statfs *buf) @@ -821,7 +865,8 @@ int ff_cre_syncobj(BYTE drv, _SYNC_t *m) int ff_del_syncobj(_SYNC_t m) { - rt_mutex_delete(m); + if (m != RT_NULL) + rt_mutex_delete(m); return RT_TRUE; } diff --git a/components/dfs/include/dfs_fs.h b/components/dfs/include/dfs_fs.h index 8d77a252e..00f73f246 100644 --- a/components/dfs/include/dfs_fs.h +++ b/components/dfs/include/dfs_fs.h @@ -35,7 +35,7 @@ struct dfs_filesystem_operation int (*unmount) (struct dfs_filesystem *fs); /* make a file system */ - int (*mkfs) (const char *device_name); + int (*mkfs) (rt_device_t devid); int (*statfs) (struct dfs_filesystem *fs, struct statfs *buf); int (*open) (struct dfs_fd *fd); diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c index 78c40013a..20f987a9a 100644 --- a/components/dfs/src/dfs_fs.c +++ b/components/dfs/src/dfs_fs.c @@ -424,6 +424,19 @@ err1: int dfs_mkfs(const char *fs_name, const char *device_name) { int index; + rt_device_t dev_id; + + /* check device name, and it should not be NULL */ + if (device_name == RT_NULL) + dev_id = RT_NULL; + else + dev_id = rt_device_find(device_name); + + if (dev_id == RT_NULL) + { + rt_set_errno(-DFS_STATUS_ENODEV); + return -1; + } /* lock file system */ dfs_lock(); @@ -438,7 +451,7 @@ int dfs_mkfs(const char *fs_name, const char *device_name) dfs_unlock(); if (ops->mkfs != RT_NULL) - return ops->mkfs(device_name); + return ops->mkfs(dev_id); break; } From 1e6bf8671ca3b4e5c305cab47d2b397e9e60253f Mon Sep 17 00:00:00 2001 From: prife Date: Tue, 8 Jan 2013 19:52:00 +0800 Subject: [PATCH 2/3] format dfs_elm.c with astyle --- components/dfs/filesystems/elmfat/dfs_elm.c | 1004 +++++++++---------- 1 file changed, 502 insertions(+), 502 deletions(-) diff --git a/components/dfs/filesystems/elmfat/dfs_elm.c b/components/dfs/filesystems/elmfat/dfs_elm.c index b4b25fbf9..c9fdfb905 100644 --- a/components/dfs/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/filesystems/elmfat/dfs_elm.c @@ -15,7 +15,7 @@ * 2012-07-26 aozima implement ff_memalloc and ff_memfree. * 2012-12-19 Bernard fixed the O_APPEND and lseek issue. */ - + #include #include "ffconf.h" #include "ff.h" @@ -30,142 +30,142 @@ static rt_device_t disk[_VOLUMES] = {0}; static int elm_result_to_dfs(FRESULT result) { - int status = DFS_STATUS_OK; + int status = DFS_STATUS_OK; - switch (result) - { - case FR_OK: - break; + switch (result) + { + case FR_OK: + break; - case FR_NO_FILE: - case FR_NO_PATH: - case FR_NO_FILESYSTEM: - status = -DFS_STATUS_ENOENT; - break; + case FR_NO_FILE: + case FR_NO_PATH: + case FR_NO_FILESYSTEM: + status = -DFS_STATUS_ENOENT; + break; - case FR_INVALID_NAME: - status = -DFS_STATUS_EINVAL; - break; + case FR_INVALID_NAME: + status = -DFS_STATUS_EINVAL; + break; - case FR_EXIST: - case FR_INVALID_OBJECT: - status = -DFS_STATUS_EEXIST; - break; + case FR_EXIST: + case FR_INVALID_OBJECT: + status = -DFS_STATUS_EEXIST; + break; - case FR_DISK_ERR: - case FR_NOT_READY: - case FR_INT_ERR: - status = -DFS_STATUS_EIO; - break; + case FR_DISK_ERR: + case FR_NOT_READY: + case FR_INT_ERR: + status = -DFS_STATUS_EIO; + break; - case FR_WRITE_PROTECTED: - case FR_DENIED: - status = -DFS_STATUS_EROFS; - break; + case FR_WRITE_PROTECTED: + case FR_DENIED: + status = -DFS_STATUS_EROFS; + break; - case FR_MKFS_ABORTED: - status = -DFS_STATUS_EINVAL; - break; + case FR_MKFS_ABORTED: + status = -DFS_STATUS_EINVAL; + break; - default: - status = -1; - break; - } + default: + status = -1; + break; + } - return status; + return status; } /* results: - * -1, no space to install fatfs driver - * >= 0, there is an space to install fatfs driver + * -1, no space to install fatfs driver + * >= 0, there is an space to install fatfs driver */ static int get_disk(rt_device_t id) { int index; - for (index = 0; index < _VOLUMES; index ++) - { - if (disk[index] == id) + for (index = 0; index < _VOLUMES; index ++) + { + if (disk[index] == id) return index; - } - + } + return -1; } int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data) { - FATFS *fat; - FRESULT result; - int index; + FATFS *fat; + FRESULT result; + int index; - /* get an empty position */ - index = get_disk(RT_NULL); - if (index == -1) - return -DFS_STATUS_ENOSPC; + /* get an empty position */ + index = get_disk(RT_NULL); + if (index == -1) + return -DFS_STATUS_ENOSPC; - /* save device */ - disk[index] = fs->dev_id; + /* save device */ + disk[index] = fs->dev_id; - fat = (FATFS *)rt_malloc(sizeof(FATFS)); - if (fat == RT_NULL) - { + fat = (FATFS *)rt_malloc(sizeof(FATFS)); + if (fat == RT_NULL) + { disk[index] = RT_NULL; - return -1; - } + return -1; + } - /* mount fatfs, always 0 logic driver */ - result = f_mount((BYTE)index, fat); - if (result == FR_OK) - { - char drive[8]; - DIR * dir; + /* mount fatfs, always 0 logic driver */ + result = f_mount((BYTE)index, fat); + if (result == FR_OK) + { + char drive[8]; + DIR *dir; - rt_snprintf(drive, sizeof(drive), "%d:/", index); - dir = (DIR *)rt_malloc(sizeof(DIR)); - if (dir == RT_NULL) - return -DFS_STATUS_ENOMEM; + rt_snprintf(drive, sizeof(drive), "%d:/", index); + dir = (DIR *)rt_malloc(sizeof(DIR)); + if (dir == RT_NULL) + return -DFS_STATUS_ENOMEM; - /* open the root directory to test whether the fatfs is valid */ - result = f_opendir(dir, drive); - if (result != FR_OK) + /* open the root directory to test whether the fatfs is valid */ + result = f_opendir(dir, drive); + if (result != FR_OK) goto __err; /* mount succeed! */ - fs->data = fat; - rt_free(dir); - return 0; - } + fs->data = fat; + rt_free(dir); + return 0; + } __err: disk[index] = RT_NULL; - rt_free(fat); - return elm_result_to_dfs(result); + rt_free(fat); + return elm_result_to_dfs(result); } int dfs_elm_unmount(struct dfs_filesystem *fs) { - FATFS *fat; - FRESULT result; - int index; + FATFS *fat; + FRESULT result; + int index; - fat = (FATFS *)fs->data; + fat = (FATFS *)fs->data; - RT_ASSERT(fat != RT_NULL); + RT_ASSERT(fat != RT_NULL); - /* find the device index and then umount it */ + /* find the device index and then umount it */ index = get_disk(fs->dev_id); if (index == -1) /* not found */ - return -DFS_STATUS_ENOENT; + return -DFS_STATUS_ENOENT; - result = f_mount((BYTE)index, RT_NULL); - if (result != FR_OK) - return elm_result_to_dfs(result); + result = f_mount((BYTE)index, RT_NULL); + if (result != FR_OK) + return elm_result_to_dfs(result); - fs->data = RT_NULL; - disk[index] = RT_NULL; - rt_free(fat); + fs->data = RT_NULL; + disk[index] = RT_NULL; + rt_free(fat); - return DFS_STATUS_OK; + return DFS_STATUS_OK; } int dfs_elm_mkfs(rt_device_t dev_id) @@ -174,13 +174,13 @@ int dfs_elm_mkfs(rt_device_t dev_id) #define FSM_STATUS_USE_TEMP_DRIVER 1 FATFS *fat; int flag; - FRESULT result; + FRESULT result; int index; if (dev_id == RT_NULL) return -DFS_STATUS_EINVAL; - /* if the device is already mounted, then just do mkfs to the drv, + /* if the device is already mounted, then just do mkfs to the drv, * while if it is not mounted yet, then find an empty drive to do mkfs */ @@ -190,11 +190,11 @@ int dfs_elm_mkfs(rt_device_t dev_id) { /* not found the device id */ index = get_disk(RT_NULL); - if (index == -1) - { + if (index == -1) + { /* no space to store an temp driver */ - rt_kprintf("sorry, there is no space to do mkfs! \n"); - return -DFS_STATUS_ENOSPC; + rt_kprintf("sorry, there is no space to do mkfs! \n"); + return -DFS_STATUS_ENOSPC; } else { @@ -206,19 +206,19 @@ int dfs_elm_mkfs(rt_device_t dev_id) disk[index] = dev_id; - /* just fill the FatFs[vol] in ff.c, or mkfs will failded! - * consider this condition: you just umount the elm fat, - * then the space in FatFs[index] is released, and now do mkfs - * on the disk, you will get a failure. so we need f_mount here, + /* just fill the FatFs[vol] in ff.c, or mkfs will failded! + * consider this condition: you just umount the elm fat, + * then the space in FatFs[index] is released, and now do mkfs + * on the disk, you will get a failure. so we need f_mount here, * just fill the FatFS[index] in elm fatfs to make mkfs work. */ f_mount((BYTE)index, fat); } } - /* 1: no partition table */ - /* 0: auto selection of cluster size */ - result = f_mkfs((BYTE)index, 1, 0); + /* 1: no partition table */ + /* 0: auto selection of cluster size */ + result = f_mkfs((BYTE)index, 1, 0); /* check flag status, we need clear the temp driver stored in disk[] */ if (flag == FSM_STATUS_USE_TEMP_DRIVER) @@ -228,513 +228,513 @@ int dfs_elm_mkfs(rt_device_t dev_id) disk[index] = RT_NULL; } - if (result != FR_OK) - { - rt_kprintf("format error\n"); - return elm_result_to_dfs(result); - } + if (result != FR_OK) + { + rt_kprintf("format error\n"); + return elm_result_to_dfs(result); + } - return DFS_STATUS_OK; + return DFS_STATUS_OK; } int dfs_elm_statfs(struct dfs_filesystem *fs, struct statfs *buf) { - FATFS *f; - FRESULT res; - char driver[4]; - DWORD fre_clust, fre_sect, tot_sect; + FATFS *f; + FRESULT res; + char driver[4]; + DWORD fre_clust, fre_sect, tot_sect; - RT_ASSERT(fs != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(fs != RT_NULL); + RT_ASSERT(buf != RT_NULL); - f = (FATFS *)fs->data; + f = (FATFS *)fs->data; - rt_snprintf(driver, sizeof(driver), "%d:", f->drv); - res = f_getfree(driver, &fre_clust, &f); - if (res) - return elm_result_to_dfs(res); + rt_snprintf(driver, sizeof(driver), "%d:", f->drv); + res = f_getfree(driver, &fre_clust, &f); + if (res) + return elm_result_to_dfs(res); - /* Get total sectors and free sectors */ - tot_sect = (f->n_fatent - 2) * f->csize; - fre_sect = fre_clust * f->csize; + /* Get total sectors and free sectors */ + tot_sect = (f->n_fatent - 2) * f->csize; + fre_sect = fre_clust * f->csize; - buf->f_bfree = fre_sect; - buf->f_blocks = tot_sect; + buf->f_bfree = fre_sect; + buf->f_blocks = tot_sect; #if _MAX_SS != 512 - buf->f_bsize = f->ssize; + buf->f_bsize = f->ssize; #else buf->f_bsize = 512; #endif - return 0; + return 0; } int dfs_elm_open(struct dfs_fd *file) { - FIL *fd; - BYTE mode; - FRESULT result; - char *drivers_fn; + FIL *fd; + BYTE mode; + FRESULT result; + char *drivers_fn; #if (_VOLUMES > 1) - int vol; - extern int elm_get_vol(FATFS *fat); + int vol; + extern int elm_get_vol(FATFS * fat); - /* add path for ELM FatFS driver support */ - vol = elm_get_vol((FATFS *)file->fs->data); - if (vol < 0) - return -DFS_STATUS_ENOENT; - drivers_fn = rt_malloc(256); - if (drivers_fn == RT_NULL) - return -DFS_STATUS_ENOMEM; + /* add path for ELM FatFS driver support */ + vol = elm_get_vol((FATFS *)file->fs->data); + if (vol < 0) + return -DFS_STATUS_ENOENT; + drivers_fn = rt_malloc(256); + if (drivers_fn == RT_NULL) + return -DFS_STATUS_ENOMEM; - rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->path); + rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->path); #else - drivers_fn = file->path; + drivers_fn = file->path; #endif - if (file->flags & DFS_O_DIRECTORY) - { - DIR *dir; + if (file->flags & DFS_O_DIRECTORY) + { + DIR *dir; - if (file->flags & DFS_O_CREAT) - { - result = f_mkdir(drivers_fn); - if (result != FR_OK) - { + if (file->flags & DFS_O_CREAT) + { + result = f_mkdir(drivers_fn); + if (result != FR_OK) + { #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - return elm_result_to_dfs(result); - } - } + return elm_result_to_dfs(result); + } + } - /* open directory */ - dir = (DIR *)rt_malloc(sizeof(DIR)); - if (dir == RT_NULL) - { + /* open directory */ + dir = (DIR *)rt_malloc(sizeof(DIR)); + if (dir == RT_NULL) + { #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - return -DFS_STATUS_ENOMEM; - } + return -DFS_STATUS_ENOMEM; + } - result = f_opendir(dir, drivers_fn); + result = f_opendir(dir, drivers_fn); #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - if (result != FR_OK) - { - rt_free(dir); - return elm_result_to_dfs(result); - } + if (result != FR_OK) + { + rt_free(dir); + return elm_result_to_dfs(result); + } - file->data = dir; - return DFS_STATUS_OK; - } - else - { - mode = FA_READ; + file->data = dir; + return DFS_STATUS_OK; + } + else + { + mode = FA_READ; - if (file->flags & DFS_O_WRONLY) - mode |= FA_WRITE; - if ((file->flags & DFS_O_ACCMODE) & DFS_O_RDWR) - mode |= FA_WRITE; - /* Opens the file, if it is existing. If not, a new file is created. */ - if (file->flags & DFS_O_CREAT) - mode |= FA_OPEN_ALWAYS; - /* Creates a new file. If the file is existing, it is truncated and overwritten. */ - if (file->flags & DFS_O_TRUNC) - mode |= FA_CREATE_ALWAYS; - /* Creates a new file. The function fails if the file is already existing. */ - if (file->flags & DFS_O_EXCL) - mode |= FA_CREATE_NEW; + if (file->flags & DFS_O_WRONLY) + mode |= FA_WRITE; + if ((file->flags & DFS_O_ACCMODE) & DFS_O_RDWR) + mode |= FA_WRITE; + /* Opens the file, if it is existing. If not, a new file is created. */ + if (file->flags & DFS_O_CREAT) + mode |= FA_OPEN_ALWAYS; + /* Creates a new file. If the file is existing, it is truncated and overwritten. */ + if (file->flags & DFS_O_TRUNC) + mode |= FA_CREATE_ALWAYS; + /* Creates a new file. The function fails if the file is already existing. */ + if (file->flags & DFS_O_EXCL) + mode |= FA_CREATE_NEW; - /* allocate a fd */ - fd = (FIL *)rt_malloc(sizeof(FIL)); - if (fd == RT_NULL) - { + /* allocate a fd */ + fd = (FIL *)rt_malloc(sizeof(FIL)); + if (fd == RT_NULL) + { #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - return -DFS_STATUS_ENOMEM; - } + return -DFS_STATUS_ENOMEM; + } - result = f_open(fd, drivers_fn, mode); + result = f_open(fd, drivers_fn, mode); #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - if (result == FR_OK) - { - file->pos = fd->fptr; - file->size = fd->fsize; - file->data = fd; + if (result == FR_OK) + { + file->pos = fd->fptr; + file->size = fd->fsize; + file->data = fd; - if (file->flags & DFS_O_APPEND) - { - /* seek to the end of file */ - f_lseek(fd, fd->fsize); - file->pos = fd->fptr; - } - } - else - { - /* open failed, return */ - rt_free(fd); - return elm_result_to_dfs(result); - } - } + if (file->flags & DFS_O_APPEND) + { + /* seek to the end of file */ + f_lseek(fd, fd->fsize); + file->pos = fd->fptr; + } + } + else + { + /* open failed, return */ + rt_free(fd); + return elm_result_to_dfs(result); + } + } - return DFS_STATUS_OK; + return DFS_STATUS_OK; } int dfs_elm_close(struct dfs_fd *file) { - FRESULT result; + FRESULT result; - result = FR_OK; - if (file->type == FT_DIRECTORY) - { - DIR *dir; + result = FR_OK; + if (file->type == FT_DIRECTORY) + { + DIR *dir; - dir = (DIR *)(file->data); - RT_ASSERT(dir != RT_NULL); + dir = (DIR *)(file->data); + RT_ASSERT(dir != RT_NULL); - /* release memory */ - rt_free(dir); - } - else if (file->type == FT_REGULAR) - { - FIL *fd; - fd = (FIL *)(file->data); - RT_ASSERT(fd != RT_NULL); + /* release memory */ + rt_free(dir); + } + else if (file->type == FT_REGULAR) + { + FIL *fd; + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); - result = f_close(fd); - if (result == FR_OK) - { - /* release memory */ - rt_free(fd); - } - } + result = f_close(fd); + if (result == FR_OK) + { + /* release memory */ + rt_free(fd); + } + } - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } -int dfs_elm_ioctl(struct dfs_fd *file, int cmd, void *args) +int dfs_elm_ioctl(struct dfs_fd *file, int cmd, void *args) { - return -DFS_STATUS_ENOSYS; + return -DFS_STATUS_ENOSYS; } int dfs_elm_read(struct dfs_fd *file, void *buf, rt_size_t len) { - FIL *fd; - FRESULT result; - UINT byte_read; + FIL *fd; + FRESULT result; + UINT byte_read; - if (file->type == FT_DIRECTORY) - { - return -DFS_STATUS_EISDIR; - } + if (file->type == FT_DIRECTORY) + { + return -DFS_STATUS_EISDIR; + } - fd = (FIL *)(file->data); - RT_ASSERT(fd != RT_NULL); + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); - result = f_read(fd, buf, len, &byte_read); - /* update position */ - file->pos = fd->fptr; - if (result == FR_OK) - return byte_read; + result = f_read(fd, buf, len, &byte_read); + /* update position */ + file->pos = fd->fptr; + if (result == FR_OK) + return byte_read; - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } int dfs_elm_write(struct dfs_fd *file, const void *buf, rt_size_t len) { - FIL *fd; - FRESULT result; - UINT byte_write; + FIL *fd; + FRESULT result; + UINT byte_write; - if (file->type == FT_DIRECTORY) - { - return -DFS_STATUS_EISDIR; - } + if (file->type == FT_DIRECTORY) + { + return -DFS_STATUS_EISDIR; + } - fd = (FIL *)(file->data); - RT_ASSERT(fd != RT_NULL); + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); - result = f_write(fd, buf, len, &byte_write); - /* update position and file size */ - file->pos = fd->fptr; - file->size = fd->fsize; - if (result == FR_OK) - return byte_write; + result = f_write(fd, buf, len, &byte_write); + /* update position and file size */ + file->pos = fd->fptr; + file->size = fd->fsize; + if (result == FR_OK) + return byte_write; - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } int dfs_elm_flush(struct dfs_fd *file) { - FIL *fd; - FRESULT result; + FIL *fd; + FRESULT result; - fd = (FIL *)(file->data); - RT_ASSERT(fd != RT_NULL); + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); - result = f_sync(fd); - return elm_result_to_dfs(result); + result = f_sync(fd); + return elm_result_to_dfs(result); } int dfs_elm_lseek(struct dfs_fd *file, rt_off_t offset) { - FRESULT result = FR_OK; - if (file->type == FT_REGULAR) - { - FIL *fd; + FRESULT result = FR_OK; + if (file->type == FT_REGULAR) + { + FIL *fd; - /* regular file type */ - fd = (FIL *)(file->data); - RT_ASSERT(fd != RT_NULL); - - result = f_lseek(fd, offset); - if (result == FR_OK) - { - /* return current position */ - file->pos = fd->fptr; - return fd->fptr; - } - } - else if (file->type == FT_DIRECTORY) - { - /* which is a directory */ - DIR *dir; + /* regular file type */ + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); - dir = (DIR *)(file->data); - RT_ASSERT(dir != RT_NULL); + result = f_lseek(fd, offset); + if (result == FR_OK) + { + /* return current position */ + file->pos = fd->fptr; + return fd->fptr; + } + } + else if (file->type == FT_DIRECTORY) + { + /* which is a directory */ + DIR *dir; - result = f_seekdir(dir, offset / sizeof(struct dirent)); - if (result == FR_OK) - { - /* update file position */ - file->pos = offset; - return file->pos; - } - } + dir = (DIR *)(file->data); + RT_ASSERT(dir != RT_NULL); - return elm_result_to_dfs(result); + result = f_seekdir(dir, offset / sizeof(struct dirent)); + if (result == FR_OK) + { + /* update file position */ + file->pos = offset; + return file->pos; + } + } + + return elm_result_to_dfs(result); } int dfs_elm_getdents(struct dfs_fd *file, struct dirent *dirp, rt_uint32_t count) { - DIR *dir; - FILINFO fno; - FRESULT result; - rt_uint32_t index; - struct dirent *d; + DIR *dir; + FILINFO fno; + FRESULT result; + rt_uint32_t index; + struct dirent *d; - dir = (DIR *)(file->data); - RT_ASSERT(dir != RT_NULL); + dir = (DIR *)(file->data); + RT_ASSERT(dir != RT_NULL); - /* make integer count */ - count = (count / sizeof(struct dirent)) * sizeof(struct dirent); - if (count == 0) - return -DFS_STATUS_EINVAL; + /* make integer count */ + count = (count / sizeof(struct dirent)) * sizeof(struct dirent); + if (count == 0) + return -DFS_STATUS_EINVAL; #if _USE_LFN - /* allocate long file name */ - fno.lfname = rt_malloc(256); - fno.lfsize = 256; + /* allocate long file name */ + fno.lfname = rt_malloc(256); + fno.lfsize = 256; #endif - index = 0; - while (1) - { - char *fn; + index = 0; + while (1) + { + char *fn; - d = dirp + index; + d = dirp + index; - result = f_readdir(dir, &fno); - if (result != FR_OK || fno.fname[0] == 0) - break; + result = f_readdir(dir, &fno); + if (result != FR_OK || fno.fname[0] == 0) + break; #if _USE_LFN - fn = *fno.lfname? fno.lfname : fno.fname; + fn = *fno.lfname ? fno.lfname : fno.fname; #else - fn = fno.fname; + fn = fno.fname; #endif - d->d_type = DFS_DT_UNKNOWN; - if (fno.fattrib & AM_DIR) - d->d_type = DFS_DT_DIR; - else - d->d_type = DFS_DT_REG; + d->d_type = DFS_DT_UNKNOWN; + if (fno.fattrib & AM_DIR) + d->d_type = DFS_DT_DIR; + else + d->d_type = DFS_DT_REG; - d->d_namlen = (rt_uint8_t)rt_strlen(fn); - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, fn, rt_strlen(fn) + 1); + d->d_namlen = (rt_uint8_t)rt_strlen(fn); + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, fn, rt_strlen(fn) + 1); - index ++; - if (index * sizeof(struct dirent) >= count) - break; - } + index ++; + if (index * sizeof(struct dirent) >= count) + break; + } #if _USE_LFN - rt_free(fno.lfname); + rt_free(fno.lfname); #endif - if (index == 0) - return elm_result_to_dfs(result); + if (index == 0) + return elm_result_to_dfs(result); - file->pos += index * sizeof(struct dirent); + file->pos += index * sizeof(struct dirent); - return index * sizeof(struct dirent); + return index * sizeof(struct dirent); } int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path) { - FRESULT result; + FRESULT result; #if _VOLUMES > 1 - int vol; - char *drivers_fn; - extern int elm_get_vol(FATFS *fat); + int vol; + char *drivers_fn; + extern int elm_get_vol(FATFS * fat); - /* add path for ELM FatFS driver support */ - vol = elm_get_vol((FATFS *)fs->data); - if (vol < 0) - return -DFS_STATUS_ENOENT; - drivers_fn = rt_malloc(256); - if (drivers_fn == RT_NULL) - return -DFS_STATUS_ENOMEM; + /* add path for ELM FatFS driver support */ + vol = elm_get_vol((FATFS *)fs->data); + if (vol < 0) + return -DFS_STATUS_ENOENT; + drivers_fn = rt_malloc(256); + if (drivers_fn == RT_NULL) + return -DFS_STATUS_ENOMEM; - rt_snprintf(drivers_fn, 256, "%d:%s", vol, path); + rt_snprintf(drivers_fn, 256, "%d:%s", vol, path); #else - const char *drivers_fn; - drivers_fn = path; + const char *drivers_fn; + drivers_fn = path; #endif - result = f_unlink(drivers_fn); + result = f_unlink(drivers_fn); #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *newpath) { - FRESULT result; + FRESULT result; #if _VOLUMES > 1 - char *drivers_oldfn; - const char *drivers_newfn; - int vol; - extern int elm_get_vol(FATFS *fat); + char *drivers_oldfn; + const char *drivers_newfn; + int vol; + extern int elm_get_vol(FATFS * fat); - /* add path for ELM FatFS driver support */ - vol = elm_get_vol((FATFS *)fs->data); - if (vol < 0) - return -DFS_STATUS_ENOENT; + /* add path for ELM FatFS driver support */ + vol = elm_get_vol((FATFS *)fs->data); + if (vol < 0) + return -DFS_STATUS_ENOENT; - drivers_oldfn = rt_malloc(256); - if (drivers_oldfn == RT_NULL) - return -DFS_STATUS_ENOMEM; - drivers_newfn = newpath; + drivers_oldfn = rt_malloc(256); + if (drivers_oldfn == RT_NULL) + return -DFS_STATUS_ENOMEM; + drivers_newfn = newpath; - rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, oldpath); + rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, oldpath); #else - const char *drivers_oldfn, *drivers_newfn; + const char *drivers_oldfn, *drivers_newfn; - drivers_oldfn = oldpath; - drivers_newfn = newpath; + drivers_oldfn = oldpath; + drivers_newfn = newpath; #endif - result = f_rename(drivers_oldfn, drivers_newfn); + result = f_rename(drivers_oldfn, drivers_newfn); #if _VOLUMES > 1 - rt_free(drivers_oldfn); + rt_free(drivers_oldfn); #endif - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st) { - FILINFO file_info; - FRESULT result; + FILINFO file_info; + FRESULT result; #if _VOLUMES > 1 - int vol; - char *drivers_fn; - extern int elm_get_vol(FATFS *fat); + int vol; + char *drivers_fn; + extern int elm_get_vol(FATFS * fat); - /* add path for ELM FatFS driver support */ - vol = elm_get_vol((FATFS *)fs->data); - if (vol < 0) - return -DFS_STATUS_ENOENT; - drivers_fn = rt_malloc(256); - if (drivers_fn == RT_NULL) - return -DFS_STATUS_ENOMEM; + /* add path for ELM FatFS driver support */ + vol = elm_get_vol((FATFS *)fs->data); + if (vol < 0) + return -DFS_STATUS_ENOENT; + drivers_fn = rt_malloc(256); + if (drivers_fn == RT_NULL) + return -DFS_STATUS_ENOMEM; - rt_snprintf(drivers_fn, 256, "%d:%s", vol, path); + rt_snprintf(drivers_fn, 256, "%d:%s", vol, path); #else - const char *drivers_fn; - drivers_fn = path; + const char *drivers_fn; + drivers_fn = path; #endif #if _USE_LFN - /* allocate long file name */ - file_info.lfname = rt_malloc(256); - file_info.lfsize = 256; + /* allocate long file name */ + file_info.lfname = rt_malloc(256); + file_info.lfsize = 256; #endif - result = f_stat(drivers_fn, &file_info); + result = f_stat(drivers_fn, &file_info); #if _VOLUMES > 1 - rt_free(drivers_fn); + rt_free(drivers_fn); #endif - if (result == FR_OK) - { - /* convert to dfs stat structure */ - st->st_dev = 0; + if (result == FR_OK) + { + /* convert to dfs stat structure */ + st->st_dev = 0; - st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | - DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; - if (file_info.fattrib & AM_DIR) - { - st->st_mode &= ~DFS_S_IFREG; - st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; - } - if (file_info.fattrib & AM_RDO) - st->st_mode &= ~(DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH); + st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + if (file_info.fattrib & AM_DIR) + { + st->st_mode &= ~DFS_S_IFREG; + st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + } + if (file_info.fattrib & AM_RDO) + st->st_mode &= ~(DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH); - st->st_size = file_info.fsize; - st->st_mtime = file_info.ftime; - st->st_blksize = 512; - } + st->st_size = file_info.fsize; + st->st_mtime = file_info.ftime; + st->st_blksize = 512; + } #if _USE_LFN - rt_free(file_info.lfname); + rt_free(file_info.lfname); #endif - return elm_result_to_dfs(result); + return elm_result_to_dfs(result); } static const struct dfs_filesystem_operation dfs_elm = { - "elm", - DFS_FS_FLAG_DEFAULT, - dfs_elm_mount, - dfs_elm_unmount, - dfs_elm_mkfs, - dfs_elm_statfs, + "elm", + DFS_FS_FLAG_DEFAULT, + dfs_elm_mount, + dfs_elm_unmount, + dfs_elm_mkfs, + dfs_elm_statfs, - dfs_elm_open, - dfs_elm_close, - dfs_elm_ioctl, - dfs_elm_read, - dfs_elm_write, - dfs_elm_flush, - dfs_elm_lseek, - dfs_elm_getdents, - dfs_elm_unlink, - dfs_elm_stat, - dfs_elm_rename, + dfs_elm_open, + dfs_elm_close, + dfs_elm_ioctl, + dfs_elm_read, + dfs_elm_write, + dfs_elm_flush, + dfs_elm_lseek, + dfs_elm_getdents, + dfs_elm_unlink, + dfs_elm_stat, + dfs_elm_rename, }; int elm_init(void) @@ -742,7 +742,7 @@ int elm_init(void) /* register fatfs file system */ dfs_register(&dfs_elm); - return 0; + return 0; } /* @@ -753,97 +753,97 @@ int elm_init(void) /* Initialize a Drive */ DSTATUS disk_initialize(BYTE drv) { - return 0; + return 0; } /* Return Disk Status */ DSTATUS disk_status(BYTE drv) { - return 0; + return 0; } /* Read Sector(s) */ DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, BYTE count) { - rt_size_t result; - rt_device_t device = disk[drv]; + rt_size_t result; + rt_device_t device = disk[drv]; - result = rt_device_read(device, sector, buff, count); - if (result == count) - { - return RES_OK; - } + result = rt_device_read(device, sector, buff, count); + if (result == count) + { + return RES_OK; + } - return RES_ERROR; + return RES_ERROR; } /* Write Sector(s) */ DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, BYTE count) { - rt_size_t result; - rt_device_t device = disk[drv]; + rt_size_t result; + rt_device_t device = disk[drv]; - result = rt_device_write(device, sector, buff, count); - if (result == count) - { - return RES_OK; - } + result = rt_device_write(device, sector, buff, count); + if (result == count) + { + return RES_OK; + } - return RES_ERROR; + return RES_ERROR; } /* Miscellaneous Functions */ DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff) { - rt_device_t device = disk[drv]; + rt_device_t device = disk[drv]; - if (device == RT_NULL) - return RES_ERROR; + if (device == RT_NULL) + return RES_ERROR; - if (ctrl == GET_SECTOR_COUNT) - { - struct rt_device_blk_geometry geometry; + if (ctrl == GET_SECTOR_COUNT) + { + struct rt_device_blk_geometry geometry; - rt_memset(&geometry, 0, sizeof(geometry)); - rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); + rt_memset(&geometry, 0, sizeof(geometry)); + rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); - *(DWORD *)buff = geometry.sector_count; - if (geometry.sector_count == 0) - return RES_ERROR; - } - else if (ctrl == GET_SECTOR_SIZE) - { - struct rt_device_blk_geometry geometry; + *(DWORD *)buff = geometry.sector_count; + if (geometry.sector_count == 0) + return RES_ERROR; + } + else if (ctrl == GET_SECTOR_SIZE) + { + struct rt_device_blk_geometry geometry; - rt_memset(&geometry, 0, sizeof(geometry)); - rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); + rt_memset(&geometry, 0, sizeof(geometry)); + rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); - *(WORD *)buff = (WORD)(geometry.bytes_per_sector); - } - else if (ctrl == GET_BLOCK_SIZE) /* Get erase block size in unit of sectors (DWORD) */ - { - struct rt_device_blk_geometry geometry; + *(WORD *)buff = (WORD)(geometry.bytes_per_sector); + } + else if (ctrl == GET_BLOCK_SIZE) /* Get erase block size in unit of sectors (DWORD) */ + { + struct rt_device_blk_geometry geometry; - rt_memset(&geometry, 0, sizeof(geometry)); - rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); + rt_memset(&geometry, 0, sizeof(geometry)); + rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); - *(DWORD *)buff = geometry.block_size/geometry.bytes_per_sector; - } - else if (ctrl == CTRL_SYNC) - { - rt_device_control(device, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL); - } - else if (ctrl == CTRL_ERASE_SECTOR) - { - rt_device_control(device, RT_DEVICE_CTRL_BLK_ERASE, buff); - } - - return RES_OK; + *(DWORD *)buff = geometry.block_size / geometry.bytes_per_sector; + } + else if (ctrl == CTRL_SYNC) + { + rt_device_control(device, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL); + } + else if (ctrl == CTRL_ERASE_SECTOR) + { + rt_device_control(device, RT_DEVICE_CTRL_BLK_ERASE, buff); + } + + return RES_OK; } rt_time_t get_fattime(void) { - return 0; + return 0; } #if _FS_REENTRANT @@ -874,14 +874,14 @@ int ff_del_syncobj(_SYNC_t m) int ff_req_grant(_SYNC_t m) { if (rt_mutex_take(m, _FS_TIMEOUT) == RT_EOK) - return RT_TRUE; + return RT_TRUE; return RT_FALSE; } void ff_rel_grant(_SYNC_t m) { - rt_mutex_release(m); + rt_mutex_release(m); } #endif @@ -889,13 +889,13 @@ void ff_rel_grant(_SYNC_t m) /* Memory functions */ #if _USE_LFN == 3 /* Allocate memory block */ -void* ff_memalloc (UINT size) +void *ff_memalloc(UINT size) { return rt_malloc(size); } /* Free memory block */ -void ff_memfree (void* mem) +void ff_memfree(void *mem) { rt_free(mem); } From 4bc0347b114e65ad68fd8d6a4a0201686af4a6b9 Mon Sep 17 00:00:00 2001 From: prife Date: Tue, 8 Jan 2013 20:30:57 +0800 Subject: [PATCH 3/3] update dfs_xxx_mkfs in jffs2 nand uffs.c to use new args --- components/dfs/filesystems/jffs2/dfs_jffs2.c | 2 +- components/dfs/filesystems/uffs/dfs_uffs.c | 1314 +++++++++--------- 2 files changed, 657 insertions(+), 659 deletions(-) diff --git a/components/dfs/filesystems/jffs2/dfs_jffs2.c b/components/dfs/filesystems/jffs2/dfs_jffs2.c index 8bd483e9a..04022f4cc 100644 --- a/components/dfs/filesystems/jffs2/dfs_jffs2.c +++ b/components/dfs/filesystems/jffs2/dfs_jffs2.c @@ -222,7 +222,7 @@ static int dfs_jffs2_unmount(struct dfs_filesystem* fs) return -DFS_STATUS_ENOENT; } -static int dfs_jffs2_mkfs(const char* device_name) +static int dfs_jffs2_mkfs(rt_device_t dev_id) { /* just erase all blocks on this nand partition */ return -DFS_STATUS_ENOSYS; diff --git a/components/dfs/filesystems/uffs/dfs_uffs.c b/components/dfs/filesystems/uffs/dfs_uffs.c index d4997faa9..607291005 100644 --- a/components/dfs/filesystems/uffs/dfs_uffs.c +++ b/components/dfs/filesystems/uffs/dfs_uffs.c @@ -1,658 +1,656 @@ -/* - * File : rtthread.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006-2012, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2011-10-22 prife the first version - * 2012-03-28 prife use mtd device interface - * 2012-04-05 prife update uffs with official repo and use uffs_UnMount/Mount -*/ -#include - -#include -#include -#include -#include "dfs_uffs.h" - -#include "uffs/uffs_fd.h" /* posix file api is here */ -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_mem.h" -#include "uffs/uffs_utils.h" - -/* - * RT-Thread DFS Interface for uffs - */ -#define UFFS_DEVICE_MAX 2 /* the max partions on a nand deivce*/ -#define UFFS_MOUNT_PATH_MAX 128 /* the mount point max length */ -#define FILE_PATH_MAX 256 /* the longest file path */ - -struct _nand_dev -{ - struct rt_mtd_nand_device * dev; - struct uffs_StorageAttrSt storage; - uffs_Device uffs_dev; - uffs_MountTable mount_table; - char mount_path[UFFS_MOUNT_PATH_MAX]; - void * data; /* when uffs use static buf, it will save ptr here */ -}; -/* make sure the following struct var had been initilased to 0! */ -static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0}; - -static int uffs_result_to_dfs(int result) -{ - int status = -1; - - result = result < 0 ? -result : result; - switch (result) - { - case UENOERR:/** no error */ - break; - case UEACCES:/** Tried to open read-only file for writing, or files sharing mode - does not allow specified operations, or given path is directory */ - status = -DFS_STATUS_EINVAL; - break;/* no suitable */ - case UEEXIST: /** _O_CREAT and _O_EXCL flags specified, but filename already exists */ - status = -DFS_STATUS_EEXIST; - break; - case UEINVAL: /** Invalid oflag or pmode argument */ - status = -DFS_STATUS_EINVAL; - break; - case UEMFILE: /** No more file handles available(too many open files) */ - status = -1; - break; - case UENOENT: /** file or path not found */ - status = -DFS_STATUS_ENOENT; - break; - case UETIME: /** can't set file time */ - status = -1; - break; - case UEBADF: /** invalid file handle */ - status = -DFS_STATUS_EBADF; - break; - case UENOMEM:/** no enough memory */ - status = -DFS_STATUS_ENOSPC; - break; - case UEIOERR: /** I/O error from lower level flash operation */ - status = -DFS_STATUS_EIO; - break; - case UENOTDIR: /** Not a directory */ - status = -DFS_STATUS_ENOTDIR; - break; - case UEISDIR: /** Is a directory */ - status = -DFS_STATUS_EISDIR; - break; - case UEUNKNOWN_ERR: - default: - status = -1; - break; /* unknown error! */ - } - - return status; -} - -static URET _device_init(uffs_Device *dev) -{ - dev->attr->_private = NULL; // hook nand_chip data structure to attr->_private - dev->ops = (struct uffs_FlashOpsSt *)&nand_ops; - - return U_SUCC; -} - -static URET _device_release(uffs_Device *dev) -{ - return U_SUCC; -} - -static int init_uffs_fs( - struct _nand_dev * nand_part) -{ - uffs_MountTable * mtb; - struct rt_mtd_nand_device * nand; - struct uffs_StorageAttrSt * flash_storage; - - mtb = &nand_part->mount_table; - nand = nand_part->dev; - flash_storage = &nand_part->storage; - - /* setup nand storage attributes */ - uffs_setup_storage(flash_storage, nand); - - /* register mount table */ - if(mtb->dev) - { - /* set memory allocator for uffs */ -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 - uffs_MemSetupSystemAllocator(&mtb->dev->mem); -#endif - /* setup device init/release entry */ - mtb->dev->Init = _device_init; - mtb->dev->Release = _device_release; - mtb->dev->attr = flash_storage; - - uffs_RegisterMountTable(mtb); - } - /* mount uffs partion on nand device */ - return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1; -} - -static int dfs_uffs_mount( - struct dfs_filesystem* fs, - unsigned long rwflag, - const void* data) -{ - rt_base_t index; - uffs_MountTable * mount_part; - struct rt_mtd_nand_device * dev; - - RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1)); - dev = RT_MTD_NAND_DEVICE(fs->dev_id); - - /*1. find a empty entry in partition table */ - for (index = 0; index < UFFS_DEVICE_MAX ; index ++) - { - if (nand_part[index].dev == RT_NULL) - break; - } - if (index == UFFS_DEVICE_MAX) - return -DFS_STATUS_ENOENT; - - /*2. fill partition structure */ - nand_part[index].dev = dev; - - /* make a right mount path for uffs, end with '/' */ - rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path); - if (nand_part[index].mount_path[1] == '/') - nand_part[index].mount_path[1] = 0; - - mount_part = &(nand_part[index].mount_table); - mount_part->mount = nand_part[index].mount_path; - mount_part->dev = &(nand_part[index].uffs_dev); - rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy. - mount_part->dev->_private = dev; /* save dev_id into uffs */ - mount_part->start_block = dev->block_start; - mount_part->end_block = dev->block_end; - /*3. mount uffs */ - if (init_uffs_fs(&nand_part[index]) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - return 0; -} - -static int dfs_uffs_unmount(struct dfs_filesystem* fs) -{ - rt_base_t index; - int result; - - /* find the device index and then unmount it */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id)) - { - nand_part[index].dev = RT_NULL; - result = uffs_UnMount(nand_part[index].mount_path); - if (result != U_SUCC) - break; - - result = uffs_UnRegisterMountTable(& nand_part[index].mount_table); - return (result == U_SUCC) ? DFS_STATUS_OK : -1; - } - } - return -DFS_STATUS_ENOENT; -} - -static int dfs_uffs_mkfs(const char* device_name) -{ - rt_base_t index; - rt_uint32_t block; - struct rt_mtd_nand_device * mtd; - - /*1. find the device index */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (rt_strncmp(nand_part[index].dev->parent.parent.name, - device_name, RT_NAME_MAX) == 0) - break; - } - - if (index == UFFS_DEVICE_MAX) - { - /* can't find device driver */ - rt_kprintf("can not find device driver: %s\n", device_name); - return -DFS_STATUS_ENOENT; - } - - /*2. then unmount the partition */ - uffs_Mount(nand_part[index].mount_path); - mtd = nand_part[index].dev; - - /*3. erase all blocks on the partition */ - block = mtd->block_start; - for (; block <= mtd->block_end; block++) - { - rt_mtd_nand_erase_block(mtd, block); - if (rt_mtd_nand_check_block(mtd, block) != RT_EOK) - { - rt_kprintf("found bad block %d\n", block); - rt_mtd_nand_mark_badblock(mtd, block); - } - } - - /*4. remount it */ - if (init_uffs_fs(&nand_part[index]) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - return DFS_STATUS_OK; -} - -static int dfs_uffs_statfs(struct dfs_filesystem* fs, - struct statfs *buf) -{ - rt_base_t index; - struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id); - - RT_ASSERT(mtd != RT_NULL); - - /* find the device index */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (nand_part[index].dev == (void *)mtd) - break; - } - if (index == UFFS_DEVICE_MAX) - return -DFS_STATUS_ENOENT; - - buf->f_bsize = mtd->page_size; - buf->f_blocks = mtd->pages_per_block* - (mtd->block_end - mtd->block_start + 1); - buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev) / mtd->page_size; - - return 0; -} - -static int dfs_uffs_open(struct dfs_fd* file) -{ - int fd; - int oflag, mode; - char * file_path; - - oflag = file->flags; - if (oflag & DFS_O_DIRECTORY) /* operations about dir */ - { - uffs_DIR * dir; - - if (oflag & DFS_O_CREAT) /* create a dir*/ - { - if (uffs_mkdir(file->path) < 0) - return uffs_result_to_dfs(uffs_get_error()); - } - /* open dir */ - file_path = rt_malloc(FILE_PATH_MAX); - if(file_path == RT_NULL) - return -DFS_STATUS_ENOMEM; - - if (file->path[0] == '/' && !(file->path[1] == 0)) - rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path); - else - { - file_path[0] = '/'; - file_path[1] = 0; - } - - dir = uffs_opendir(file_path); - - if (dir == RT_NULL) - { - rt_free(file_path); - return uffs_result_to_dfs(uffs_get_error()); - } - /* save this pointer,will used by dfs_uffs_getdents*/ - file->data = dir; - rt_free(file_path); - return DFS_STATUS_OK; - } - /* regular file operations */ - /* int uffs_open(const char *name, int oflag, ...); what is this? - * uffs_open can open dir!! **/ - mode = 0; - if (oflag & DFS_O_RDONLY) mode |= UO_RDONLY; - if (oflag & DFS_O_WRONLY) mode |= UO_WRONLY; - if (oflag & DFS_O_RDWR) mode |= UO_RDWR; - /* Opens the file, if it is existing. If not, a new file is created. */ - if (oflag & DFS_O_CREAT) mode |= UO_CREATE; - /* Creates a new file. If the file is existing, it is truncated and overwritten. */ - if (oflag & DFS_O_TRUNC) mode |= UO_TRUNC; - /* Creates a new file. The function fails if the file is already existing. */ - if (oflag & DFS_O_EXCL) mode |= UO_EXCL; - - fd = uffs_open(file->path, mode); - if (fd < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - - /* save this pointer, it will be used when calling read()£¬write(), - * flush(), seek(), and will be free when calling close()*/ - - file->data = (void *)fd; - file->pos = uffs_seek(fd, 0, USEEK_CUR); - file->size = uffs_seek(fd, 0, USEEK_END); - uffs_seek(fd, file->pos, USEEK_SET); - - if (oflag & DFS_O_APPEND) - { - file->pos = uffs_seek(fd, 0, USEEK_END); - } - return 0; -} - -static int dfs_uffs_close(struct dfs_fd* file) -{ - int oflag; - int fd; - - oflag = file->flags; - if (oflag & DFS_O_DIRECTORY) - { - /* operations about dir */ - if (uffs_closedir((uffs_DIR *)(file->data)) < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; - } - /* regular file operations */ - fd = (int)(file->data); - - if (uffs_close(fd) == 0) - return 0; - - return uffs_result_to_dfs(uffs_get_error()); -} - -static int dfs_uffs_ioctl(struct dfs_fd * file, int cmd, void* args) -{ - return -DFS_STATUS_ENOSYS; -} - -static int dfs_uffs_read(struct dfs_fd * file, void* buf, rt_size_t len) -{ - int fd; - int char_read; - - fd = (int)(file->data); - char_read = uffs_read(fd, buf, len); - if (char_read < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* update position */ - file->pos = uffs_seek(fd, 0, USEEK_CUR); - return char_read; -} - -static int dfs_uffs_write(struct dfs_fd* file, - const void* buf, - rt_size_t len) -{ - int fd; - int char_write; - - fd = (int)(file->data); - - char_write = uffs_write(fd, buf, len); - if (char_write < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* update position */ - file->pos = uffs_seek(fd, 0, USEEK_CUR); - return char_write; -} - -static int dfs_uffs_flush(struct dfs_fd* file) -{ - int fd; - int result; - - fd = (int)(file->data); - - result = uffs_flush(fd); - if (result < 0 ) - return uffs_result_to_dfs(uffs_get_error()); - return 0; -} - -int uffs_seekdir(uffs_DIR *dir, long offset) -{ - int i = 0; - - while(i < offset) - { - if (uffs_readdir(dir) == RT_NULL) - return -1; - i++; - } - return 0; -} - - -static int dfs_uffs_seek(struct dfs_fd* file, - rt_off_t offset) -{ - int result; - - /* set offset as current offset */ - if (file->type == FT_DIRECTORY) - { - uffs_rewinddir((uffs_DIR *)(file->data)); - result = uffs_seekdir((uffs_DIR *)(file->data), offset/sizeof(struct dirent)); - if (result >= 0) - { - file->pos = offset; - return offset; - } - } - else if (file->type == FT_REGULAR) - { - result = uffs_seek((int)(file->data), offset, USEEK_SET); - if (result >= 0) - return offset; - } - - return uffs_result_to_dfs(uffs_get_error()); -} - -/* return the size of struct dirent*/ -static int dfs_uffs_getdents( - struct dfs_fd* file, - struct dirent* dirp, - rt_uint32_t count) -{ - rt_uint32_t index; - char * file_path; - struct dirent* d; - uffs_DIR* dir; - struct uffs_dirent * uffs_d; - - dir = (uffs_DIR*)(file->data); - RT_ASSERT(dir != RT_NULL); - - /* round count, count is always 1 */ - count = (count / sizeof(struct dirent)) * sizeof(struct dirent); - if (count == 0) return -DFS_STATUS_EINVAL; - - /* allocate file name */ - file_path = rt_malloc(FILE_PATH_MAX); - if (file_path == RT_NULL) - return -DFS_STATUS_ENOMEM; - - index = 0; - /* usually, the while loop should only be looped only once! */ - while (1) - { - struct uffs_stat s; - - d = dirp + index; - - uffs_d = uffs_readdir(dir); - if (uffs_d == RT_NULL) - { - rt_free(file_path); - return (uffs_result_to_dfs(uffs_get_error())); - } - - if (file->path[0] == '/' && !(file->path[1] == 0)) - rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name); - else - rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX); - - uffs_stat(file_path, &s); - switch(s.st_mode & US_IFMT) /* file type mark */ - { - case US_IFREG: /* directory */ - d->d_type = DFS_DT_REG; - break; - case US_IFDIR: /* regular file */ - d->d_type = DFS_DT_DIR; - break; - case US_IFLNK: /* symbolic link */ - case US_IREAD: /* read permission */ - case US_IWRITE:/* write permission */ - default: - d->d_type = DFS_DT_UNKNOWN; - break; - } - - /* write the rest args of struct dirent* dirp */ - d->d_namlen = rt_strlen(uffs_d->d_name); - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1); - - index ++; - if (index * sizeof(struct dirent) >= count) - break; - } - - /* free file name buf */ - rt_free(file_path); - - if (index == 0) - return uffs_result_to_dfs(uffs_get_error()); - - file->pos += index * sizeof(struct dirent); - - return index * sizeof(struct dirent); -} - -static int dfs_uffs_unlink(struct dfs_filesystem* fs, const char* path) -{ - int result; - struct uffs_stat s; - - /* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */ - if (uffs_lstat(path, &s) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - - switch(s.st_mode & US_IFMT) - { - case US_IFREG: - result = uffs_remove(path); - break; - case US_IFDIR: - result = uffs_rmdir(path); - break; - default: - /* unknown file type */ - return -1; - } - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; -} - -static int dfs_uffs_rename( - struct dfs_filesystem* fs, - const char* oldpath, - const char* newpath) -{ - int result; - - result = uffs_rename(oldpath, newpath); - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; -} - -static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) -{ - int result; - struct uffs_stat s; - struct rt_mtd_nand_device * mtd; - - result = uffs_stat(path, &s); - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* convert uffs stat to dfs stat structure */ - /* FIXME, these field may not be the same */ - st->st_dev = 0; - st->st_mode = s.st_mode; - st->st_size = s.st_size; - st->st_mtime = s.st_mtime; - - mtd = RT_MTD_NAND_DEVICE(fs->dev_id); - st->st_blksize = mtd->page_size; - - return 0; -} - -static const struct dfs_filesystem_operation dfs_uffs_ops = -{ - "uffs", /* file system type: uffs */ -#if RTTHREAD_VERSION >= 10100 - DFS_FS_FLAG_FULLPATH, -#else -#error "uffs can only work with rtthread whose version should >= 1.01\n" -#endif - dfs_uffs_mount, - dfs_uffs_unmount, - dfs_uffs_mkfs, - dfs_uffs_statfs, - - dfs_uffs_open, - dfs_uffs_close, - dfs_uffs_ioctl, - dfs_uffs_read, - dfs_uffs_write, - dfs_uffs_flush, - dfs_uffs_seek, - dfs_uffs_getdents, - dfs_uffs_unlink, - dfs_uffs_stat, - dfs_uffs_rename, -}; - -int dfs_uffs_init(void) -{ - /* register uffs file system */ - dfs_register(&dfs_uffs_ops); - - if (uffs_InitObjectBuf() == U_SUCC) - { - if (uffs_DirEntryBufInit() == U_SUCC) - { - uffs_InitGlobalFsLock(); - return RT_EOK; - } - } - return -RT_ERROR; -} +/* + * File : rtthread.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2012, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2011-10-22 prife the first version + * 2012-03-28 prife use mtd device interface + * 2012-04-05 prife update uffs with official repo and use uffs_UnMount/Mount +*/ +#include + +#include +#include +#include +#include "dfs_uffs.h" + +#include "uffs/uffs_fd.h" /* posix file api is here */ +#include "uffs/uffs_mtb.h" +#include "uffs/uffs_mem.h" +#include "uffs/uffs_utils.h" + +/* + * RT-Thread DFS Interface for uffs + */ +#define UFFS_DEVICE_MAX 2 /* the max partions on a nand deivce*/ +#define UFFS_MOUNT_PATH_MAX 128 /* the mount point max length */ +#define FILE_PATH_MAX 256 /* the longest file path */ + +struct _nand_dev +{ + struct rt_mtd_nand_device * dev; + struct uffs_StorageAttrSt storage; + uffs_Device uffs_dev; + uffs_MountTable mount_table; + char mount_path[UFFS_MOUNT_PATH_MAX]; + void * data; /* when uffs use static buf, it will save ptr here */ +}; +/* make sure the following struct var had been initilased to 0! */ +static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0}; + +static int uffs_result_to_dfs(int result) +{ + int status = -1; + + result = result < 0 ? -result : result; + switch (result) + { + case UENOERR:/** no error */ + break; + case UEACCES:/** Tried to open read-only file for writing, or files sharing mode + does not allow specified operations, or given path is directory */ + status = -DFS_STATUS_EINVAL; + break;/* no suitable */ + case UEEXIST: /** _O_CREAT and _O_EXCL flags specified, but filename already exists */ + status = -DFS_STATUS_EEXIST; + break; + case UEINVAL: /** Invalid oflag or pmode argument */ + status = -DFS_STATUS_EINVAL; + break; + case UEMFILE: /** No more file handles available(too many open files) */ + status = -1; + break; + case UENOENT: /** file or path not found */ + status = -DFS_STATUS_ENOENT; + break; + case UETIME: /** can't set file time */ + status = -1; + break; + case UEBADF: /** invalid file handle */ + status = -DFS_STATUS_EBADF; + break; + case UENOMEM:/** no enough memory */ + status = -DFS_STATUS_ENOSPC; + break; + case UEIOERR: /** I/O error from lower level flash operation */ + status = -DFS_STATUS_EIO; + break; + case UENOTDIR: /** Not a directory */ + status = -DFS_STATUS_ENOTDIR; + break; + case UEISDIR: /** Is a directory */ + status = -DFS_STATUS_EISDIR; + break; + case UEUNKNOWN_ERR: + default: + status = -1; + break; /* unknown error! */ + } + + return status; +} + +static URET _device_init(uffs_Device *dev) +{ + dev->attr->_private = NULL; // hook nand_chip data structure to attr->_private + dev->ops = (struct uffs_FlashOpsSt *)&nand_ops; + + return U_SUCC; +} + +static URET _device_release(uffs_Device *dev) +{ + return U_SUCC; +} + +static int init_uffs_fs( + struct _nand_dev * nand_part) +{ + uffs_MountTable * mtb; + struct rt_mtd_nand_device * nand; + struct uffs_StorageAttrSt * flash_storage; + + mtb = &nand_part->mount_table; + nand = nand_part->dev; + flash_storage = &nand_part->storage; + + /* setup nand storage attributes */ + uffs_setup_storage(flash_storage, nand); + + /* register mount table */ + if(mtb->dev) + { + /* set memory allocator for uffs */ +#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 + uffs_MemSetupSystemAllocator(&mtb->dev->mem); +#endif + /* setup device init/release entry */ + mtb->dev->Init = _device_init; + mtb->dev->Release = _device_release; + mtb->dev->attr = flash_storage; + + uffs_RegisterMountTable(mtb); + } + /* mount uffs partion on nand device */ + return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1; +} + +static int dfs_uffs_mount( + struct dfs_filesystem* fs, + unsigned long rwflag, + const void* data) +{ + rt_base_t index; + uffs_MountTable * mount_part; + struct rt_mtd_nand_device * dev; + + RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1)); + dev = RT_MTD_NAND_DEVICE(fs->dev_id); + + /*1. find a empty entry in partition table */ + for (index = 0; index < UFFS_DEVICE_MAX ; index ++) + { + if (nand_part[index].dev == RT_NULL) + break; + } + if (index == UFFS_DEVICE_MAX) + return -DFS_STATUS_ENOENT; + + /*2. fill partition structure */ + nand_part[index].dev = dev; + + /* make a right mount path for uffs, end with '/' */ + rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path); + if (nand_part[index].mount_path[1] == '/') + nand_part[index].mount_path[1] = 0; + + mount_part = &(nand_part[index].mount_table); + mount_part->mount = nand_part[index].mount_path; + mount_part->dev = &(nand_part[index].uffs_dev); + rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy. + mount_part->dev->_private = dev; /* save dev_id into uffs */ + mount_part->start_block = dev->block_start; + mount_part->end_block = dev->block_end; + /*3. mount uffs */ + if (init_uffs_fs(&nand_part[index]) < 0) + { + return uffs_result_to_dfs(uffs_get_error()); + } + return 0; +} + +static int dfs_uffs_unmount(struct dfs_filesystem* fs) +{ + rt_base_t index; + int result; + + /* find the device index and then unmount it */ + for (index = 0; index < UFFS_DEVICE_MAX; index++) + { + if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id)) + { + nand_part[index].dev = RT_NULL; + result = uffs_UnMount(nand_part[index].mount_path); + if (result != U_SUCC) + break; + + result = uffs_UnRegisterMountTable(& nand_part[index].mount_table); + return (result == U_SUCC) ? DFS_STATUS_OK : -1; + } + } + return -DFS_STATUS_ENOENT; +} + +static int dfs_uffs_mkfs(rt_device_t dev_id) +{ + rt_base_t index; + rt_uint32_t block; + struct rt_mtd_nand_device * mtd; + + /*1. find the device index */ + for (index = 0; index < UFFS_DEVICE_MAX; index++) + { + if (nand_part[index].dev == (struct rt_mtd_nand_device *)dev_id) + break; + } + + if (index == UFFS_DEVICE_MAX) + { + /* can't find device driver */ + return -DFS_STATUS_ENOENT; + } + + /*2. then unmount the partition */ + uffs_Mount(nand_part[index].mount_path); + mtd = nand_part[index].dev; + + /*3. erase all blocks on the partition */ + block = mtd->block_start; + for (; block <= mtd->block_end; block++) + { + rt_mtd_nand_erase_block(mtd, block); + if (rt_mtd_nand_check_block(mtd, block) != RT_EOK) + { + rt_kprintf("found bad block %d\n", block); + rt_mtd_nand_mark_badblock(mtd, block); + } + } + + /*4. remount it */ + if (init_uffs_fs(&nand_part[index]) < 0) + { + return uffs_result_to_dfs(uffs_get_error()); + } + return DFS_STATUS_OK; +} + +static int dfs_uffs_statfs(struct dfs_filesystem* fs, + struct statfs *buf) +{ + rt_base_t index; + struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id); + + RT_ASSERT(mtd != RT_NULL); + + /* find the device index */ + for (index = 0; index < UFFS_DEVICE_MAX; index++) + { + if (nand_part[index].dev == (void *)mtd) + break; + } + if (index == UFFS_DEVICE_MAX) + return -DFS_STATUS_ENOENT; + + buf->f_bsize = mtd->page_size; + buf->f_blocks = mtd->pages_per_block* + (mtd->block_end - mtd->block_start + 1); + buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev) / mtd->page_size; + + return 0; +} + +static int dfs_uffs_open(struct dfs_fd* file) +{ + int fd; + int oflag, mode; + char * file_path; + + oflag = file->flags; + if (oflag & DFS_O_DIRECTORY) /* operations about dir */ + { + uffs_DIR * dir; + + if (oflag & DFS_O_CREAT) /* create a dir*/ + { + if (uffs_mkdir(file->path) < 0) + return uffs_result_to_dfs(uffs_get_error()); + } + /* open dir */ + file_path = rt_malloc(FILE_PATH_MAX); + if(file_path == RT_NULL) + return -DFS_STATUS_ENOMEM; + + if (file->path[0] == '/' && !(file->path[1] == 0)) + rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path); + else + { + file_path[0] = '/'; + file_path[1] = 0; + } + + dir = uffs_opendir(file_path); + + if (dir == RT_NULL) + { + rt_free(file_path); + return uffs_result_to_dfs(uffs_get_error()); + } + /* save this pointer,will used by dfs_uffs_getdents*/ + file->data = dir; + rt_free(file_path); + return DFS_STATUS_OK; + } + /* regular file operations */ + /* int uffs_open(const char *name, int oflag, ...); what is this? + * uffs_open can open dir!! **/ + mode = 0; + if (oflag & DFS_O_RDONLY) mode |= UO_RDONLY; + if (oflag & DFS_O_WRONLY) mode |= UO_WRONLY; + if (oflag & DFS_O_RDWR) mode |= UO_RDWR; + /* Opens the file, if it is existing. If not, a new file is created. */ + if (oflag & DFS_O_CREAT) mode |= UO_CREATE; + /* Creates a new file. If the file is existing, it is truncated and overwritten. */ + if (oflag & DFS_O_TRUNC) mode |= UO_TRUNC; + /* Creates a new file. The function fails if the file is already existing. */ + if (oflag & DFS_O_EXCL) mode |= UO_EXCL; + + fd = uffs_open(file->path, mode); + if (fd < 0) + { + return uffs_result_to_dfs(uffs_get_error()); + } + + /* save this pointer, it will be used when calling read()£¬write(), + * flush(), seek(), and will be free when calling close()*/ + + file->data = (void *)fd; + file->pos = uffs_seek(fd, 0, USEEK_CUR); + file->size = uffs_seek(fd, 0, USEEK_END); + uffs_seek(fd, file->pos, USEEK_SET); + + if (oflag & DFS_O_APPEND) + { + file->pos = uffs_seek(fd, 0, USEEK_END); + } + return 0; +} + +static int dfs_uffs_close(struct dfs_fd* file) +{ + int oflag; + int fd; + + oflag = file->flags; + if (oflag & DFS_O_DIRECTORY) + { + /* operations about dir */ + if (uffs_closedir((uffs_DIR *)(file->data)) < 0) + return uffs_result_to_dfs(uffs_get_error()); + + return 0; + } + /* regular file operations */ + fd = (int)(file->data); + + if (uffs_close(fd) == 0) + return 0; + + return uffs_result_to_dfs(uffs_get_error()); +} + +static int dfs_uffs_ioctl(struct dfs_fd * file, int cmd, void* args) +{ + return -DFS_STATUS_ENOSYS; +} + +static int dfs_uffs_read(struct dfs_fd * file, void* buf, rt_size_t len) +{ + int fd; + int char_read; + + fd = (int)(file->data); + char_read = uffs_read(fd, buf, len); + if (char_read < 0) + return uffs_result_to_dfs(uffs_get_error()); + + /* update position */ + file->pos = uffs_seek(fd, 0, USEEK_CUR); + return char_read; +} + +static int dfs_uffs_write(struct dfs_fd* file, + const void* buf, + rt_size_t len) +{ + int fd; + int char_write; + + fd = (int)(file->data); + + char_write = uffs_write(fd, buf, len); + if (char_write < 0) + return uffs_result_to_dfs(uffs_get_error()); + + /* update position */ + file->pos = uffs_seek(fd, 0, USEEK_CUR); + return char_write; +} + +static int dfs_uffs_flush(struct dfs_fd* file) +{ + int fd; + int result; + + fd = (int)(file->data); + + result = uffs_flush(fd); + if (result < 0 ) + return uffs_result_to_dfs(uffs_get_error()); + return 0; +} + +int uffs_seekdir(uffs_DIR *dir, long offset) +{ + int i = 0; + + while(i < offset) + { + if (uffs_readdir(dir) == RT_NULL) + return -1; + i++; + } + return 0; +} + + +static int dfs_uffs_seek(struct dfs_fd* file, + rt_off_t offset) +{ + int result; + + /* set offset as current offset */ + if (file->type == FT_DIRECTORY) + { + uffs_rewinddir((uffs_DIR *)(file->data)); + result = uffs_seekdir((uffs_DIR *)(file->data), offset/sizeof(struct dirent)); + if (result >= 0) + { + file->pos = offset; + return offset; + } + } + else if (file->type == FT_REGULAR) + { + result = uffs_seek((int)(file->data), offset, USEEK_SET); + if (result >= 0) + return offset; + } + + return uffs_result_to_dfs(uffs_get_error()); +} + +/* return the size of struct dirent*/ +static int dfs_uffs_getdents( + struct dfs_fd* file, + struct dirent* dirp, + rt_uint32_t count) +{ + rt_uint32_t index; + char * file_path; + struct dirent* d; + uffs_DIR* dir; + struct uffs_dirent * uffs_d; + + dir = (uffs_DIR*)(file->data); + RT_ASSERT(dir != RT_NULL); + + /* round count, count is always 1 */ + count = (count / sizeof(struct dirent)) * sizeof(struct dirent); + if (count == 0) return -DFS_STATUS_EINVAL; + + /* allocate file name */ + file_path = rt_malloc(FILE_PATH_MAX); + if (file_path == RT_NULL) + return -DFS_STATUS_ENOMEM; + + index = 0; + /* usually, the while loop should only be looped only once! */ + while (1) + { + struct uffs_stat s; + + d = dirp + index; + + uffs_d = uffs_readdir(dir); + if (uffs_d == RT_NULL) + { + rt_free(file_path); + return (uffs_result_to_dfs(uffs_get_error())); + } + + if (file->path[0] == '/' && !(file->path[1] == 0)) + rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name); + else + rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX); + + uffs_stat(file_path, &s); + switch(s.st_mode & US_IFMT) /* file type mark */ + { + case US_IFREG: /* directory */ + d->d_type = DFS_DT_REG; + break; + case US_IFDIR: /* regular file */ + d->d_type = DFS_DT_DIR; + break; + case US_IFLNK: /* symbolic link */ + case US_IREAD: /* read permission */ + case US_IWRITE:/* write permission */ + default: + d->d_type = DFS_DT_UNKNOWN; + break; + } + + /* write the rest args of struct dirent* dirp */ + d->d_namlen = rt_strlen(uffs_d->d_name); + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1); + + index ++; + if (index * sizeof(struct dirent) >= count) + break; + } + + /* free file name buf */ + rt_free(file_path); + + if (index == 0) + return uffs_result_to_dfs(uffs_get_error()); + + file->pos += index * sizeof(struct dirent); + + return index * sizeof(struct dirent); +} + +static int dfs_uffs_unlink(struct dfs_filesystem* fs, const char* path) +{ + int result; + struct uffs_stat s; + + /* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */ + if (uffs_lstat(path, &s) < 0) + { + return uffs_result_to_dfs(uffs_get_error()); + } + + switch(s.st_mode & US_IFMT) + { + case US_IFREG: + result = uffs_remove(path); + break; + case US_IFDIR: + result = uffs_rmdir(path); + break; + default: + /* unknown file type */ + return -1; + } + if (result < 0) + return uffs_result_to_dfs(uffs_get_error()); + + return 0; +} + +static int dfs_uffs_rename( + struct dfs_filesystem* fs, + const char* oldpath, + const char* newpath) +{ + int result; + + result = uffs_rename(oldpath, newpath); + if (result < 0) + return uffs_result_to_dfs(uffs_get_error()); + + return 0; +} + +static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) +{ + int result; + struct uffs_stat s; + struct rt_mtd_nand_device * mtd; + + result = uffs_stat(path, &s); + if (result < 0) + return uffs_result_to_dfs(uffs_get_error()); + + /* convert uffs stat to dfs stat structure */ + /* FIXME, these field may not be the same */ + st->st_dev = 0; + st->st_mode = s.st_mode; + st->st_size = s.st_size; + st->st_mtime = s.st_mtime; + + mtd = RT_MTD_NAND_DEVICE(fs->dev_id); + st->st_blksize = mtd->page_size; + + return 0; +} + +static const struct dfs_filesystem_operation dfs_uffs_ops = +{ + "uffs", /* file system type: uffs */ +#if RTTHREAD_VERSION >= 10100 + DFS_FS_FLAG_FULLPATH, +#else +#error "uffs can only work with rtthread whose version should >= 1.01\n" +#endif + dfs_uffs_mount, + dfs_uffs_unmount, + dfs_uffs_mkfs, + dfs_uffs_statfs, + + dfs_uffs_open, + dfs_uffs_close, + dfs_uffs_ioctl, + dfs_uffs_read, + dfs_uffs_write, + dfs_uffs_flush, + dfs_uffs_seek, + dfs_uffs_getdents, + dfs_uffs_unlink, + dfs_uffs_stat, + dfs_uffs_rename, +}; + +int dfs_uffs_init(void) +{ + /* register uffs file system */ + dfs_register(&dfs_uffs_ops); + + if (uffs_InitObjectBuf() == U_SUCC) + { + if (uffs_DirEntryBufInit() == U_SUCC) + { + uffs_InitGlobalFsLock(); + return RT_EOK; + } + } + return -RT_ERROR; +}