diff options
| author | bernard.xiong <[email protected]> | 2009-07-02 22:48:23 +0000 |
|---|---|---|
| committer | bernard.xiong <[email protected]> | 2009-07-02 22:48:23 +0000 |
| commit | bda4730a9482c23083006abea939ee8d95d6ecff (patch) | |
| tree | 83005121824bd50ac74e63688c0d5eac148665f8 /filesystem/dfs | |
| parent | 80c72e66de0b00b1a6de3e3508366a4c3eee458d (diff) | |
import RT-Thread RTOS 0.3.x to Google SVN
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'filesystem/dfs')
53 files changed, 9005 insertions, 0 deletions
diff --git a/filesystem/dfs/config.mk b/filesystem/dfs/config.mk new file mode 100644 index 0000000000..9a8de66a52 --- /dev/null +++ b/filesystem/dfs/config.mk @@ -0,0 +1,40 @@ +#+------------------------------------------------------------------------------ +#| Device FileSystem +#+------------------------------------------------------------------------------ +#| Copyright 2004, 2005 www.fayfayspace.org. +#| All rights reserved. +#+------------------------------------------------------------------------------ +#| File : config.mk, the configuration of makefile +#+------------------------------------------------------------------------------ +#| Chang Logs: +#| Date Author notes +#| 2005-01-22 ffxz The first version. +#+------------------------------------------------------------------------------ + +KERNEL_ROOT=$(DFS_ROOT_DIR)/../.. +include $(KERNEL_ROOT)/config.mk + +CFLAGS +=-I$(KERNEL_ROOT)/include -I$(DFS_ROOT_DIR)/include -I. + +# Source and objects +DFS_SRC = $(DFS_ROOT_DIR)/src/dfs_fs.c $(DFS_ROOT_DIR)/src/dfs_init.c \ + $(DFS_ROOT_DIR)/src/dfs_util.c $(DFS_ROOT_DIR)/src/dfs_raw.c \ + $(DFS_ROOT_DIR)/src/dfs_api.c $(DFS_ROOT_DIR)/src/dfs_task.c \ + $(DFS_ROOT_DIR)/src/dfs_cache.c + +ifneq ($(RT_USING_NEWLIB), 1) +DFS_SRC += $(DFS_ROOT_DIR)/src/dfs_posix.c +endif + +DFS_OBJS= $(DFS_SRC:.c=.o) + +FAT_SRC = $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_init.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_mount.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_fat.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_misc.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_file.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_cache.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_filename.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_direntry.c \ + $(DFS_ROOT_DIR)/filesystems/fatfs/fatfs_mkfs.c +FAT_OBJS = $(FAT_SRC:.c=.o) diff --git a/filesystem/dfs/dfs_config.h b/filesystem/dfs/dfs_config.h new file mode 100644 index 0000000000..378030f742 --- /dev/null +++ b/filesystem/dfs/dfs_config.h @@ -0,0 +1,100 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_opts.h, the option definitions of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-01-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+
+#ifndef __DFS_CONFIG_H__
+#define __DFS_CONFIG_H__
+
+/*
++------------------------------------------------------------------------------
+| Device Manager options
++------------------------------------------------------------------------------
+*/
+/* Device Options parameters */
+#define DEVICES_MAX 8
+#define DEVICE_NAME_MAX 8
+
+/*
++------------------------------------------------------------------------------
+| Device Filesystem options
++------------------------------------------------------------------------------
+*/
+/* the max length of filesystem name */
+#define DFS_FS_NAME_MAX 4
+/* the max type of filesystem */
+#define DFS_FILESYSTEM_TYPES_MAX 2
+
+/* the max length of path name */
+#define DFS_PATH_MAX 256
+/* the max length of file name */
+#define DFS_FILE_MAX 256
+
+/* options for server task */
+#define DFS_MBOX_NUMBER 32
+#define DFS_SERVER_STACK 1024
+#define DFS_SERVER_PRI 110
+#define DFS_SERVER_SLICE 20
+
+/*
++------------------------------------------------------------------------------
+| FAT filesystem options
++------------------------------------------------------------------------------
+*/
+/* file name max length */
+#define FAT_NAME_MAX 256
+/* max number of FAT filesystem */
+#define FATFS_MAX 2
+
+/* the size of sector */
+#define SECTOR_SIZE 512
+
+/* FAT table sector cache options */
+#define FAT_CACHE_SIZE 0x10 /* config parameter */
+#define FAT_CACHE_MASK (FAT_CACHE_SIZE-1)
+
+#define GET16(x) (*(x)) | (*((x)+1) << 8)
+#define GET32(x) (*(x)) | (*((x)+1) << 8) | (*((x)+2) << 16) | (*((x)+3) << 24)
+
+#define SET16(x, v) \
+ do \
+ { \
+ *(x) = (v) & 0x00ff; \
+ (*((x)+1)) = (v) >> 8; \
+ } while ( 0 )
+
+#define SET32(x, v) \
+ do \
+ { \
+ *(x) = (v) & 0x000000ff; \
+ (*((x)+1)) = ((v) >> 8) & 0x000000ff; \
+ (*((x)+2)) = ((v) >> 16) & 0x000000ff; \
+ (*((x)+3)) = ((v) >> 24); \
+ } while ( 0 )
+
+#define DFS_DEBUG_INFO 0x01
+#define DFS_DEBUG_WARNING 0x02
+#define DFS_DEBUG_ERROR 0x04
+
+#define DFS_DEBUG_LEVEL (DFS_DEBUG_INFO | DFS_DEBUG_WARNING | DFS_DEBUG_ERROR)
+
+/* #define DFS_DEBUG */
+#ifdef DFS_DEBUG
+#define dfs_log(level, x) do { if (level & DFS_DEBUG_LEVEL) \
+ {rt_kprintf("DFS %s, %d:", __FILE__, __LINE__); rt_kprintf x; \
+ rt_kprintf ("\n");}}while (0)
+#else
+#define dfs_log(level, x)
+#endif
+
+#endif
diff --git a/filesystem/dfs/filesystems/efsl/CHANGELOG b/filesystem/dfs/filesystems/efsl/CHANGELOG new file mode 100644 index 0000000000..94f188c3d9 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/CHANGELOG @@ -0,0 +1,39 @@ +CHANGEFILE +---------- + +This is the Changefile for the development 0.3 branch of EFSL. +Recording began with EFSL-0.3.3 + +0.3.5 +----- +* Added warning in documentation that it is outdated +* Changed structure definitions +* Implemnted full-feature cp +* Renamed some efsl-functions (all starting with EFSL_) +* Added another example for AVR. +* Updated docs on getting started on AVR. + +0.3.4 +----- +* Fixed avr support +* Created new avr example + makefile +* Some more work on new fsutils + +0.3.3 +----- + +* Renamed src/core to src/base +* Implemented new hwInterface structure + Support for multiple hwEndpoints in one project +* Modified SD_SPI to work as a general protocol +* Modified Linuxfile to the new hwInterface model +* Created a new efs_configger, now supports every + combination of partitions/disc +* Implemented full support for little and big endian + machines, as well as for little and big endian + filesystems +* Created new build system, for multiple platforms, + configurable from one file +* Changes cpo to use the new library functions +* Broke both dsp & atmega support + diff --git a/filesystem/dfs/filesystems/efsl/VERSION b/filesystem/dfs/filesystems/efsl/VERSION new file mode 100644 index 0000000000..dc6910364f --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/VERSION @@ -0,0 +1,3 @@ +efsl-0.3.6
+
+[Embedded Filesystems Library]
diff --git a/filesystem/dfs/filesystems/efsl/src/base/debug.c b/filesystem/dfs/filesystems/efsl/src/base/debug.c new file mode 100644 index 0000000000..05962c6178 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/debug.c @@ -0,0 +1,182 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : debug.c * +* Release : 0.3 - devel * +* Description : These functions are used for debugging output on different * +* environments * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/* COMMENT REGARDING FUNCTION COMMENTS IN THIS FILE + * Only the linuxfile debug functions are commented since all functions + * perform the same logical task. +*/ + +/*****************************************************************************/ +#include "debug.h" +/*****************************************************************************/ + + +/*****************************************************************************/ +#ifdef DEBUG +#ifdef HW_ENDPOINT_LINUX_ALL +/*****************************************************************************/ + +/* **************************************************************************** + * void debug(const eint8 *format, ...) + * Description: This function prints debug output to the screen (target dependant) + * and if DO_FUNC_DEBUG is defined also to a localfile. + * Return value: void +*/ + +void debug(const eint8 *format, ...) +{ + va_list ap; + #ifdef DO_FUNC_DEBUG + euint8 c; + extern FILE* debugfile; + extern volatile euint8 tw; + #endif + + va_start(ap, format); + vprintf(format,ap); + #ifdef DO_FUNC_DEBUG + for(c=0;c<tw+1;c++) + { + fprintf(debugfile," "); + } + vfprintf(debugfile,format,ap); + #endif + va_end(ap); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void debug_funcin(const eint8 *format, ...) + * Description: This function marks the entrance of a function, which + * increments a tabfieldcounter. A tree like structure can the be found in the + * debugging file. + * Return value: void +*/ + +void debug_funcin(const eint8 *format, ...) +{ + #ifdef DO_FUNC_DEBUG + eint8 c; + va_list ap; + extern FILE* debugfile; + extern volatile unsigned char tw; + + if(debugfile==RT_NULL)return; + + for(c=0;c<tw;c++){ + fprintf(debugfile," "); + } + + va_start(ap, format); + vfprintf(debugfile,format,ap); + va_end(ap); + fprintf(debugfile,"\n"); + + tw++; + #endif +} +/*****************************************************************************/ + +/* **************************************************************************** + * void debug_funcout(const eint8 *format, ...) + * Description: Decrements the tabfieldcounter. This function is called everywhere + * a function is left. + * Return value: void +*/ + +void debug_funcout(const eint8 *format, ...) +{ + #ifdef DO_FUNC_DEBUG + eint8 c; + va_list ap; + extern FILE* debugfile; + extern volatile euint8 tw; + + if(debugfile==RT_NULL)return; + + if(tw>0)tw--; + + for(c=0;c<tw;c++){ + fprintf(debugfile," "); + } + + va_start(ap, format); + vfprintf(debugfile,format,ap); + va_end(ap); + fprintf(debugfile,"\n"); + #endif +} +/*****************************************************************************/ + +/* **************************************************************************** + * void debug_init() + * Description: This function optionally opens the debugfile, or does any other + * initialisation to enable debugoutput. + * Return value: void +*/ +void debug_init() +{ + #ifdef DO_FUNC_DEBUG + extern FILE* debugfile; + extern volatile unsigned char tw; + + debugfile=RT_NULL; + tw=0; + + debugfile=fopen("DBG.OUT","w"); + #endif +} +/*****************************************************************************/ + +/* **************************************************************************** + * void debug_end() + * Description: This function closes the debugfile. + * Return value: void +*/ +void debug_end() +{ + #ifdef DO_FUNC_DEBUG + extern FILE* debugfile; + + fflush(debugfile); + fclose(debugfile); + #endif +} +/*****************************************************************************/ + +/*****************************************************************************/ +#endif +#endif +/*****************************************************************************/ + diff --git a/filesystem/dfs/filesystems/efsl/src/base/efs.c b/filesystem/dfs/filesystems/efsl/src/base/efs.c new file mode 100644 index 0000000000..2ac98abb55 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/efs.c @@ -0,0 +1,489 @@ + /* + * File : efs.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, 2007, RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://openlab.rt-thread.com/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-16 Yi.Qiu The first version. + */ + +#include "efs.h" +#include "ls.h" +#include "ui.h" +#include "fat.h" +#include <string.h>
+ +#define EFS_MAX 2 + +struct dfs_filesystem_operation efs; + +/** + * This function will initialize efsl to DFS interface. + *
+ * @return 0 on succesful + */ +int efsl_init() +{ + /* init EFS filesystem operations */ + efs.name[0] = 'e'; + efs.name[1] = 'f'; + efs.name[2] = 's'; + efs.name[3] = '\0'; + + efs.mount = efs_mount; + efs.unmount = efs_unmount; + efs.open = efs_open; + efs.close = efs_close; + efs.ioctl = efs_ioctl; + efs.read = efs_read; + efs.write = efs_write; + efs.lseek = efs_lseek; + efs.getdents= efs_getdents; + efs.unlink = efs_unlink; + efs.stat = efs_stat; + efs.rename = efs_rename; + + /* register EFS file system */ + dfs_register(&efs); + + return 0; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_mount(struct dfs_filesystem* fs) +{ + efsl_fs* efsfs; + int result; + + /* allocate an EFS filesystem entry */
+ efsfs = (efsl_fs*) rt_malloc (sizeof(efsl_fs));
+ + /* init efs filesystem struct */ + efsfs->partition.ioman = rt_malloc(sizeof(IOManager)); + efsfs->partition.ioman->device = fs->dev_id; + + part_initPartition(&efsfs->partition); + ioman_init(efsfs->partition.ioman); + result = fs_initFs(&efsfs->filesystem ,&efsfs->partition);
+ + /* set to DFS filesystem user data */ + fs->data = efsfs; + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_unmount(struct dfs_filesystem* fs) +{ + efsl_fs* efsfs; + + efsfs = (efsl_fs*) fs->data; + if ( efsfs == RT_NULL ) return -DFS_STATUS_EINVAL; + + fs_flushFs(&efsfs->filesystem); + rt_free(efsfs->partition.ioman);
+ rt_free(efsfs); + + fs->data = RT_NULL; + + return 0; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_open(struct dfs_fd* file) +{ + File* efsfile; + DirList* efsdir; + efsl_fs* efsfs = (efsl_fs*)(file->fs->data); + int result = 0; + + /* parameter check */ + if ( file == RT_NULL || file->fs == RT_NULL || + file->fs->data == RT_NULL ) + { + dfs_log(DFS_DEBUG_INFO, ("Invalid argument")); + return -DFS_STATUS_EINVAL; + } + + /* open directory */ + if(file->flags & DFS_O_DIRECTORY) + { + /* write directory is not supported */ + if(file->flags & DFS_O_WRONLY || file->flags & DFS_O_RDWR) + { + dfs_log(DFS_DEBUG_INFO, ("write directory isn't supported")); + return -DFS_STATUS_EISDIR; + } + + /* create directory */ + if(file->flags & DFS_O_CREAT) + { + dfs_log(DFS_DEBUG_INFO, ("create directory")); + result = mk_dir(&efsfs->filesystem, file->path); + if(result < 0) + { + dfs_log(DFS_DEBUG_INFO, ("directory %s has existed", file->path)); + return -DFS_STATUS_EEXIST; + } + } + + efsdir = (DirList*)rt_malloc(sizeof(DirList)); + if(efsdir == RT_NULL) + { + dfs_log(DFS_DEBUG_INFO, ("memory alloc failed")); + return -DFS_STATUS_ENOMEM; + } + + result = ls_openDir(efsdir, &efsfs->filesystem, file->path); + if(result < 0) + { + dfs_log(DFS_DEBUG_INFO, ("open directory %s failed", file->path)); + rt_free(efsdir); + } + else + { + file->data = efsdir; + } + } + /* open file */ + else + { + efsfile = (File *)rt_malloc(sizeof(File)); + if (efsfile == RT_NULL) + { + dfs_log(DFS_DEBUG_INFO, ("memory alloc failed")); + return -DFS_STATUS_ENOMEM; + } + + result = file_fopen(efsfile, &efsfs->filesystem, file->path, file->flags); + if(result < 0) + { + dfs_log(DFS_DEBUG_INFO, ("open file %s failed", file->path)); + rt_free(efsfile); + } + else + { + file->pos = efsfile->FilePtr; + file->size = efsfile->FileSize; + file->data = efsfile; + } + } + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_close(struct dfs_fd* file) +{ + int result = 0; + + if (!file || !(file->flags & DFS_F_OPEN)) return -DFS_STATUS_EBADF;
+ + if(!(file->flags & DFS_F_DIRECTORY)) + result = file_fclose((File *)file->data); + else
+ {
+ dfs_log(DFS_DEBUG_INFO, ("close a directory, %s", file->path)); + }
+ + dfs_log(DFS_DEBUG_INFO, ("close a file, %s", file->path)); + + /* free directory or file */ + rt_free(file->data);
+ file->data = RT_NULL; + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_ioctl(struct dfs_fd* file, int cmd, void* args) +{ + return 0; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_read(struct dfs_fd* file, void* buf, rt_size_t len) +{ + File* efsfile = file->data; + int result = 0; + + /* parameter check */
+ RT_ASSERT(efsfile != RT_NULL);
+ + result = file_read(efsfile, len, buf); + file->pos = efsfile->FilePtr; + + dfs_log(DFS_DEBUG_INFO, ("read file %s %d bytes", file->path, result)); + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_write(struct dfs_fd* file, const void* buf, rt_size_t len) +{ + File* efsfile = file->data; + int result = 0; + + /* parameter check */
+ RT_ASSERT(efsfile != RT_NULL);
+ + result = file_write(efsfile, len, (euint8 *)buf); + file->pos = efsfile->FilePtr; + file->size = efsfile->FileSize; + + dfs_log(DFS_DEBUG_INFO, ("write file %s %d bytes", file->path, result)); + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_lseek(struct dfs_fd* file, rt_off_t offset) +{ + int result = 0; + DirList* efsdir; + efsl_fs* efsfs = (efsl_fs *)file->fs->data;
+ + /* parameter check */
+ RT_ASSERT(efsfs != RT_NULL); + + /* seek directory */ + if(file->flags & DFS_O_DIRECTORY) + { + efsdir = (DirList*)file->data; + + /* only support offset equels zero */ + if(offset == 0) + { + result = ls_openDir(efsdir, &efsfs->filesystem, file->path); + if(result < 0) + { + dfs_log(DFS_DEBUG_INFO, ("open directory %s failed", file->path)); + } + } + /* should implement in future version */ + else + { + dfs_log(DFS_DEBUG_INFO, ("not implement")); + } + } + /* seek file */ + else + { + File* efsfile = file->data; + + /* parameter check */ + if ( efsfile == RT_NULL) return -DFS_STATUS_EBADF; + + result = file_setpos(efsfile, offset); + } + + return result; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_getdents(struct dfs_fd* file, struct dfs_dirent* dirp, rt_uint32_t count) +{ + DirList* efsdir = (DirList*)file->data; + struct dfs_dirent* d; + int result = 0; + + /* fd check */ + if ( efsdir == RT_NULL) return -DFS_STATUS_EBADF; + + /* flags check */ + if(!(file->flags & DFS_F_DIRECTORY)) return -DFS_STATUS_EBADF; + + /* make integer count */ + count = (count / sizeof(struct dfs_dirent)) * sizeof(struct dfs_dirent); + if ( count == 0 ) return -DFS_STATUS_EINVAL; + + while(1) + { + /* it's the end of file */ + if(ls_getNext(efsdir) < 0) return 0; + + d = dirp + result; + /* copy dirent name */ + fat_ShortnameToString(efsdir->currentEntry.FileName, d->d_name); + d->d_reclen = (euint16)sizeof(struct dfs_dirent); + + /* set type */ + d->d_type = DFS_DT_UNKNOWN; + if (efsdir->currentEntry.Attribute & ATTR_DIRECTORY ) d->d_type &= DFS_DT_DIR; + else d->d_type &= DFS_DT_REG; + + result ++; + + /* is it enough? */ + if ( result * sizeof(struct dfs_dirent) >= count )
+ break; + } + + return result * sizeof(struct dfs_dirent); +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_unlink(struct dfs_filesystem* fs, const char* path) +{ + efsl_fs* efsfs;
+ + RT_ASSERT(fs != RT_NULL);
+ efsfs = (efsl_fs *)fs->data;
+ + RT_ASSERT(path != RT_NULL);
+ RT_ASSERT(efsfs != RT_NULL);
+ + return un_link(&efsfs->filesystem, (euint8 *)path); +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_stat(struct dfs_filesystem* fs, const char *path, struct dfs_stat *st) +{ + FileRecord entry; + FileLocation loc; + efsl_fs* efsfs = (efsl_fs*)(fs->data); + + /* parameter check */
+ RT_ASSERT(efsfs != RT_NULL); + + /* file does not exist */ + if(fs_findFile(&efsfs->filesystem, (char *)path, &loc, 0) == 0) + { + dfs_log(DFS_DEBUG_ERROR, ("can't find direntry")); + return -DFS_STATUS_ENOENT; + } + + dir_getFileStructure(&efsfs->filesystem, &entry, &loc); + + st->st_dev = fs->dev_id; + st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH | + DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH; + if ( entry.Attribute & ATTR_DIRECTORY ) + { + st->st_mode &= ~DFS_S_IFREG; + st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH; + } + if ( entry.Attribute & ATTR_READ_ONLY ) + st->st_mode &= ~(DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH); + + st->st_size = entry.FileSize; + st->st_mtime = entry.WriteTime; + + return 0; +} + +/** + * This function will set a hook function, which will be invoked when a memory + * block is allocated from heap memory. + * + * @param hook the hook function + */ +int efs_rename(struct dfs_filesystem* fs, const char* oldpath, const char* newpath) +{ + FileRecord old_entry, new_entry; + FileLocation old_loc, new_loc; + efsl_fs* efsfs; + eint8 fatfilename[11]; + + efsfs = (efsl_fs*) fs->data ; + RT_ASSERT(efsfs != RT_NULL);
+ + dir_getFatFileName((eint8 *)newpath, &fatfilename[0]); + + /* parameters check */ + if (strlen(oldpath) > DFS_PATH_MAX || + strlen(newpath) > DFS_PATH_MAX || + /* old path is a directory that contains newpath */ + strncmp(oldpath, newpath, strlen(newpath)) == 0) + { + dfs_log(DFS_DEBUG_ERROR, ("old path is a directory that contains newpath")); + return -DFS_STATUS_EINVAL; + } + + /* if can't find old direntry */ + if(fs_findFile(&efsfs->filesystem, (eint8 *)oldpath, &old_loc, 0) == 0) + { + dfs_log(DFS_DEBUG_ERROR, ("can't find old direntry")); + return -DFS_STATUS_ENOENT; + } + dir_getFileStructure(&efsfs->filesystem, &old_entry, &old_loc); + + /* if the new direntry exist */ + if(fs_findFile(&efsfs->filesystem, (eint8 *)newpath, &new_loc, 0) > 0) + { + dfs_log(DFS_DEBUG_ERROR, ("new direntry existed")); + return -DFS_STATUS_ENOENT; + } + if(fs_findFreeFile(&efsfs->filesystem, (eint8 *)newpath, &new_loc, 0)) + { + memCpy(&old_entry, &new_entry, sizeof(FileRecord)); + memCpy(fatfilename, new_entry.FileName, 11); + dir_createDirectoryEntry(&efsfs->filesystem, &new_entry, &new_loc); + } + + /* delete the old direntry */ + old_entry.FileName[0] = 0xe5; + dir_updateDirectoryEntry(&efsfs->filesystem, &old_entry, &old_loc); + + return 0; +} diff --git a/filesystem/dfs/filesystems/efsl/src/base/extract.c b/filesystem/dfs/filesystems/efsl/src/base/extract.c new file mode 100644 index 0000000000..7b4b77336b --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/extract.c @@ -0,0 +1,57 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : extract.c * +* Release : 0.3 - devel * +* Description : This file contains functions to copy structures that get * +* corrupted when using direct memory copy * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "extract.h" +/*****************************************************************************/ + +#if !(defined(BYTE_ALIGNMENT)) +#warning "Compiling f_setbxx" +void ex_setb16(euint8* buf,euint16 data) +{ + buf[1] = data>>8; + buf[0] = data>>0; +} + +void ex_setb32(euint8* buf,euint32 data) +{ + buf[3] = data>>24; + buf[2] = data>>16; + buf[1] = data>>8; + buf[0] = data>>0; +} +#endif + + + diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/debug.h b/filesystem/dfs/filesystems/efsl/src/base/include/debug.h new file mode 100644 index 0000000000..505e0466a6 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/debug.h @@ -0,0 +1,68 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : debug.h * +* Release : 0.3 - devel * +* Description : These functions are used for debugging output on different * +* environments * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +/*****************************************************************************/ +#include "types.h" +#include "config.h" +/*****************************************************************************/ + +#ifndef DEBUG + #define TXT(x) ; + #define DBG(x) ; + #define FUNC_IN(x) ; + #define FUNC_OUT(x) ; +#endif + +#ifdef DEBUG + + #ifdef HW_ENDPOINT_LINUX + #include <stdio.h> + #include <stdarg.h> + + #define TXT(x) x + #define DBG(x) debug x + #define FUNC_IN(x) debug_funcin(x) + #define FUNC_OUT(x) debug_funcout(x) + #endif + + void debug(const eint8 *format, ...); + void debug_init(); + void debug_end(); + +#endif + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/efs.h b/filesystem/dfs/filesystems/efsl/src/base/include/efs.h new file mode 100644 index 0000000000..3ab3d914f6 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/efs.h @@ -0,0 +1,89 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : efs.c * +* Release : 0.3 - devel * +* Description : This should become the wrapper around efs. It will contain * +* functions like efs_init etc. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __EFS_H__ +#define __EFS_H__ + +/*****************************************************************************/ +#include <dfs_fs.h> + +#include "types.h" +#include "config.h" +#include "extract.h" +#include "partition.h" + +/* WARNING !!!! + * These includes DO NOT BELONG HERE, + * remove them when the VFS layer is implemented !!!! + */ +#include "fs.h" +#include "file.h" +#include "tm.h" +#include "ui.h" + +/*****************************************************************************/ +#define LINUX_FILE_CONFIG 0x00 +#define AVR_SD_CONFIG 0x01 +/*****************************************************************************/ + +#define efs_read_sectors(device, start, count, buf) rt_device_read(device, \ + (start) * SECTOR_SIZE, (buf), (count) * SECTOR_SIZE) / SECTOR_SIZE +#define efs_write_sectors(device, start, count, buf) rt_device_write(device, \ + (start) * SECTOR_SIZE, (buf), (count) * SECTOR_SIZE) / SECTOR_SIZE + +struct _efsl_fs { + Partition partition; + FileSystem filesystem; +}; +typedef struct _efsl_fs efsl_fs; + +/* EFS filesystem file operations */ +int efs_mount(struct dfs_filesystem* fs); +int efs_unmount(struct dfs_filesystem* fs); +int efs_open(struct dfs_fd* file); +int efs_close(struct dfs_fd* file); +int efs_ioctl(struct dfs_fd* file, int cmd, void* args); +int efs_read(struct dfs_fd* file, void* buf, rt_size_t len); +int efs_write(struct dfs_fd* file, const void* buf, rt_size_t len); +int efs_lseek(struct dfs_fd* file, rt_off_t offset); +int efs_getdents(struct dfs_fd* file, struct dfs_dirent* dirp, rt_uint32_t count); +int efs_unlink(struct dfs_filesystem* fs, const char* path); +int efs_stat(struct dfs_filesystem* fs, const char *path, struct dfs_stat *st); +int efs_rename(struct dfs_filesystem* fs, const char* oldpath, const char* newpath); + +/*****************************************************************************/ +int efsl_init(void); + +#endif + diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/extract.h b/filesystem/dfs/filesystems/efsl/src/base/include/extract.h new file mode 100644 index 0000000000..4ae5212c5c --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/extract.h @@ -0,0 +1,101 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : extract.h * +* Release : 0.3 - devel * +* Description : This file contains functions to copy structures that get * +* corrupted when using direct memory copy * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __EXTRACT_H_ +#define __EXTRACT_H_ + +/*****************************************************************************/ +#include "config.h" +#include "types.h" +/*****************************************************************************/ + +#if !(defined(HOST_LITTLE_ENDIAN)) && !(defined(HOST_BIG_ENDIAN)) +#error Endianess undefined, see config.h +#elif defined(HOST_LITTLE_ENDIAN) && (defined(HOST_BIG_ENDIAN)) +#error Endianess defined as little and big, see config.h +#endif + +/*****************************************************************************/ + +#define end_conv16(x) ((((euint16)(x) & 0xff00) >> 8) | \ + (((euint16)(x) & 0x00ff) << 8)) +#define end_conv32(x) ((((euint32)(x) & 0xff000000) >> 24) | \ + (((euint32)(x) & 0x00ff0000) >> 8) | \ + (((euint32)(x) & 0x0000ff00) << 8) | \ + (((euint32)(x) & 0x000000ff) << 24)) + +/*****************************************************************************/ + +#if defined(BYTE_ALIGNMENT) + #define ex_getb16(buf) (*((euint16*)(buf))) + #define ex_setb16(buf,data) *((euint16*)(buf))=(data) + #define ex_getb32(buf) (*((euint32*)(buf))) + #define ex_setb32(buf,data) *((euint32*)(buf))=(data) +#else + #define ex_getb16(buf) \ + ((euint16)(*((euint8*)(buf)+1)<<8) + \ + (euint16)(*((euint8*)(buf)+0)<<0)) + void ex_setb16(euint8* buf,euint16 data); + #define ex_getb32(buf) \ + ((euint32)(*((euint8*)(buf)+3)<<24) + \ + (euint32)(*((euint8*)(buf)+2)<<16) + \ + (euint32)(*((euint8*)(buf)+1)<<8) + \ + (euint32)(*((euint8*)(buf)+0)<<0)) + void ex_setb32(euint8* buf,euint32 data); +#endif + +#if defined(HOST_LITTLE_ENDIAN) + #define ex_lth16(buf) ex_getb16(buf) + #define ex_lth32(buf) ex_getb32(buf) + #define ex_bth16(buf) end_conv16(ex_getb16(buf)) + #define ex_bth32(buf) end_conv32(ex_getb32(buf)) + + #define ex_htl16(buf) ex_setb16(buf) + #define ex_htl32(buf) ex_setb32(buf) + #define ex_htb16(buf) ex_setb16(end_conv16(buf)) + #define ex_htb32(buf) ex_setb32(end_conv32(buf)) +#elif defined(HOST_BIG_ENDIAN) + #define ex_lth16(buf) end_conv16(ex_getb16(buf)) + #define ex_lth32(buf) end_conv32(ex_getb32(buf)) + #define ex_bth16(buf) ex_getb16(buf) + #define ex_bth32(buf) ex_getb32(buf) + + #define ex_htl16(buf) ex_setb16(end_conv16(buf)) + #define ex_htl32(buf) ex_setb32(end_conv32(buf)) + #define ex_htb16(buf) ex_setb16(buf) + #define ex_htb32(buf) ex_setb32(buf) +#endif + +#endif + diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/ioman.h b/filesystem/dfs/filesystems/efsl/src/base/include/ioman.h new file mode 100644 index 0000000000..406ed5aff3 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/ioman.h @@ -0,0 +1,140 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ioman.c * +* Release : 0.3 - devel * +* Description : The IO Manager receives all requests for sectors in a central * +* allowing it to make smart decision regarding caching. * +* The IOMAN_NUMBUFFER parameter determines how many sectors * +* ioman can cache. ioman also supports overallocating and * +* backtracking sectors. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __IOMAN_H__ +#define __IOMAN_H__ + +/*****************************************************************************/ +#include <rtthread.h> + +#include "error.h" +#include "plibc.h" +#include "debug.h" +#include "types.h" +#include "config.h" +/*****************************************************************************/ + +#define IOMAN_STATUS_ATTR_VALIDDATA 0 +#define IOMAN_STATUS_ATTR_USERBUFFER 1 +#define IOMAN_STATUS_ATTR_WRITE 2 + +#define IOM_MODE_READONLY 1 +#define IOM_MODE_READWRITE 2 +#define IOM_MODE_EXP_REQ 4 + +struct _IOManStack{ + euint32 sector; + euint8 status; + euint8 usage; +}; +typedef struct _IOManStack IOManStack; + +struct _IOManager{ + rt_device_t device; + euint8 *bufptr; + euint16 numbuf; + euint16 numit; + + IOMAN_ERR_EUINT8 + + IOManStack stack[IOMAN_NUMBUFFER][IOMAN_NUMITERATIONS]; + + euint32 sector[IOMAN_NUMBUFFER]; + euint8 status[IOMAN_NUMBUFFER]; + euint8 usage[IOMAN_NUMBUFFER]; + euint8 reference[IOMAN_NUMBUFFER]; + euint8 itptr[IOMAN_NUMBUFFER]; +#ifdef IOMAN_DO_MEMALLOC + euint8 cache_mem[IOMAN_NUMBUFFER * 512]; +#endif +}; +typedef struct _IOManager IOManager; + +#define IOBJ ioman + +#define ioman_isValid(bp) ioman_getAttr(IOBJ,bp,IOMAN_STATUS_ATTR_VALIDDATA) +#define ioman_isUserBuf(bp) ioman_getAttr(IOBJ,bp,IOMAN_STATUS_ATTR_USERBUFFER) +#define ioman_isWritable(bp) ioman_getAttr(IOBJ,bp,IOMAN_STATUS_ATTR_WRITE) + +#define ioman_setValid(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_VALIDDATA,1) +#define ioman_setUserBuf(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_USERBUFFER,1) +#define ioman_setWritable(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_WRITE,1) + +#define ioman_setNotValid(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_VALIDDATA,0) +#define ioman_setNotUserBuf(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_USERBUFFER,0) +#define ioman_setNotWritable(bp) ioman_setAttr(IOBJ,bp,IOMAN_STATUS_ATTR_WRITE,0) + +#define ioman_isReqRo(mode) ((mode)&(IOM_MODE_READONLY)) +#define ioman_isReqRw(mode) ((mode)&(IOM_MODE_READWRITE)) +#define ioman_isReqExp(mode) ((mode)&(IOM_MODE_EXP_REQ)) + +esint8 ioman_init(IOManager *ioman, euint8* bufferarea); +void ioman_reset(IOManager *ioman); +euint8* ioman_getBuffer(IOManager *ioman,euint8* bufferarea); +void ioman_setAttr(IOManager *ioman,euint16 bufplace,euint8 attribute,euint8 val); +euint8 ioman_getAttr(IOManager *ioman,euint16 bufplace,euint8 attribute); +euint8 ioman_getUseCnt(IOManager *ioman,euint16 bufplace); +void ioman_incUseCnt(IOManager *ioman,euint16 bufplace); +void ioman_decUseCnt(IOManager *ioman,euint16 bufplace); +void ioman_resetUseCnt(IOManager *ioman,euint16 bufplace); +euint8 ioman_getRefCnt(IOManager *ioman,euint16 bufplace); +void ioman_incRefCnt(IOManager *ioman,euint16 bufplace); +void ioman_decRefCnt(IOManager *ioman,euint16 bufplace); +void ioman_resetRefCnt(IOManager *ioman,euint16 bufplace); +esint8 ioman_pop(IOManager *ioman,euint16 bufplace); +esint8 ioman_push(IOManager *ioman,euint16 bufplace); +euint8* ioman_getPtr(IOManager *ioman,euint16 bufplace); +esint16 ioman_getBp(IOManager *ioman,euint8* buf); +esint8 ioman_readSector(IOManager *ioman,euint32 address,euint8* buf); +esint8 ioman_writeSector(IOManager *ioman, euint32 address, euint8* buf); +void ioman_resetCacheItem(IOManager *ioman,euint16 bufplace); +esint32 ioman_findSectorInCache(IOManager *ioman, euint32 address); +esint32 ioman_findFreeSpot(IOManager *ioman); +esint32 ioman_findUnusedSpot(IOManager *ioman); +esint32 ioman_findOverallocableSpot(IOManager *ioman); +esint8 ioman_putSectorInCache(IOManager *ioman,euint32 address, euint16 bufplace); +esint8 ioman_flushSector(IOManager *ioman, euint16 bufplace); +euint8* ioman_getSector(IOManager *ioman,euint32 address, euint8 mode); +esint8 ioman_releaseSector(IOManager *ioman,euint8* buf); +esint8 ioman_directSectorRead(IOManager *ioman,euint32 address, euint8* buf); +esint8 ioman_directSectorWrite(IOManager *ioman,euint32 address, euint8* buf); +esint8 ioman_flushRange(IOManager *ioman,euint32 address_low, euint32 address_high); +esint8 ioman_flushAll(IOManager *ioman); + +void ioman_printStatus(IOManager *ioman); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/ioman_small.h b/filesystem/dfs/filesystems/efsl/src/base/include/ioman_small.h new file mode 100644 index 0000000000..5962f56c6e --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/ioman_small.h @@ -0,0 +1,93 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ioman_small.c * +* Release : 0.3 - devel * +* Description : The IO Manager receives all requests for sectors in a central * +* allowing it to make smart decision regarding caching. * +* The IOMAN_NUMBUFFER parameter determines how many sectors * +* ioman can cache. ioman also supports overallocating and * +* backtracking sectors. * +* This is the small version of IOMan, for systems with limited * +* resources. It features only one fixed buffer, and has * +* simplified operation * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#include "error.h" +#include "plibc.h" +#include "debug.h" +#include "types.h" +#include "config.h" + +#define IOMAN_STATUS_ATTR_VALIDDATA 0 +#define IOMAN_STATUS_ATTR_USERBUFFER 1 +#define IOMAN_STATUS_ATTR_WRITE 2 + +#define IOM_MODE_READONLY 1 +#define IOM_MODE_READWRITE 2 +#define IOM_MODE_EXP_REQ 4 + +struct _IOManStack{ + euint32 sector; + euint8 status; +}; +typedef struct _IOManStack IOManStack; + +struct _IOManager{ + rt_device_t device; /* device handler */ + euint8 bufptr[512]; + IOMAN_ERR_EUINT8 + euint32 sector; + euint8 status; + euint8 itptr; + IOManStack stack; +}; +typedef struct _IOManager IOManager; + +#define IOBJ ioman + +#define ioman_isValid() ioman_getAttr(IOBJ,IOMAN_STATUS_ATTR_VALIDDATA) +#define ioman_isUserBuf() ioman_getAttr(IOBJ,IOMAN_STATUS_ATTR_USERBUFFER) +#define ioman_isWritable() ioman_getAttr(IOBJ,IOMAN_STATUS_ATTR_WRITE) + +#define ioman_setValid() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_VALIDDATA,1) +#define ioman_setUserBuf() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_USERBUFFER,1) +#define ioman_setWritable() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_WRITE,1) + +#define ioman_setNotValid() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_VALIDDATA,0) +#define ioman_setNotUserBuf() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_USERBUFFER,0) +#define ioman_setNotWritable() ioman_setAttr(IOBJ,IOMAN_STATUS_ATTR_WRITE,0) + +#define ioman_isReqRo(mode) ((mode)&(IOM_MODE_READONLY)) +#define ioman_isReqRw(mode) ((mode)&(IOM_MODE_READWRITE)) +#define ioman_isReqExp(mode) ((mode)&(IOM_MODE_EXP_REQ)) + +esint8 ioman_init(IOManager *ioman, euint8* bufferarea); +void ioman_reset(IOManager *ioman); +void ioman_setAttr(IOManager *ioman,euint8 attribute,euint8 val); +euint8 ioman_getAttr(IOManager *ioman,euint8 attribute); diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/partition.h b/filesystem/dfs/filesystems/efsl/src/base/include/partition.h new file mode 100644 index 0000000000..07118b658a --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/partition.h @@ -0,0 +1,73 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : partition.c * +* Release : 0.3 - devel * +* Description : These functions are partition specific. Searching FAT type * +* partitions and read/write functions to partitions. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __PARTITION_H__ +#define __PARTITION_H__ + +/*****************************************************************************/ +#include "config.h" +#include "error.h" +#include "types.h" +// #include "ioman.h"
+#include <dfs_cache.h> +/*****************************************************************************/ + +#define PT_FAT12 0x01 +#define PT_FAT16A 0x04 +#define PT_FAT16 0x06 +#define PT_FAT32 0x0B +#define PT_FAT32A 0x5C +#define PT_FAT16B 0x5E + +struct _Partition{ + IOManager *ioman; +}; +typedef struct _Partition Partition; + +void part_initPartition(Partition *part); +eint16 part_isFatPart(euint8 type); +esint8 part_readBuf(Partition *part, euint32 address, euint8* buf); +esint8 part_readPartBuf(Partition *part, euint32 address, euint8* buf, euint32 offset, euint16 len); +eint16 part_writeBuf(Partition *part,euint32 address,euint8* buf); +euint8* part_getSect(Partition *part, euint32 address,euint8 mode); +esint8 part_relSect(Partition *part, euint8* buf); + +esint8 part_flushPart(Partition *part,euint32 addr_l, euint32 addr_h); + +esint8 part_directSectorRead(Partition *part, euint32 address, euint8* buf, euint32 numsector); +esint8 part_directSectorWrite(Partition *part, euint32 address, euint8* buf, euint32 numsector); + +#include "extract.h" + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/base/include/plibc.h b/filesystem/dfs/filesystems/efsl/src/base/include/plibc.h new file mode 100644 index 0000000000..30d86bd60b --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/include/plibc.h @@ -0,0 +1,49 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : plibc.c * +* Release : 0.3 - devel * +* Description : This file contains replacements of common c library functions * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __PLIBC_H__ +#define __PLIBC_H__ + +/*****************************************************************************/ +#include "debug.h" +#include "types.h" +#include "config.h" +/*****************************************************************************/ + +euint16 strMatch(eint8* bufa, eint8*bufb,euint32 n); +void memCpy(void* psrc, void* pdest, euint32 size); +void memClr(void *pdest,euint32 size); +void memSet(void *pdest,euint32 size,euint8 data); + + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/base/ioman.c b/filesystem/dfs/filesystems/efsl/src/base/ioman.c new file mode 100644 index 0000000000..42fb664324 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/ioman.c @@ -0,0 +1,600 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ioman.c * +* Release : 0.3 - devel * +* Description : The IO Manager receives all requests for sectors in a central * +* allowing it to make smart decision regarding caching. * +* The IOMAN_NUMBUFFER parameter determines how many sectors * +* ioman can cache. ioman also supports overallocating and * +* backtracking sectors. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "ioman.h" +#include "efs.h" +/*****************************************************************************/ + +esint8 ioman_init(IOManager *ioman, euint8* bufferarea) +{ + ioman->bufptr = ioman_getBuffer(ioman,bufferarea); + ioman->numbuf = IOMAN_NUMBUFFER; + ioman->numit = IOMAN_NUMITERATIONS; + + ioman_reset(ioman); + return(0); +} +/*****************************************************************************/ + +void ioman_reset(IOManager *ioman) +{ + euint16 nb,ni; + + memClr(ioman->sector,sizeof(euint32)*ioman->numbuf); + memClr(ioman->status,sizeof(euint8) *ioman->numbuf); + memClr(ioman->usage ,sizeof(euint8) *ioman->numbuf); + memClr(ioman->itptr ,sizeof(euint8) *ioman->numbuf); + ioman_setError(ioman,IOMAN_NOERROR); + + for(nb=0;nb<ioman->numbuf;nb++){ + for(ni=0;ni<ioman->numit;ni++){ + ioman->stack[nb][ni].sector=0; + ioman->stack[nb][ni].status=0; + ioman->stack[nb][ni].usage =0; + } + } +} +/*****************************************************************************/ + +euint8* ioman_getBuffer(IOManager *ioman,euint8* bufferarea) +{ +#ifdef IOMAN_DO_MEMALLOC + return(ioman->cache_mem); +#else + return(bufferarea); +#endif +} +/*****************************************************************************/ + +void ioman_setAttr(IOManager *ioman,euint16 bufplace,euint8 attribute,euint8 val) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_SETATTROUTOFBOUNDS); + return; /* Out of bounds */ + } + + if(val){ + ioman->status[bufplace]|=1<<attribute; + }else{ + ioman->status[bufplace]&=~(1<<attribute); + } +} +/*****************************************************************************/ + +euint8 ioman_getAttr(IOManager *ioman,euint16 bufplace,euint8 attribute) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_GETATTROUTOFBOUNDS); + return(0xFF); /* Out of bounds */ + } + + return(ioman->status[bufplace]&(1<<attribute)); +} +/*****************************************************************************/ + +euint8 ioman_getUseCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return(0x00); + } + return(ioman->usage[bufplace]); +} +/*****************************************************************************/ + + +void ioman_incUseCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + if(ioman->usage[bufplace]==0xFF)return; + else ioman->usage[bufplace]++; +} +/*****************************************************************************/ + +void ioman_decUseCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + if(ioman->usage[bufplace]==0x0)return; + else ioman->usage[bufplace]--; +} +/*****************************************************************************/ + +void ioman_resetUseCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + ioman->usage[bufplace]=0x00; +} +/*****************************************************************************/ + +euint8 ioman_getRefCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return(0x00); + } + return(ioman->reference[bufplace]); +} +/*****************************************************************************/ + +void ioman_incRefCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + if(ioman->reference[bufplace]==0xFF)return; + else ioman->reference[bufplace]++; +} +/*****************************************************************************/ + +void ioman_decRefCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + if(ioman->reference[bufplace]==0x00)return; + else ioman->reference[bufplace]--; +} +/*****************************************************************************/ + +void ioman_resetRefCnt(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + ioman->reference[bufplace]=0x00; +} +/*****************************************************************************/ + +esint8 ioman_pop(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_POPEMPTYSTACK); + return(-1); + } + if(ioman->itptr[bufplace]==0 || ioman->itptr[bufplace]>IOMAN_NUMITERATIONS)return(-1); + ioman->itptr[bufplace]--; + ioman->sector[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].sector; + ioman->status[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].status; + ioman->usage[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].usage; + return(0); +} +/*****************************************************************************/ + +esint8 ioman_push(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return(-1); + } + if(ioman->itptr[bufplace]>=IOMAN_NUMITERATIONS){ + ioman_setError(ioman,IOMAN_ERR_PUSHBEYONDSTACK); + return(-1); + } + ioman->stack[bufplace][ioman->itptr[bufplace]].sector = ioman->sector[bufplace]; + ioman->stack[bufplace][ioman->itptr[bufplace]].status = ioman->status[bufplace]; + ioman->stack[bufplace][ioman->itptr[bufplace]].usage = ioman->usage[bufplace]; + ioman->itptr[bufplace]++; + return(0); +} +/*****************************************************************************/ + +euint8* ioman_getPtr(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return(0); + } + return(ioman->bufptr+bufplace*512); +} +/*****************************************************************************/ + +esint16 ioman_getBp(IOManager *ioman,euint8* buf) +{ + if(buf<(ioman->bufptr) || buf>=( ioman->bufptr+(ioman->numbuf*512) )){ + ioman_setError(ioman,IOMAN_ERR_CACHEPTROUTOFRANGE); + return(-1); + } + return((buf-(ioman->bufptr))/512); +} +/*****************************************************************************/ + +esint8 ioman_readSector(IOManager *ioman,euint32 address,euint8* buf) +{ + esint8 r; + + if(buf==0){ + return(-1); + } + + r = efs_read_sectors(ioman->device, address, 1, buf); + + if(r!=1){ + ioman_setError(ioman,IOMAN_ERR_READFAIL); + return(-1); + } + return(0); +} +/*****************************************************************************/ + +esint8 ioman_writeSector(IOManager *ioman, euint32 address, euint8* buf) +{ + esint8 r; + + if(buf==0)return(-1); + + r = efs_write_sectors(ioman->device, address, 1, buf); + + if(r!=1){ + ioman_setError(ioman,IOMAN_ERR_WRITEFAIL); + return(-1); + } + return(0); +} +/*****************************************************************************/ + +void ioman_resetCacheItem(IOManager *ioman,euint16 bufplace) +{ + if(bufplace>=ioman->numbuf){ + ioman_setError(ioman,IOMAN_ERR_OPOUTOFBOUNDS); + return; + } + ioman->sector[bufplace] = 0; + ioman->status[bufplace] = 0; + ioman->usage[bufplace] = 0; + ioman->reference[bufplace] = 0; +} +/*****************************************************************************/ + +esint32 ioman_findSectorInCache(IOManager *ioman, euint32 address) +{ + euint16 c; + + for(c=0;c<ioman->numbuf;c++){ + if(ioman_isValid(c) && ioman->sector[c] == address)return(c); + } + return(-1); +} +/*****************************************************************************/ + +esint32 ioman_findFreeSpot(IOManager *ioman) +{ + euint16 c; + + for(c=0;c<ioman->numbuf;c++){ + if(!ioman_isValid(c))return(c); + } + return(-1); +} +/*****************************************************************************/ + +esint32 ioman_findUnusedSpot(IOManager *ioman) +{ + esint32 r=-1; + euint16 c; + euint8 fr=0,lr=0xFF; + + for(c=0;c<ioman->numbuf;c++){ + if(ioman_getUseCnt(ioman,c)==0){ + if(!ioman_isWritable(c) && !fr){ + fr=1; + lr=0xFF; + r=-1; + } + if(ioman_isWritable(c) && !fr){ + if(ioman_getRefCnt(ioman,c)<=lr){ + r=c; + lr=ioman_getRefCnt(ioman,c); + } + } + if(fr && !ioman_isWritable(c)){ + if(ioman_getRefCnt(ioman,c)<=lr){ + r=c; + lr=ioman_getRefCnt(ioman,c); + } + } + } + } + return(r); +} +/*****************************************************************************/ + +esint32 ioman_findOverallocableSpot(IOManager *ioman) +{ + euint8 points,lp=0xFF; + euint16 c; + esint32 r=-1; + + for(c=0;c<ioman->numbuf;c++){ + if(ioman->itptr[c]<ioman->numit){ + points = 0; + if(ioman_isWritable(c))points+=0x7F; + points += ((euint16)(ioman->itptr[c]*0x4D))/(ioman->numit); + points += ((euint16)(ioman_getRefCnt(ioman,c)*0x33))/0xFF; + if(points<lp){ + lp=points; + r=c; + } + } + } + return(r); +} +/*****************************************************************************/ + +esint8 ioman_putSectorInCache(IOManager *ioman, euint32 address, euint16 bufplace) +{ + euint8* buf; + + if((buf = ioman_getPtr(ioman,bufplace))==0){ + ioman_setError(ioman,IOMAN_ERR_CACHEPTROUTOFRANGE); + return(-1); + } + if((ioman_readSector(ioman,address,buf))){ + ioman_setError(ioman,IOMAN_ERR_READFAIL); + return(-1); + } + ioman_setValid(bufplace); + ioman->sector[bufplace]=address; + return(0); +} +/***************** if(bufplace>=ioman->numbuf)return; +************************************************************/ + +esint8 ioman_flushSector(IOManager *ioman, euint16 bufplace) +{ + euint8* buf; + + if((buf = ioman_getPtr(ioman,bufplace))==0){ + ioman_setError(ioman,IOMAN_ERR_CACHEPTROUTOFRANGE); + return(-1); + } + if(!ioman_isWritable(bufplace)){ + ioman_setError(ioman,IOMAN_ERR_WRITEREADONLYSECTOR); + return(-1); + } + if(ioman_writeSector(ioman,ioman->sector[bufplace],buf)){ /* ERROR HERE STILL TO BE FIXED -> ! must be removed! */ + ioman_setError(ioman,IOMAN_ERR_WRITEFAIL); + return(-1); + } + if(ioman->usage[bufplace]==0)ioman_setNotWritable(bufplace); + return(0); +} +/*****************************************************************************/ + +esint8 ioman_flushRange(IOManager *ioman,euint32 address_low, euint32 address_high) +{ + euint32 c; + + if(address_low>address_high){ + c=address_low; address_low=address_high;address_high=c; + } + + for(c=0;c<ioman->numbuf;c++){ + if((ioman->sector[c]>=address_low) && (ioman->sector[c]<=address_high) && (ioman_isWritable(c))){ + if(ioman_flushSector(ioman,c)){ + return(-1); + } + if(ioman->usage[c]==0)ioman_setNotWritable(c); + } + } + return(0); +} +/*****************************************************************************/ + +esint8 ioman_flushAll(IOManager *ioman) +{ + euint16 c; + + for(c=0;c<ioman->numbuf;c++){ + if(ioman_isWritable(c)){ + if(ioman_flushSector(ioman,c)){ + return(-1); + } + if(ioman->usage[c]==0)ioman_setNotWritable(c); + } + } + return(0); +} +/*****************************************************************************/ + +euint8* ioman_getSector(IOManager *ioman,euint32 address, euint8 mode) +{ + esint32 bp; + + if((bp=ioman_findSectorInCache(ioman,address))!=-1){ + if(ioman_isReqRw(mode)){ + ioman_setWritable(bp); + } + ioman_incUseCnt(ioman,bp); + if(!ioman_isReqExp(mode))ioman_incRefCnt(ioman,bp); + return(ioman_getPtr(ioman,bp)); + } + + if((bp=ioman_findFreeSpot(ioman))==-1){ + if(((bp=ioman_findUnusedSpot(ioman))!=-1)&&(ioman_isWritable(bp))){ + ioman_flushSector(ioman,bp); + } + } + + if(bp!=-1){ + ioman_resetCacheItem(ioman,bp); + if((ioman_putSectorInCache(ioman,address,bp))){ + return(0); + } + if(ioman_isReqRw(mode)){ + ioman_setWritable(bp); + } + ioman_incUseCnt(ioman,bp); + if(!ioman_isReqExp(mode))ioman_incRefCnt(ioman,bp); + return(ioman_getPtr(ioman,bp)); + } + + if((bp=ioman_findOverallocableSpot(ioman))!=-1){ + if(ioman_isWritable(bp)){ + ioman_flushSector(ioman,bp); + } + if(ioman_push(ioman,bp)){ + return(0); + } + ioman_resetCacheItem(ioman,bp); + if((ioman_putSectorInCache(ioman,address,bp))){ + return(0); + } + if(ioman_isReqRw(mode)){ + ioman_setWritable(bp); + } + ioman_incUseCnt(ioman,bp); + if(!ioman_isReqExp(mode))ioman_incRefCnt(ioman,bp); + return(ioman_getPtr(ioman,bp)); + } + ioman_setError(ioman,IOMAN_ERR_NOMEMORY); + return(0); +} +/*****************************************************************************/ + +esint8 ioman_releaseSector(IOManager *ioman,euint8* buf) +{ + euint16 bp; + + bp=ioman_getBp(ioman,buf); + ioman_decUseCnt(ioman,bp); + + if(ioman_getUseCnt(ioman,bp)==0) + { + if(ioman_isWritable(bp)) + { + ioman_flushSector(ioman,bp); + } + if(ioman->itptr[bp]!=0) + { + ioman_pop(ioman,bp); + ioman_putSectorInCache(ioman,ioman->sector[bp],bp); + } + } + + return(0); +} +/*****************************************************************************/ + +esint8 ioman_directSectorRead(IOManager *ioman,euint32 address, euint8* buf) +{ + euint8* ibuf; + esint16 bp; + + if((bp=ioman_findSectorInCache(ioman,address))!=-1){ + ibuf=ioman_getPtr(ioman,bp); + memCpy(ibuf,buf,512); + return(0); + } + + if((bp=ioman_findFreeSpot(ioman))!=-1){ + if((ioman_putSectorInCache(ioman,address,bp))){ + return(-1); + } + ibuf=ioman_getPtr(ioman,bp); + memCpy(ibuf,buf,512); + return(0); + } + + if(ioman_readSector(ioman,address,buf)){ + return(-1); + } + + return(0); +} +/*****************************************************************************/ + +esint8 ioman_directSectorWrite(IOManager *ioman,euint32 address, euint8* buf) +{ + euint8* ibuf; + esint16 bp; + + if((bp=ioman_findSectorInCache(ioman,address))!=-1){ + ibuf=ioman_getPtr(ioman,bp); + memCpy(buf,ibuf,512); + ioman_setWritable(bp); + return(0); + } + + if((bp=ioman_findFreeSpot(ioman))!=-1){ + ibuf=ioman_getPtr(ioman,bp); + memCpy(buf,ibuf,512); + ioman_resetCacheItem(ioman,bp); + ioman->sector[bp]=address; + ioman_setWritable(bp); + ioman_setValid(bp); + return(0); + } + + if(ioman_writeSector(ioman,address,buf)){ + return(-1); + } + + return(0); +} +/*****************************************************************************/ + +void ioman_printStatus(IOManager *ioman) +{ + euint16 c; + + DBG((TXT("IO-Manager -- Report\n====================\n"))); + DBG((TXT("Buffer is %i sectors, from %p to %p\n"), + ioman->numbuf,ioman->bufptr,ioman->bufptr+(ioman->numbuf*512))); + for(c=0;c<ioman->numbuf;c++){ + if(ioman_isValid(c)){ + DBG((TXT("BP %3i\t SC %8li\t\t US %i\t RF %i\t %s %s\n"), + c,ioman->sector[c],ioman_getUseCnt(ioman,c),ioman_getRefCnt(ioman,c), + ioman_isUserBuf(c) ? "USRBUF" : " ", + ioman_isWritable(c) ? "WRITABLE" : "READONLY")); + } + } +} +/*****************************************************************************/ + diff --git a/filesystem/dfs/filesystems/efsl/src/base/ioman_small.c b/filesystem/dfs/filesystems/efsl/src/base/ioman_small.c new file mode 100644 index 0000000000..287e0e08a4 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/ioman_small.c @@ -0,0 +1,120 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ioman_small.c * +* Release : 0.3 - devel * +* Description : The IO Manager receives all requests for sectors in a central * +* allowing it to make smart decision regarding caching. * +* The IOMAN_NUMBUFFER parameter determines how many sectors * +* ioman can cache. ioman also supports overallocating and * +* backtracking sectors. * +* This is the small version of IOMan, for systems with limited * +* resources. It features only one fixed buffer, and has * +* simplified operation * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#include "ioman_small.h" + +esint8 ioman_init(IOManager *ioman, euint8* bufferarea) +{ + ioman_reset(ioman); + return(0); +} +/*****************************************************************************/ + +void ioman_reset(IOManager *ioman) +{ + ioman->sector=ioman->status=ioman->itptr=0; + ioman->stack.sector=ioman->stack.status=0; + + ioman_setError(ioman,IOMAN_NOERROR); + +} +/*****************************************************************************/ + +void ioman_setAttr(IOManager *ioman,euint8 attribute,euint8 val) +{ + if(val){ + ioman->status|=1<<attribute; + }else{ + ioman->status&=~(1<<attribute); + } +} +/*****************************************************************************/ + +euint8 ioman_getAttr(IOManager *ioman,euint8 attribute) +{ + return(ioman->status&(1<<attribute)); +} +/*****************************************************************************/ + + +euint8* ioman_getSector(IOManager *ioman,euint32 address, euint8 mode) +{ + if(address==ioman->sector){ + if(mode==IOM_MODE_READWRITE)ioman_setWritable(); + return(ioman->bufptr); + } + +} + +esint8 ioman_readSector(IOManager *ioman,euint32 address,euint8* buf) +{ + esint8 r; + + if(buf==0){ + return(-1); + } + + //r=if_readBuf(ioman->iface,address,buf); + r = efs_read_sectors(ioman->device, address, 1, buf); + + if(r!=0){ + ioman_setError(ioman,IOMAN_ERR_READFAIL); + return(-1); + } + return(0); +} +/*****************************************************************************/ + +esint8 ioman_writeSector(IOManager *ioman, euint32 address, euint8* buf) +{ + esint8 r; + + if(buf==0)return(-1); + + //r=if_writeBuf(ioman->iface,address,buf); + r = efs_write_sectors(ioman->device, address, 1, buf); + + if(r<=0){ + ioman_setError(ioman,IOMAN_ERR_WRITEFAIL); + return(-1); + } + return(0); +} +/*****************************************************************************/ diff --git a/filesystem/dfs/filesystems/efsl/src/base/partition.c b/filesystem/dfs/filesystems/efsl/src/base/partition.c new file mode 100644 index 0000000000..7aa67c99c1 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/partition.c @@ -0,0 +1,125 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : partition.c * +* Release : 0.3 - devel * +* Description : These functions are partition specific. Searching FAT type * +* partitions and read/write functions to partitions. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "partition.h" +#include "efs.h" +/*****************************************************************************/ + +/* **************************************************************************** + * void part_initPartition(Partition *part,Disc* refDisc) + * Description: This function searches the 4 partitions for a FAT class partition + * and marks the first one found as the active to be used partition. +*/ +void part_initPartition(Partition *part) +{ + part_setError(part,PART_NOERROR); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * eint16 part_isFatPart(euint8 type) + * Description: This functions checks if a partitiontype (eint8) is of the FAT + * type in the broadest sense. I + * Return value: If it is FAT, returns 1, otherwise 0. +*/ +eint16 part_isFatPart(euint8 type) +{ + if(type == PT_FAT12 || + type == PT_FAT16A || + type == PT_FAT16 || + type == PT_FAT32 || + type == PT_FAT32A || + type == PT_FAT16B ) + { + return(1); + } + return(0); +} +/*****************************************************************************/ + +esint8 part_readBuf(Partition *part, euint32 address, euint8* buf) +{ + return efs_read_sectors(part->ioman->device, address, 1, buf); +} + +/* **************************************************************************** + * eint16 part_writeBuf(Partition *part,euint32 address,euint8* buf) + * Description: This function writes 512 bytes, from buf. It's offset is address + * sectors from the beginning of the partition. + * Return value: It returns whatever the hardware function returns. (-1=error) +*/ +eint16 part_writeBuf(Partition *part,euint32 address,euint8* buf) +{ + /*DBG((TXT("part_writeBuf :: %li\n"),address));*/ + return efs_write_sectors(part->ioman->device, address, 1, buf); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint8* part_getSect(Partition *part, euint32 address, euint8 mode) + * Description: This function calls ioman_getSector, but recalculates the sector + * address to be partition relative. + * Return value: Whatever getSector returns. (pointer or 0) +*/ +euint8* part_getSect(Partition *part, euint32 address, euint8 mode) +{ + return(ioman_getSector(part->ioman,address,mode)); +} + +/* **************************************************************************** + * esint8 part_relSect(Partition *part, euint8* buf) + * Description: This function calls ioman_releaseSector. + * Return value: Whatever releaseSector returns. +*/ +esint8 part_relSect(Partition *part, euint8* buf) +{ + return(ioman_releaseSector(part->ioman,buf)); +} + +esint8 part_flushPart(Partition *part,euint32 addr_l, euint32 addr_h) +{ + return ioman_flushRange(part->ioman,addr_l,addr_h); +} + +esint8 part_directSectorRead(Partition *part, euint32 address, euint8* buf, euint32 numsector) +{ + return ioman_directSectorRead(part->ioman, address, buf, numsector); +} + +esint8 part_directSectorWrite(Partition *part,euint32 address, euint8* buf, euint32 numsector) +{ + return ioman_directSectorWrite(part->ioman, address, buf, numsector); +} diff --git a/filesystem/dfs/filesystems/efsl/src/base/plibc.c b/filesystem/dfs/filesystems/efsl/src/base/plibc.c new file mode 100644 index 0000000000..ee2c923846 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/base/plibc.c @@ -0,0 +1,83 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : plibc.c * +* Release : 0.3 - devel * +* Description : This file contains replacements of common c library functions * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "plibc.h" +/*****************************************************************************/ + +/* **************************************************************************** + * unsigned short strMatch(char* bufa, char*bufb, unsigned long n) + * Description: Compares bufa and bufb for a length of n bytes. + * Return value: Returns the number of character NOT matching. +*/ +euint16 strMatch(eint8* bufa, eint8*bufb,euint32 n) +{ + euint32 c; + euint16 res=0; + for(c=0;c<n;c++)if(bufa[c]!=bufb[c])res++; + return(res); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * void memCpy(void* psrc, void* pdest, unsigned long size) + * Description: Copies the contents of psrc into pdest on a byte per byte basis. + * The total number of bytes copies is size. +*/ +void memCpy(void* psrc, void* pdest, euint32 size) +{ + while(size>0){ + *((eint8*)pdest+size-1)=*((eint8*)psrc+size-1); + size--; + } +} +/*****************************************************************************/ + +void memClr(void *pdest,euint32 size) +{ + while(size>0){ + *(((eint8*)pdest)+size-1)=0x00; + size--; + } +} + +void memSet(void *pdest,euint32 size,euint8 data) +{ + while(size>0){ + *(((eint8*)pdest)+size-1)=data; + size--; + } +} + + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/dir.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/dir.c new file mode 100644 index 0000000000..4cf13ca4a0 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/dir.c @@ -0,0 +1,365 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : dir.c * +* Release : 0.3 - devel * +* Description : The functions of dir.c are part of fs.c, they deal with all * +* the directory specific stuff. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "dir.h" +/*****************************************************************************/ + +/* **************************************************************************** + * void dir_getFileStructure(FileSystem *fs,FileRecord *filerec,FileLocation *loc) + * Description: This function stores the filerecord located at loc in filerec. + * It fetches the required sector for this. + * Return value: void +*/ +void dir_getFileStructure(FileSystem *fs,FileRecord *filerec,FileLocation *loc) +{ + euint8 *buf; + + buf=part_getSect(fs->part,loc->Sector,IOM_MODE_READONLY); + *filerec=*(((FileRecord*)buf)+loc->Offset); + part_relSect(fs->part,buf); +} + +/*****************************************************************************/ + +/* **************************************************************************** + * void dir_createDirectoryEntry(FileSystem *fs,FileRecord *filerec,FileLocation *loc) + * Description: This function writes the filerecord stored in filerec to disc at + * location loc. + * Return value: void +*/ +void dir_createDirectoryEntry(FileSystem *fs,FileRecord *filerec,FileLocation *loc) +{ + euint8 *buf; + + buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); + memCpy(filerec,buf+(loc->Offset*sizeof(*filerec)),sizeof(*filerec)); + part_relSect(fs->part,buf); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void dir_createDefaultEntry(FileSystem *fs,FileRecord *filerec,eint8* fatfilename) + * Description: This function fills in a filerecord with safe default values, and + * a given fatfilename. If your system has a means of knowing time, here is an + * excellent place to apply it to the filerecord. + * Return value: void +*/ +void dir_createDefaultEntry(FileSystem *fs,FileRecord *filerec,eint8* fatfilename) +{ + memCpy(fatfilename,filerec->FileName,11); + filerec->Attribute=0x00; + filerec->NTReserved=0x00; + filerec->MilliSecTimeStamp=0x00; + filerec->CreatedTime=time_getTime(); + filerec->CreatedDate=time_getDate(); + filerec->AccessDate=filerec->CreatedDate; + filerec->FirstClusterHigh=0x0000; + filerec->WriteTime=filerec->CreatedTime; + filerec->WriteDate=filerec->CreatedDate; + filerec->FirstClusterLow=0x0000; + filerec->FileSize=0x00000000; +} +/*****************************************************************************/ + +/* **************************************************************************** + * void dir_setFirstCluster(File *file,euint32 cluster_addr) + * Description: This function requires modification to release it from + * depending on the file object. + * Return value: +*/ +void dir_setFirstCluster(FileSystem *fs,FileLocation *loc,euint32 cluster_addr) +{ + euint8 *buf; + + buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); + (((FileRecord*)buf)+loc->Offset)->FirstClusterHigh=cluster_addr>>16; + (((FileRecord*)buf)+loc->Offset)->FirstClusterLow=cluster_addr&0xFFFF; + part_relSect(fs->part,buf); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void dir_setFileSize(FileSystem *fs, FileLocation *loc,euint32 numbytes) + * Description: This function changes the filesize recorded at loc->Sector + * to 'numbytes'. + * Return value: void +*/ +void dir_setFileSize(FileSystem *fs, FileLocation *loc,euint32 numbytes) +{ + euint8 *buf; + + buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); + (((FileRecord*)buf)+loc->Offset)->FileSize=numbytes; + part_relSect(fs->part,buf); +} +/*****************************************************************************/ + +/* **************************************************************************** + * esint8 dir_updateDirectoryEntry(FileSystem *fs,FileRecord *entry,FileLocation *loc)) + * This function changes the entire entity stores at loc to the data recorded + * in entry. This is for custom updates to the directoryentry. + * Return value: 0 on success, -1 on failure +*/ +esint8 dir_updateDirectoryEntry(FileSystem *fs,FileRecord *entry,FileLocation *loc) +{ + euint8 *buf; + + buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); + memCpy(entry,buf+(loc->Offset*sizeof(*entry)),sizeof(*entry)); + part_relSect(fs->part,buf); + return(0); +} + +/* **************************************************************************** + * euint32 dir_findFileinBuf(euint8 *buf, eint8 *fatname, FileLocation *loc) + * This function searches for a given fatfilename in the buffer provided. + * It will iterate through the 16 direntry's in the buffer and searches + * for the fatfilename. If found, it will store the offset and attribute + * entry of the directoryrecord in the loc structure. + * If loc is 0, then it's members are not touched. + * Return value: This function returns 0 when it cannot find the file, + * if it can find the file it will return the first cluster number. +*/ +euint32 dir_findFileinBuf(euint8 *buf, eint8 *fatname, FileLocation *loc) +{ + FileRecord fileEntry; + euint8 c; + + for(c=0; c<16; c++) + { + fileEntry = *(((FileRecord*)buf) + c); + /* Check if the entry is for short filenames */ + if( !( (fileEntry.Attribute & 0x0F) == 0x0F ) ) + { + if( strMatch((eint8*)fileEntry.FileName,fatname,11) == 0 ) + { + /* The entry has been found, return the location in the dir */ + if(loc)loc->Offset = c; + if(loc)loc->attrib = fileEntry.Attribute; + if((((euint32 )fileEntry.FirstClusterHigh)<<16)+ fileEntry.FirstClusterLow==0){ + return(1); /* Lie about cluster, 0 means not found! */ + }else{ + return + ( + (((euint32 )fileEntry.FirstClusterHigh)<<16) + + fileEntry.FirstClusterLow + ); + } + } + } + } + return(0); +} + +/* **************************************************************************** + * euint32 dir_findFreeEntryinBuf(euint8* buf, FileLocation *loc) + * This function searches for a free entry in a given sector 'buf'. + * It will put the offset into the loc->Offset field, given that loc is not 0. + * Return value: 1 when it found a free spot, 0 if it hasn't. +*/ +euint32 dir_findFreeEntryinBuf(euint8* buf, FileLocation *loc) +{ + FileRecord fileEntry; + euint8 c; + + for(c=0;c<16;c++){ + fileEntry = *(((FileRecord*)buf) + c); + if( !( (fileEntry.Attribute & 0x0F) == 0x0F ) ){ + if(fileEntry.FileName[0] == 0x00 || + fileEntry.FileName[0] == 0xE5 ){ + if(loc)loc->Offset=c; + return(1); + } + } + } + return(0); +} + +/* **************************************************************************** + * euint32 dir_findinBuf(euint8 *buf, eint8 *fatname, FileLocation *loc) + * Description: This function searches for a given fatfilename in a buffer. + * Return value: Returns 0 on not found, and the firstcluster when the name is found. +*/ +euint32 dir_findinBuf(euint8 *buf, eint8 *fatname, FileLocation *loc, euint8 mode) +{ + switch(mode){ + case DIRFIND_FILE: + return(dir_findFileinBuf(buf,fatname,loc)); + break; + case DIRFIND_FREE: + return(dir_findFreeEntryinBuf(buf,loc)); + break; + default: + return(0); + break; + } + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 dir_findinCluster(FileSystem *fs,euint32 cluster,eint8 *fatname, FileLocation *loc, euint8 mode) + * This function will search for an existing (fatname) or free directory entry + * in a full cluster. + * Return value: 0 on failure, firstcluster on finding file, and 1 on finding free spot. +*/ +euint32 dir_findinCluster(FileSystem *fs,euint32 cluster,eint8 *fatname, FileLocation *loc, euint8 mode) +{ + euint8 c,*buf=0; + euint32 fclus; + + for(c=0;c<fs->volumeId.SectorsPerCluster;c++){ + buf = part_getSect(fs->part,fs_clusterToSector(fs,cluster)+c,IOM_MODE_READONLY); + fclus=dir_findinBuf(buf,fatname,loc,mode);
+
+ if(fclus)
+ { + if(loc)loc->Sector=fs_clusterToSector(fs,cluster)+c; + part_relSect(fs->part,buf); + return(fclus); + } + part_relSect(fs->part,buf); + } + part_relSect(fs->part,buf); + return(0); +} + +/* **************************************************************************** + * euint32 dir_findinDir(FileSystem *fs, eint8* fatname,euint32 firstcluster, FileLocation *loc, euint8 mode) + * This function will search for an existing (fatname) or free directory entry + * in a directory, following the clusterchains. + * Return value: 0 on failure, firstcluster on finding file, and 1 on finding free spot. +*/ +euint32 dir_findinDir(FileSystem *fs, eint8* fatname,euint32 firstcluster, FileLocation *loc, euint8 mode) +{ + euint32 c=0,cluster; + ClusterChain Cache; + + Cache.DiscCluster = Cache.FirstCluster = firstcluster; + Cache.LogicCluster = Cache.LastCluster = Cache.Linear = 0; + + if(firstcluster <= 1){ + return(dir_findinRootArea(fs,fatname,loc,mode)); + } + + while(!fat_LogicToDiscCluster(fs,&Cache,c++)){ + if((cluster=dir_findinCluster(fs,Cache.DiscCluster,fatname,loc,mode))){ + return(cluster); + } + } + return(0); +} + +/* **************************************************************************** + * euint32 dir_findinDir(FileSystem *fs, eint8* fatname,euint32 firstcluster, FileLocation *loc, euint8 mode) + * This function will search for an existing (fatname) or free directory entry + * in the rootdirectory-area of a FAT12/FAT16 filesystem. + * Return value: 0 on failure, firstcluster on finding file, and 1 on finding free spot. +*/ +euint32 dir_findinRootArea(FileSystem *fs,eint8* fatname, FileLocation *loc, euint8 mode) +{ + euint32 c,fclus; + euint8 *buf=0; + + if((fs->type != FAT12) && (fs->type != FAT16))return(0); + + for(c=fs->FirstSectorRootDir;c<(fs->FirstSectorRootDir+fs->volumeId.RootEntryCount/32);c++){ + buf = part_getSect(fs->part,c,IOM_MODE_READONLY); + if((fclus=dir_findinBuf(buf,fatname,loc,mode))){ + if(loc)loc->Sector=c; + part_relSect(fs->part,buf); + return(fclus); + } + part_relSect(fs->part,buf); + } + part_relSect(fs->part,buf); + return(0); +} + +/* **************************************************************************** + * esint8 dir_getFatFileName(eint8* filename, eint8* fatfilename) + * This function will take a full directory path, and strip off all leading + * dirs and characters, leaving you with the MS-DOS notation of the actual filename. + * Return value: 1 on success, 0 on not being able to produca a filename +*/ +esint8 dir_getFatFileName(eint8* filename, eint8* fatfilename) +{ + eint8 ffnamec[11],*next,nn=0; + + memClr(ffnamec,11); memClr(fatfilename,11); + next = filename; + + if(*filename=='/')next++; + + while((next=file_normalToFatName(next,ffnamec))){ + memCpy(ffnamec,fatfilename,11); + nn++; + } + if(nn)return(1); + return(0); +} + +/* **************************************************************************** + * esint8 dir_addCluster(FileSystem *fs,euint32 firstCluster) + * This function extends a directory by 1 cluster + optional the number of + * clusters you want pre-allocated. It will also delete the contents of that + * cluster. (or clusters) + * Return value: 0 on success, -1 on fail +*/ +esint8 dir_addCluster(FileSystem *fs,euint32 firstCluster) +{ + euint32 lastc,logicalc; + ClusterChain cache; + + fs_initClusterChain(fs,&cache,firstCluster); + if(fat_allocClusterChain(fs,&cache,1)){ + return(-1); + } + lastc = fs_getLastCluster(fs,&cache); + if(CLUSTER_PREALLOC_DIRECTORY){ + if(fat_allocClusterChain(fs,&cache,CLUSTER_PREALLOC_DIRECTORY)){ + return(-1); + } + logicalc = fat_DiscToLogicCluster(fs,firstCluster,lastc); + while(!fat_LogicToDiscCluster(fs,&cache,++logicalc)){ + fs_clearCluster(fs,cache.DiscCluster); + } + }else{ + fs_clearCluster(fs,lastc); + } + return(0); +} + + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/fat.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/fat.c new file mode 100644 index 0000000000..b9f856cf10 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/fat.c @@ -0,0 +1,577 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : fat.c * +* Release : 0.3 - devel * +* Description : This file contains all the functions dealing with the FAT * +* in a Microsoft FAT filesystem. It belongs under fs.c * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "fs.h" +/*****************************************************************************/ + +/* **************************************************************************** + * unsigned long fat_getSectorAddressFatEntry(FileSystem *fs,unsigned long cluster_addr) + * Description: Returns the sectornumber that holds the fat entry for cluster cluster_addr. + * This works for all FAT types. + * Return value: Sectornumber, or 0. Warning, no boundary check. +*/ +euint32 fat_getSectorAddressFatEntry(FileSystem *fs,euint32 cluster_addr) +{ + euint32 base = fs->volumeId.ReservedSectorCount,res; + + switch(fs->type){ + case FAT12: + res=(cluster_addr*3/1024); + if(res>=fs->FatSectorCount){ + return(0); + }else{ + return(base+res); + } + break; + case FAT16: + res=cluster_addr/256; + if(res>=fs->FatSectorCount){ + return(0); + }else{ + return(base+res); + } + break; + case FAT32: + res=cluster_addr/128; + if(res>=fs->FatSectorCount){ + return(0); + }else{ + return(base+res); + } + break; + } + return(0); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * unsigned long fat_getNextClusterAddress(FileSystem *fs,unsigned long cluster_addr + * Description: This function loads the sector of the fat which contains the entry + * for cluster_addr. It then fetches and (if required) calculates it's value. + * This value is the EoC marker -or- the number of the next cluster in the chain. + * Return value: Clusternumber or EoC +*/ +euint32 fat_getNextClusterAddress(FileSystem *fs,euint32 cluster_addr,euint16 *linear) +{ + euint8 *buf; + euint8 hb,lb; + euint16 offset; + euint32 sector; + euint32 nextcluster=0; + + sector=fat_getSectorAddressFatEntry(fs,cluster_addr); + if( (fs->FatSectorCount <= (sector-fs->volumeId.ReservedSectorCount)) || sector==0 ) + { + return(0); + } + + buf=part_getSect(fs->part,sector,IOM_MODE_READONLY); + + switch(fs->type) + { + case FAT12: + offset = ((cluster_addr%1024)*3/2)%512; + hb = buf[offset]; + if(offset == 511){ + part_relSect(fs->part,buf); + buf=part_getSect(fs->part,sector+1,IOM_MODE_READONLY); + lb = buf[0]; + }else{ + lb = buf[offset + 1]; + } + if(cluster_addr%2==0){ + nextcluster = ( ((lb&0x0F)<<8) + (hb) ); + }else{ + nextcluster = ( (lb<<4) + (hb>>4) ); + } + break; + case FAT16: + offset=cluster_addr%256; + nextcluster = *((euint16 *)buf + offset); + break; + case FAT32: + offset=cluster_addr%128; + nextcluster = *((euint32 *)buf + offset); + break; + } + + part_relSect(fs->part,buf); + + return(nextcluster); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * void fat_setNextClusterAddress(FileSystem *fs,unsigned long cluster_addr,unsigned long next_cluster_addr) + * Description: This function makes an entry in the fattable for cluster_addr. The value it puts there + * is next_cluster_addr. +*/ +void fat_setNextClusterAddress(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr) +{ + euint8 *buf,*buf2; + euint16 offset; + euint32 sector; + + sector=fat_getSectorAddressFatEntry(fs,cluster_addr); + if(fs->FatSectorCount<sector){ + DBG((TXT("HARDERROR:::fat_getNextClusterAddress READ PAST FAT BOUNDARY\n"))); + return; + } + + buf=part_getSect(fs->part,sector,IOM_MODE_READWRITE); + + switch(fs->type){ + case FAT12: + offset = ((cluster_addr%1024)*3/2)%512; + if(offset == 511){ + if(cluster_addr%2==0){ + buf[offset]=next_cluster_addr&0xFF; + }else{ + buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); + } + buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READWRITE); + if(cluster_addr%2==0){ + buf2[0]=(buf2[0]&0xF0)+((next_cluster_addr>>8)&0xF); + }else{ + buf2[0]=(next_cluster_addr>>4)&0xFF; + } + part_relSect(fs->part,buf2); + }else{ + if(cluster_addr%2==0){ + buf[offset]=next_cluster_addr&0xFF; + buf[offset+1]=(buf[offset+1]&0xF0)+((next_cluster_addr>>8)&0xF); + }else{ + buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); + buf[offset+1]=(next_cluster_addr>>4)&0xFF; + } + } + part_relSect(fs->part,buf); + break; + case FAT16: + offset=cluster_addr%256; + *((euint16*)buf+offset)=next_cluster_addr; + part_relSect(fs->part,buf); + break; + case FAT32: + offset=cluster_addr%128; + *((euint32*)buf+offset)=next_cluster_addr; + part_relSect(fs->part,buf); + break; + } + +} +/*****************************************************************************/ + + +/* **************************************************************************** + * short fat_isEocMarker(FileSystem *fs,unsigned long fat_entry) + * Description: Checks if a certain value is the EoC marker for the filesystem + * noted in fs->type. + * Return value: Returns 0 when it is the EoC marker, and 1 otherwise. +*/ +eint16 fat_isEocMarker(FileSystem *fs,euint32 fat_entry) +{ + switch(fs->type){ + case FAT12: + if(fat_entry<0xFF8){ + return(0); + } + break; + case FAT16: + if(fat_entry<0xFFF8){ + return(0); + } + break; + case FAT32: + if((fat_entry&0x0FFFFFFF)<0xFFFFFF8){ + return(0); + } + break; + } + return(1); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * unsigned long fat_giveEocMarker(FileSystem *fs) + * Description: Returns an EoC markernumber valid for the filesystem noted in + * fs->type. + * Note, for FAT32, the upper 4 bits are set to zero, although they should be un + * touched according to MicroSoft specifications. I didn't care. + * Return value: The EoC marker cast to an ulong. +*/ +euint32 fat_giveEocMarker(FileSystem *fs) +{ + switch(fs->type) + { + case FAT12: + return(0xFFF); + break; + case FAT16: + return(0xFFFF); + break; + case FAT32: + return(0x0FFFFFFF); + break; + } + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 fat_getNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr, euint8* buf) + * Description: This function retrieves the contents of a FAT field. It does not fetch + * it's own buffer, it is given as a parameter. (ioman makes this function rather obsolete) + * Only in the case of a FAT12 crosssector data entry a sector is retrieved here. + * Return value: The value of the clusterfield is returned. +*/ +euint32 fat_getNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr, euint8* buf) +{ + euint8 *buf2; /* For FAT12 fallover only */ + euint8 hb,lb; + euint16 offset; + euint32 nextcluster=0; + + switch(fs->type) + { + case FAT12: + offset = ((cluster_addr%1024)*3/2)%512; + hb = buf[offset]; + if(offset == 511){ + buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READONLY); + lb = buf2[0]; + part_relSect(fs->part,buf2); + }else{ + lb = buf[offset + 1]; + } + if(cluster_addr%2==0){ + nextcluster = ( ((lb&0x0F)<<8) + (hb) ); + }else{ + nextcluster = ( (lb<<4) + (hb>>4) ); + } + break; + case FAT16: + offset=cluster_addr%256; + nextcluster = *((euint16*)buf + offset); + break; + case FAT32: + offset=cluster_addr%128; + nextcluster = *((euint32*)buf + offset); + break; + } + return(nextcluster); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void fat_setNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr,euint8* buf) + * Description: This function fills in a fat entry. The entry is cluster_addr and the + * data entered is next_cluster_addr. This function is also given a *buf, so it does + * not write the data itself, except in the case of FAT 12 cross sector data, where + * the second sector is handled by this function. + * Return value: +*/ +void fat_setNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr,euint8* buf) +{ + euint16 offset; + euint8 *buf2; + + switch(fs->type) + { + case FAT12: + offset = ((cluster_addr%1024)*3/2)%512; + if(offset == 511){ + if(cluster_addr%2==0){ + buf[offset]=next_cluster_addr&0xFF; + }else{ + buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); + } + buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READWRITE); + if(cluster_addr%2==0){ + buf2[0]=(buf2[0]&0xF0)+((next_cluster_addr>>8)&0xF); + }else{ + buf2[0]=(next_cluster_addr>>4)&0xFF; + } + part_relSect(fs->part,buf2); + }else{ + if(cluster_addr%2==0){ + buf[offset]=next_cluster_addr&0xFF; + buf[offset+1]=(buf[offset+1]&0xF0)+((next_cluster_addr>>8)&0xF); + }else{ + buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); + buf[offset+1]=(next_cluster_addr>>4)&0xFF; + } + } + break; + case FAT16: + offset=cluster_addr%256; + *((euint16*)buf+offset)=next_cluster_addr; + break; + case FAT32: + offset=cluster_addr%128; + *((euint32*)buf+offset)=next_cluster_addr; + break; + } +} +/*****************************************************************************/ + +/* **************************************************************************** + * esint16 fat_getNextClusterChain(FileSystem *fs, ClusterChain *Cache) + * Description: This function is to advance the clusterchain of a Cache. + * First, the function verifies if the Cache is valid. It could correct it if it + * is not, but this is not done at the time. If the cachen is valid, the next step is + * to see what the next cluster is, if this is the End of Clustermark, the cache is + * updated to know the lastcluster but will remain untouched otherwise. -1 is returned. + * If there are more clusters the function scans the rest of the chain until the next + * cluster is no longer lineair, or until it has run out of fat data (only 1 sector) is + * examined, namely the one fetched to check for EoC. + * With lineair is meant that logical cluster n+1 should be 1 more than logical cluster n + * at the disc level. + * Return value: 0 on success, or -1 when EoC. +*/ +esint16 fat_getNextClusterChain(FileSystem *fs, ClusterChain *Cache) +{ + euint32 sect,lr,nlr,dc; + esint16 lin=0; + euint8 *buf; + + if(Cache->DiscCluster==0) + { + return(-1); + } + + sect=fat_getSectorAddressFatEntry(fs,Cache->DiscCluster); + buf=part_getSect(fs->part,sect,IOM_MODE_READONLY); + dc=fat_getNextClusterAddressWBuf(fs,Cache->DiscCluster,buf); + if(fat_isEocMarker(fs,dc)) + { + Cache->LastCluster=Cache->DiscCluster; + part_relSect(fs->part,buf); + return(-1); + } + + Cache->DiscCluster=dc; + Cache->LogicCluster++; + + lr=Cache->DiscCluster-1; + nlr=lr+1; + + while(nlr-1==lr && fat_getSectorAddressFatEntry(fs,nlr)==sect) + { + lr=nlr; + nlr=fat_getNextClusterAddressWBuf(fs,lr,buf); + lin++; + } + + Cache->Linear=lin-1<0?0:lin-1; + + part_relSect(fs->part,buf); + return(0); +} +/*****************************************************************************/ + + +/* **************************************************************************** + * esint16 fat_LogicToDiscCluster(FileSystem *fs, ClusterChain *Cache,euint32 logiccluster) + * Description: This function is used to follow clusterchains. When called it will convert + * a logical cluster, to a disc cluster, using a Cache object. All it does is call + * getNextClusterChain in the proper manner, and rewind clusterchains if required. + * It is NOT recommended to go backwards in clusterchains, since this will require + * scanning the entire chain every time. + * Return value: 0 on success and -1 on failure (meaning out of bounds). +*/ +esint16 fat_LogicToDiscCluster(FileSystem *fs, ClusterChain *Cache,euint32 logiccluster) +{ + if(logiccluster<Cache->LogicCluster || Cache->DiscCluster==0){ + Cache->LogicCluster=0; + Cache->DiscCluster=Cache->FirstCluster; + Cache->Linear=0; + } + + if(Cache->LogicCluster==logiccluster){ + return(0); + } + + while(Cache->LogicCluster!=logiccluster) + { + if(Cache->Linear!=0) + { + Cache->Linear--; + Cache->LogicCluster++; + Cache->DiscCluster++; + } + else + { + if((fat_getNextClusterChain(fs,Cache))!=0){ + return(-1); + } + } + } + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * eint16 fat_allocClusterChain(FileSystem *fs,ClusterChain *Cache,euint32 num_clusters) + * Description: This function extends a clusterchain by num_clusters. It returns the + * number of clusters it *failed* to allocate. + * Return value: 0 on success, all other values are the number of clusters it could + * not allocate. +*/ +eint16 fat_allocClusterChain(FileSystem *fs,ClusterChain *Cache,euint32 num_clusters) +{ + euint32 cc,ncl=num_clusters,lc; + euint8 *bufa=0,*bufb=0; + euint8 overflow=0; + + if(Cache->FirstCluster<=1)return(num_clusters); + + lc=fs_getLastCluster(fs,Cache); + cc=lc; + + while(ncl > 0){ + cc++; + if(cc>=fs->DataClusterCount+1){ + if(overflow){ + bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE); + fat_setNextClusterAddressWBuf(fs,lc,fat_giveEocMarker(fs),bufa); + Cache->LastCluster=lc; + part_relSect(fs->part,bufa); + return(num_clusters-ncl); + } + cc=2; + overflow++; + } + bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cc),IOM_MODE_READONLY); + if(fat_getNextClusterAddressWBuf(fs,cc,bufa)==0){ + bufb=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE); + fat_setNextClusterAddressWBuf(fs,lc,cc,bufb); + part_relSect(fs->part,bufb); + ncl--; + lc=cc; + } + part_relSect(fs->part,bufa); + if(ncl==0){ + bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE); + fat_setNextClusterAddressWBuf(fs,lc,fat_giveEocMarker(fs),bufa); + Cache->LastCluster=lc; + part_relSect(fs->part,bufa); + } + } + return(0); +} + +/* **************************************************************************** + * eint16 fat_unlinkClusterChain(FileSystem *fs,ClusterChain *Cache) + * Description: This function removes a clusterchain. Starting at FirstCluster + * it follows the chain until the end, resetting all values to 0. + * Return value: 0 on success. +*/ +eint16 fat_unlinkClusterChain(FileSystem *fs,ClusterChain *Cache) +{ + euint32 c,tbd=0; + + Cache->LogicCluster=0; + Cache->DiscCluster=Cache->FirstCluster; + + c=0; + + while(!fat_LogicToDiscCluster(fs,Cache,c++)){ + if(tbd!=0){ + fat_setNextClusterAddress(fs,tbd,0); + } + tbd=Cache->DiscCluster; + } + fat_setNextClusterAddress(fs,Cache->DiscCluster,0); + return(0); +} + +euint32 fat_countClustersInChain(FileSystem *fs,euint32 firstcluster) +{ + ClusterChain cache; + euint32 c=0; + + if(firstcluster<=1)return(0); + + cache.DiscCluster = cache.LogicCluster = cache.LastCluster = cache.Linear = 0; + cache.FirstCluster = firstcluster; + + while(!(fat_LogicToDiscCluster(fs,&cache,c++))); + + return(c-1); +} + +euint32 fat_DiscToLogicCluster(FileSystem *fs,euint32 firstcluster,euint32 disccluster) +{ + ClusterChain cache; + euint32 c=0,r=0; + + cache.DiscCluster = cache.LogicCluster = cache.LastCluster = cache.Linear = 0; + cache.FirstCluster = firstcluster; + + while(!(fat_LogicToDiscCluster(fs,&cache,c++)) && !r){ + if(cache.DiscCluster == disccluster){ + r = cache.LogicCluster; + } + } + return(r); +} + +void fat_ShortnameToString(const euint8* src, eint8* nm) +{ + register eint32 i; + + i = 8; + while (i-- && *src != ' ') + { + *nm++ = *src++; + } + + src += i + 1; + if (*src > ' ') + { + *nm++ = '.'; + i = 3; + while (i-- && *src != ' ') + { + *nm++ = *src++; + } + } + + *nm = '\0'; +} diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/file.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/file.c new file mode 100644 index 0000000000..436989edc0 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/file.c @@ -0,0 +1,551 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : file.c * +* Release : 0.3 - devel * +* Description : This file contains functions dealing with files such as: * +* fopen, fread and fwrite. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include <dfs_fs.h> + +#include "file.h" +#include "ui.h" +/*****************************************************************************/ +/* **************************************************************************** + * euint32 file_fread(File *file,euint32 offset, euint32 size,euint8 *buf) + * Description: This function reads 'size' bytes from 'file' starting at + * 'offset' and puts the result in '*buf'. + * Return value: amount of bytes actually read (can differ from the given + * size when the file was smaller +*/ +euint32 file_fread(File *file,euint32 offset, euint32 size,euint8 *buf) +{ + euint32 bytes_read=0,size_left=size,coffset=offset; + euint32 cclus,csec,cbyte; + euint32 rclus,rsec; + euint32 btr; + euint8 *tbuf; + + if(!file_getAttr(file,FILE_STATUS_OPEN))return(0); + + if(offset>=file->FileSize) + size_left=0; /* Offset check */ + + if( (offset+size > file->FileSize) && size_left!=0) + size_left=file->FileSize-offset; + + while(size_left>0)
+ { + cclus = coffset/(512*file->fs->volumeId.SectorsPerCluster); + csec = (coffset/(512))%file->fs->volumeId.SectorsPerCluster; + cbyte = coffset%512; +
+ if ((size_left > 512 * file->fs->volumeId.SectorsPerCluster) &&
+ (csec == 0) && (cbyte == 0))
+ {
+ /* read whole cluster */
+ btr = 512 * file->fs->volumeId.SectorsPerCluster;
+ }
+ else if(cbyte!=0 || size_left<512)
+ {
+ btr = 512-(coffset%512) >= size_left? size_left:512-(coffset%512); + }
+ else
+ {
+ /* whole sector */ + btr = 512; + } + + if((fat_LogicToDiscCluster(file->fs,&(file->Cache),cclus))!=0){ + return(0); + }
+ + rclus = file->Cache.DiscCluster; + rsec = fs_clusterToSector(file->fs,rclus); + + if(btr > 512)
+ { + part_directSectorRead(file->fs->part, rsec + csec, buf + bytes_read, btr / 512); + }
+ else
+ { + tbuf = part_getSect(file->fs->part,rsec+csec,IOM_MODE_READONLY); + memCpy(tbuf+(coffset%512),buf+bytes_read,btr); + part_relSect(file->fs->part,tbuf); + } + + coffset+=btr; + bytes_read+=btr; + size_left-=btr; + } + + return(bytes_read); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 file_read (File *file,euint32 size,euint8 *buf) + * Description: This function reads from a file, taking the FilePtr into account + * and advancing it according to the freadcall. + * Return value: Value obtained from fread +*/ +euint32 file_read(File *file,euint32 size,euint8 *buf) +{ + euint32 r; + + r=file_fread(file,file->FilePtr,size,buf); + file->FilePtr+=r; + return(r); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 file_write(File *file, euint32 size,euint8 *buf) + * Description: This function writes to a file, taking FilePtr into account + * and advancing it according to the fwritecall. + * Return value: Value obtained from fread +*/ +euint32 file_write(File *file, euint32 size,euint8 *buf) +{ + euint32 r; + + r=file_fwrite(file,file->FilePtr,size,buf); + file->FilePtr+=r; + return(r); +} +/*****************************************************************************/ + +/* **************************************************************************** + * esint32 file_setpos(File *file,euint32 pos) + * Description: This function does a sanity check on the requested position + * and changes the fileptr accordingly. + * Return value: 0 on success and -1 on failure. +*/ +esint32 file_setpos(File *file,euint32 pos) +{ + if(pos<=file->FileSize){ + file->FilePtr=pos; + return(pos); + } + return(-1); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 file_fwrite(File* file,euint32 offset,euint32 size,euint8* buf) + * Description: This function writes to a file, at offset 'offset' and size 'size'. + * It also updates the FileSize in the object, and discstructure. + * Return value: Bytes actually written. +*/ +euint32 file_fwrite(File* file,euint32 offset,euint32 size,euint8* buf) +{ + euint32 need_cluster; + euint32 cclus,csec,cbyte; + euint32 size_left=size,bytes_written=0; + euint32 rclus,rsec; + euint32 coffset=offset; + euint16 btr; + euint8 *tbuf; + + if(!file_getAttr(file,FILE_STATUS_OPEN) || !file_getAttr(file,FILE_STATUS_WRITE))return(0); + + if(offset>file->FileSize){ + offset=file->FileSize; + } + + need_cluster = file_requiredCluster(file,offset,size); + + if(need_cluster){ + if(fat_allocClusterChain(file->fs,&(file->Cache),need_cluster+CLUSTER_PREALLOC_FILE)!=0){ + return(0); + } + } + + while(size_left>0){ + + cclus = coffset/(512*file->fs->volumeId.SectorsPerCluster); + csec = (coffset/(512))%file->fs->volumeId.SectorsPerCluster; + cbyte = coffset%512; + + if ((size_left > 512 * file->fs->volumeId.SectorsPerCluster) &&
+ (csec == 0) && (cbyte == 0))
+ {
+ /* write whole cluster */
+ btr = 512 * file->fs->volumeId.SectorsPerCluster;
+ }
+ else if(cbyte!=0 || size_left<512)
+ { + btr = 512- (coffset%512) >= size_left? size_left:512-(coffset%512); + }
+ else
+ {
+ /* whole sector */ + btr = 512; + } + + if((fat_LogicToDiscCluster(file->fs,&(file->Cache),cclus))!=0){ + file->FileSize+=bytes_written; + dir_setFileSize(file->fs,&(file->Location),file->FileSize); + return(bytes_written); + } + rclus=file->Cache.DiscCluster; + rsec=fs_clusterToSector(file->fs,rclus); + + if(btr > 512)
+ { + part_directSectorWrite(file->fs->part, rsec + csec, buf + bytes_written, btr / 512); + }
+ else
+ { + tbuf = part_getSect(file->fs->part,rsec+csec,IOM_MODE_READWRITE); + memCpy(buf+bytes_written, tbuf+(coffset%512), btr); + part_relSect(file->fs->part,tbuf); + } + + coffset+=btr; + bytes_written+=btr; + size_left-=btr; + } + + if(bytes_written>file->FileSize-offset){ + file->FileSize+=bytes_written-(file->FileSize-offset); + } + + return(bytes_written); +} + +/* **************************************************************************** + * esint8 file_fclose(File *file) + * Description: This function closes a file, by clearing the object. + * Return value: 0 on success. +*/ +esint8 file_fclose(File *file) +{ + if(fs_hasTimeSupport()){ + file->DirEntry.AccessDate = time_getDate(); + if(file_getAttr(file,FILE_STATUS_WRITE)){ + file->DirEntry.FileSize = file->FileSize; + file->DirEntry.WriteDate = file->DirEntry.AccessDate; + file->DirEntry.WriteTime = time_getTime(); + } + dir_updateDirectoryEntry(file->fs,&(file->DirEntry),&(file->Location)); + }else{ + if(file_getAttr(file,FILE_STATUS_WRITE)){ + dir_setFileSize(file->fs,&(file->Location),file->FileSize); + } + } + + memClr(file,sizeof(*file)); + file_setAttr(file,FILE_STATUS_OPEN,0); + file_setAttr(file,FILE_STATUS_WRITE,0); + return(0); +} + + +/* **************************************************************************** + * void file_initFile(File *file, FileSystem *fs, FileLocation *loc) + * Description: This function initialises a new file object, by filling in + * the fs pointer, filesize (note, that DirEntry must already be filled in) + * and known cache parameters. + * Return value: void +*/ +void file_initFile(File *file, FileSystem *fs, FileLocation *loc) +{ + file->fs=fs; + file->FileSize=file->DirEntry.FileSize; + file->FilePtr=0; + file->Location.Sector=loc->Sector; + file->Location.Offset=loc->Offset; + file->Cache.Linear=0; + file->Cache.FirstCluster=(((euint32)file->DirEntry.FirstClusterHigh)<<16)+ + file->DirEntry.FirstClusterLow; + file->Cache.LastCluster=0; + file->Cache.LogicCluster=0; + file->Cache.DiscCluster=file->Cache.FirstCluster; +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint8* file_normalToFatName(eint8* filename,eint8* fatfilename) + * Description: This function converts a human readable filename (limited to + * 8.3 eint8 character) to a valid FAT (not VFAT) filename. Invalid characters are + * changed to capital X and only the first 11 characters are used. + * Furthermore all letters are capitalised. + * Return value: pointer after the filename +*/ +eint8* file_normalToFatName(eint8* filename,eint8* fatfilename) +{ + euint8 c,dot=0,vc=0; + + for(c=0;c<11;c++)fatfilename[c]=' '; + + c=0; + + if(*filename == '.'){ + fatfilename[0]='.'; + vc++; + if(*(filename+1) == '.'){ + fatfilename[1]='.'; + filename+=2; + }else{ + filename++; + } + }else{ + while(*filename != '\0' && *filename != ' ' && *filename != '/'){ + if(*filename=='.' && !dot){ + dot=1; + c=8; + }else{ + if(dot){ + if(c<=10){ + fatfilename[c]=file_validateChar(*filename); + c++; + } + }else{ + if(c<=7){ + fatfilename[c]=file_validateChar(*filename); + c++; vc++; + } + } + } + filename++; + } + } + + if(vc>0){ + if(*filename=='\0'){ + return(filename); + }else{ + return(filename+1); + } + }else{ + return(0); + } +} +/*****************************************************************************/ + +/* **************************************************************************** + * + * Description: This function takes the character c, and if it is not a * + * valid FAT Filename character returns X. If it is a lowercase letter the * + * uppercase equivalent is returned. The remaining characters are returned * + * as they are. + * Return value: The validated char +*/ +euint8 file_validateChar(euint8 c) +{ + if( (c<0x20) || (c>0x20&&c<0x30&&c!='-') || (c>0x39&&c<0x41) || (c>0x5A&&c<0x61&&c!='_') || (c>0x7A&&c!='~') ) + return(0x58); + if( c>=0x61 && c<=0x7A ) + return(c-32); + + return(c); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void ioman_setAttr(IOManager *ioman,euint16 bufplace,euint8 attribute,euint8 val) + * Description: This sets the attribute of 'bufplace' to the given value (binary). + * + * Return value: void +*/ +void file_setAttr(File* file,euint8 attribute,euint8 val) +{ + if(val){ + file->FileStatus|=1<<attribute; + }else{ + file->FileStatus&=~(1<<attribute); + } +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint8 ioman_getAttr(IOManager *ioman,euint16 bufplace,euint8 attribute) + * Description: This function retrieves an attribute from the bufstat array. + * It returns nonzero when it attribute is true and 0 when it is false. + * Please note, I said "nonzero", not 1. + * Return value: Attribute. +*/ +euint8 file_getAttr(File* file,euint8 attribute) +{ + return(file->FileStatus&(1<<attribute)); +} +/*****************************************************************************/ + +euint32 file_requiredCluster(File *file,euint32 offset, euint32 size) +{ + euint32 clusters_required,clustersize; + euint32 hc; + + if((offset+size)>file->FileSize){ + hc = fat_countClustersInChain(file->fs,file->Cache.FirstCluster); + clustersize = file->fs->volumeId.BytesPerSector * file->fs->volumeId.SectorsPerCluster; + if((size-file->FileSize+offset)> + ((hc-((file->FileSize+clustersize-1)/clustersize))*clustersize)){ + clusters_required = (((offset+size)-(hc*clustersize))+clustersize-1)/clustersize; + }else{ + clusters_required = 0; + } + }else{ + clusters_required = 0; + } + return(clusters_required); +} + +esint8 file_fopen(File* file,FileSystem *fs,eint8* filename,eint32 mode) +{ + FileLocation loc; + FileRecord wtmp; + eint8 fatfilename[11]; + euint32 sec; + + dir_getFatFileName(filename,fatfilename); + + /* create */ + if(mode & DFS_O_CREAT) + { + /* file does not exist */ + if(fs_findFile(fs,filename,&loc,0) == 0) + { + if(fs_findFreeFile(fs,filename,&loc,0)) + { + dir_createDefaultEntry(fs,&wtmp,fatfilename); + dir_createDirectoryEntry(fs,&wtmp,&loc); + memCpy(&wtmp,&(file->DirEntry),sizeof(wtmp)); + file_initFile(file,fs,&loc); + sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); + dir_setFirstCluster(file->fs,&(file->Location),sec); + fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); + fs_initClusterChain(fs,&(file->Cache),sec); + fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); + + if (mode & DFS_O_APPEND) + file_setpos(file,file->FileSize); + } + else + { + dfs_log(DFS_DEBUG_INFO, ("no space left on device")); + + return -DFS_STATUS_ENOSPC; + } + } + else if ( mode & DFS_O_EXCL) + { + dfs_log(DFS_DEBUG_INFO, ("file has existed")); + + return -DFS_STATUS_EEXIST; + } + /*file exist*/ + else + { + dir_getFileStructure(fs,&(file->DirEntry), &loc); + file_initFile(file,fs,&loc); + } + + file_setAttr(file,FILE_STATUS_OPEN,1); + file_setAttr(file,FILE_STATUS_WRITE,1); + } + /* write */ + else if(mode & DFS_O_WRONLY || mode & DFS_O_RDWR) + { + /* file does not exist */ + if(fs_findFile(fs,filename,&loc,0) == 0) + { + if(fs_findFreeFile(fs,filename,&loc,0)) + { + dir_createDefaultEntry(fs,&wtmp,fatfilename); + dir_createDirectoryEntry(fs,&wtmp,&loc); + memCpy(&wtmp,&(file->DirEntry),sizeof(wtmp)); + file_initFile(file,fs,&loc); + sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); + dir_setFirstCluster(file->fs,&(file->Location),sec); + fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); + fs_initClusterChain(fs,&(file->Cache),sec); + fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); + + if (mode & DFS_O_APPEND) + file_setpos(file,file->FileSize); + } + else + { + dfs_log(DFS_DEBUG_INFO, ("no space left on device")); + + return -DFS_STATUS_ENOSPC; + } + } + else + { + if (mode & DFS_O_APPEND) + { + dir_getFileStructure(fs,&(file->DirEntry), &loc); + file_initFile(file,fs,&loc); + if(file->Cache.FirstCluster==0) + { + sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); + dir_setFirstCluster(file->fs,&(file->Location),sec); + fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); + fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); + file_initFile(file,fs,&loc); + file_setpos(file,file->FileSize); + } + } + else + { + dir_getFileStructure(fs,&(file->DirEntry), &loc); + file_initFile(file,fs,&loc); + } + } + + file_setAttr(file,FILE_STATUS_OPEN,1); + file_setAttr(file,FILE_STATUS_WRITE,1); + } + /* read */ + else + { + /* file does not exist */ + if(fs_findFile(fs,filename,&loc,0) == 0) + { + dfs_log(DFS_DEBUG_INFO, ("file doesn't exist")); + + return -DFS_STATUS_ENOENT; + } + else + { + dir_getFileStructure(fs,&(file->DirEntry), &loc); + file_initFile(file,fs,&loc); + + file_setAttr(file,FILE_STATUS_OPEN,1); + file_setAttr(file,FILE_STATUS_WRITE,0); + } + } + + return 0; +} + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/fs.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/fs.c new file mode 100644 index 0000000000..0958f90cce --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/fs.c @@ -0,0 +1,503 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : fs.c * +* Release : 0.3 - devel * +* Description : These are general filesystem functions, supported by the * +* functions of dir.c and fat.c file.c uses these functions * +* heavily, but is not used by fs.c (not true anymore) * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "fs.h" +#include "fat.h" +#include "dir.h" +/*****************************************************************************/ + +/* **************************************************************************** + * eint16 fs_initFs(FileSystem *fs,Partition *part) + * Description: This functions glues the initialisation of the filesystem together. + * It loads the volumeID, computes the FS type and searches for the rootsector. + * Return value: Returns 0 on succes and -1 on error (if magic code is wrong) +*/ +eint16 fs_initFs(FileSystem *fs,Partition *part) +{ + if(!fs_isValidFat(part)){ + return(-1); + } + fs->part=part; + fs_loadVolumeId(fs,part); + if(!fs_verifySanity(fs))return(-2); + fs_countDataSectors(fs); + fs_determineFatType(fs); + fs_findFirstSectorRootDir(fs); + fs_initCurrentDir(fs); + + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * eint16 fs_isValidFat(Partition *part) + * Description: This functions loads the volumeID and checks if the magic + * value is present. + * Return value: returns 0 when magic code is missing, 1 if it is there. +*/ +eint16 fs_isValidFat(Partition *part) +{ + euint8 *buf; + + buf=part_getSect(part,0,IOM_MODE_READONLY|IOM_MODE_EXP_REQ); /* Load Volume label */ + if( ex_getb16(buf+0x1FE) != 0xAA55 ){ + return (0); + } + part_relSect(part,buf); + return(1); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void fs_loadVolumeId(FileSystem *fs, Partition *part) + * Description: This function loads all relevant fields from the volumeid. +*/ +void fs_loadVolumeId(FileSystem *fs, Partition *part) +{ + euint8 *buf; + + buf=part_getSect(part,0,IOM_MODE_READONLY|IOM_MODE_EXP_REQ); + + fs->volumeId.BytesPerSector=ex_getb16(buf+0x0B); + fs->volumeId.SectorsPerCluster=*((eint8*)(buf+0x0D)); + fs->volumeId.ReservedSectorCount=ex_getb16(buf+0x0E); + fs->volumeId.NumberOfFats=*((eint8*)(buf+0x10)); + fs->volumeId.RootEntryCount=ex_getb16(buf+0x11); + fs->volumeId.SectorCount16=ex_getb16(buf+0x13); + fs->volumeId.FatSectorCount16=ex_getb16(buf+0x16); + fs->volumeId.SectorCount32=ex_getb32(buf+0x20); + fs->volumeId.FatSectorCount32=ex_getb32(buf+0x24); + fs->volumeId.RootCluster=ex_getb32(buf+0x2C); + + part_relSect(part,buf); + +} +/*****************************************************************************/ + +/* **************************************************************************** + * esint16 fs_verifySanity(FileSystem *fs) + * Description: Does some sanity calculations. + * Return value: 1 on success, 0 when discrepancies were found. +*/ +esint16 fs_verifySanity(FileSystem *fs) +{ + esint16 sane=1; /* Sane until proven otherwise */ + /* First check, BPS, we only support 512 */ + if(fs->volumeId.BytesPerSector!=512)sane=0; + /* Check is SPC is valid (multiple of 2, and clustersize >=32KB */ + if(!((fs->volumeId.SectorsPerCluster == 1 ) | + (fs->volumeId.SectorsPerCluster == 2 ) | + (fs->volumeId.SectorsPerCluster == 4 ) | + (fs->volumeId.SectorsPerCluster == 8 ) | + (fs->volumeId.SectorsPerCluster == 16) | + (fs->volumeId.SectorsPerCluster == 32) | + (fs->volumeId.SectorsPerCluster == 64) ))sane=0; + /* Any number of FAT's should be supported... (untested) */ + /* There should be at least 1 reserved sector */ + if(fs->volumeId.ReservedSectorCount==0)sane=0; + + return(sane); +} +/*****************************************************************************/ + +/* **************************************************************************** + * void fs_countDataSectors(FileSystem *fs) + * Description: This functions calculates the sectorcounts, fatsectorcounts and + * dataclustercounts. It fills in the general fields. +*/ +void fs_countDataSectors(FileSystem *fs) +{ + euint32 rootDirSectors,dataSectorCount; + + rootDirSectors=((fs->volumeId.RootEntryCount*32) + + (fs->volumeId.BytesPerSector - 1)) / + fs->volumeId.BytesPerSector; + + if(fs->volumeId.FatSectorCount16 != 0) + { + fs->FatSectorCount=fs->volumeId.FatSectorCount16; + fs->volumeId.FatSectorCount32=0; + } + else + { + fs->FatSectorCount=fs->volumeId.FatSectorCount32; + fs->volumeId.FatSectorCount16=0; + } + + if(fs->volumeId.SectorCount16!=0) + { + fs->SectorCount=fs->volumeId.SectorCount16; + fs->volumeId.SectorCount32=0; + } + else + { + fs->SectorCount=fs->volumeId.SectorCount32; + fs->volumeId.SectorCount16=0; + } + + dataSectorCount=fs->SectorCount - ( + fs->volumeId.ReservedSectorCount + + (fs->volumeId.NumberOfFats * fs->FatSectorCount) + + rootDirSectors); + + fs->DataClusterCount=dataSectorCount/fs->volumeId.SectorsPerCluster; +} +/*****************************************************************************/ + +/* **************************************************************************** + * void fs_determineFatType(FileSystem *fs) + * Description: This function looks af the Dataclustercount and determines the + * FAT type. It fills in fs->type. +*/ +void fs_determineFatType(FileSystem *fs) +{ + if(fs->DataClusterCount < 4085) + { + fs->type=FAT12; + fs->volumeId.RootCluster=0; + } + else if(fs->DataClusterCount < 65525) + { + fs->type=FAT16; + fs->volumeId.RootCluster=0; + } + else + { + fs->type=FAT32; + } +} +/*****************************************************************************/ + +/* **************************************************************************** + * void fs_findFirstSectorRootDir(FileSystem *fs) + * Description: This functions fills in the fs->FirstSectorRootDir field, even + * for FAT32, although that is not necessary (because you have FirstClusterRootDir). +*/ +void fs_findFirstSectorRootDir(FileSystem *fs) +{ + if(fs->type==FAT32) + fs->FirstSectorRootDir = fs->volumeId.ReservedSectorCount + + (fs->volumeId.NumberOfFats*fs->volumeId.FatSectorCount32) + + (fs->volumeId.RootCluster-2)*fs->volumeId.SectorsPerCluster; + else + fs->FirstSectorRootDir = fs->volumeId.ReservedSectorCount + + (fs->volumeId.NumberOfFats*fs->volumeId.FatSectorCount16); +} +/*****************************************************************************/ + +void fs_initCurrentDir(FileSystem *fs) +{ + fs->FirstClusterCurrentDir = fs_getFirstClusterRootDir(fs); +} +/*****************************************************************************/ + +/* **************************************************************************** + * long fs_clusterToSector(FileSystem *fs,euint32 cluster) + * Description: This function converts a clusternumber in the effective sector + * number where this cluster starts. Boundary check is not implemented + * Return value: A long is returned representing the sectornumber. +*/ +euint32 fs_clusterToSector(FileSystem *fs,euint32 cluster) +{ + eint32 base; + + if(fs->type==FAT32) + { + base= + fs->volumeId.ReservedSectorCount+ + fs->FatSectorCount*fs->volumeId.NumberOfFats; + } + else + { + base= + fs->volumeId.ReservedSectorCount+ + fs->FatSectorCount*fs->volumeId.NumberOfFats+ + fs->volumeId.RootEntryCount/16; + } + return( base + (cluster-2)*fs->volumeId.SectorsPerCluster ); +} +/*****************************************************************************/ + +/* Function is unused, but may be usefull */ +euint32 fs_sectorToCluster(FileSystem *fs,euint32 sector) +{ + eint32 base; + + if(fs->type==FAT32) + { + base= + fs->volumeId.ReservedSectorCount+ + fs->FatSectorCount*fs->volumeId.NumberOfFats; + } + else + { + base= + fs->volumeId.ReservedSectorCount+ + fs->FatSectorCount*fs->volumeId.NumberOfFats+ + fs->volumeId.RootEntryCount/16; + } + return(((sector-base)-((sector-base)%fs->volumeId.SectorsPerCluster))/fs->volumeId.SectorsPerCluster+2 ); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 fs_getNextFreeCluster(FileSystem *fs,euint32 startingcluster) + * Description: This functions searches for a free cluster, starting it's search at + * cluster startingcluster. This allow to speed up searches and try to avoid + * fragmentation. Implementing rollover search is still to be done. + * Return value: If a free cluster is found it's number is returned. If none is + * found 0 is returned. +*/ +euint32 fs_getNextFreeCluster(FileSystem *fs,euint32 startingcluster) +{ + euint32 r; + + while(startingcluster<fs->DataClusterCount){ + r=fat_getNextClusterAddress(fs,startingcluster,0); + if(r==0){ + return(startingcluster); + } + startingcluster++; + } + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 fs_giveFreeClusterHint(FileSystem *fs) + * + * Description: This function should return a clusternumber that is free or + * lies close before free clusters. The result MUST be checked to see if + * it is free! Implementationhint: search the largest clusternumber in the + * files in the rootdirectory. + * + * Return value: Returns it's best guess. +*/ +euint32 fs_giveFreeClusterHint(FileSystem *fs) +{ + return(2); /* Now THIS is a hint ;) */ +} +/*****************************************************************************/ + +/* **************************************************************************** + * esint8 fs_findFile(FileSystem *fs,eint8* filename,FileLocation *loc,euint32 *lastDir) + * + * Description: This function looks if the given filename is on the given fs + * and, if found, fills in its location in loc. + * The function will first check if the pathname starts with a slash. If so it will + * set the starting directory to the rootdirectory. Else, it will take the firstcluster- + * currentdir (That you can change with chdir()) as startingpoint. + * The lastdir pointer will be the first cluster of the last directory fs_findfile + * enters. It starts out at the root/current dir and then traverses the path along with + * fs_findFile. + * It is set to 0 in case of errors (like dir/dir/dir/file/dir/dir...) + * Return value: Returns 0 when nothing was found, 1 when the thing found + * was a file and 2 if the thing found was a directory. +*/ + +esint8 fs_findFile(FileSystem *fs,eint8* filename,FileLocation *loc,euint32 *lastDir) +{ + euint32 fccd,tmpclus; + eint8 ffname[11],*next,it=0,filefound=0; + + if(*filename=='/'){ + fccd = fs_getFirstClusterRootDir(fs); + filename++; + if(!*filename){ + if(lastDir)*lastDir=fccd; + return(2); + } + }else{ + fccd = fs->FirstClusterCurrentDir; + } + + if(lastDir)*lastDir=fccd; + + while((next=file_normalToFatName(filename,ffname))!=0){ + if((tmpclus=dir_findinDir(fs,ffname,fccd,loc,DIRFIND_FILE))==0)return(0); + it++; + if(loc->attrib&ATTR_DIRECTORY){ + fccd = tmpclus; + filename = next; + if(lastDir)*lastDir=fccd; + if(filefound)*lastDir=0; + }else{ + filefound=1; + if((file_normalToFatName(next,ffname))!=0){ + return(0); + }else{ + filename=next; + } + } + } + + if(it==0)return(0); + if(loc->attrib&ATTR_DIRECTORY || !filefound)return(2); + return(1); +} +/*****************************************************************************/ + +esint16 fs_findFreeFile(FileSystem *fs,eint8* filename,FileLocation *loc,euint8 mode) +{ + euint32 targetdir=0; + eint8 ffname[11]; + + if(fs_findFile(fs,filename,loc,&targetdir))return(0); + if(!dir_getFatFileName(filename,ffname))return(0); + if(dir_findinDir(fs,ffname,targetdir,loc,DIRFIND_FREE)){ + return(1); + }else{ + if(dir_addCluster(fs,targetdir)){ + return(0); + }else{ + if(dir_findinDir(fs,ffname,targetdir,loc,DIRFIND_FREE)){ + return(1); + } + } + } + + return(0); +} +/*****************************************************************************/ + +/* **************************************************************************** + * euint32 fs_getLastCluster(FileSystem *fs,ClusterChain *Cache) + * Description: This function searches the last cluster of a chain. + * Return value: The LastCluster (also stored in cache); +*/ +euint32 fs_getLastCluster(FileSystem *fs,ClusterChain *Cache) +{ + if(Cache->DiscCluster==0){ + Cache->DiscCluster=Cache->FirstCluster; + Cache->LogicCluster=0; + } + + if(Cache->LastCluster==0) + { + while(fat_getNextClusterChain(fs, Cache)==0) + { + Cache->LogicCluster+=Cache->Linear; + Cache->DiscCluster+=Cache->Linear; + Cache->Linear=0; + } + } + return(Cache->LastCluster); +} +/*****************************************************************************/ + +euint32 fs_getFirstClusterRootDir(FileSystem *fs) +{
+ if (fs->type == FAT32)
+ return fs->volumeId.RootCluster;
+
+ return 1; +} +/*****************************************************************************/ + +void fs_initClusterChain(FileSystem *fs,ClusterChain *cache,euint32 cluster_addr) +{ + cache->FirstCluster=cluster_addr; + cache->DiscCluster=cluster_addr; + cache->LogicCluster=0; + cache->LastCluster=0; /* Warning flag here */ + cache->Linear=0; +} +/*****************************************************************************/ + +void fs_setFirstClusterInDirEntry(FileRecord *rec,euint32 cluster_addr) +{ + rec->FirstClusterHigh=cluster_addr>>16; + rec->FirstClusterLow=cluster_addr&0xFFFF; +} +/*****************************************************************************/ + +esint8 fs_flushFs(FileSystem *fs) +{ + return(part_flushPart(fs->part,0,fs->SectorCount)); +} +/*****************************************************************************/ + +esint8 fs_umount(FileSystem *fs) +{ + return(fs_flushFs(fs)); +} +/*****************************************************************************/ + +esint8 fs_clearCluster(FileSystem *fs,euint32 cluster) +{ + euint16 c; + euint8* buf; + + for(c=0;c<(fs->volumeId.SectorsPerCluster);c++){ + buf = part_getSect(fs->part,fs_clusterToSector(fs,cluster)+c,IOM_MODE_READWRITE); + memClr(buf,512); + part_relSect(fs->part,buf); + } + return(0); +} + +esint8 fs_getFsInfo(FileSystem *fs) +{ + euint8 *buf; + + if(!fs->type==FAT32)return(0); + buf = part_getSect(fs->part,FS_INFO_SECTOR,IOM_MODE_READONLY); + if(ex_getb32(buf+0)!=FSINFO_MAGIC_BEGIN || ex_getb32(buf+508)!=FSINFO_MAGIC_END){ + part_relSect(fs->part,buf); + return(-1); + } + fs->FreeClusterCount = ex_getb32(buf+488); + fs->NextFreeCluster = ex_getb32(buf+492); + part_relSect(fs->part,buf); + return(0); +} + +esint8 fs_setFsInfo(FileSystem *fs) +{ + euint8* buf; + + if(!fs->type==FAT32)return(0); + buf = part_getSect(fs->part,FS_INFO_SECTOR,IOM_MODE_READWRITE); + if(ex_getb32(buf+0)!=FSINFO_MAGIC_BEGIN || ex_getb32(buf+508)!=FSINFO_MAGIC_END){ + part_relSect(fs->part,buf); + return(-1); + } + ex_setb32(buf+488,fs->FreeClusterCount); + ex_setb32(buf+492,fs->NextFreeCluster); + part_relSect(fs->part,buf); + return(0); +} + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/dir.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/dir.h new file mode 100644 index 0000000000..4e7b880a0e --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/dir.h @@ -0,0 +1,86 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : dir.h * +* Release : 0.3 - devel * +* Description : The functions of dir.c are part of fs.c, they deal with all * +* the directory specific stuff. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __DDIR_H__ +#define __DDIR_H__ + +/*****************************************************************************/ +#include "config.h" +#include "error.h" +#include "fat.h" +#include "plibc.h" +#include "types.h" +// #include "ioman.h"
+#include "tm.h" +#include "fs.h" +#include <dfs_cache.h> +/*****************************************************************************/ + +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 + +#define OFFSET_DE_FILENAME 0 +#define OFFSET_DE_ATTRIBUTE 11 +#define OFFSET_DE_NTRESERVED 12 +#define OFFSET_DE_CRTIMETNT 13 +#define OFFSET_DE_CREATETIME 14 +#define OFFSET_DE_CREATEDATE 16 +#define OFFSET_DE_LASTACCESSDATE 18 +#define OFFSET_DE_FIRSTCLUSTERHIGH 20 +#define OFFSET_DE_WRITETIME 22 +#define OFFSET_DE_WRITEDATE 24 +#define OFFSET_DE_FIRSTCLUSTERLOW 26 +#define OFFSET_DE_FILESIZE 28 + +#define DIRFIND_FILE 0 +#define DIRFIND_FREE 1 + +void dir_getFileStructure(FileSystem *fs,FileRecord *filerec,FileLocation *loc); +void dir_createDirectoryEntry(FileSystem *fs,FileRecord *filerec,FileLocation *loc); +void dir_createDefaultEntry(FileSystem *fs,FileRecord *filerec,eint8* fatfilename); +void dir_setFirstCluster(FileSystem *fs,FileLocation *loc,euint32 cluster_addr); +void dir_setFileSize(FileSystem *fs,FileLocation *loc,euint32 numbytes); +euint32 dir_findinRoot(FileSystem *fs,eint8 * fatname, FileLocation *loc); +euint32 dir_findinDir(FileSystem *fs, eint8 * fatname, euint32 startCluster, FileLocation *loc, euint8 mode); +euint32 dir_findinBuf(euint8 *buf,eint8 *fatname, FileLocation *loc, euint8 mode); +euint32 dir_findinCluster(FileSystem *fs,euint32 cluster,eint8 *fatname, FileLocation *loc, euint8 mode); +euint32 dir_findinRootArea(FileSystem *fs,eint8* fatname, FileLocation *loc, euint8 mode); +esint8 dir_getFatFileName(eint8* filename, eint8* fatfilename); +esint8 dir_updateDirectoryEntry(FileSystem *fs,FileRecord *entry,FileLocation *loc); +esint8 dir_addCluster(FileSystem *fs,euint32 firstCluster); +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fat.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fat.h new file mode 100644 index 0000000000..3a3b169660 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fat.h @@ -0,0 +1,64 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : fat.h * +* Release : 0.3 - devel * +* Description : This file contains all the functions dealing with the FAT * +* in a Microsoft FAT filesystem. It belongs under fs.c * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __FAT_H_ +#define __FAT_H_ + +/*****************************************************************************/ +#include "config.h" +#include "error.h" +#include "file.h" +#include "debug.h" +#include "types.h" +/*****************************************************************************/ + +euint32 fat_getSectorAddressFatEntry(FileSystem *fs,euint32 cluster_addr); +euint32 fat_getNextClusterAddress(FileSystem *fs, euint32 cluster_addr, euint16 *linear); +void fat_setNextClusterAddress(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr); +eint16 fat_isEocMarker(FileSystem *fs,euint32 fat_entry); +euint32 fat_giveEocMarker(FileSystem *fs); +euint32 fat_findClusterAddress(FileSystem *fs,euint32 cluster,euint32 offset, euint8 *linear); +euint32 fat_getNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr, euint8 * buf); +void fat_setNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr,euint8 * buf); +esint16 fat_getNextClusterChain(FileSystem *fs, ClusterChain *Cache); +void fat_bogus(void); +esint16 fat_LogicToDiscCluster(FileSystem *fs, ClusterChain *Cache,euint32 logiccluster); +eint16 fat_allocClusterChain(FileSystem *fs,ClusterChain *Cache,euint32 num_clusters); +eint16 fat_unlinkClusterChain(FileSystem *fs,ClusterChain *Cache); +euint32 fat_countClustersInChain(FileSystem *fs,euint32 firstcluster); +euint32 fat_DiscToLogicCluster(FileSystem *fs,euint32 firstcluster,euint32 disccluster); +void fat_ShortnameToString(const euint8* src, eint8* nm); + + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/file.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/file.h new file mode 100644 index 0000000000..d389ccdf20 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/file.h @@ -0,0 +1,100 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : file.h * +* Release : 0.3 - devel * +* Description : This file contains functions dealing with files such as: * +* fopen, fread and fwrite. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __FILE_H_ +#define __FILE_H_ + +/*****************************************************************************/ +#include "config.h" +#include "error.h" +#include "tm.h" +#include "fs.h" +#include "dir.h" +#include "plibc.h" +#include "debug.h" +#include "types.h" +#include "fat.h" +/*****************************************************************************/ + +/* Operation flags */ +#define EFSL_O_RDONLY 0 +#define EFSL_O_WRONLY 1 +#define EFSL_O_RDWR 2 +#define EFSL_O_APPEND 8 + +#define FILE_STATUS_OPEN 0 +#define FILE_STATUS_WRITE 1 + +/*****************************************************************************\ + * File + * ------ + * FileRecord DirEntry Copy of the FileRecord for this file + * FileLocation Location Location of the direntry + * FileSystem *fs Pointer to the filesystem this file is on + * FileCache Cache Pointer to the cache object of the file + * euint8 FileStatus Contains bitfield regarding filestatus + * euint32 FilePtr Offsetpointer for fread/fwrite functions + * euint32 FileSize Working copy of the filesize, always use this, + it is more up to date than DirEntry->FileSize, + which is only updated when flushing to disc. +\*****************************************************************************/ +struct _File{ + FileRecord DirEntry; + FileLocation Location; /* Location in directory!! */ + FileSystem *fs; + ClusterChain Cache; + euint8 FileStatus; + euint32 FilePtr; + euint32 FileSize; + euint32 ref_count; /* Descriptor reference count */ +}; +typedef struct _File File; + + +esint8 file_fopen(File *file, FileSystem *fs,eint8 *filename, eint32 mode); +esint8 file_fclose(File *file); +esint32 file_setpos(File *file,euint32 pos); +euint32 file_fread(File *file,euint32 offset, euint32 size,euint8 *buf); +euint32 file_read (File *file,euint32 size,euint8 *buf); +euint32 file_fwrite(File* file,euint32 offset,euint32 size,euint8* buf); +euint32 file_write (File* file,euint32 size,euint8* buf); +eint8* file_normalToFatName(eint8* filename,eint8* fatfilename); +euint8 file_validateChar(euint8 c); +void file_initFile(File *file, FileSystem *fs, FileLocation *loc); +eint16 file_allocClusterChain(File *file,euint32 num_clusters); +void file_setAttr(File* file,euint8 attribute,euint8 val); +euint8 file_getAttr(File* file,euint8 attribute); +euint32 file_requiredCluster(File *file,euint32 offset, euint32 size); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fs.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fs.h new file mode 100644 index 0000000000..21cc3c0852 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fs.h @@ -0,0 +1,201 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : fs.h * +* Release : 0.3 - devel * +* Description : These are general filesystem functions, supported by the * +* functions of dir.c and fat.c file.c uses these functions * +* heavily, but is not used by fs.c (not true anymore) * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __FS_H_ +#define __FS_H_ + +/*****************************************************************************/ +#include "config.h" +#include "types.h" +#include "error.h" +#include "partition.h" +#include "debug.h" +#include "tm.h" +#include "extract.h" +/*****************************************************************************/ + +#define FAT12 1 +#define FAT16 2 +#define FAT32 3 + +#define FS_INFO_SECTOR 1 +#define FSINFO_MAGIC_BEGIN 0x41615252 +#define FSINFO_MAGIC_END 0xAA550000 + +/*****************************************************************************************\ + VolumeId + ------ +* ushort BytesPerSector Must be 512 or shit happens. +* uchar SectorsPerCluster Must be multiple of 2 (1,2,4,8,16 or 32) +* ushort ReservedSectorCount Number of sectors after which the first FAT begins. +* uchar NumberOfFats Should be 2 +* ushort RootEntryCount Number of filerecords the Rootdir can contain. NOT for FAT32 +* ushort SectorCount16 Number of Sectors for 12/16 bit FAT +* ushort FatSectorCount16 Number of Sectors for 1 FAT on FAT12/16 bit FAT's +* ulong SectorCount32 Number of Sectors for 32 bit FAT +* ulong FatSectorCount32 Number of Sectors for 1 FAT on FAT32 +* ulong RootCluster Clusternumber of the first cluster of the RootDir on FAT 32 +This is NOT a complete volumeId copy, no direct I/O is possible. +\*****************************************************************************************/ +struct _VolumeId{ + euint16 BytesPerSector; + euint8 SectorsPerCluster; + euint16 ReservedSectorCount; + euint8 NumberOfFats; + euint16 RootEntryCount; + euint16 SectorCount16; + euint16 FatSectorCount16; + euint32 SectorCount32; + euint32 FatSectorCount32; + euint32 RootCluster; +}; +typedef struct _VolumeId VolumeId; + +/**************************************************************************************************\ + FileSystem + -------- +* Partition* part Pointer to partition on which this FS resides. +* VolumeId volumeId Contains important FS info. +* ulong DataClusterCount Number of dataclusters. This number determines the FATType. +* ulong FatSectorCount Number of sectors for 1 FAT, regardless of FATType +* ulong SectorCount Number of sectors, regardless of FATType +* ulong FirstSectorRootDir First sector of the RootDir. +* uchar type Determines FATType (FAT12 FAT16 or FAT32 are defined) + +\**************************************************************************************************/ +struct _FileSystem{ + Partition *part; + VolumeId volumeId; + euint32 DataClusterCount; + euint32 FatSectorCount; + euint32 SectorCount; + euint32 FirstSectorRootDir; + euint32 FirstClusterCurrentDir; + euint32 FreeClusterCount; + euint32 NextFreeCluster; + euint8 type; +}; +typedef struct _FileSystem FileSystem; + +/**************************************************************************************************\ + FileLocation + ---------- +* euint32 Sector Sector where the directoryentry of the file/directory can be found. +* euint8 Offset Offset (in 32byte segments) where in the sector the entry is. + +\**************************************************************************************************/ +struct _FileLocation{ + euint32 Sector; + euint8 Offset; + euint8 attrib; +}; +typedef struct _FileLocation FileLocation; + +/*****************************************************************************\ +* FileCache +* ----------- +* This struct acts as cache for the current file. It contains the current +* FATPointer (next location in the FAT table), LogicCluster +* (the last part of the file that was read) and DataCluster +* (the last cluster that was read). +* euint8 Linear For how many more clusters the file is nonfragmented +* euint32 LogicCluster This field determines the n'th cluster of the file as current +* euint32 DiscCluster If this field is 0, it means the cache is invalid. Otherwise + it is the clusternumber corresponding with + logic(FirstCluster+LogicCluster). +* euint32 FirstCluster First cluster of the chain. Zero or one are invalid. +* euint32 LastCluster Last cluster of the chain (is not always filled in) +\*****************************************************************************/ +struct _ClusterChain{ + euint8 Linear; + esint32 LogicCluster; + euint32 DiscCluster; + euint32 FirstCluster; + euint32 LastCluster; +}; +typedef struct _ClusterChain ClusterChain; + +/*****************************************************************************\ +* FileRecord * +* ------------ * +* This struct represents a 32 byte file entry as it occurs in the data area * +* of the filesystem. Direct I/O is possible. * +\*****************************************************************************/ +struct _FileRecord{ + euint8 FileName[11]; + euint8 Attribute; + euint8 NTReserved; + euint8 MilliSecTimeStamp; + euint16 CreatedTime; + euint16 CreatedDate; + euint16 AccessDate; + euint16 FirstClusterHigh; + euint16 WriteTime; + euint16 WriteDate; + euint16 FirstClusterLow; + euint32 FileSize; +}; +typedef struct _FileRecord FileRecord; + + +eint16 fs_initFs(FileSystem *fs,Partition *part); +eint16 fs_isValidFat(Partition *part); +void fs_loadVolumeId(FileSystem *fs, Partition *part); +esint16 fs_verifySanity(FileSystem *fs); +void fs_countDataSectors(FileSystem *fs); +void fs_determineFatType(FileSystem *fs); +void fs_findFirstSectorRootDir(FileSystem *fs); +void fs_initCurrentDir(FileSystem *fs); +euint32 fs_getSectorAddressRootDir(FileSystem *fs,euint32 secref); +euint32 fs_clusterToSector(FileSystem *fs,euint32 cluster); +euint32 fs_sectorToCluster(FileSystem *fs,euint32 sector); +euint32 fs_getNextFreeCluster(FileSystem *fs,euint32 startingcluster); +euint32 fs_giveFreeClusterHint(FileSystem *fs); +esint16 fs_findFreeFile(FileSystem *fs,eint8* filename,FileLocation *loc,euint8 mode); +esint8 fs_findFile(FileSystem *fs,eint8* filename,FileLocation *loc,euint32 *lastDir); +esint8 fs_findFile_broken(FileSystem *fs,eint8* filename,FileLocation *loc); +euint32 fs_getLastCluster(FileSystem *fs,ClusterChain *Cache); +euint32 fs_getFirstClusterRootDir(FileSystem *fs); +euint16 fs_makeDate(void); +euint16 fs_makeTime(void); +void fs_setFirstClusterInDirEntry(FileRecord *rec,euint32 cluster_addr); +void fs_initClusterChain(FileSystem *fs,ClusterChain *cache,euint32 cluster_addr); +esint8 fs_flushFs(FileSystem *fs); +esint8 fs_umount(FileSystem *fs); +esint8 fs_clearCluster(FileSystem *fs,euint32 cluster); +esint8 fs_getFsInfo(FileSystem *fs); +esint8 fs_setFsInfo(FileSystem *fs); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ls.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ls.h new file mode 100644 index 0000000000..c4d9701fed --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ls.h @@ -0,0 +1,69 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ls.h * +* Release : 0.3 - devel * +* Description : This file contains functions to list the files in a directory * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __LS_H__ +#define __LS_H__ + +/*****************************************************************************/ +#include "config.h" +#include "fs.h" +#include "dir.h" +#include "fat.h" +/*****************************************************************************/ + +struct _ListDirEntry{ + euint8 FileName[LIST_MAXLENFILENAME]; + euint32 FileSize; + euint8 Attribute; +}; +typedef struct _ListDirEntry ListDirEntry; + +struct _DirList{ + FileSystem *fs; + euint16 cEntry,rEntry; + /*FileRecord currentEntry;*/ + ListDirEntry currentEntry; + ClusterChain Cache; +}; +typedef struct _DirList DirList; + +esint8 ls_openDir(DirList *dlist,FileSystem *fs,eint8* dirname); +esint8 ls_getNext(DirList *dlist); + +esint8 ls_getDirEntry(DirList *dlist); +esint8 ls_getRealDirEntry(DirList *dlist); +esint8 ls_getRootAreaEntry(DirList *dlist); +esint8 ls_isValidFileEntry(ListDirEntry *entry); +void ls_fileEntryToDirListEntry(DirList *dlist, euint8* buf, euint16 offset); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/mkfs.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/mkfs.h new file mode 100644 index 0000000000..b211538b46 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/mkfs.h @@ -0,0 +1,50 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : mkfs.h * +* Release : 0.3 - devel * +* Description : These functions are used for creating an empty filesystem. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __MKFS_H_ +#define __MKFS_H_ + +/*****************************************************************************/ +#include "partition.h" +#include "plibc.h" +#include "debug.h" +#include "types.h" +#include "extract.h" +#include "config.h" +/*****************************************************************************/ + +#define MKFS_ERR_TOOLITTLESECTORS 1 + +esint16 mkfs_makevfat(Partition *part); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/tm.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/tm.h new file mode 100644 index 0000000000..42b1bade08 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/tm.h @@ -0,0 +1,74 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : time.h * +* Release : 0.3 - devel * +* Description : This file contains functions for time support * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __TIME_H_ +#define __TIME_H_ + +/*****************************************************************************/ +#include "types.h" +/*****************************************************************************/ + +#ifdef DATE_TIME_SUPPORT + #define time_getYear(void) efsl_getYear() + #define time_getMonth(void) efsl_getMonth() + #define time_getDay(void) efsl_getDay() + #define time_getHour(void) efsl_getHour() + #define time_getMinute(void) efsl_getMinute() + #define time_getSecond(void) efsl_getSecond() + #define time_getDate(void) fs_makeDate() + #define time_getTime(void) fs_makeTime() +#else + #define time_getYear(void) 0x0; + #define time_getMonth(void) 0x0; + #define time_getDay(void) 0x0; + #define time_getHour(void) 0x0; + #define time_getMinute(void) 0x0; + #define time_getSecond(void) 0x0; + #define time_getDate(void) 0x0; + #define time_getTime(void) 0x0; +#endif + +#ifdef DATE_TIME_SUPPORT +euint16 efsl_getYear(void); +euint8 efsl_getMonth(void); +euint8 efsl_getDay(void); +euint8 efsl_getHour(void); +euint8 efsl_getMinute(void); +euint8 efsl_getSecond(void); +euint16 fs_makeDate(void); +euint16 fs_makeTime(void); +#endif + +euint8 fs_hasTimeSupport(void); + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ui.h b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ui.h new file mode 100644 index 0000000000..bf4d64358d --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ui.h @@ -0,0 +1,50 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ui.h * +* Release : 0.3 - devel * +* Description : This file contains functions which will be presented to the * +* user of this library. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __UI_H__ +#define __UI_H__ + +/*****************************************************************************/ +#include "fs.h" +#include "types.h" +#include "fat.h" +#include "dir.h" +#include "config.h" +/*****************************************************************************/ + +esint8 mk_dir(FileSystem *fs,eint8* dirname); +esint16 un_link(FileSystem *fs,euint8* filename); + + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/ls.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/ls.c new file mode 100644 index 0000000000..c203a0cd4c --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/ls.c @@ -0,0 +1,150 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ls.c * +* Release : 0.3 - devel * +* Description : This file contains functions to list the files in a directory * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include <dfs_fs.h> + +#include "ls.h" +/*****************************************************************************/ + +esint8 ls_openDir(DirList *dlist,FileSystem *fs,eint8* dirname) +{ + FileLocation loc; + euint32 fc; + esint8 result; + + dlist->fs=fs; + + result = fs_findFile(dlist->fs,dirname,&loc,&fc); + + if(result == 2) + { + fs_initClusterChain(dlist->fs,&(dlist->Cache),fc); + memClr(&(dlist->currentEntry),sizeof(dlist->currentEntry)); + dlist->rEntry=0; + dlist->cEntry=0xFFFF; + + return(0); + } + else if(result == 1) + dfs_log(DFS_DEBUG_INFO, ("%s is not a directory", dirname)); + else + dfs_log(DFS_DEBUG_INFO, ("can't find %s", dirname)); + + return (-1); +} +/*****************************************************************************/ + +esint8 ls_getDirEntry(DirList *dlist) +{ + if(dlist->Cache.FirstCluster == 1){ + return(ls_getRootAreaEntry(dlist)); + }else if(dlist->Cache.FirstCluster){ + return(ls_getRealDirEntry(dlist)); + } + return(-1); +} +/*****************************************************************************/ + +esint8 ls_getNext(DirList *dlist) +{ + do{ + if(ls_getDirEntry(dlist))return(-1); + dlist->rEntry++; + }while(!ls_isValidFileEntry(&(dlist->currentEntry))); + dlist->cEntry++; + return(0); +} +/*****************************************************************************/ + +esint8 ls_getRealDirEntry(DirList *dlist) +{ + euint8* buf; + + if(dlist->Cache.FirstCluster<=1)return(-1); + + if(fat_LogicToDiscCluster(dlist->fs, + &(dlist->Cache), + (dlist->rEntry)/(16 * dlist->fs->volumeId.SectorsPerCluster))){ + return(-1); + } + + buf = part_getSect(dlist->fs->part, + fs_clusterToSector(dlist->fs,dlist->Cache.DiscCluster) + (dlist->rEntry/16)%dlist->fs->volumeId.SectorsPerCluster, + IOM_MODE_READONLY); + + /*memCpy(buf+(dlist->rEntry%16)*32,&(dlist->currentEntry),32);*/ + ls_fileEntryToDirListEntry(dlist,buf,32*(dlist->rEntry%16)); + + part_relSect(dlist->fs->part,buf); + + return(0); +} +/*****************************************************************************/ + +esint8 ls_getRootAreaEntry(DirList *dlist) +{ + euint8 *buf=0; + + if((dlist->fs->type != FAT12) && (dlist->fs->type != FAT16))return(-1); + if(dlist->rEntry>=dlist->fs->volumeId.RootEntryCount)return(-1); + + buf = part_getSect(dlist->fs->part, + dlist->fs->FirstSectorRootDir+dlist->rEntry/16, + IOM_MODE_READONLY); + /*memCpy(buf+32*(dlist->rEntry%16),&(dlist->currentEntry),32);*/ + ls_fileEntryToDirListEntry(dlist,buf,32*(dlist->rEntry%16)); + part_relSect(dlist->fs->part,buf); + return(0); +} +/*****************************************************************************/ + +esint8 ls_isValidFileEntry(ListDirEntry *entry) +{ + if(entry->FileName[0] == 0 || entry->FileName[0] == 0xE5 || entry->FileName[0] == '.')return(0); + if((entry->Attribute&0x0F)==0x0F)return(0); + return(1); +} +/*****************************************************************************/ + +void ls_fileEntryToDirListEntry(DirList *dlist, euint8* buf, euint16 offset) +{ + if(offset>480 || offset%32)return; + + buf+=offset; + memCpy(buf+OFFSET_DE_FILENAME,dlist->currentEntry.FileName,LIST_MAXLENFILENAME); + dlist->currentEntry.Attribute = *(buf+OFFSET_DE_ATTRIBUTE); + dlist->currentEntry.FileSize = ex_getb32(buf+OFFSET_DE_FILESIZE); +} +/*****************************************************************************/ + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/mkfs.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/mkfs.c new file mode 100644 index 0000000000..e19e2468ea --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/mkfs.c @@ -0,0 +1,166 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : mkfs.c * +* Release : 0.3 - devel * +* Description : These functions are used for creating an empty filesystem. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "mkfs.h" +/*****************************************************************************/ + +esint16 mkfs_makevfat(Partition *part) +{ + unsigned long c,cc,ret; + unsigned long ns,fs,ds,dc; + unsigned char buf[512]; + + ns=part->disc->partitions[part->activePartition].numSectors; + + if( ns < 66581 ){ + DBG((TXT("This is not possible due to insufficient sectors. Sorry\n"))); + return(MKFS_ERR_TOOLITTLESECTORS); + } + + ret=0; + + for(c=1<<6;c>=1;c>>=1){ + + /* First guess */ + ds = ns - 32; + fs = ((ds/c)+127)/128; + /* ds was guess too large, so fs is too large now too. */ + + for(cc=0;cc<2;cc++){ + + /* Round 2, error round */ + ds = ns - 32 - 2*fs; + fs = ((ds/c)+127)/128; + /* Since fs was too large, ds became too small. So the fs for this small ds is too small as well. */ + + /* Round 3, correction round */ + ds = ns - 32 - 2*fs; + fs = ((ds/c)+127)/128; + /* The fs was too small, so ds was too large. The calculated fs should be slightly too large. */ + + } + + /* Round 4, finalise */ + ds = ns - 32 - 2*fs; + + dc = ds / c; + if(ret<(fs*128-dc)/128)ret=(fs*128-dc)/128; + + /* Check if with current setting we have a valid fat ? */ + + if(dc >= 65525 + 16){ + break; + } + } + + /* Generate BPB */ + memClr(buf,512); + + /* Boot code */ + *(buf+0)=0xE9; *(buf+1)=0x00; *(buf+2)=0x00; /* RESET */ + + /* OEM name */ + memCpy("DSCOSMSH",buf+3,8); + + /* Bytes/Sector */ + /* *((unsigned short*)(buf+11)) = 512; */ + ex_setb16(buf+11,512); + + /* Sectors/Cluster */ + *(buf+13) = c; + + /* Reserved Sectors */ + /* *((unsigned short*)(buf+14)) = 32; */ + ex_setb16(buf+14,32); + + /* Number of FAT Tables */ + *(buf+16) = 2; + + /* RootEntryCount */ + /* *((unsigned short*)(buf+17)) = 0; */ + ex_setb16(buf+17,0); + + /* Total Sector Count __16 */ + /* *((unsigned short*)(buf+19)) = 0; */ + ex_setb16(buf+19,0); + + /* Media (crap) */ + *(buf+21) = 0xF8; + + /* FAT size 16 */ + /* *((unsigned short*)(buf+22)) = 0; */ + ex_setb16(buf+22,0); + + /* Total Sector Count __32 */ + /* *((unsigned long*)(buf+32)) = ns; */ + ex_setb32(buf+32,ns); + + /* Fat Size 32 */ + /* *((unsigned long*)(buf+36)) = fs; */ + ex_setb32(buf+36,fs); + + /* First Cluster Root Dir */ + /* *((unsigned long*)(buf+44)) = 2; */ + ex_setb32(buf+44,2); + + /* VolumeID */ + /* *((unsigned long*)(buf+67)) = 0x13371337; */ + ex_setb32(buf+67,0); + + /* Volume Label */ + memCpy("EFSL-0.3.3 ",buf+71,11);
+ + /* Filesystemtype */ + memCpy("FAT32 ",buf+82,8); + + /* Magic */ + *(buf+510) = 0x55; *(buf+511) = 0xAA; + + part_writeBuf(part,0,buf); + + memClr(buf,512); + for(c=32;c<(32+2*fs);c++){ + part_writeBuf(part,c,buf); + } + /* *(((unsigned long*)buf) )=0x0FFFFFF8; + *(((unsigned long*)buf)+1)=0x0FFFFFFF; + *(((unsigned long*)buf)+2)=0x0FFFFFF8; */ + ex_setb32(buf+0,(euint32)0x0FFFFFF8); + ex_setb32(buf+4,(euint32)0x0FFFFFFF); + ex_setb32(buf+8,(euint32)0x0FFFFFF8); + part_writeBuf(part,32,buf); + part_writeBuf(part,32+fs,buf); + + return(0); +}
\ No newline at end of file diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/time.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/time.c new file mode 100644 index 0000000000..f5ab55f865 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/time.c @@ -0,0 +1,89 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : time.c * +* Release : 0.3 - devel * +* Description : This file contains functions for time support * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "tm.h" +/*****************************************************************************/ + +euint16 fs_makeDate(void) +{ +#ifndef DATE_TIME_SUPPORT + return(0); +#else + euint8 m,d; + euint16 y; + + y = time_getYear()-1980; + m = time_getMonth(); + d = time_getDay(); + + return( + (y>127?127<<9:(y&0x3F)<<9) | + ((m==0||m>12)?1:(m&0xF)<<5) | + ((d==0||d>31)?1:(d&0x1F)) + ); +#endif +} +/*****************************************************************************/ + +euint16 fs_makeTime(void) +{ +#ifndef DATE_TIME_SUPPORT + return(0); +#else + euint8 s,m,h; + + s = time_getSecond(); + m = time_getMinute(); + h = time_getHour(); + + return( + (h>23?0:(h&0x1F)<<11) | + (m>59?0:(m&0x3F)<<5) | + (s>59?0:(s-s%2)/2) + ); +#endif +} +/*****************************************************************************/ + +euint8 fs_hasTimeSupport(void) +{ +#ifdef DATE_TIME_SUPPORT + return(1); +#else + return(0); +#endif +} +/*****************************************************************************/ + + diff --git a/filesystem/dfs/filesystems/efsl/src/fs/vfat/ui.c b/filesystem/dfs/filesystems/efsl/src/fs/vfat/ui.c new file mode 100644 index 0000000000..b37e0397e2 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/fs/vfat/ui.c @@ -0,0 +1,200 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ui.c * +* Release : 0.3 - devel * +* Description : This file contains functions which will be presented to the * +* user of this library. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +/*****************************************************************************/ +#include "ui.h" +#include "ls.h" +#include "efs.h"
+/*****************************************************************************/ + +/* **************************************************************************** +* unlink dir or [email protected],2008-08-19 +*/ +esint16 un_link(FileSystem *fs,euint8* filename) +{ + FileLocation loc; + ClusterChain cache; + DirList *dlist; + euint8* buf; + euint8 attr; + euint32 firstCluster=0; + euint32 fc; + + if ( filename[0] == '/' && filename[1] == '\0') + { + /* it's the root directory */ + dfs_log(DFS_DEBUG_INFO, ("Can't delete root directory")); + return -DFS_STATUS_EISDIR; + } + + if((fs_findFile(fs,(eint8*)filename,&loc,&fc)) > 0) + { + buf = part_getSect(fs->part,loc.Sector,IOM_MODE_READWRITE); + firstCluster = ex_getb16(buf+loc.Offset*32+20); + firstCluster <<= 16; + firstCluster += ex_getb16(buf+loc.Offset*32+26); + attr = ex_getb16(buf+loc.Offset*32+11); + if(attr == ATTR_DIRECTORY) + { + dlist = (DirList *)rt_malloc(sizeof(DirList)); + if(dlist == RT_NULL) + { + part_relSect(fs->part,buf); + + dfs_log(DFS_DEBUG_INFO, ("Memory alloc failed")); + return -DFS_STATUS_ENOMEM; + } + + if(firstCluster != 0) + { + dlist->fs = fs; + fs_initClusterChain(fs,&(dlist->Cache),fc); + memClr(&(dlist->currentEntry),sizeof(dlist->currentEntry)); + dlist->rEntry = 0; + dlist->cEntry = 0xFFFF; + + while(1) + { + /* it's the end of file */ + if(ls_getNext(dlist) == 0) + { + /* '.' and '..' */ + if(dlist->currentEntry.FileName[0] == '.') continue; + + part_relSect(fs->part,buf); + + dfs_log(DFS_DEBUG_INFO, ("Directory not empty")); + return -DFS_STATUS_ENOTEMPTY; + } + else break; + } + } + } + + memClr(buf+(loc.Offset*32),32); + part_relSect(fs->part,buf); + cache.DiscCluster = cache.LastCluster = cache.Linear = cache.LogicCluster = 0; + cache.FirstCluster = firstCluster; + fat_unlinkClusterChain(fs,&cache); + + return 0; + } + return -DFS_STATUS_ENOENT; +} + +/*****************************************************************************/ +esint8 mk_dir(FileSystem *fs,eint8* dirname) +{ + FileLocation loc; + FileRecord direntry; + euint32 nc,parentdir; + euint8* buf; + eint8 ffname[11]; + + if( fs_findFile(fs,dirname,&loc,&parentdir) ) + { + dfs_log(DFS_DEBUG_INFO, ("directory %s has existed", dirname)); + return(-1); + } + if(parentdir==0) + { + dfs_log(DFS_DEBUG_INFO, ("parent directory doesn't existe")); + return(-2); + } + + if(!fs_findFreeFile(fs,dirname,&loc,0)) + { + dfs_log(DFS_DEBUG_INFO, ("can't find free entry")); + return(-3); + } + + /* You may never search for a free cluster, and the call + * functions that may cause changes to the FAT table, that + * is why getNextFreeCluster has to be called AFTER calling + * fs_findFreeFile, which may have to expand a directory in + * order to store the new filerecord !! + */ + + nc = fs_getNextFreeCluster(fs,fs_giveFreeClusterHint(fs)); + if(nc==0) + { + dfs_log(DFS_DEBUG_INFO, ("no free cluster")); + return(0); + } + + fs_clearCluster(fs,nc); + + buf = part_getSect(fs->part,loc.Sector,IOM_MODE_READWRITE); + + dir_getFatFileName(dirname,ffname); + memClr(&direntry,sizeof(direntry)); + memCpy(ffname,&direntry,11); + direntry.FileSize = 0; + direntry.FirstClusterHigh=nc>>16; + direntry.FirstClusterLow=nc&0xFFFF; + direntry.Attribute = ATTR_DIRECTORY; + memCpy(&direntry,buf+(32*loc.Offset),32); + + part_relSect(fs->part,buf); + + buf = part_getSect(fs->part,fs_clusterToSector(fs,nc),IOM_MODE_READWRITE); + + memClr(&direntry,sizeof(direntry)); + memCpy(". ",&direntry,11); + direntry.Attribute = ATTR_DIRECTORY; + direntry.FileSize = 0; + direntry.FirstClusterHigh=nc>>16; + direntry.FirstClusterLow=nc&0xFFFF; + memCpy(&direntry,buf,32); + + if(fs->type == FAT32 && parentdir == fs->volumeId.RootCluster) + parentdir = 0; + + if(fs->type != FAT32 && parentdir<=1) + parentdir = 0; + + memClr(&direntry,sizeof(direntry)); + memCpy(".. ",&direntry,11); + direntry.Attribute = ATTR_DIRECTORY; + direntry.FileSize = 0; + direntry.FirstClusterHigh=parentdir>>16; + direntry.FirstClusterLow=parentdir&0xFFFF; + memCpy(&direntry,buf+32,32); + + part_relSect(fs->part,buf); + + fat_setNextClusterAddress(fs,nc,fat_giveEocMarker(fs)); + + return(0); +} diff --git a/filesystem/dfs/filesystems/efsl/src/include/config.h b/filesystem/dfs/filesystems/efsl/src/include/config.h new file mode 100644 index 0000000000..f4e296b18a --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/include/config.h @@ -0,0 +1,151 @@ +#ifndef __EFSL_CONFIG_H__
+#define __EFSL_CONFIG_H__
+
+/* Hardware target
+ ---------------
+
+ * Here you will define for what hardware-endpoint EFSL should be compiled.
+ * Look in interfaces.h to see what systems are supported, and add your own
+ * there if you need to write your own driver. Then, define the name you
+ * selected for your hardware there here. Make sure that you only select one
+ * device!
+*/
+
+ /*#define HW_ENDPOINT_LINUX*/
+ /*#define HW_ENDPOINT_ATMEGA128_SD*/
+ /*#define HW_ENDPOINT_DSP_TI6713_SD*/
+
+#define MULTIPLE_INTERFACE_SUPPORT
+/*#define HWIFUNC_INIT(x) lf_init(x)
+#define HWIFUNC_READ(x,y,z) lf_readBuf(x,y,z)
+#define HWIFUNC_WRITE(x,y,z) lf_writeBuf(x,y,z)
+#define HWIFUNC_HEADER interfaces/linuxfile.h */
+
+/* Architecture
+ ------------
+
+ * In this section you should configure how large the default variable
+ * types in your system are. This is controlled in types.h in the general
+ * include directory. The selection you make here defines to what the various
+ * e(s|u)int(8,16,32) types will map.
+ * For 32 bit Linux : VARSIZE_LINUX32
+ * For 64 bit Linux : VARSIZE_LINUX64
+ * For AVR's : VARSIZE_ATMEGA
+ * For TMS67XX : VARSIZE_TMS67XX
+ */
+
+#define VARSIZE_LINUX32
+
+/* Memory configuration
+ --------------------
+
+ * Here you must configure wheter your processor can access memory byte
+ * oriented. All x86 processors can do it, AVR's can do it to. Some DSP
+ * or other microcontrollers can't. If you have an 8 bit system you're safe.
+ * If you are really unsure, leave the setting commented out, it will be slower
+ * but it will work for sure.
+*/
+
+#define BYTE_ALIGNMENT
+
+/* Cache configuration
+ -------------------
+
+ * Here you must configure how much memory of cache you can/want to use.
+ * The number you put at IOMAN_NUMBUFFER is multiplied by 512. So 1 means
+ * 512 bytes cache, 4 means 2048 bytes cache. More is better.
+ * The number after IOMAN_NUMITERATIONS should be untouched.
+ * The last field (IOMAN_DO_MEMALLOC) is to tell ioman to allocate it's
+ * own memory in it's structure, or not. If you choose to do it yourself
+ * you will have to pass a pointer to the memory as the last argument of
+ * ioman_init.
+*/
+ #define IOMAN_NUMBUFFER 10
+ #define IOMAN_NUMITERATIONS 3
+ #define IOMAN_DO_MEMALLOC
+
+/* Cluster pre-allocation
+ ----------------------
+
+ * When writing files, the function that performs the actual write has to
+ * calculate how many clusters it will need for that request. It then allocates
+ * that number of new clusters to the file. Since this involves some
+ * calculations and writing of the FAT, you might find it beneficial to limit
+ * the number of allocations, and allow fwrite to pre-allocate a number of
+ * clusters extra. This setting determines how many clusters will be extra
+ * allocated whenever this is required.
+ * Take in carefull consideration how large your clustersize is, putting 10 here
+ * with a clustersize of 32kb means you might waste 320 kb.
+ * The first option is for preallocating files, the other is used when enlarging
+ * a directory to accomodate more files
+*/
+ #define CLUSTER_PREALLOC_FILE 5
+ #define CLUSTER_PREALLOC_DIRECTORY 2
+
+/* Endianess configuration
+ -----------------------
+
+ * Here you can configure wheter your architecture is little or big endian. This
+ * is important since all FAT structures are stored in intel little endian
+ * order. So if you have a big endian system the library has to convert all
+ * figures to big endian in order to work.
+ */
+ /*#define HOST_BIG_ENDIAN*/
+ #define HOST_LITTLE_ENDIAN
+
+/* Date and Time support
+ ---------------------
+
+ * Here you can enable or disable date and time support. If you enable
+ * it you will have to create 6 functions, that are described in the
+ * EFSL manual. If the functions are not present when linking your
+ * program with the library you will get unresolved dependencies.
+ */
+ /* #define DATE_TIME_SUPPORT */
+
+/* Error reporting support
+ -----------------------
+
+ * When you receive an error in userland, it usually only gives limited
+ * information (most likely, fail or success). If error detection and
+ * reporting is important for you, you can enable more detailed error
+ * reporting here. This is optional, the costs are 1 byte per object,
+ * and a small increase in code size.
+ * You can enable error recording for all object, or you can select the
+ * object manually.
+ * For full error reporting use FULL_ERROR_SUPPORT
+ * For only the base-core of the library use BASE_ERROR_SUPPORT
+ * For IO/Man use ERRSUP_IOMAN
+ * For Disc use ERRSUP_IOMAN
+ * For Part use ERRSUP_PARTITION
+ * For Fs use ERRSUP_FILESYSTEM
+ * For File use ERRSUP_FILE
+*/
+
+ #define FULL_ERROR_SUPPORT
+ /*#define BASE_ERROR_SUPPORT*/
+
+
+/* Debugging configuration
+ -----------------------
+
+ * Here you can configure the debugging behaviour. Debugging is different
+ * on every platform (see debug.h for more information).
+ * If your hardware has no means of output (printf) dont define any anything,
+ * and nothing will happen. For real world use debugging should be turned off.
+*/
+
+ /*#define DEBUG*/
+ /*#define DO_FUNC_DEBUG*/
+
+/* List options
+ ------------
+
+ * In this section you can configure what kind of data you will get from
+ * directory listing requests. Please refer to the documentation for
+ * more information
+*/
+
+ #define LIST_MAXLENFILENAME 12
+
+#endif
diff --git a/filesystem/dfs/filesystems/efsl/src/include/error.h b/filesystem/dfs/filesystems/efsl/src/include/error.h new file mode 100644 index 0000000000..7dec992a29 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/include/error.h @@ -0,0 +1,124 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : error.h * +* Release : 0.3 - devel * +* Description : Header file containing error-defines. * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __ERROR_H_ +#define __ERROR_H_ + +/*****************************************************************************/ +#include "config.h" +/*****************************************************************************/ + +#if defined (FULL_ERROR_SUPPORT) + #define ERRSUP_IOMAN + #define ERRSUP_DISC + #define ERRSUP_PARTITION + #define ERRSUP_FAT_FILESYSTEM + #define ERRSUP_FAT_FILESYSTEM +#elif defined (BASE_ERROR_SUPPORT) + #define ERRSUP_IOMAN + #define ERRSUP_DISC + #define ERRSUP_PARTITION +#endif + +#if defined (HWINT_HAS_ERROR_SUPPORT) && defined (INTERFACE_ERROR_SUPPORT) + #define ERRSUP_HWINTERFACE +#endif + +#ifdef ERRSUP_IOMAN + #define IOMAN_ERR_EUINT8 euint8 error; + #define ioman_setError(ioman,errval) ioman->error = errval + #define ioman_getError(ioman) ioman->error +#else + #define IOMAN_ERR_EUINT8 + #define ioman_setError(ioman,errval) + #define ioman_getError(ioman) 0 +#endif + +#ifdef ERRSUP_DISC + #define DISC_ERR_EUINT8 euint8 error; + #define disc_setError(disc,errval) disc->error = errval + #define disc_getError(disc) disc->error +#else + #define DISC_ERR_EUINT8 + #define disc_setError(disc,errval) + #define disc_getError(disc) 0 +#endif + +#ifdef ERRSUP_PART + #define PART_ERR_EUINT8 euint8 error; + #define part_setError(part,errval) part->error = errval + #define part_getError(part) part->error +#else + #define PART_ERR_EUINT8 + #define part_setError(part,errval) + #define part_getError(part) 0 +#endif + +#ifdef ERRSUP_FAT_FILESYSTEM + #define FILESYSTEM_ERR_EUINT8 euint8 error; + #define fs_setError(fs,errval) fs->error = errval + #define fs_getError(fs) fs->error +#else + #define FILESYSTEM_ERR_EUINT8 + #define fs_setError(fs,errval) + #define fs_getError(fs) 0 +#endif + +#ifdef ERRSUP_FILE + #define FILE_ERR_EUINT8 euint8 error; + #define file_setError(file,errval) file->error = errval + #define file_getError(file) file->error +#else + #define FILE_ERR_EUINT8 + #define file_setError(file,errval) + #define file_getError(file) 0 +#endif + +#define IOMAN_NOERROR 0 +#define IOMAN_ERR_SETATTROUTOFBOUNDS 1 +#define IOMAN_ERR_GETATTROUTOFBOUNDS 2 +#define IOMAN_ERR_READFAIL 3 +#define IOMAN_ERR_WRITEFAIL 4 +#define IOMAN_ERR_OPOUTOFBOUNDS 5 +#define IOMAN_ERR_PUSHBEYONDSTACK 6 +#define IOMAN_ERR_POPEMPTYSTACK 7 +#define IOMAN_ERR_CACHEPTROUTOFRANGE 8 +#define IOMAN_ERR_WRITEREADONLYSECTOR 9 +#define IOMAN_ERR_NOMEMORY 10 + +#define DISC_NOERROR 0 + +#define PART_NOERROR 0 + + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/include/ioctl.h b/filesystem/dfs/filesystems/efsl/src/include/ioctl.h new file mode 100644 index 0000000000..93a0b947a7 --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/include/ioctl.h @@ -0,0 +1,44 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : ioctl.h * +* Release : 0.3 - devel * +* Description : This file contains the ioctl command numbers * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __EFS_IOCTL_H__ +#define __EFS_IOCTL_H__ + +/*****************************************************************************/ +#include "config.h" +/*****************************************************************************/ + +#define IOCTL_NOP 0 +#define IOCTL_SECTORCOUNT 1 + +#endif diff --git a/filesystem/dfs/filesystems/efsl/src/include/types.h b/filesystem/dfs/filesystems/efsl/src/include/types.h new file mode 100644 index 0000000000..6e05e6239f --- /dev/null +++ b/filesystem/dfs/filesystems/efsl/src/include/types.h @@ -0,0 +1,110 @@ +/*****************************************************************************\ +* EFSL - Embedded Filesystems Library * +* ----------------------------------- * +* * +* Filename : types.h * +* Release : 0.3 - devel * +* Description : This file contains the crossplatform data types * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; version 2 * +* of the License. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* As a special exception, if other files instantiate templates or * +* use macros or inline functions from this file, or you compile this * +* file and link it with other works to produce a work based on this file, * +* this file does not by itself cause the resulting work to be covered * +* by the GNU General Public License. However the source code for this * +* file must still be made available in accordance with section (3) of * +* the GNU General Public License. * +* * +* This exception does not invalidate any other reasons why a work based * +* on this file might be covered by the GNU General Public License. * +* * +* (c)2006 Lennart Yseboodt * +* (c)2006 Michael De Nil * +\*****************************************************************************/ + +#ifndef __EFS_TYPES_H__ +#define __EFS_TYPES_H__ + +/*****************************************************************************/ +#include "config.h" +/*****************************************************************************/ + +/* VARIABLE SIZES + ============== + + * eint8 -> 1 byte + * eint16 -> 2 bytes + * eint32 -> 4 bytes + * + * VARSIZE_LINUX32 is suitable for 32bit Linux + * VARSIZE_LINUX64 is suitable for 64bit Linux + * VARSIZE_ATMEGA is suitable for AVR's + * VARSIZE_TMS67XX is suitable for the TI TMS67XX + * + * If nothing is selected a default is used, that should work on + * 32 bit systems + */ + +#if defined(VARSIZE_LINUX32) + typedef char eint8; + typedef signed char esint8; + typedef unsigned char euint8; + typedef short eint16; + typedef signed short esint16; + typedef unsigned short euint16; + typedef long eint32; + typedef signed long esint32; + typedef unsigned long euint32; +#elif defined(VARSIZE_LINUX64) + typedef char eint8; + typedef signed char esint8; + typedef unsigned char euint8; + typedef short eint16; + typedef signed short esint16; + typedef unsigned short euint16; + typedef int eint32; + typedef signed int esint32; + typedef unsigned int euint32; +#elif defined (VARSIZE_ATMEGA) + typedef char eint8; + typedef signed char esint8; + typedef unsigned char euint8; + typedef short eint16; + typedef signed short esint16; + typedef unsigned short euint16; + typedef long eint32; + typedef signed long esint32; + typedef unsigned long euint32; +#elif defined(VARSIZE_TMS67XX) + typedef char eint8; + typedef signed char esint8; + typedef unsigned char euint8; + typedef short eint16; + typedef signed short esint16; + typedef unsigned short euint16; + typedef int eint32; + typedef signed int esint32; + typedef unsigned int euint32; +#else +#warning "No VARSIZE selection has been made, beware!" + typedef char eint8; + typedef signed char esint8; + typedef unsigned char euint8; + typedef short eint16; + typedef signed short esint16; + typedef unsigned short euint16; + typedef long eint32; + typedef signed long esint32; + typedef unsigned long euint32; +#endif + +#endif diff --git a/filesystem/dfs/include/dfs_cache.h b/filesystem/dfs/include/dfs_cache.h new file mode 100644 index 0000000000..4321664e23 --- /dev/null +++ b/filesystem/dfs/include/dfs_cache.h @@ -0,0 +1,41 @@ +#ifndef __DFS_CACHE_H__
+#define __DFS_CACHE_H__
+
+#include <rtthread.h>
+
+#define IOMAN_STATUS_ATTR_VALIDDATA 0
+#define IOMAN_STATUS_ATTR_USERBUFFER 1
+#define IOMAN_STATUS_ATTR_WRITE 2
+
+#define IOM_MODE_READONLY 1
+#define IOM_MODE_READWRITE 2
+#define IOM_MODE_EXP_REQ 4
+
+#define DFS_SECTOR_SIZE 512
+
+struct _IOManager
+{
+ rt_device_t device;
+ rt_uint8_t numbuf;
+
+ rt_uint32_t sector[DFS_CACHE_MAX_NUM];
+ rt_uint8_t status[DFS_CACHE_MAX_NUM];
+ rt_uint8_t usage [DFS_CACHE_MAX_NUM];
+
+ /* cache FIFO */
+ rt_uint8_t ring_fifo[DFS_CACHE_MAX_NUM];
+
+ /* cache buffer */
+ rt_uint8_t cache[DFS_CACHE_MAX_NUM][DFS_SECTOR_SIZE];
+};
+typedef struct _IOManager IOManager;
+
+rt_err_t ioman_init(IOManager* ioman); +rt_uint8_t* ioman_getSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t mode); +rt_err_t ioman_releaseSector(IOManager *ioman, rt_uint8_t* buf); +rt_err_t ioman_flushRange(IOManager *ioman, rt_uint32_t address_low, rt_uint32_t address_high);
+ +rt_err_t ioman_directSectorRead(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector); +rt_err_t ioman_directSectorWrite(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector); + +#endif
diff --git a/filesystem/dfs/include/dfs_def.h b/filesystem/dfs/include/dfs_def.h new file mode 100644 index 0000000000..27b05e20e0 --- /dev/null +++ b/filesystem/dfs/include/dfs_def.h @@ -0,0 +1,173 @@ +/* ++------------------------------------------------------------------------------ +| Device FileSystem ++------------------------------------------------------------------------------ +| Copyright 2004, 2005 www.fayfayspace.org. +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs_def.h, the definitions of Device FileSystem +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author notes +| 2004-10-01 ffxz The first version. +| 2004-10-14 ffxz Clean up the code. +| 2005-01-22 ffxz Clean up the code, port to MinGW ++------------------------------------------------------------------------------ +*/ + +#ifndef __DFS_DEF_H__ +#define __DFS_DEF_H__ + +#include <rtthread.h> +#include <dfs_config.h> + +#if defined(RT_USING_NEWLIB) || defined (RT_USING_MINILIBC) +#include <string.h> +#endif + +#ifndef __D_FS__ +#define __D_FS__ +#endif + +/* Device error codes */ +#define DFS_STATUS_ENOENT 2 /* No such file or directory */ +#define DFS_STATUS_EIO 5 /* I/O error */ +#define DFS_STATUS_ENXIO 6 /* No such device or address */ +#define DFS_STATUS_EBADF 9 /* Bad file number */ +#define DFS_STATUS_EAGIAN 11 /* Try again */ +#define DFS_STATUS_ENOMEM 12 /* no memory */ +#define DFS_STATUS_EBUSY 16 /* Device or resource busy */ +#define DFS_STATUS_EEXIST 17 /* File exists */ +#define DFS_STATUS_EXDEV 18 /* Cross-device link */ +#define DFS_STATUS_ENODEV 19 /* No such device */ +#define DFS_STATUS_ENOTDIR 20 /* Not a directory */ +#define DFS_STATUS_EISDIR 21 /* Is a directory */ +#define DFS_STATUS_EINVAL 22 /* Invalid argument */ +#define DFS_STATUS_ENOSPC 28 /* No space left on device */ +#define DFS_STATUS_EROFS 30 /* Read-only file system */ +#define DFS_STATUS_ENOSYS 38 /* Function not implemented */ +#define DFS_STATUS_ENOTEMPTY 39 /* Directory not empty */ +#define DFS_STATUS_EMMOUNT 128 /* Filesystem table full */ + +/* Operation flags */ +#define DFS_O_RDONLY 0000000 +#define DFS_O_WRONLY 0000001 +#define DFS_O_RDWR 0000002 +#define DFS_O_ACCMODE 0000003 +#define DFS_O_CREAT 0000100 +#define DFS_O_EXCL 0000200 +#define DFS_O_TRUNC 0001000 +#define DFS_O_APPEND 0002000 +#define DFS_O_DIRECTORY 0200000 + +/* File flags */ +#define DFS_F_OPEN 0x01000000 +#define DFS_F_DIRECTORY 0x02000000 +#define DFS_F_EOF 0x04000000 +#define DFS_F_ERR 0x08000000 + +/* Seek flags */ +#define DFS_SEEK_SET 0 +#define DFS_SEEK_CUR 1 +#define DFS_SEEK_END 2 + +/* Stat codes */ +#define DFS_S_IFMT 00170000 +#define DFS_S_IFSOCK 0140000 +#define DFS_S_IFLNK 0120000 +#define DFS_S_IFREG 0100000 +#define DFS_S_IFBLK 0060000 +#define DFS_S_IFDIR 0040000 +#define DFS_S_IFCHR 0020000 +#define DFS_S_IFIFO 0010000 +#define DFS_S_ISUID 0004000 +#define DFS_S_ISGID 0002000 +#define DFS_S_ISVTX 0001000 + +#define DFS_S_ISLNK(m) (((m) & DFS_S_IFMT) == DFS_S_IFLNK) +#define DFS_S_ISREG(m) (((m) & DFS_S_IFMT) == DFS_S_IFREG) +#define DFS_S_ISDIR(m) (((m) & DFS_S_IFMT) == DFS_S_IFDIR) +#define DFS_S_ISCHR(m) (((m) & DFS_S_IFMT) == DFS_S_IFCHR) +#define DFS_S_ISBLK(m) (((m) & DFS_S_IFMT) == DFS_S_IFBLK) +#define DFS_S_ISFIFO(m) (((m) & DFS_S_IFMT) == DFS_S_IFIFO) +#define DFS_S_ISSOCK(m) (((m) & DFS_S_IFMT) == DFS_S_IFSOCK) + +#define DFS_S_IRWXU 00700 +#define DFS_S_IRUSR 00400 +#define DFS_S_IWUSR 00200 +#define DFS_S_IXUSR 00100 + +#define DFS_S_IRWXG 00070 +#define DFS_S_IRGRP 00040 +#define DFS_S_IWGRP 00020 +#define DFS_S_IXGRP 00010 + +#define DFS_S_IRWXO 00007 +#define DFS_S_IROTH 00004 +#define DFS_S_IWOTH 00002 +#define DFS_S_IXOTH 00001 + +#define DEVICE_GETGEOME 0 +#define DEVICE_GETINFO 1 +#define DEVICE_FORMAT 2 +#define DEVICE_CLEAN_SECTOR 3 + +struct device_geometry +{ + rt_uint32_t sector_count; /* count of sectors */ + rt_uint32_t cylinder_count; /* count of cylinder */ + rt_uint32_t sectors_per_track; /* number of sectors per track */ + rt_uint32_t head_count; /* count of head */ + rt_uint32_t bytes_per_sector; /* number of bytes per sector */ +}; + +struct dfs_stat +{ + rt_device_t st_dev; + rt_uint16_t st_mode; + rt_uint32_t st_size; + rt_time_t st_mtime; + rt_uint32_t st_blksize; +}; +#define stat dfs_stat + +/* File types */ +#define FT_REGULAR 0 +#define FT_SOCKET 1 +#define FT_DIRECTORY 2 + +/* file descriptor */ +struct dfs_fd +{ + char path[DFS_PATH_MAX + 1];/* Name (below mount point) */ + int type; /* Type (regular or socket) */ + int ref_count; /* Descriptor reference count */ + + struct dfs_filesystem* fs; /* Resident file system */ + + rt_uint32_t flags; /* Descriptor flags */ + rt_size_t size; /* Size in bytes */ + rt_off_t pos; /* Current file position */ + + void *data; /* Specific file system data */ +}; + +#define DFS_DT_UNKNOWN 0x00 +#define DFS_DT_REG 0x01 +#define DFS_DT_DIR 0x02 + +struct dfs_dirent +{ + rt_uint8_t d_type; /* The type of the file */ + rt_uint8_t d_namlen; /* The length of the not including the terminating null file name */ + rt_uint16_t d_reclen; /* length of this record */ + char d_name[256]; /* The null-terminated file name */ +}; +#define dirent dfs_dirent + +struct dfs_session +{ + rt_mailbox_t mbox; +}; + +#endif diff --git a/filesystem/dfs/include/dfs_efs.h b/filesystem/dfs/include/dfs_efs.h new file mode 100644 index 0000000000..122f33a8ac --- /dev/null +++ b/filesystem/dfs/include/dfs_efs.h @@ -0,0 +1,29 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_efs.h
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2008-08-30 Yi.Qiu
++------------------------------------------------------------------------------
+*/
+
+#ifndef __DFS_EFS_H__
+#define __DFS_EFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int efsl_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/filesystem/dfs/include/dfs_fat.h b/filesystem/dfs/include/dfs_fat.h new file mode 100644 index 0000000000..65af6cebb3 --- /dev/null +++ b/filesystem/dfs/include/dfs_fat.h @@ -0,0 +1,29 @@ +/* ++------------------------------------------------------------------------------ +| Project : Device Filesystem ++------------------------------------------------------------------------------ +| Copyright 2004, 2005 www.fayfayspace.org. +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs_fat.h, FAT 12/16/32 file system definitions +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author Notes +| 2003-03-30 ffxz ++------------------------------------------------------------------------------ +*/ + +#ifndef __DFS_FAT_H__ +#define __DFS_FAT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int fatfs_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/filesystem/dfs/include/dfs_fs.h b/filesystem/dfs/include/dfs_fs.h new file mode 100644 index 0000000000..4299e0d6ba --- /dev/null +++ b/filesystem/dfs/include/dfs_fs.h @@ -0,0 +1,87 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_fs.h, the filesystem related defines of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-02-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+#ifndef __DFS_FS_H__
+#define __DFS_FS_H__
+
+#include <dfs_def.h>
+#include <dfs_config.h>
+
+/* Pre-declaration */
+struct dfs_filesystem;
+struct dfs_fd;
+struct dfs_dirent;
+
+/* File system operations struct */
+struct dfs_filesystem_operation
+{
+ char name[DFS_FS_NAME_MAX + 1];
+
+ int (*mount) (struct dfs_filesystem* fs);
+ int (*unmount) (struct dfs_filesystem* fs);
+
+ 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 (*lseek) (struct dfs_fd* fd, rt_off_t offset);
+ int (*getdents) (struct dfs_fd* fd, struct dfs_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 dfs_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[DFS_PATH_MAX + 1]; /* File system mount point */
+ struct dfs_filesystem_operation* ops; /* Operations for file system type */
+ rt_uint32_t block_id; /* Current block_id on attached device */
+
+ 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(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 struct dfs_filesystem_operation* filesystem_operation_table[];
+extern struct dfs_filesystem filesystem_table[];
+
+extern rt_sem_t filesystem_table_lock;
+extern rt_sem_t filesystem_operation_table_lock;
+
+extern char working_directory[];
+extern rt_sem_t working_directory_lock;
+
+#endif
diff --git a/filesystem/dfs/include/dfs_init.h b/filesystem/dfs/include/dfs_init.h new file mode 100644 index 0000000000..712ce61156 --- /dev/null +++ b/filesystem/dfs/include/dfs_init.h @@ -0,0 +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
diff --git a/filesystem/dfs/include/dfs_posix.h b/filesystem/dfs/include/dfs_posix.h new file mode 100644 index 0000000000..a6ddfe1474 --- /dev/null +++ b/filesystem/dfs/include/dfs_posix.h @@ -0,0 +1,100 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_posix.h, the filesystem related defines of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2009-05-27 Yi.qiu The first version.
++------------------------------------------------------------------------------
+*/
+#ifndef __DFS_POSIX_H__
+#define __DFS_POSIX_H__
+
+#include <dfs_raw.h>
+
+#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
+
+#define SEEK_SET DFS_SEEK_SET
+#define SEEK_CUR DFS_SEEK_CUR
+#define SEEK_END DFS_SEEK_END
+
+typedef struct
+{
+ int fd; /* directory file */
+ char buf[512];
+ int num;
+ int cur;
+ rt_sem_t *sem;
+} DIR;
+
+/* file api*/
+int open(const char *file, int flags, int mode);
+int close(int d);
+int read(int fd, char *buf, int len);
+int write(int fd, char *buf, int len);
+int lseek(int fd, int offset, int dir);
+int rename(const char* old, const char* new );
+int unlink(const char *pathname);
+int stat(const char *file, struct dfs_stat *buf);
+
+/* directory api*/
+int mkdir (const char *path, rt_uint16_t mode);
+int rmdir(const char *path);
+DIR* opendir(const char* name);
+struct dfs_dirent* readdir(DIR *d);
+rt_off_t telldir(DIR *d);
+void seekdir(DIR *d, rt_off_t offset);
+void rewinddir(DIR *d);
+int closedir(DIR* d);
+int chdir(const char *path);
+char* getcwd(char *buf, rt_size_t size);
+
+#endif
diff --git a/filesystem/dfs/include/dfs_raw.h b/filesystem/dfs/include/dfs_raw.h new file mode 100644 index 0000000000..dd6bfb0cad --- /dev/null +++ b/filesystem/dfs/include/dfs_raw.h @@ -0,0 +1,38 @@ +/*
++------------------------------------------------------------------------------
+| 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_fs.h>
+
+int dfile_raw_open(struct dfs_fd* fd, const char *path, int flags);
+int dfile_raw_close(struct dfs_fd* fd);
+int dfile_raw_ioctl(struct dfs_fd* fd, int cmd, void *args);
+int dfile_raw_read(struct dfs_fd* fd, void *buf, rt_size_t len);
+int dfile_raw_getdents(struct dfs_fd* fd, struct dfs_dirent* dirp, rt_size_t nbytes);
+int dfile_raw_unlink(const char *path);
+int dfile_raw_write(struct dfs_fd* fd, const void *buf, rt_size_t len);
+int dfile_raw_lseek(struct dfs_fd* fd, rt_off_t offset);
+int dfile_raw_stat(const char *path, struct dfs_stat *buf);
+int dfile_raw_rename(const char* oldpath, const char* newpath);
+
+/* FD APIs */
+int fd_new(void);
+struct dfs_fd* fd_get(int fd);
+void fd_put(struct dfs_fd* fd);
+
+#endif
diff --git a/filesystem/dfs/include/dfs_util.h b/filesystem/dfs/include/dfs_util.h new file mode 100644 index 0000000000..948abe09cc --- /dev/null +++ b/filesystem/dfs/include/dfs_util.h @@ -0,0 +1,35 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_util.h, some misc definitions of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-01-26 ffxz The first version
++------------------------------------------------------------------------------
+*/
+
+#ifndef __DFS_UTIL_H__
+#define __DFS_UTIL_H__
+
+#include <dfs_def.h>
+
+int dir_name(const char* path, char* dirname, int len);
+int file_name(const char* path, char* filename, int len);
+
+int next_dir_name(const char* path, int pos, char* next);
+void build_fullpath(const char *directory, const char *filename, char *fullpath);
+int str_is_prefix(const char* prefix, const char* str);
+
+#if !defined(RT_USING_MINILIBC) && !defined(RT_USING_NEWLIB)
+char *strrchr(const char *t, int c);
+#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION / 10000 < 35)
+int strncasecmp(const char* s1, const char* s2, rt_size_t len);
+#endif /* end of __ARMCC_VERSION */
+#endif
+
+#endif
diff --git a/filesystem/dfs/src/dfs_cache.c b/filesystem/dfs/src/dfs_cache.c new file mode 100644 index 0000000000..cd4deab415 --- /dev/null +++ b/filesystem/dfs/src/dfs_cache.c @@ -0,0 +1,273 @@ +/* ++------------------------------------------------------------------------------ +| Project : Device Filesystem ++------------------------------------------------------------------------------ +| Copyright 2004 - 2009 www.rt-thread.org +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs_cache.c, the LUT disk cache implementation +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author Notes +| 2009-04-26 bernard The first version. ++------------------------------------------------------------------------------ +*/ +#include "dfs_cache.h" + +#define ioman_isReqRo(mode) ((mode)&(IOM_MODE_READONLY)) +#define ioman_isReqRw(mode) ((mode)&(IOM_MODE_READWRITE)) +#define ioman_isReqExp(mode) ((mode)&(IOM_MODE_EXP_REQ)) + +rt_err_t ioman_init(IOManager* ioman) +{ + register rt_uint32_t index; + RT_ASSERT(ioman != RT_NULL); + + ioman->numbuf = DFS_CACHE_MAX_NUM;
+
+ rt_memset(ioman->sector, 0,sizeof(ioman->sector));
+ rt_memset(ioman->status, 0,sizeof(ioman->status));
+ rt_memset(ioman->usage, 0, sizeof(ioman->usage));
+ rt_memset(ioman->ring_fifo, 0, sizeof(ioman->ring_fifo));
+ rt_memset(ioman->cache, 0, sizeof(ioman->cache));
+ + /* init fifo */ + for (index = 0; index < ioman->numbuf; index ++) + { + ioman->ring_fifo[index] = ioman->numbuf - index - 1; + } + + return RT_EOK; +} + +/* + * get the last fifo item and put it to the top of fifo ring + */ +static rt_uint8_t ioman_ring_fifo_swap(IOManager *ioman) +{ + rt_uint8_t bp; + rt_uint32_t index; + + bp = ioman->ring_fifo[ioman->numbuf - 1]; + for (index = ioman->numbuf - 1; index > 0; index --) + { + ioman->ring_fifo[index] = ioman->ring_fifo[index - 1]; + } + + ioman->ring_fifo[0] = bp; + + return bp; +} + +/* + * get the index of bp in fifo ring and then put it to the top of + * fifo ring + */ +static void ioman_ring_fifo_relocate(IOManager *ioman, rt_uint32_t bp) +{ + rt_uint32_t bp_index = 0; + register rt_uint32_t index; + + /* find bp in fifo ring */ + for (index = 0; index < ioman->numbuf; index ++) + { + if (ioman->ring_fifo[index] == bp) + { + bp_index = index; + break; + } + } + + /* not found bp in fifo ring */ + if (index == ioman->numbuf) return; + + /* move the bp to the top of fifo ring */ + for (index = bp_index; index > 0; index --) + { + ioman->ring_fifo[index] = ioman->ring_fifo[index - 1]; + } + ioman->ring_fifo[0] = bp; +} + +/* + * get last bp in fifo ring + */ +rt_inline rt_uint8_t ioman_ring_fifo_last(IOManager *ioman) +{ + RT_ASSERT(ioman != RT_NULL); + return ioman->ring_fifo[ioman->numbuf - 1]; +} + +static rt_err_t ioman_readSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf) +{ + rt_err_t result; + + RT_ASSERT(buf != RT_NULL); + + result = rt_device_read(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE); + if (result == DFS_SECTOR_SIZE) return RT_EOK; + + return -RT_ERROR; +} + +static rt_err_t ioman_writeSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf) +{ + rt_err_t result; + + RT_ASSERT(buf != RT_NULL); + + result = rt_device_write(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE); + if (result == DFS_SECTOR_SIZE) return RT_EOK; + + return -RT_ERROR; +} + +static rt_int32_t ioman_findSectorInCache(IOManager *ioman, rt_uint32_t address) +{ + rt_uint32_t c; + + for(c=0;c<ioman->numbuf;c++) + { + if((ioman->status[c] & (1 << IOMAN_STATUS_ATTR_VALIDDATA)) && + ioman->sector[c] == address) + return (c); + } + + return -RT_ERROR; +}
+ +static rt_err_t ioman_flushSector(IOManager *ioman, rt_uint32_t bp) +{ + rt_err_t result; + + RT_ASSERT(ioman != RT_NULL); + + result = ioman_writeSector(ioman, ioman->sector[bp], &ioman->cache[bp][0]); + if (result == RT_EOK) + { + /* set status */ + ioman->status[bp] &= ~(1 << IOMAN_STATUS_ATTR_WRITE); + } + + return result; +} + +rt_uint8_t* ioman_getSector(IOManager *ioman, rt_uint32_t address, rt_uint8_t mode) +{ + rt_int32_t bp; + + RT_ASSERT(ioman != RT_NULL); + + bp = ioman_findSectorInCache(ioman, address); + if (bp != -RT_ERROR) + { + /* incress cache usage */ + ioman->usage[bp] ++; + + /* relocate bp in fifo ring */ + ioman_ring_fifo_relocate(ioman, bp); + + if (ioman_isReqRw(mode)) + ioman->status[bp] |= (1 << IOMAN_STATUS_ATTR_WRITE); + + return &(ioman->cache[bp][0]); + } + + /* not find in cache, get the last bp in fifo ring */ + bp = ioman_ring_fifo_last(ioman); + if ((ioman->status[bp] & (1 << IOMAN_STATUS_ATTR_WRITE)) &&
+ ioman->usage[bp] == 0) + { + /* it's a writable buffer, flush it */ + ioman_flushSector(ioman, bp); + } + + /* strip last bp in fifo ring */ + bp = ioman_ring_fifo_swap(ioman); + + /* read sector */ + ioman_readSector(ioman, address, &ioman->cache[bp][0]); + ioman->sector[bp] = address; + ioman->usage [bp] = 1; + ioman->status[bp] = (1 << IOMAN_STATUS_ATTR_VALIDDATA);
+ if (ioman_isReqRw(mode)) + ioman->status[bp] |= (1 << IOMAN_STATUS_ATTR_WRITE);
+ + return &ioman->cache[bp][0]; +} + +rt_err_t ioman_releaseSector(IOManager *ioman, rt_uint8_t* buf) +{ + rt_uint32_t bp; + + /* get buffer place */ + bp = ((rt_uint32_t)buf - (rt_uint32_t)&ioman->cache[0]) / DFS_SECTOR_SIZE; + + /* decrease usage */ + if (ioman->usage[bp] > 0) ioman->usage[bp] --; + if (ioman->usage[bp] == 0) + { + if(ioman->status[bp] & (1 << IOMAN_STATUS_ATTR_WRITE)) + { + ioman_flushSector(ioman,bp); + } + } + + return RT_EOK; +} + +rt_err_t ioman_flushRange(IOManager *ioman, rt_uint32_t address_low, rt_uint32_t address_high) +{ + rt_uint32_t c; + + if(address_low > address_high) + { + c = address_low; address_low = address_high; address_high = c; + } + + for(c = 0; c < ioman->numbuf; c++) + { + if((ioman->sector[c]>=address_low) + && (ioman->sector[c]<=address_high) + && (ioman->status[c] & (1 << IOMAN_STATUS_ATTR_WRITE))) + { + if(ioman_flushSector(ioman,c) != RT_EOK) + return -RT_ERROR; + + /* remove writable status */ + if(ioman->usage[c]==0) ioman->status[c] &= ~IOMAN_STATUS_ATTR_WRITE; + } + } + + return RT_EOK; +}
+ +/*
+ * read multi-sectors directly (none-cachable)
+ */ +rt_err_t ioman_directSectorRead(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector) +{ + rt_err_t result; + + RT_ASSERT(buf != RT_NULL); + + result = rt_device_read(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE * numsector); + if (result == DFS_SECTOR_SIZE * numsector) return RT_EOK; + + return -RT_ERROR; +}
+ +/*
+ * write multi-sectors directly (none-cachable)
+ */ +rt_err_t ioman_directSectorWrite(IOManager *ioman, rt_uint32_t address, rt_uint8_t* buf, rt_uint32_t numsector) +{ + rt_err_t result; + + RT_ASSERT(buf != RT_NULL); + + result = rt_device_write(ioman->device, address * DFS_SECTOR_SIZE, buf, DFS_SECTOR_SIZE * numsector); + if (result == DFS_SECTOR_SIZE * numsector) return RT_EOK; + + return -RT_ERROR; +} diff --git a/filesystem/dfs/src/dfs_fs.c b/filesystem/dfs/src/dfs_fs.c new file mode 100644 index 0000000000..f0ca291c24 --- /dev/null +++ b/filesystem/dfs/src/dfs_fs.c @@ -0,0 +1,362 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_fs.c, the filesystem related implementations of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-02-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_fs.h>
+#include <dfs_raw.h>
+#include <dfs_util.h>
+
+#include <string.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_register
++------------------------------------------------------------------------------
+| Description : registers a filesystem
+|
+| Parameters : ops, the implementation of filesystem
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_register(struct dfs_filesystem_operation* ops)
+{
+ int index;
+
+ rt_sem_take(filesystem_operation_table_lock, RT_WAITING_FOREVER);
+
+ /* check if this filesystem was already registered */
+ for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++)
+ {
+ if (filesystem_operation_table[index] != RT_NULL &&
+ strcmp(filesystem_operation_table[index]->name, ops->name) == 0)
+ goto err;
+ }
+
+ /* find out an empty filesystem type entry */
+ for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX && filesystem_operation_table[index] != RT_NULL;
+ index++) ;
+
+ /* filesystem type table full */
+ if (index == DFS_FILESYSTEM_TYPES_MAX) goto err;
+
+ /* save the filesystem's operations */
+ filesystem_operation_table[index] = ops;
+
+ rt_sem_release(filesystem_operation_table_lock);
+ return 0;
+
+err:
+ rt_sem_release(filesystem_operation_table_lock);
+ return -1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_filesystem_lookup
++------------------------------------------------------------------------------
+| Description : lookup the mounted filesystem on the specified path
+|
+| Parameters : path, the specified path string
+| Returns : the found filesystem
++------------------------------------------------------------------------------
+*/
+struct dfs_filesystem* dfs_filesystem_lookup(const char *path)
+{
+ struct dfs_filesystem* fs;
+ rt_uint32_t index, fspath, prefixlen;
+
+ fs = RT_NULL;
+ prefixlen = 0;
+
+ /* lock filesystem table */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* lookup it in the filesystem table */
+ for (index = 0; index < DFS_FILESYSTEMS_MAX + 1; index++)
+ {
+ fspath = strlen(filesystem_table[index].path);
+ if (fspath < prefixlen) continue;
+
+ if ((filesystem_table[index].ops != RT_NULL) &&
+ str_is_prefix(filesystem_table[index].path, path) == 0)
+ {
+ fs = &filesystem_table[index];
+ prefixlen = fspath;
+ }
+ }
+
+ rt_sem_release(filesystem_table_lock);
+ return fs;
+}
+
+rt_err_t dfs_filesystem_get_partition(struct dfs_partition* part, rt_uint8_t* buf, rt_uint32_t pindex)
+{
+#define DPT_ADDRESS 0x1be /* device partition offset in Boot Sector */
+#define DPT_ITEM_SIZE 16 /* partition item size */
+
+ rt_uint8_t* dpt;
+ rt_uint8_t type;
+ rt_err_t result;
+
+ RT_ASSERT(part != RT_NULL);
+ RT_ASSERT(buf != RT_NULL);
+
+ result = RT_EOK;
+
+ dpt = buf + DPT_ADDRESS + pindex * DPT_ITEM_SIZE;
+
+ if ((*dpt != 0x80) && (*dpt != 0x00))
+ {
+ /* which is not a partition table */
+ result = -RT_ERROR;
+ return result;
+ }
+
+ /* get partition type */
+ type = *(dpt+4);
+
+ if (type != 0)
+ {
+ /* set partition type */
+ part->type = type;
+
+ /* get partition offset and size */
+ part->offset = *(dpt+ 8) | *(dpt+ 9) << 8 |
+ *(dpt+10) << 16 | *(dpt+11) << 24;
+ part->size = *(dpt+12) | *(dpt+13) << 8 |
+ *(dpt+14) << 16 | *(dpt+15) << 24;
+
+#ifdef RT_USING_FINSH
+ rt_kprintf("part[%d], begin: %d, size: %d\n",
+ pindex, part->offset * 512, part->size* 512);
+#endif
+ }
+ else
+ {
+ result = -RT_ERROR;
+ }
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_mount
++------------------------------------------------------------------------------
+| Description : mount a filesystem to specified path
+|
+| Parameters : device_name, the implementation of filesystem
+| path,
+| filesystemtype,
+| rwflag,
+| data,
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_mount(const char* device_name, const char* path,
+ const char* filesystemtype, unsigned long rwflag, const
+ void* data)
+{
+ struct dfs_filesystem_operation* ops;
+ struct dfs_filesystem* fs;
+ char *fullpath=RT_NULL;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ rt_device_t dev_id;
+ int index;
+
+ /* open specific device */
+ dev_id = rt_device_find(device_name);
+ if (dev_id == RT_NULL)
+ {
+ /* no this device */
+ rt_set_errno(-DFS_STATUS_ENODEV);
+ return -1;
+ }
+
+ /* find out specific filesystem */
+ rt_sem_take(filesystem_operation_table_lock, RT_WAITING_FOREVER);
+ for ( index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index++ )
+ {
+ if (strcmp(filesystem_operation_table[index]->name, filesystemtype) == 0)break;
+ }
+
+ /* can't find filesystem */
+ if ( index == DFS_FILESYSTEM_TYPES_MAX )
+ {
+ rt_set_errno(-DFS_STATUS_ENODEV);
+ rt_sem_release(filesystem_operation_table_lock);
+ return -1;
+ }
+ ops = filesystem_operation_table[index];
+ rt_sem_release(filesystem_operation_table_lock);
+
+ /* make full path for special file */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/') /* not an abstract path */
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+#endif
+ }
+
+ /* Check if the path exists or not, raw APIs call, fixme */
+ if ( (strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0) )
+ {
+ struct dfs_fd fd;
+
+ if ( dfile_raw_open(&fd, fullpath, DFS_O_RDONLY | DFS_O_DIRECTORY) < 0 )
+ {
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+ }
+ dfile_raw_close(&fd);
+ }
+
+ /* check whether the file system mounted or not */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+ for (index =0; index < DFS_FILESYSTEMS_MAX; index++)
+ {
+ if ( filesystem_table[index].ops != RT_NULL &&
+ strcmp(filesystem_table[index].path, path) == 0 )
+ {
+ rt_set_errno(-DFS_STATUS_EINVAL);
+ goto err1;
+ }
+ }
+
+ /* find out en empty filesystem table entry */
+ for (index = 0; index < DFS_FILESYSTEMS_MAX && filesystem_table[index].ops != RT_NULL;
+ index++) ;
+ if ( index == DFS_FILESYSTEMS_MAX ) /* can't find en empty filesystem table entry */
+ {
+ rt_set_errno(-DFS_STATUS_EMMOUNT);
+ goto err1;
+ }
+
+ /* register file system */
+ fs = &(filesystem_table[index]);
+ strncpy(fs->path, fullpath, strlen(fullpath));
+ fs->ops = ops;
+ fs->dev_id = dev_id;
+ /* release filesystem_table lock */
+ rt_sem_release(filesystem_table_lock);
+
+ /* open device, but do not check the status of device */
+ rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDWR);
+
+ if ( ops->mount == RT_NULL ) /* there is no mount implementation */
+ {
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* clear filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+
+ rt_set_errno(-DFS_STATUS_ENOSYS);
+ return -1;
+ }
+ /* call mount of this filesystem */
+ else if ( ops->mount(fs) < 0 )
+ {
+ /* mount failed */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ /* close device */
+ rt_device_close(fs->dev_id);
+
+ /* clear filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+ }
+
+ return 0;
+
+err1:
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfs_unmount
++------------------------------------------------------------------------------
+| Description : unmount a filesystem
+|
+| Parameters :
+| Returns : the status of register
+| 0 , successful
+| -1, failed
++------------------------------------------------------------------------------
+*/
+int dfs_unmount(const char *specialfile)
+{
+ char *fullpath;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ struct dfs_filesystem* fs = RT_NULL;
+
+ fullpath = (char*)specialfile;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, specialfile, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+ rt_set_errno(-DFS_STATUS_ENOTDIR);
+ return -1;
+#endif
+ }
+
+ /* lock filesystem table */
+ rt_sem_take(filesystem_table_lock, RT_WAITING_FOREVER);
+
+ fs = dfs_filesystem_lookup(fullpath);
+ if (fs != RT_NULL && fs->ops->unmount != RT_NULL && fs->ops->unmount(fs) < 0)
+ {
+ goto err1;
+ }
+
+ /* close device, but do not check the status of device */
+ rt_device_close(fs->dev_id);
+
+ /* clear this filesystem table entry */
+ rt_memset(fs, 0, sizeof(struct dfs_filesystem));
+
+ rt_sem_release(filesystem_table_lock);
+
+ return 0;
+
+err1:
+ rt_sem_release(filesystem_table_lock);
+ return -1;
+}
diff --git a/filesystem/dfs/src/dfs_init.c b/filesystem/dfs/src/dfs_init.c new file mode 100644 index 0000000000..5b72da71ed --- /dev/null +++ b/filesystem/dfs/src/dfs_init.c @@ -0,0 +1,92 @@ +/* ++------------------------------------------------------------------------------ +| Project : Device Filesystem ++------------------------------------------------------------------------------ +| Copyright 2004, 2005 www.fayfayspace.org. +| All rights reserved. +|------------------------------------------------------------------------------ +| File : dfs.c, the implementation of Device FileSystem +|------------------------------------------------------------------------------ +| Chang Logs: +| Date Author Notes +| 2002-12-31 ffxz The first version. +| 2005-01-22 ffxz Clean up the code. ++------------------------------------------------------------------------------ +*/ +#include <dfs_def.h> +#include <dfs_config.h> + +#include <dfs_fs.h> +#include <dfs_raw.h> + +#include <string.h> + +/* Global variables */ +struct dfs_filesystem_operation* filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX + 1]; +struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX + 1]; + +rt_sem_t filesystem_table_lock; +rt_sem_t filesystem_operation_table_lock; + +#ifdef RT_USING_WORKDIR +char working_directory[DFS_PATH_MAX + 1]; +rt_sem_t working_directory_lock; +#endif + +struct dfs_fd fd_table[DFS_FD_MAX + 1]; +rt_sem_t fd_table_lock; + +/* ++------------------------------------------------------------------------------ +| Function : dfs_init ++------------------------------------------------------------------------------ +| Description : Inits the Device Filesystem +| Parameters : null +| Returns : null ++------------------------------------------------------------------------------ +*/ +void dfs_init() +{ + int index; + + /* clear filesystem operations table */ + for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX + 1; index++) + filesystem_operation_table[index] = RT_NULL; + + /* create filesystem operations table lock */ + filesystem_operation_table_lock = rt_sem_create("sem_fot", 1, RT_IPC_FLAG_FIFO); + + /* clear filesystem table */ + for (index = 0; index < DFS_FILESYSTEMS_MAX + 1; index++) + { + rt_memset(filesystem_table[index].path, 0, DFS_PATH_MAX + 1); + + filesystem_table[index].ops = RT_NULL; + filesystem_table[index].dev_id = 0; + filesystem_table[index].block_id = 0; + filesystem_table[index].data = RT_NULL; + } + + /* create filesystem table lock */ + filesystem_table_lock = rt_sem_create("sem_fst", 1, RT_IPC_FLAG_FIFO); + +#ifdef RT_USING_WORKDIR + /* set current working directory */ + strcpy(working_directory, "/"); + working_directory_lock = rt_sem_create("sem_wd", 1, RT_IPC_FLAG_FIFO); +#endif + + /* clean fd table */ + for ( index = 0; index < DFS_FD_MAX; index ++) + { + rt_memset(&fd_table[index], 0, sizeof(struct dfs_fd)); + } + + /* create fd table lock */ + fd_table_lock = rt_sem_create("sem_fdt", 1, RT_IPC_FLAG_FIFO); + +#if defined(RT_USING_FINSH) && !defined(FINSH_USING_SYMTAB) + dfs_export_finsh(); +#endif +} + diff --git a/filesystem/dfs/src/dfs_posix.c b/filesystem/dfs/src/dfs_posix.c new file mode 100644 index 0000000000..6ea66a0e76 --- /dev/null +++ b/filesystem/dfs/src/dfs_posix.c @@ -0,0 +1,564 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_posix.c, the interface related implementations of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2009-05-27 Yi.qiu The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_posix.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : open
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int open(const char *file, int flags, int mode)
+{
+ int fd, result;
+ struct dfs_fd* d;
+
+ /* allocate a fd */
+ fd = fd_new();
+ if (fd < 0) return -1;
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, file, flags);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return fd;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : close
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int close(int d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d);
+
+ result = dfile_raw_close(fd);
+ fd_put(fd);
+ fd_put(fd);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : read
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int read(int fd, char *buf, int len)
+{
+ int result;
+ struct dfs_fd* d;
+
+ /* get the fd */
+ d = fd_get(fd);
+
+ result = dfile_raw_read(d, buf, len);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : write
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int write(int fd, char *buf, int len)
+{
+ int result;
+ struct dfs_fd* d;
+
+ /* get the fd */
+ d = fd_get(fd);
+
+ result = dfile_raw_write(d, buf, len);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : lseek
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int lseek(int fd, int offset, int dir)
+{
+ int result;
+ struct dfs_fd* d;
+
+ d = fd_get(fd);
+
+ switch (dir)
+ {
+ case DFS_SEEK_SET:
+ break;
+
+ case DFS_SEEK_CUR:
+ offset += d->pos;
+ break;
+
+ case DFS_SEEK_END:
+ offset = d->pos - offset;
+ break;
+ }
+
+ result = dfile_raw_lseek(d, offset);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ fd_put(d);
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rename
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int rename(const char* old, const char* new )
+{
+ int result;
+
+ result = dfile_raw_rename(old, new);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : unlink
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int unlink(const char *pathname)
+{
+ int result;
+
+ result = dfile_raw_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : stat
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int stat(const char *file, struct dfs_stat *buf)
+{
+ int result;
+
+ result = dfile_raw_stat(file, (struct dfs_stat *)buf);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : mkdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int mkdir (const char *path, rt_uint16_t mode)
+{
+ int fd;
+ struct dfs_fd* d;
+ int result;
+
+ fd = fd_new();
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, path, DFS_O_DIRECTORY | DFS_O_CREAT);
+ fd_put(d);
+ fd_put(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rmdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int rmdir(const char *pathname)
+{
+ int result;
+
+ result = dfile_raw_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : opendir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+DIR* opendir(const char* name)
+{
+ struct dfs_fd* d;
+ int fd, result;
+ DIR* t;
+
+ t = RT_NULL;
+
+ /* allocate a fd */
+ fd = fd_new();
+ d = fd_get(fd);
+
+ result = dfile_raw_open(d, name, DFS_O_RDONLY | DFS_O_DIRECTORY);
+ if (result >= 0)
+ {
+ /* open successfully */
+ t = (DIR *) rt_malloc (sizeof(DIR));
+ if (t == RT_NULL)
+ {
+ dfile_raw_close(d);
+ fd_put(d);
+ }
+ else t->fd = fd;
+ fd_put(d);
+ return t;
+ }
+
+ /* open failed */
+ fd_put(d);
+ fd_put(d);
+ rt_set_errno(result);
+
+ return RT_NULL;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : readdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+struct dfs_dirent* readdir(DIR *d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+
+ if (!d->num || (d->cur += ((struct dfs_dirent*)(d->buf + d->cur))->d_reclen) >= d->num)
+ {
+ result = dfile_raw_getdents(fd, (struct dfs_dirent*)d->buf, sizeof(d->buf) - 1);
+ if (result <= 0)
+ {
+ rt_set_errno(result);
+ fd_put(fd);
+
+ return RT_NULL;
+ }
+
+ d->num = result;
+ d->cur = 0;
+ }
+
+ fd_put(fd);
+ return (struct dfs_dirent*)(d->buf+d->cur);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : telldir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+rt_off_t telldir(DIR *d)
+{
+ struct dfs_fd* fd;
+ rt_off_t result;
+
+ fd = fd_get(d->fd);
+ result = fd->pos - d->num + d->cur;
+ fd_put(fd);
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : seekdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void seekdir(DIR *d, rt_off_t offset)
+{
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+ if (dfile_raw_lseek(fd, offset) >= 0) d->num = d->cur = 0;
+ fd_put(fd);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : rewinddir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void rewinddir(DIR *d)
+{
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+ if (dfile_raw_lseek(fd, 0) >= 0) d->num = d->cur = 0;
+ fd_put(fd);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : closedir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int closedir(DIR* d)
+{
+ int result;
+ struct dfs_fd* fd;
+
+ fd = fd_get(d->fd);
+
+ result = dfile_raw_close(fd);
+ fd_put(fd);
+
+ rt_free(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+ return -1;
+ }
+ else return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : chdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int chdir(const char *path)
+{
+ char* fullpath, full_path[DFS_PATH_MAX + 1];
+
+ if(path == RT_NULL || strlen(path) > DFS_PATH_MAX)
+ return -1;
+
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/' )
+ {
+ /* build full path */
+ fullpath = full_path;
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ strcpy(working_directory, fullpath);
+ rt_sem_release(working_directory_lock);
+#endif
+ }
+ else
+ {
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ rt_strncpy(working_directory, path, strlen(path) + 1);
+ working_directory[strlen(path)] = '\0';
+ rt_sem_release(working_directory_lock);
+#endif
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : chdir
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+char* getcwd(char *buf, rt_size_t size)
+{
+#ifdef RT_USING_WORKDIR
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ rt_strncpy(buf, working_directory, size);
+ rt_sem_release(working_directory_lock);
+#endif
+ return buf;
+}
+
diff --git a/filesystem/dfs/src/dfs_raw.c b/filesystem/dfs/src/dfs_raw.c new file mode 100644 index 0000000000..816197c5e9 --- /dev/null +++ b/filesystem/dfs/src/dfs_raw.c @@ -0,0 +1,668 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_raw.c, the raw APIs of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-02-22 ffxz The first version.
++------------------------------------------------------------------------------
+*/
+#include <dfs_raw.h>
+#include <dfs_util.h>
+#include <string.h>
+
+extern struct dfs_fd fd_table[DFS_FD_MAX + 1];
+extern rt_sem_t fd_table_lock;
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_new
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int fd_new(void)
+{
+ struct dfs_fd* d;
+ int idx;
+
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+
+ /* find an empty fd entry */
+ for (idx = 3; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++);
+
+ /* can't find an empty fd entry */
+ if (idx == DFS_FD_MAX)
+ {
+ rt_sem_release(fd_table_lock);
+ return -1;
+ }
+
+ d = &(fd_table[idx]);
+ d->ref_count = 1;
+ rt_sem_release(fd_table_lock);
+
+ return idx;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_get
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+struct dfs_fd* fd_get(int fd)
+{
+ struct dfs_fd* d;
+
+ if ( fd < 3 || fd > DFS_FD_MAX ) return RT_NULL;
+
+ d = &fd_table[fd];
+
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ d->ref_count ++;
+ rt_sem_release(fd_table_lock);
+
+ return d;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : fd_put
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+void fd_put(struct dfs_fd* fd)
+{
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ fd->ref_count --;
+ /* clear this fd entry */
+ if ( fd->ref_count == 0 )
+ {
+ rt_memset(fd, 0, sizeof(struct dfs_fd));
+ }
+ rt_sem_release(fd_table_lock);
+};
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_open
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_open(struct dfs_fd* fd, const char *path, int flags)
+{
+ struct dfs_filesystem* fs;
+ char *fullpath;
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ int fspathlen, result;
+
+ /* parameter check */
+ if ( fd == RT_NULL ) return -DFS_STATUS_EINVAL;
+
+ /* make sure we have an absolute path */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = &full_path[0];
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ dfs_log(DFS_DEBUG_INFO, ("open file:%s", fullpath));
+
+ /* find filesystem */
+ fs = dfs_filesystem_lookup(fullpath);
+ if ( fs == RT_NULL ) return -DFS_STATUS_ENOENT;
+
+ dfs_log(DFS_DEBUG_INFO, ("open in filesystem:%s", fs->ops->name));
+ fd->fs = fs;
+
+ /* initilize the fd item */
+ fd->type = FT_REGULAR;
+ //fd->ref_count = 1;
+ fd->flags = flags;
+ fd->size = 0;
+ fd->pos = 0;
+
+ fspathlen = strlen(fs->path);
+ rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
+ if (*(fullpath + fspathlen) != '/') strcpy(fd->path, "/");
+ strcat(fd->path, fullpath + fspathlen);
+
+ /* specific file system open routine */
+ if (fs->ops->open == RT_NULL)
+ {
+ /* clear fd */
+ rt_memset(fd->path, 0, DFS_PATH_MAX + 1);
+
+ fd->type = FT_REGULAR;
+ fd->ref_count = 0;
+ fd->fs = RT_NULL;
+ fd->flags = 0;
+ fd->size = 0;
+ fd->pos = 0;
+ fd->data = RT_NULL;
+
+ return -DFS_STATUS_ENOSYS;
+ }
+
+ if ((result = fs->ops->open(fd)) < 0)
+ {
+ /* clear fd */
+ fd->fs = RT_NULL;
+ fd->flags = 0;
+ fd->data = RT_NULL;
+
+ dfs_log(DFS_DEBUG_INFO, ("open failed"));
+
+ return result;
+ }
+
+ fd->flags |= DFS_F_OPEN;
+ if ( flags & DFS_O_DIRECTORY ) fd->flags |= DFS_F_DIRECTORY;
+
+ dfs_log(DFS_DEBUG_INFO, ("open successful"));
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_close
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_close(struct dfs_fd* fd)
+{
+ int result = 0;
+
+ if (fd != RT_NULL && fd->fs->ops->close != RT_NULL) result = fd->fs->ops->close(fd);
+
+ /* close fd error, return */
+ if ( result < 0 ) return result;
+
+ fd->flags &= ~DFS_F_OPEN;
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_ioctl
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_ioctl(struct dfs_fd* fd, int cmd, void *args)
+{
+ struct dfs_filesystem* fs;
+
+ if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL;
+
+ fs = fd->fs;
+#if 0 /* not support right now */
+ if (cmd == FILEGETSIZE)
+ {
+ if (args == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ *((rt_uint32_t *) args) = fd->size;
+
+ return 0;
+ }
+ else if (cmd == FILEGETPOS)
+ {
+ if (args == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ *((rt_uint32_t *) args) = fd->pos;
+
+ return 0;
+ }
+#endif
+
+ if (fs->ops->ioctl != RT_NULL) return fs->ops->ioctl(fd, cmd, args);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_read
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_read(struct dfs_fd* fd, void *buf, rt_size_t len)
+{
+ struct dfs_filesystem* fs;
+ int result = 0;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+
+ fs = (struct dfs_filesystem*) fd->fs;
+ if (fs->ops->read == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ if ( (result = fs->ops->read(fd, buf, len)) < 0 ) fd->flags |= DFS_F_EOF;
+
+ return result;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_getdents
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_getdents(struct dfs_fd* fd, struct dfs_dirent* dirp, rt_size_t nbytes)
+{
+ struct dfs_filesystem* fs;
+
+ /* parameter check */
+ if (fd == RT_NULL || fd->type != FT_REGULAR) return -DFS_STATUS_EINVAL;
+
+ fs = (struct dfs_filesystem*) fd->fs;
+ if (fs->ops->getdents != RT_NULL) return fs->ops->getdents(fd, dirp, nbytes);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_unlink
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_unlink(const char *path)
+{
+ struct dfs_filesystem* fs;
+ char *fullpath, *real_path, search_path[DFS_PATH_MAX + 1];
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX+1];
+#endif
+ struct dfs_fd* fd;
+ int index, fspathlen;
+
+ /* Make sure we have an absolute path */
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/')
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL) return -DFS_STATUS_ENOENT;
+
+ /* Check whether file is already open */
+ rt_sem_take(fd_table_lock, RT_WAITING_FOREVER);
+ for (index = 0; index < DFS_FD_MAX; index++)
+ {
+ fd = &(fd_table[index]);
+ if (fd->fs == RT_NULL) continue;
+
+ build_fullpath(fd->fs->path, fd->path, search_path);
+ if (strcmp(fullpath, search_path) == 0)
+ {
+ rt_sem_release(fd_table_lock);
+ return -DFS_STATUS_EEXIST;
+ }
+ }
+ rt_sem_release(fd_table_lock);
+
+ fspathlen = strlen(fs->path);
+ real_path = search_path;
+ rt_memset( real_path, 0, sizeof( real_path ) );
+ if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
+ strcat(real_path, fullpath + fspathlen);
+
+ if (fs->ops->unlink != RT_NULL) return fs->ops->unlink(fs, real_path);
+
+ return -DFS_STATUS_ENOSYS;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_write
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_write(struct dfs_fd* fd, const void *buf, rt_size_t len)
+{
+ struct dfs_filesystem* fs = fd->fs;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+ if (fs->ops->write == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ return fs->ops->write(fd, buf, len);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_lseek
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_lseek(struct dfs_fd* fd, rt_off_t offset)
+{
+ struct dfs_filesystem* fs = fd->fs;
+
+ if (fd == RT_NULL) return -DFS_STATUS_EINVAL;
+ if (fs->ops->lseek == RT_NULL) return -DFS_STATUS_ENOSYS;
+
+ return fs->ops->lseek(fd, offset);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_stat
++------------------------------------------------------------------------------
+| Description : get the file or directory stat description
+|
+| Parameters : path, the file or directory path
+| buf, the stat description will be saved in it
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_stat(const char *path, struct dfs_stat *buf)
+{
+ struct dfs_filesystem* fs;
+ char* fullpath, real_path[DFS_PATH_MAX + 1];
+#ifdef RT_USING_WORKDIR
+ char full_path[DFS_PATH_MAX + 1];
+#endif
+ int fspathlen;
+
+ fullpath = (char*)path;
+ if ( fullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ fullpath = full_path;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, path, fullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (fs = dfs_filesystem_lookup(fullpath)) == RT_NULL )
+ {
+ dfs_log(DFS_DEBUG_ERROR, ("can't find mounted filesystem on this path:%s", fullpath));
+ return -DFS_STATUS_ENOENT;
+ }
+
+ fspathlen = strlen(fs->path);
+ rt_memset(real_path, 0, sizeof(real_path));
+ if (*(fullpath + fspathlen) != '/') strcpy(real_path, "/");
+ strcat(real_path, fullpath + fspathlen);
+
+ if (fs->ops->stat == RT_NULL)
+ {
+ dfs_log(DFS_DEBUG_ERROR, ("the filesystem didn't implement this function"));
+ return -DFS_STATUS_ENOSYS;
+ }
+
+ return fs->ops->stat(fs, real_path, buf);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : dfile_raw_rename
++------------------------------------------------------------------------------
+| Description :
+|
+| Parameters :
+| Returns :
+|
++------------------------------------------------------------------------------
+*/
+int dfile_raw_rename(const char* oldpath, const char* newpath)
+{
+ struct dfs_filesystem *oldfs, *newfs;
+ char *oldfullpath, *newfullpath;
+ #ifdef RT_USING_WORKDIR
+ /* Change DFS_PATH_MAX to DFS_PATH_MAX + 1, [email protected]*/
+ char old_realpath[DFS_PATH_MAX + 1], new_realpath[DFS_PATH_MAX + 1];
+ #endif
+
+ oldfullpath = (char*)oldpath;
+ newfullpath = (char*)newpath;
+
+ if ( oldfullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ oldfullpath = old_realpath;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, oldpath, oldfullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( newfullpath[0] != '/' )
+ {
+#ifdef RT_USING_WORKDIR
+ /* build full path */
+ newfullpath = new_realpath;
+ rt_sem_take(working_directory_lock, RT_WAITING_FOREVER);
+ build_fullpath(working_directory, newpath, newfullpath);
+ rt_sem_release(working_directory_lock);
+#else
+#ifdef RT_USING_FINSH
+ rt_kprintf("bad filename");
+#endif
+ return -1;
+#endif
+ }
+
+ if ( (oldfs = dfs_filesystem_lookup(oldfullpath)) == RT_NULL )
+ {
+ return -DFS_STATUS_ENOENT;
+ }
+
+ if ( (newfs = dfs_filesystem_lookup(newfullpath)) == RT_NULL )
+ {
+ return -DFS_STATUS_ENOENT;
+ }
+
+ if ( oldfs == newfs )
+ {
+ if ( oldfs->ops->rename == RT_NULL ) return -DFS_STATUS_ENOSYS;
+
+ return oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
+ }
+
+ /* not at same file system, return EXDEV */
+ return -DFS_STATUS_EXDEV;
+}
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+
+static char fullpath[256 + 1];
+static struct dfs_fd fd;
+static struct dfs_dirent dirent;
+void __ls(const char* pathname)
+{
+ struct dfs_stat stat;
+ int length;
+
+ /* list directory */
+ if ( dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY) == 0 )
+ {
+ rt_kprintf("Directory %s:\n", pathname);
+ do
+ {
+ rt_memset(&dirent, 0, sizeof(struct dfs_dirent));
+ length = dfile_raw_getdents(&fd, &dirent, sizeof(struct dfs_dirent));
+ if ( length > 0 )
+ {
+ rt_memset(&stat, 0, sizeof(struct dfs_stat));
+
+ /* build full path for each file */
+ strncpy(fullpath, pathname, 256);
+ strcat(fullpath, "/");
+ strcat(fullpath, dirent.d_name);
+
+ dfile_raw_stat(fullpath, &stat);
+ if ( stat.st_mode & DFS_S_IFDIR )
+ {
+ rt_kprintf("%s\t\t<DIR>\n", dirent.d_name);
+ }
+ else
+ {
+ rt_kprintf("%s\t\t%lu\n", dirent.d_name, stat.st_size);
+ }
+ }
+ }while(length > 0);
+
+ dfile_raw_close(&fd);
+ }
+ else
+ {
+ rt_kprintf("No such directory\n");
+ }
+}
+FINSH_FUNCTION_EXPORT(__ls, list directory contents)
+
+void __mkdir(const char* pathname)
+{
+ /* make a new directory */
+ if (dfile_raw_open(&fd, pathname, DFS_O_DIRECTORY | DFS_O_CREAT) == 0)
+ {
+ dfile_raw_close(&fd);
+ }
+ else rt_kprintf("Can't mkdir %s\n", pathname);
+}
+FINSH_FUNCTION_EXPORT(__mkdir, make a directory)
+
+void __rm(const char* filename)
+{
+ if (dfile_raw_unlink(filename) < 0)
+ {
+ rt_kprintf("Delete %s failed\n", filename);
+ }
+}
+FINSH_FUNCTION_EXPORT(__rm, remove files or directories)
+
+void __cat(const char* filename)
+{
+ rt_uint32_t length;
+ char buffer[81];
+
+ if (dfile_raw_open(&fd, filename, DFS_O_RDONLY) < 0)
+ {
+ rt_kprintf("Open %s failed\n", filename);
+ return;
+ }
+
+ do
+ {
+ rt_memset(buffer, 0, sizeof(buffer));
+ length = dfile_raw_read(&fd, buffer, 81);
+ if (length > 0)
+ {
+ rt_kprintf("%s", buffer);
+ }
+ }while (length > 0);
+
+ dfile_raw_close(&fd);
+}
+FINSH_FUNCTION_EXPORT(__cat, print file)
+
+#ifndef FINSH_USING_SYMTAB
+void dfs_export_finsh(void)
+{
+ finsh_syscall_append("ls", (syscall_func)__ls);
+ finsh_syscall_append("mkdir", (syscall_func)__mkdir);
+ finsh_syscall_append("rm", (syscall_func)__rm);
+ finsh_syscall_append("cat", (syscall_func)__cat);
+}
+#endif
+#endif
diff --git a/filesystem/dfs/src/dfs_util.c b/filesystem/dfs/src/dfs_util.c new file mode 100644 index 0000000000..455c9f1f9d --- /dev/null +++ b/filesystem/dfs/src/dfs_util.c @@ -0,0 +1,297 @@ +/*
++------------------------------------------------------------------------------
+| Project : Device Filesystem
++------------------------------------------------------------------------------
+| Copyright 2004, 2005 www.fayfayspace.org.
+| All rights reserved.
+|------------------------------------------------------------------------------
+| File : dfs_utl.c, some misc functions of Device FileSystem
+|------------------------------------------------------------------------------
+| Chang Logs:
+| Date Author Notes
+| 2005-01-26 ffxz The first version
++------------------------------------------------------------------------------
+*/
+
+#include <string.h>
+
+#include <dfs_fs.h>
+#include <dfs_util.h>
+
+/*
++------------------------------------------------------------------------------
+| Function : dir_name
++------------------------------------------------------------------------------
+| Description : Gets the directory name in specified path string
+|
+| Parameters : path, the specified path string
+| path_name, return the path name in this parameter
+| len, the length of path name
+| Returns : the status of path_name:
+| 0 , successful
+| -1, failed
+| For Example :
+| path, dir_name
+| /, /
+| /usr, /
+| /usr/lib, /usr
+| /usr/lib/, /usr
++------------------------------------------------------------------------------
+*/
+int dir_name(const char* path, char* dirname, int len)
+{
+ int pos;
+
+ if ( path[0] == '/' && path[1] == '\0' )
+ {
+ *dirname++ = '/';
+ *dirname = '\0';
+ return 0;
+ }
+
+ pos = strlen(path);
+ while ( *(path + pos - 1) =='/' ) pos --;
+ while ( pos > 0 && *(path + pos - 1) != '/' ) pos --;
+ while ( pos > 0 && *(path + pos - 1) == '/' ) pos --;
+
+ if ( pos > len ) return -1;
+
+ if ( pos != 0)
+ {
+ memcpy(dirname, path, pos);
+ *(dirname+pos) = '\0';
+ }
+ else
+ {
+ *dirname++ = '/';
+ *dirname = '\0';
+ }
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : file_name
++------------------------------------------------------------------------------
+| Description : Gets the file name in specified path string
+|
+| Parameters : path, the specified path string
+| filename, return the path name in this parameter
+| len, the length of file name
+| Returns : the status of file_name:
+| 0 , successful
+| -1, failed
+| For Example :
+| path, filename
+| /, RT_NULL
+| /usr, usr
+| /usr/lib, lib
+| /usr/lib/, lib
++------------------------------------------------------------------------------
+*/
+int file_name(const char* path, char* filename, int len)
+{
+ int pos, size;
+
+ if ( path[0] == '/' && path[1] == '\0' )
+ {
+ *filename = '\0';
+ return 0;
+ }
+
+ pos = strlen(path);
+ while ( *(path + pos -1)=='/' ) pos --;
+ size = pos;
+
+ while ( *(path + pos -1) != '/' && pos > 0 ) pos --;
+
+ if ( size - pos > len ) return -1;
+ else size = size - pos ;
+
+ memcpy(filename, path + pos, size);
+ *(filename+size) = '\0';
+
+ return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : next_path_name
++------------------------------------------------------------------------------
+| Description : Gets the next directory name from specified path string
+|
+| Parameters : path, the specified path string
+| pos, the specified position of path string
+| next, return the next path in this parameter
+| Returns : the position of next directory item,
+| -1, if pos reach in the end of the specified path string
+| For Example :
++------------------------------------------------------------------------------
+*/
+int next_dir_name(const char* path, int pos, char* next)
+{
+ const char* q;
+
+ if ( pos > strlen(path) || pos < 0|| path == RT_NULL ) return -1;
+
+ q = path + pos;
+
+ /* check for firt '/' */
+ while ( *q == '/' ) q++;
+ if ( *q == '\0' )
+ {
+ *next = '\0';
+ return -1;
+ }
+
+ while ( *q != '/' && *q != '\0' )
+ {
+ *next++ = *q++;
+ }
+ *next = '\0';
+
+ return q - path + 1;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function : build_fullpath
++------------------------------------------------------------------------------
+| Description : make up the full path from directory and filename
+|
+| Parameters : path, the specified path string
+| filename, return the path name in this parameter
+| fullpath, the returned full path name
+| Returns : null
++------------------------------------------------------------------------------
+*/
+void build_fullpath(const char *directory, const char *filename, char *fullpath)
+{
+ char elem[DFS_PATH_MAX + 1];
+ int pos, start, len;
+
+ len = 0;
+ /* check parameters */
+ RT_ASSERT(directory != RT_NULL);
+ RT_ASSERT(filename != RT_NULL);
+ RT_ASSERT(fullpath != RT_NULL);
+
+ /* copy full of directory */
+ strncpy(fullpath, directory, DFS_PATH_MAX + 1);
+
+ for (pos = 0; filename[pos] != '\0'; )
+ {
+ /* strip '//' */
+ while (filename[pos] == '/') pos++;
+
+ /* get the filename element, save to elem array */
+ for (start = pos; filename[pos] != '/' && filename[pos] != '\0'; pos++)
+ len = pos - start + 1;
+
+ strncpy(elem, filename + start, DFS_PATH_MAX + 1);
+ /* clear the end of elem */
+ elem[(len < DFS_PATH_MAX + 1? len : DFS_PATH_MAX + 1)] = '\0';
+
+ /* strip '..' */
+ if (elem[0] == '.' && elem[1] == '.')
+ {
+ if (strlen(fullpath) == 0) strcpy(fullpath, ""); /* empty filename */
+ else if (fullpath[0] == '/' && fullpath[1] !='\0')
+ {
+ int i = strlen(fullpath);
+
+ while (fullpath[i - 1] == '/') i--;
+ while (i > 0 && fullpath[i - 1] != '/') i--;
+
+ fullpath[i] = '\0';
+ }
+ }
+ /* not '.', copy as normally */
+ else if (elem[0] != '.')
+ {
+ len = strlen(fullpath);
+
+ if (len == 0) strncpy(fullpath, elem, DFS_PATH_MAX + 1);
+ else if (fullpath[len - 1] == '/')
+ {
+ if (elem[0] == '/') strncat(fullpath, elem + 1, DFS_PATH_MAX + 1);
+ else strncat(fullpath, elem, DFS_PATH_MAX + 1);
+ }
+ else
+ {
+ if (elem[0] == '/') strcat(fullpath, elem);
+ else
+ {
+ strncat(fullpath, "/", DFS_PATH_MAX + 1);
+ strncat(fullpath + 1, elem, DFS_PATH_MAX + 1);
+ }
+ }
+ }
+ }
+
+ if ( fullpath[0] != '/' && fullpath[(len = strlen(fullpath)) - 1] == '/')
+ {
+ fullpath[len - 1] = '\0';
+ }
+}
+
+int str_is_prefix(const char* prefix, const char* str)
+{
+ while ((*prefix) && (*str) && (*prefix == *str))
+ {
+ prefix ++;
+ str ++;
+ }
+
+ if (*prefix == 0) return 0;
+
+ return -1;
+}
+
+#if !defined(RT_USING_MINILIBC) && !defined(RT_USING_NEWLIB)
+#if !defined(__ICCARM__)
+char *strrchr(const char *t, int c)
+{
+ register char ch;
+ register const char *l=0;
+
+ ch = c;
+ for (;;)
+ {
+ if ((*t == ch)) l=t;
+ if ((!*t)) return (char*)l; ++t;
+ }
+
+ return (char*)l;
+}
+#endif
+
+#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION / 10000 < 35)
+int strncasecmp ( const char* s1, const char* s2, size_t len )
+{
+ register unsigned int x2;
+ register unsigned int x1;
+ register const char* end = s1 + len;
+
+ while (1)
+ {
+ if ((s1 >= end) )
+ return 0;
+
+ x2 = *s2 - 'A'; if ((x2 < 26u)) x2 += 32;
+ x1 = *s1 - 'A'; if ((x1 < 26u)) x1 += 32;
+ s1++; s2++;
+
+ if ((x2 != x1))
+ break;
+
+ if ((x1 == (unsigned int)-'A'))
+ break;
+ }
+
+ return x1 - x2;
+}
+#endif /* end of __ARMCC_VERSION */
+
+#endif
|
