diff --git a/components/dfs/filesystems/devfs/console.c b/components/dfs/filesystems/devfs/console.c index 46fc3804607b4ead59ef8cc30242690aaca54e15..cce707a817eadae0f396b7dc7e4820f80d3a8a44 100644 --- a/components/dfs/filesystems/devfs/console.c +++ b/components/dfs/filesystems/devfs/console.c @@ -1,85 +1,85 @@ -/* - * RT-Thread Console Device File - * - */ -#include - -struct console_device -{ - struct rt_device parent; - - rt_device_t device; /* the actual device */ -}; -struct console_device _console; - -/* common device interface */ -static rt_err_t console_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t console_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t console_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_size_t console_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - struct console_device* device; - - device = (struct console_device*)dev; - RT_ASSERT(device != RT_NULL); - - return rt_device_read(device->device, pos, buffer, size); -} - -static rt_size_t console_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - struct console_device* device; - - device = (struct console_device*)dev; - RT_ASSERT(device != RT_NULL); - - return rt_device_write(device->device, pos, buffer, size); -} - -static rt_err_t console_control(rt_device_t dev, rt_uint8_t cmd, void *args) -{ - return rt_device_control(_console.device, cmd, args); -} - -void rt_console_init(const char* device_name) -{ - rt_device_t device; - /* register to device framework */ - - device = rt_device_find(device_name); - if (device != RT_NULL) - { - struct console_device* console; - /* get console device */ - console = &_console; - rt_memset(console, 0, sizeof(_console)); - - /* device initialization */ - console->parent.type = RT_Device_Class_Char; - /* set device interface */ - console->parent.init = console_init; - console->parent.open = console_open; - console->parent.close = console_close; - console->parent.read = console_read; - console->parent.write = console_write; - console->parent.control = RT_NULL; - console->parent.user_data = RT_NULL; - - console->device = device; - - rt_device_register(&console->parent, "console", RT_DEVICE_FLAG_RDWR); - } -} - +/* + * RT-Thread Console Device File + * + */ +#include + +struct console_device +{ + struct rt_device parent; + + rt_device_t device; /* the actual device */ +}; +struct console_device _console; + +/* common device interface */ +static rt_err_t console_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t console_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t console_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t console_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + struct console_device* device; + + device = (struct console_device*)dev; + RT_ASSERT(device != RT_NULL); + + return rt_device_read(device->device, pos, buffer, size); +} + +static rt_size_t console_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + struct console_device* device; + + device = (struct console_device*)dev; + RT_ASSERT(device != RT_NULL); + + return rt_device_write(device->device, pos, buffer, size); +} + +static rt_err_t console_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return rt_device_control(_console.device, cmd, args); +} + +void rt_console_init(const char* device_name) +{ + rt_device_t device; + /* register to device framework */ + + device = rt_device_find(device_name); + if (device != RT_NULL) + { + struct console_device* console; + /* get console device */ + console = &_console; + rt_memset(console, 0, sizeof(_console)); + + /* device initialization */ + console->parent.type = RT_Device_Class_Char; + /* set device interface */ + console->parent.init = console_init; + console->parent.open = console_open; + console->parent.close = console_close; + console->parent.read = console_read; + console->parent.write = console_write; + console->parent.control = RT_NULL; + console->parent.user_data = RT_NULL; + + console->device = device; + + rt_device_register(&console->parent, "console", RT_DEVICE_FLAG_RDWR); + } +} + diff --git a/components/dfs/filesystems/devfs/devfs.c b/components/dfs/filesystems/devfs/devfs.c index 98f2146f6d9a8c5c5545b72a989511069ab5a46f..2a8e78df5e13f317dbfdb72521b518e90160f3f5 100644 --- a/components/dfs/filesystems/devfs/devfs.c +++ b/components/dfs/filesystems/devfs/devfs.c @@ -1,276 +1,276 @@ -#include -#include -#include - -#include "devfs.h" - -/* introduce from kservice.c */ +#include +#include +#include + +#include "devfs.h" + +/* introduce from kservice.c */ #define rt_list_entry(node, type, member) \ ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) - -struct device_dirent -{ - rt_device_t *devices; - rt_uint16_t read_index; - rt_uint16_t device_count; -}; - -int dfs_device_fs_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data) -{ - return DFS_STATUS_OK; -} - -int dfs_device_fs_ioctl(struct dfs_fd* file, int cmd, void* args) -{ - rt_err_t result; - rt_device_t dev_id; - - RT_ASSERT(file != RT_NULL); - - /* get device handler */ - dev_id = (rt_device_t)file->data; - RT_ASSERT(dev_id != RT_NULL); - - /* close device handler */ - result = rt_device_control(dev_id, cmd, args); - if (result == RT_EOK) - return DFS_STATUS_OK; - - return -DFS_STATUS_EIO; -} - -int dfs_device_fs_read(struct dfs_fd* file, void *buf, rt_size_t count) -{ - int result; - rt_device_t dev_id; - - RT_ASSERT(file != RT_NULL); - - /* get device handler */ - dev_id = (rt_device_t)file->data; - RT_ASSERT(dev_id != RT_NULL); - - /* read device data */ - result = rt_device_read(dev_id, file->pos, buf, count); - file->pos += result; - - return result; -} - -int dfs_device_fs_write(struct dfs_fd* file, const void *buf, rt_size_t count) -{ - int result; - rt_device_t dev_id; - - RT_ASSERT(file != RT_NULL); - - /* get device handler */ - dev_id = (rt_device_t)file->data; - RT_ASSERT(dev_id != RT_NULL); - - /* read device data */ - result = rt_device_write(dev_id, file->pos, buf, count); - file->pos += result; - - return result; -} - -int dfs_device_fs_close(struct dfs_fd* file) -{ - rt_err_t result; - rt_device_t dev_id; - - RT_ASSERT(file != RT_NULL); - - if (file->type == FT_DIRECTORY) - { - struct device_dirent *root_dirent; - - root_dirent = (struct device_dirent*)file->data; - RT_ASSERT(root_dirent != RT_NULL); - - /* release dirent */ - rt_free(root_dirent); - return DFS_STATUS_OK; - } - - /* get device handler */ - dev_id = (rt_device_t)file->data; - RT_ASSERT(dev_id != RT_NULL); - - /* close device handler */ - result = rt_device_close(dev_id); - if (result == RT_EOK) - { - file->data = RT_NULL; - return DFS_STATUS_OK; - } - - return -DFS_STATUS_EIO; -} - -int dfs_device_fs_open(struct dfs_fd* file) -{ - rt_device_t device; - - if (file->flags & DFS_O_CREAT) return -DFS_STATUS_EINVAL; - - /* open root directory */ - if ((file->path[0] == '/') && (file->path[1] == '\0') && - (file->flags & DFS_O_DIRECTORY)) - { - struct rt_object* object; - struct rt_list_node* node; - struct rt_object_information *information; - struct device_dirent* root_dirent; - rt_uint32_t count = 0; - - extern struct rt_object_information rt_object_container[]; - - /* lock scheduler */ - rt_enter_critical(); - - /* traverse device object */ - information = &rt_object_container[RT_Object_Class_Device]; - for (node = information->object_list.next; node != &(information->object_list); node = node->next) - { - count ++; - } - - root_dirent = (struct device_dirent*) rt_malloc (sizeof(struct device_dirent) + - count * sizeof(rt_device_t)); - if (root_dirent != RT_NULL) - { - root_dirent->devices = (rt_device_t *)(root_dirent + 1); - root_dirent->read_index = 0; - root_dirent->device_count = count; - count = 0; - /* get all device node */ - for (node = information->object_list.next; node != &(information->object_list); node = node->next) - { - object = rt_list_entry(node, struct rt_object, list); - root_dirent->devices[count] = (rt_device_t)object; - count ++; - } - } - rt_exit_critical(); - - /* set data */ - file->data = root_dirent; - return DFS_STATUS_OK; - } - - device = rt_device_find(&file->path[1]); - if (device == RT_NULL) - return -DFS_STATUS_ENODEV; - - file->data = device; - return DFS_STATUS_OK; -} - -int dfs_device_fs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) -{ - /* stat root directory */ - if ((path[0] == '/') && (path[1] == '\0')) - { - st->st_dev = 0; - - st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | - DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; - st->st_mode &= ~DFS_S_IFREG; - st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; - - st->st_size = 0; - st->st_mtime = 0; - st->st_blksize = 512; - return DFS_STATUS_OK; - } - else - { - rt_device_t dev_id; - - dev_id = rt_device_find(&path[1]); - if (dev_id != RT_NULL) - { - st->st_dev = 0; - - st->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | - DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; - - if (dev_id->type == RT_Device_Class_Char) - st->st_mode |= DFS_S_IFCHR; - else if (dev_id->type == RT_Device_Class_Block) - st->st_mode |= DFS_S_IFBLK; - else - st->st_mode |= DFS_S_IFREG; - - st->st_size = 0; - st->st_mtime = 0; - st->st_blksize = 512; - return DFS_STATUS_OK; - } - } - - return -DFS_STATUS_ENOENT; -} - -int dfs_device_fs_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count) -{ - rt_uint32_t index; - rt_object_t object; - struct dirent* d; - struct device_dirent *root_dirent; - - root_dirent = (struct device_dirent*)file->data; - RT_ASSERT(root_dirent != RT_NULL); - - /* make integer count */ - count = (count / sizeof(struct dirent)); - if ( count == 0 ) return -DFS_STATUS_EINVAL; - - for (index = 0; index < count && index + root_dirent->read_index < root_dirent->device_count; - index ++) - { - object = (rt_object_t)root_dirent->devices[root_dirent->read_index + index]; - - d = dirp + index; - d->d_type = DFS_DT_REG; - d->d_namlen = RT_NAME_MAX; - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, object->name, RT_NAME_MAX); - } - - root_dirent->read_index += index; - - return index * sizeof(struct dirent); -} - -static const struct dfs_filesystem_operation _device_fs = -{ - "devfs", - dfs_device_fs_mount, - RT_NULL, - RT_NULL, - RT_NULL, - - dfs_device_fs_open, - dfs_device_fs_close, - dfs_device_fs_ioctl, - dfs_device_fs_read, - dfs_device_fs_write, - RT_NULL, - RT_NULL, - dfs_device_fs_getdents, - RT_NULL, - dfs_device_fs_stat, - RT_NULL, -}; - -int devfs_init(void) -{ - /* register rom file system */ - dfs_register(&_device_fs); - - return 0; -} - + +struct device_dirent +{ + rt_device_t *devices; + rt_uint16_t read_index; + rt_uint16_t device_count; +}; + +int dfs_device_fs_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data) +{ + return DFS_STATUS_OK; +} + +int dfs_device_fs_ioctl(struct dfs_fd* file, int cmd, void* args) +{ + rt_err_t result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* close device handler */ + result = rt_device_control(dev_id, cmd, args); + if (result == RT_EOK) + return DFS_STATUS_OK; + + return -DFS_STATUS_EIO; +} + +int dfs_device_fs_read(struct dfs_fd* file, void *buf, rt_size_t count) +{ + int result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* read device data */ + result = rt_device_read(dev_id, file->pos, buf, count); + file->pos += result; + + return result; +} + +int dfs_device_fs_write(struct dfs_fd* file, const void *buf, rt_size_t count) +{ + int result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* read device data */ + result = rt_device_write(dev_id, file->pos, buf, count); + file->pos += result; + + return result; +} + +int dfs_device_fs_close(struct dfs_fd* file) +{ + rt_err_t result; + rt_device_t dev_id; + + RT_ASSERT(file != RT_NULL); + + if (file->type == FT_DIRECTORY) + { + struct device_dirent *root_dirent; + + root_dirent = (struct device_dirent*)file->data; + RT_ASSERT(root_dirent != RT_NULL); + + /* release dirent */ + rt_free(root_dirent); + return DFS_STATUS_OK; + } + + /* get device handler */ + dev_id = (rt_device_t)file->data; + RT_ASSERT(dev_id != RT_NULL); + + /* close device handler */ + result = rt_device_close(dev_id); + if (result == RT_EOK) + { + file->data = RT_NULL; + return DFS_STATUS_OK; + } + + return -DFS_STATUS_EIO; +} + +int dfs_device_fs_open(struct dfs_fd* file) +{ + rt_device_t device; + + if (file->flags & DFS_O_CREAT) return -DFS_STATUS_EINVAL; + + /* open root directory */ + if ((file->path[0] == '/') && (file->path[1] == '\0') && + (file->flags & DFS_O_DIRECTORY)) + { + struct rt_object* object; + struct rt_list_node* node; + struct rt_object_information *information; + struct device_dirent* root_dirent; + rt_uint32_t count = 0; + + extern struct rt_object_information rt_object_container[]; + + /* lock scheduler */ + rt_enter_critical(); + + /* traverse device object */ + information = &rt_object_container[RT_Object_Class_Device]; + for (node = information->object_list.next; node != &(information->object_list); node = node->next) + { + count ++; + } + + root_dirent = (struct device_dirent*) rt_malloc (sizeof(struct device_dirent) + + count * sizeof(rt_device_t)); + if (root_dirent != RT_NULL) + { + root_dirent->devices = (rt_device_t *)(root_dirent + 1); + root_dirent->read_index = 0; + root_dirent->device_count = count; + count = 0; + /* get all device node */ + for (node = information->object_list.next; node != &(information->object_list); node = node->next) + { + object = rt_list_entry(node, struct rt_object, list); + root_dirent->devices[count] = (rt_device_t)object; + count ++; + } + } + rt_exit_critical(); + + /* set data */ + file->data = root_dirent; + return DFS_STATUS_OK; + } + + device = rt_device_find(&file->path[1]); + if (device == RT_NULL) + return -DFS_STATUS_ENODEV; + + file->data = device; + return DFS_STATUS_OK; +} + +int dfs_device_fs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) +{ + /* stat root directory */ + if ((path[0] == '/') && (path[1] == '\0')) + { + st->st_dev = 0; + + st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + st->st_mode &= ~DFS_S_IFREG; + st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + + st->st_size = 0; + st->st_mtime = 0; + st->st_blksize = 512; + return DFS_STATUS_OK; + } + else + { + rt_device_t dev_id; + + dev_id = rt_device_find(&path[1]); + if (dev_id != RT_NULL) + { + st->st_dev = 0; + + st->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + + if (dev_id->type == RT_Device_Class_Char) + st->st_mode |= DFS_S_IFCHR; + else if (dev_id->type == RT_Device_Class_Block) + st->st_mode |= DFS_S_IFBLK; + else + st->st_mode |= DFS_S_IFREG; + + st->st_size = 0; + st->st_mtime = 0; + st->st_blksize = 512; + return DFS_STATUS_OK; + } + } + + return -DFS_STATUS_ENOENT; +} + +int dfs_device_fs_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count) +{ + rt_uint32_t index; + rt_object_t object; + struct dirent* d; + struct device_dirent *root_dirent; + + root_dirent = (struct device_dirent*)file->data; + RT_ASSERT(root_dirent != RT_NULL); + + /* make integer count */ + count = (count / sizeof(struct dirent)); + if ( count == 0 ) return -DFS_STATUS_EINVAL; + + for (index = 0; index < count && index + root_dirent->read_index < root_dirent->device_count; + index ++) + { + object = (rt_object_t)root_dirent->devices[root_dirent->read_index + index]; + + d = dirp + index; + d->d_type = DFS_DT_REG; + d->d_namlen = RT_NAME_MAX; + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, object->name, RT_NAME_MAX); + } + + root_dirent->read_index += index; + + return index * sizeof(struct dirent); +} + +static const struct dfs_filesystem_operation _device_fs = +{ + "devfs", + dfs_device_fs_mount, + RT_NULL, + RT_NULL, + RT_NULL, + + dfs_device_fs_open, + dfs_device_fs_close, + dfs_device_fs_ioctl, + dfs_device_fs_read, + dfs_device_fs_write, + RT_NULL, + RT_NULL, + dfs_device_fs_getdents, + RT_NULL, + dfs_device_fs_stat, + RT_NULL, +}; + +int devfs_init(void) +{ + /* register rom file system */ + dfs_register(&_device_fs); + + return 0; +} + diff --git a/components/dfs/filesystems/devfs/devfs.h b/components/dfs/filesystems/devfs/devfs.h index 90583e979ffde8e054672aa31da0f50e15f0c8e7..248aab91d76575c3fd150c8ac497ed9bc16606dd 100644 --- a/components/dfs/filesystems/devfs/devfs.h +++ b/components/dfs/filesystems/devfs/devfs.h @@ -1,8 +1,8 @@ -#ifndef __DEVICE_FS_H__ -#define __DEVICE_FS_H__ - -#include - -int devfs_init(void); - -#endif +#ifndef __DEVICE_FS_H__ +#define __DEVICE_FS_H__ + +#include + +int devfs_init(void); + +#endif diff --git a/components/dfs/filesystems/nfs/rpc/auth.h b/components/dfs/filesystems/nfs/rpc/auth.h index e117e7e411e8a3013467464574e6f6c86ebc2db6..3351fbbf9558e56fd8932153198df44247cc54b1 100644 --- a/components/dfs/filesystems/nfs/rpc/auth.h +++ b/components/dfs/filesystems/nfs/rpc/auth.h @@ -1,104 +1,104 @@ -#ifndef __AUTH_H__ -#define __AUTH_H__ - -#include - -/* - * Status returned from authentication check - */ -enum auth_stat { - AUTH_OK=0, - /* - * failed at remote end - */ - AUTH_BADCRED=1, /* bogus credentials (seal broken) */ - AUTH_REJECTEDCRED=2, /* client should begin new session */ - AUTH_BADVERF=3, /* bogus verifier (seal broken) */ - AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ - AUTH_TOOWEAK=5, /* rejected due to security reasons */ - /* - * failed locally - */ - AUTH_INVALIDRESP=6, /* bogus response verifier */ - AUTH_FAILED=7 /* some unknown reason */ -}; - -union des_block { - struct { - uint32_t high; - uint32_t low; - } key; - char c[8]; -}; -typedef union des_block des_block; - -/* - * Authentication info. Opaque to client. - */ -struct opaque_auth { - enum_t oa_flavor; /* flavor of auth */ - char* oa_base; /* address of more auth stuff */ - unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */ -}; - -/* - * Auth handle, interface to client side authenticators. - */ -typedef struct AUTH AUTH; -struct AUTH { - struct opaque_auth ah_cred; - struct opaque_auth ah_verf; - union des_block ah_key; - struct auth_ops { - void (*ah_nextverf) (AUTH *); - int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */ - int (*ah_validate) (AUTH *, struct opaque_auth *); - /* validate verifier */ - int (*ah_refresh) (AUTH *); /* refresh credentials */ - void (*ah_destroy) (AUTH *); /* destroy this structure */ - } *ah_ops; - char* ah_private; -}; - -extern struct opaque_auth _null_auth; - - -/* - * Authentication ops. - * The ops and the auth handle provide the interface to the authenticators. - * - * AUTH *auth; - * XDR *xdrs; - * struct opaque_auth verf; - */ -#define AUTH_NEXTVERF(auth) \ - ((*((auth)->ah_ops->ah_nextverf))(auth)) -#define auth_nextverf(auth) \ - ((*((auth)->ah_ops->ah_nextverf))(auth)) - -#define AUTH_MARSHALL(auth, xdrs) \ - ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) -#define auth_marshall(auth, xdrs) \ - ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) - -#define AUTH_VALIDATE(auth, verfp) \ - ((*((auth)->ah_ops->ah_validate))((auth), verfp)) -#define auth_validate(auth, verfp) \ - ((*((auth)->ah_ops->ah_validate))((auth), verfp)) - -#define AUTH_REFRESH(auth) \ - ((*((auth)->ah_ops->ah_refresh))(auth)) -#define auth_refresh(auth) \ - ((*((auth)->ah_ops->ah_refresh))(auth)) - -#define AUTH_DESTROY(auth) \ - ((*((auth)->ah_ops->ah_destroy))(auth)) -#define auth_destroy(auth) \ - ((*((auth)->ah_ops->ah_destroy))(auth)) - -#define MAX_AUTH_BYTES 400 -#define MAXNETNAMELEN 255 /* maximum length of network user's name */ - -AUTH *authnone_create(void); - -#endif +#ifndef __AUTH_H__ +#define __AUTH_H__ + +#include + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + uint32_t high; + uint32_t low; + } key; + char c[8]; +}; +typedef union des_block des_block; + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + char* oa_base; /* address of more auth stuff */ + unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct AUTH AUTH; +struct AUTH { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf) (AUTH *); + int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */ + int (*ah_validate) (AUTH *, struct opaque_auth *); + /* validate verifier */ + int (*ah_refresh) (AUTH *); /* refresh credentials */ + void (*ah_destroy) (AUTH *); /* destroy this structure */ + } *ah_ops; + char* ah_private; +}; + +extern struct opaque_auth _null_auth; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +AUTH *authnone_create(void); + +#endif diff --git a/components/dfs/filesystems/nfs/rpc/pmap.c b/components/dfs/filesystems/nfs/rpc/pmap.c index 0a1fb9af89e434133b4029c9bed30ac526e744d9..cbf5add2abd21ef9b94a8f9524d3d6df8ed5abc3 100644 --- a/components/dfs/filesystems/nfs/rpc/pmap.c +++ b/components/dfs/filesystems/nfs/rpc/pmap.c @@ -1,60 +1,60 @@ -#include "pmap.h" -#include "clnt.h" -#include - -static struct timeval timeout = { 5, 0 }; -static struct timeval tottimeout = { 60, 0 }; - - -bool_t xdr_pmap(xdrs, regs) -XDR *xdrs; -struct pmap *regs; -{ - if (xdr_u_long(xdrs, ®s->pm_prog) && - xdr_u_long(xdrs, ®s->pm_vers) && - xdr_u_long(xdrs, ®s->pm_prot)) - return (xdr_u_long(xdrs, ®s->pm_port)); - return (FALSE); -} - -/* - * Find the mapped port for program,version. - * Calls the pmap service remotely to do the lookup. - * Returns 0 if no map exists. - */ -unsigned short pmap_getport(address, program, version, protocol) -struct sockaddr_in *address; -unsigned long program; -unsigned long version; -unsigned int protocol; -{ - unsigned short port = 0; - int socket = -1; - register CLIENT *client; - struct pmap parms; - - address->sin_port = htons((unsigned short)PMAPPORT); - if (protocol == IPPROTO_UDP) - client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, - &socket, RPCSMALLMSGSIZE, - RPCSMALLMSGSIZE); - - if (client != (CLIENT *) NULL) - { - parms.pm_prog = program; - parms.pm_vers = version; - parms.pm_prot = protocol; - parms.pm_port = 0; /* not needed or used */ - if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, (char*)&parms, - (xdrproc_t)xdr_u_short, (char*)&port, tottimeout) != RPC_SUCCESS) - { - rt_kprintf("pmap failure\n"); - } - CLNT_DESTROY(client); - } - - (void) lwip_close(socket); - address->sin_port = 0; - - return (port); -} +#include "pmap.h" +#include "clnt.h" +#include + +static struct timeval timeout = { 5, 0 }; +static struct timeval tottimeout = { 60, 0 }; + + +bool_t xdr_pmap(xdrs, regs) +XDR *xdrs; +struct pmap *regs; +{ + if (xdr_u_long(xdrs, ®s->pm_prog) && + xdr_u_long(xdrs, ®s->pm_vers) && + xdr_u_long(xdrs, ®s->pm_prot)) + return (xdr_u_long(xdrs, ®s->pm_port)); + return (FALSE); +} + +/* + * Find the mapped port for program,version. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +unsigned short pmap_getport(address, program, version, protocol) +struct sockaddr_in *address; +unsigned long program; +unsigned long version; +unsigned int protocol; +{ + unsigned short port = 0; + int socket = -1; + register CLIENT *client; + struct pmap parms; + + address->sin_port = htons((unsigned short)PMAPPORT); + if (protocol == IPPROTO_UDP) + client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, + &socket, RPCSMALLMSGSIZE, + RPCSMALLMSGSIZE); + + if (client != (CLIENT *) NULL) + { + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = 0; /* not needed or used */ + if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, (char*)&parms, + (xdrproc_t)xdr_u_short, (char*)&port, tottimeout) != RPC_SUCCESS) + { + rt_kprintf("pmap failure\n"); + } + CLNT_DESTROY(client); + } + + (void) lwip_close(socket); + address->sin_port = 0; + + return (port); +} diff --git a/components/dfs/filesystems/nfs/rpc/pmap.h b/components/dfs/filesystems/nfs/rpc/pmap.h index 96a67375bba836138420d50c018bbb294d386aaa..aaf28a331ad71477c69c4c323ac233467b9a6c2d 100644 --- a/components/dfs/filesystems/nfs/rpc/pmap.h +++ b/components/dfs/filesystems/nfs/rpc/pmap.h @@ -1,58 +1,58 @@ -#ifndef __RPC_PMAP_PROT_H__ -#define __RPC_PMAP_PROT_H__ - -#include - -/* The following procedures are supported by the protocol: - * - * PMAPPROC_NULL() returns () - * takes nothing, returns nothing - * - * PMAPPROC_SET(struct pmap) returns (bool_t) - * TRUE is success, FALSE is failure. Registers the tuple - * [prog, vers, prot, port]. - * - * PMAPPROC_UNSET(struct pmap) returns (bool_t) - * TRUE is success, FALSE is failure. Un-registers pair - * [prog, vers]. prot and port are ignored. - * - * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). - * 0 is failure. Otherwise returns the port number where the pair - * [prog, vers] is registered. It may lie! - * - * PMAPPROC_DUMP() RETURNS (struct pmaplist *) - * - * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) - * RETURNS (port, string<>); - * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); - * Calls the procedure on the local machine. If it is not registered, - * this procedure is quite; ie it does not return error information!!! - * This procedure only is supported on rpc/udp and calls via - * rpc/udp. This routine only passes null authentication parameters. - * This file has no interface to xdr routines for PMAPPROC_CALLIT. - * - * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. - */ - -#define PMAPPORT ((unsigned short)111) -#define PMAPPROG ((unsigned long)100000) -#define PMAPVERS ((unsigned long)2) -#define PMAPVERS_PROTO ((unsigned long)2) -#define PMAPVERS_ORIG ((unsigned long)1) -#define PMAPPROC_NULL ((unsigned long)0) -#define PMAPPROC_SET ((unsigned long)1) -#define PMAPPROC_UNSET ((unsigned long)2) -#define PMAPPROC_GETPORT ((unsigned long)3) -#define PMAPPROC_DUMP ((unsigned long)4) -#define PMAPPROC_CALLIT ((unsigned long)5) - -struct pmap { - long unsigned pm_prog; - long unsigned pm_vers; - long unsigned pm_prot; - long unsigned pm_port; -}; - -extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs); - -#endif +#ifndef __RPC_PMAP_PROT_H__ +#define __RPC_PMAP_PROT_H__ + +#include + +/* The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#define PMAPPORT ((unsigned short)111) +#define PMAPPROG ((unsigned long)100000) +#define PMAPVERS ((unsigned long)2) +#define PMAPVERS_PROTO ((unsigned long)2) +#define PMAPVERS_ORIG ((unsigned long)1) +#define PMAPPROC_NULL ((unsigned long)0) +#define PMAPPROC_SET ((unsigned long)1) +#define PMAPPROC_UNSET ((unsigned long)2) +#define PMAPPROC_GETPORT ((unsigned long)3) +#define PMAPPROC_DUMP ((unsigned long)4) +#define PMAPPROC_CALLIT ((unsigned long)5) + +struct pmap { + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +}; + +extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs); + +#endif diff --git a/components/dfs/include/dfs.h b/components/dfs/include/dfs.h index dc5d311bc6111d8515790f366a53d76c1de05701..04fe6783873d1f54634b882af96aeb3e235b6952 100644 --- a/components/dfs/include/dfs.h +++ b/components/dfs/include/dfs.h @@ -1,37 +1,37 @@ -/* - * File : dfs.h - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - */ - -#ifndef __DFS_H__ -#define __DFS_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -char* dfs_normalize_path(const char* directory, const char* filename); -const char* dfs_subdir(const char* directory, const char* filename); - -/* FD APIs */ -int fd_new(void); -struct dfs_fd* fd_get(int fd); -void fd_put(struct dfs_fd* fd); -int fd_is_open(const char* pathname); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * File : dfs.h + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2005-02-22 Bernard The first version. + */ + +#ifndef __DFS_H__ +#define __DFS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char* dfs_normalize_path(const char* directory, const char* filename); +const char* dfs_subdir(const char* directory, const char* filename); + +/* FD APIs */ +int fd_new(void); +struct dfs_fd* fd_get(int fd); +void fd_put(struct dfs_fd* fd); +int fd_is_open(const char* pathname); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/include/dfs_elm.h b/components/dfs/include/dfs_elm.h index dea71620800fd7ffd4ffbbaadf344c4e578eae5e..c54ee83c1dbb68ea2928b5a3af78263da710afff 100644 --- a/components/dfs/include/dfs_elm.h +++ b/components/dfs/include/dfs_elm.h @@ -1,29 +1,29 @@ -/* -+------------------------------------------------------------------------------ -| Project : Device Filesystem -+------------------------------------------------------------------------------ -| Copyright 2004, 2005 www.fayfayspace.org. -| All rights reserved. -|------------------------------------------------------------------------------ -| File : dfs_efs.h -|------------------------------------------------------------------------------ -| Chang Logs: -| Date Author Notes -| 2010-02-06 Bernard Add elm_init function declaration -+------------------------------------------------------------------------------ -*/ - -#ifndef __DFS_ELM_H__ -#define __DFS_ELM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -int elm_init(void); - -#ifdef __cplusplus -} -#endif - -#endif +/* ++------------------------------------------------------------------------------ +| Project : Device Filesystem ++------------------------------------------------------------------------------ +| Copyright 2004, 2005 www.fayfayspace.org. +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs_efs.h +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author Notes +| 2010-02-06 Bernard Add elm_init function declaration ++------------------------------------------------------------------------------ +*/ + +#ifndef __DFS_ELM_H__ +#define __DFS_ELM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int elm_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/include/dfs_file.h b/components/dfs/include/dfs_file.h index ab75916977cb06b83ef6a8bc9e8ca2759ad96953..3cf66819243f940d0d39d511a928bfbe284fa44f 100644 --- a/components/dfs/include/dfs_file.h +++ b/components/dfs/include/dfs_file.h @@ -1,35 +1,35 @@ -/* -+------------------------------------------------------------------------------ -| Project : Device Filesystem -+------------------------------------------------------------------------------ -| Copyright 2004, 2005 www.fayfayspace.org. -| All rights reserved. -|------------------------------------------------------------------------------ -| File : dfs_raw.h, the raw APIs of Device FileSystem -|------------------------------------------------------------------------------ -| Chang Logs: -| Date Author Notes -| 2005-01-26 ffxz The first version -+------------------------------------------------------------------------------ -*/ - -#ifndef __DFS_RAW_H__ -#define __DFS_RAW_H__ - -#include -#include -#include - -int dfs_file_open(struct dfs_fd* fd, const char *path, int flags); -int dfs_file_close(struct dfs_fd* fd); -int dfs_file_ioctl(struct dfs_fd* fd, int cmd, void *args); -int dfs_file_read(struct dfs_fd* fd, void *buf, rt_size_t len); -int dfs_file_getdents(struct dfs_fd* fd, struct dirent* dirp, rt_size_t nbytes); -int dfs_file_unlink(const char *path); -int dfs_file_write(struct dfs_fd* fd, const void *buf, rt_size_t len); -int dfs_file_lseek(struct dfs_fd* fd, rt_off_t offset); -int dfs_file_stat(const char *path, struct stat *buf); -int dfs_file_rename(const char* oldpath, const char* newpath); - -#endif - +/* ++------------------------------------------------------------------------------ +| Project : Device Filesystem ++------------------------------------------------------------------------------ +| Copyright 2004, 2005 www.fayfayspace.org. +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs_raw.h, the raw APIs of Device FileSystem +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author Notes +| 2005-01-26 ffxz The first version ++------------------------------------------------------------------------------ +*/ + +#ifndef __DFS_RAW_H__ +#define __DFS_RAW_H__ + +#include +#include +#include + +int dfs_file_open(struct dfs_fd* fd, const char *path, int flags); +int dfs_file_close(struct dfs_fd* fd); +int dfs_file_ioctl(struct dfs_fd* fd, int cmd, void *args); +int dfs_file_read(struct dfs_fd* fd, void *buf, rt_size_t len); +int dfs_file_getdents(struct dfs_fd* fd, struct dirent* dirp, rt_size_t nbytes); +int dfs_file_unlink(const char *path); +int dfs_file_write(struct dfs_fd* fd, const void *buf, rt_size_t len); +int dfs_file_lseek(struct dfs_fd* fd, rt_off_t offset); +int dfs_file_stat(const char *path, struct stat *buf); +int dfs_file_rename(const char* oldpath, const char* newpath); + +#endif + diff --git a/components/dfs/include/dfs_fs.h b/components/dfs/include/dfs_fs.h index b04de24f0b23eb746844d85c5c62cfbaeadcc80d..fafac355c1fc3d71d64bd0803a45ec2ca09919ab 100644 --- a/components/dfs/include/dfs_fs.h +++ b/components/dfs/include/dfs_fs.h @@ -1,89 +1,89 @@ -/* - * File : dfs_fs.h - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - */ -#ifndef __DFS_FS_H__ -#define __DFS_FS_H__ - -#include - -/* Pre-declaration */ -struct dfs_filesystem; -struct dfs_fd; - -/* File system operations struct */ -struct dfs_filesystem_operation -{ - char *name; - - /* mount and unmount file system */ - int (*mount) (struct dfs_filesystem* fs, unsigned long rwflag, const void* data); - int (*unmount) (struct dfs_filesystem* fs); - - /* make a file system */ - int (*mkfs) (const char* device_name); - int (*statfs) (struct dfs_filesystem* fs, struct statfs *buf); - - int (*open) (struct dfs_fd* fd); - int (*close) (struct dfs_fd* fd); - int (*ioctl) (struct dfs_fd* fd, int cmd, void *args); - int (*read) (struct dfs_fd* fd, void* buf, rt_size_t count); - int (*write) (struct dfs_fd* fd, const void* buf, rt_size_t count); - int (*flush) (struct dfs_fd* fd); - int (*lseek) (struct dfs_fd* fd, rt_off_t offset); - int (*getdents) (struct dfs_fd* fd, struct dirent* dirp, rt_uint32_t count); - - int (*unlink) (struct dfs_filesystem* fs, const char* pathname); - int (*stat) (struct dfs_filesystem* fs, const char* filename, struct stat* buf); - int (*rename) (struct dfs_filesystem* fs, const char* oldpath, const char* newpath); -}; - -/* Mounted file system */ -struct dfs_filesystem -{ - rt_device_t dev_id; /* Attached device */ - - char* path; /* File system mount point */ - const struct dfs_filesystem_operation* ops; /* Operations for file system type */ - - void *data; /* Specific file system data */ -}; - -/* file system partition table */ -struct dfs_partition -{ - rt_uint8_t type; /* file system type */ - rt_off_t offset; /* partition start offset */ - rt_size_t size; /* partition size */ - rt_sem_t lock; -}; - -int dfs_register(const struct dfs_filesystem_operation* ops); -struct dfs_filesystem* dfs_filesystem_lookup(const char *path); -rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* buf, rt_uint32_t pindex); - -int dfs_mount(const char* device_name, const char* path, - const char* filesystemtype, rt_uint32_t rwflag, const - void* data); -int dfs_unmount(const char *specialfile); - -/* extern variable */ -extern const struct dfs_filesystem_operation* filesystem_operation_table[]; -extern struct dfs_filesystem filesystem_table[]; - -extern char working_directory[]; - -void dfs_lock(void); -void dfs_unlock(void); -int dfs_statfs(const char* path, struct statfs* buffer); - -#endif +/* + * File : dfs_fs.h + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2005-02-22 Bernard The first version. + */ +#ifndef __DFS_FS_H__ +#define __DFS_FS_H__ + +#include + +/* Pre-declaration */ +struct dfs_filesystem; +struct dfs_fd; + +/* File system operations struct */ +struct dfs_filesystem_operation +{ + char *name; + + /* mount and unmount file system */ + int (*mount) (struct dfs_filesystem* fs, unsigned long rwflag, const void* data); + int (*unmount) (struct dfs_filesystem* fs); + + /* make a file system */ + int (*mkfs) (const char* device_name); + int (*statfs) (struct dfs_filesystem* fs, struct statfs *buf); + + int (*open) (struct dfs_fd* fd); + int (*close) (struct dfs_fd* fd); + int (*ioctl) (struct dfs_fd* fd, int cmd, void *args); + int (*read) (struct dfs_fd* fd, void* buf, rt_size_t count); + int (*write) (struct dfs_fd* fd, const void* buf, rt_size_t count); + int (*flush) (struct dfs_fd* fd); + int (*lseek) (struct dfs_fd* fd, rt_off_t offset); + int (*getdents) (struct dfs_fd* fd, struct dirent* dirp, rt_uint32_t count); + + int (*unlink) (struct dfs_filesystem* fs, const char* pathname); + int (*stat) (struct dfs_filesystem* fs, const char* filename, struct stat* buf); + int (*rename) (struct dfs_filesystem* fs, const char* oldpath, const char* newpath); +}; + +/* Mounted file system */ +struct dfs_filesystem +{ + rt_device_t dev_id; /* Attached device */ + + char* path; /* File system mount point */ + const struct dfs_filesystem_operation* ops; /* Operations for file system type */ + + void *data; /* Specific file system data */ +}; + +/* file system partition table */ +struct dfs_partition +{ + rt_uint8_t type; /* file system type */ + rt_off_t offset; /* partition start offset */ + rt_size_t size; /* partition size */ + rt_sem_t lock; +}; + +int dfs_register(const struct dfs_filesystem_operation* ops); +struct dfs_filesystem* dfs_filesystem_lookup(const char *path); +rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* buf, rt_uint32_t pindex); + +int dfs_mount(const char* device_name, const char* path, + const char* filesystemtype, rt_uint32_t rwflag, const + void* data); +int dfs_unmount(const char *specialfile); + +/* extern variable */ +extern const struct dfs_filesystem_operation* filesystem_operation_table[]; +extern struct dfs_filesystem filesystem_table[]; + +extern char working_directory[]; + +void dfs_lock(void); +void dfs_unlock(void); +int dfs_statfs(const char* path, struct statfs* buffer); + +#endif diff --git a/components/dfs/include/dfs_init.h b/components/dfs/include/dfs_init.h index 712ce61156c43511d033221bc7e9427193babb79..bc4e6faab505d96f995890b6f304e85c8ad22065 100644 --- a/components/dfs/include/dfs_init.h +++ b/components/dfs/include/dfs_init.h @@ -1,42 +1,42 @@ -/* - -+------------------------------------------------------------------------------ - -| Project : Device Filesystem - -+------------------------------------------------------------------------------ - -| Copyright 2004, 2005 www.fayfayspace.org. - -| All rights reserved. - -|------------------------------------------------------------------------------ - -| File : dfs_init.h, the initilization definitions of Device FileSystem -|------------------------------------------------------------------------------ -| Chang Logs: - -| Date Author Notes - -| 2005-02-21 ffxz The first version. -+------------------------------------------------------------------------------ -*/ - -#ifndef __DFS_INIT_H__ -#define __DFS_INIT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* initilization of dfs */ -void dfs_init(void); - -/* initilization of dfs with filesystem server */ -void dfs_server_init(void); - -#ifdef __cplusplus -} -#endif - -#endif +/* + ++------------------------------------------------------------------------------ + +| Project : Device Filesystem + ++------------------------------------------------------------------------------ + +| Copyright 2004, 2005 www.fayfayspace.org. + +| All rights reserved. + +|------------------------------------------------------------------------------ + +| File : dfs_init.h, the initilization definitions of Device FileSystem +|------------------------------------------------------------------------------ +| Chang Logs: + +| Date Author Notes + +| 2005-02-21 ffxz The first version. ++------------------------------------------------------------------------------ +*/ + +#ifndef __DFS_INIT_H__ +#define __DFS_INIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* initilization of dfs */ +void dfs_init(void); + +/* initilization of dfs with filesystem server */ +void dfs_server_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/include/dfs_posix.h b/components/dfs/include/dfs_posix.h index ad4d3fc167e37ceed5cd2f4d2bc2746649e0e24d..2eee57a1a80bb5f618405fcd43be8aea23f0de6f 100644 --- a/components/dfs/include/dfs_posix.h +++ b/components/dfs/include/dfs_posix.h @@ -1,116 +1,116 @@ -/* - * File : dfs_def.h - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2009-05-27 Yi.qiu The first version. - * 2010-07-18 Bernard add stat and statfs structure definitions. - * 2011-05-16 Yi.qiu Change parameter name of rename, "new" is C++ key word. - */ -#ifndef __DFS_POSIX_H__ -#define __DFS_POSIX_H__ - -#include -#include - -#ifndef RT_USING_NEWLIB -#define O_RDONLY DFS_O_RDONLY -#define O_WRONLY DFS_O_WRONLY -#define O_RDWR DFS_O_RDWR -#define O_ACCMODE DFS_O_ACCMODE -#define O_CREAT DFS_O_CREAT -#define O_EXCL DFS_O_EXCL -#define O_TRUNC DFS_O_TRUNC -#define O_APPEND DFS_O_APPEND -#define O_DIRECTORY DFS_O_DIRECTORY - -#define S_IFMT DFS_S_IFMT -#define S_IFSOCK DFS_S_IFSOCK -#define S_IFLNK DFS_S_IFLNK -#define S_IFREG DFS_S_IFREG -#define S_IFBLK DFS_S_IFBLK -#define S_IFDIR DFS_S_IFDIR -#define S_IFCHR DFS_S_IFCHR -#define S_IFIFO DFS_S_IFIFO -#define S_ISUID DFS_S_ISUID -#define S_ISGID DFS_S_ISGID -#define S_ISVTX DFS_S_ISVTX - -#define S_ISLNK(m) (((m) & DFS_S_IFMT) == DFS_S_IFLNK) -#define S_ISREG(m) (((m) & DFS_S_IFMT) == DFS_S_IFREG) -#define S_ISDIR(m) (((m) & DFS_S_IFMT) == DFS_S_IFDIR) -#define S_ISCHR(m) (((m) & DFS_S_IFMT) == DFS_S_IFCHR) -#define S_ISBLK(m) (((m) & DFS_S_IFMT) == DFS_S_IFBLK) -#define S_ISFIFO(m) (((m) & DFS_S_IFMT) == DFS_S_IFIFO) -#define S_ISSOCK(m) (((m) & DFS_S_IFMT) == DFS_S_IFSOCK) - -#define S_IRWXU DFS_S_IRWXU -#define S_IRUSR DFS_S_IRUSR -#define S_IWUSR DFS_S_IWUSR -#define S_IXUSR DFS_S_IXUSR - -#define S_IRWXG DFS_S_IRWXG -#define S_IRGRP DFS_S_IRGRP -#define S_IWGRP DFS_S_IWGRP -#define S_IXGRP DFS_S_IXGRP - -#define S_IRWXO DFS_S_IRWXO -#define S_IROTH DFS_S_IROTH -#define S_IWOTH DFS_S_IWOTH -#define S_IXOTH DFS_S_IXOTH - -#if defined(__CC_ARM) -#include -#else -#define SEEK_SET DFS_SEEK_SET -#define SEEK_CUR DFS_SEEK_CUR -#define SEEK_END DFS_SEEK_END -#endif - -typedef struct -{ - int fd; /* directory file */ - char buf[512]; - int num; - int cur; -} DIR; - -/* directory api*/ -int mkdir (const char *path, mode_t mode); -DIR* opendir(const char* name); -struct dirent* readdir(DIR *d); -long telldir(DIR *d); -void seekdir(DIR *d, off_t offset); -void rewinddir(DIR *d); -int closedir(DIR* d); - -#else -/* use newlib header file */ -#include -#endif - -/* file api*/ -int open(const char *file, int flags, int mode); -int close(int d); -int read(int fd, void *buf, size_t len); -int write(int fd, const void *buf, size_t len); -off_t lseek(int fd, off_t offset, int whence); -int rename(const char *from, const char *to); -int unlink(const char *pathname); -int stat(const char *file, struct stat *buf); -int fstat(int fildes, struct stat *buf); -int statfs(const char *path, struct statfs *buf); - -/* directory api*/ -int rmdir(const char *path); -int chdir(const char *path); -char *getcwd(char *buf, size_t size); - -#endif - +/* + * File : dfs_def.h + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2009-05-27 Yi.qiu The first version. + * 2010-07-18 Bernard add stat and statfs structure definitions. + * 2011-05-16 Yi.qiu Change parameter name of rename, "new" is C++ key word. + */ +#ifndef __DFS_POSIX_H__ +#define __DFS_POSIX_H__ + +#include +#include + +#ifndef RT_USING_NEWLIB +#define O_RDONLY DFS_O_RDONLY +#define O_WRONLY DFS_O_WRONLY +#define O_RDWR DFS_O_RDWR +#define O_ACCMODE DFS_O_ACCMODE +#define O_CREAT DFS_O_CREAT +#define O_EXCL DFS_O_EXCL +#define O_TRUNC DFS_O_TRUNC +#define O_APPEND DFS_O_APPEND +#define O_DIRECTORY DFS_O_DIRECTORY + +#define S_IFMT DFS_S_IFMT +#define S_IFSOCK DFS_S_IFSOCK +#define S_IFLNK DFS_S_IFLNK +#define S_IFREG DFS_S_IFREG +#define S_IFBLK DFS_S_IFBLK +#define S_IFDIR DFS_S_IFDIR +#define S_IFCHR DFS_S_IFCHR +#define S_IFIFO DFS_S_IFIFO +#define S_ISUID DFS_S_ISUID +#define S_ISGID DFS_S_ISGID +#define S_ISVTX DFS_S_ISVTX + +#define S_ISLNK(m) (((m) & DFS_S_IFMT) == DFS_S_IFLNK) +#define S_ISREG(m) (((m) & DFS_S_IFMT) == DFS_S_IFREG) +#define S_ISDIR(m) (((m) & DFS_S_IFMT) == DFS_S_IFDIR) +#define S_ISCHR(m) (((m) & DFS_S_IFMT) == DFS_S_IFCHR) +#define S_ISBLK(m) (((m) & DFS_S_IFMT) == DFS_S_IFBLK) +#define S_ISFIFO(m) (((m) & DFS_S_IFMT) == DFS_S_IFIFO) +#define S_ISSOCK(m) (((m) & DFS_S_IFMT) == DFS_S_IFSOCK) + +#define S_IRWXU DFS_S_IRWXU +#define S_IRUSR DFS_S_IRUSR +#define S_IWUSR DFS_S_IWUSR +#define S_IXUSR DFS_S_IXUSR + +#define S_IRWXG DFS_S_IRWXG +#define S_IRGRP DFS_S_IRGRP +#define S_IWGRP DFS_S_IWGRP +#define S_IXGRP DFS_S_IXGRP + +#define S_IRWXO DFS_S_IRWXO +#define S_IROTH DFS_S_IROTH +#define S_IWOTH DFS_S_IWOTH +#define S_IXOTH DFS_S_IXOTH + +#if defined(__CC_ARM) +#include +#else +#define SEEK_SET DFS_SEEK_SET +#define SEEK_CUR DFS_SEEK_CUR +#define SEEK_END DFS_SEEK_END +#endif + +typedef struct +{ + int fd; /* directory file */ + char buf[512]; + int num; + int cur; +} DIR; + +/* directory api*/ +int mkdir (const char *path, mode_t mode); +DIR* opendir(const char* name); +struct dirent* readdir(DIR *d); +long telldir(DIR *d); +void seekdir(DIR *d, off_t offset); +void rewinddir(DIR *d); +int closedir(DIR* d); + +#else +/* use newlib header file */ +#include +#endif + +/* file api*/ +int open(const char *file, int flags, int mode); +int close(int d); +int read(int fd, void *buf, size_t len); +int write(int fd, const void *buf, size_t len); +off_t lseek(int fd, off_t offset, int whence); +int rename(const char *from, const char *to); +int unlink(const char *pathname); +int stat(const char *file, struct stat *buf); +int fstat(int fildes, struct stat *buf); +int statfs(const char *path, struct statfs *buf); + +/* directory api*/ +int rmdir(const char *path); +int chdir(const char *path); +char *getcwd(char *buf, size_t size); + +#endif + diff --git a/components/dfs/src/dfs.c b/components/dfs/src/dfs.c index eaf865031084d7fb55b34aa45db98e685ffb89b2..bf042a1b58e50106e9ffc7d34aa625b026a8706e 100644 --- a/components/dfs/src/dfs.c +++ b/components/dfs/src/dfs.c @@ -1,365 +1,365 @@ -/* - * File : dfs.c - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - * 2010-07-16 - */ - -#include -#include -#include - -#define NO_WORKING_DIR "system does not support working dir\n" - -/* Global variables */ -const struct dfs_filesystem_operation* filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; -struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX]; - -/* device filesystem lock */ -static struct rt_mutex fslock; - -#ifdef DFS_USING_WORKDIR -char working_directory[DFS_PATH_MAX] = {"/"}; -#endif - -#ifdef DFS_USING_STDIO -struct dfs_fd fd_table[3 + DFS_FD_MAX]; -#else -struct dfs_fd fd_table[DFS_FD_MAX]; -#endif - -/** - * @addtogroup DFS - */ -/*@{*/ - -/** - * this function will initialize device file system. - */ -void dfs_init() -{ - /* clear filesystem operations table */ - rt_memset(filesystem_operation_table, 0, sizeof(filesystem_operation_table)); - /* clear filesystem table */ - rt_memset(filesystem_table, 0, sizeof(filesystem_table)); - /* clean fd table */ - rt_memset(fd_table, 0, sizeof(fd_table)); - - /* create device filesystem lock */ - rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO); - -#ifdef DFS_USING_WORKDIR - /* set current working directory */ - rt_memset(working_directory, 0, sizeof(working_directory)); - working_directory[0] = '/'; -#endif -} - -/** - * this function will lock device file system. - * - * @note please don't invoke it on ISR. - */ -void dfs_lock() -{ - rt_err_t result; - - result = rt_mutex_take(&fslock, RT_WAITING_FOREVER); - if (result != RT_EOK) - { - RT_ASSERT(0); - } -} - -/** - * this function will lock device file system. - * - * @note please don't invoke it on ISR. - */ -void dfs_unlock() -{ - rt_mutex_release(&fslock); -} - -/** - * @ingroup Fd - * This function will allocate a file descriptor. - * - * @return -1 on failed or the allocated file descriptor. - */ -int fd_new(void) -{ - struct dfs_fd* d; - int idx; - - /* lock filesystem */ - dfs_lock(); - - /* find an empty fd entry */ -#ifdef DFS_USING_STDIO - for (idx = 3; idx < DFS_FD_MAX + 3 && fd_table[idx].ref_count > 0; idx++); -#else - for (idx = 0; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++); -#endif - - /* can't find an empty fd entry */ -#ifdef DFS_USING_STDIO - if (idx == DFS_FD_MAX + 3) -#else - if (idx == DFS_FD_MAX) -#endif - { - idx = -1; - goto __result; - } - - d = &(fd_table[idx]); - d->ref_count = 1; - -__result: - dfs_unlock(); - return idx; -} - -/** - * @ingroup Fd - * - * This function will return a file descriptor structure according to file - * descriptor. - * - * @return NULL on on this file descriptor or the file descriptor structure - * pointer. - */ -struct dfs_fd* fd_get(int fd) -{ - struct dfs_fd* d; - -#ifdef DFS_USING_STDIO - if ( fd < 3 || fd > DFS_FD_MAX + 3) return RT_NULL; -#else - if ( fd < 0 || fd > DFS_FD_MAX ) return RT_NULL; -#endif - - dfs_lock(); - d = &fd_table[fd]; - - /* increase the reference count */ - d->ref_count ++; - dfs_unlock(); - - return d; -} - -/** - * @ingroup Fd - * - * This function will put the file descriptor. - */ -void fd_put(struct dfs_fd* fd) -{ - dfs_lock(); - fd->ref_count --; - - /* clear this fd entry */ - if ( fd->ref_count == 0 ) - { - rt_memset(fd, 0, sizeof(struct dfs_fd)); - } - dfs_unlock(); -}; - -/** - * @ingroup Fd - * - * This function will return whether this file has been opend. - * - * @param pathname the file path name. - * - * @return 0 on file has been open successfully, -1 on open failed. - */ -int fd_is_open(const char* pathname) -{ - char *fullpath; - unsigned int index; - struct dfs_filesystem* fs; - struct dfs_fd* fd; - - fullpath = dfs_normalize_path(RT_NULL, pathname); - if (fullpath != RT_NULL) - { - char *mountpath; - fs = dfs_filesystem_lookup(fullpath); - if (fs == RT_NULL) - { - /* can't find mounted file system */ - rt_free(fullpath); - return -1; - } - - /* get file path name under mounted file system */ - if (fs->path[0] == '/' && fs->path[1] == '\0') - mountpath = fullpath; - else mountpath = fullpath + strlen(fs->path); - - dfs_lock(); - for (index = 0; index < DFS_FD_MAX; index++) - { - fd = &(fd_table[index]); - if (fd->fs == RT_NULL) continue; - - if (fd->fs == fs && - strcmp(fd->path, mountpath) == 0) - { - /* found file in file descriptor table */ - rt_free(fullpath); - dfs_unlock(); - return 0; - } - } - dfs_unlock(); - - rt_free(fullpath); - } - - return -1; -} - -/** - * this function will return a sub-path name under directory. - * - * @param directory the parent directory. - * @param filename the filename. - * - * @return the subdir pointer in filename - */ -const char* dfs_subdir(const char* directory, const char* filename) -{ - const char* dir; - - if (strlen(directory) == strlen(filename)) /* it's a same path */ - return RT_NULL; - - dir = filename + strlen(directory); - if ((*dir != '/') && (dir != filename)) - { - dir --; - } - return dir; -} - -/** - * this function will normalize a path according to specified parent directory and file name. - * - * @param directory the parent path - * @param filename the file name - * - * @return the built full file path (absoluted path) - */ -char* dfs_normalize_path(const char* directory, const char* filename) -{ - char *fullpath; - char *dst0, *dst, *src; - - /* check parameters */ - RT_ASSERT(filename != RT_NULL); - -#ifdef DFS_USING_WORKDIR - if (directory == NULL) /* shall use working directory */ - directory = &working_directory[0]; -#else - if ((directory == NULL) && (filename[0] != '/')) - { - rt_kprintf(NO_WORKING_DIR); - return RT_NULL; - } -#endif - - if (filename[0] != '/') /* it's a absolute path, use it directly */ - { - fullpath = rt_malloc(strlen(directory) + strlen(filename) + 2); - - /* join path and file name */ - rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2, - "%s/%s", directory, filename); - } - else - { - fullpath = rt_strdup(filename); /* copy string */ - } - - src = fullpath; - dst = fullpath; - - dst0 = dst; - while (1) - { - char c = *src; - - if (c == '.') - { - if (!src[1]) src ++; /* '.' and ends */ - else if (src[1] == '/') - { - /* './' case */ - src += 2; - - while ((*src == '/') && (*src != '\0')) src ++; - continue; - } - else if (src[1] == '.') - { - if (!src[2]) - { - /* '..' and ends case */ - src += 2; - goto up_one; - } - else if (src[2] == '/') - { - /* '../' case */ - src += 3; - - while ((*src == '/') && (*src != '\0')) src ++; - goto up_one; - } - } - } - - /* copy up the next '/' and erase all '/' */ - while ((c = *src++) != '\0' && c != '/') *dst ++ = c; - - if (c == '/') - { - *dst ++ = '/'; - while (c == '/') c = *src++; - - src --; - } - else if (!c) break; - - continue; - -up_one: - dst --; - if (dst < dst0) { rt_free(fullpath); return NULL;} - while (dst0 < dst && dst[-1] != '/') dst --; - } - - *dst = '\0'; - - /* remove '/' in the end of path if exist */ - dst --; - if ((dst != fullpath) && (*dst == '/')) *dst = '\0'; - - return fullpath; -} -/*@}*/ - +/* + * File : dfs.c + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2005-02-22 Bernard The first version. + * 2010-07-16 + */ + +#include +#include +#include + +#define NO_WORKING_DIR "system does not support working dir\n" + +/* Global variables */ +const struct dfs_filesystem_operation* filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; +struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX]; + +/* device filesystem lock */ +static struct rt_mutex fslock; + +#ifdef DFS_USING_WORKDIR +char working_directory[DFS_PATH_MAX] = {"/"}; +#endif + +#ifdef DFS_USING_STDIO +struct dfs_fd fd_table[3 + DFS_FD_MAX]; +#else +struct dfs_fd fd_table[DFS_FD_MAX]; +#endif + +/** + * @addtogroup DFS + */ +/*@{*/ + +/** + * this function will initialize device file system. + */ +void dfs_init() +{ + /* clear filesystem operations table */ + rt_memset(filesystem_operation_table, 0, sizeof(filesystem_operation_table)); + /* clear filesystem table */ + rt_memset(filesystem_table, 0, sizeof(filesystem_table)); + /* clean fd table */ + rt_memset(fd_table, 0, sizeof(fd_table)); + + /* create device filesystem lock */ + rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO); + +#ifdef DFS_USING_WORKDIR + /* set current working directory */ + rt_memset(working_directory, 0, sizeof(working_directory)); + working_directory[0] = '/'; +#endif +} + +/** + * this function will lock device file system. + * + * @note please don't invoke it on ISR. + */ +void dfs_lock() +{ + rt_err_t result; + + result = rt_mutex_take(&fslock, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + RT_ASSERT(0); + } +} + +/** + * this function will lock device file system. + * + * @note please don't invoke it on ISR. + */ +void dfs_unlock() +{ + rt_mutex_release(&fslock); +} + +/** + * @ingroup Fd + * This function will allocate a file descriptor. + * + * @return -1 on failed or the allocated file descriptor. + */ +int fd_new(void) +{ + struct dfs_fd* d; + int idx; + + /* lock filesystem */ + dfs_lock(); + + /* find an empty fd entry */ +#ifdef DFS_USING_STDIO + for (idx = 3; idx < DFS_FD_MAX + 3 && fd_table[idx].ref_count > 0; idx++); +#else + for (idx = 0; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++); +#endif + + /* can't find an empty fd entry */ +#ifdef DFS_USING_STDIO + if (idx == DFS_FD_MAX + 3) +#else + if (idx == DFS_FD_MAX) +#endif + { + idx = -1; + goto __result; + } + + d = &(fd_table[idx]); + d->ref_count = 1; + +__result: + dfs_unlock(); + return idx; +} + +/** + * @ingroup Fd + * + * This function will return a file descriptor structure according to file + * descriptor. + * + * @return NULL on on this file descriptor or the file descriptor structure + * pointer. + */ +struct dfs_fd* fd_get(int fd) +{ + struct dfs_fd* d; + +#ifdef DFS_USING_STDIO + if ( fd < 3 || fd > DFS_FD_MAX + 3) return RT_NULL; +#else + if ( fd < 0 || fd > DFS_FD_MAX ) return RT_NULL; +#endif + + dfs_lock(); + d = &fd_table[fd]; + + /* increase the reference count */ + d->ref_count ++; + dfs_unlock(); + + return d; +} + +/** + * @ingroup Fd + * + * This function will put the file descriptor. + */ +void fd_put(struct dfs_fd* fd) +{ + dfs_lock(); + fd->ref_count --; + + /* clear this fd entry */ + if ( fd->ref_count == 0 ) + { + rt_memset(fd, 0, sizeof(struct dfs_fd)); + } + dfs_unlock(); +}; + +/** + * @ingroup Fd + * + * This function will return whether this file has been opend. + * + * @param pathname the file path name. + * + * @return 0 on file has been open successfully, -1 on open failed. + */ +int fd_is_open(const char* pathname) +{ + char *fullpath; + unsigned int index; + struct dfs_filesystem* fs; + struct dfs_fd* fd; + + fullpath = dfs_normalize_path(RT_NULL, pathname); + if (fullpath != RT_NULL) + { + char *mountpath; + fs = dfs_filesystem_lookup(fullpath); + if (fs == RT_NULL) + { + /* can't find mounted file system */ + rt_free(fullpath); + return -1; + } + + /* get file path name under mounted file system */ + if (fs->path[0] == '/' && fs->path[1] == '\0') + mountpath = fullpath; + else mountpath = fullpath + strlen(fs->path); + + dfs_lock(); + for (index = 0; index < DFS_FD_MAX; index++) + { + fd = &(fd_table[index]); + if (fd->fs == RT_NULL) continue; + + if (fd->fs == fs && + strcmp(fd->path, mountpath) == 0) + { + /* found file in file descriptor table */ + rt_free(fullpath); + dfs_unlock(); + return 0; + } + } + dfs_unlock(); + + rt_free(fullpath); + } + + return -1; +} + +/** + * this function will return a sub-path name under directory. + * + * @param directory the parent directory. + * @param filename the filename. + * + * @return the subdir pointer in filename + */ +const char* dfs_subdir(const char* directory, const char* filename) +{ + const char* dir; + + if (strlen(directory) == strlen(filename)) /* it's a same path */ + return RT_NULL; + + dir = filename + strlen(directory); + if ((*dir != '/') && (dir != filename)) + { + dir --; + } + return dir; +} + +/** + * this function will normalize a path according to specified parent directory and file name. + * + * @param directory the parent path + * @param filename the file name + * + * @return the built full file path (absoluted path) + */ +char* dfs_normalize_path(const char* directory, const char* filename) +{ + char *fullpath; + char *dst0, *dst, *src; + + /* check parameters */ + RT_ASSERT(filename != RT_NULL); + +#ifdef DFS_USING_WORKDIR + if (directory == NULL) /* shall use working directory */ + directory = &working_directory[0]; +#else + if ((directory == NULL) && (filename[0] != '/')) + { + rt_kprintf(NO_WORKING_DIR); + return RT_NULL; + } +#endif + + if (filename[0] != '/') /* it's a absolute path, use it directly */ + { + fullpath = rt_malloc(strlen(directory) + strlen(filename) + 2); + + /* join path and file name */ + rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2, + "%s/%s", directory, filename); + } + else + { + fullpath = rt_strdup(filename); /* copy string */ + } + + src = fullpath; + dst = fullpath; + + dst0 = dst; + while (1) + { + char c = *src; + + if (c == '.') + { + if (!src[1]) src ++; /* '.' and ends */ + else if (src[1] == '/') + { + /* './' case */ + src += 2; + + while ((*src == '/') && (*src != '\0')) src ++; + continue; + } + else if (src[1] == '.') + { + if (!src[2]) + { + /* '..' and ends case */ + src += 2; + goto up_one; + } + else if (src[2] == '/') + { + /* '../' case */ + src += 3; + + while ((*src == '/') && (*src != '\0')) src ++; + goto up_one; + } + } + } + + /* copy up the next '/' and erase all '/' */ + while ((c = *src++) != '\0' && c != '/') *dst ++ = c; + + if (c == '/') + { + *dst ++ = '/'; + while (c == '/') c = *src++; + + src --; + } + else if (!c) break; + + continue; + +up_one: + dst --; + if (dst < dst0) { rt_free(fullpath); return NULL;} + while (dst0 < dst && dst[-1] != '/') dst --; + } + + *dst = '\0'; + + /* remove '/' in the end of path if exist */ + dst --; + if ((dst != fullpath) && (*dst == '/')) *dst = '\0'; + + return fullpath; +} +/*@}*/ + diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c index 58d57ea3dac50ac49a04790371cd7cc899a69422..f102c15d32cd6c8b5f4218268edd720fc82fba3f 100644 --- a/components/dfs/src/dfs_file.c +++ b/components/dfs/src/dfs_file.c @@ -1,589 +1,589 @@ -/* - * File : dfs_file.c - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - */ -#include -#include - -/** - * @addtogroup FileApi - */ -/*@{*/ - -/** - * this function will open a file which specified by path with specified flags. - * - * @param fd the file descriptor pointer to return the corresponding result. - * @param path the spaciefied file path. - * @param flags the flags for open operator. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_open(struct dfs_fd* fd, const char *path, int flags) -{ - struct dfs_filesystem* fs; - char *fullpath; - int result; - - /* parameter check */ - if ( fd == RT_NULL ) return -DFS_STATUS_EINVAL; - - /* make sure we have an absolute path */ - fullpath = dfs_normalize_path(RT_NULL, path); - if (fullpath == RT_NULL) - { - return -1; - } - - dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath)); - - /* find filesystem */ - fs = dfs_filesystem_lookup(fullpath); - if ( fs == RT_NULL ) - { - rt_free(fullpath); /* release path */ - 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->flags = flags; - fd->size = 0; - fd->pos = 0; - - if (dfs_subdir(fs->path, fullpath) == RT_NULL) - fd->path = rt_strdup("/"); - else - fd->path = rt_strdup(dfs_subdir(fs->path, fullpath)); - rt_free(fullpath); - dfs_log(DFS_DEBUG_INFO, ("actul file path: %s\n", fd->path)); - - /* specific file system open routine */ - if (fs->ops->open == RT_NULL) - { - /* clear fd */ - rt_free(fd->path); - rt_memset(fd, 0, sizeof(*fd)); - - return -DFS_STATUS_ENOSYS; - } - - if ((result = fs->ops->open(fd)) < 0) - { - /* clear fd */ - rt_free(fd->path); - rt_memset(fd, 0, sizeof(*fd)); - - dfs_log(DFS_DEBUG_INFO, ("open failed")); - - return result; - } - - fd->flags |= DFS_F_OPEN; - if ( flags & DFS_O_DIRECTORY ) - { - fd->type = FT_DIRECTORY; - fd->flags |= DFS_F_DIRECTORY; - } - - dfs_log(DFS_DEBUG_INFO, ("open successful")); - return 0; -} - -/** - * this function will close a file descriptor. - * - * @param fd the file descriptor to be closed. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_close(struct dfs_fd* fd) -{ - 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; - - rt_free(fd->path); - rt_memset(fd, 0, sizeof(struct dfs_fd)); - - return result; -} - -/** - * this function will perform a io control on a file descriptor. - * - * @param fd the file descriptor. - * @param cmd the command to send to file descriptor. - * @param args the argument to send to file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_ioctl(struct dfs_fd* fd, int cmd, void *args) -{ - struct dfs_filesystem* fs; - - if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL; - - fs = fd->fs; - if (fs->ops->ioctl != RT_NULL) return fs->ops->ioctl(fd, cmd, args); - - return -DFS_STATUS_ENOSYS; -} - -/** - * this function will read specified length data from a file descriptor to a buffer. - * - * @param fd the file descriptor. - * @param buf the buffer to save the read data. - * @param len the length of data buffer to be read. - * - * @return the actual read data bytes or 0 on end of file or failed. - */ -int dfs_file_read(struct dfs_fd* fd, void *buf, 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; -} - -/** - * this function will fetch directory entries from a directory descriptor. - * - * @param fd the directory decriptor. - * @param dirp the dirent buffer to save result. - * @param nbytes the aviable room in the buffer. - * - * @return the read dirent, others on failed. - */ -int dfs_file_getdents(struct dfs_fd* fd, struct dirent* dirp, rt_size_t nbytes) -{ - struct dfs_filesystem* fs; - - /* parameter check */ - if (fd == RT_NULL || fd->type != FT_DIRECTORY) 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; -} - -/** - * this function will unlink (remove) a specified path file from file system. - * - * @param path the specified path file to be unlinked. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_unlink(const char *path) -{ - int result; - char *fullpath; - struct dfs_filesystem* fs; - - result = DFS_STATUS_OK; - - /* Make sure we have an absolute path */ - fullpath = dfs_normalize_path(RT_NULL, path); - if ( fullpath == RT_NULL) - { - return -DFS_STATUS_EINVAL; - } - - /* get filesystem */ - if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) - { - result = -DFS_STATUS_ENOENT; - goto __exit; - } - - /* Check whether file is already open */ - if (fd_is_open(fullpath) == 0) - { - result = -DFS_STATUS_EBUSY; - goto __exit; - } - - if (fs->ops->unlink != RT_NULL) - { - if (dfs_subdir(fs->path, fullpath) == RT_NULL) - result = fs->ops->unlink(fs, "/"); - else - result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath)); - } - else result = -DFS_STATUS_ENOSYS; - -__exit: - rt_free(fullpath); - return result; -} - -/** - * this function will write some specified length data to file system. - * - * @param fd the file descriptor. - * @param buf the data buffer to be written. - * @param len the data buffer length - * - * @return the actual written data length. - */ -int dfs_file_write(struct dfs_fd* fd, const void *buf, rt_size_t len) -{ - struct dfs_filesystem* fs; - - if (fd == RT_NULL) return -DFS_STATUS_EINVAL; - - fs = fd->fs; - if (fs->ops->write == RT_NULL) return -DFS_STATUS_ENOSYS; - - return fs->ops->write(fd, buf, len); -} - -/** - * this function will flush buffer on a file descriptor. - * - * @param fd the file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_flush(struct dfs_fd* fd) -{ - struct dfs_filesystem* fs; - - if (fd == RT_NULL) return -DFS_STATUS_EINVAL; - - fs = fd->fs; - if (fs->ops->flush == RT_NULL) return -DFS_STATUS_ENOSYS; - - return fs->ops->flush(fd); -} - -/** - * this function will seek the offset for specified file descriptor. - * - * @param fd the file descriptor. - * @param offset the offset to be seeked. - * - * @return the current position after seek. - */ -int dfs_file_lseek(struct dfs_fd* fd, rt_off_t offset) -{ - int result; - struct dfs_filesystem* fs = fd->fs; - - if (fd == RT_NULL) return -DFS_STATUS_EINVAL; - if (fs->ops->lseek == RT_NULL) return -DFS_STATUS_ENOSYS; - - result = fs->ops->lseek(fd, offset); - - /* update current position */ - if (result >= 0) - fd->pos = result; - - return result; -} - -/** - * this function will get file information. - * - * @param path the file path. - * @param buf the data buffer to save stat description. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_stat(const char *path, struct stat *buf) -{ - int result; - char* fullpath; - struct dfs_filesystem* fs; - - fullpath = dfs_normalize_path(RT_NULL, path); - if ( fullpath == RT_NULL ) - { - return -1; - } - - if ((fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) - { - dfs_log(DFS_DEBUG_ERROR, ("can't find mounted filesystem on this path:%s", fullpath)); - rt_free(fullpath); - return -DFS_STATUS_ENOENT; - } - - if ((fullpath[0] == '/' && fullpath[1] == '\0') || - (dfs_subdir(fs->path, fullpath) == RT_NULL)) - { - /* it's the root directory */ - buf->st_dev = 0; - - buf->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | - DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; - buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; - - buf->st_size = 0; - buf->st_mtime = 0; - buf->st_blksize = 512; - - /* release full path */ - rt_free(fullpath); - - return DFS_STATUS_OK; - } - else - { - if (fs->ops->stat == RT_NULL) - { - rt_free(fullpath); - dfs_log(DFS_DEBUG_ERROR, ("the filesystem didn't implement this function")); - return -DFS_STATUS_ENOSYS; - } - - /* get the real file path and get file stat */ - result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf); - } - - rt_free(fullpath); - - return result; -} - -/** - * this funciton will rename an old path name to a new path name. - * - * @param oldpath the old path name. - * @param newpath the new path name. - * - * @return 0 on successful, -1 on failed. - */ -int dfs_file_rename(const char* oldpath, const char* newpath) -{ - int result; - struct dfs_filesystem *oldfs, *newfs; - char *oldfullpath, *newfullpath; - - result = DFS_STATUS_OK; - newfullpath = RT_NULL; - - oldfullpath = dfs_normalize_path(RT_NULL, oldpath); - if ( oldfullpath == RT_NULL ) - { - result = -DFS_STATUS_ENOENT; - goto __exit; - } - - newfullpath = dfs_normalize_path(RT_NULL, newpath); - if ( newfullpath == RT_NULL ) - { - result = -DFS_STATUS_ENOENT; - goto __exit; - } - - if ( (oldfs = dfs_filesystem_lookup(oldfullpath)) == RT_NULL ) - { - result = -DFS_STATUS_ENOENT; - goto __exit; - } - - if ( (newfs = dfs_filesystem_lookup(newfullpath)) == RT_NULL ) - { - result = -DFS_STATUS_ENOENT; - goto __exit; - } - - if ( oldfs == newfs ) - { - if ( oldfs->ops->rename == RT_NULL ) - { - result = -DFS_STATUS_ENOSYS; - goto __exit; - } - - result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath); - goto __exit; - } - - result = -DFS_STATUS_EXDEV; - -__exit: - rt_free(oldfullpath); - rt_free(newfullpath); - - /* not at same file system, return EXDEV */ - return result; -} - -#ifdef RT_USING_FINSH -#include - -static struct dfs_fd fd; -static struct dirent dirent; -void ls(const char* pathname) -{ - struct stat stat; - int length; - char *fullpath, *path; - - fullpath = RT_NULL; - if (pathname == RT_NULL) - { -#ifdef DFS_USING_WORKDIR - /* open current working directory */ - path = rt_strdup(working_directory); -#else - path = rt_strdup("/"); -#endif - if (path == RT_NULL) return ; /* out of memory */ - } - else - { - path = (char*)pathname; - } - - /* list directory */ - if ( dfs_file_open(&fd, path, DFS_O_DIRECTORY) == 0 ) - { - rt_kprintf("Directory %s:\n", path); - do - { - rt_memset(&dirent, 0, sizeof(struct dirent)); - length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent)); - if ( length > 0 ) - { - rt_memset(&stat, 0, sizeof(struct stat)); - - /* build full path for each file */ - fullpath = dfs_normalize_path(path, dirent.d_name); - if (fullpath == RT_NULL) break; - - if (dfs_file_stat(fullpath, &stat) == 0) - { - rt_kprintf("%-20s", dirent.d_name); - if ( DFS_S_ISDIR(stat.st_mode)) - { - rt_kprintf("%-25s\n", ""); - } - else - { - rt_kprintf("%-25lu\n", stat.st_size); - } - } - else - rt_kprintf("BAD file: %s\n", dirent.d_name); - rt_free(fullpath); - } - }while(length > 0); - - dfs_file_close(&fd); - } - else - { - rt_kprintf("No such directory\n"); - } - if (pathname == RT_NULL) rt_free(path); -} -FINSH_FUNCTION_EXPORT(ls, list directory contents) - -void rm(const char* filename) -{ - if (dfs_file_unlink(filename) < 0) - { - rt_kprintf("Delete %s failed\n", filename); - } -} -FINSH_FUNCTION_EXPORT(rm, remove files or directories) - -void cat(const char* filename) -{ - rt_uint32_t length; - char buffer[81]; - - if (dfs_file_open(&fd, filename, DFS_O_RDONLY) < 0) - { - rt_kprintf("Open %s failed\n", filename); - return; - } - - do - { - rt_memset(buffer, 0, sizeof(buffer)); - length = dfs_file_read(&fd, buffer, sizeof(buffer)-1 ); - if (length > 0) - { - rt_kprintf("%s", buffer); - } - }while (length > 0); - - dfs_file_close(&fd); -} -FINSH_FUNCTION_EXPORT(cat, print file) - -#define BUF_SZ 4096 -void copy(const char* src, const char* dst) -{ - struct dfs_fd src_fd; - rt_uint8_t *block_ptr; - rt_uint32_t read_bytes; - - block_ptr = rt_malloc(BUF_SZ); - if (block_ptr == RT_NULL) - { - rt_kprintf("out of memory\n"); - return; - } - - if (dfs_file_open(&src_fd, src, DFS_O_RDONLY) < 0) - { - rt_free(block_ptr); - rt_kprintf("Read %s failed\n", src); - return; - } - if (dfs_file_open(&fd, dst, DFS_O_WRONLY | DFS_O_CREAT) < 0) - { - rt_free(block_ptr); - dfs_file_close(&src_fd); - - rt_kprintf("Write %s failed\n", dst); - return; - } - - do - { - read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ); - if (read_bytes > 0) - { - dfs_file_write(&fd, block_ptr, read_bytes); - } - } while (read_bytes > 0); - - dfs_file_close(&src_fd); - dfs_file_close(&fd); - rt_free(block_ptr); -} -FINSH_FUNCTION_EXPORT(copy, copy source file to destination file) - -#endif -/* @} */ - +/* + * File : dfs_file.c + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2005-02-22 Bernard The first version. + */ +#include +#include + +/** + * @addtogroup FileApi + */ +/*@{*/ + +/** + * this function will open a file which specified by path with specified flags. + * + * @param fd the file descriptor pointer to return the corresponding result. + * @param path the spaciefied file path. + * @param flags the flags for open operator. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_open(struct dfs_fd* fd, const char *path, int flags) +{ + struct dfs_filesystem* fs; + char *fullpath; + int result; + + /* parameter check */ + if ( fd == RT_NULL ) return -DFS_STATUS_EINVAL; + + /* make sure we have an absolute path */ + fullpath = dfs_normalize_path(RT_NULL, path); + if (fullpath == RT_NULL) + { + return -1; + } + + dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath)); + + /* find filesystem */ + fs = dfs_filesystem_lookup(fullpath); + if ( fs == RT_NULL ) + { + rt_free(fullpath); /* release path */ + 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->flags = flags; + fd->size = 0; + fd->pos = 0; + + if (dfs_subdir(fs->path, fullpath) == RT_NULL) + fd->path = rt_strdup("/"); + else + fd->path = rt_strdup(dfs_subdir(fs->path, fullpath)); + rt_free(fullpath); + dfs_log(DFS_DEBUG_INFO, ("actul file path: %s\n", fd->path)); + + /* specific file system open routine */ + if (fs->ops->open == RT_NULL) + { + /* clear fd */ + rt_free(fd->path); + rt_memset(fd, 0, sizeof(*fd)); + + return -DFS_STATUS_ENOSYS; + } + + if ((result = fs->ops->open(fd)) < 0) + { + /* clear fd */ + rt_free(fd->path); + rt_memset(fd, 0, sizeof(*fd)); + + dfs_log(DFS_DEBUG_INFO, ("open failed")); + + return result; + } + + fd->flags |= DFS_F_OPEN; + if ( flags & DFS_O_DIRECTORY ) + { + fd->type = FT_DIRECTORY; + fd->flags |= DFS_F_DIRECTORY; + } + + dfs_log(DFS_DEBUG_INFO, ("open successful")); + return 0; +} + +/** + * this function will close a file descriptor. + * + * @param fd the file descriptor to be closed. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_close(struct dfs_fd* fd) +{ + 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; + + rt_free(fd->path); + rt_memset(fd, 0, sizeof(struct dfs_fd)); + + return result; +} + +/** + * this function will perform a io control on a file descriptor. + * + * @param fd the file descriptor. + * @param cmd the command to send to file descriptor. + * @param args the argument to send to file descriptor. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_ioctl(struct dfs_fd* fd, int cmd, void *args) +{ + struct dfs_filesystem* fs; + + if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL; + + fs = fd->fs; + if (fs->ops->ioctl != RT_NULL) return fs->ops->ioctl(fd, cmd, args); + + return -DFS_STATUS_ENOSYS; +} + +/** + * this function will read specified length data from a file descriptor to a buffer. + * + * @param fd the file descriptor. + * @param buf the buffer to save the read data. + * @param len the length of data buffer to be read. + * + * @return the actual read data bytes or 0 on end of file or failed. + */ +int dfs_file_read(struct dfs_fd* fd, void *buf, 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; +} + +/** + * this function will fetch directory entries from a directory descriptor. + * + * @param fd the directory decriptor. + * @param dirp the dirent buffer to save result. + * @param nbytes the aviable room in the buffer. + * + * @return the read dirent, others on failed. + */ +int dfs_file_getdents(struct dfs_fd* fd, struct dirent* dirp, rt_size_t nbytes) +{ + struct dfs_filesystem* fs; + + /* parameter check */ + if (fd == RT_NULL || fd->type != FT_DIRECTORY) 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; +} + +/** + * this function will unlink (remove) a specified path file from file system. + * + * @param path the specified path file to be unlinked. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_unlink(const char *path) +{ + int result; + char *fullpath; + struct dfs_filesystem* fs; + + result = DFS_STATUS_OK; + + /* Make sure we have an absolute path */ + fullpath = dfs_normalize_path(RT_NULL, path); + if ( fullpath == RT_NULL) + { + return -DFS_STATUS_EINVAL; + } + + /* get filesystem */ + if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) + { + result = -DFS_STATUS_ENOENT; + goto __exit; + } + + /* Check whether file is already open */ + if (fd_is_open(fullpath) == 0) + { + result = -DFS_STATUS_EBUSY; + goto __exit; + } + + if (fs->ops->unlink != RT_NULL) + { + if (dfs_subdir(fs->path, fullpath) == RT_NULL) + result = fs->ops->unlink(fs, "/"); + else + result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath)); + } + else result = -DFS_STATUS_ENOSYS; + +__exit: + rt_free(fullpath); + return result; +} + +/** + * this function will write some specified length data to file system. + * + * @param fd the file descriptor. + * @param buf the data buffer to be written. + * @param len the data buffer length + * + * @return the actual written data length. + */ +int dfs_file_write(struct dfs_fd* fd, const void *buf, rt_size_t len) +{ + struct dfs_filesystem* fs; + + if (fd == RT_NULL) return -DFS_STATUS_EINVAL; + + fs = fd->fs; + if (fs->ops->write == RT_NULL) return -DFS_STATUS_ENOSYS; + + return fs->ops->write(fd, buf, len); +} + +/** + * this function will flush buffer on a file descriptor. + * + * @param fd the file descriptor. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_flush(struct dfs_fd* fd) +{ + struct dfs_filesystem* fs; + + if (fd == RT_NULL) return -DFS_STATUS_EINVAL; + + fs = fd->fs; + if (fs->ops->flush == RT_NULL) return -DFS_STATUS_ENOSYS; + + return fs->ops->flush(fd); +} + +/** + * this function will seek the offset for specified file descriptor. + * + * @param fd the file descriptor. + * @param offset the offset to be seeked. + * + * @return the current position after seek. + */ +int dfs_file_lseek(struct dfs_fd* fd, rt_off_t offset) +{ + int result; + struct dfs_filesystem* fs = fd->fs; + + if (fd == RT_NULL) return -DFS_STATUS_EINVAL; + if (fs->ops->lseek == RT_NULL) return -DFS_STATUS_ENOSYS; + + result = fs->ops->lseek(fd, offset); + + /* update current position */ + if (result >= 0) + fd->pos = result; + + return result; +} + +/** + * this function will get file information. + * + * @param path the file path. + * @param buf the data buffer to save stat description. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_stat(const char *path, struct stat *buf) +{ + int result; + char* fullpath; + struct dfs_filesystem* fs; + + fullpath = dfs_normalize_path(RT_NULL, path); + if ( fullpath == RT_NULL ) + { + return -1; + } + + if ((fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) + { + dfs_log(DFS_DEBUG_ERROR, ("can't find mounted filesystem on this path:%s", fullpath)); + rt_free(fullpath); + return -DFS_STATUS_ENOENT; + } + + if ((fullpath[0] == '/' && fullpath[1] == '\0') || + (dfs_subdir(fs->path, fullpath) == RT_NULL)) + { + /* it's the root directory */ + buf->st_dev = 0; + + buf->st_mode = DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + + buf->st_size = 0; + buf->st_mtime = 0; + buf->st_blksize = 512; + + /* release full path */ + rt_free(fullpath); + + return DFS_STATUS_OK; + } + else + { + if (fs->ops->stat == RT_NULL) + { + rt_free(fullpath); + dfs_log(DFS_DEBUG_ERROR, ("the filesystem didn't implement this function")); + return -DFS_STATUS_ENOSYS; + } + + /* get the real file path and get file stat */ + result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf); + } + + rt_free(fullpath); + + return result; +} + +/** + * this funciton will rename an old path name to a new path name. + * + * @param oldpath the old path name. + * @param newpath the new path name. + * + * @return 0 on successful, -1 on failed. + */ +int dfs_file_rename(const char* oldpath, const char* newpath) +{ + int result; + struct dfs_filesystem *oldfs, *newfs; + char *oldfullpath, *newfullpath; + + result = DFS_STATUS_OK; + newfullpath = RT_NULL; + + oldfullpath = dfs_normalize_path(RT_NULL, oldpath); + if ( oldfullpath == RT_NULL ) + { + result = -DFS_STATUS_ENOENT; + goto __exit; + } + + newfullpath = dfs_normalize_path(RT_NULL, newpath); + if ( newfullpath == RT_NULL ) + { + result = -DFS_STATUS_ENOENT; + goto __exit; + } + + if ( (oldfs = dfs_filesystem_lookup(oldfullpath)) == RT_NULL ) + { + result = -DFS_STATUS_ENOENT; + goto __exit; + } + + if ( (newfs = dfs_filesystem_lookup(newfullpath)) == RT_NULL ) + { + result = -DFS_STATUS_ENOENT; + goto __exit; + } + + if ( oldfs == newfs ) + { + if ( oldfs->ops->rename == RT_NULL ) + { + result = -DFS_STATUS_ENOSYS; + goto __exit; + } + + result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath); + goto __exit; + } + + result = -DFS_STATUS_EXDEV; + +__exit: + rt_free(oldfullpath); + rt_free(newfullpath); + + /* not at same file system, return EXDEV */ + return result; +} + +#ifdef RT_USING_FINSH +#include + +static struct dfs_fd fd; +static struct dirent dirent; +void ls(const char* pathname) +{ + struct stat stat; + int length; + char *fullpath, *path; + + fullpath = RT_NULL; + if (pathname == RT_NULL) + { +#ifdef DFS_USING_WORKDIR + /* open current working directory */ + path = rt_strdup(working_directory); +#else + path = rt_strdup("/"); +#endif + if (path == RT_NULL) return ; /* out of memory */ + } + else + { + path = (char*)pathname; + } + + /* list directory */ + if ( dfs_file_open(&fd, path, DFS_O_DIRECTORY) == 0 ) + { + rt_kprintf("Directory %s:\n", path); + do + { + rt_memset(&dirent, 0, sizeof(struct dirent)); + length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent)); + if ( length > 0 ) + { + rt_memset(&stat, 0, sizeof(struct stat)); + + /* build full path for each file */ + fullpath = dfs_normalize_path(path, dirent.d_name); + if (fullpath == RT_NULL) break; + + if (dfs_file_stat(fullpath, &stat) == 0) + { + rt_kprintf("%-20s", dirent.d_name); + if ( DFS_S_ISDIR(stat.st_mode)) + { + rt_kprintf("%-25s\n", ""); + } + else + { + rt_kprintf("%-25lu\n", stat.st_size); + } + } + else + rt_kprintf("BAD file: %s\n", dirent.d_name); + rt_free(fullpath); + } + }while(length > 0); + + dfs_file_close(&fd); + } + else + { + rt_kprintf("No such directory\n"); + } + if (pathname == RT_NULL) rt_free(path); +} +FINSH_FUNCTION_EXPORT(ls, list directory contents) + +void rm(const char* filename) +{ + if (dfs_file_unlink(filename) < 0) + { + rt_kprintf("Delete %s failed\n", filename); + } +} +FINSH_FUNCTION_EXPORT(rm, remove files or directories) + +void cat(const char* filename) +{ + rt_uint32_t length; + char buffer[81]; + + if (dfs_file_open(&fd, filename, DFS_O_RDONLY) < 0) + { + rt_kprintf("Open %s failed\n", filename); + return; + } + + do + { + rt_memset(buffer, 0, sizeof(buffer)); + length = dfs_file_read(&fd, buffer, sizeof(buffer)-1 ); + if (length > 0) + { + rt_kprintf("%s", buffer); + } + }while (length > 0); + + dfs_file_close(&fd); +} +FINSH_FUNCTION_EXPORT(cat, print file) + +#define BUF_SZ 4096 +void copy(const char* src, const char* dst) +{ + struct dfs_fd src_fd; + rt_uint8_t *block_ptr; + rt_uint32_t read_bytes; + + block_ptr = rt_malloc(BUF_SZ); + if (block_ptr == RT_NULL) + { + rt_kprintf("out of memory\n"); + return; + } + + if (dfs_file_open(&src_fd, src, DFS_O_RDONLY) < 0) + { + rt_free(block_ptr); + rt_kprintf("Read %s failed\n", src); + return; + } + if (dfs_file_open(&fd, dst, DFS_O_WRONLY | DFS_O_CREAT) < 0) + { + rt_free(block_ptr); + dfs_file_close(&src_fd); + + rt_kprintf("Write %s failed\n", dst); + return; + } + + do + { + read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ); + if (read_bytes > 0) + { + dfs_file_write(&fd, block_ptr, read_bytes); + } + } while (read_bytes > 0); + + dfs_file_close(&src_fd); + dfs_file_close(&fd); + rt_free(block_ptr); +} +FINSH_FUNCTION_EXPORT(copy, copy source file to destination file) + +#endif +/* @} */ + diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c index 3a04a05f2832fa0a5b958dc798901ed8002f8a01..da1e456c7b5297bf5067e5a9db7c81354fc9a664 100644 --- a/components/dfs/src/dfs_fs.c +++ b/components/dfs/src/dfs_fs.c @@ -1,460 +1,460 @@ -/* - * File : dfs_fs.c - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2005-02-22 Bernard The first version. - * 2010-06-30 Bernard Optimize for RT-Thread RTOS - * 2011-03-12 Bernard fix the filesystem lookup issue. - */ -#include -#include - -/** - * @addtogroup FsApi - */ -/*@{*/ - -/** - * this function will register a file system instance to device file system. - * - * @param ops the file system instance to be registered. - * - * @return 0 on sucessful, -1 on failed. - */ -int dfs_register(const struct dfs_filesystem_operation* ops) -{ - int index, result; - - result = 0; - - /* lock filesystem */ - dfs_lock(); - - /* 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) - { - result = -1; - 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) - { - result = -1; - goto err; - } - - /* save the filesystem's operations */ - filesystem_operation_table[index] = ops; - -err: - dfs_unlock(); - return result; -} - -/** - * this function will return the file system mounted on specified path. - * - * @param path the specified path string. - * - * @return the found file system or NULL if no file system mounted on - * specified path - */ -struct dfs_filesystem* dfs_filesystem_lookup(const char *path) -{ - struct dfs_filesystem* fs; - rt_uint32_t index, fspath, prefixlen; - - fs = RT_NULL; - prefixlen = 0; - - /* lock filesystem */ - dfs_lock(); - - /* lookup it in the filesystem table */ - for (index = 0; index < DFS_FILESYSTEMS_MAX; index++) - { - if (filesystem_table[index].path == RT_NULL) continue; - else - { - fspath = strlen(filesystem_table[index].path); - if (fspath < prefixlen) continue; - } - - if ((filesystem_table[index].ops != RT_NULL) && - (strncmp(filesystem_table[index].path, path, fspath) == 0)) - { - /* check next path separator */ - if ( fspath > 1 && (strlen(path) > fspath) && - (path[fspath] != '/')) continue; - - fs = &filesystem_table[index]; - prefixlen = fspath; - } - } - - dfs_unlock(); - - return fs; -} - -/** - * this function will fetch the partition table on specified buffer. - * - * @param part the returned partition structure. - * @param buf the buffer contains partition table. - * @param pindex the index of partition table to fetch. - * - * @return RT_EOK on successful or -RT_ERROR on failed. - */ -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; - - rt_kprintf("found part[%d], begin: %d, size: ", - pindex, part->offset * 512); - if ( (part->size>>11) > 0 ) /* MB */ - { - unsigned int part_size; - part_size = part->size>>11;/* MB */ - if ( (part_size>>10) > 0) /* GB */ - { - rt_kprintf("%d.%d%s",part_size>>10,part_size&0x3FF,"GB\r\n");/* GB */ - } - else - { - rt_kprintf("%d.%d%s",part_size,(part->size>>1)&0x3FF,"MB\r\n");/* MB */ - } - } - else - { - rt_kprintf("%d%s",part->size>>1,"KB\r\n");/* KB */ - } - } - else - { - result = -RT_ERROR; - } - - return result; -} - -/** - * this function will mount a file system on a specified path. - * - * @param device_name the name of device which includes a file system. - * @param path the path to mount a file system - * @param filesystemtype the file system type - * @param rwflag the read/write etc. flag. - * @param data the private data(parameter) for this file system. - * - * @return 0 on successful or -1 on failed. - */ -int dfs_mount(const char* device_name, const char* path, - const char* filesystemtype, unsigned long rwflag, const - void* data) -{ - const struct dfs_filesystem_operation* ops; - struct dfs_filesystem* fs; - char *fullpath=RT_NULL; - rt_device_t dev_id; - int index; - - /* open specific device */ - if (device_name != RT_NULL) - { - dev_id = rt_device_find(device_name); - if (dev_id == RT_NULL) - { - /* no this device */ - rt_set_errno(-DFS_STATUS_ENODEV); - return -1; - } - } - else - { - /* which is a non-device filesystem mount */ - dev_id = RT_NULL; - } - - /* find out specific filesystem */ - dfs_lock(); - 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); - dfs_unlock(); - return -1; - } - ops = filesystem_operation_table[index]; - dfs_unlock(); - - /* make full path for special file */ - fullpath = dfs_normalize_path(RT_NULL, path); - if ( fullpath == RT_NULL) /* not an abstract path */ - { - rt_set_errno(-DFS_STATUS_ENOTDIR); - return -1; - } - - /* Check if the path exists or not, raw APIs call, fixme */ - if ( (strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0) ) - { - struct dfs_fd fd; - - if ( dfs_file_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 ) - { - rt_free(fullpath); - rt_set_errno(-DFS_STATUS_ENOTDIR); - return -1; - } - dfs_file_close(&fd); - } - - /* check whether the file system mounted or not */ - dfs_lock(); - 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_ENOSPC); - goto err1; - } - - /* register file system */ - fs = &(filesystem_table[index]); - fs->path = fullpath; - fs->ops = ops; - fs->dev_id = dev_id; - /* release filesystem_table lock */ - dfs_unlock(); - - /* open device, but do not check the status of device */ - if (dev_id != RT_NULL) rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDWR); - - if (ops->mount == RT_NULL) /* there is no mount implementation */ - { - if (dev_id != RT_NULL) rt_device_close(dev_id); - dfs_lock(); - /* clear filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - dfs_unlock(); - - rt_free(fullpath); - rt_set_errno(-DFS_STATUS_ENOSYS); - return -1; - } - /* call mount of this filesystem */ - else if (ops->mount(fs, rwflag, data) < 0) - { - /* close device */ - if (dev_id != RT_NULL) rt_device_close(fs->dev_id); - - /* mount failed */ - dfs_lock(); - /* clear filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - dfs_unlock(); - - rt_free(fullpath); - return -1; - } - - return 0; - -err1: - dfs_unlock(); - if (fullpath != RT_NULL) rt_free(fullpath); - - return -1; -} - -/** - * this function will umount a file system on specified path. - * - * @param specialfile the specified path which mounted a file system. - * - * @return 0 on successful or -1 on failed. - */ -int dfs_unmount(const char *specialfile) -{ - char *fullpath; - struct dfs_filesystem* fs = RT_NULL; - - fullpath = dfs_normalize_path(RT_NULL, specialfile); - if (fullpath == RT_NULL) - { - rt_set_errno(-DFS_STATUS_ENOTDIR); - return -1; - } - - /* lock filesystem */ - dfs_lock(); - - 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 */ - if (fs->dev_id != RT_NULL) - rt_device_close(fs->dev_id); - - /* clear this filesystem table entry */ - rt_memset(fs, 0, sizeof(struct dfs_filesystem)); - - dfs_unlock(); - rt_free(fullpath); - - return 0; - -err1: - dfs_unlock(); - rt_free(fullpath); - - return -1; -} - -/** - * make a file system on the special device - * - * @param fs_name the file system name - * @param device_name the special device name - * - * @return 0 on successful, otherwise failed. - */ -int dfs_mkfs(const char* fs_name, const char* device_name) -{ - int index; - - /* lock filesystem */ - dfs_lock(); - /* find the file system operations */ - for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++) - { - if (filesystem_operation_table[index] != RT_NULL && - strcmp(filesystem_operation_table[index]->name, fs_name) == 0) - { - /* find file system operation */ - const struct dfs_filesystem_operation* ops = filesystem_operation_table[index]; - dfs_unlock(); - - if (ops->mkfs != RT_NULL) - return ops->mkfs(device_name); - - break; - } - } - dfs_unlock(); - - return -1; -} - -/** - * this function will return the information about a mounted file system. - * - * @param path the path which mounted file system. - * @param buffer the buffer to save the returned information. - * - * @return 0 on successful, others on failed. - */ -int dfs_statfs(const char* path, struct statfs* buffer) -{ - struct dfs_filesystem* fs; - - fs = dfs_filesystem_lookup(path); - if (fs != NULL) - { - if (fs->ops->statfs!= RT_NULL) - return fs->ops->statfs(fs, buffer); - } - - return -1; -} - -#ifdef RT_USING_FINSH -#include -void mkfs(const char* fs_name, const char* device_name) -{ - dfs_mkfs(fs_name, device_name); -} -FINSH_FUNCTION_EXPORT(mkfs, make a file system); - -void df(const char* path) -{ - struct statfs buffer; - - if (dfs_statfs(path, &buffer) == 0) - { - rt_kprintf("disk free: %d block[%d bytes per block]\n", buffer.f_bfree, buffer.f_bsize); - } -} -FINSH_FUNCTION_EXPORT(df, get disk free); -#endif - -/* @} */ +/* + * File : dfs_fs.c + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2005-02-22 Bernard The first version. + * 2010-06-30 Bernard Optimize for RT-Thread RTOS + * 2011-03-12 Bernard fix the filesystem lookup issue. + */ +#include +#include + +/** + * @addtogroup FsApi + */ +/*@{*/ + +/** + * this function will register a file system instance to device file system. + * + * @param ops the file system instance to be registered. + * + * @return 0 on sucessful, -1 on failed. + */ +int dfs_register(const struct dfs_filesystem_operation* ops) +{ + int index, result; + + result = 0; + + /* lock filesystem */ + dfs_lock(); + + /* 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) + { + result = -1; + 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) + { + result = -1; + goto err; + } + + /* save the filesystem's operations */ + filesystem_operation_table[index] = ops; + +err: + dfs_unlock(); + return result; +} + +/** + * this function will return the file system mounted on specified path. + * + * @param path the specified path string. + * + * @return the found file system or NULL if no file system mounted on + * specified path + */ +struct dfs_filesystem* dfs_filesystem_lookup(const char *path) +{ + struct dfs_filesystem* fs; + rt_uint32_t index, fspath, prefixlen; + + fs = RT_NULL; + prefixlen = 0; + + /* lock filesystem */ + dfs_lock(); + + /* lookup it in the filesystem table */ + for (index = 0; index < DFS_FILESYSTEMS_MAX; index++) + { + if (filesystem_table[index].path == RT_NULL) continue; + else + { + fspath = strlen(filesystem_table[index].path); + if (fspath < prefixlen) continue; + } + + if ((filesystem_table[index].ops != RT_NULL) && + (strncmp(filesystem_table[index].path, path, fspath) == 0)) + { + /* check next path separator */ + if ( fspath > 1 && (strlen(path) > fspath) && + (path[fspath] != '/')) continue; + + fs = &filesystem_table[index]; + prefixlen = fspath; + } + } + + dfs_unlock(); + + return fs; +} + +/** + * this function will fetch the partition table on specified buffer. + * + * @param part the returned partition structure. + * @param buf the buffer contains partition table. + * @param pindex the index of partition table to fetch. + * + * @return RT_EOK on successful or -RT_ERROR on failed. + */ +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; + + rt_kprintf("found part[%d], begin: %d, size: ", + pindex, part->offset * 512); + if ( (part->size>>11) > 0 ) /* MB */ + { + unsigned int part_size; + part_size = part->size>>11;/* MB */ + if ( (part_size>>10) > 0) /* GB */ + { + rt_kprintf("%d.%d%s",part_size>>10,part_size&0x3FF,"GB\r\n");/* GB */ + } + else + { + rt_kprintf("%d.%d%s",part_size,(part->size>>1)&0x3FF,"MB\r\n");/* MB */ + } + } + else + { + rt_kprintf("%d%s",part->size>>1,"KB\r\n");/* KB */ + } + } + else + { + result = -RT_ERROR; + } + + return result; +} + +/** + * this function will mount a file system on a specified path. + * + * @param device_name the name of device which includes a file system. + * @param path the path to mount a file system + * @param filesystemtype the file system type + * @param rwflag the read/write etc. flag. + * @param data the private data(parameter) for this file system. + * + * @return 0 on successful or -1 on failed. + */ +int dfs_mount(const char* device_name, const char* path, + const char* filesystemtype, unsigned long rwflag, const + void* data) +{ + const struct dfs_filesystem_operation* ops; + struct dfs_filesystem* fs; + char *fullpath=RT_NULL; + rt_device_t dev_id; + int index; + + /* open specific device */ + if (device_name != RT_NULL) + { + dev_id = rt_device_find(device_name); + if (dev_id == RT_NULL) + { + /* no this device */ + rt_set_errno(-DFS_STATUS_ENODEV); + return -1; + } + } + else + { + /* which is a non-device filesystem mount */ + dev_id = RT_NULL; + } + + /* find out specific filesystem */ + dfs_lock(); + 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); + dfs_unlock(); + return -1; + } + ops = filesystem_operation_table[index]; + dfs_unlock(); + + /* make full path for special file */ + fullpath = dfs_normalize_path(RT_NULL, path); + if ( fullpath == RT_NULL) /* not an abstract path */ + { + rt_set_errno(-DFS_STATUS_ENOTDIR); + return -1; + } + + /* Check if the path exists or not, raw APIs call, fixme */ + if ( (strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0) ) + { + struct dfs_fd fd; + + if ( dfs_file_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 ) + { + rt_free(fullpath); + rt_set_errno(-DFS_STATUS_ENOTDIR); + return -1; + } + dfs_file_close(&fd); + } + + /* check whether the file system mounted or not */ + dfs_lock(); + 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_ENOSPC); + goto err1; + } + + /* register file system */ + fs = &(filesystem_table[index]); + fs->path = fullpath; + fs->ops = ops; + fs->dev_id = dev_id; + /* release filesystem_table lock */ + dfs_unlock(); + + /* open device, but do not check the status of device */ + if (dev_id != RT_NULL) rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDWR); + + if (ops->mount == RT_NULL) /* there is no mount implementation */ + { + if (dev_id != RT_NULL) rt_device_close(dev_id); + dfs_lock(); + /* clear filesystem table entry */ + rt_memset(fs, 0, sizeof(struct dfs_filesystem)); + dfs_unlock(); + + rt_free(fullpath); + rt_set_errno(-DFS_STATUS_ENOSYS); + return -1; + } + /* call mount of this filesystem */ + else if (ops->mount(fs, rwflag, data) < 0) + { + /* close device */ + if (dev_id != RT_NULL) rt_device_close(fs->dev_id); + + /* mount failed */ + dfs_lock(); + /* clear filesystem table entry */ + rt_memset(fs, 0, sizeof(struct dfs_filesystem)); + dfs_unlock(); + + rt_free(fullpath); + return -1; + } + + return 0; + +err1: + dfs_unlock(); + if (fullpath != RT_NULL) rt_free(fullpath); + + return -1; +} + +/** + * this function will umount a file system on specified path. + * + * @param specialfile the specified path which mounted a file system. + * + * @return 0 on successful or -1 on failed. + */ +int dfs_unmount(const char *specialfile) +{ + char *fullpath; + struct dfs_filesystem* fs = RT_NULL; + + fullpath = dfs_normalize_path(RT_NULL, specialfile); + if (fullpath == RT_NULL) + { + rt_set_errno(-DFS_STATUS_ENOTDIR); + return -1; + } + + /* lock filesystem */ + dfs_lock(); + + 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 */ + if (fs->dev_id != RT_NULL) + rt_device_close(fs->dev_id); + + /* clear this filesystem table entry */ + rt_memset(fs, 0, sizeof(struct dfs_filesystem)); + + dfs_unlock(); + rt_free(fullpath); + + return 0; + +err1: + dfs_unlock(); + rt_free(fullpath); + + return -1; +} + +/** + * make a file system on the special device + * + * @param fs_name the file system name + * @param device_name the special device name + * + * @return 0 on successful, otherwise failed. + */ +int dfs_mkfs(const char* fs_name, const char* device_name) +{ + int index; + + /* lock filesystem */ + dfs_lock(); + /* find the file system operations */ + for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++) + { + if (filesystem_operation_table[index] != RT_NULL && + strcmp(filesystem_operation_table[index]->name, fs_name) == 0) + { + /* find file system operation */ + const struct dfs_filesystem_operation* ops = filesystem_operation_table[index]; + dfs_unlock(); + + if (ops->mkfs != RT_NULL) + return ops->mkfs(device_name); + + break; + } + } + dfs_unlock(); + + return -1; +} + +/** + * this function will return the information about a mounted file system. + * + * @param path the path which mounted file system. + * @param buffer the buffer to save the returned information. + * + * @return 0 on successful, others on failed. + */ +int dfs_statfs(const char* path, struct statfs* buffer) +{ + struct dfs_filesystem* fs; + + fs = dfs_filesystem_lookup(path); + if (fs != NULL) + { + if (fs->ops->statfs!= RT_NULL) + return fs->ops->statfs(fs, buffer); + } + + return -1; +} + +#ifdef RT_USING_FINSH +#include +void mkfs(const char* fs_name, const char* device_name) +{ + dfs_mkfs(fs_name, device_name); +} +FINSH_FUNCTION_EXPORT(mkfs, make a file system); + +void df(const char* path) +{ + struct statfs buffer; + + if (dfs_statfs(path, &buffer) == 0) + { + rt_kprintf("disk free: %d block[%d bytes per block]\n", buffer.f_bfree, buffer.f_bsize); + } +} +FINSH_FUNCTION_EXPORT(df, get disk free); +#endif + +/* @} */ diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c index c1e80a3d9de00f28651caa470aea348e16adb9e3..f3e6a3edfd64e4e0296e428549353e96feea7818 100644 --- a/components/dfs/src/dfs_posix.c +++ b/components/dfs/src/dfs_posix.c @@ -1,668 +1,668 @@ -/* - * File : dfs_posix.c - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2010, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. - * - * Change Logs: - * Date Author Notes - * 2009-05-27 Yi.qiu The first version - */ - -#include -#include - -/** - * @addtogroup FsPosixApi - */ -/*@{*/ - -/** - * this function is a POSIX compliant version, which will open a file and return - * a file descriptor. - * - * @param file the path name of file. - * @param flags the file open flags. - * @param mode - * - * @return the non-negative integer on successful open, others for failed. - */ -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 = dfs_file_open(d, file, flags); - if (result < 0) - { - rt_set_errno(result); - - /* release the ref-count of fd */ - fd_put(d); - fd_put(d); - - return -1; - } - - /* release the ref-count of fd */ - fd_put(d); - return fd; -} - -/** - * this function is a POSIX compliant version, which will close the open - * file descriptor. - * - * @param fd the file descriptor. - * - * @return 0 on successful, -1 on failed. - */ -int close(int fd) -{ - int result; - struct dfs_fd* d; - - d = fd_get(fd); - if (d == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - result = dfs_file_close(d); - fd_put(d); - - if (result < 0) - { - rt_set_errno(result); - return -1; - } - - fd_put(d); - return 0; -} - -/** - * this function is a POSIX compliant version, which will read specified data buffer - * length for an open file descriptor. - * - * @param fd the file descriptor. - * @param buf the buffer to save the read data. - * @param len the maximal length of data buffer - * - * @return the actual read data buffer length - */ -int read(int fd, void *buf, size_t len) -{ - int result; - struct dfs_fd* d; - - /* get the fd */ - d = fd_get(fd); - if (d == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - result = dfs_file_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; -} - -/** - * this function is a POSIX compliant version, which will write pecified data buffer - * length for an open file descriptor. - * - * @param fd the file descriptor - * @param buf the data buffer to be written. - * @param len the data buffer length. - * - * @return the actual written data buffer length. - */ -int write(int fd, const void *buf, size_t len) -{ - int result; - struct dfs_fd* d; - - /* get the fd */ - d = fd_get(fd); - if (d == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - result = dfs_file_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; -} - -/** - * this function is a POSIX compliant version, which will seek the offset for an - * open file descriptor. - * - * @param fd the file descriptor. - * @param offset the offset to be seeked. - * @param whence the directory of seek. - * - * @return the current file position, or -1 on failed. - */ -off_t lseek(int fd, off_t offset, int whence) -{ - int result; - struct dfs_fd* d; - - d = fd_get(fd); - if (d == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - switch (whence) - { - case DFS_SEEK_SET: - break; - - case DFS_SEEK_CUR: - offset += d->pos; - break; - - case DFS_SEEK_END: - offset += d->size; - break; - } - - result = dfs_file_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 offset; -} - -/** - * this function is a POSIX compliant version, which will rename old file name to - * new file name. - * - * @param old the old file name. - * @param new the new file name. - * - * @return 0 on successful, -1 on failed. - * - * note: the old and new file name must be belong to a same file system. - */ -int rename(const char* old, const char* new) -{ - int result; - - result = dfs_file_rename(old, new); - if (result < 0) - { - rt_set_errno(result); - return -1; - } - return 0; -} - -/** - * this function is a POSIX compliant version, which will unlink (remove) a - * specified path file from file system. - * - * @param pathname the specified path name to be unlinked. - * - * @return 0 on successful, -1 on failed. - */ -int unlink(const char *pathname) -{ - int result; - - result = dfs_file_unlink(pathname); - if (result < 0) - { - rt_set_errno(result); - return -1; - } - return 0; -} - -/** - * this function is a POSIX compliant version, which will get file information. - * - * @param file the file name - * @param buf the data buffer to save stat description. - * - * @return 0 on successful, -1 on failed. - */ -int stat(const char *file, struct stat *buf) -{ - int result; - - result = dfs_file_stat(file, buf); - if (result < 0) - { - rt_set_errno(result); - return -1; - } - return result; -} - -/** - * this function is a POSIX compliant version, which will get file status. - * - * @param fildes the file description - * @param buf the data buffer to save stat description. - */ -int fstat(int fildes, struct stat *buf) -{ - struct dfs_fd* d; - - /* get the fd */ - d = fd_get(fildes); - if (d == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - /* it's the root directory */ - buf->st_dev = 0; - - buf->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | - DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; - if (d->type == FT_DIRECTORY) - { - buf->st_mode &= ~DFS_S_IFREG; - buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; - } - - buf->st_size = d->size; - buf->st_mtime = 0; - buf->st_blksize = 512; - - fd_put(d); - - return DFS_STATUS_OK; -} - -/** - * this function is a POSIX compliant version, which will return the - * information about a mounted file system. - * - * @param path the path which mounted file system. - * @param buf the buffer to save the returned information. - * - * @return 0 on successful, others on failed. - */ -int statfs(const char *path, struct statfs *buf) -{ - int result; - - result = dfs_statfs(path, buf); - if (result < 0) - { - rt_set_errno(result); - return -1; - } - - return result; -} - -/** - * this function is a POSIX compliant version, which will make a directory - * - * @param path the directory path to be made. - * @param mode - * - * @return 0 on successful, others on failed. - */ -int mkdir (const char *path, mode_t mode) -{ - int fd; - struct dfs_fd* d; - int result; - - fd = fd_new(); - if (fd == -1) { rt_kprintf("no fd\n"); return -1; } - - d = fd_get(fd); - - result = dfs_file_open(d, path, DFS_O_DIRECTORY | DFS_O_CREAT); - - if (result < 0) - { - rt_set_errno(result); - fd_put(d); - return -1; - } - - dfs_file_close(d); - fd_put(d); - return 0; -} -#ifdef RT_USING_FINSH -#include -FINSH_FUNCTION_EXPORT(mkdir, create a directory); -#endif - -/** - * this function is a POSIX compliant version, which will remove a directory. - * - * @param pathname the path name to be removed. - * - * @return 0 on sucessfull, others on failed. - */ -int rmdir(const char *pathname) -{ - int result; - - result = dfs_file_unlink(pathname); - if (result < 0) - { - rt_set_errno(result); - return -1; - } - - return 0; -} - -/** - * this function is a POSIX compliant version, which will open a directory. - * - * @param name the path name to be open. - * - * @return the DIR pointer of directory, NULL on open failed. - */ -DIR* opendir(const char* name) -{ - struct dfs_fd* d; - int fd, result; - DIR* t; - - t = RT_NULL; - - /* allocate a fd */ - fd = fd_new(); - if (fd == -1) { rt_kprintf("no fd\n"); return RT_NULL; } - d = fd_get(fd); - - result = dfs_file_open(d, name, DFS_O_RDONLY | DFS_O_DIRECTORY); - if (result >= 0) - { - /* open successfully */ - t = (DIR *) rt_malloc (sizeof(DIR)); - if (t == RT_NULL) - { - dfs_file_close(d); - fd_put(d); - } - else - { - rt_memset(t, 0, sizeof(DIR)); - t->fd = fd; - } - fd_put(d); - return t; - } - - /* open failed */ - fd_put(d); - fd_put(d); - rt_set_errno(result); - - return RT_NULL; -} - -/** - * this function is a POSIX compliant version, which will return a pointer - * to a dirent structure representing the next directory entry in the - * directory stream. - * - * @param d the directory stream pointer. - * - * @return the next directory entry, NULL on the end of directory or failed. - */ -struct dirent* readdir(DIR *d) -{ - int result; - struct dfs_fd* fd; - - fd = fd_get(d->fd); - if (fd == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return RT_NULL; - } - - if (!d->num || (d->cur += ((struct dirent*)(d->buf + d->cur))->d_reclen) >= d->num) - { - /* get a new entry */ - result = dfs_file_getdents(fd, (struct dirent*)d->buf, sizeof(d->buf) - 1); - if (result <= 0) - { - rt_set_errno(result); - fd_put(fd); - - return RT_NULL; - } - - d->num = result; - d->cur = 0; /* current entry index */ - } - - fd_put(fd); - return (struct dirent*)(d->buf+d->cur); -} - -/** - * this function is a POSIX compliant version, which will return current - * location in directory stream. - * - * @param d the directory stream pointer. - * - * @return the current location in directory stream. - */ -long telldir(DIR *d) -{ - struct dfs_fd* fd; - long result; - - fd = fd_get(d->fd); - if (fd == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return 0; - } - - result = fd->pos - d->num + d->cur; - fd_put(fd); - - return result; -} - -/** - * this function is a POSIX compliant version, which will set position of - * next directory structure in the directory stream. - * - * @param d the directory stream. - * @param offset the offset in directory stream. - */ -void seekdir(DIR *d, off_t offset) -{ - struct dfs_fd* fd; - - fd = fd_get(d->fd); - if (fd == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return ; - } - - /* seek to the offset position of directory */ - if (dfs_file_lseek(fd, offset) >= 0) d->num = d->cur = 0; - fd_put(fd); -} - -/** - * this function is a POSIX compliant version, which will reset directory stream. - * - * @param d the directory stream. - */ -void rewinddir(DIR *d) -{ - struct dfs_fd* fd; - - fd = fd_get(d->fd); - if (fd == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return ; - } - - /* seek to the beginning of directory */ - if (dfs_file_lseek(fd, 0) >= 0) d->num = d->cur = 0; - fd_put(fd); -} - -/** - * this function is a POSIX compliant version, which will close a directory - * stream. - * - * @param d the directory stream. - * - * @return 0 on successful, -1 on failed. - */ -int closedir(DIR* d) -{ - int result; - struct dfs_fd* fd; - - fd = fd_get(d->fd); - if (fd == RT_NULL) - { - rt_set_errno(-RT_ERROR); - return -1; - } - - result = dfs_file_close(fd); - fd_put(fd); - - fd_put(fd); - rt_free(d); - - if (result < 0) - { - rt_set_errno(result); - return -1; - } - else return 0; -} - -#ifdef DFS_USING_WORKDIR -/** - * this function is a POSIX compliant version, which will change working directory. - * - * @param path the path name to be changed to. - * - * @return 0 on successful, -1 on failed. - */ -int chdir(const char *path) -{ - char* fullpath; - DIR* d; - - if(path == RT_NULL) - { - dfs_lock(); - rt_kprintf("%s\n", working_directory); - dfs_unlock(); - return 0; - } - - if (rt_strlen(path) > DFS_PATH_MAX) - return -1; - - fullpath = dfs_normalize_path(NULL, path); - if (fullpath == RT_NULL) - return -1; /* build path failed */ - - dfs_lock(); - d = opendir(fullpath); - if (d == RT_NULL) - { - rt_free(fullpath); - /* this is a not exist directory */ - dfs_unlock(); - return -1; - } - - /* close directory stream */ - closedir(d); - - /* copy full path to working directory */ - strncpy(working_directory, fullpath, DFS_PATH_MAX); - rt_free(fullpath); /* release normalize directory path name */ - - dfs_unlock(); - - return 0; -} -#ifdef RT_USING_FINSH -FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory); -#endif -#endif - -/** - * this function is a POSIX compliant version, which will return current - * working directory. - * - * @param buf the returned current directory. - * @param size the buffer size. - * - * @return the returned current directory. - */ -char *getcwd(char *buf, size_t size) -{ -#ifdef DFS_USING_WORKDIR - rt_enter_critical(); - rt_strncpy(buf, working_directory, size); - rt_exit_critical(); -#else - rt_kprintf("WARNING: not support working directory\n"); -#endif - return buf; -} - -/* @} */ +/* + * File : dfs_posix.c + * This file is part of Device File System in RT-Thread RTOS + * COPYRIGHT (C) 2004-2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE. + * + * Change Logs: + * Date Author Notes + * 2009-05-27 Yi.qiu The first version + */ + +#include +#include + +/** + * @addtogroup FsPosixApi + */ +/*@{*/ + +/** + * this function is a POSIX compliant version, which will open a file and return + * a file descriptor. + * + * @param file the path name of file. + * @param flags the file open flags. + * @param mode + * + * @return the non-negative integer on successful open, others for failed. + */ +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 = dfs_file_open(d, file, flags); + if (result < 0) + { + rt_set_errno(result); + + /* release the ref-count of fd */ + fd_put(d); + fd_put(d); + + return -1; + } + + /* release the ref-count of fd */ + fd_put(d); + return fd; +} + +/** + * this function is a POSIX compliant version, which will close the open + * file descriptor. + * + * @param fd the file descriptor. + * + * @return 0 on successful, -1 on failed. + */ +int close(int fd) +{ + int result; + struct dfs_fd* d; + + d = fd_get(fd); + if (d == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + result = dfs_file_close(d); + fd_put(d); + + if (result < 0) + { + rt_set_errno(result); + return -1; + } + + fd_put(d); + return 0; +} + +/** + * this function is a POSIX compliant version, which will read specified data buffer + * length for an open file descriptor. + * + * @param fd the file descriptor. + * @param buf the buffer to save the read data. + * @param len the maximal length of data buffer + * + * @return the actual read data buffer length + */ +int read(int fd, void *buf, size_t len) +{ + int result; + struct dfs_fd* d; + + /* get the fd */ + d = fd_get(fd); + if (d == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + result = dfs_file_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; +} + +/** + * this function is a POSIX compliant version, which will write pecified data buffer + * length for an open file descriptor. + * + * @param fd the file descriptor + * @param buf the data buffer to be written. + * @param len the data buffer length. + * + * @return the actual written data buffer length. + */ +int write(int fd, const void *buf, size_t len) +{ + int result; + struct dfs_fd* d; + + /* get the fd */ + d = fd_get(fd); + if (d == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + result = dfs_file_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; +} + +/** + * this function is a POSIX compliant version, which will seek the offset for an + * open file descriptor. + * + * @param fd the file descriptor. + * @param offset the offset to be seeked. + * @param whence the directory of seek. + * + * @return the current file position, or -1 on failed. + */ +off_t lseek(int fd, off_t offset, int whence) +{ + int result; + struct dfs_fd* d; + + d = fd_get(fd); + if (d == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + switch (whence) + { + case DFS_SEEK_SET: + break; + + case DFS_SEEK_CUR: + offset += d->pos; + break; + + case DFS_SEEK_END: + offset += d->size; + break; + } + + result = dfs_file_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 offset; +} + +/** + * this function is a POSIX compliant version, which will rename old file name to + * new file name. + * + * @param old the old file name. + * @param new the new file name. + * + * @return 0 on successful, -1 on failed. + * + * note: the old and new file name must be belong to a same file system. + */ +int rename(const char* old, const char* new) +{ + int result; + + result = dfs_file_rename(old, new); + if (result < 0) + { + rt_set_errno(result); + return -1; + } + return 0; +} + +/** + * this function is a POSIX compliant version, which will unlink (remove) a + * specified path file from file system. + * + * @param pathname the specified path name to be unlinked. + * + * @return 0 on successful, -1 on failed. + */ +int unlink(const char *pathname) +{ + int result; + + result = dfs_file_unlink(pathname); + if (result < 0) + { + rt_set_errno(result); + return -1; + } + return 0; +} + +/** + * this function is a POSIX compliant version, which will get file information. + * + * @param file the file name + * @param buf the data buffer to save stat description. + * + * @return 0 on successful, -1 on failed. + */ +int stat(const char *file, struct stat *buf) +{ + int result; + + result = dfs_file_stat(file, buf); + if (result < 0) + { + rt_set_errno(result); + return -1; + } + return result; +} + +/** + * this function is a POSIX compliant version, which will get file status. + * + * @param fildes the file description + * @param buf the data buffer to save stat description. + */ +int fstat(int fildes, struct stat *buf) +{ + struct dfs_fd* d; + + /* get the fd */ + d = fd_get(fildes); + if (d == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + /* it's the root directory */ + buf->st_dev = 0; + + buf->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + if (d->type == FT_DIRECTORY) + { + buf->st_mode &= ~DFS_S_IFREG; + buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + } + + buf->st_size = d->size; + buf->st_mtime = 0; + buf->st_blksize = 512; + + fd_put(d); + + return DFS_STATUS_OK; +} + +/** + * this function is a POSIX compliant version, which will return the + * information about a mounted file system. + * + * @param path the path which mounted file system. + * @param buf the buffer to save the returned information. + * + * @return 0 on successful, others on failed. + */ +int statfs(const char *path, struct statfs *buf) +{ + int result; + + result = dfs_statfs(path, buf); + if (result < 0) + { + rt_set_errno(result); + return -1; + } + + return result; +} + +/** + * this function is a POSIX compliant version, which will make a directory + * + * @param path the directory path to be made. + * @param mode + * + * @return 0 on successful, others on failed. + */ +int mkdir (const char *path, mode_t mode) +{ + int fd; + struct dfs_fd* d; + int result; + + fd = fd_new(); + if (fd == -1) { rt_kprintf("no fd\n"); return -1; } + + d = fd_get(fd); + + result = dfs_file_open(d, path, DFS_O_DIRECTORY | DFS_O_CREAT); + + if (result < 0) + { + rt_set_errno(result); + fd_put(d); + return -1; + } + + dfs_file_close(d); + fd_put(d); + return 0; +} +#ifdef RT_USING_FINSH +#include +FINSH_FUNCTION_EXPORT(mkdir, create a directory); +#endif + +/** + * this function is a POSIX compliant version, which will remove a directory. + * + * @param pathname the path name to be removed. + * + * @return 0 on sucessfull, others on failed. + */ +int rmdir(const char *pathname) +{ + int result; + + result = dfs_file_unlink(pathname); + if (result < 0) + { + rt_set_errno(result); + return -1; + } + + return 0; +} + +/** + * this function is a POSIX compliant version, which will open a directory. + * + * @param name the path name to be open. + * + * @return the DIR pointer of directory, NULL on open failed. + */ +DIR* opendir(const char* name) +{ + struct dfs_fd* d; + int fd, result; + DIR* t; + + t = RT_NULL; + + /* allocate a fd */ + fd = fd_new(); + if (fd == -1) { rt_kprintf("no fd\n"); return RT_NULL; } + d = fd_get(fd); + + result = dfs_file_open(d, name, DFS_O_RDONLY | DFS_O_DIRECTORY); + if (result >= 0) + { + /* open successfully */ + t = (DIR *) rt_malloc (sizeof(DIR)); + if (t == RT_NULL) + { + dfs_file_close(d); + fd_put(d); + } + else + { + rt_memset(t, 0, sizeof(DIR)); + t->fd = fd; + } + fd_put(d); + return t; + } + + /* open failed */ + fd_put(d); + fd_put(d); + rt_set_errno(result); + + return RT_NULL; +} + +/** + * this function is a POSIX compliant version, which will return a pointer + * to a dirent structure representing the next directory entry in the + * directory stream. + * + * @param d the directory stream pointer. + * + * @return the next directory entry, NULL on the end of directory or failed. + */ +struct dirent* readdir(DIR *d) +{ + int result; + struct dfs_fd* fd; + + fd = fd_get(d->fd); + if (fd == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return RT_NULL; + } + + if (!d->num || (d->cur += ((struct dirent*)(d->buf + d->cur))->d_reclen) >= d->num) + { + /* get a new entry */ + result = dfs_file_getdents(fd, (struct dirent*)d->buf, sizeof(d->buf) - 1); + if (result <= 0) + { + rt_set_errno(result); + fd_put(fd); + + return RT_NULL; + } + + d->num = result; + d->cur = 0; /* current entry index */ + } + + fd_put(fd); + return (struct dirent*)(d->buf+d->cur); +} + +/** + * this function is a POSIX compliant version, which will return current + * location in directory stream. + * + * @param d the directory stream pointer. + * + * @return the current location in directory stream. + */ +long telldir(DIR *d) +{ + struct dfs_fd* fd; + long result; + + fd = fd_get(d->fd); + if (fd == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return 0; + } + + result = fd->pos - d->num + d->cur; + fd_put(fd); + + return result; +} + +/** + * this function is a POSIX compliant version, which will set position of + * next directory structure in the directory stream. + * + * @param d the directory stream. + * @param offset the offset in directory stream. + */ +void seekdir(DIR *d, off_t offset) +{ + struct dfs_fd* fd; + + fd = fd_get(d->fd); + if (fd == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return ; + } + + /* seek to the offset position of directory */ + if (dfs_file_lseek(fd, offset) >= 0) d->num = d->cur = 0; + fd_put(fd); +} + +/** + * this function is a POSIX compliant version, which will reset directory stream. + * + * @param d the directory stream. + */ +void rewinddir(DIR *d) +{ + struct dfs_fd* fd; + + fd = fd_get(d->fd); + if (fd == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return ; + } + + /* seek to the beginning of directory */ + if (dfs_file_lseek(fd, 0) >= 0) d->num = d->cur = 0; + fd_put(fd); +} + +/** + * this function is a POSIX compliant version, which will close a directory + * stream. + * + * @param d the directory stream. + * + * @return 0 on successful, -1 on failed. + */ +int closedir(DIR* d) +{ + int result; + struct dfs_fd* fd; + + fd = fd_get(d->fd); + if (fd == RT_NULL) + { + rt_set_errno(-RT_ERROR); + return -1; + } + + result = dfs_file_close(fd); + fd_put(fd); + + fd_put(fd); + rt_free(d); + + if (result < 0) + { + rt_set_errno(result); + return -1; + } + else return 0; +} + +#ifdef DFS_USING_WORKDIR +/** + * this function is a POSIX compliant version, which will change working directory. + * + * @param path the path name to be changed to. + * + * @return 0 on successful, -1 on failed. + */ +int chdir(const char *path) +{ + char* fullpath; + DIR* d; + + if(path == RT_NULL) + { + dfs_lock(); + rt_kprintf("%s\n", working_directory); + dfs_unlock(); + return 0; + } + + if (rt_strlen(path) > DFS_PATH_MAX) + return -1; + + fullpath = dfs_normalize_path(NULL, path); + if (fullpath == RT_NULL) + return -1; /* build path failed */ + + dfs_lock(); + d = opendir(fullpath); + if (d == RT_NULL) + { + rt_free(fullpath); + /* this is a not exist directory */ + dfs_unlock(); + return -1; + } + + /* close directory stream */ + closedir(d); + + /* copy full path to working directory */ + strncpy(working_directory, fullpath, DFS_PATH_MAX); + rt_free(fullpath); /* release normalize directory path name */ + + dfs_unlock(); + + return 0; +} +#ifdef RT_USING_FINSH +FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory); +#endif +#endif + +/** + * this function is a POSIX compliant version, which will return current + * working directory. + * + * @param buf the returned current directory. + * @param size the buffer size. + * + * @return the returned current directory. + */ +char *getcwd(char *buf, size_t size) +{ +#ifdef DFS_USING_WORKDIR + rt_enter_critical(); + rt_strncpy(buf, working_directory, size); + rt_exit_critical(); +#else + rt_kprintf("WARNING: not support working directory\n"); +#endif + return buf; +} + +/* @} */