📄 fat_driver.c
字号:
#ifdef DEBUG //debug printf("SEEK CLUSTER CHAIN CACHE fileSize=%i blockSize=%i \n", fatDir->size, blockSize); for (i = 0; i < DIR_CHAIN_SIZE; i++) { printf("index=%i cluster=%i offset= %i - %i start=%i \n", fatDir->chain[i].index, fatDir->chain[i].cluster, fatDir->chain[i].index * bpb->clusterSize * bpb->sectorSize, (fatDir->chain[i].index+1) * bpb->clusterSize * bpb->sectorSize, i * blockSize); }#endif /* debug */ XPRINTF("FAT driver: read cluster chain done!\n");}/* Set base attributes of direntry */void fat_setFatDir(fat_bpb* bpb, fat_dir* fatDir, fat_direntry_sfn* dsfn, fat_direntry* dir, int getClusterInfo ) { int i; unsigned char* srcName; XPRINTF("setting fat dir...\n"); srcName = dir->sname; if (dir->name[0] != 0) { //long filename not empty srcName = dir->name; } //copy name for (i = 0; srcName[i] != 0; i++) fatDir->name[i] = srcName[i]; fatDir->name[i] = 0; //terminate fatDir->attr = dsfn->attr; fatDir->size = dir->size; //Date: Day, Month, Year-low, Year-high fatDir->date[0] = (dsfn->dateWrite[0] & 0x1F); fatDir->date[1] = (dsfn->dateWrite[0] >> 5) + ((dsfn->dateWrite[1] & 0x01) << 3 ); i = 1980 + (dsfn->dateWrite[1] >> 1); fatDir->date[2] = (i & 0xFF); fatDir->date[3] = ((i & 0xFF00)>> 8); //Time: Hours, Minutes, Seconds fatDir->time[0] = ((dsfn->timeWrite[1] & 0xF8) >> 3); fatDir->time[1] = ((dsfn->timeWrite[1] & 0x07) << 3) + ((dsfn->timeWrite[0] & 0xE0) >> 5); fatDir->time[2] = ((dsfn->timeWrite[0] & 0x1F) << 1); fatDir->chain[0].cluster = dir->cluster; fatDir->chain[0].index = 0; if (getClusterInfo) { fat_setFatDirChain(bpb, fatDir); }}int fat_getDirentrySectorData(fat_bpb* bpb, unsigned int* startCluster, unsigned int* startSector, int* dirSector) { int chainSize; if (*startCluster == 0 && bpb->fatType < FAT32) { //Root directory *startSector = bpb->rootDirStart; *dirSector = bpb->rootSize / (bpb->sectorSize / 32); return 0; } //other directory or fat 32 if (*startCluster == 0 && bpb->fatType == FAT32) { *startCluster = bpb->rootDirCluster; } *startSector = fat_cluster2sector(bpb, *startCluster); chainSize = fat_getClusterChain(bpb, *startCluster, cbuf, MAX_DIR_CLUSTER, 1); if (chainSize > 0) { *dirSector = chainSize * bpb->clusterSize; } else { printf("FAT driver: Error getting cluster chain! startCluster=%i \n", *startCluster); return -1; }#ifdef DEBUG fat_dumpClusterChain(cbuf, chainSize, 0);#endif return chainSize;}int fat_getDirentryStartCluster(fat_bpb* bpb, unsigned char* dirName, unsigned int* startCluster, fat_dir* fatDir) { fat_direntry_sfn* dsfn; fat_direntry_lfn* dlfn; fat_direntry dir; int i, j; int dirSector; unsigned int startSector; int cont; int ret; int dirPos; int clusterMod; cont = 1; XPRINTF("\n"); XPRINTF("getting cluster for dir entry: %s \n", dirName); clusterMod = bpb->clusterSize - 1; //clear name strings dir.sname[0] = 0; dir.name[0] = 0; fat_getDirentrySectorData(bpb, startCluster, &startSector, &dirSector); XPRINTF("dirCluster=%i startSector=%i (%i) dirSector=%i \n", *startCluster, startSector, startSector * Size_Sector, dirSector); //go through first directory sector till the max number of directory sectors //or stop when no more direntries detected for (i = 0; i < dirSector && cont; i++) { ret = READ_SECTOR(startSector + i, sbuf); if (ret < 0) { printf("FAT driver: read directory sector failed ! sector=%i\n", startSector + i); return FAT_ERROR; } XPRINTF("read sector ok, scanning sector for direntries...\n"); //get correct sector from cluster chain buffer if ((*startCluster != 0) && (i % bpb->clusterSize == clusterMod)) { startSector = fat_cluster2sector(bpb, cbuf[(i / bpb->clusterSize) + 1]); startSector -= (i+1); } dirPos = 0; // go through start of the sector till the end of sector while (cont && dirPos < bpb->sectorSize) { dsfn = (fat_direntry_sfn*) (sbuf + dirPos); dlfn = (fat_direntry_lfn*) (sbuf + dirPos); cont = fat_getDirentry(dsfn, dlfn, &dir); //get single directory entry from sector buffer if (cont == 1) { //when short file name entry detected if (!(dir.attr & 0x08)) { //not volume label if ((strEqual(dir.sname, dirName) == 0) || (strEqual(dir.name, dirName) == 0) ) { XPRINTF("found! %s\n", dir.name); if (fatDir != NULL) { //fill the directory properties fat_setFatDir(bpb, fatDir, dsfn, &dir, 1); } *startCluster = dir.cluster; XPRINTF("direntry %s found at cluster: %i \n", dirName, dir.cluster); return dir.attr; //returns file or directory attr } } //clear name strings dir.sname[0] = 0; dir.name[0] = 0; } dirPos += 32; //directory entry of size 32 bytes } } XPRINTF("direntry %s not found! \n", dirName); return -EFAULT;}// start cluster should be 0 - if we want to search from root directory// otherwise the start cluster should be correct cluster of directory// to search directory - set fatDir as NULLint fat_getFileStartCluster(fat_bpb* bpb, const char* fname, unsigned int* startCluster, fat_dir* fatDir) { unsigned char tmpName[257]; int i; int offset; int cont; int ret; cont = 1; offset = 0; i=0; if (fname[i] == '/' || fname[i] == '\\' ) { i++; } for ( ; fname[i] !=0; i++) { if (fname[i] == '/' || fname[i] == '\\') { //directory separator tmpName[offset] = 0; //terminate string ret = fat_getDirentryStartCluster(bpb, tmpName, startCluster, fatDir); if (ret < 0) { return -ENOENT; } offset = 0; } else{ tmpName[offset] = fname[i]; offset++; } } //and the final file if (fatDir != NULL) { //if the last char of the name was slash - the name was already found -exit if (offset == 0 && i > 1) { return 1; } tmpName[offset] = 0; //terminate string ret = fat_getDirentryStartCluster(bpb, tmpName, startCluster, fatDir); if (ret < 0) { return ret; } XPRINTF("file's startCluster found. Name=%s, cluster=%i \n", fname, *startCluster); } return 1;}void fat_getClusterAtFilePos(fat_bpb* bpb, fat_dir* fatDir, unsigned int filePos, unsigned int* cluster, unsigned int* clusterPos) { int i; int blockSize; int j = (DIR_CHAIN_SIZE-1); blockSize = bpb->clusterSize * bpb->sectorSize; for (i = 0; i < (DIR_CHAIN_SIZE-1); i++) { if (fatDir->chain[i].index * blockSize <= filePos && fatDir->chain[i+1].index * blockSize > filePos) { j = i; break; } } *cluster = fatDir->chain[j].cluster; *clusterPos = (fatDir->chain[j].index * blockSize);}int fat_readFile(fat_bpb* bpb, fat_dir* fatDir, unsigned int filePos, unsigned char* buffer, int size) { int ret; int i,j; int chainSize; int nextChain; int startSector; int bufSize; int sectorSkip; int clusterSkip; int dataSkip; unsigned int bufferPos; unsigned int fileCluster; unsigned int clusterPos; int clusterChainStart; fat_getClusterAtFilePos(bpb, fatDir, filePos, &fileCluster, &clusterPos); sectorSkip = (filePos - clusterPos) / bpb->sectorSize; clusterSkip = sectorSkip / bpb->clusterSize; sectorSkip %= bpb->clusterSize; dataSkip = filePos % bpb->sectorSize; bufferPos = 0; XPRINTF("fileCluster = %i, clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i \n", fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip); if (fileCluster < 2) { return 0; } bufSize = SECTOR_SIZE; nextChain = 1; clusterChainStart = 1; while (nextChain && size > 0 ) { chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart); clusterChainStart = 0; if (chainSize == 0) { //the chain is full, but more chain parts exist chainSize = MAX_DIR_CLUSTER; fileCluster = cbuf[MAX_DIR_CLUSTER - 1]; }else { //chain fits in the chain buffer completely - no next chain needed nextChain = 0; } while (clusterSkip >= MAX_DIR_CLUSTER) { chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart); clusterChainStart = 0; if (chainSize == 0) { //the chain is full, but more chain parts exist chainSize = MAX_DIR_CLUSTER; fileCluster = cbuf[MAX_DIR_CLUSTER - 1]; }else { //chain fits in the chain buffer completely - no next chain needed nextChain = 0; } clusterSkip -= MAX_DIR_CLUSTER; }#ifdef DEBUG fat_dumpClusterChain(cbuf, chainSize, clusterSkip); printf("fileCluster = %i, clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i filePos=%i \n", fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip, filePos);#endif //process the cluster chain (cbuf) and skip leading clusters if needed for (i = 0 + clusterSkip; i < chainSize && size > 0; i++) { //read cluster and save cluster content startSector = fat_cluster2sector(bpb, cbuf[i]); //process all sectors of the cluster (and skip leading sectors if needed) for (j = 0 + sectorSkip; j < bpb->clusterSize && size > 0; j++) { ret = READ_SECTOR(startSector + j, sbuf); if (ret < 0) { printf("Read sector failed ! sector=%i\n", startSector + j); return bufferPos; } //compute exact size of transfered bytes if (size < bufSize) { bufSize = size + dataSkip; } if (bufSize > SECTOR_SIZE) { bufSize = SECTOR_SIZE; } XPRINTF("memcopy dst=%i, src=%i, size=%i bufSize=%i \n", bufferPos, dataSkip, bufSize-dataSkip, bufSize); MEMCPY(buffer+bufferPos, sbuf + dataSkip, bufSize - dataSkip); size-= (bufSize - dataSkip); bufferPos += (bufSize - dataSkip); dataSkip = 0; bufSize = SECTOR_SIZE; } sectorSkip = 0; } clusterSkip = 0; } return bufferPos;}int fat_mountCheck() { int mediaStatus; int ret;#ifdef _PS2_ mediaStatus = mass_stor_getStatus(); if (mediaStatus < 0) { mounted = 0; return mediaStatus; } if ((mediaStatus & 0x03) == 3) { /* media is ready for operation */ /* in the meantime the media was reconnected and maybe changed - force unmount*/ if ((mediaStatus & 0x04) == 4) { mounted = 0; } if (mounted) { /* and is mounted */ return 1; } ret = fat_initDriver(); return ret; } if (mounted) { /* fs mounted but media is not ready - force unmount */ mounted = 0; } return -10;#else return 1;#endif}int fat_getNextDirentry(fat_dir* fatDir) { fat_bpb* bpb; fat_direntry_sfn* dsfn; fat_direntry_lfn* dlfn; fat_direntry dir; int i, j; int dirSector; unsigned int startSector; int cont = 1; int ret; int dirPos; int clusterMod; int index; unsigned int dirCluster; //the getFirst function was not called if (direntryCluster == 0xFFFFFFFF || fatDir == NULL) { return -2; } bpb = &partBpb; dirCluster = direntryCluster; index = 0; clusterMod = bpb->clusterSize - 1; //clear name strings dir.sname[0] = 0; dir.name[0] = 0; fat_getDirentrySectorData(bpb, &dirCluster, &startSector, &dirSector); XPRINTF("dirCluster=%i startSector=%i (%i) dirSector=%i \n", dirCluster, startSector, startSector * Size_Sector, dirSector); //go through first directory sector till the max number of directory sectors //or stop when no more direntries detected for (i = 0; i < dirSector && cont; i++) { ret = READ_SECTOR(startSector + i, sbuf); if (ret < 0) { printf("Read directory sector failed ! sector=%i\n", startSector + i); return -3; } //get correct sector from cluster chain buffer if ((dirCluster != 0) && (i % bpb->clusterSize == clusterMod)) { startSector = fat_cluster2sector(bpb, cbuf[(i / bpb->clusterSize) + 1]); startSector -= (i+1); } dirPos = 0; // go through start of the sector till the end of sector while (cont && dirPos < bpb->sectorSize) { dsfn = (fat_direntry_sfn*) (sbuf + dirPos); dlfn = (fat_direntry_lfn*) (sbuf + dirPos); cont = fat_getDirentry(dsfn, dlfn, &dir); //get single directory entry from sector buffer if (cont == 1) { //when short file name entry detected index++; if ((index-1) == direntryIndex) { direntryIndex++; fat_setFatDir(bpb, fatDir, dsfn, &dir, 0); return 1; } //clear name strings dir.sname[0] = 0; dir.name[0] = 0; } dirPos += 32; //directory entry of size 32 bytes } } // when we get this far - reset the direntry cluster direntryCluster = 0xFFFFFFFF; //no more files return -1; //indicate that no direntry is avalable}int fat_getFirstDirentry(char * dirName, fat_dir* fatDir) { int ret; unsigned int startCluster = 0; ret = fat_mountCheck(); if (ret < 0) { return ret; } if ( ((dirName[0] == '/' || dirName[0]=='\\') && dirName[1] == 0) || // the root directory dirName[0] == 0 || dirName == NULL) { direntryCluster = 0; } else { ret = fat_getFileStartCluster(&partBpb, dirName, &startCluster, fatDir); if (ret < 0) { //dir name not found return -4; } //check that direntry is directory if ((fatDir->attr & 0x10) == 0) { return -3; //it's a file - exit } direntryCluster = startCluster; } direntryIndex = 0; return fat_getNextDirentry(fatDir);}int fat_initDriver() { int ret; lastChainCluster = 0xFFFFFFFF; lastChainResult = -1; direntryCluster = 0xFFFFFFFF; direntryIndex = 0; ret = DISK_INIT("disk1.bin", Size_Sector); // modified by Hermes if (ret < 0) { printf ("fat_driver: disk init failed \n" ); return ret; } fat_getPartitionTable(&partTable); fat_getPartitionBootSector(&partTable.record[workPartition], &partBpb);#ifdef DEBUG fat_dumpPartitionTable(); fat_dumpPartitionBootSector();#endif fs_init(NULL); mounted = 1;}void fat_closeDriver() { DISK_CLOSE();}fat_bpb* fat_getBpb() { return &partBpb;}/*************************************************************************************//* File IO functions *//*************************************************************************************/#ifdef _PS2_int nameSignature;int removalTime;int removalResult;#endif /* __PS2_ */typedef struct { int status; fat_dir fatdir;} D_PRIVATE;int fs_findFreeFileSlot(int fd) { int i; int result = -1; for (i = 0; i < MAX_FILES; i++) { if (fsRec[i].fd == fd) { result = i; break; } } return result;}int fs_findFileSlot(iop_file_t* file) { int i; int result = -1; fs_rec* rec = (fs_rec*)file->privdata; int fd = rec->fd; for (i = 0; i < MAX_FILES; i++) { if (fsRec[i].fd == fd) { result = i; break; } } return result;}int fs_findFileSlotByName(const char* name) { int i; int result = -1; for (i = 0; i < MAX_FILES; i++) { if (fsRec[i].fd >= 0 && strEqual(fsDir[i].name, (unsigned char*) name) == 0) { result = i; break; } } return result;}int fs_init(iop_device_t *driver) { int i; mounted = 0; for (i = 0; i < MAX_FILES; i++) { fsRec[i].fd = -1; } return 1;}int fs_open(iop_file_t* fd, const char *name, int mode, ...) { int index, index2; int mode2; int ret; unsigned int cluster; char escapeNotExist; XPRINTF("fs_open called: %s mode=%X \n", name, mode) ; //check if media mounted ret = fat_mountCheck(); if (ret < 0) { return ret; }#ifndef WRITE_SUPPORT //read only support if (mode != 0 && mode != O_RDONLY) { //correct O_RDONLY number? XPRINTF("mode (%d) != O_RDONLY (%d) \n", mode, O_RDONLY); return -EROFS; } #endif //check if the slot is free index = fs_findFreeFileSlot(-1); if (index < 0) return -EMFILE;#ifdef WRITE_SUPPORT //check if the file is already open index2 = fs_findFileSlotByName(name); //file already open if (index2 >= 0) { mode2 = fsRec[index2].mode; if ( (mode & O_RDWR || mode & O_WRONLY) || //current file is opened for write (mode2 & O_RDWR || mode2 & O_WRONLY) ) {//other file is opened for write return -EACCES; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -