?? 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 "kernel.h"#include "fileio.h"#include "cyg_ass.h" // assertion macros#include "types.h"#include "stat.h"#include "codes.h"#include "dirent.h"#include "string.h"#include "malloc.h"#include "io.h"#include "fatfs.h"#include "windows.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);// -------------------------------------------------------------------------// 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; printf( "Finding dir entry '%s'", ds->name); ds->node = fatfs_node_find(ds->disk, ds->name, ds->namelen, ds->dir->cluster); if (ds->node != NULL) { printf( "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)) { printf( "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) ) { printf( "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; printf( "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; printf( "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) { printf( "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++; printf( "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; printf("Mount fste=%p mte=%p", fste, mte); printf("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; printf( "Initializing FAT table cache"); if (ENOERR != fatfs_tcache_create(disk, 10240)) { free(disk); return ENOMEM; } printf( "Initializing block cache"); disk->dev_h = 0; printf( "Initializing disk"); err = fatfs_get_disk_info(disk); if (err != ENOERR) { fatfs_tcache_delete(disk); free(disk); return err; } #if TFS print_disk_info(disk);#endif printf( "Initializing node cache"); fatfs_node_cache_init(disk); printf( "Initializing root node"); fatfs_get_root_node(disk, &root_data); disk->root = fatfs_node_alloc(disk, &root_data); fatfs_node_ref(disk, disk->root); mte->root = (cyg_dir)disk->root; mte->data = (CYG_ADDRWORD)disk; printf( "Disk mounted"); return ENOERR;}// -------------------------------------------------------------------------// fatfs_umount()// Unmount the filesystem. This will currently only succeed if the// filesystem is empty.static intfatfs_umount(cyg_mtab_entry *mte){ fatfs_disk_t *disk = (fatfs_disk_t *)mte->data; fatfs_node_t *root = (fatfs_node_t *)mte->root; printf( "Umount mte=%p %d live nodes %d dead nodes", mte, fatfs_get_live_node_count(disk), fatfs_get_dead_node_count(disk)); if (root->refcnt > 1) return EBUSY; if (fatfs_get_live_node_count(disk) != 1) return EBUSY; fatfs_node_unref(disk, root); fatfs_node_cache_flush(disk); fatfs_tcache_delete(disk); // FIXME: cache delete can fail if cache can't be synced free(disk); mte->root = CYG_DIR_NULL; mte->data = (CYG_ADDRWORD)NULL; printf( "Disk umounted"); return ENOERR;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -