📄 fatfs.c
字号:
/* $Id: fatfs.c,v 1.1 2003/07/08 20:57:50 pefo Exp $ *//* * Copyright (c) 2003 Opsycon AB (www.opsycon.se) * Copyright (c) 2003 Patrik Lindergren (www.lindergren.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Opsycon AB, Sweden. * This product includes software developed by Patrik Lindergren. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include <stdio.h>#include <string.h>#include <termio.h>#include <fcntl.h>#include <file.h>#include <ctype.h>#include <ramfile.h>#include <sys/unistd.h>#include <stdlib.h>#include <unistd.h>#undef _KERNEL#include <errno.h>#include <pmon.h>#include <file.h>#include "fat.h"extern int errno;int fat_open (int, const char *, int, int);int fat_close (int);int fat_read (int, void *, size_t);int fat_write (int, const void *, size_t);off_t fat_lseek (int, off_t, int);/* * Internal */int fat_init(int , struct fat_sc *, int);int fat_dump_fatsc(struct fat_sc *);u_int32_t getFatEntry(struct fat_sc *, int );int readsector(struct fat_sc *, int , int , u_int8_t *);int parseShortFilename(struct direntry *, char *);int fat_getChain(struct fat_sc *, int , struct fatchain *);int getSectorIndex(struct fat_sc *, struct fatchain *, int );int fat_getPartition(struct fat_sc *, int );int fat_findfile(struct fat_sc *, char *);int fat_subdirscan(struct fat_sc *, char *, struct fatchain *);int fat_dump_fatsc(struct fat_sc *);int fat_dump_fileentry(struct fat_sc *);u_int8_t shortNameChkSum(u_int8_t *);int fat_parseDirEntries(int ,struct fat_fileentry *);/* * Supported paths: * /dev/fat/disk@wd0/file * /dev/fat/ram@address/file * */intfat_open(int fd, const char *path, int flags, int mode){ char dpath[64]; char dpath2[64]; const char *opath; char *filename; struct fat_sc *fsc; int fd2; int res; /* Try to get to the physical device */ opath = path; if (strncmp(opath, "/dev/", 5) == 0) opath += 5; if (strncmp(opath, "fat/", 4) == 0) opath += 4; /* There has to be at least one more component after the devicename */ if (strchr(opath, '/') == NULL) { errno = ENOENT; return (-1); } /* Dig out the device name */ strncpy(dpath2, opath, sizeof(dpath2)); *(strchr(dpath2, '/')) = '\0'; sprintf(dpath, "/dev/%s", dpath2); /* Set opath to point at the isolated filname path */ filename = strchr(opath, '/') + 1; fsc = (struct fat_sc *)malloc(sizeof(struct fat_sc)); if (fsc == NULL) { errno = ENOMEM; return (-1); } /* * Need to mark existing fd to valid otherwise we can't * open the new device. */ _file[fd].valid = 1; /* Try to open the physical device */ fd2 = open(dpath, flags, mode); if (fd2 < 0) { free(fsc); errno = EINVAL; _file[fd].valid = 0; return (-1); } if (fat_init(fd2, fsc, 0) == 0) { close(fd2); free(fsc); errno = EINVAL; _file[fd].valid = 0; return (-1); } res = fat_findfile(fsc, filename); if (res <= 0) { close(fd2); free(fsc); errno = EINVAL; _file[fd].valid = 0; return (-1); } fsc->LastSector = -1; /* No valid sector in sector buffer */ _file[fd].posn = 0; _file[fd].data = (void *)fsc; return (fd);}intfat_close(int fd){ struct fat_sc *fsc; fsc = (struct fat_sc *)_file[fd].data; if (fsc->file.Chain.entries) { free(fsc->file.Chain.entries); fsc->file.Chain.entries = NULL; } fsc->file.Chain.count = 0; close(fsc->fd); free(fsc); return (0);}intfat_read(int fd, void *buf, size_t len){ struct fat_sc *fsc; int sectorIndex; int totalcopy = 0; int origpos; int copylen; int offset; int sector; int res = 0; fsc = (struct fat_sc *)_file[fd].data; origpos = _file[fd].posn; /* * Check file size bounder */ if (_file[fd].posn >= fsc->file.FileSize) { return (-1); } if ((_file[fd].posn + len) > fsc->file.FileSize) { len = fsc->file.FileSize - _file[fd].posn; } while (len) { offset = _file[fd].posn % SECTORSIZE; sectorIndex = _file[fd].posn / SECTORSIZE; sector = getSectorIndex(fsc, &fsc->file.Chain, sectorIndex); copylen = len; if (copylen > (SECTORSIZE - offset)) { copylen = (SECTORSIZE - offset); } if (sector != fsc->LastSector) { res = readsector(fsc, sector, 1, fsc->LastSectorBuffer); if (res < 0) break; fsc->LastSector = sector; } memcpy(buf, &fsc->LastSectorBuffer[offset], copylen); buf += copylen; _file[fd].posn += copylen; len -= copylen; totalcopy += copylen; } if (res < 0) { _file[fd].posn = origpos; return res; } return totalcopy;}intfat_write(int fd, const void *start, size_t size){ errno = EROFS; return EROFS;}off_tfat_lseek(int fd, off_t offset, int whence){ struct fat_sc *fsc; fsc = (struct fat_sc *)_file[fd].data; switch (whence) { case SEEK_SET: _file[fd].posn = offset; break; case SEEK_CUR: _file[fd].posn += offset; break; case SEEK_END: _file[fd].posn = fsc->file.FileSize + offset; break; default: errno = EINVAL; return (-1); } return (_file[fd].posn);}/* * File system registration info. */static FileSystem fatfs = { "fat", FS_FILE, fat_open, fat_read, fat_write, fat_lseek, fat_close, NULL};static void init_fs(void) __attribute__ ((constructor));static voidinit_fs(){ filefs_init(&fatfs);}/*************************************************************************************************** * Internal function ***************************************************************************************************/int getSectorIndex(struct fat_sc *fsc, struct fatchain * chain, int index){ int clusterIndex; int sectorIndex; int sector; int entry; clusterIndex = index / fsc->SecPerClust; sectorIndex = index % fsc->SecPerClust; if (clusterIndex < chain->count) entry = chain->entries[clusterIndex]; else entry = -1; sector = fsc->DataSectorBase + (entry - 2) * fsc->SecPerClust + sectorIndex; return (sector);}int fat_getPartition(struct fat_sc *fsc, int partition){ u_int8_t buffer[SECTORSIZE]; struct mbr_t *mbr; struct bpb_t *bpb; int i; fsc->PartitionStart = 0; if (readsector(fsc, 0, 1, buffer) == 0) return (0); /* * Check if there exists a MBR */ bpb = (struct bpb_t *)buffer; #if 0 if ((bpb->bpbBytesPerSec == 512) && ((bpb->efat16.bsBootSig == BPB_SIG_VALUE1) || (bpb->efat16.bsBootSig == BPB_SIG_VALUE2))) { /* * No MBR where found */ return (1); }#endif if ((bpb->bpbBytesPerSec == 512) && (bpb->bpbResSectors >= 1) && ((bpb->bpbMedia & 0xf0) == 0xf0)) { /* * No MBR where found */ return (1); } /* * Find the active partition */ mbr = (struct mbr_t *)buffer; for (i = 0; i < PART_SIZE; i++) { if ((mbr->partition[i].bootid == PART_BOOTID_ACTIVE) && ((mbr->partition[i].systid == PART_TYPE_FAT12) || (mbr->partition[i].systid == PART_TYPE_FAT16) || (mbr->partition[i].systid == PART_TYPE_FAT16BIG))) { break; } } if (i == PART_SIZE) { return (0); } fsc->PartitionStart = letoh32(mbr->partition[i].relsect); return (1);}int fat_init(int fd, struct fat_sc *fsc, int partition){ unsigned char bootsector[SECTORSIZE]; struct bpb_t *bpb; bzero(fsc, sizeof(struct fat_sc)); fsc->fd = fd; /* * Check for partition */ fat_getPartition(fsc, partition); /* * Init BPB */ if (readsector(fsc, 0, 1, bootsector) == 0) { fprintf(stderr, "Can't read from %d bytes\n", SECTORSIZE); return (-1); } bpb = (struct bpb_t *)bootsector; /* * Init Fat Software structure */ fsc->RootDirEnts = letoh16(bpb->bpbRootDirEnts); fsc->BytesPerSec = letoh16(bpb->bpbBytesPerSec); fsc->ResSectors = letoh16(bpb->bpbResSectors); fsc->SecPerClust = bpb->bpbSecPerClust; fsc->NumFATs = bpb->bpbFATs; fsc->FatCacheNum = -1; if (bpb->bpbFATsecs != 0) fsc->FATsecs = (u_int32_t)letoh16(bpb->bpbFATsecs); else fsc->FATsecs = letoh32(bpb->efat32.bpbFATSz32); if (bpb->bpbSectors != 0) fsc->TotalSectors = (u_int32_t)letoh16(bpb->bpbSectors); else fsc->TotalSectors = letoh32(bpb->bpbHugeSectors); fsc->RootDirSectors = ((fsc->RootDirEnts * 32) + (fsc->BytesPerSec - 1)) / fsc->BytesPerSec; fsc->DataSectors = fsc->TotalSectors - (fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs) + fsc->RootDirSectors); fsc->DataSectorBase = fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs) + fsc->RootDirSectors; fsc->CountOfClusters = fsc->DataSectors / fsc->SecPerClust; fsc->ClusterSize = fsc->BytesPerSec * fsc->SecPerClust; fsc->FirstRootDirSecNum = fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs); if (fsc->CountOfClusters < 4085) { /* Volume is FAT12 */ fsc->FatType = TYPE_FAT12; } else if (fsc->CountOfClusters < 65525) { /* Volume is FAT16 */ fsc->FatType = TYPE_FAT16; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -