summaryrefslogtreecommitdiff
path: root/filesystem/dfs
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/dfs')
-rw-r--r--filesystem/dfs/config.mk40
-rw-r--r--filesystem/dfs/dfs_config.h100
-rw-r--r--filesystem/dfs/filesystems/efsl/CHANGELOG39
-rw-r--r--filesystem/dfs/filesystems/efsl/VERSION3
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/debug.c182
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/efs.c489
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/extract.c57
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/debug.h68
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/efs.h89
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/extract.h101
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/ioman.h140
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/ioman_small.h93
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/partition.h73
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/include/plibc.h49
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/ioman.c600
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/ioman_small.c120
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/partition.c125
-rw-r--r--filesystem/dfs/filesystems/efsl/src/base/plibc.c83
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/dir.c365
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/fat.c577
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/file.c551
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/fs.c503
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/dir.h86
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fat.h64
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/file.h100
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/fs.h201
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ls.h69
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/mkfs.h50
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/tm.h74
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/include/ui.h50
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/ls.c150
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/mkfs.c166
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/time.c89
-rw-r--r--filesystem/dfs/filesystems/efsl/src/fs/vfat/ui.c200
-rw-r--r--filesystem/dfs/filesystems/efsl/src/include/config.h151
-rw-r--r--filesystem/dfs/filesystems/efsl/src/include/error.h124
-rw-r--r--filesystem/dfs/filesystems/efsl/src/include/ioctl.h44
-rw-r--r--filesystem/dfs/filesystems/efsl/src/include/types.h110
-rw-r--r--filesystem/dfs/include/dfs_cache.h41
-rw-r--r--filesystem/dfs/include/dfs_def.h173
-rw-r--r--filesystem/dfs/include/dfs_efs.h29
-rw-r--r--filesystem/dfs/include/dfs_fat.h29
-rw-r--r--filesystem/dfs/include/dfs_fs.h87
-rw-r--r--filesystem/dfs/include/dfs_init.h42
-rw-r--r--filesystem/dfs/include/dfs_posix.h100
-rw-r--r--filesystem/dfs/include/dfs_raw.h38
-rw-r--r--filesystem/dfs/include/dfs_util.h35
-rw-r--r--filesystem/dfs/src/dfs_cache.c273
-rw-r--r--filesystem/dfs/src/dfs_fs.c362
-rw-r--r--filesystem/dfs/src/dfs_init.c92
-rw-r--r--filesystem/dfs/src/dfs_posix.c564
-rw-r--r--filesystem/dfs/src/dfs_raw.c668
-rw-r--r--filesystem/dfs/src/dfs_util.c297
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