Browse Source

change to UNIX end of line.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1746 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong@gmail.com 14 years ago
parent
commit
b2f9217686

+ 85 - 85
components/dfs/filesystems/devfs/console.c

@@ -1,85 +1,85 @@
-/*
- * RT-Thread Console Device File
- *
- */
-#include <rtthread.h>
-
-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 <rtthread.h>
+
+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);
+	}
+}
+

+ 274 - 274
components/dfs/filesystems/devfs/devfs.c

@@ -1,276 +1,276 @@
-#include <rtthread.h>
-#include <dfs.h>
-#include <dfs_fs.h>
-
-#include "devfs.h"
-
-/* introduce from kservice.c */
+#include <rtthread.h>
+#include <dfs.h>
+#include <dfs_fs.h>
+
+#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;
+}
+

+ 8 - 8
components/dfs/filesystems/devfs/devfs.h

@@ -1,8 +1,8 @@
-#ifndef __DEVICE_FS_H__
-#define __DEVICE_FS_H__
-
-#include <rtthread.h>
-
-int devfs_init(void);
-
-#endif
+#ifndef __DEVICE_FS_H__
+#define __DEVICE_FS_H__
+
+#include <rtthread.h>
+
+int devfs_init(void);
+
+#endif

+ 104 - 104
components/dfs/filesystems/nfs/rpc/auth.h

@@ -1,104 +1,104 @@
-#ifndef __AUTH_H__
-#define __AUTH_H__
-
-#include <rpc/xdr.h>
-
-/*
- * 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 <rpc/xdr.h>
+
+/*
+ * 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

+ 60 - 60
components/dfs/filesystems/nfs/rpc/pmap.c

@@ -1,60 +1,60 @@
-#include "pmap.h"
-#include "clnt.h"
-#include <rpc/rpc.h>
-
-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, &regs->pm_prog) &&
-		xdr_u_long(xdrs, &regs->pm_vers) &&
-		xdr_u_long(xdrs, &regs->pm_prot))
-			return (xdr_u_long(xdrs, &regs->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 <rpc/rpc.h>
+
+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, &regs->pm_prog) &&
+		xdr_u_long(xdrs, &regs->pm_vers) &&
+		xdr_u_long(xdrs, &regs->pm_prot))
+			return (xdr_u_long(xdrs, &regs->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);
+}

+ 58 - 58
components/dfs/filesystems/nfs/rpc/pmap.h

@@ -1,58 +1,58 @@
-#ifndef __RPC_PMAP_PROT_H__
-#define __RPC_PMAP_PROT_H__
-
-#include <rpc/xdr.h>
-
-/* 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 <rpc/xdr.h>
+
+/* 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

+ 37 - 37
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 <string.h>
-
-#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 <string.h>
+
+#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

+ 29 - 29
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

+ 35 - 35
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 <dfs_def.h>
-#include <dfs.h>
-#include <dfs_fs.h>
-
-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 <dfs_def.h>
+#include <dfs.h>
+#include <dfs_fs.h>
+
+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
+

+ 89 - 89
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 <dfs_def.h>
-
-/* 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 <dfs_def.h>
+
+/* 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

+ 42 - 42
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

+ 116 - 116
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 <dfs_file.h>
-#include <dfs_def.h>
-
-#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 <stdio.h>
-#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 <sys/stat.h>
-#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 <dfs_file.h>
+#include <dfs_def.h>
+
+#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 <stdio.h>
+#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 <sys/stat.h>
+#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
+

+ 365 - 365
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 <dfs.h>
-#include <dfs_fs.h>
-#include <dfs_file.h>
-
-#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 <dfs.h>
+#include <dfs_fs.h>
+#include <dfs_file.h>
+
+#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;
+}
+/*@}*/
+

+ 589 - 589
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 <dfs.h>
-#include <dfs_file.h>
-
-/**
- * @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 <finsh.h>
-
-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", "<DIR>");
-					}
-					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 <dfs.h>
+#include <dfs_file.h>
+
+/**
+ * @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 <finsh.h>
+
+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", "<DIR>");
+					}
+					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
+/* @} */
+

+ 460 - 460
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 <dfs_fs.h>
-#include <dfs_file.h>
-
-/**
- * @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 <finsh.h>
-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 <dfs_fs.h>
+#include <dfs_file.h>
+
+/**
+ * @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 <finsh.h>
+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
+
+/* @} */

+ 668 - 668
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 <dfs.h>
-#include <dfs_posix.h>
-
-/**
- * @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.h>
-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 <dfs.h>
+#include <dfs_posix.h>
+
+/**
+ * @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.h>
+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;
+}
+
+/* @} */