📄 ff.c
字号:
/*-----------------------------------------------------------------------*//* Get file status from directory entry *//*-----------------------------------------------------------------------*/#if _FS_MINIMIZE <= 1staticvoid get_fileinfo ( /* No return code */ FILINFO *finfo, /* Ptr to store the file information */ const U8 *dir /* Ptr to the directory entry */ ){ U8 n, c, a; char *p; p = &finfo->fname[0]; a = _USE_NTFLAG ? dir[DIR_NTres] : 0; /* NT flag */ for (n = 0; n < 8; n++) { /* Convert file name (body) */ c = dir[n]; if (c == ' ') break; if (c == 0x05) c = 0xE5; if (a & 0x08 && c >= 'A' && c <= 'Z') c += 0x20; *p++ = c; } if (dir[8] != ' ') { /* Convert file name (extension) */ *p++ = '.'; for (n = 8; n < 11; n++) { c = dir[n]; if (c == ' ') break; if (a & 0x10 && c >= 'A' && c <= 'Z') c += 0x20; *p++ = c; } } *p = '\0'; finfo->fattrib = dir[DIR_Attr]; /* Attribute */ finfo->fsize = LD_U32(&dir[DIR_FileSize]); /* Size */ finfo->fdate = LD_U16(&dir[DIR_WrtDate]); /* Date */ finfo->ftime = LD_U16(&dir[DIR_WrtTime]); /* Time */}#endif /* _FS_MINIMIZE <= 1 *//*-----------------------------------------------------------------------*//* Pick a paragraph and create the name in format of directory entry *//*-----------------------------------------------------------------------*/staticchar make_dirfile ( /* 1: error - detected an invalid format, '\0'or'/': next character */ const char **path, /* Pointer to the file path pointer */ char *dirname /* Pointer to directory name buffer {Name(8), Ext(3), NT flag(1)} */ ){ U8 n, t, c, a, b; memset(dirname, ' ', 8+3); /* Fill buffer with spaces */ a = 0; b = 0x18; /* NT flag */ n = 0; t = 8; for (;;) { c = *(*path)++; if (c == '\0' || c == '/') { /* Reached to end of str or directory separator */ if (n == 0) break; dirname[11] = _USE_NTFLAG ? (a & b) : 0; return c; } if (c <= ' ' || c == 0x7F) break; /* Reject invisible chars */ if (c == '.') { if (!(a & 1) && n >= 1 && n <= 8) { /* Enter extension part */ n = 8; t = 11; continue; } break; } if (_USE_SJIS && ((c >= 0x81 && c <= 0x9F) || /* Accept S-JIS code */ (c >= 0xE0 && c <= 0xFC))) { if (n == 0 && c == 0xE5) /* Change heading \xE5 to \x05 */ c = 0x05; a ^= 1; goto md_l2; } if (c == '"') break; /* Reject " */ if (c <= ')') goto md_l1; /* Accept ! # $ % & ' ( ) */ if (c <= ',') break; /* Reject * + , */ if (c <= '9') goto md_l1; /* Accept - 0-9 */ if (c <= '?') break; /* Reject : ; < = > ? */ if (!(a & 1)) { /* These checks are not applied to S-JIS 2nd byte */ if (c == '|') break; /* Reject | */ if (c >= '[' && c <= ']') break;/* Reject [ \ ] */ if (_USE_NTFLAG && c >= 'A' && c <= 'Z') (t == 8) ? (b &= ~0x08) : (b &= ~0x10); if (c >= 'a' && c <= 'z') { /* Convert to upper case */ c -= 0x20; if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10); } }md_l1: a &= ~1;md_l2: if (n >= t) break; dirname[n++] = c; } return 1;}/*-----------------------------------------------------------------------*//* Trace a file path *//*-----------------------------------------------------------------------*/staticFRESULT trace_path ( /* FR_OK(0): successful, !=0: error code */ DIR *dirobj, /* Pointer to directory object to return last directory */ char *fn, /* Pointer to last segment name to return {file(8),ext(3),attr(1)} */ const char *path, /* Full-path string to trace a file or directory */ U8 **dir /* Directory pointer in Win[] to retutn */ ){ U32 clust; char ds; U8 *dptr = NULL; FATFS *fs = dirobj->fs; /* Get logical drive from the given DIR structure */ /* Initialize directory object */ clust = fs->dirbase; if (fs->fs_type == FS_FAT32) { dirobj->clust = dirobj->sclust = clust; dirobj->sect = clust2sect(fs, clust); } else { dirobj->clust = dirobj->sclust = 0; dirobj->sect = clust; } dirobj->index = 0; if (*path == '\0') { /* Null path means the root directory */ *dir = NULL; return FR_OK; } for (;;) { ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */ if (ds == 1) return FR_INVALID_NAME; for (;;) { if (!move_window(fs, dirobj->sect)) return FR_RW_ERROR; dptr = &fs->win[(dirobj->index & ((S_SIZ - 1) / 32)) * 32]; /* Pointer to the directory entry */ if (dptr[DIR_Name] == 0) /* Has it reached to end of dir? */ return !ds ? FR_NO_FILE : FR_NO_PATH; if (dptr[DIR_Name] != 0xE5 /* Matched? */ && !(dptr[DIR_Attr] & AM_VOL) && !memcmp(&dptr[DIR_Name], fn, 8+3) ) break; if (!next_dir_entry(dirobj)) /* Next directory pointer */ return !ds ? FR_NO_FILE : FR_NO_PATH; } if (!ds) { *dir = dptr; return FR_OK; } /* Matched with end of path */ if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH; /* Cannot trace because it is a file */ clust = ((U32)LD_U16(&dptr[DIR_FstClusHI]) << 16) | LD_U16(&dptr[DIR_FstClusLO]); /* Get cluster# of the directory */ dirobj->clust = dirobj->sclust = clust; /* Restart scanning at the new directory */ dirobj->sect = clust2sect(fs, clust); dirobj->index = 2; }}/*-----------------------------------------------------------------------*//* Reserve a directory entry *//*-----------------------------------------------------------------------*/#if !_FS_READONLYstaticFRESULT reserve_direntry ( /* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */ DIR *dirobj, /* Target directory to create new entry */ U8 **dir /* Pointer to pointer to created entry to retutn */ ){ U32 clust, sector; U8 c, n, *dptr; FATFS *fs = dirobj->fs; /* Re-initialize directory object */ clust = dirobj->sclust; if (clust) { /* Dyanmic directory table */ dirobj->clust = clust; dirobj->sect = clust2sect(fs, clust); } else { /* Static directory table */ dirobj->sect = fs->dirbase; } dirobj->index = 0; do { if (!move_window(fs, dirobj->sect)) return FR_RW_ERROR; dptr = &fs->win[(dirobj->index & ((S_SIZ - 1) / 32)) * 32]; /* Pointer to the directory entry */ c = dptr[DIR_Name]; if (c == 0 || c == 0xE5) { /* Found an empty entry! */ *dir = dptr; return FR_OK; } } while (next_dir_entry(dirobj)); /* Next directory pointer */ /* Reached to end of the directory table */ /* Abort when static table or could not stretch dynamic table */ if (!clust || !(clust = create_chain(fs, dirobj->clust))) return FR_DENIED; if (clust == 1 || !move_window(fs, 0)) return FR_RW_ERROR; fs->winsect = sector = clust2sect(fs, clust); /* Cleanup the expanded table */ memset(fs->win, 0, S_SIZ); for (n = fs->sects_clust; n; n--) { if (diskWrite(fs->drive, fs->win, sector, 1) != DRESULT_OK) return FR_RW_ERROR; sector++; } fs->winflag = 1; *dir = fs->win; return FR_OK;}#endif /* !_FS_READONLY *//*-----------------------------------------------------------------------*//* Load boot record and check if it is a FAT boot record *//*-----------------------------------------------------------------------*/staticU8 check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */ FATFS *fs, /* File system object */ U32 sect /* Sector# (lba) to check if it is a FAT boot record or not */ ){ if (diskRead(fs->drive, fs->win, sect, 1) != DRESULT_OK) /* Load boot record */ return 2; if (LD_U16(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always offset 510) */ return 2; if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3)) /* Check FAT signature */ return 0; if (!memcmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80)) return 0; return 1;}/*-----------------------------------------------------------------------*//* Make sure that the file system is valid *//*-----------------------------------------------------------------------*/staticFRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ const char **path, /* Pointer to pointer to the path name (drive number) */ FATFS **rfs, /* Pointer to pointer to the found file system object */ U8 chk_wp /* !=0: Check media write protection for wrinting fuctions */ ){ U8 drv, fmt, *tbl; DSTATUS stat; U32 bootsect, fatsize, totalsect, maxclust; const char *p = *path; FATFS *fs; /* Get drive number from the path name */ while (*p == ' ') p++; /* Strip leading spaces */ drv = p[0] - '0'; /* Is there a drive number? */ if (drv <= 9 && p[1] == ':') p += 2; /* Found a drive number, get and strip it */ else drv = 0; /* No drive number is given, select drive 0 in default */ if (*p == '/') p++; /* Strip heading slash */ *path = p; /* Return pointer to the path name */ /* Check if the drive number is valid or not */ if (drv >= _DRIVES) return FR_INVALID_DRIVE; /* Is the drive number valid? */ if (!(fs = FatFs[drv])) return FR_NOT_ENABLED; /* Is the file system object registered? */ *rfs = fs; /* Returen pointer to the corresponding file system object */ /* Check if the logical drive has been mounted or not */ if (fs->fs_type) { stat = diskStatus(fs->drive); if (!(stat & DSTATUS_NOINIT)) { /* If the physical drive is kept initialized */#if !_FS_READONLY if (chk_wp && (stat & DSTATUS_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED;#endif return FR_OK; /* The file system object is valid */ } } /* The logical drive has not been mounted, following code attempts to mount the logical drive */ memset(fs, 0, sizeof(FATFS)); /* Clean-up the file system object */ fs->drive = LD2PD(drv); /* Bind the logical drive and a physical drive */ stat = diskInitialize (fs->drive); /* Initialize low level disk I/O layer */ if (stat & DSTATUS_NOINIT) /* Check if the drive is ready */ return FR_NOT_READY;#if S_MAX_SIZ > 512 /* Check disk sector size */ if (diskIoctl(drv, IOCTL_GET_SECTOR_SIZE, &S_SIZ) != DRESULT_OK || S_SIZ > S_MAX_SIZ) return FR_NO_FILESYSTEM;#endif#if !_FS_READONLY if (chk_wp && (stat & DSTATUS_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED;#endif /* Search FAT partition on the drive */ fmt = check_fs(fs, bootsect = 0); /* Check sector 0 as an SFD format */ if (fmt == 1) { /* Not a FAT boot record, it may be patitioned */ /* Check a partition listed in top of the partition table */ tbl = &fs->win[MBR_Table + LD2PT(drv) * 16]; /* Partition table */ if (tbl[4]) { /* Is the partition existing? */ bootsect = LD_U32(&tbl[8]); /* Partition offset in LBA */ fmt = check_fs(fs, bootsect); /* Check the partition */ } } if (fmt || LD_U16(&fs->win[BPB_BytsPerSec]) != S_SIZ) /* No valid FAT patition is found */ return FR_NO_FILESYSTEM; /* Initialize the file system object */ fatsize = LD_U16(&fs->win[BPB_FATSz16]); /* Number of sectors per FAT */ if (!fatsize) fatsize = LD_U32(&fs->win[BPB_FATSz32]); fs->sects_fat = fatsize; fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */ fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */ fs->fatbase = bootsect + LD_U16(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */ fs->sects_clust = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ fs->n_rootdir = LD_U16(&fs->win[BPB_RootEntCnt]); /* Nmuber of root directory entries */ totalsect = LD_U16(&fs->win[BPB_TotSec16]); /* Number of sectors on the file system */ if (!totalsect) totalsect = LD_U32(&fs->win[BPB_TotSec32]);#if 0 // // Patch from David Johnson // sectsize = LD_U16(&fs->win[BPB_BytsPerSec]); rootdirsect = ((fs->n_rootdir * 32) + (sectsize - 1)) / sectsize; if ((((fs->n_rootdir * 32) + (sectsize - 1)) % sectsize) > 0) rootdirsect++; datasec = totalsect - (LD_U16(&fs->win[BPB_RsvdSecCnt]) + fatsize + rootdirsect); clustercnt = datasec / fs->sects_clust; fs->max_clust = clustercnt + 1; fmt = FS_FAT12; if (clustercnt >= 4085) fmt = FS_FAT16; if (clustercnt >= 65525) fmt = FS_FAT32;#else fs->max_clust = maxclust = (totalsect /* Last cluster# + 1 */ - LD_U16(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / (S_SIZ/32) ) / fs->sects_clust + 2; fmt = FS_FAT12; /* Determine the FAT sub type */ if (maxclust > 0xFF7) fmt = FS_FAT16; if (maxclust > 0xFFF7) fmt = FS_FAT32;#endif fs->fs_type = fmt; if (fmt == FS_FAT32) fs->dirbase = LD_U32(&fs->win[BPB_RootClus]); /* Root directory start cluster */ else fs->dirbase = fs->fatbase + fatsize; /* Root directory start sector (lba) */ fs->database = fs->fatbase + fatsize + fs->n_rootdir / (S_SIZ/32); /* Data start sector (lba) */#if !_FS_READONLY fs->free_clust = 0xFFFFFFFF;#if _USE_FSINFO /* Load fsinfo sector if needed */ if (fmt == FS_FAT32) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -