summaryrefslogtreecommitdiff
path: root/filesystem/dfs/src
diff options
context:
space:
mode:
authorbernard.xiong <[email protected]>2009-07-02 22:48:23 +0000
committerbernard.xiong <[email protected]>2009-07-02 22:48:23 +0000
commitbda4730a9482c23083006abea939ee8d95d6ecff (patch)
tree83005121824bd50ac74e63688c0d5eac148665f8 /filesystem/dfs/src
parent80c72e66de0b00b1a6de3e3508366a4c3eee458d (diff)
import RT-Thread RTOS 0.3.x to Google SVN
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'filesystem/dfs/src')
-rw-r--r--filesystem/dfs/src/dfs_cache.c273
-rw-r--r--filesystem/dfs/src/dfs_fs.c362
-rw-r--r--filesystem/dfs/src/dfs_init.c92
-rw-r--r--filesystem/dfs/src/dfs_posix.c564
-rw-r--r--filesystem/dfs/src/dfs_raw.c668
-rw-r--r--filesystem/dfs/src/dfs_util.c297
6 files changed, 2256 insertions, 0 deletions
diff --git a/filesystem/dfs/src/dfs_cache.c b/filesystem/dfs/src/dfs_cache.c
new file mode 100644
index 0000000000..cd4deab415
--- /dev/null
+++ b/filesystem/dfs/src/dfs_cache.c
@@ -0,0 +1,273 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004 - 2009 www.rt-thread.org
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_cache.c, the LUT disk cache implementation
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2009-04-26 bernard The first version.
++------------------------------------------------------------------------------
+*/
+#include "dfs_cache.h"
+
+#define ioman_isReqRo(mode) ((mode)&(IOM_MODE_READONLY))
+#define ioman_isReqRw(mode) ((mode)&(IOM_MODE_READWRITE))
+#define ioman_isReqExp(mode) ((mode)&(IOM_MODE_EXP_REQ))
+
+rt_err_t ioman_init(IOManager* ioman)
+{
+ register rt_uint32_t index;
+ RT_ASSERT(ioman != RT_NULL);
+
+ ioman->numbuf = DFS_CACHE_MAX_NUM;
+
+ rt_memset(ioman->sector, 0,sizeof(ioman->sector));
+ rt_memset(ioman->status, 0,sizeof(ioman->status));
+ rt_memset(ioman->usage, 0, sizeof(ioman->usage));
+ rt_memset(ioman->ring_fifo, 0, sizeof(ioman->ring_fifo));
+ rt_memset(ioman->cache, 0, sizeof(ioman->cache));
+
+ /* init fifo */
+ for (index = 0; index < ioman->numbuf; index ++)
+ {
+ ioman->ring_fifo[index] = ioman->numbuf - index - 1;
+ }
+
+ return RT_EOK;
+}
+
+/*
+ * get the last fifo item and put it to the top of fifo ring
+ */
+static rt_uint8_t ioman_ring_fifo_swap(IOManager *ioman)
+{
+ rt_uint8_t bp;
+ rt_uint32_t index;
+
+ bp = ioman->ring_fifo[ioman->numbuf - 1];
+ for (index = ioman->numbuf - 1; index > 0; index --)
+ {
+ ioman->ring_fifo[index] = ioman->ring_fifo[index - 1];
+ }
+
+ ioman->ring_fifo[0] = bp;
+
+ return bp;
+}
+
+/*
+ * get the index of bp in fifo ring and then put it to the top of
+ * fifo ring
+ */
+static void ioman_ring_fifo_relocate(IOManager *ioman, rt_uint32_t bp)
+{
+ rt_uint32_t bp_index = 0;
+ register rt_uint32_t index;
+
+ /* find bp in fifo ring */
+ for (index = 0; index < ioman->numbuf; index ++)
+ {
+ if (ioman->ring_fifo[index] == bp)
+ {
+ bp_index = index;
+ break;
+ }
+ }
+
+ /* not found bp in fifo ring */
+ if (index == ioman->numbuf) return;
+
+ /* move the bp to the top of fifo ring */
+ for (index = bp_index; index > 0; index --)
+ {
+ ioman->ring_fifo[index] = ioman->ring_fifo[index - 1];
+ }
+ ioman->ring_fifo[0] = bp;
+}
+
+/*
+ * get last bp in fifo ring
+ */
+rt_inline rt_uint8_t ioman_ring_fifo_last(IOManager *ioman)
+{
+ RT_ASSERT(ioman != RT_NULL);
+ return ioman->ring_fifo[ioman->numbuf - 1];
+}
+
+static rt_err_t ioman_readSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf)
+{
+ rt_err_t result;
+
+ RT_ASSERT(buf != RT_NULL);
+
+ result = rt_device_read(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE);
+ if (result == DFS_SECTOR_SIZE) return RT_EOK;
+
+ return -RT_ERROR;
+}
+
+static rt_err_t ioman_writeSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf)
+{
+ rt_err_t result;
+
+ RT_ASSERT(buf != RT_NULL);
+
+ result = rt_device_write(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE);
+ if (result == DFS_SECTOR_SIZE) return RT_EOK;
+
+ return -RT_ERROR;
+}
+
+static rt_int32_t ioman_findSectorInCache(IOManager *ioman, rt_uint32_t address)
+{
+ rt_uint32_t c;
+
+ for(c=0;c<ioman->numbuf;c++)
+ {
+ if((ioman->status[c] & (1 << IOMAN_STATUS_ATTR_VALIDDATA)) &&
+ ioman->sector[c] == address)
+ return (c);
+ }
+
+ return -RT_ERROR;
+}
+
+static rt_err_t ioman_flushSector(IOManager *ioman, rt_uint32_t bp)
+{
+ rt_err_t result;
+
+ RT_ASSERT(ioman != RT_NULL);
+
+ result = ioman_writeSector(ioman, ioman->sector[bp], &ioman->cache[bp][0]);
+ if (result == RT_EOK)
+ {
+ /* set status */
+ ioman->status[bp] &= ~(1 << IOMAN_STATUS_ATTR_WRITE);
+ }
+
+ return result;
+}
+
+rt_uint8_t* ioman_getSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t mode)
+{
+ rt_int32_t bp;
+
+ RT_ASSERT(ioman != RT_NULL);
+
+ bp = ioman_findSectorInCache(ioman, address);
+ if (bp != -RT_ERROR)
+ {
+ /* incress cache usage */
+ ioman->usage[bp] ++;
+
+ /* relocate bp in fifo ring */
+ ioman_ring_fifo_relocate(ioman, bp);
+
+ if (ioman_isReqRw(mode))
+ ioman->status[bp] |= (1 << IOMAN_STATUS_ATTR_WRITE);
+
+ return &(ioman->cache[bp][0]);
+ }
+
+ /* not find in cache, get the last bp in fifo ring */
+ bp = ioman_ring_fifo_last(ioman);
+ if ((ioman->status[bp] & (1 << IOMAN_STATUS_ATTR_WRITE)) &&
+ ioman->usage[bp] == 0)
+ {
+ /* it's a writable buffer, flush it */
+ ioman_flushSector(ioman, bp);
+ }
+
+ /* strip last bp in fifo ring */
+ bp = ioman_ring_fifo_swap(ioman);
+
+ /* read sector */
+ ioman_readSector(ioman, address, &ioman->cache[bp][0]);
+ ioman->sector[bp] = address;
+ ioman->usage [bp] = 1;
+ ioman->status[bp] = (1 << IOMAN_STATUS_ATTR_VALIDDATA);
+ if (ioman_isReqRw(mode))
+ ioman->status[bp] |= (1 << IOMAN_STATUS_ATTR_WRITE);
+
+ return &ioman->cache[bp][0];
+}
+
+rt_err_t ioman_releaseSector(IOManager *ioman, rt_uint8_t* buf)
+{
+ rt_uint32_t bp;
+
+ /* get buffer place */
+ bp = ((rt_uint32_t)buf - (rt_uint32_t)&ioman->cache[0]) / DFS_SECTOR_SIZE;
+
+ /* decrease usage */
+ if (ioman->usage[bp] > 0) ioman->usage[bp] --;
+ if (ioman->usage[bp] == 0)
+ {
+ if(ioman->status[bp] & (1 << IOMAN_STATUS_ATTR_WRITE))
+ {
+ ioman_flushSector(ioman,bp);
+ }
+ }
+
+ return RT_EOK;
+}
+
+rt_err_t ioman_flushRange(IOManager *ioman, rt_uint32_t address_low, rt_uint32_t address_high)
+{
+ rt_uint32_t c;
+
+ if(address_low > address_high)
+ {
+ c = address_low; address_low = address_high; address_high = c;
+ }
+
+ for(c = 0; c < ioman->numbuf; c++)
+ {
+ if((ioman->sector[c]>=address_low)
+ && (ioman->sector[c]<=address_high)
+ && (ioman->status[c] & (1 << IOMAN_STATUS_ATTR_WRITE)))
+ {
+ if(ioman_flushSector(ioman,c) != RT_EOK)
+ return -RT_ERROR;
+
+ /* remove writable status */
+ if(ioman->usage[c]==0) ioman->status[c] &= ~IOMAN_STATUS_ATTR_WRITE;
+ }
+ }
+
+ return RT_EOK;
+}
+
+/*
+ * read multi-sectors directly (none-cachable)
+ */
+rt_err_t ioman_directSectorRead(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector)
+{
+ rt_err_t result;
+
+ RT_ASSERT(buf != RT_NULL);
+
+ result = rt_device_read(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE * numsector);
+ if (result == DFS_SECTOR_SIZE * numsector) return RT_EOK;
+
+ return -RT_ERROR;
+}
+
+/*
+ * write multi-sectors directly (none-cachable)
+ */
+rt_err_t ioman_directSectorWrite(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector)
+{
+ rt_err_t result;
+
+ RT_ASSERT(buf != RT_NULL);
+
+ result = rt_device_write(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE * numsector);
+ if (result == DFS_SECTOR_SIZE * numsector) return RT_EOK;
+
+ return -RT_ERROR;
+}
diff --git a/filesystem/dfs/src/dfs_fs.c b/filesystem/dfs/src/dfs_fs.c
new file mode 100644
index 0000000000..f0ca291c24
--- /dev/null
+++ b/filesystem/dfs/src/dfs_fs.c
@@ -0,0 +1,362 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_fs.c, the filesystem related implementations of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-02-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_fs.h>
+#include <dfs_raw.h>
+#include <dfs_util.h>
+
+#include <string.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_register
++------------------------------------------------------------------------------
+| Description : registers a filesystem
+|
+| Parameters : ops, the implementation of filesystem
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_register(struct dfs_filesystem_operation* ops)
+{
+ int index;
+
+ rt_sem_take(filesystem_operation_table_lock, RT_WAITING_FOREVER);
+
+ /* check if this filesystem was already registered */
+ for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++)
+ {
+ if (filesystem_operation_table[index] != RT_NULL &&
+ strcmp(filesystem_operation_table[index]->name, ops->name) == 0)
+ goto err;
+ }
+
+ /* find out an empty filesystem type entry */
+ for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX && filesystem_operation_table[index] != RT_NULL;
+ index++) ;
+
+ /* filesystem type table full */
+ if (index == DFS_FILESYSTEM_TYPES_MAX) goto err;
+
+ /* save the filesystem's operations */
+ filesystem_operation_table[index] = ops;
+
+ rt_sem_release(filesystem_operation_table_lock);
+ return 0;
+
+err:
+ rt_sem_release(filesystem_operation_table_lock);
+ return -1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_filesystem_lookup
++------------------------------------------------------------------------------
+| Description : lookup the mounted filesystem on the specified path
+|
+| Parameters : path, the specified path string
+| Returns : the found filesystem
++------------------------------------------------------------------------------
+*/
+struct dfs_filesystem* dfs_filesystem_lookup(const char *path)
+{
+ struct dfs_filesystem* fs;
+ rt_uint32_t index, fspath, prefixlen;
+
+ fs = RT_NULL;
+ prefixlen = 0;
+
+ /* lock filesystem table */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* lookup it in the filesystem table */
+ for (index = 0; index < DFS_FILESYSTEMS_MAX + 1; index++)
+ {
+ fspath = strlen(filesystem_table[index].path);
+ if (fspath < prefixlen) continue;
+
+ if ((filesystem_table[index].ops != RT_NULL) &&
+ str_is_prefix(filesystem_table[index].path, path) == 0)
+ {
+ fs = &filesystem_table[index];
+ prefixlen = fspath;
+ }
+ }
+
+ rt_sem_release(filesystem_table_lock);
+ return fs;
+}
+
+rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* buf, rt_uint32_t pindex)
+{
+#define DPT_ADDRESS 0x1be /* device partition offset in Boot Sector */
+#define DPT_ITEM_SIZE 16 /* partition item size */
+
+ rt_uint8_t* dpt;
+ rt_uint8_t type;
+ rt_err_t result;
+
+ RT_ASSERT(part != RT_NULL);
+ RT_ASSERT(buf != RT_NULL);
+
+ result = RT_EOK;
+
+ dpt = buf + DPT_ADDRESS + pindex * DPT_ITEM_SIZE;
+
+ if ((*dpt != 0x80) && (*dpt != 0x00))
+ {
+ /* which is not a partition table */
+ result = -RT_ERROR;
+ return result;
+ }
+
+ /* get partition type */
+ type = *(dpt+4);
+
+ if (type != 0)
+ {
+ /* set partition type */
+ part->type = type;
+
+ /* get partition offset and size */
+ 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;
+
+#ifdef RT_USING_FINSH
+ rt_kprintf("part[%d], begin: %d, size: %d\n",
+ pindex, part->offset * 512, part->size* 512);
+#endif
+ }
+ else
+ {
+ result = -RT_ERROR;
+ }
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_mount
++------------------------------------------------------------------------------
+| Description : mount a filesystem to specified path
+|
+| Parameters : device_name, the implementation of filesystem
+| path,
+| filesystemtype,
+| rwflag,
+| data,
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_mount(const char* device_name, const char* path,
+ const char* filesystemtype, unsigned long rwflag, const
+ void* data)
+{
+ struct dfs_filesystem_operation* ops;
+ struct dfs_filesystem* fs;
+ char *fullpath=RT_NULL;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ rt_device_t dev_id;
+ int index;
+
+ /* open specific device */
+ dev_id = rt_device_find(device_name);
+ if (dev_id == RT_NULL)
+ {
+ /* no this device */
+ rt_set_errno(-DFS_STATUS_ENODEV);
+ return -1;
+ }
+
+ /* find out specific filesystem */
+ rt_sem_take(filesystem_operation_table_lock, RT_WAITING_FOREVER);
+ for ( index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++ )
+ {
+ if (strcmp(filesystem_operation_table[index]->name, filesystemtype) == 0)break;
+ }
+
+ /* can't find filesystem */
+ if ( index == DFS_FILESYSTEM_TYPES_MAX )
+ {
+ rt_set_errno(-DFS_STATUS_ENODEV);
+ rt_sem_release(filesystem_operation_table_lock);
+ return -1;
+ }
+ ops = filesystem_operation_table[index];
+ rt_sem_release(filesystem_operation_table_lock);
+
+ /* make full path for special file */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/') /* not an abstract path */
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+#endif
+ }
+
+ /* Check if the path exists or not, raw APIs call, fixme */
+ if ( (strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0) )
+ {
+ struct dfs_fd fd;
+
+ if ( dfile_raw_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 )
+ {
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+ }
+ dfile_raw_close(&fd);
+ }
+
+ /* check whether the file system mounted or not */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+ for (index =0; index < DFS_FILESYSTEMS_MAX; index++)
+ {
+ if ( filesystem_table[index].ops != RT_NULL &&
+ strcmp(filesystem_table[index].path, path) == 0 )
+ {
+ rt_set_errno(-DFS_STATUS_EINVAL);
+ goto err1;
+ }
+ }
+
+ /* find out en empty filesystem table entry */
+ for (index = 0; index < DFS_FILESYSTEMS_MAX && filesystem_table[index].ops != RT_NULL;
+ index++) ;
+ if ( index == DFS_FILESYSTEMS_MAX ) /* can't find en empty filesystem table entry */
+ {
+ rt_set_errno(-DFS_STATUS_EMMOUNT);
+ goto err1;
+ }
+
+ /* register file system */
+ fs = &(filesystem_table[index]);
+ strncpy(fs->path, fullpath, strlen(fullpath));
+ fs->ops = ops;
+ fs->dev_id = dev_id;
+ /* release filesystem_table lock */
+ rt_sem_release(filesystem_table_lock);
+
+ /* open device, but do not check the status of device */
+ rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDWR);
+
+ if ( ops->mount == RT_NULL ) /* there is no mount implementation */
+ {
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* clear filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+
+ rt_set_errno(-DFS_STATUS_ENOSYS);
+ return -1;
+ }
+ /* call mount of this filesystem */
+ else if ( ops->mount(fs) < 0 )
+ {
+ /* mount failed */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* close device */
+ rt_device_close(fs->dev_id);
+
+ /* clear filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+ }
+
+ return 0;
+
+err1:
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_unmount
++------------------------------------------------------------------------------
+| Description : unmount a filesystem
+|
+| Parameters :
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_unmount(const char *specialfile)
+{
+ char *fullpath;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ struct dfs_filesystem* fs = RT_NULL;
+
+ fullpath = (char*)specialfile;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, specialfile, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+#endif
+ }
+
+ /* lock filesystem table */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ fs = dfs_filesystem_lookup(fullpath);
+ if (fs != RT_NULL && fs->ops->unmount != RT_NULL && fs->ops->unmount(fs) < 0)
+ {
+ goto err1;
+ }
+
+ /* close device, but do not check the status of device */
+ rt_device_close(fs->dev_id);
+
+ /* clear this filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+
+ return 0;
+
+err1:
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+}
diff --git a/filesystem/dfs/src/dfs_init.c b/filesystem/dfs/src/dfs_init.c
new file mode 100644
index 0000000000..5b72da71ed
--- /dev/null
+++ b/filesystem/dfs/src/dfs_init.c
@@ -0,0 +1,92 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs.c, the implementation of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2002-12-31 ffxz The first version.
+| 2005-01-22 ffxz Clean up the code.
++------------------------------------------------------------------------------
+*/
+#include <dfs_def.h>
+#include <dfs_config.h>
+
+#include <dfs_fs.h>
+#include <dfs_raw.h>
+
+#include <string.h>
+
+/* Global variables */
+struct dfs_filesystem_operation* filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX + 1];
+struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX + 1];
+
+rt_sem_t filesystem_table_lock;
+rt_sem_t filesystem_operation_table_lock;
+
+#ifdef RT_USING_WORKDIR
+char working_directory[DFS_PATH_MAX + 1];
+rt_sem_t working_directory_lock;
+#endif
+
+struct dfs_fd fd_table[DFS_FD_MAX + 1];
+rt_sem_t fd_table_lock;
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_init
++------------------------------------------------------------------------------
+| Description : Inits the Device Filesystem
+| Parameters : null
+| Returns : null
++------------------------------------------------------------------------------
+*/
+void dfs_init()
+{
+ int index;
+
+ /* clear filesystem operations table */
+ for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX + 1; index++)
+ filesystem_operation_table[index] = RT_NULL;
+
+ /* create filesystem operations table lock */
+ filesystem_operation_table_lock = rt_sem_create("sem_fot", 1, RT_IPC_FLAG_FIFO);
+
+ /* clear filesystem table */
+ for (index = 0; index < DFS_FILESYSTEMS_MAX + 1; index++)
+ {
+ rt_memset(filesystem_table[index].path, 0, DFS_PATH_MAX + 1);
+
+ filesystem_table[index].ops = RT_NULL;
+ filesystem_table[index].dev_id = 0;
+ filesystem_table[index].block_id = 0;
+ filesystem_table[index].data = RT_NULL;
+ }
+
+ /* create filesystem table lock */
+ filesystem_table_lock = rt_sem_create("sem_fst", 1, RT_IPC_FLAG_FIFO);
+
+#ifdef RT_USING_WORKDIR
+ /* set current working directory */
+ strcpy(working_directory, "/");
+ working_directory_lock = rt_sem_create("sem_wd", 1, RT_IPC_FLAG_FIFO);
+#endif
+
+ /* clean fd table */
+ for ( index = 0; index < DFS_FD_MAX; index ++)
+ {
+ rt_memset(&fd_table[index], 0, sizeof(struct dfs_fd));
+ }
+
+ /* create fd table lock */
+ fd_table_lock = rt_sem_create("sem_fdt", 1, RT_IPC_FLAG_FIFO);
+
+#if defined(RT_USING_FINSH) && !defined(FINSH_USING_SYMTAB)
+ dfs_export_finsh();
+#endif
+}
+
diff --git a/filesystem/dfs/src/dfs_posix.c b/filesystem/dfs/src/dfs_posix.c
new file mode 100644
index 0000000000..6ea66a0e76
--- /dev/null
+++ b/filesystem/dfs/src/dfs_posix.c
@@ -0,0 +1,564 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_posix.c, the interface related implementations of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2009-05-27 Yi.qiu The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_posix.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : open
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int open(const char *file, int flags, int mode)
+{
+ int fd, result;
+ struct dfs_fd* d;
+
+ /* allocate a fd */
+ fd = fd_new();
+ if (fd < 0) return -1;
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, file, flags);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return fd;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : close
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int close(int d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d);
+
+ result = dfile_raw_close(fd);
+ fd_put(fd);
+ fd_put(fd);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : read
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int read(int fd, char *buf, int len)
+{
+ int result;
+ struct dfs_fd* d;
+
+ /* get the fd */
+ d = fd_get(fd);
+
+ result = dfile_raw_read(d, buf, len);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : write
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int write(int fd, char *buf, int len)
+{
+ int result;
+ struct dfs_fd* d;
+
+ /* get the fd */
+ d = fd_get(fd);
+
+ result = dfile_raw_write(d, buf, len);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : lseek
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int lseek(int fd, int offset, int dir)
+{
+ int result;
+ struct dfs_fd* d;
+
+ d = fd_get(fd);
+
+ switch (dir)
+ {
+ case DFS_SEEK_SET:
+ break;
+
+ case DFS_SEEK_CUR:
+ offset += d->pos;
+ break;
+
+ case DFS_SEEK_END:
+ offset = d->pos - offset;
+ break;
+ }
+
+ result = dfile_raw_lseek(d, offset);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rename
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int rename(const char* old, const char* new )
+{
+ int result;
+
+ result = dfile_raw_rename(old, new);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : unlink
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int unlink(const char *pathname)
+{
+ int result;
+
+ result = dfile_raw_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : stat
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int stat(const char *file, struct dfs_stat *buf)
+{
+ int result;
+
+ result = dfile_raw_stat(file, (struct dfs_stat *)buf);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : mkdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int mkdir (const char *path, rt_uint16_t mode)
+{
+ int fd;
+ struct dfs_fd* d;
+ int result;
+
+ fd = fd_new();
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, path, DFS_O_DIRECTORY | DFS_O_CREAT);
+ fd_put(d);
+ fd_put(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rmdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int rmdir(const char *pathname)
+{
+ int result;
+
+ result = dfile_raw_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : opendir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+DIR* opendir(const char* name)
+{
+ struct dfs_fd* d;
+ int fd, result;
+ DIR* t;
+
+ t = RT_NULL;
+
+ /* allocate a fd */
+ fd = fd_new();
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, name, DFS_O_RDONLY | DFS_O_DIRECTORY);
+ if (result >= 0)
+ {
+ /* open successfully */
+ t = (DIR *) rt_malloc (sizeof(DIR));
+ if (t == RT_NULL)
+ {
+ dfile_raw_close(d);
+ fd_put(d);
+ }
+ else t->fd = fd;
+ fd_put(d);
+ return t;
+ }
+
+ /* open failed */
+ fd_put(d);
+ fd_put(d);
+ rt_set_errno(result);
+
+ return RT_NULL;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : readdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+struct dfs_dirent* readdir(DIR *d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+
+ if (!d->num || (d->cur += ((struct dfs_dirent*)(d->buf + d->cur))->d_reclen) >= d->num)
+ {
+ result = dfile_raw_getdents(fd, (struct dfs_dirent*)d->buf, sizeof(d->buf) - 1);
+ if (result <= 0)
+ {
+ rt_set_errno(result);
+ fd_put(fd);
+
+ return RT_NULL;
+ }
+
+ d->num = result;
+ d->cur = 0;
+ }
+
+ fd_put(fd);
+ return (struct dfs_dirent*)(d->buf+d->cur);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : telldir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+rt_off_t telldir(DIR *d)
+{
+ struct dfs_fd* fd;
+ rt_off_t result;
+
+ fd = fd_get(d->fd);
+ result = fd->pos - d->num + d->cur;
+ fd_put(fd);
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : seekdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void seekdir(DIR *d, rt_off_t offset)
+{
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+ if (dfile_raw_lseek(fd, offset) >= 0) d->num = d->cur = 0;
+ fd_put(fd);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rewinddir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void rewinddir(DIR *d)
+{
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+ if (dfile_raw_lseek(fd, 0) >= 0) d->num = d->cur = 0;
+ fd_put(fd);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : closedir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int closedir(DIR* d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+
+ result = dfile_raw_close(fd);
+ fd_put(fd);
+
+ rt_free(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ else return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : chdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int chdir(const char *path)
+{
+ char* fullpath, full_path[DFS_PATH_MAX + 1];
+
+ if(path == RT_NULL || strlen(path) > DFS_PATH_MAX)
+ return -1;
+
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/' )
+ {
+ /* build full path */
+ fullpath = full_path;
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ strcpy(working_directory, fullpath);
+ rt_sem_release(working_directory_lock);
+#endif
+ }
+ else
+ {
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ rt_strncpy(working_directory, path, strlen(path) + 1);
+ working_directory[strlen(path)] = '\0';
+ rt_sem_release(working_directory_lock);
+#endif
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : chdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+char* getcwd(char *buf, rt_size_t size)
+{
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ rt_strncpy(buf, working_directory, size);
+ rt_sem_release(working_directory_lock);
+#endif
+ return buf;
+}
+
diff --git a/filesystem/dfs/src/dfs_raw.c b/filesystem/dfs/src/dfs_raw.c
new file mode 100644
index 0000000000..816197c5e9
--- /dev/null
+++ b/filesystem/dfs/src/dfs_raw.c
@@ -0,0 +1,668 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_raw.c, the raw APIs of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-02-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_raw.h>
+#include <dfs_util.h>
+#include <string.h>
+
+extern struct dfs_fd fd_table[DFS_FD_MAX + 1];
+extern rt_sem_t fd_table_lock;
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_new
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int fd_new(void)
+{
+ struct dfs_fd* d;
+ int idx;
+
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+
+ /* find an empty fd entry */
+ for (idx = 3; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++);
+
+ /* can't find an empty fd entry */
+ if (idx == DFS_FD_MAX)
+ {
+ rt_sem_release(fd_table_lock);
+ return -1;
+ }
+
+ d = &(fd_table[idx]);
+ d->ref_count = 1;
+ rt_sem_release(fd_table_lock);
+
+ return idx;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_get
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+struct dfs_fd* fd_get(int fd)
+{
+ struct dfs_fd* d;
+
+ if ( fd < 3 || fd > DFS_FD_MAX ) return RT_NULL;
+
+ d = &fd_table[fd];
+
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ d->ref_count ++;
+ rt_sem_release(fd_table_lock);
+
+ return d;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_put
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void fd_put(struct dfs_fd* fd)
+{
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ fd->ref_count --;
+ /* clear this fd entry */
+ if ( fd->ref_count == 0 )
+ {
+ rt_memset(fd, 0, sizeof(struct dfs_fd));
+ }
+ rt_sem_release(fd_table_lock);
+};
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_open
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_open(struct dfs_fd* fd, const char *path, int flags)
+{
+ struct dfs_filesystem* fs;
+ char *fullpath;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ int fspathlen, result;
+
+ /* parameter check */
+ if ( fd == RT_NULL ) return -DFS_STATUS_EINVAL;
+
+ /* make sure we have an absolute path */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = &full_path[0];
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath));
+
+ /* find filesystem */
+ fs = dfs_filesystem_lookup(fullpath);
+ if ( fs == RT_NULL ) return -DFS_STATUS_ENOENT;
+
+ dfs_log(DFS_DEBUG_INFO, ("open in filesystem:%s", fs->ops->name));
+ fd->fs = fs;
+
+ /* initilize the fd item */
+ fd->type = FT_REGULAR;
+ //fd->ref_count = 1;
+ fd->flags = flags;
+ fd->size = 0;
+ fd->pos = 0;
+
+ fspathlen = strlen(fs->path);
+ rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
+ if (*(fullpath + fspathlen) != '/') strcpy(fd->path, "/");
+ strcat(fd->path, fullpath + fspathlen);
+
+ /* specific file system open routine */
+ if (fs->ops->open == RT_NULL)
+ {
+ /* clear fd */
+ rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
+
+ fd->type = FT_REGULAR;
+ fd->ref_count = 0;
+ fd->fs = RT_NULL;
+ fd->flags = 0;
+ fd->size = 0;
+ fd->pos = 0;
+ fd->data = RT_NULL;
+
+ return -DFS_STATUS_ENOSYS;
+ }
+
+ if ((result = fs->ops->open(fd)) < 0)
+ {
+ /* clear fd */
+ fd->fs = RT_NULL;
+ fd->flags = 0;
+ fd->data = RT_NULL;
+
+ dfs_log(DFS_DEBUG_INFO, ("open failed"));
+
+ return result;
+ }
+
+ fd->flags |= DFS_F_OPEN;
+ if ( flags & DFS_O_DIRECTORY ) fd->flags |= DFS_F_DIRECTORY;
+
+ dfs_log(DFS_DEBUG_INFO, ("open successful"));
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_close
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_close(struct dfs_fd* fd)
+{
+ int result = 0;
+
+ if (fd != RT_NULL && fd->fs->ops->close != RT_NULL) result = fd->fs->ops->close(fd);
+
+ /* close fd error, return */
+ if ( result < 0 ) return result;
+
+ fd->flags &= ~DFS_F_OPEN;
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_ioctl
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_ioctl(struct dfs_fd* fd, int cmd, void *args)
+{
+ struct dfs_filesystem* fs;
+
+ if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL;
+
+ fs = fd->fs;
+#if 0 /* not support right now */
+ if (cmd == FILEGETSIZE)
+ {
+ if (args == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ *((rt_uint32_t *) args) = fd->size;
+
+ return 0;
+ }
+ else if (cmd == FILEGETPOS)
+ {
+ if (args == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ *((rt_uint32_t *) args) = fd->pos;
+
+ return 0;
+ }
+#endif
+
+ if (fs->ops->ioctl != RT_NULL) return fs->ops->ioctl(fd, cmd, args);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_read
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_read(struct dfs_fd* fd, void *buf, rt_size_t len)
+{
+ struct dfs_filesystem* fs;
+ int result = 0;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ fs = (struct dfs_filesystem*) fd->fs;
+ if (fs->ops->read == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ if ( (result = fs->ops->read(fd, buf, len)) < 0 ) fd->flags |= DFS_F_EOF;
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_getdents
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_getdents(struct dfs_fd* fd, struct dfs_dirent* dirp, rt_size_t nbytes)
+{
+ struct dfs_filesystem* fs;
+
+ /* parameter check */
+ if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL;
+
+ fs = (struct dfs_filesystem*) fd->fs;
+ if (fs->ops->getdents != RT_NULL) return fs->ops->getdents(fd, dirp, nbytes);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_unlink
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_unlink(const char *path)
+{
+ struct dfs_filesystem* fs;
+ char *fullpath, *real_path, search_path[DFS_PATH_MAX + 1];
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX+1];
+#endif
+ struct dfs_fd* fd;
+ int index, fspathlen;
+
+ /* Make sure we have an absolute path */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) return -DFS_STATUS_ENOENT;
+
+ /* Check whether file is already open */
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ for (index = 0; index < DFS_FD_MAX; index++)
+ {
+ fd = &(fd_table[index]);
+ if (fd->fs == RT_NULL) continue;
+
+ build_fullpath(fd->fs->path, fd->path, search_path);
+ if (strcmp(fullpath, search_path) == 0)
+ {
+ rt_sem_release(fd_table_lock);
+ return -DFS_STATUS_EEXIST;
+ }
+ }
+ rt_sem_release(fd_table_lock);
+
+ fspathlen = strlen(fs->path);
+ real_path = search_path;
+ rt_memset( real_path, 0, sizeof( real_path ) );
+ if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
+ strcat(real_path, fullpath + fspathlen);
+
+ if (fs->ops->unlink != RT_NULL) return fs->ops->unlink(fs, real_path);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_write
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_write(struct dfs_fd* fd, const void *buf, rt_size_t len)
+{
+ struct dfs_filesystem* fs = fd->fs;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+ if (fs->ops->write == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ return fs->ops->write(fd, buf, len);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_lseek
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_lseek(struct dfs_fd* fd, rt_off_t offset)
+{
+ struct dfs_filesystem* fs = fd->fs;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+ if (fs->ops->lseek == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ return fs->ops->lseek(fd, offset);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_stat
++------------------------------------------------------------------------------
+| Description : get the file or directory stat description
+|
+| Parameters : path, the file or directory path
+| buf, the stat description will be saved in it
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_stat(const char *path, struct dfs_stat *buf)
+{
+ struct dfs_filesystem* fs;
+ char* fullpath, real_path[DFS_PATH_MAX + 1];
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ int fspathlen;
+
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL )
+ {
+ dfs_log(DFS_DEBUG_ERROR, ("can't find mounted filesystem on this path:%s", fullpath));
+ return -DFS_STATUS_ENOENT;
+ }
+
+ fspathlen = strlen(fs->path);
+ rt_memset(real_path, 0, sizeof(real_path));
+ if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
+ strcat(real_path, fullpath + fspathlen);
+
+ if (fs->ops->stat == RT_NULL)
+ {
+ dfs_log(DFS_DEBUG_ERROR, ("the filesystem didn't implement this function"));
+ return -DFS_STATUS_ENOSYS;
+ }
+
+ return fs->ops->stat(fs, real_path, buf);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_rename
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_rename(const char* oldpath, const char* newpath)
+{
+ struct dfs_filesystem *oldfs, *newfs;
+ char *oldfullpath, *newfullpath;
+ #ifdef RT_USING_WORKDIR
+ /* Change DFS_PATH_MAX to DFS_PATH_MAX + 1, [email protected]*/
+ char old_realpath[DFS_PATH_MAX + 1], new_realpath[DFS_PATH_MAX + 1];
+ #endif
+
+ oldfullpath = (char*)oldpath;
+ newfullpath = (char*)newpath;
+
+ if ( oldfullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ oldfullpath = old_realpath;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, oldpath, oldfullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( newfullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ newfullpath = new_realpath;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, newpath, newfullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (oldfs = dfs_filesystem_lookup(oldfullpath)) == RT_NULL )
+ {
+ return -DFS_STATUS_ENOENT;
+ }
+
+ if ( (newfs = dfs_filesystem_lookup(newfullpath)) == RT_NULL )
+ {
+ return -DFS_STATUS_ENOENT;
+ }
+
+ if ( oldfs == newfs )
+ {
+ if ( oldfs->ops->rename == RT_NULL ) return -DFS_STATUS_ENOSYS;
+
+ return oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
+ }
+
+ /* not at same file system, return EXDEV */
+ return -DFS_STATUS_EXDEV;
+}
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+
+static char fullpath[256 + 1];
+static struct dfs_fd fd;
+static struct dfs_dirent dirent;
+void __ls(const char* pathname)
+{
+ struct dfs_stat stat;
+ int length;
+
+ /* list directory */
+ if ( dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY) == 0 )
+ {
+ rt_kprintf("Directory %s:\n", pathname);
+ do
+ {
+ rt_memset(&dirent, 0, sizeof(struct dfs_dirent));
+ length = dfile_raw_getdents(&fd, &dirent, sizeof(struct dfs_dirent));
+ if ( length > 0 )
+ {
+ rt_memset(&stat, 0, sizeof(struct dfs_stat));
+
+ /* build full path for each file */
+ strncpy(fullpath, pathname, 256);
+ strcat(fullpath, "/");
+ strcat(fullpath, dirent.d_name);
+
+ dfile_raw_stat(fullpath, &stat);
+ if ( stat.st_mode & DFS_S_IFDIR )
+ {
+ rt_kprintf("%s\t\t<DIR>\n", dirent.d_name);
+ }
+ else
+ {
+ rt_kprintf("%s\t\t%lu\n", dirent.d_name, stat.st_size);
+ }
+ }
+ }while(length > 0);
+
+ dfile_raw_close(&fd);
+ }
+ else
+ {
+ rt_kprintf("No such directory\n");
+ }
+}
+FINSH_FUNCTION_EXPORT(__ls, list directory contents)
+
+void __mkdir(const char* pathname)
+{
+ /* make a new directory */
+ if (dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY | DFS_O_CREAT) == 0)
+ {
+ dfile_raw_close(&fd);
+ }
+ else rt_kprintf("Can't mkdir %s\n", pathname);
+}
+FINSH_FUNCTION_EXPORT(__mkdir, make a directory)
+
+void __rm(const char* filename)
+{
+ if (dfile_raw_unlink(filename) < 0)
+ {
+ rt_kprintf("Delete %s failed\n", filename);
+ }
+}
+FINSH_FUNCTION_EXPORT(__rm, remove files or directories)
+
+void __cat(const char* filename)
+{
+ rt_uint32_t length;
+ char buffer[81];
+
+ if (dfile_raw_open(&fd, filename, DFS_O_RDONLY) < 0)
+ {
+ rt_kprintf("Open %s failed\n", filename);
+ return;
+ }
+
+ do
+ {
+ rt_memset(buffer, 0, sizeof(buffer));
+ length = dfile_raw_read(&fd, buffer, 81);
+ if (length > 0)
+ {
+ rt_kprintf("%s", buffer);
+ }
+ }while (length > 0);
+
+ dfile_raw_close(&fd);
+}
+FINSH_FUNCTION_EXPORT(__cat, print file)
+
+#ifndef FINSH_USING_SYMTAB
+void dfs_export_finsh(void)
+{
+ finsh_syscall_append("ls", (syscall_func)__ls);
+ finsh_syscall_append("mkdir", (syscall_func)__mkdir);
+ finsh_syscall_append("rm", (syscall_func)__rm);
+ finsh_syscall_append("cat", (syscall_func)__cat);
+}
+#endif
+#endif
diff --git a/filesystem/dfs/src/dfs_util.c b/filesystem/dfs/src/dfs_util.c
new file mode 100644
index 0000000000..455c9f1f9d
--- /dev/null
+++ b/filesystem/dfs/src/dfs_util.c
@@ -0,0 +1,297 @@
+/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_utl.c, some misc functions of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-01-26 ffxz The first version
++------------------------------------------------------------------------------
+*/
+
+#include <string.h>
+
+#include <dfs_fs.h>
+#include <dfs_util.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : dir_name
++------------------------------------------------------------------------------
+| Description : Gets the directory name in specified path string
+|
+| Parameters : path, the specified path string
+| path_name, return the path name in this parameter
+| len, the length of path name
+| Returns : the status of path_name:
+| 0 , successful
+| -1, failed
+| For Example :
+| path, dir_name
+| /, /
+| /usr, /
+| /usr/lib, /usr
+| /usr/lib/, /usr
++------------------------------------------------------------------------------
+*/
+int dir_name(const char* path, char* dirname, int len)
+{
+ int pos;
+
+ if ( path[0] == '/' && path[1] == '\0' )
+ {
+ *dirname++ = '/';
+ *dirname = '\0';
+ return 0;
+ }
+
+ pos = strlen(path);
+ while ( *(path + pos - 1) =='/' ) pos --;
+ while ( pos > 0 && *(path + pos - 1) != '/' ) pos --;
+ while ( pos > 0 && *(path + pos - 1) == '/' ) pos --;
+
+ if ( pos > len ) return -1;
+
+ if ( pos != 0)
+ {
+ memcpy(dirname, path, pos);
+ *(dirname+pos) = '\0';
+ }
+ else
+ {
+ *dirname++ = '/';
+ *dirname = '\0';
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : file_name
++------------------------------------------------------------------------------
+| Description : Gets the file name in specified path string
+|
+| Parameters : path, the specified path string
+| filename, return the path name in this parameter
+| len, the length of file name
+| Returns : the status of file_name:
+| 0 , successful
+| -1, failed
+| For Example :
+| path, filename
+| /, RT_NULL
+| /usr, usr
+| /usr/lib, lib
+| /usr/lib/, lib
++------------------------------------------------------------------------------
+*/
+int file_name(const char* path, char* filename, int len)
+{
+ int pos, size;
+
+ if ( path[0] == '/' && path[1] == '\0' )
+ {
+ *filename = '\0';
+ return 0;
+ }
+
+ pos = strlen(path);
+ while ( *(path + pos -1)=='/' ) pos --;
+ size = pos;
+
+ while ( *(path + pos -1) != '/' && pos > 0 ) pos --;
+
+ if ( size - pos > len ) return -1;
+ else size = size - pos ;
+
+ memcpy(filename, path + pos, size);
+ *(filename+size) = '\0';
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : next_path_name
++------------------------------------------------------------------------------
+| Description : Gets the next directory name from specified path string
+|
+| Parameters : path, the specified path string
+| pos, the specified position of path string
+| next, return the next path in this parameter
+| Returns : the position of next directory item,
+| -1, if pos reach in the end of the specified path string
+| For Example :
++------------------------------------------------------------------------------
+*/
+int next_dir_name(const char* path, int pos, char* next)
+{
+ const char* q;
+
+ if ( pos > strlen(path) || pos < 0|| path == RT_NULL ) return -1;
+
+ q = path + pos;
+
+ /* check for firt '/' */
+ while ( *q == '/' ) q++;
+ if ( *q == '\0' )
+ {
+ *next = '\0';
+ return -1;
+ }
+
+ while ( *q != '/' && *q != '\0' )
+ {
+ *next++ = *q++;
+ }
+ *next = '\0';
+
+ return q - path + 1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : build_fullpath
++------------------------------------------------------------------------------
+| Description : make up the full path from directory and filename
+|
+| Parameters : path, the specified path string
+| filename, return the path name in this parameter
+| fullpath, the returned full path name
+| Returns : null
++------------------------------------------------------------------------------
+*/
+void build_fullpath(const char *directory, const char *filename, char *fullpath)
+{
+ char elem[DFS_PATH_MAX + 1];
+ int pos, start, len;
+
+ len = 0;
+ /* check parameters */
+ RT_ASSERT(directory != RT_NULL);
+ RT_ASSERT(filename != RT_NULL);
+ RT_ASSERT(fullpath != RT_NULL);
+
+ /* copy full of directory */
+ strncpy(fullpath, directory, DFS_PATH_MAX + 1);
+
+ for (pos = 0; filename[pos] != '\0'; )
+ {
+ /* strip '//' */
+ while (filename[pos] == '/') pos++;
+
+ /* get the filename element, save to elem array */
+ for (start = pos; filename[pos] != '/' && filename[pos] != '\0'; pos++)
+ len = pos - start + 1;
+
+ strncpy(elem, filename + start, DFS_PATH_MAX + 1);
+ /* clear the end of elem */
+ elem[(len < DFS_PATH_MAX + 1? len : DFS_PATH_MAX + 1)] = '\0';
+
+ /* strip '..' */
+ if (elem[0] == '.' && elem[1] == '.')
+ {
+ if (strlen(fullpath) == 0) strcpy(fullpath, ""); /* empty filename */
+ else if (fullpath[0] == '/' && fullpath[1] !='\0')
+ {
+ int i = strlen(fullpath);
+
+ while (fullpath[i - 1] == '/') i--;
+ while (i > 0 && fullpath[i - 1] != '/') i--;
+
+ fullpath[i] = '\0';
+ }
+ }
+ /* not '.', copy as normally */
+ else if (elem[0] != '.')
+ {
+ len = strlen(fullpath);
+
+ if (len == 0) strncpy(fullpath, elem, DFS_PATH_MAX + 1);
+ else if (fullpath[len - 1] == '/')
+ {
+ if (elem[0] == '/') strncat(fullpath, elem + 1, DFS_PATH_MAX + 1);
+ else strncat(fullpath, elem, DFS_PATH_MAX + 1);
+ }
+ else
+ {
+ if (elem[0] == '/') strcat(fullpath, elem);
+ else
+ {
+ strncat(fullpath, "/", DFS_PATH_MAX + 1);
+ strncat(fullpath + 1, elem, DFS_PATH_MAX + 1);
+ }
+ }
+ }
+ }
+
+ if ( fullpath[0] != '/' && fullpath[(len = strlen(fullpath)) - 1] == '/')
+ {
+ fullpath[len - 1] = '\0';
+ }
+}
+
+int str_is_prefix(const char* prefix, const char* str)
+{
+ while ((*prefix) && (*str) && (*prefix == *str))
+ {
+ prefix ++;
+ str ++;
+ }
+
+ if (*prefix == 0) return 0;
+
+ return -1;
+}
+
+#if !defined(RT_USING_MINILIBC) && !defined(RT_USING_NEWLIB)
+#if !defined(__ICCARM__)
+char *strrchr(const char *t, int c)
+{
+ register char ch;
+ register const char *l=0;
+
+ ch = c;
+ for (;;)
+ {
+ if ((*t == ch)) l=t;
+ if ((!*t)) return (char*)l; ++t;
+ }
+
+ return (char*)l;
+}
+#endif
+
+#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION / 10000 < 35)
+int strncasecmp ( const char* s1, const char* s2, size_t len )
+{
+ register unsigned int x2;
+ register unsigned int x1;
+ register const char* end = s1 + len;
+
+ while (1)
+ {
+ if ((s1 >= end) )
+ return 0;
+
+ x2 = *s2 - 'A'; if ((x2 < 26u)) x2 += 32;
+ x1 = *s1 - 'A'; if ((x1 < 26u)) x1 += 32;
+ s1++; s2++;
+
+ if ((x2 != x1))
+ break;
+
+ if ((x1 == (unsigned int)-'A'))
+ break;
+ }
+
+ return x1 - x2;
+}
+#endif /* end of __ARMCC_VERSION */
+
+#endif