📄 fatfs.c
字号:
/* Volume is FAT32 */ fsc->FatType = TYPE_FAT32; } return (1);}u_int32_t getFatEntry(struct fat_sc *fsc, int entry){ u_int32_t fatsect; u_int32_t byteoffset; u_int32_t fatstart; u_int32_t fatoffset; u_int8_t b1,b2,b3,b4; int res; fatstart = fsc->ResSectors; if (fsc->FatType == TYPE_FAT12) { int odd; odd = entry & 1; byteoffset = ((entry & ~1) * 3) / 2; fatsect = byteoffset / SECTORSIZE; fatoffset = byteoffset % SECTORSIZE; if (fsc->FatCacheNum != fatsect) { res = readsector(fsc, fatsect + fatstart, 1, fsc->FatBuffer); if (res < 0) { return res; } fsc->FatCacheNum = fatsect; } b1 = fsc->FatBuffer[fatoffset]; if ((fatoffset+1) >= SECTORSIZE) { res = readsector(fsc, fatsect + 1 + fatstart, 1, fsc->FatBuffer); if (res < 0) { return res; } fsc->FatCacheNum = fatsect+1; fatoffset -= SECTORSIZE; } b2 = fsc->FatBuffer[fatoffset+1]; if ((fatoffset+2) >= SECTORSIZE) { res = readsector(fsc, fatsect + 1 + fatstart, 1, fsc->FatBuffer); if (res < 0) { return res; } fsc->FatCacheNum = fatsect + 1; fatoffset -= SECTORSIZE; } b3 = fsc->FatBuffer[fatoffset+2]; if (odd) { return ((unsigned int) b3 << 4) + ((unsigned int) (b2 & 0xF0) >> 4); } else { return ((unsigned int) (b2 & 0x0F) << 8) + ((unsigned int) b1); } } else if (fsc->FatType == TYPE_FAT16) { byteoffset = entry * 2; fatsect = byteoffset / SECTORSIZE; fatoffset = byteoffset % SECTORSIZE; if (fsc->FatCacheNum != fatsect) { res = readsector(fsc, fatsect + fatstart, 1, fsc->FatBuffer); if (res < 0) { return res; } fsc->FatCacheNum = fatsect; } b1 = fsc->FatBuffer[fatoffset]; b2 = fsc->FatBuffer[fatoffset+1]; return ((unsigned int) b1) + (((unsigned int) b2) << 8); } else if (fsc->FatType == TYPE_FAT32) { byteoffset = entry * 4; fatsect = byteoffset / SECTORSIZE; fatoffset = byteoffset % SECTORSIZE; if (fsc->FatCacheNum != fatsect) { res = readsector(fsc, fatsect + fatstart, 1, fsc->FatBuffer); if (res < 0) { return res; } fsc->FatCacheNum = fatsect; } b1 = fsc->FatBuffer[fatoffset]; b2 = fsc->FatBuffer[fatoffset+1]; b3 = fsc->FatBuffer[fatoffset+2]; b4 = fsc->FatBuffer[fatoffset+3]; return (((unsigned int) b1) + (((unsigned int) b2) << 8) + (((unsigned int) b3) << 16) + (((unsigned int) b4) << 24)); } return (0);}#define MAX_DIRBUF 10struct direntry dirbuf[MAX_DIRBUF];int fat_findfile(struct fat_sc *fsc, char *name){ struct fat_fileentry filee; struct direntry *dire; char *dpath; int long_name = 0; int dir_scan = 0; int i; bzero(&filee, sizeof(filee)); dpath = strchr(name, '/'); if (dpath != NULL) { *dpath = '\0'; dpath++; dir_scan = 1; } for (fsc->DirCacheNum = fsc->FirstRootDirSecNum; fsc->DirCacheNum < (fsc->RootDirSectors + fsc->FirstRootDirSecNum); fsc->DirCacheNum++) { if (readsector(fsc, fsc->DirCacheNum, 1, fsc->DirBuffer) == 0) { return (0); } dire = (struct direntry *)fsc->DirBuffer; for (i = 0; (i < (SECTORSIZE / sizeof(struct direntry))); i++, dire++) { if (dire->dirName[0] == SLOT_EMPTY) return (0); if (dire->dirName[0] == SLOT_DELETED) continue; if (dire->dirAttributes == ATTR_WIN95) { bcopy((void *)dire, (void *)&dirbuf[long_name], sizeof(struct direntry)); long_name++; if (long_name > MAX_DIRBUF - 1) long_name = 0; continue; } if (dir_scan == 0 && dire->dirAttributes == ATTR_DIRECTORY) { long_name = 0; continue; } bcopy((void *)dire, (void *)&dirbuf[long_name], sizeof(struct direntry)); fat_parseDirEntries(long_name, &filee); if ((strcasecmp(name, filee.shortName) == 0) || (strcasecmp(name, filee.longName) == 0)) { if (dir_scan) { struct fatchain chain; int res; fat_getChain(fsc, letoh16(dire->dirStartCluster), &chain); res = fat_subdirscan(fsc, dpath, &chain); if (chain.entries) { free(chain.entries); } return (res); } else { strcpy(fsc->file.shortName, filee.shortName); fsc->file.HighClust = filee.HighClust; fsc->file.StartCluster = filee.StartCluster; fsc->file.FileSize = filee.FileSize; fat_getChain(fsc, fsc->file.StartCluster, &fsc->file.Chain); return (1); } } } } return (0);}int fat_subdirscan(struct fat_sc *fsc, char *name, struct fatchain *chain){ struct fat_fileentry filee; struct direntry *dire; char *dpath; int long_name = 0; int dir_scan = 0; int sector; int i; int j; int k; bzero(&filee, sizeof(filee)); dpath = strchr(name, '/'); if (dpath != NULL) { *dpath = '\0'; dpath++; dir_scan = 1; } for (i = 0; i < chain->count; i++) { for (j = 0; j < fsc->SecPerClust; j++) { sector = getSectorIndex(fsc, chain, j); if (readsector(fsc, sector, 1, fsc->DirBuffer) == 0) { return (0); } dire = (struct direntry *)fsc->DirBuffer; for (k = 0; (k < (SECTORSIZE / sizeof(struct direntry))); k++, dire++) { if (dire->dirName[0] == SLOT_EMPTY) return (0); if (dire->dirName[0] == SLOT_DELETED) continue; if (dire->dirAttributes == ATTR_WIN95) { bcopy((void *)dire, (void *)&dirbuf[long_name], sizeof(struct direntry)); long_name++; if (long_name > MAX_DIRBUF - 1) long_name = 0; continue; } if (dir_scan == 0 && dire->dirAttributes == ATTR_DIRECTORY) { long_name = 0; continue; } bcopy((void *)dire, (void *)&dirbuf[long_name], sizeof(struct direntry)); fat_parseDirEntries(long_name, &filee); if ((strcasecmp(name, filee.shortName) == 0) || (strcasecmp(name, filee.longName) == 0)) { if (dir_scan) { struct fatchain chain; int res; fat_getChain(fsc, letoh16(dire->dirStartCluster), &chain); res = fat_subdirscan(fsc, dpath, &chain); if (chain.entries) { free(chain.entries); } return (res); } else { strcpy(fsc->file.shortName, filee.shortName); fsc->file.HighClust = filee.HighClust; fsc->file.StartCluster = filee.StartCluster; fsc->file.FileSize = filee.FileSize; fat_getChain(fsc, fsc->file.StartCluster, &fsc->file.Chain); return (1); } } } } } return (0);}int fat_parseDirEntries(int dirc, struct fat_fileentry *filee){ struct direntry *dire; struct winentry *wine; u_int8_t longName[290]; u_int8_t chksum; int c = 0; int i; dire = &dirbuf[dirc]; filee->HighClust = letoh16(dire->dirHighClust); filee->StartCluster = letoh16(dire->dirStartCluster); filee->FileSize = letoh32(dire->dirFileSize); parseShortFilename(dire, filee->shortName); chksum = shortNameChkSum(filee->shortName); if (dirc != 0) { u_int8_t buffer[26]; u_int16_t *bp; int j = 0; for (i = dirc; i != 0; i--) { wine = (struct winentry *)&dirbuf[i-1]; bzero(buffer, sizeof(buffer)); bcopy(wine->wePart1, &buffer[0], sizeof(wine->wePart1)); bcopy(wine->wePart2, &buffer[sizeof(wine->wePart1)], sizeof(wine->wePart2)); bcopy(wine->wePart3, &buffer[sizeof(wine->wePart1) + sizeof(wine->wePart2)], sizeof(wine->wePart3)); bp = (u_int16_t *)buffer; for (j = 0; j < 14; j++, c++) { longName[c] = (u_int8_t)letoh16(bp[j]); if (longName[c] == '\0') goto done; } } done: strcpy(filee->longName, longName); } return (1);}u_int8_t shortNameChkSum(u_int8_t *name){ u_int16_t len; u_int8_t sum; sum = 0; for (len = 11; len != 0; len--) { sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *name++; } return (sum); }int fat_getChain(struct fat_sc *fsc, int start, struct fatchain *chain){ u_int32_t mask; u_int32_t entry; int count; int i; switch (fsc->FatType) { case TYPE_FAT12: mask = FAT12_MASK; break; case TYPE_FAT16: mask = FAT16_MASK; break; case TYPE_FAT32: mask = FAT32_MASK; break; default: mask = 0; } for (count = 0; 1; count++) { entry = getFatEntry(fsc, start + count); if (entry >= (CLUST_EOFE & mask)) break; } chain->count = count + 1; chain->start = start; chain->entries = (u_int32_t *)malloc(sizeof(u_int32_t) * chain->count); if (chain->entries == NULL) { return (-1); } chain->entries[0] = start; for (i = 0; i < count; i++) { chain->entries[i+1] = getFatEntry(fsc, start + i); } return (1);}int parseShortFilename(struct direntry *dire, char *name){ int j; for (j = 0; j < 8; j++) { if (dire->dirName[j] == ' ') break; *name++ = dire->dirName[j]; } if (dire->dirExtension[0] != ' ') *name++ = '.'; for (j = 0; j < 3; j++) { if (dire->dirExtension[j] == ' ') break; *name++ = dire->dirExtension[j]; } *name = '\0'; return (-1);}int readsector(struct fat_sc *fsc, int sector, int count, u_int8_t *buffer){ int res; res = lseek(fsc->fd, (sector * SECTORSIZE + (fsc->PartitionStart * SECTORSIZE)), SEEK_SET); res = read(fsc->fd, buffer, (SECTORSIZE * count)); if (res == (SECTORSIZE * count)) { return (1); } else { return (-1); }}#ifdef FAT_DEBUGint fat_dump_fatsc(struct fat_sc *fsc){ printf("Bytes per Sector = %d\n", fsc->BytesPerSec); printf("Sectors Per Cluster = %d\n", fsc->SecPerClust); printf("Number of reserved sectors = %d\n", fsc->ResSectors); printf("Number of FATs = %d\n", fsc->NumFATs); printf("Number of Root directory entries = %d\n", fsc->RootDirEnts); printf("Total number of sectors = %d\n", fsc->TotalSectors); printf("Number of sectors per FAT = %d\n", fsc->FATsecs); printf("Sectors per track = %d\n", fsc->SecPerTrack); printf("Number of hidden sectors = %d\n", fsc->HiddenSecs); printf("Number of Root directory sectors = %d\n", fsc->RootDirSectors); printf("Count of clusters = %d\n", fsc->CountOfClusters); printf("Clustersize = %d\n", fsc->ClusterSize); printf("First Root directory sector = %d\n", fsc->FirstRootDirSecNum); printf("Total Data Sectors = %d\n", fsc->DataSectors); printf("Data Sector base = %d\n", fsc->DataSectorBase); return (1);}int fat_dump_fileentry(struct fat_sc *fsc){ int i; printf(" File: %s\n", fsc->file.Name); printf(" HighClust: %d\n", fsc->file.HighClust); printf("StartCluster: %d\n", fsc->file.StartCluster); printf(" FileSize: %d\n", fsc->file.FileSize); if (fsc->file.Chain.count) { printf("Cluster chain: "); for (i = 0; i < fsc->file.Chain.count; i++) { printf("0x%08x ", fsc->file.Chain.entries[i]); } printf("\n"); } return (1);}#endif /* FAT_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -