From bda4730a9482c23083006abea939ee8d95d6ecff Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Thu, 2 Jul 2009 22:48:23 +0000 Subject: 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 --- filesystem/dfs/src/dfs_cache.c | 273 +++++++++++++++++ filesystem/dfs/src/dfs_fs.c | 362 ++++++++++++++++++++++ filesystem/dfs/src/dfs_init.c | 92 ++++++ filesystem/dfs/src/dfs_posix.c | 564 ++++++++++++++++++++++++++++++++++ filesystem/dfs/src/dfs_raw.c | 668 +++++++++++++++++++++++++++++++++++++++++ filesystem/dfs/src/dfs_util.c | 297 ++++++++++++++++++ 6 files changed, 2256 insertions(+) create mode 100644 filesystem/dfs/src/dfs_cache.c create mode 100644 filesystem/dfs/src/dfs_fs.c create mode 100644 filesystem/dfs/src/dfs_init.c create mode 100644 filesystem/dfs/src/dfs_posix.c create mode 100644 filesystem/dfs/src/dfs_raw.c create mode 100644 filesystem/dfs/src/dfs_util.c (limited to 'filesystem/dfs/src') 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;cnumbuf;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 +#include +#include + +#include + +/* ++------------------------------------------------------------------------------ +| 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 +#include + +#include +#include + +#include + +/* 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 + +/* ++------------------------------------------------------------------------------ +| 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 +#include +#include + +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, yi.qiu@2008.09.23*/ + 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 + +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\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 + +#include +#include + +/* ++------------------------------------------------------------------------------ +| 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 -- cgit v1.3.1