diff options
| author | bernard.xiong <[email protected]> | 2009-07-02 22:48:23 +0000 |
|---|---|---|
| committer | bernard.xiong <[email protected]> | 2009-07-02 22:48:23 +0000 |
| commit | bda4730a9482c23083006abea939ee8d95d6ecff (patch) | |
| tree | 83005121824bd50ac74e63688c0d5eac148665f8 /filesystem/dfs/src | |
| parent | 80c72e66de0b00b1a6de3e3508366a4c3eee458d (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.c | 273 | ||||
| -rw-r--r-- | filesystem/dfs/src/dfs_fs.c | 362 | ||||
| -rw-r--r-- | filesystem/dfs/src/dfs_init.c | 92 | ||||
| -rw-r--r-- | filesystem/dfs/src/dfs_posix.c | 564 | ||||
| -rw-r--r-- | filesystem/dfs/src/dfs_raw.c | 668 | ||||
| -rw-r--r-- | filesystem/dfs/src/dfs_util.c | 297 |
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
|
