📄 fatfs.c
字号:
//==========================================================================//// fatfs.c//// FAT file system////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003 Savin Zlobec//// eCos 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; either version 2 or (at your option) any later version.//// eCos 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.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// 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.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): savin (based on ramfs.c)// Original data: nickg// Date: 2003-06-29// Purpose: FAT file system// Description: This is a FAT filesystem for eCos. ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#include <pkgconf/hal.h>#include <pkgconf/kernel.h>#include <pkgconf/io_fileio.h>#include <pkgconf/fs_fat.h>#include <cyg/kernel/ktypes.h> // base kernel types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <dirent.h>#include <stdlib.h>#include <string.h>#include <cyg/kernel/kapi.h>#include <cyg/infra/diag.h>#include <cyg/fileio/fileio.h>#include <cyg/io/io.h>#include <blib/blib.h>#include "fatfs.h"//==========================================================================// Tracing support defines #ifdef FATFS_TRACE_FS_OP# define TFS 1#else# define TFS 0#endif#ifdef FATFS_TRACE_FILE_OP# define TFO 1#else# define TFO 0#endif//==========================================================================// Forward definitions// Filesystem operationsstatic int fatfs_mount (cyg_fstab_entry *fste, cyg_mtab_entry *mte);static int fatfs_umount (cyg_mtab_entry *mte);static int fatfs_open (cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *fte);static int fatfs_unlink (cyg_mtab_entry *mte, cyg_dir dir, const char *name);static int fatfs_mkdir (cyg_mtab_entry *mte, cyg_dir dir, const char *name);static int fatfs_rmdir (cyg_mtab_entry *mte, cyg_dir dir, const char *name);static int fatfs_rename (cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 );static int fatfs_link (cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type );static int fatfs_opendir(cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *fte );static int fatfs_chdir (cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out );static int fatfs_stat (cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf);static int fatfs_getinfo(cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len );static int fatfs_setinfo(cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len );// File operationsstatic int fatfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int fatfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int fatfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );static int fatfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data);static int fatfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode ); static int fatfs_fo_close (struct CYG_FILE_TAG *fp);static int fatfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );static int fatfs_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len );static int fatfs_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len );// Directory operationsstatic int fatfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int fatfs_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence);//==========================================================================// Filesystem table entries// -------------------------------------------------------------------------// Fstab entry.FSTAB_ENTRY(fatfs_fste, "fatfs", 0, CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM, fatfs_mount, fatfs_umount, fatfs_open, fatfs_unlink, fatfs_mkdir, fatfs_rmdir, fatfs_rename, fatfs_link, fatfs_opendir, fatfs_chdir, fatfs_stat, fatfs_getinfo, fatfs_setinfo);// -------------------------------------------------------------------------// File operations.static cyg_fileops fatfs_fileops ={ fatfs_fo_read, fatfs_fo_write, fatfs_fo_lseek, fatfs_fo_ioctl, cyg_fileio_seltrue, fatfs_fo_fsync, fatfs_fo_close, fatfs_fo_fstat, fatfs_fo_getinfo, fatfs_fo_setinfo};// -------------------------------------------------------------------------// Directory file operations.static cyg_fileops fatfs_dirops ={ fatfs_fo_dirread, (cyg_fileop_write *)cyg_fileio_enosys, fatfs_fo_dirlseek, (cyg_fileop_ioctl *)cyg_fileio_enosys, cyg_fileio_seltrue, (cyg_fileop_fsync *)cyg_fileio_enosys, fatfs_fo_close, (cyg_fileop_fstat *)cyg_fileio_enosys, (cyg_fileop_getinfo *)cyg_fileio_enosys, (cyg_fileop_setinfo *)cyg_fileio_enosys};// -------------------------------------------------------------------------// Directory search data// Parameters for a directory search. The fields of this structure are// updated as we follow a pathname through the directory tree.struct fatfs_dirsearch_t{ fatfs_disk_t *disk; // Disk info fatfs_node_t *dir; // Directory to search const char *path; // Path to follow fatfs_node_t *node; // Node found const char *name; // Last name fragment used int namelen; // Name fragment length cyg_bool last; // Last name in path?};typedef struct fatfs_dirsearch_t fatfs_dirsearch_t;//==========================================================================#if TFSstatic void print_disk_info(fatfs_disk_t *disk){ diag_printf("FAT: sector size: %u\n", disk->sector_size); diag_printf("FAT: cluster size: %u\n", disk->cluster_size); diag_printf("FAT: FAT table position: %u\n", disk->fat_tbl_pos); diag_printf("FAT: FAT table num ent: %u\n", disk->fat_tbl_nents); diag_printf("FAT: FAT table size: %u\n", disk->fat_tbl_size); diag_printf("FAT: FAT tables num: %u\n", disk->fat_tbls_num); diag_printf("FAT: FAT root dir pos: %u\n", disk->fat_root_dir_pos); diag_printf("FAT: FAT root dir nents: %u\n", disk->fat_root_dir_nents); diag_printf("FAT: FAT root dir size: %u\n", disk->fat_root_dir_size); diag_printf("FAT: FAT data position: %u\n", disk->fat_data_pos);}#endifstatic voidinit_dirsearch(fatfs_dirsearch_t *ds, fatfs_disk_t *disk, fatfs_node_t *dir, const char *name){ ds->disk = disk; if (NULL == dir) ds->dir = disk->root; else ds->dir = dir; ds->path = name; ds->node = ds->dir; ds->namelen = 0; ds->last = false;}static intfind_direntry(fatfs_dirsearch_t *ds){ int err; cyg_uint32 pos = 0; fatfs_node_t node_data; CYG_TRACE1(TFS, "Finding dir entry '%s'", ds->name); ds->node = fatfs_node_find(ds->disk, ds->name, ds->namelen, ds->dir->cluster); if (ds->node != NULL) { CYG_TRACE1(TFS, "Found dir entry '%s' in cache", ds->name); fatfs_node_touch(ds->disk, ds->node); return ENOERR; } while (true) { err = fatfs_get_dir_entry_node(ds->disk, ds->dir, &pos, &node_data); if (err != ENOERR) return (err == EEOF ? ENOERR : err); if ('\0' == node_data.filename[ds->namelen] && 0 == strncasecmp(node_data.filename, ds->name, ds->namelen)) { CYG_TRACE2(TFS, "Read dir entry '%s' at %d", node_data.filename, pos); ds->node = fatfs_node_alloc(ds->disk, &node_data); if (NULL == ds->node) return ENOMEM; return ENOERR; } pos++; }}static int find_entry(fatfs_dirsearch_t *ds){ int err; const char *name = ds->path; const char *n = name; char namelen = 0; // check that we really have a directory if( !S_ISDIR(ds->dir->mode) ) { CYG_TRACE1(TFS, "Entry '%s' not dir", ds->dir->filename); return ENOTDIR; } // Isolate the next element of the path name. while (*n != '\0' && *n != '/') n++, namelen++; // If we terminated on a NUL, set last flag. if (*n == '\0') ds->last = true; // update name in dirsearch object ds->name = name; ds->namelen = namelen; err = find_direntry(ds); if (err != ENOERR) return err; CYG_TRACE2(TFS, "Entry '%s' %s", name, (ds->node ? "found" : "not found")); if (ds->node != NULL) return ENOERR; else return ENOENT; }static intfatfs_find(fatfs_dirsearch_t *ds){ int err; CYG_TRACE1(TFS, "Find path='%s'", ds->path); // Short circuit empty paths if (*(ds->path) == '\0') return ENOERR; // Iterate down directory tree until we find the object // we want. for(;;) { err = find_entry(ds); if (err != ENOERR) return err; if (ds->last) { CYG_TRACE0(TFS, "Entry found"); return ENOERR; } // Update dirsearch object to search next directory. ds->dir = ds->node; ds->path += ds->namelen; // Skip dirname separators if (*(ds->path) == '/') ds->path++; CYG_TRACE1(TFS, "Find path to go='%s'", ds->path); }}//==========================================================================// Filesystem operations// -------------------------------------------------------------------------// fatfs_mount()// Process a mount request. This mainly creates a root for the// filesystem.static int fatfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte){ cyg_io_handle_t dev_h; Cyg_ErrNo err; fatfs_disk_t *disk; fatfs_node_t root_data; CYG_TRACE2(TFS, "Mount fste=%p mte=%p", fste, mte); CYG_TRACE1(TFS, "Looking up disk device '%s'", mte->devname); err = cyg_io_lookup(mte->devname, &dev_h); if (err != ENOERR) return err; disk = (fatfs_disk_t *)malloc(sizeof(fatfs_disk_t)); if (NULL == disk) return ENOMEM; CYG_TRACE0(TFS, "Initializing FAT table cache"); if (ENOERR != fatfs_tcache_create(disk, CYGNUM_FS_FAT_FAT_TABLE_CACHE_MEMSIZE)) { free(disk); return ENOMEM; } CYG_TRACE0(TFS, "Initializing block cache"); disk->bcache_mem = (cyg_uint8 *)malloc(CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE); if (NULL == disk->bcache_mem) { fatfs_tcache_delete(disk); free(disk); return ENOMEM; } // FIXME: get block size from disk device err = cyg_blib_io_create(dev_h, disk->bcache_mem, CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE, 512, &disk->blib); if (err != ENOERR) { fatfs_tcache_delete(disk); free(disk->bcache_mem); free(disk); return err; } disk->dev_h = dev_h; CYG_TRACE0(TFS, "Initializing disk");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -