Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
fs_port_fatfs.c
Go to the documentation of this file.
00001 /** 00002 * @file fs_port_fatfs.c 00003 * @brief File system abstraction layer (FatFs) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00024 * @version 1.7.6 00025 **/ 00026 00027 //Dependencies 00028 #include <string.h> 00029 #include "fs_port.h" 00030 #include "error.h" 00031 #include "debug.h" 00032 00033 //FatFs specific headers 00034 #include "ff.h" 00035 00036 //File system objects 00037 static FATFS fs; 00038 static FIL fileTable[FS_MAX_FILES]; 00039 static DIR dirTable[FS_MAX_DIRS]; 00040 00041 //Mutex that protects critical sections 00042 static OsMutex fsMutex; 00043 00044 00045 /** 00046 * @brief File system initialization 00047 * @return Error code 00048 **/ 00049 00050 error_t fsInit(void) 00051 { 00052 FRESULT res; 00053 00054 //Clear file system objects 00055 memset(fileTable, 0, sizeof(fileTable)); 00056 memset(dirTable, 0, sizeof(dirTable)); 00057 00058 //Create a mutex to protect critical sections 00059 if(!osCreateMutex(&fsMutex)) 00060 { 00061 //Failed to create mutex 00062 return ERROR_OUT_OF_RESOURCES; 00063 } 00064 00065 //Revision 0.09b or lower? 00066 #if (_FATFS == 124 || _FATFS == 126 || _FATFS == 8085 || _FATFS == 8255 || \ 00067 _FATFS == 8237 || _FATFS == 6502 || _FATFS == 4004 || _FATFS == 82786) 00068 //Mount file system 00069 res = f_mount(0, &fs); 00070 //Revision 0.10 or higher? 00071 #else 00072 //Mount file system 00073 res = f_mount(&fs, "", 1); 00074 #endif 00075 00076 //Failed to mount file system? 00077 if(res != FR_OK) 00078 { 00079 //Clean up side effects 00080 osDeleteMutex(&fsMutex); 00081 //Report an error 00082 return ERROR_FAILURE; 00083 } 00084 00085 //Successful processing 00086 return NO_ERROR; 00087 } 00088 00089 00090 /** 00091 * @brief Check whether a file exists 00092 * @param[in] path NULL-terminated string specifying the filename 00093 * @return The function returns TRUE if the file exists. Otherwise FALSE is returned 00094 **/ 00095 00096 bool_t fsFileExists(const char_t *path) 00097 { 00098 FRESULT res; 00099 FILINFO fno; 00100 00101 //Long filename support? 00102 #if (_USE_LFN != 0) 00103 fno.lfname = NULL; 00104 fno.lfsize = 0; 00105 #endif 00106 00107 //Make sure the pathname is valid 00108 if(path == NULL) 00109 return FALSE; 00110 00111 #if (_FS_REENTRANT == 0) 00112 //Enter critical section 00113 osAcquireMutex(&fsMutex); 00114 #endif 00115 00116 //Check whether the file exists 00117 res = f_stat(path, &fno); 00118 00119 #if (_FS_REENTRANT == 0) 00120 //Leave critical section 00121 osReleaseMutex(&fsMutex); 00122 #endif 00123 00124 //Any error to report? 00125 if(res != FR_OK) 00126 return FALSE; 00127 00128 //Valid file? 00129 if(fno.fattrib & AM_DIR) 00130 return FALSE; 00131 else 00132 return TRUE; 00133 } 00134 00135 00136 /** 00137 * @brief Retrieve the size of the specified file 00138 * @param[in] path NULL-terminated string specifying the filename 00139 * @param[out] size Size of the file in bytes 00140 * @return Error code 00141 **/ 00142 00143 error_t fsGetFileSize(const char_t *path, uint32_t *size) 00144 { 00145 FRESULT res; 00146 FILINFO fno; 00147 00148 //Long filename support? 00149 #if (_USE_LFN != 0) 00150 fno.lfname = NULL; 00151 fno.lfsize = 0; 00152 #endif 00153 00154 //Check parameters 00155 if(path == NULL || size == NULL) 00156 return ERROR_INVALID_PARAMETER; 00157 00158 #if (_FS_REENTRANT == 0) 00159 //Enter critical section 00160 osAcquireMutex(&fsMutex); 00161 #endif 00162 00163 //Retrieve information about the specified file 00164 res = f_stat(path, &fno); 00165 00166 #if (_FS_REENTRANT == 0) 00167 //Leave critical section 00168 osReleaseMutex(&fsMutex); 00169 #endif 00170 00171 //Any error to report? 00172 if(res != FR_OK) 00173 return ERROR_FAILURE; 00174 //Valid file? 00175 if(fno.fattrib & AM_DIR) 00176 return ERROR_FAILURE; 00177 00178 //Return the size of the file 00179 *size = fno.fsize; 00180 00181 //Successful processing 00182 return NO_ERROR; 00183 } 00184 00185 00186 /** 00187 * @brief Rename the specified file 00188 * @param[in] oldPath NULL-terminated string specifying the pathname of the file to be renamed 00189 * @param[in] newPath NULL-terminated string specifying the new filename 00190 * @return Error code 00191 **/ 00192 00193 error_t fsRenameFile(const char_t *oldPath, const char_t *newPath) 00194 { 00195 FRESULT res; 00196 00197 //Check parameters 00198 if(oldPath == NULL || newPath == NULL) 00199 return ERROR_INVALID_PARAMETER; 00200 00201 #if (_FS_REENTRANT == 0) 00202 //Enter critical section 00203 osAcquireMutex(&fsMutex); 00204 #endif 00205 00206 //Rename the specified file 00207 res = f_rename(oldPath, newPath); 00208 00209 #if (_FS_REENTRANT == 0) 00210 //Leave critical section 00211 osReleaseMutex(&fsMutex); 00212 #endif 00213 00214 //Any error to report? 00215 if(res != FR_OK) 00216 return ERROR_FAILURE; 00217 00218 //Successful processing 00219 return NO_ERROR; 00220 } 00221 00222 00223 /** 00224 * @brief Delete a file 00225 * @param[in] path NULL-terminated string specifying the filename 00226 * @return Error code 00227 **/ 00228 00229 error_t fsDeleteFile(const char_t *path) 00230 { 00231 FRESULT res; 00232 00233 //Make sure the pathname is valid 00234 if(path == NULL) 00235 return ERROR_INVALID_PARAMETER; 00236 00237 #if (_FS_REENTRANT == 0) 00238 //Enter critical section 00239 osAcquireMutex(&fsMutex); 00240 #endif 00241 00242 //Delete the specified file 00243 res = f_unlink(path); 00244 00245 #if (_FS_REENTRANT == 0) 00246 //Leave critical section 00247 osReleaseMutex(&fsMutex); 00248 #endif 00249 00250 //Any error to report? 00251 if(res != FR_OK) 00252 return ERROR_FAILURE; 00253 00254 //Successful processing 00255 return NO_ERROR; 00256 } 00257 00258 00259 /** 00260 * @brief Open the specified file for reading or writing 00261 * @param[in] path NULL-terminated string specifying the filename 00262 * @param[in] mode Type of access permitted (FS_FILE_MODE_READ, 00263 * FS_FILE_MODE_WRITE or FS_FILE_MODE_CREATE) 00264 * @return File handle 00265 **/ 00266 00267 FsFile *fsOpenFile(const char_t *path, uint_t mode) 00268 { 00269 uint_t i; 00270 uint_t flags; 00271 FRESULT res; 00272 00273 //File pointer 00274 FsFile *file = NULL; 00275 00276 //Make sure the pathname is valid 00277 if(path == NULL) 00278 return NULL; 00279 00280 //Enter critical section 00281 osAcquireMutex(&fsMutex); 00282 00283 //Loop through the file objects 00284 for(i = 0; i < FS_MAX_FILES; i++) 00285 { 00286 //Unused file object found? 00287 if(fileTable[i].fs == NULL) 00288 { 00289 //Default access mode 00290 flags = 0; 00291 00292 //Check access mode 00293 if(mode & FS_FILE_MODE_READ) 00294 flags |= FA_READ; 00295 if(mode & FS_FILE_MODE_WRITE) 00296 flags |= FA_WRITE; 00297 if(mode & FS_FILE_MODE_CREATE) 00298 flags |= FA_OPEN_ALWAYS; 00299 if(mode & FS_FILE_MODE_TRUNC) 00300 flags |= FA_CREATE_ALWAYS; 00301 00302 //Open the specified file 00303 res = f_open(&fileTable[i], path, flags); 00304 00305 //Check status code 00306 if(res == FR_OK) 00307 file = &fileTable[i]; 00308 00309 //Stop immediately 00310 break; 00311 } 00312 } 00313 00314 //Leave critical section 00315 osReleaseMutex(&fsMutex); 00316 //Return a handle to the file 00317 return file; 00318 } 00319 00320 00321 /** 00322 * @brief Move to specified position in file 00323 * @param[in] file Handle that identifies the file 00324 * @param[in] offset Number of bytes to move from origin 00325 * @param[in] origin Position used as reference for the offset (FS_SEEK_SET, 00326 * FS_SEEK_CUR or FS_SEEK_END) 00327 * @return Error code 00328 **/ 00329 00330 error_t fsSeekFile(FsFile *file, int_t offset, uint_t origin) 00331 { 00332 FRESULT res; 00333 00334 //Make sure the file pointer is valid 00335 if(file == NULL) 00336 return ERROR_INVALID_PARAMETER; 00337 00338 #if (_FS_REENTRANT == 0) 00339 //Enter critical section 00340 osAcquireMutex(&fsMutex); 00341 #endif 00342 00343 //Offset is relative to the current file pointer position? 00344 if(origin == FS_SEEK_CUR) 00345 offset += f_tell((FIL *) file); 00346 //Offset is relative to the end of the file? 00347 else if(origin == FS_SEEK_END) 00348 offset += f_size((FIL *) file); 00349 00350 //Move read/write pointer 00351 res = f_lseek((FIL *) file, offset); 00352 00353 #if (_FS_REENTRANT == 0) 00354 //Leave critical section 00355 osReleaseMutex(&fsMutex); 00356 #endif 00357 00358 //Any error to report? 00359 if(res != FR_OK) 00360 return ERROR_FAILURE; 00361 00362 //Successful processing 00363 return NO_ERROR; 00364 } 00365 00366 00367 /** 00368 * @brief Write data to the specified file 00369 * @param[in] file Handle that identifies the file to be written 00370 * @param[in] data Pointer to a buffer containing the data to be written 00371 * @param[in] length Number of data bytes to write 00372 * @return Error code 00373 **/ 00374 00375 error_t fsWriteFile(FsFile *file, void *data, size_t length) 00376 { 00377 UINT n; 00378 FRESULT res; 00379 00380 //Make sure the file pointer is valid 00381 if(file == NULL) 00382 return ERROR_INVALID_PARAMETER; 00383 00384 #if (_FS_REENTRANT == 0) 00385 //Enter critical section 00386 osAcquireMutex(&fsMutex); 00387 #endif 00388 00389 //Write data 00390 res = f_write((FIL *) file, data, length, &n); 00391 00392 #if (_FS_REENTRANT == 0) 00393 //Leave critical section 00394 osReleaseMutex(&fsMutex); 00395 #endif 00396 00397 //Any error to report? 00398 if(res != FR_OK) 00399 return ERROR_FAILURE; 00400 00401 //Sanity check 00402 if(n != length) 00403 return ERROR_FAILURE; 00404 00405 //Successful processing 00406 return NO_ERROR; 00407 } 00408 00409 00410 /** 00411 * @brief Read data from the specified file 00412 * @param[in] file Handle that identifies the file to be read 00413 * @param[in] data Pointer to the buffer where to copy the data 00414 * @param[in] size Size of the buffer, in bytes 00415 * @param[out] length Number of data bytes that have been read 00416 * @return Error code 00417 **/ 00418 00419 error_t fsReadFile(FsFile *file, void *data, size_t size, size_t *length) 00420 { 00421 UINT n; 00422 FRESULT res; 00423 00424 //No data has been read yet 00425 *length = 0; 00426 00427 //Make sure the file pointer is valid 00428 if(file == NULL) 00429 return ERROR_INVALID_PARAMETER; 00430 00431 #if (_FS_REENTRANT == 0) 00432 //Enter critical section 00433 osAcquireMutex(&fsMutex); 00434 #endif 00435 00436 //Read data 00437 res = f_read((FIL *) file, data, size, &n); 00438 00439 #if (_FS_REENTRANT == 0) 00440 //Leave critical section 00441 osReleaseMutex(&fsMutex); 00442 #endif 00443 00444 //Any error to report? 00445 if(res != FR_OK) 00446 return ERROR_FAILURE; 00447 00448 //End of file? 00449 if(!n) 00450 return ERROR_END_OF_FILE; 00451 00452 //Total number of data that have been read 00453 *length = n; 00454 //Successful processing 00455 return NO_ERROR; 00456 } 00457 00458 00459 /** 00460 * @brief Close a file 00461 * @param[in] file Handle that identifies the file to be closed 00462 **/ 00463 00464 void fsCloseFile(FsFile *file) 00465 { 00466 //Make sure the file pointer is valid 00467 if(file != NULL) 00468 { 00469 //Enter critical section 00470 osAcquireMutex(&fsMutex); 00471 00472 //Close the specified file 00473 f_close((FIL *) file); 00474 //Mark the corresponding entry as free 00475 ((FIL *) file)->fs = NULL; 00476 00477 //Leave critical section 00478 osReleaseMutex(&fsMutex); 00479 } 00480 } 00481 00482 00483 /** 00484 * @brief Check whether a directory exists 00485 * @param[in] path NULL-terminated string specifying the directory path 00486 * @return The function returns TRUE if the directory exists. Otherwise FALSE is returned 00487 **/ 00488 00489 bool_t fsDirExists(const char_t *path) 00490 { 00491 FRESULT res; 00492 FILINFO fno; 00493 00494 //Long filename support? 00495 #if (_USE_LFN != 0) 00496 fno.lfname = NULL; 00497 fno.lfsize = 0; 00498 #endif 00499 00500 //Make sure the pathname is valid 00501 if(path == NULL) 00502 return FALSE; 00503 00504 //Root directory? 00505 if(!strcmp(path, "/")) 00506 return TRUE; 00507 00508 #if (_FS_REENTRANT == 0) 00509 //Enter critical section 00510 osAcquireMutex(&fsMutex); 00511 #endif 00512 00513 //Check whether the file exists 00514 res = f_stat(path, &fno); 00515 00516 #if (_FS_REENTRANT == 0) 00517 //Leave critical section 00518 osReleaseMutex(&fsMutex); 00519 #endif 00520 00521 //Any error to report? 00522 if(res != FR_OK) 00523 return FALSE; 00524 00525 //Valid directory? 00526 if(fno.fattrib & AM_DIR) 00527 return TRUE; 00528 else 00529 return FALSE; 00530 } 00531 00532 00533 /** 00534 * @brief Create a directory 00535 * @param[in] path NULL-terminated string specifying the directory path 00536 * @return Error code 00537 **/ 00538 00539 error_t fsCreateDir(const char_t *path) 00540 { 00541 FRESULT res; 00542 00543 //Make sure the pathname is valid 00544 if(path == NULL) 00545 return ERROR_INVALID_PARAMETER; 00546 00547 #if (_FS_REENTRANT == 0) 00548 //Enter critical section 00549 osAcquireMutex(&fsMutex); 00550 #endif 00551 00552 //Create a new directory 00553 res = f_mkdir(path); 00554 00555 #if (_FS_REENTRANT == 0) 00556 //Leave critical section 00557 osReleaseMutex(&fsMutex); 00558 #endif 00559 00560 //Any error to report? 00561 if(res != FR_OK) 00562 return ERROR_FAILURE; 00563 00564 //Successful processing 00565 return NO_ERROR; 00566 } 00567 00568 00569 /** 00570 * @brief Remove a directory 00571 * @param[in] path NULL-terminated string specifying the directory path 00572 * @return Error code 00573 **/ 00574 00575 error_t fsRemoveDir(const char_t *path) 00576 { 00577 FRESULT res; 00578 00579 //Make sure the pathname is valid 00580 if(path == NULL) 00581 return ERROR_INVALID_PARAMETER; 00582 00583 #if (_FS_REENTRANT == 0) 00584 //Enter critical section 00585 osAcquireMutex(&fsMutex); 00586 #endif 00587 00588 //Remove the specified directory 00589 res = f_unlink(path); 00590 00591 #if (_FS_REENTRANT == 0) 00592 //Leave critical section 00593 osReleaseMutex(&fsMutex); 00594 #endif 00595 00596 //Any error to report? 00597 if(res != FR_OK) 00598 return ERROR_FAILURE; 00599 00600 //Successful processing 00601 return NO_ERROR; 00602 } 00603 00604 00605 /** 00606 * @brief Open a directory stream 00607 * @param[in] path NULL-terminated string specifying the directory path 00608 * @return Directory handle 00609 **/ 00610 00611 FsDir *fsOpenDir(const char_t *path) 00612 { 00613 uint_t i; 00614 FRESULT res; 00615 00616 //Directory pointer 00617 FsDir *dir = NULL; 00618 00619 //Make sure the pathname is valid 00620 if(path == NULL) 00621 return NULL; 00622 00623 //Enter critical section 00624 osAcquireMutex(&fsMutex); 00625 00626 //Loop through the directory objects 00627 for(i = 0; i < FS_MAX_DIRS; i++) 00628 { 00629 //Unused directory object found? 00630 if(dirTable[i].fs == NULL) 00631 { 00632 //Open the specified directory 00633 res = f_opendir(&dirTable[i], path); 00634 00635 //Check status code 00636 if(res == FR_OK) 00637 dir = &dirTable[i]; 00638 00639 //Stop immediately 00640 break; 00641 } 00642 } 00643 00644 //Leave critical section 00645 osReleaseMutex(&fsMutex); 00646 //Return a handle to the directory 00647 return dir; 00648 } 00649 00650 00651 /** 00652 * @brief Read an entry from the specified directory stream 00653 * @param[in] dir Handle that identifies the directory 00654 * @param[out] dirEntry Pointer to a directory entry 00655 * @return Error code 00656 **/ 00657 00658 error_t fsReadDir(FsDir *dir, FsDirEntry *dirEntry) 00659 { 00660 FRESULT res; 00661 FILINFO fno; 00662 char_t *fn; 00663 size_t n; 00664 00665 //Long filename support? 00666 #if (_USE_LFN != 0) 00667 char_t lfn[_MAX_LFN + 1]; 00668 fno.lfname = lfn; 00669 fno.lfsize = sizeof(lfn); 00670 #endif 00671 00672 //Make sure the directory pointer is valid 00673 if(dir == NULL) 00674 return ERROR_INVALID_PARAMETER; 00675 00676 #if (_FS_REENTRANT == 0) 00677 //Enter critical section 00678 osAcquireMutex(&fsMutex); 00679 #endif 00680 00681 //Read the specified directory 00682 res = f_readdir((DIR *) dir, &fno); 00683 00684 #if (_FS_REENTRANT == 0) 00685 //Leave critical section 00686 osReleaseMutex(&fsMutex); 00687 #endif 00688 00689 //Any error to report? 00690 if(res != FR_OK) 00691 return ERROR_FAILURE; 00692 00693 //End of the directory stream? 00694 if(fno.fname[0] == '\0') 00695 return ERROR_END_OF_STREAM; 00696 00697 //Long filename support? 00698 #if (_USE_LFN != 0) 00699 fn = (*fno.lfname != '\0') ? fno.lfname : fno.fname; 00700 #else 00701 fn = fno.fname; 00702 #endif 00703 00704 //File attributes 00705 dirEntry->attributes = fno.fattrib; 00706 //File size 00707 dirEntry->size = fno.fsize; 00708 //Last modified date 00709 dirEntry->modified.year = 1980 + ((fno.fdate >> 9) & 0x7F); 00710 dirEntry->modified.month = (fno.fdate >> 5) & 0x0F; 00711 dirEntry->modified.day = fno.fdate & 0x1F; 00712 dirEntry->modified.dayOfWeek = 0; 00713 //Last modified time 00714 dirEntry->modified.hours = (fno.ftime >> 11) & 0x1F; 00715 dirEntry->modified.minutes = (fno.ftime >> 5) & 0x3F; 00716 dirEntry->modified.seconds = (fno.ftime & 0x1F) * 2; 00717 dirEntry->modified.milliseconds = 0; 00718 00719 //Make sure the date is valid 00720 dirEntry->modified.month = MAX(dirEntry->modified.month, 1); 00721 dirEntry->modified.month = MIN(dirEntry->modified.month, 12); 00722 dirEntry->modified.day = MAX(dirEntry->modified.day, 1); 00723 dirEntry->modified.day = MIN(dirEntry->modified.day, 31); 00724 00725 //Retrieve the length of the file name 00726 n = strlen(fn); 00727 //Limit the number of characters to be copied 00728 n = MIN(n, FS_MAX_NAME_LEN); 00729 00730 //Copy file name 00731 strncpy(dirEntry->name, fn, n); 00732 //Properly terminate the string with a NULL character 00733 dirEntry->name[n] = '\0'; 00734 00735 //Successful processing 00736 return NO_ERROR; 00737 } 00738 00739 00740 /** 00741 * @brief Close a directory stream 00742 * @param[in] dir Handle that identifies the directory to be closed 00743 **/ 00744 00745 void fsCloseDir(FsDir *dir) 00746 { 00747 //Make sure the directory pointer is valid 00748 if(dir != NULL) 00749 { 00750 //Enter critical section 00751 osAcquireMutex(&fsMutex); 00752 00753 #if (_FATFS == 80960) 00754 //Close the specified directory 00755 f_closedir((DIR *) dir); 00756 #endif 00757 //Mark the corresponding entry as free 00758 ((DIR *) dir)->fs = NULL; 00759 00760 //Leave critical section 00761 osReleaseMutex(&fsMutex); 00762 } 00763 } 00764
Generated on Tue Jul 12 2022 17:10:13 by
