Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pff.cpp
00001 /*----------------------------------------------------------------------------/ 00002 / Petit FatFs - FAT file system module R0.02 (C)ChaN, 2009 00003 /-----------------------------------------------------------------------------/ 00004 / Petit FatFs module is an open source software to implement FAT file system to 00005 / small embedded systems. This is a free software and is opened for education, 00006 / research and commercial developments under license policy of following trems. 00007 / 00008 / Copyright (C) 2009, ChaN, all right reserved. 00009 / 00010 / * The Petit FatFs module is a free software and there is NO WARRANTY. 00011 / * No restriction on use. You can use, modify and redistribute it for 00012 / personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. 00013 / * Redistributions of source code must retain the above copyright notice. 00014 / 00015 /-----------------------------------------------------------------------------/ 00016 / Jun 15,'09 R0.01a First release. (Branched from FatFs R0.07b.) 00017 / 00018 / Dec 14,'09 R0.02 Added multiple code page support. 00019 / Added write funciton. 00020 / Changed stream read mode interface. 00021 /----------------------------------------------------------------------------*/ 00022 00023 #include "pff.h" /* Petit FatFs configurations and declarations */ 00024 #include "diskio.h" /* Declarations of low level disk I/O functions */ 00025 00026 00027 /*-------------------------------------------------------------------------- 00028 00029 Private Functions 00030 00031 ---------------------------------------------------------------------------*/ 00032 00033 00034 00035 /*-----------------------------------------------------------------------*/ 00036 /* String functions */ 00037 /*-----------------------------------------------------------------------*/ 00038 00039 /* Fill memory */ 00040 void PetitFileSystem::mem_set (void* dst, int val, int cnt) { 00041 char *d = (char*)dst; 00042 while (cnt--) *d++ = (char)val; 00043 } 00044 00045 /* Compare memory to memory */ 00046 int PetitFileSystem::mem_cmp (const void* dst, const void* src, int cnt) { 00047 const char *d = (const char *)dst, *s = (const char *)src; 00048 int r = 0; 00049 while (cnt-- && (r = *d++ - *s++) == 0) ; 00050 return r; 00051 } 00052 00053 00054 00055 /*-----------------------------------------------------------------------*/ 00056 /* FAT access - Read value of a FAT entry */ 00057 /*-----------------------------------------------------------------------*/ 00058 00059 CLUST PetitFileSystem::get_fat ( /* 1:IO error, Else:Cluster status */ 00060 FATFS *fs, 00061 CLUST clst /* Cluster# to get the link information */ 00062 ) { 00063 WORD wc, bc, ofs; 00064 BYTE buf[4]; 00065 00066 if (clst < 2 || clst >= fs->max_clust) /* Range check */ 00067 return 1; 00068 00069 switch (fs->fs_type) { 00070 case FS_FAT12 : 00071 bc = (WORD)clst; 00072 bc += bc / 2; 00073 ofs = bc % 512; 00074 bc /= 512; 00075 if (ofs != 511) { 00076 if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break; 00077 } else { 00078 if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break; 00079 if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break; 00080 } 00081 wc = LD_WORD(buf); 00082 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); 00083 00084 case FS_FAT16 : 00085 if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break; 00086 return LD_WORD(buf); 00087 #if _FS_FAT32 00088 case FS_FAT32 : 00089 if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break; 00090 return LD_DWORD(buf) & 0x0FFFFFFF; 00091 #endif 00092 } 00093 00094 return 1; /* An error occured at the disk I/O layer */ 00095 } 00096 00097 00098 00099 00100 /*-----------------------------------------------------------------------*/ 00101 /* Get sector# from cluster# */ 00102 /*-----------------------------------------------------------------------*/ 00103 00104 DWORD PetitFileSystem::clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ 00105 FATFS *fs, CLUST clst /* Cluster# to be converted */ 00106 ) { 00107 00108 clst -= 2; 00109 if (clst >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */ 00110 return (DWORD)clst * fs->csize + fs->database; 00111 } 00112 00113 00114 00115 00116 /*-----------------------------------------------------------------------*/ 00117 /* Directory handling - Rewind directory index */ 00118 /*-----------------------------------------------------------------------*/ 00119 00120 PetitFileSystem::FRESULT PetitFileSystem::dir_rewind ( FATFS *fs, 00121 FATDIR *dj /* Pointer to directory object */ 00122 ) { 00123 CLUST clst; 00124 00125 00126 00127 dj->index = 0; 00128 clst = dj->sclust; 00129 if (clst == 1 || clst >= fs->max_clust) /* Check start cluster range */ 00130 return FR_DISK_ERR; 00131 #if _FS_FAT32 00132 if (!clst && fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ 00133 clst = fs->dirbase; 00134 #endif 00135 dj->clust = clst; /* Current cluster */ 00136 dj->sect = clst ? clust2sect(fs, clst) : fs->dirbase; /* Current sector */ 00137 00138 return FR_OK; /* Seek succeeded */ 00139 } 00140 00141 00142 00143 00144 /*-----------------------------------------------------------------------*/ 00145 /* Directory handling - Move directory index next */ 00146 /*-----------------------------------------------------------------------*/ 00147 00148 PetitFileSystem::FRESULT PetitFileSystem::dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table */ 00149 FATFS *fs, 00150 FATDIR *dj /* Pointer to directory object */ 00151 ) { 00152 CLUST clst; 00153 WORD i; 00154 00155 00156 i = dj->index + 1; 00157 if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ 00158 return FR_NO_FILE; 00159 00160 if (!(i & (16-1))) { /* Sector changed? */ 00161 dj->sect++; /* Next sector */ 00162 00163 if (dj->clust == 0) { /* Static table */ 00164 if (i >= fs->n_rootdir) /* Report EOT when end of table */ 00165 return FR_NO_FILE; 00166 } else { /* Dynamic table */ 00167 if (((i / 16) & (fs->csize-1)) == 0) { /* Cluster changed? */ 00168 clst = get_fat(fs, dj->clust); /* Get next cluster */ 00169 if (clst <= 1) return FR_DISK_ERR; 00170 if (clst >= fs->max_clust) /* When it reached end of dynamic table */ 00171 return FR_NO_FILE; /* Report EOT */ 00172 dj->clust = clst; /* Initialize data for new cluster */ 00173 dj->sect = clust2sect(fs, clst); 00174 } 00175 } 00176 } 00177 00178 dj->index = i; 00179 00180 return FR_OK; 00181 } 00182 00183 00184 00185 00186 /*-----------------------------------------------------------------------*/ 00187 /* Directory handling - Find an object in the directory */ 00188 /*-----------------------------------------------------------------------*/ 00189 00190 PetitFileSystem::FRESULT PetitFileSystem::dir_find ( 00191 FATFS *fs, 00192 FATDIR *dj /* Pointer to the directory object linked to the file name */ 00193 ) { 00194 FRESULT res; 00195 BYTE c, *dir; 00196 00197 00198 res = dir_rewind(fs, dj); /* Rewind directory object */ 00199 if (res != FR_OK) return res; 00200 00201 dir = fs->buf; 00202 do { 00203 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00204 ? FR_DISK_ERR : FR_OK; 00205 if (res != FR_OK) break; 00206 c = dir[DIR_Name]; /* First character */ 00207 if (c == 0) { 00208 res = FR_NO_FILE; /* Reached to end of table */ 00209 break; 00210 } 00211 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ 00212 break; 00213 res = dir_next(fs, dj); /* Next entry */ 00214 } while (res == FR_OK); 00215 00216 return res; 00217 } 00218 00219 00220 00221 00222 /*-----------------------------------------------------------------------*/ 00223 /* Read an object from the directory */ 00224 /*-----------------------------------------------------------------------*/ 00225 #if _USE_DIR 00226 PetitFileSystem::FRESULT PetitFileSystem::dir_read ( 00227 FATFS *fs, 00228 FATDIR *dj /* Pointer to the directory object to store read object name */ 00229 ) { 00230 FRESULT res; 00231 BYTE a, c, *dir; 00232 00233 00234 res = FR_NO_FILE; 00235 dir = fs->buf; 00236 while (dj->sect) { 00237 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00238 ? FR_DISK_ERR : FR_OK; 00239 if (res != FR_OK) break; 00240 c = dir[DIR_Name]; 00241 if (c == 0) { 00242 res = FR_NO_FILE; /* Reached to end of table */ 00243 break; 00244 } 00245 a = dir[DIR_Attr] & AM_MASK; 00246 if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ 00247 break; 00248 res = dir_next(fs, dj); /* Next entry */ 00249 if (res != FR_OK) break; 00250 } 00251 00252 if (res != FR_OK) dj->sect = 0; 00253 00254 return res; 00255 } 00256 #endif 00257 00258 00259 00260 /*-----------------------------------------------------------------------*/ 00261 /* Pick a segment and create the object name in directory form */ 00262 /*-----------------------------------------------------------------------*/ 00263 00264 #ifdef _EXCVT 00265 static const BYTE cvt[] = _EXCVT; 00266 #endif 00267 00268 PetitFileSystem::FRESULT PetitFileSystem::create_name ( 00269 FATDIR *dj, /* Pointer to the directory object */ 00270 const char **path /* Pointer to pointer to the segment in the path string */ 00271 ) { 00272 BYTE c, d, ni, si, i, *sfn; 00273 const char *p; 00274 00275 /* Create file name in directory form */ 00276 sfn = dj->fn; 00277 mem_set(sfn, ' ', 11); 00278 si = i = 0; 00279 ni = 8; 00280 p = *path; 00281 for (;;) { 00282 c = p[si++]; 00283 if (c <= ' ' || c == '/') break; /* Break on end of segment */ 00284 if (c == '.' || i >= ni) { 00285 if (ni != 8 || c != '.') break; 00286 i = 8; 00287 ni = 11; 00288 continue; 00289 } 00290 #ifdef _EXCVT 00291 if (c >= 0x80) /* To upper extended char (SBCS) */ 00292 c = cvt[c - 0x80]; 00293 #endif 00294 if (IsDBCS1(c) && i >= ni - 1) { /* DBC 1st byte? */ 00295 d = p[si++]; /* Get 2nd byte */ 00296 sfn[i++] = c; 00297 sfn[i++] = d; 00298 } else { /* Single byte code */ 00299 if (IsLower(c)) c -= 0x20; /* toupper */ 00300 sfn[i++] = c; 00301 } 00302 } 00303 *path = &p[si]; /* Rerurn pointer to the next segment */ 00304 00305 sfn[11] = (c <= ' ') ? 1 : 0; /* Set last segment flag if end of path */ 00306 00307 return FR_OK; 00308 } 00309 00310 00311 00312 00313 /*-----------------------------------------------------------------------*/ 00314 /* Get file information from directory entry */ 00315 /*-----------------------------------------------------------------------*/ 00316 #if _USE_DIR 00317 void PetitFileSystem::get_fileinfo ( /* No return code */ 00318 FATFS *fs, 00319 FATDIR *dj, /* Pointer to the directory object */ 00320 FILINFO *fno /* Pointer to store the file information */ 00321 ) { 00322 BYTE i, c, *dir; 00323 char *p; 00324 00325 00326 p = fno->fname; 00327 if (dj->sect) { 00328 dir = fs->buf; 00329 for (i = 0; i < 8; i++) { /* Copy file name body */ 00330 c = dir[i]; 00331 if (c == ' ') break; 00332 if (c == 0x05) c = 0xE5; 00333 *p++ = c; 00334 } 00335 if (dir[8] != ' ') { /* Copy file name extension */ 00336 *p++ = '.'; 00337 for (i = 8; i < 11; i++) { 00338 c = dir[i]; 00339 if (c == ' ') break; 00340 *p++ = c; 00341 } 00342 } 00343 fno->fattrib = dir[DIR_Attr]; /* Attribute */ 00344 fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ 00345 fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ 00346 fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ 00347 } 00348 *p = 0; 00349 } 00350 #endif /* _USE_DIR */ 00351 00352 00353 00354 /*-----------------------------------------------------------------------*/ 00355 /* Follow a file path */ 00356 /*-----------------------------------------------------------------------*/ 00357 00358 PetitFileSystem::FRESULT PetitFileSystem::follow_path ( /* FR_OK(0): successful, !=0: error code */ 00359 FATFS *fs, 00360 FATDIR *dj, /* Directory object to return last directory and found object */ 00361 const char *path /* Full-path string to find a file or directory */ 00362 ) { 00363 FRESULT res; 00364 BYTE *dir; 00365 00366 00367 while (*path == ' ') path++; /* Skip leading spaces */ 00368 if (*path == '/') path++; /* Strip heading separator */ 00369 dj->sclust = 0; /* Set start directory (always root dir) */ 00370 00371 if ((BYTE)*path <= ' ') { /* Null path means the root directory */ 00372 res = dir_rewind(fs, dj); 00373 fs->buf[0] = 0; 00374 00375 } else { /* Follow path */ 00376 for (;;) { 00377 res = create_name(dj, &path); /* Get a segment */ 00378 if (res != FR_OK) break; 00379 res = dir_find(fs, dj); /* Find it */ 00380 if (res != FR_OK) { /* Could not find the object */ 00381 if (res == FR_NO_FILE && !*(dj->fn+11)) 00382 res = FR_NO_PATH; 00383 break; 00384 } 00385 if (*(dj->fn+11)) break; /* Last segment match. Function completed. */ 00386 dir = fs->buf; /* There is next segment. Follow the sub directory */ 00387 if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ 00388 res = FR_NO_PATH; 00389 break; 00390 } 00391 dj->sclust = 00392 #if _FS_FAT32 00393 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00394 #endif 00395 LD_WORD(dir+DIR_FstClusLO); 00396 } 00397 } 00398 00399 return res; 00400 } 00401 00402 00403 00404 00405 /*-----------------------------------------------------------------------*/ 00406 /* Check a sector if it is an FAT boot record */ 00407 /*-----------------------------------------------------------------------*/ 00408 00409 BYTE PetitFileSystem::check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */ 00410 BYTE *buf, /* Working buffer */ 00411 DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ 00412 ) { 00413 if (disk_readp(buf, sect, 510, 2)) /* Read the boot sector */ 00414 return 3; 00415 if (LD_WORD(buf) != 0xAA55) /* Check record signature */ 00416 return 2; 00417 00418 if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */ 00419 return 0; 00420 #if _FS_FAT32 00421 if (!disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146) /* Check FAT32 */ 00422 return 0; 00423 #endif 00424 return 1; 00425 } 00426 00427 00428 00429 00430 /*-------------------------------------------------------------------------- 00431 00432 Public Functions 00433 00434 --------------------------------------------------------------------------*/ 00435 00436 00437 00438 /*-----------------------------------------------------------------------*/ 00439 /* Mount/Unmount a Locical Drive */ 00440 /*-----------------------------------------------------------------------*/ 00441 00442 PetitFileSystem::FRESULT PetitFileSystem::unmount () { 00443 FatFs = 0; 00444 return FR_OK; /* Unregister fs object */ 00445 } 00446 00447 PetitFileSystem::FRESULT PetitFileSystem::mount () { 00448 BYTE fmt, buf[36]; 00449 DWORD bsect, fsize, tsect, mclst; 00450 FATFS *fs = &FileSystemObject; 00451 00452 if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */ 00453 return FR_NOT_READY; 00454 00455 /* Search FAT partition on the drive */ 00456 bsect = 0; 00457 fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */ 00458 if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */ 00459 /* Check a partition listed in top of the partition table */ 00460 if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */ 00461 fmt = 3; 00462 } else { 00463 if (buf[4]) { /* Is the partition existing? */ 00464 bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */ 00465 fmt = check_fs(buf, bsect); /* Check the partition */ 00466 } 00467 } 00468 } 00469 if (fmt == 3) return FR_DISK_ERR; 00470 if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */ 00471 00472 /* Initialize the file system object */ 00473 if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR; 00474 00475 fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */ 00476 if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13); 00477 00478 fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */ 00479 fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */ 00480 fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */ 00481 fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */ 00482 tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */ 00483 if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13); 00484 mclst = (tsect /* Last cluster# + 1 */ 00485 - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16 00486 ) / fs->csize + 2; 00487 fs->max_clust = (CLUST)mclst; 00488 00489 fmt = FS_FAT12; /* Determine the FAT sub type */ 00490 if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */ 00491 if (mclst >= 0xFFF7) /* Number of clusters >= 0xFFF5 */ 00492 #if _FS_FAT32 00493 fmt = FS_FAT32; 00494 #else 00495 return FR_NO_FILESYSTEM; 00496 #endif 00497 00498 fs->fs_type = fmt; /* FAT sub-type */ 00499 #if _FS_FAT32 00500 if (fmt == FS_FAT32) 00501 fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */ 00502 else 00503 #endif 00504 fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ 00505 fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */ 00506 00507 fs->flag = 0; 00508 FatFs = fs; 00509 00510 return FR_OK; 00511 } 00512 00513 00514 00515 00516 /*-----------------------------------------------------------------------*/ 00517 /* Open or Create a File */ 00518 /*-----------------------------------------------------------------------*/ 00519 00520 PetitFileSystem::FRESULT PetitFileSystem::open ( 00521 const char *path /* Pointer to the file name */ 00522 ) { 00523 FRESULT res; 00524 FATDIR dj; 00525 BYTE sp[12], dir[32]; 00526 00527 00528 if (!FatFs) /* Check file system */ 00529 return FR_NOT_ENABLED; 00530 00531 FatFs->flag = 0; 00532 FatFs->buf = dir; 00533 dj.fn = sp; 00534 res = follow_path(FatFs, &dj, path); /* Follow the file path */ 00535 if (res != FR_OK) return res; /* Follow failed */ 00536 if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */ 00537 return FR_NO_FILE; 00538 00539 FatFs->org_clust = /* File start cluster */ 00540 #if _FS_FAT32 00541 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00542 #endif 00543 LD_WORD(dir+DIR_FstClusLO); 00544 FatFs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ 00545 FatFs->fptr = 0; /* File pointer */ 00546 FatFs->flag = FA_OPENED; 00547 00548 return FR_OK; 00549 } 00550 00551 00552 00553 00554 /*-----------------------------------------------------------------------*/ 00555 /* Read File */ 00556 /*-----------------------------------------------------------------------*/ 00557 #if _USE_READ 00558 00559 PetitFileSystem::FRESULT PetitFileSystem::read ( 00560 void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ 00561 WORD btr, /* Number of bytes to read */ 00562 WORD* br /* Pointer to number of bytes read */ 00563 ) { 00564 DRESULT dr; 00565 CLUST clst; 00566 DWORD sect, remain; 00567 BYTE *rbuff = (BYTE *)buff; 00568 WORD rcnt; 00569 FATFS *fs = FatFs; 00570 00571 00572 *br = 0; 00573 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00574 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00575 return FR_NOT_OPENED; 00576 00577 remain = fs->fsize - fs->fptr; 00578 if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining bytes */ 00579 00580 while (btr) { /* Repeat until all data transferred */ 00581 if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ 00582 if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ 00583 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00584 fs->org_clust : get_fat(fs, fs->curr_clust); 00585 if (clst <= 1) goto fr_abort; 00586 fs->curr_clust = clst; /* Update current cluster */ 00587 fs->csect = 0; /* Reset sector offset in the cluster */ 00588 } 00589 sect = clust2sect(fs, fs->curr_clust); /* Get current sector */ 00590 if (!sect) goto fr_abort; 00591 fs->dsect = sect + fs->csect++; 00592 } 00593 rcnt = 512 - ((WORD)fs->fptr % 512); /* Get partial sector data from sector buffer */ 00594 if (rcnt > btr) rcnt = btr; 00595 dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); 00596 if (dr) goto fr_abort; 00597 fs->fptr += rcnt; 00598 rbuff += rcnt; /* Update pointers and counters */ 00599 btr -= rcnt; 00600 *br += rcnt; 00601 } 00602 00603 return FR_OK; 00604 00605 fr_abort: 00606 fs->flag = 0; 00607 return FR_DISK_ERR; 00608 } 00609 #endif 00610 00611 00612 00613 /*-----------------------------------------------------------------------*/ 00614 /* Write File */ 00615 /*-----------------------------------------------------------------------*/ 00616 #if _USE_WRITE 00617 00618 PetitFileSystem::FRESULT PetitFileSystem::write ( 00619 const void* buff, /* Pointer to the data to be written */ 00620 WORD btw, /* Number of bytes to write (0:Finalize the current write operation) */ 00621 WORD* bw /* Pointer to number of bytes written */ 00622 ) { 00623 CLUST clst; 00624 DWORD sect, remain; 00625 const BYTE *p = (const BYTE *)buff; 00626 WORD wcnt; 00627 FATFS *fs = FatFs; 00628 00629 00630 *bw = 0; 00631 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00632 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00633 return FR_NOT_OPENED; 00634 00635 if (!btw) { /* Finalize request */ 00636 if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort; 00637 fs->flag &= ~FA__WIP; 00638 return FR_OK; 00639 } else { /* Write data request */ 00640 if (!(fs->flag & FA__WIP)) /* Round down fptr to the sector boundary */ 00641 fs->fptr &= 0xFFFFFE00; 00642 } 00643 remain = fs->fsize - fs->fptr; 00644 if (btw > remain) btw = (WORD)remain; /* Truncate btw by remaining bytes */ 00645 00646 while (btw) { /* Repeat until all data transferred */ 00647 if (((WORD)fs->fptr % 512) == 0) { /* On the sector boundary? */ 00648 if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ 00649 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00650 fs->org_clust : get_fat(fs, fs->curr_clust); 00651 if (clst <= 1) goto fw_abort; 00652 fs->curr_clust = clst; /* Update current cluster */ 00653 fs->csect = 0; /* Reset sector offset in the cluster */ 00654 } 00655 sect = clust2sect(fs, fs->curr_clust); /* Get current sector */ 00656 if (!sect) goto fw_abort; 00657 fs->dsect = sect + fs->csect++; 00658 if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */ 00659 fs->flag |= FA__WIP; 00660 } 00661 wcnt = 512 - ((WORD)fs->fptr % 512); /* Number of bytes to write to the sector */ 00662 if (wcnt > btw) wcnt = btw; 00663 if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */ 00664 fs->fptr += wcnt; 00665 p += wcnt; /* Update pointers and counters */ 00666 btw -= wcnt; 00667 *bw += wcnt; 00668 if (((WORD)fs->fptr % 512) == 0) { 00669 if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */ 00670 fs->flag &= ~FA__WIP; 00671 } 00672 } 00673 00674 return FR_OK; 00675 00676 fw_abort: 00677 fs->flag = 0; 00678 return FR_DISK_ERR; 00679 } 00680 #endif 00681 00682 00683 00684 /*-----------------------------------------------------------------------*/ 00685 /* Seek File R/W Pointer */ 00686 /*-----------------------------------------------------------------------*/ 00687 #if _USE_LSEEK 00688 00689 PetitFileSystem::FRESULT PetitFileSystem::lseek ( 00690 DWORD ofs /* File pointer from top of file */ 00691 ) { 00692 CLUST clst; 00693 DWORD bcs, sect, ifptr; 00694 FATFS *fs = FatFs; 00695 00696 00697 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00698 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00699 return FR_NOT_OPENED; 00700 00701 if (ofs > fs->fsize) ofs = fs->fsize; /* Clip offset with the file size */ 00702 ifptr = fs->fptr; 00703 fs->fptr = 0; 00704 if (ofs > 0) { 00705 bcs = (DWORD)fs->csize * 512; /* Cluster size (byte) */ 00706 if (ifptr > 0 && 00707 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ 00708 fs->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ 00709 ofs -= fs->fptr; 00710 clst = fs->curr_clust; 00711 } else { /* When seek to back cluster, */ 00712 clst = fs->org_clust; /* start from the first cluster */ 00713 fs->curr_clust = clst; 00714 } 00715 while (ofs > bcs) { /* Cluster following loop */ 00716 clst = get_fat(fs, clst); /* Follow cluster chain */ 00717 if (clst <= 1 || clst >= fs->max_clust) goto fe_abort; 00718 fs->curr_clust = clst; 00719 fs->fptr += bcs; 00720 ofs -= bcs; 00721 } 00722 fs->fptr += ofs; 00723 sect = clust2sect(fs, clst); /* Current sector */ 00724 if (!sect) goto fe_abort; 00725 fs->csect = (BYTE)(ofs / 512); /* Sector offset in the cluster */ 00726 if (ofs % 512) 00727 fs->dsect = sect + fs->csect++; 00728 } 00729 00730 return FR_OK; 00731 00732 fe_abort: 00733 fs->flag = 0; 00734 return FR_DISK_ERR; 00735 } 00736 #endif 00737 00738 00739 00740 /*-----------------------------------------------------------------------*/ 00741 /* Create a Directroy Object */ 00742 /*-----------------------------------------------------------------------*/ 00743 #if _USE_DIR 00744 00745 PetitFileSystem::FRESULT PetitFileSystem::opendir ( 00746 const char *path /* Pointer to the directory path */ 00747 ) { 00748 FRESULT res; 00749 BYTE sp[12], dir[32]; 00750 FATDIR *dj = &DirectoryObject; 00751 00752 if (!FatFs) { /* Check file system */ 00753 res = FR_NOT_ENABLED; 00754 } else { 00755 FatFs->buf = dir; 00756 dj->fn = sp; 00757 res = follow_path(FatFs, dj, path); /* Follow the path to the directory */ 00758 if (res == FR_OK) { /* Follow completed */ 00759 if (dir[0]) { /* It is not the root dir */ 00760 if (dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ 00761 dj->sclust = 00762 #if _FS_FAT32 00763 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00764 #endif 00765 LD_WORD(dir+DIR_FstClusLO); 00766 } else { /* The object is not a directory */ 00767 res = FR_NO_PATH; 00768 } 00769 } 00770 if (res == FR_OK) 00771 res = dir_rewind(FatFs, dj); /* Rewind dir */ 00772 } 00773 if (res == FR_NO_FILE) res = FR_NO_PATH; 00774 } 00775 00776 return res; 00777 } 00778 00779 00780 00781 00782 /*-----------------------------------------------------------------------*/ 00783 /* Read Directory Entry in Sequense */ 00784 /*-----------------------------------------------------------------------*/ 00785 00786 PetitFileSystem::FRESULT PetitFileSystem::readdir ( 00787 FILINFO *fno /* Pointer to file information to return */ 00788 ) { 00789 FRESULT res; 00790 BYTE sp[12], dir[32]; 00791 FATDIR *dj = &DirectoryObject; 00792 00793 if (!FatFs) { /* Check file system */ 00794 res = FR_NOT_ENABLED; 00795 } else { 00796 FatFs->buf = dir; 00797 dj->fn = sp; 00798 if (!fno) { 00799 res = dir_rewind(FatFs, dj); 00800 } else { 00801 res = dir_read(FatFs, dj); 00802 if (res == FR_NO_FILE) { 00803 dj->sect = 0; 00804 res = FR_OK; 00805 } 00806 if (res == FR_OK) { /* A valid entry is found */ 00807 get_fileinfo(FatFs, dj, fno); /* Get the object information */ 00808 res = dir_next(FatFs, dj); /* Increment index for next */ 00809 if (res == FR_NO_FILE) { 00810 dj->sect = 0; 00811 res = FR_OK; 00812 } 00813 } 00814 } 00815 } 00816 00817 return res; 00818 } 00819 00820 #endif /* _USE_DIR */ 00821
Generated on Mon Jul 18 2022 15:07:54 by
1.7.2