提交 800f0924 编写于 作者: B bernard.xiong

remove efsl from device file system.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@506 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 3c6a9775
......@@ -3,7 +3,6 @@ Import('rtconfig')
Import('RTT_ROOT')
dfs = Split("""
src/dfs_cache.c
src/dfs_fs.c
src/dfs_init.c
src/dfs_posix.c
......@@ -22,21 +21,6 @@ filesystems/fatfs/fatfs_init.c
filesystems/fatfs_misc.c
filesystems/fatfs/fatfs_mount.c""")
# DFS-EFSL options
efsl = Split("""
filesystems/efsl/src/base/efs.c
filesystems/efsl/src/base/extract.c
filesystems/efsl/src/base/partition.c
filesystems/efsl/src/base/plibc.c
filesystems/efsl/src/fs/vfat/dir.c
filesystems/efsl/src/fs/vfat/fat.c
filesystems/efsl/src/fs/vfat/file.c
filesystems/efsl/src/fs/vfat/fs.c
filesystems/efsl/src/fs/vfat/ls.c
filesystems/efsl/src/fs/vfat/time.c
filesystems/efsl/src/fs/vfat/ui.c
""")
# DFS-ELMFAT options
elmfat = Split("""
filesystems/elmfat/dfs_elm.c
......@@ -72,10 +56,6 @@ if rtconfig.RT_USING_DFS_YAFFS2:
src_local = src_local + yaffs2_main + yaffs2_comm
path = path + [RTT_ROOT + '/filesystem/dfs/filesystems/yaffs2', RTT_ROOT + '/filesystem/dfs/filesystems/yaffs2/direct']
if rtconfig.RT_USING_DFS_EFSL:
src_local = src_local + efsl
path = path + [RTT_ROOT + '/filesystem/dfs/filesystems/efsl/src/include', RTT_ROOT + '/filesystem/dfs/filesystems/efsl/src/base/include', RTT_ROOT + '/filesystem/dfs/filesystems/efsl/src/fs/vfat/include']
if rtconfig.RT_USING_DFS_ELMFAT:
src_local = src_local + elmfat
path = path + [RTT_ROOT + '/filesystem/dfs/filesystems/elmfat']
......
#+------------------------------------------------------------------------------
#| 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)
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
efsl-0.3.6
[Embedded Filesystems Library]
/*
* 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 <string.h>
#include "efs.h"
#include "dfs_cache.h"
#include "ls.h"
#include "ui.h"
#include "fat.h"
#define EFS_MAX 2
struct dfs_filesystem_operation efs;
#ifdef DFS_EFLS_USING_STATIC_CACHE
IOManager _ioman;
#endif
/**
* 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 */
#ifdef DFS_EFLS_USING_STATIC_CACHE
efsfs->partition.ioman = &_ioman;
#else
efsfs->partition.ioman = rt_malloc(sizeof(IOManager));
#endif
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);
#ifdef DFS_EFLS_USING_STATIC_CACHE
efsfs->partition.ioman = RT_NULL;
#else
rt_free(efsfs->partition.ioman);
#endif
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_ERROR, ("memory alloc failed"));
rt_free(efsdir);
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_ERROR, ("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;
}
/*****************************************************************************\
* 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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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);
}
/*****************************************************************************\
* 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--;
}
}
/*****************************************************************************\
* 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));
case DIRFIND_FREE:
return(dir_findFreeEntryinBuf(buf,loc));
}
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++)){
cluster=dir_findinCluster(fs,Cache.DiscCluster,fatname,loc,mode);
if(cluster) 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);
fclus=dir_findinBuf(buf,fatname,loc,mode);
if(fclus){
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++;
next=file_normalToFatName(next,ffnamec);
while(next){
memCpy(ffnamec,fatfilename,11);
nn++;
next=file_normalToFatName(next,ffnamec);
}
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);
}
/*****************************************************************************\
* 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);
}
return(base+res);
case FAT16:
res=cluster_addr/256;
if(res>=fs->FatSectorCount){
return(0);
}
return(base+res);
case FAT32:
res=cluster_addr/128;
if(res>=fs->FatSectorCount){
return(0);
}
return(base+res);
}
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){
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);
case FAT16:
return(0xFFFF);
case FAT32:
return(0x0FFFFFFF);
}
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';
}
/*****************************************************************************\
* 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;
}
dfs_log(DFS_DEBUG_INFO, ("offset:%d", offset));
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;
}
/*****************************************************************************\
* 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);
}
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.h"
#include "error.h"
#include "partition.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
/*****************************************************************************\
* 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
/*****************************************************************************\
* 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 "etypes.h"
#include "extract.h"
#include "config.h"
/*****************************************************************************/
#define MKFS_ERR_TOOLITTLESECTORS 1
esint16 mkfs_makevfat(Partition *part);
#endif
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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 "etypes.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
/*****************************************************************************\
* 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);
}
/*****************************************************************************/
/*****************************************************************************\
* 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
/*****************************************************************************\
* 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
}
/*****************************************************************************/
/*****************************************************************************\
* 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 file@yi.qiu,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);
part_relSect(fs->part,buf);
if(attr == ATTR_DIRECTORY)
{
dlist = (DirList *)rt_malloc(sizeof(DirList));
if(dlist == RT_NULL)
{
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;
dfs_log(DFS_DEBUG_INFO, ("Directory not empty"));
return -DFS_STATUS_ENOTEMPTY;
}
else break;
}
}
}
buf = part_getSect(fs->part,loc.Sector,IOM_MODE_READWRITE);
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);
}
#ifndef __EFSL_CONFIG_H__
#define __EFSL_CONFIG_H__
/* include RT-Thread to import configuration */
#include <rtthread.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
/*****************************************************************************\
* 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
/*****************************************************************************\
* 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
/*****************************************************************************\
* 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
#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
/*
+------------------------------------------------------------------------------
| 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
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册