📄 fat_driver.c
字号:
} if (mode & O_RDWR || mode & O_WRONLY) { cluster = 0; //start from root escapeNotExist = 1; if (mode & O_CREAT) { XPRINTF("FAT I: O_CREAT detected!\n"); escapeNotExist = 0; } fsRec[index].sfnSector = 0; fsRec[index].sfnOffset = 0; ret = fat_createFile(&partBpb, name, 0, escapeNotExist, &cluster, &fsRec[index].sfnSector, &fsRec[index].sfnOffset); if (ret < 0) { return ret; } //the file already exist but mode is set to truncate if (ret == 2 && (mode & O_TRUNC)) { XPRINTF("FAT I: O_TRUNC detected!\n"); fat_truncateFile(&partBpb, cluster, fsRec[index].sfnSector, fsRec[index].sfnOffset); } }#endif /*WRITE_SUPPORT */ //find the file cluster = 0; //allways start from root ret = fat_getFileStartCluster(&partBpb, name, &cluster, &fsDir[index]); if (ret < 0) { return ret; } //store fd to file slot fsCounter++; fsRec[index].fd = fsCounter; //fd fsRec[index].mode = mode; fsRec[index].filePos = 0; fsRec[index].sizeChange = 0;#ifdef WRITE_SUPPORT if ((mode & O_APPEND) && (mode & O_RDWR || mode & O_WRONLY)) { XPRINTF("FAT I: O_APPEND detected!\n"); fsRec[index].filePos = fsDir[index].size; }#endif /*WRITE_SUPPORT */ //store the slot to user parameters fd->privdata = &fsRec[index]; return fsCounter;}int fs_close(iop_file_t* fd) { int index; index = fs_findFileSlot(fd); if (index < 0) { return -EFAULT; } fsRec[index].fd = -1;#ifdef WRITE_SUPPORT if (fsRec[index].mode & O_RDWR || fsRec[index].mode & O_WRONLY) { //update direntry size and time if (fsRec[index].sizeChange) { fat_updateSfn(fsDir[index].size, fsRec[index].sfnSector, fsRec[index].sfnOffset); } FLUSH_SECTORS(); }#endif /*WRITE_SUPPORT */ return 0;}int fs_lseek(iop_file_t* fd, unsigned long offset, int whence) { int index; index = fs_findFileSlot(fd); if (index < 0) { return -EFAULT; } switch(whence) { case SEEK_SET: fsRec[index].filePos = offset; break; case SEEK_CUR: fsRec[index].filePos += offset; break; case SEEK_END: fsRec[index].filePos = fsDir[index].size + offset; break; default: return -1; } if (fsRec[index].filePos < 0) { fsRec[index].filePos = 0; } if (fsRec[index].filePos > fsDir[index].size) { fsRec[index].filePos = fsDir[index].size; } return fsRec[index].filePos;}int fs_write(iop_file_t* fd, void * buffer, int size ) {#ifdef WRITE_SUPPORT int index; int result; int updateClusterIndices; updateClusterIndices = 0; index = fs_findFileSlot(fd); if (index < 0) { return -1; } if (size<=0) { return 0; } result = fat_writeFile(&partBpb, &fsDir[index], &updateClusterIndices, fsRec[index].filePos, (unsigned char*) buffer, size); if (result > 0) { //write succesful fsRec[index].filePos += result; if (fsRec[index].filePos > fsDir[index].size) { fsDir[index].size = fsRec[index].filePos; fsRec[index].sizeChange = 1; //if new clusters allocated - then update file cluster indices if (updateClusterIndices) { fat_setFatDirChain(&partBpb, &fsDir[index]); } } } return result;#else return -EROFS; //Read Only file system#endif}int fs_read(iop_file_t* fd, void * buffer, int size ) { int index; int result; index = fs_findFileSlot(fd); if (index < 0) { return -1; } if (size<=0) { return 0; } if ((fsRec[index].filePos+size) > fsDir[index].size) { size = fsDir[index].size - fsRec[index].filePos; } result = fat_readFile(&partBpb, &fsDir[index], fsRec[index].filePos, (unsigned char*) buffer, size); if (result > 0) { //read succesful fsRec[index].filePos += result; } return result;}#ifdef _PS2_int getNameSignature(const char *name) { int ret; int i; ret = 0; for (i=0; name[i] != 0 ; i++) ret += (name[i]*i/2 + name[i]); return ret;}int getMillis() { iop_sys_clock_t clock; u32 sec, usec; GetSystemTime(&clock); SysClock2USec(&clock, &sec, &usec); return (sec*1000) + (usec/1000);}#endif /* __PS2_ */int fs_remove (iop_file_t *fd, const char *name) {#ifdef WRITE_SUPPORT int index; int result; if (fat_mountCheck() < 0) { result = -1;#ifdef _PS2_ removalResult = result;#endif /* PS2 */ return result; } index = fs_findFileSlotByName(name);#ifdef _PS2_ //store filename signature and time of removal nameSignature = getNameSignature(name); removalTime = getMillis();#endif /* __PS2_ */ //file is opened - can't delete the file if (index >= 0) { result = -EINVAL;#ifdef _PS2_ removalResult = result;#endif /* PS2 */ return result; } result = fat_deleteFile(&partBpb, name, 0); FLUSH_SECTORS();#ifdef _PS2_ removalTime = getMillis(); //update removal time removalResult = result;#endif /* _PS2_ */ return result;#else return fs_dummy();#endif /* write support */}int fs_mkdir (iop_file_t *fd, const char *name) {#ifdef WRITE_SUPPORT int ret; int sfnOffset; unsigned int sfnSector; unsigned int cluster;#ifdef _PS2_ int sig, millis;#endif /* _PS2_ */ if (fat_mountCheck() < 0) return -1;#ifdef _PS2_ printf("fs_mkdir: name=%s \n",name); //workaround for bug that invokes fioMkdir right after fioRemove sig = getNameSignature(name); millis = getMillis(); if (sig == nameSignature && (millis - removalTime) < 1000) { return removalResult; //return the original return code from fs_remove }#endif /* _PS2_ */ ret = fat_createFile(&partBpb, name, 1, 0, &cluster, &sfnSector, &sfnOffset); //directory of the same name already exist if (ret == 2) { ret = -EEXIST; } FLUSH_SECTORS(); return ret;#else return fs_dummy();#endif /* write support */}// NOTE! you MUST call fioRmdir with device number in the name// or else this fs_rmdir function is never called.// example: fioRmdir("mass:/dir1"); // <-- doesn't work (bug?)// fioRmdir("mass0:/dir1"); // <-- works fineint fs_rmdir (iop_file_t *fd, const char *name) {#ifdef WRITE_SUPPORT int ret; if (fat_mountCheck() < 0) return -1; ret = fat_deleteFile(&partBpb, name, 1); FLUSH_SECTORS(); return ret;#else return fs_dummy();#endif /* write support */}int fs_dopen (iop_file_t *fd, const char *name) { int index; fat_dir fatdir; fsCounter++; if (fat_mountCheck() < 0) { return -1; } printf ("dopen: '%s'\n", name); if (fat_getFirstDirentry((char*)name, &fatdir)<1) { return -1; } fd->privdata = (void*)malloc(sizeof(D_PRIVATE)); memset(fd->privdata, 0, sizeof(D_PRIVATE)); memcpy(&(((D_PRIVATE*)fd->privdata)->fatdir), &fatdir, sizeof(fatdir)); return fsCounter;}int fs_dclose (iop_file_t *fd) { free(fd->privdata); return 0;}int fs_dread (iop_file_t *fd, void* data) { int notgood; fio_dirent_t *buffer = (fio_dirent_t *)data; do { if (((D_PRIVATE*)fd->privdata)->status) return -1; notgood = 0; memset(buffer, 0, sizeof(fio_dirent_t)); if ((((D_PRIVATE*)fd->privdata)->fatdir).attr & 0x08) { /* volume name */ notgood = 1; } if ((((D_PRIVATE*)fd->privdata)->fatdir).attr & 0x10) { buffer->stat.mode |= FIO_SO_IFDIR; } else { buffer->stat.mode |= FIO_SO_IFREG; } buffer->stat.size = (((D_PRIVATE*)fd->privdata)->fatdir).size; strcpy(buffer->name, (const char*)(((D_PRIVATE*)fd->privdata)->fatdir).name); if (fat_getNextDirentry(&(((D_PRIVATE*)fd->privdata)->fatdir))<1) ((D_PRIVATE*)fd->privdata)->status = 1; /* no more entries */ } while (notgood); return 1;}int fs_getstat(iop_file_t *fd, const char *name, void* data) { int ret; unsigned int cluster = 0; fio_stat_t *stat = (fio_stat_t *)data; fat_dir fatdir; if (fat_mountCheck() < 0) return -1; ret = fat_getFileStartCluster(&partBpb, name, &cluster, &fatdir); if (ret < 0) { return -1; } memset(stat, 0, sizeof(fio_stat_t)); stat->size = fatdir.size; if (fatdir.attr & 10) stat->mode |= FIO_SO_IFDIR; else stat->mode |= FIO_SO_IFREG; return 0;}int fs_chstat (iop_file_t *fd, const char *name, void *buffer, unsigned int a) { return fs_dummy();}int fs_deinit (iop_device_t *fd) { return fs_dummy();}int fs_format (iop_file_t *fd, ...) { return fs_dummy();}int fs_ioctl (iop_file_t *fd, unsigned long a, void *b) { return fs_dummy();}int fs_dummy(void) { return -5;}/*************************************************************************************//* Test / debug functions *//*************************************************************************************/void fat_dumpClusterChain(unsigned int* buf, int maxBuf, int clusterSkip) { int i; printf("cluster chain:"); for (i=0 + clusterSkip; i < maxBuf; i++) { printf(" %i,", buf[i]); } printf(" end (skip=%d, maxBuf=%d arrayLimit=%d) \n", clusterSkip, maxBuf, MAX_DIR_CLUSTER);}void fat_dumpPartitionTable() { fat_part* part; int i; part = &partTable; printf ("\nPartition info\n" ); printf ("--------------\n" ); for (i = 0 ; i < 4 ; i++) { if (part->record[i].sid != 0) { printf ("Partition nr: %i \n", i); printf ("id=%02X \n", part->record[i].sid); printf ("start sector=%i\n", part->record[i].start); printf ("sector count=%i\n", part->record[i].count); } }}void fat_dumpPartitionBootSector() { fat_bpb* bpb; bpb = &partBpb; printf("\n"); printf("Partition boot sector info\n" ); printf("--------------------------\n"); printf("sector size = %i \n", bpb->sectorSize); printf("cluster size = %i \n", bpb->clusterSize); printf("reserved sectors = %i \n", bpb->resSectors); printf("fat count = %i \n", bpb->fatCount); printf("root entry count = %i sectors=%i \n", bpb->rootSize, bpb->rootSize / 16); printf("fat size (sect) = %i \n", bpb->fatSize); printf("track size (sect) = %i \n", bpb->trackSize); printf("head count = %i \n", bpb->headCount); printf("hidden count(sect) = %i \n", bpb->hiddenCount); printf("sector count = %i \n", bpb->sectorCount); printf("\n"); printf("root start sector = %i \n", bpb->rootDirStart); printf("fat type = %i \n", bpb->fatType); printf("fat id = %s \n", bpb->fatId); if (bpb->fatType == FAT32) { printf("root dir cluster = %i \n", bpb->rootDirCluster); printf("active fat = %i \n", bpb->activeFat); }}void fat_dumpSectorHex(unsigned char* buf, int bufSize) { int i; char c; char line[17]; line[16] = 0; for (i = 0; i < bufSize; i++) { c = buf[i]; if (c < 32) { c = 32; } line[i % 16] = c; if (i % 16 == 0) { printf ("%08X ", i); } printf("%02X ", buf[i]); if (i % 16 == 15) { printf (" %s\n", line); } } if (i % 16 != 0) { line[i%16] = 0; printf (" %s\n", line); }}int fat_dumpFatSector(int fatSectorIndex) { int ret; unsigned int sector; fat_bpb* bpb; bpb = &partBpb; sector = bpb->partStart + bpb->resSectors + fatSectorIndex; ret = READ_SECTOR(sector, sbuf); if (ret < 0) { printf("FAT driver: read fat sector failed! sector=%i! \n", sector ); return -1; } printf("\n"); printf("Fat sector, index=%i\n", fatSectorIndex); fat_dumpSectorHex(sbuf, SECTOR_SIZE);}int fat_dumpRootDirSector(int sectorIndex, int sectorCount) { int ret; int i; unsigned int sector; fat_bpb* bpb; bpb = &partBpb; printf("\n"); if (bpb->fatType == FAT32) { sector = fat_cluster2sector(bpb, bpb->rootDirCluster); } else { sector = bpb->rootDirStart + sectorIndex; } for (i = 0; i < sectorCount; i++) { ret = READ_SECTOR(sector + i , sbuf); if (ret < 0) { printf("FAT driver: read directory sector failed! sector=%i! \n", sector + i); return -1; } printf("Directory sector=%i, index=%i\n", sector, i); fat_dumpSectorHex(sbuf, SECTOR_SIZE); }}/* dumps the fat system information */int fat_dumpSystemInfo() { int ret; ret = fat_mountCheck() ; if (ret < 0) { return ret; } fat_dumpPartitionTable(); fat_dumpPartitionBootSector(); fat_dumpFatSector(0); fat_dumpRootDirSector(0, 10);}/*these functions helps the developper to get the flash disk sector image encoded as hex byes. That image can be useful when debugging the fat filesystem functions.*/void dumpReadData(unsigned char * buf, int bufSize) { int i; char c; int size = bufSize / 16; int offs; printf("\n"); for (i = 0; i < size; i++) { offs = i * 16; printf("##%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", buf[offs], buf[offs+1], buf[offs+2], buf[offs+3], buf[offs+4], buf[offs+5], buf[offs+6], buf[offs+7], buf[offs+8], buf[offs+9], buf[offs+10], buf[offs+11], buf[offs+12], buf[offs+13], buf[offs+14], buf[offs+15] ); }}int fat_dumpSector(unsigned int sector) { int ret; ret = READ_SECTOR(sector, sbuf); if (ret < 0) { printf("Read sector failed ! sector=%i\n", sector); return -1; } dumpReadData(sbuf, SECTOR_SIZE); return 1;}int fat_readSector(unsigned int sector, unsigned char** buf) { int ret; ret = READ_SECTOR(sector, sbuf); if (ret < 0) { printf("Read sector failed ! sector=%i\n", sector); return -1; } *buf = sbuf; return Size_Sector;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -