📄 libfat.c
字号:
WORD val; DWORD out; // lo hi if (N%2 == 0) { // XX -X val = 0; ((BYTE *) &val)[0] = (BYTE) V->fat[((int) (N * 1.5))]; ((BYTE *) &val)[1] = (BYTE) V->fat[((int) (N * 1.5)) + 1]; ((BYTE *) &val)[1] &= 0x0F; } else { /* odd X- XX \ \ XX -X */ val =0; ((BYTE *) &val)[0] = (BYTE) V->fat[((int) (N * 1.5))]; ((BYTE *) &val)[1] = (BYTE) V->fat[((int) (N * 1.5)) + 1]; ((BYTE *) &val)[0] = (((BYTE *) &val)[0] >> 4); ((BYTE *) &val)[0] |= (((BYTE *) &val)[1] << 4); ((BYTE *) &val)[1] = (((BYTE *) &val)[1] >> 4); } out = val; *Value = EFD(out); return 0; }static int fat12_write_entry(Volume_t *V, DWORD N, int FatNum, DWORD Value) { WORD val; val = Value; val = EFW(val); // now val is little endian word if (N%2 == 0) { // XX -X : just mix hi byte *((BYTE *) (V->fat + ((int) (N * 1.5)))) = ((BYTE *) &val)[0]; *((BYTE *) (V->fat + ((int) (N * 1.5)) + 1)) &= 0xF0; *((BYTE *) (V->fat + ((int) (N * 1.5)) + 1)) |= ( ((BYTE *) &val)[1] & 0x0F ); } else { // XX -X // / / // X- XX *((BYTE *) (V->fat + ((int) (N * 1.5)))) &= 0x0F; *((BYTE *) (V->fat + ((int) (N * 1.5)))) |= ( (((BYTE *) &val)[0] << 4) ); *((BYTE *) (V->fat + ((int) (N * 1.5)) + 1)) = ( (((BYTE *) &val)[1] << 4) ); *((BYTE *) (V->fat + ((int) (N * 1.5)) + 1)) |= ( (((BYTE *) &val)[0] >> 4) ); }// fprintf(stderr,"fat12_write_entry: N:%u, value:%u\n",N,Value); return 0;}static int fat12_unlinkn(Volume_t *V, DWORD Cluster) { int Res; DWORD Next; int i = 0; if ((fat_isfree(V,Cluster)) || (fat_iseoc(V,Cluster))) return 0; if (fat_isbad(V,Cluster)) return -1; do { /* Read the next entry in the chain */ if ( (Res = fat12_read_entry(V, Cluster, 0, &Next)) != 0 ) { fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i, __LINE__); return -1; } /* Update every FAT in the volume */ if ( (Res = fat12_write_entry(V, Cluster, 0, 0)) != 0 ) { fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i,__LINE__); return -1; } /* Update FSInfo Sector values */ V->freecnt++;// if (Cluster < V->nextfree ) ->nextfree = Cluster; Cluster = Next; i++; } while (!(fat_iseoc(V,Next))); return 0;}/* GENERAL WRAPPERS FOR THE ABOVE FUNCTIONS */static int fat_read_entry(Volume_t *V, DWORD N, int FatNum, DWORD *Value) { if (V->FatType == FAT32) { return fat32_read_entry(V, N, FatNum, Value); } else if (V->FatType == FAT16) { return fat16_read_entry(V, N, FatNum, Value); } else { return fat12_read_entry(V, N, FatNum, Value); } return 0;}#if 0/* Useless atm */static int fat_write_entry(Volume_t *V, DWORD N, int FatNum, DWORD Value) { if (V->FatType == FAT32) { return fat32_write_entry(V, N, FatNum, Value); } else if (V->FatType == FAT16) { return fat16_write_entry(V, N, FatNum, Value); } else { return fat12_write_entry(V, N, FatNum, Value); } return 0;}#endifstatic int fat_writen_entry(Volume_t *V, DWORD N, DWORD Value) { if (V->FatType == FAT32) { return fat32_writen_entry(V, N, Value); } else if (V->FatType == FAT16) { return fat16_write_entry(V, N, 0 ,Value); } else { return fat12_write_entry(V, N, 0, Value); } return 0;}static int fat_unlinkn(Volume_t *V, DWORD Cluster) { if (V->FatType == FAT32) { return fat32_unlinkn(V, Cluster); } else if (V->FatType == FAT16) { return fat16_unlinkn(V, Cluster); } else { return fat12_unlinkn(V, Cluster); } return 0;}/* set the volume as dirty, *//* the routine set the 5th high bit to 0 for dirty flag *//* bitmaks: 0x08000000. */static int fat_mark_dirty(Volume_t *V) { DWORD val; int Res; if (V->FatType == FAT32) { DWORD dirty32 = 0xF7FFFFFF; if ((Res = fat_read_entry(V, 1, 0, &val)) != 0) { perror("fat_read_entry error"); return Res; } val = val & dirty32; if ((Res = fat_writen_entry(V, 1, val)) != 0) { perror("fat_write_entry error"); return -1; } } else if (V->FatType == FAT16) { WORD dirty16 = 0x8000; WORD val16; if ((Res = fat_read_entry(V, 1, 0, &val)) != 0) { perror("fat_read_entry error"); return Res; } val16 = val; val16 = val16 & dirty16; if ((Res = fat_writen_entry(V, 1, (DWORD) val16)) != 0) { perror("fat_write_entry error"); return -1; } } return 0; }/* set the volume as clean, *//* the routine set the 5th high bit to 1 for clean flag *//* bitmaks: 0x08000000. */static int fat_mark_clean(Volume_t *V) { DWORD val; int Res; if (V->FatType == FAT32) { DWORD clean32 = 0x08000000; if ((Res = fat_read_entry(V, 1, 0, &val)) != 0) { perror("fat32_read_entry error"); return Res; } val = val | clean32; if ((Res = fat_writen_entry(V, 1, val)) != 0) { perror("fat32_write_entry error"); return -1; } } else if (V->FatType == FAT16) { WORD clean16 = 0x8000; WORD val16; if ((Res = fat_read_entry(V, 1, 0, &val)) != 0) { perror("fat_read_entry error"); return Res; } val16 = val; val16 = val16 | clean16; if ((Res = fat_writen_entry(V, 1, (DWORD) val16)) != 0) { perror("fat_write_entry error"); return -1; } } return 0; }#endif /* #ifdef FATWRITE *//************************************************************************* Functions to work on Directory entries *************************************************************************/static void printVolumeData(Volume_t *V) { DWORD sz; if (V->FatType == FAT32) { sz = EFD(V->Bpb.BPB_FATSz32); } else { sz = EFW(V->Bpb.BPB_FATSz16); fprintf(stderr,"root dir off : %lld \n", byte_offset(V,1,0)); } fprintf(stderr,"dataclusters :%u \n", V->DataClusters); fprintf(stderr,"first data byte : %lld \n", V->fdb64 ); fprintf(stderr,"1st fat off : %d \n", V->rsvdbytecnt ); fprintf(stderr,"2nd fat off : %d\n", V->rsvdbytecnt+ (sz * V->bps) ); fprintf(stderr,"fat_eoc_value: %u\n", fat_eocvalue(V)); fprintf(stderr,"fat_eoc_value is eoc?: %d\n", fat_iseoc(V,fat_eocvalue(V))); return ;}static int libfat_determine_fattype(Volume_t *V) { int res; off_t fsi_offset; char type[9]; sprintf(type,"FAT12 "); if ((res = memcmp( (char *) &(((char *) &(V->Bpb))[54]), type, 8)) == 0) { V->FatType = FAT12; fprintf(stderr,"fat type: FAT12\n"); return 0; } sprintf(type,"FAT16 "); if ((res = memcmp( (char *) &(((char *) &(V->Bpb))[54]), type, 8)) == 0) { V->FatType = FAT16; fprintf(stderr,"fat type: FAT16\n");return 0; } sprintf(type,"FAT32 "); if ((res = memcmp( (char *) V->Bpb.BS_FilSysType, type, 8)) == 0) { fprintf(stderr,"fat type: FAT32. Fsi at %u\n",EFW(V->Bpb.BPB_FSInfo)); V->FatType = FAT32; fsi_offset = EFW(V->Bpb.BPB_FSInfo) * EFW(V->Bpb.BPB_BytsPerSec); // Only for FAT32 fprintf(stderr,"Fsioff: %d, size: %d\n",(int) fsi_offset, sizeof(FSInfo_t)); if ( (res = lseek(V->blkDevFd, fsi_offset, SEEK_SET)) != fsi_offset ) { perror("FSI lseek() error"); return -1; } if ( (res = readn(V->blkDevFd, &(V->Fsi), sizeof(FSInfo_t))) != sizeof(FSInfo_t) ) { perror("FSI readn() error"); return -1; } fprintf(stderr,"--- nxtfree --- :%u\n",EFD(V->Fsi.FSI_Nxt_Free)); fprintf(stderr,"--- freecnt --- :%u\n",EFD(V->Fsi.FSI_Free_Count)); fflush(stderr); return 0; } /* else */ return -1;/* Now we can determine FAT type *//* if (CountofClusters < 4085) { sprintf(buf,"FAT12"); } else if (CountofClusters < 65525) { sprintf(buf,"FAT16"); } else { sprintf(buf,"FAT32"); }*/}/* load the whole fat into memory for fat12/16 volumes */static int libfat_initialize_fat(Volume_t *V) { int res; int fatsz = 0; // total size of the fat in bytes /* Lets determine the total size of the fat in bytes */ if (V->FatType == FAT16) { fatsz = (V->DataClusters + 2) * sizeof(WORD); } else if (V->FatType == FAT12) { fatsz = ((V->DataClusters + 2) / 2) * 3; if (((V->DataClusters + 2) % 2) != 0) fatsz += 2; } else { fprintf(stderr,"unknown fat type in initialise_fat\n"); return -1; } /* Memory Map or Load/Restore the FAT? Load/restore for the moment */ V->fat = malloc(fatsz); // up to 128k of memory for the biggest fat16 ever. memset(V->fat, 0, fatsz); if ( (res = lseek64(V->blkDevFd, V->rsvdbytecnt, SEEK_SET)) < 0) { fprintf(stderr,"lseek() error in initialize fat(), off:%d\n",V->rsvdbytecnt); return res; } /* read() */ if ( (res = readn(V->blkDevFd, V->fat, fatsz)) != fatsz) { fprintf(stderr,"readn() error in initialize fat. size: %d\n", fatsz); return -1; }/* fprintf(stderr,"\n\n\n\n\n"); for(i=0; i< 200; i++) { fprintf(stderr,"%d: %X ",i,(BYTE) V->fat[i]); // if ((i %2) == 0) fprintf(stderr, " "); } fprintf(stderr,"\n\n\n\n\n"); getc(stdin);*/ /* we have now the whole fat in V->fat. We need to write it down in finalize in all the fat copies in the volume */ return 0;}static int libfat_scan_for_free(Volume_t *V) { int i,res; // int is ok, because this routine is only for fat12/16 int count=0; DWORD val; for (i=2; i<=(V->DataClusters + 1); i++) { if ((res=fat_read_entry(V,i,0,&val)) != 0) { fprintf(stderr,"scan_for_free error\n"); return -1; } if ( fat_isfree(V,val) ) count++; } return count;}static int libfat_initialize_freelist(Volume_t *V) { int res; V->fstfclus=0; V->fclusz=0; if (V->FatType == FAT32) { V->freecnt = EFD(V->Fsi.FSI_Free_Count); V->nextfree = EFD(V->Fsi.FSI_Nxt_Free); if ( !(FAT32_LEGALCLUS(V->nextfree)) || (V->nextfree > (V->DataClusters + 1) ) ) { //to fix 1st condition fprintf(stderr,"invalid next free field: %u\n",V->nextfree); return -1; } if ((res = fat_populate_freelist(V)) <= 0) { perror("populate freelist error"); return -1; } } else { // FAT12 || FAT16 if ((res = libfat_initialize_fat(V)) < 0 ) { fprintf(stderr,"initialize fat error\n"); return -1; } /* we need to scan the fat to find the free cluster count */ V->freecnt = libfat_scan_for_free(V); if (V->freecnt < 0) { fprintf(stderr,"initialize freelist error\n"); return -1; } V->nextfree = 2; } return 0;}/* Initialise a Volume_t structure with the data found in the BootSector *//* NB: the pathname must refer to a valid *FAT32* filesystem and must be *//* canonical name *//* FAT12/16 NOT SUPPORTED right now */int fat_partition_init(Volume_t *V, char *pathname, int flags) { // todo: add uid and gid; DWORD RootDirSectors = 0; // Only for FAT12/16 DWORD FATSz; DWORD FirstDataSector; DWORD TotSec; DWORD CountofClusters; DWORD DataSec; int fd,res;/* Variables we need to read from Boot Sector unsigned short int BPB_RootEntCnt; unsigned short int BPB_BytsPerSec; unsigned short int BPB_FATSz16; unsigned int BPB_FATSz32; unsigned short int BPB_TotSec16; unsigned int BPB_TotSec32; unsigned short int BPB_ResvdSecCnt; unsigned char BPB_NumFATs; unsigned short int BPB_SecPerClus; ------------------------------------------ */ V->uid = 0; //=uid; V->gid = 0; //=gid; V->fat = NULL; if (sizeof(off64_t) < 8) { perror("off64_t not supported properly by this system. the driver wont work properly"); return -1; } if (sizeof(DWORD) != 4) { perror("DWORD not supported properly by this system. the driver wont work properly"); return -1; } if (sizeof(long long int) < 8) { perror("long long int not supported properly by this system. the driver wont work properly"); return -1; }#ifdef FATWRITE if (flags & FAT_WRITE_ACCESS_FLAG) { if ( (fd = open(pathname, O_RDWR)) == -1 ) perror("open() (RDWR) error"); } else { if ( (fd = open(pathname, O_RDONLY)) == -1 ) perror("open() (RDONLY) error"); }#else if ( (fd = open(pathname, O_RDONLY)) == -1 ) perror("open() (RDONLY) error");#endif V->blkDevFd = fd; if ( (res = readn(fd, &(V->Bpb), sizeof(Bpb_t))) != sizeof(Bpb_t)) //we read directly from da disk (NB FAT32 BPB) perror("BPB readn() error");/* -------------------------------------------------------------------- */ if ( V->Bpb.BPB_FATSz16 != 0) { /* 0 is endianess independent */ FATSz = EFW(V->Bpb.BPB_FATSz16); } else { FATSz = EFD(V->Bpb.BPB_FATSz32); } if ( V->Bpb.BPB_TotSec16 != 0) { TotSec = EFW(V->Bpb.BPB_TotSec16); } else { TotSec = EFD(V->Bpb.BPB_TotSec32); } RootDirSectors = (EFW(V->Bpb.BPB_RootEntCnt) * 32) / EFW(V->Bpb.BPB_BytsPerSec) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -