add flush, statfs, mkfs to device file system interface.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@802 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
bernard.xiong@gmail.com
2010-07-18 16:15:53 +00:00
parent fd12462d57
commit 33feb176d0
12 changed files with 462 additions and 1594 deletions
+151 -102
View File
@@ -1,36 +1,28 @@
/*
+------------------------------------------------------------------------------
| Project : Device Filesystem
+------------------------------------------------------------------------------
| Copyright 2004, 2005 www.fayfayspace.org.
| All rights reserved.
|------------------------------------------------------------------------------
| File : dfs_fs.c, the filesystem related implementations of Device FileSystem
|------------------------------------------------------------------------------
| Chang Logs:
| Date Author Notes
| 2005-02-22 ffxz The first version.
+------------------------------------------------------------------------------
*/
* 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
*/
#include <dfs_fs.h>
#include <dfs_raw.h>
#include <dfs_util.h>
#include <dfs_file.h>
#include <string.h>
/*
+------------------------------------------------------------------------------
| Function : dfs_register
+------------------------------------------------------------------------------
| Description : registers a filesystem
|
| Parameters : ops, the implementation of filesystem
| Returns : the status of register
| 0 , successful
| -1, failed
+------------------------------------------------------------------------------
*/
int dfs_register(struct dfs_filesystem_operation* ops)
/**
* 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;
@@ -69,16 +61,14 @@ err:
return result;
}
/*
+------------------------------------------------------------------------------
| Function : dfs_filesystem_lookup
+------------------------------------------------------------------------------
| Description : lookup the mounted filesystem on the specified path
|
| Parameters : path, the specified path string
| Returns : the found filesystem
+------------------------------------------------------------------------------
*/
/**
* 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;
@@ -97,7 +87,7 @@ struct dfs_filesystem* dfs_filesystem_lookup(const char *path)
if (fspath < prefixlen) continue;
if ((filesystem_table[index].ops != RT_NULL) &&
str_is_prefix(filesystem_table[index].path, path) == 0)
strncmp(filesystem_table[index].path, path, fspath) == 0)
{
fs = &filesystem_table[index];
prefixlen = fspath;
@@ -109,6 +99,15 @@ struct dfs_filesystem* dfs_filesystem_lookup(const char *path)
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 */
@@ -146,8 +145,7 @@ rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* bu
part->size = *(dpt+12) | *(dpt+13) << 8 |
*(dpt+14) << 16 | *(dpt+15) << 24;
#ifdef RT_USING_FINSH
rt_kprintf("part[%d], begin: %d, size: ",
rt_kprintf("found part[%d], begin: %d, size: ",
pindex, part->offset * 512);
if ( (part->size>>11) > 0 ) /* MB */
{
@@ -166,7 +164,6 @@ rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* bu
{
rt_kprintf("%d%s",part->size>>1,"KB\r\n");/* KB */
}
#endif
}
else
{
@@ -176,32 +173,23 @@ rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* bu
return result;
}
/*
+------------------------------------------------------------------------------
| Function : dfs_mount
+------------------------------------------------------------------------------
| Description : mount a filesystem to specified path
|
| Parameters : device_name, the implementation of filesystem
| path,
| filesystemtype,
| rwflag,
| data,
| Returns : the status of register
| 0 , successful
| -1, failed
+------------------------------------------------------------------------------
*/
/**
* this function will mount a file system on a specified path.
*
* @param device_name the name of device which includes a file system.
* @param filesystemtype the file system type
* @param rwflag the read/write etc. flag.
* @param data the privated 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)
{
struct dfs_filesystem_operation* ops;
const struct dfs_filesystem_operation* ops;
struct dfs_filesystem* fs;
char *fullpath=RT_NULL;
#ifdef DFS_USING_WORKDIR
char full_path[DFS_PATH_MAX + 1];
#endif
rt_device_t dev_id;
int index;
@@ -240,19 +228,11 @@ int dfs_mount(const char* device_name, const char* path,
dfs_unlock();
/* make full path for special file */
fullpath = (char*)path;
if ( fullpath[0] != '/') /* not an abstract path */
fullpath = dfs_normalize_path(RT_NULL, path);
if ( fullpath == RT_NULL) /* not an abstract path */
{
#ifdef DFS_USING_WORKDIR
/* build full path */
fullpath = full_path;
dfs_lock();
build_fullpath(working_directory, path, fullpath);
dfs_unlock();
#else
rt_set_errno(-DFS_STATUS_ENOTDIR);
return -1;
#endif
}
/* Check if the path exists or not, raw APIs call, fixme */
@@ -260,12 +240,13 @@ int dfs_mount(const char* device_name, const char* path,
{
struct dfs_fd fd;
if ( dfile_raw_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 )
if ( dfs_file_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 )
{
rt_free(fullpath);
rt_set_errno(-DFS_STATUS_ENOTDIR);
return -1;
}
dfile_raw_close(&fd);
dfs_file_close(&fd);
}
/* check whether the file system mounted or not */
@@ -291,7 +272,7 @@ int dfs_mount(const char* device_name, const char* path,
/* register file system */
fs = &(filesystem_table[index]);
strncpy(fs->path, fullpath, strlen(fullpath));
fs->path = fullpath;
fs->ops = ops;
fs->dev_id = dev_id;
/* release filesystem_table lock */
@@ -308,6 +289,7 @@ int dfs_mount(const char* device_name, const char* path,
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
dfs_unlock();
rt_free(fullpath);
rt_set_errno(-DFS_STATUS_ENOSYS);
return -1;
}
@@ -323,6 +305,7 @@ int dfs_mount(const char* device_name, const char* path,
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
dfs_unlock();
rt_free(fullpath);
return -1;
}
@@ -330,42 +313,28 @@ int dfs_mount(const char* device_name, const char* path,
err1:
dfs_unlock();
if (fullpath != RT_NULL) rt_free(fullpath);
return -1;
}
/*
+------------------------------------------------------------------------------
| Function : dfs_unmount
+------------------------------------------------------------------------------
| Description : unmount a filesystem
|
| Parameters :
| Returns : the status of register
| 0 , successful
| -1, failed
+------------------------------------------------------------------------------
*/
/**
* 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;
#ifdef DFS_USING_WORKDIR
char full_path[DFS_PATH_MAX + 1];
#endif
struct dfs_filesystem* fs = RT_NULL;
fullpath = (char*)specialfile;
if ( fullpath[0] != '/')
fullpath = dfs_normalize_path(RT_NULL, specialfile);
if (fullpath == RT_NULL)
{
#ifdef DFS_USING_WORKDIR
/* build full path */
fullpath = full_path;
dfs_lock();
build_fullpath(working_directory, specialfile, fullpath);
dfs_unlock();
#else
rt_set_errno(-DFS_STATUS_ENOTDIR);
return -1;
#endif
}
/* lock filesystem */
@@ -385,11 +354,91 @@ int dfs_unmount(const char *specialfile)
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 dfs_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 dfs_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
-84
View File
@@ -1,84 +0,0 @@
/*
+------------------------------------------------------------------------------
| Project : Device Filesystem
+------------------------------------------------------------------------------
| Copyright 2004, 2005 www.fayfayspace.org.
| All rights reserved.
|------------------------------------------------------------------------------
| File : dfs.c, the implementation of Device FileSystem
|------------------------------------------------------------------------------
| Chang Logs:
| Date Author Notes
| 2002-12-31 ffxz The first version.
| 2005-01-22 ffxz Clean up the code.
+------------------------------------------------------------------------------
*/
#include <dfs_def.h>
#include <dfs_config.h>
#include <dfs_fs.h>
#include <dfs_raw.h>
#include <string.h>
/* Global variables */
struct dfs_filesystem_operation* filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX + 1];
struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX + 1];
/* device filesystem lock */
struct rt_mutex dlock;
#ifdef DFS_USING_WORKDIR
char working_directory[DFS_PATH_MAX + 1];
#endif
#ifdef DFS_USING_STDIO
struct dfs_fd fd_table[3 + DFS_FD_MAX];
#else
struct dfs_fd fd_table[DFS_FD_MAX];
#endif
/*
+------------------------------------------------------------------------------
| Function : dfs_init
+------------------------------------------------------------------------------
| Description : Inits the Device Filesystem
| Parameters : null
| Returns : null
+------------------------------------------------------------------------------
*/
void dfs_init()
{
int index;
/* clear filesystem operations table */
for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX + 1; index++)
filesystem_operation_table[index] = RT_NULL;
/* create device filesystem lock */
rt_mutex_init(&dlock, "dlock", RT_IPC_FLAG_FIFO);
/* clear filesystem table */
rt_memset(filesystem_table, 0, sizeof(filesystem_table));
#ifdef DFS_USING_WORKDIR
/* set current working directory */
strcpy(working_directory, "/");
#endif
/* clean fd table */
rt_memset(fd_table, 0, sizeof(fd_table));
}
void dfs_lock()
{
rt_err_t result;
result = rt_mutex_take(&dlock, RT_WAITING_FOREVER);
RT_ASSERT(result == RT_EOK);
}
void dfs_unlock()
{
rt_mutex_release(&dlock);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-295
View File
@@ -1,295 +0,0 @@
/*
+------------------------------------------------------------------------------
| Project : Device Filesystem
+------------------------------------------------------------------------------
| Copyright 2004, 2005 www.fayfayspace.org.
| All rights reserved.
|------------------------------------------------------------------------------
| File : dfs_utl.c, some misc functions of Device FileSystem
|------------------------------------------------------------------------------
| Chang Logs:
| Date Author Notes
| 2005-01-26 ffxz The first version
+------------------------------------------------------------------------------
*/
#include <string.h>
#include <dfs_fs.h>
#include <dfs_util.h>
/*
+------------------------------------------------------------------------------
| Function : dir_name
+------------------------------------------------------------------------------
| Description : Gets the directory name in specified path string
|
| Parameters : path, the specified path string
| path_name, return the path name in this parameter
| len, the length of path name
| Returns : the status of path_name:
| 0 , successful
| -1, failed
| For Example :
| path, dir_name
| /, /
| /usr, /
| /usr/lib, /usr
| /usr/lib/, /usr
+------------------------------------------------------------------------------
*/
int dir_name(const char* path, char* dirname, int len)
{
int pos;
if ( path[0] == '/' && path[1] == '\0' )
{
*dirname++ = '/';
*dirname = '\0';
return 0;
}
pos = strlen(path);
while ( *(path + pos - 1) =='/' ) pos --;
while ( pos > 0 && *(path + pos - 1) != '/' ) pos --;
while ( pos > 0 && *(path + pos - 1) == '/' ) pos --;
if ( pos > len ) return -1;
if ( pos != 0)
{
memcpy(dirname, path, pos);
*(dirname+pos) = '\0';
}
else
{
*dirname++ = '/';
*dirname = '\0';
}
return 0;
}
/*
+------------------------------------------------------------------------------
| Function : file_name
+------------------------------------------------------------------------------
| Description : Gets the file name in specified path string
|
| Parameters : path, the specified path string
| filename, return the path name in this parameter
| len, the length of file name
| Returns : the status of file_name:
| 0 , successful
| -1, failed
| For Example :
| path, filename
| /, RT_NULL
| /usr, usr
| /usr/lib, lib
| /usr/lib/, lib
+------------------------------------------------------------------------------
*/
int file_name(const char* path, char* filename, int len)
{
int pos, size;
if ( path[0] == '/' && path[1] == '\0' )
{
*filename = '\0';
return 0;
}
pos = strlen(path);
while ( *(path + pos -1)=='/' ) pos --;
size = pos;
while ( *(path + pos -1) != '/' && pos > 0 ) pos --;
if ( size - pos > len ) return -1;
else size = size - pos ;
memcpy(filename, path + pos, size);
*(filename+size) = '\0';
return 0;
}
/*
+------------------------------------------------------------------------------
| Function : next_path_name
+------------------------------------------------------------------------------
| Description : Gets the next directory name from specified path string
|
| Parameters : path, the specified path string
| pos, the specified position of path string
| next, return the next path in this parameter
| Returns : the position of next directory item,
| -1, if pos reach in the end of the specified path string
| For Example :
+------------------------------------------------------------------------------
*/
int next_dir_name(const char* path, int pos, char* next)
{
const char* q;
if ( pos > strlen(path) || pos < 0|| path == RT_NULL ) return -1;
q = path + pos;
/* check for firt '/' */
while ( *q == '/' ) q++;
if ( *q == '\0' )
{
*next = '\0';
return -1;
}
while ( *q != '/' && *q != '\0' )
{
*next++ = *q++;
}
*next = '\0';
return q - path + 1;
}
/*
+------------------------------------------------------------------------------
| Function : build_fullpath
+------------------------------------------------------------------------------
| Description : make up the full path from directory and filename
|
| Parameters : path, the specified path string
| filename, return the path name in this parameter
| fullpath, the returned full path name
| Returns : null
+------------------------------------------------------------------------------
*/
void build_fullpath(const char *directory, const char *filename, char *fullpath)
{
char elem[DFS_PATH_MAX + 1];
int pos, start, len;
len = 0;
/* check parameters */
RT_ASSERT(directory != RT_NULL);
RT_ASSERT(filename != RT_NULL);
RT_ASSERT(fullpath != RT_NULL);
/* copy full of directory */
strncpy(fullpath, directory, DFS_PATH_MAX + 1);
for (pos = 0; filename[pos] != '\0'; )
{
/* strip '//' */
while (filename[pos] == '/') pos++;
/* get the filename element, save to elem array */
for (start = pos; filename[pos] != '/' && filename[pos] != '\0'; pos++)
len = pos - start + 1;
strncpy(elem, filename + start, DFS_PATH_MAX + 1);
/* clear the end of elem */
elem[(len < DFS_PATH_MAX + 1? len : DFS_PATH_MAX + 1)] = '\0';
/* strip '..' */
if (elem[0] == '.' && elem[1] == '.')
{
if (strlen(fullpath) == 0) strcpy(fullpath, ""); /* empty filename */
else if (fullpath[0] == '/' && fullpath[1] !='\0')
{
int i = strlen(fullpath);
while (fullpath[i - 1] == '/') i--;
while (i > 0 && fullpath[i - 1] != '/') i--;
fullpath[i] = '\0';
}
}
/* not '.', copy as normally */
else if (elem[0] != '.')
{
len = strlen(fullpath);
if (len == 0) strncpy(fullpath, elem, DFS_PATH_MAX + 1);
else if (fullpath[len - 1] == '/')
{
if (elem[0] == '/') strncat(fullpath, elem + 1, DFS_PATH_MAX + 1);
else strncat(fullpath, elem, DFS_PATH_MAX + 1);
}
else
{
if (elem[0] == '/') strcat(fullpath, elem);
else
{
strncat(fullpath, "/", DFS_PATH_MAX + 1);
strncat(fullpath + 1, elem, DFS_PATH_MAX + 1);
}
}
}
}
if ( fullpath[0] != '/' && fullpath[(len = strlen(fullpath)) - 1] == '/')
{
fullpath[len - 1] = '\0';
}
}
int str_is_prefix(const char* prefix, const char* str)
{
while ((*prefix) && (*str) && (*prefix == *str))
{
prefix ++;
str ++;
}
if (*prefix == 0) return 0;
return -1;
}
#if !defined(RT_USING_MINILIBC) && !defined(RT_USING_NEWLIB)
#if !defined(__ICCARM__)
char *strrchr(const char *t, int c)
{
register char ch;
register const char *l=0;
ch = c;
for (;;)
{
if ((*t == ch)) l=t;
if ((!*t)) return (char*)l; ++t;
}
}
#endif
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION / 10000 < 35)
int strncasecmp ( const char* s1, const char* s2, size_t len )
{
register unsigned int x2;
register unsigned int x1;
register const char* end = s1 + len;
while (1)
{
if ((s1 >= end) )
return 0;
x2 = *s2 - 'A'; if ((x2 < 26u)) x2 += 32;
x1 = *s1 - 'A'; if ((x1 < 26u)) x1 += 32;
s1++; s2++;
if ((x2 != x1))
break;
if ((x1 == (unsigned int)-'A'))
break;
}
return x1 - x2;
}
#endif /* end of __ARMCC_VERSION */
#endif