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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
tinydir.h
00001 /* 00002 Copyright (c) 2013-2017, tinydir authors: 00003 - Cong Xu 00004 - Lautis Sun 00005 - Baudouin Feildel 00006 - Andargor <andargor@yahoo.com> 00007 All rights reserved. 00008 00009 Redistribution and use in source and binary forms, with or without 00010 modification, are permitted provided that the following conditions are met: 00011 00012 1. Redistributions of source code must retain the above copyright notice, this 00013 list of conditions and the following disclaimer. 00014 2. Redistributions in binary form must reproduce the above copyright notice, 00015 this list of conditions and the following disclaimer in the documentation 00016 and/or other materials provided with the distribution. 00017 00018 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00019 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00020 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00021 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 00022 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00024 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00025 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00026 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00027 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #ifndef TINYDIR_H 00030 #define TINYDIR_H 00031 00032 #ifdef __cplusplus 00033 extern "C" { 00034 #endif 00035 00036 #if ((defined _UNICODE) && !(defined UNICODE)) 00037 #define UNICODE 00038 #endif 00039 00040 #if ((defined UNICODE) && !(defined _UNICODE)) 00041 #define _UNICODE 00042 #endif 00043 00044 #include <errno.h> 00045 #include <stdlib.h> 00046 #include <string.h> 00047 #ifdef _MSC_VER 00048 # define WIN32_LEAN_AND_MEAN 00049 # include <windows.h> 00050 # include <tchar.h> 00051 # pragma warning(push) 00052 # pragma warning (disable : 4996) 00053 #else 00054 # include <dirent.h> 00055 # include <libgen.h> 00056 # include <sys/stat.h> 00057 # include <stddef.h> 00058 #endif 00059 #ifdef __MINGW32__ 00060 # include <tchar.h> 00061 #endif 00062 00063 00064 /* types */ 00065 00066 /* Windows UNICODE wide character support */ 00067 #if defined _MSC_VER || defined __MINGW32__ 00068 #define _tinydir_char_t TCHAR 00069 #define TINYDIR_STRING(s) _TEXT(s) 00070 #define _tinydir_strlen _tcslen 00071 #define _tinydir_strcpy _tcscpy 00072 #define _tinydir_strcat _tcscat 00073 #define _tinydir_strcmp _tcscmp 00074 #define _tinydir_strrchr _tcsrchr 00075 #define _tinydir_strncmp _tcsncmp 00076 #else 00077 #define _tinydir_char_t char 00078 #define TINYDIR_STRING(s) s 00079 #define _tinydir_strlen strlen 00080 #define _tinydir_strcpy strcpy 00081 #define _tinydir_strcat strcat 00082 #define _tinydir_strcmp strcmp 00083 #define _tinydir_strrchr strrchr 00084 #define _tinydir_strncmp strncmp 00085 #endif 00086 00087 #if (defined _MSC_VER || defined __MINGW32__) 00088 #include <windows.h> 00089 #define _TINYDIR_PATH_MAX MAX_PATH 00090 #elif defined __linux__ 00091 #include <linux/limits.h> 00092 #define _TINYDIR_PATH_MAX PATH_MAX 00093 #else 00094 #define _TINYDIR_PATH_MAX 4096 00095 #endif 00096 00097 #ifdef _MSC_VER 00098 /* extra chars for the "\\*" mask */ 00099 # define _TINYDIR_PATH_EXTRA 2 00100 #else 00101 # define _TINYDIR_PATH_EXTRA 0 00102 #endif 00103 00104 #define _TINYDIR_FILENAME_MAX 256 00105 00106 #if (defined _MSC_VER || defined __MINGW32__) 00107 #define _TINYDIR_DRIVE_MAX 3 00108 #endif 00109 00110 #ifdef _MSC_VER 00111 # define _TINYDIR_FUNC static __inline 00112 #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 00113 # define _TINYDIR_FUNC static __inline__ 00114 #else 00115 # define _TINYDIR_FUNC static inline 00116 #endif 00117 00118 /* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */ 00119 #ifdef TINYDIR_USE_READDIR_R 00120 00121 /* readdir_r is a POSIX-only function, and may not be available under various 00122 * environments/settings, e.g. MinGW. Use readdir fallback */ 00123 #if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\ 00124 _POSIX_SOURCE 00125 # define _TINYDIR_HAS_READDIR_R 00126 #endif 00127 #if _POSIX_C_SOURCE >= 200112L 00128 # define _TINYDIR_HAS_FPATHCONF 00129 # include <unistd.h> 00130 #endif 00131 #if _BSD_SOURCE || _SVID_SOURCE || \ 00132 (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) 00133 # define _TINYDIR_HAS_DIRFD 00134 # include <sys/types.h> 00135 #endif 00136 #if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\ 00137 defined _PC_NAME_MAX 00138 # define _TINYDIR_USE_FPATHCONF 00139 #endif 00140 #if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\ 00141 !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX) 00142 # define _TINYDIR_USE_READDIR 00143 #endif 00144 00145 /* Use readdir by default */ 00146 #else 00147 # define _TINYDIR_USE_READDIR 00148 #endif 00149 00150 /* MINGW32 has two versions of dirent, ASCII and UNICODE*/ 00151 #ifndef _MSC_VER 00152 #if (defined __MINGW32__) && (defined _UNICODE) 00153 #define _TINYDIR_DIR _WDIR 00154 #define _tinydir_dirent _wdirent 00155 #define _tinydir_opendir _wopendir 00156 #define _tinydir_readdir _wreaddir 00157 #define _tinydir_closedir _wclosedir 00158 #else 00159 #define _TINYDIR_DIR DIR 00160 #define _tinydir_dirent dirent 00161 #define _tinydir_opendir opendir 00162 #define _tinydir_readdir readdir 00163 #define _tinydir_closedir closedir 00164 #endif 00165 #endif 00166 00167 /* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */ 00168 #if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE) 00169 #elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE) 00170 #else 00171 #error "Either define both alloc and free or none of them!" 00172 #endif 00173 00174 #if !defined(_TINYDIR_MALLOC) 00175 #define _TINYDIR_MALLOC(_size) malloc(_size) 00176 #define _TINYDIR_FREE(_ptr) free(_ptr) 00177 #endif /* !defined(_TINYDIR_MALLOC) */ 00178 00179 typedef struct tinydir_file 00180 { 00181 _tinydir_char_t path[_TINYDIR_PATH_MAX]; 00182 _tinydir_char_t name[_TINYDIR_FILENAME_MAX]; 00183 _tinydir_char_t *extension; 00184 int is_dir; 00185 int is_reg; 00186 00187 #ifndef _MSC_VER 00188 #ifdef __MINGW32__ 00189 struct _stat _s; 00190 #else 00191 struct stat _s; 00192 #endif 00193 #endif 00194 } tinydir_file; 00195 00196 typedef struct tinydir_dir 00197 { 00198 _tinydir_char_t path[_TINYDIR_PATH_MAX]; 00199 int has_next; 00200 size_t n_files; 00201 00202 tinydir_file *_files; 00203 #ifdef _MSC_VER 00204 HANDLE _h; 00205 WIN32_FIND_DATA _f; 00206 #else 00207 _TINYDIR_DIR *_d; 00208 struct _tinydir_dirent *_e; 00209 #ifndef _TINYDIR_USE_READDIR 00210 struct _tinydir_dirent *_ep; 00211 #endif 00212 #endif 00213 } tinydir_dir; 00214 00215 00216 /* declarations */ 00217 00218 _TINYDIR_FUNC 00219 int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path); 00220 _TINYDIR_FUNC 00221 int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path); 00222 _TINYDIR_FUNC 00223 void tinydir_close(tinydir_dir *dir); 00224 00225 _TINYDIR_FUNC 00226 int tinydir_next(tinydir_dir *dir); 00227 _TINYDIR_FUNC 00228 int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file); 00229 _TINYDIR_FUNC 00230 int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i); 00231 _TINYDIR_FUNC 00232 int tinydir_open_subdir_n(tinydir_dir *dir, size_t i); 00233 00234 _TINYDIR_FUNC 00235 int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path); 00236 _TINYDIR_FUNC 00237 void _tinydir_get_ext(tinydir_file *file); 00238 _TINYDIR_FUNC 00239 int _tinydir_file_cmp(const void *a, const void *b); 00240 #ifndef _MSC_VER 00241 #ifndef _TINYDIR_USE_READDIR 00242 _TINYDIR_FUNC 00243 size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp); 00244 #endif 00245 #endif 00246 00247 00248 /* definitions*/ 00249 00250 _TINYDIR_FUNC 00251 int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) 00252 { 00253 #ifndef _MSC_VER 00254 #ifndef _TINYDIR_USE_READDIR 00255 int error; 00256 int size; /* using int size */ 00257 #endif 00258 #else 00259 _tinydir_char_t path_buf[_TINYDIR_PATH_MAX]; 00260 #endif 00261 _tinydir_char_t *pathp; 00262 00263 if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) 00264 { 00265 errno = EINVAL; 00266 return -1; 00267 } 00268 if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 00269 { 00270 errno = ENAMETOOLONG; 00271 return -1; 00272 } 00273 00274 /* initialise dir */ 00275 dir->_files = NULL; 00276 #ifdef _MSC_VER 00277 dir->_h = INVALID_HANDLE_VALUE; 00278 #else 00279 dir->_d = NULL; 00280 #ifndef _TINYDIR_USE_READDIR 00281 dir->_ep = NULL; 00282 #endif 00283 #endif 00284 tinydir_close(dir); 00285 00286 _tinydir_strcpy(dir->path, path); 00287 /* Remove trailing slashes */ 00288 pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; 00289 while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) 00290 { 00291 *pathp = TINYDIR_STRING('\0'); 00292 pathp++; 00293 } 00294 #ifdef _MSC_VER 00295 _tinydir_strcpy(path_buf, dir->path); 00296 _tinydir_strcat(path_buf, TINYDIR_STRING("\\*")); 00297 #if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) 00298 dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0); 00299 #else 00300 dir->_h = FindFirstFile(path_buf, &dir->_f); 00301 #endif 00302 if (dir->_h == INVALID_HANDLE_VALUE) 00303 { 00304 errno = ENOENT; 00305 #else 00306 dir->_d = _tinydir_opendir(path); 00307 if (dir->_d == NULL) 00308 { 00309 #endif 00310 goto bail; 00311 } 00312 00313 /* read first file */ 00314 dir->has_next = 1; 00315 #ifndef _MSC_VER 00316 #ifdef _TINYDIR_USE_READDIR 00317 dir->_e = _tinydir_readdir(dir->_d); 00318 #else 00319 /* allocate dirent buffer for readdir_r */ 00320 size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ 00321 if (size == -1) return -1; 00322 dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); 00323 if (dir->_ep == NULL) return -1; 00324 00325 error = readdir_r(dir->_d, dir->_ep, &dir->_e); 00326 if (error != 0) return -1; 00327 #endif 00328 if (dir->_e == NULL) 00329 { 00330 dir->has_next = 0; 00331 } 00332 #endif 00333 00334 return 0; 00335 00336 bail: 00337 tinydir_close(dir); 00338 return -1; 00339 } 00340 00341 _TINYDIR_FUNC 00342 int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) 00343 { 00344 /* Count the number of files first, to pre-allocate the files array */ 00345 size_t n_files = 0; 00346 if (tinydir_open(dir, path) == -1) 00347 { 00348 return -1; 00349 } 00350 while (dir->has_next) 00351 { 00352 n_files++; 00353 if (tinydir_next(dir) == -1) 00354 { 00355 goto bail; 00356 } 00357 } 00358 tinydir_close(dir); 00359 00360 if (tinydir_open(dir, path) == -1) 00361 { 00362 return -1; 00363 } 00364 00365 dir->n_files = 0; 00366 dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); 00367 if (dir->_files == NULL) 00368 { 00369 goto bail; 00370 } 00371 while (dir->has_next) 00372 { 00373 tinydir_file *p_file; 00374 dir->n_files++; 00375 00376 p_file = &dir->_files[dir->n_files - 1]; 00377 if (tinydir_readfile(dir, p_file) == -1) 00378 { 00379 goto bail; 00380 } 00381 00382 if (tinydir_next(dir) == -1) 00383 { 00384 goto bail; 00385 } 00386 00387 /* Just in case the number of files has changed between the first and 00388 second reads, terminate without writing into unallocated memory */ 00389 if (dir->n_files == n_files) 00390 { 00391 break; 00392 } 00393 } 00394 00395 qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp); 00396 00397 return 0; 00398 00399 bail: 00400 tinydir_close(dir); 00401 return -1; 00402 } 00403 00404 _TINYDIR_FUNC 00405 void tinydir_close(tinydir_dir *dir) 00406 { 00407 if (dir == NULL) 00408 { 00409 return; 00410 } 00411 00412 memset(dir->path, 0, sizeof(dir->path)); 00413 dir->has_next = 0; 00414 dir->n_files = 0; 00415 _TINYDIR_FREE(dir->_files); 00416 dir->_files = NULL; 00417 #ifdef _MSC_VER 00418 if (dir->_h != INVALID_HANDLE_VALUE) 00419 { 00420 FindClose(dir->_h); 00421 } 00422 dir->_h = INVALID_HANDLE_VALUE; 00423 #else 00424 if (dir->_d) 00425 { 00426 _tinydir_closedir(dir->_d); 00427 } 00428 dir->_d = NULL; 00429 dir->_e = NULL; 00430 #ifndef _TINYDIR_USE_READDIR 00431 _TINYDIR_FREE(dir->_ep); 00432 dir->_ep = NULL; 00433 #endif 00434 #endif 00435 } 00436 00437 _TINYDIR_FUNC 00438 int tinydir_next(tinydir_dir *dir) 00439 { 00440 if (dir == NULL) 00441 { 00442 errno = EINVAL; 00443 return -1; 00444 } 00445 if (!dir->has_next) 00446 { 00447 errno = ENOENT; 00448 return -1; 00449 } 00450 00451 #ifdef _MSC_VER 00452 if (FindNextFile(dir->_h, &dir->_f) == 0) 00453 #else 00454 #ifdef _TINYDIR_USE_READDIR 00455 dir->_e = _tinydir_readdir(dir->_d); 00456 #else 00457 if (dir->_ep == NULL) 00458 { 00459 return -1; 00460 } 00461 if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) 00462 { 00463 return -1; 00464 } 00465 #endif 00466 if (dir->_e == NULL) 00467 #endif 00468 { 00469 dir->has_next = 0; 00470 #ifdef _MSC_VER 00471 if (GetLastError() != ERROR_SUCCESS && 00472 GetLastError() != ERROR_NO_MORE_FILES) 00473 { 00474 tinydir_close(dir); 00475 errno = EIO; 00476 return -1; 00477 } 00478 #endif 00479 } 00480 00481 return 0; 00482 } 00483 00484 _TINYDIR_FUNC 00485 int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) 00486 { 00487 if (dir == NULL || file == NULL) 00488 { 00489 errno = EINVAL; 00490 return -1; 00491 } 00492 #ifdef _MSC_VER 00493 if (dir->_h == INVALID_HANDLE_VALUE) 00494 #else 00495 if (dir->_e == NULL) 00496 #endif 00497 { 00498 errno = ENOENT; 00499 return -1; 00500 } 00501 if (_tinydir_strlen(dir->path) + 00502 _tinydir_strlen( 00503 #ifdef _MSC_VER 00504 dir->_f.cFileName 00505 #else 00506 dir->_e->d_name 00507 #endif 00508 ) + 1 + _TINYDIR_PATH_EXTRA >= 00509 _TINYDIR_PATH_MAX) 00510 { 00511 /* the path for the file will be too long */ 00512 errno = ENAMETOOLONG; 00513 return -1; 00514 } 00515 if (_tinydir_strlen( 00516 #ifdef _MSC_VER 00517 dir->_f.cFileName 00518 #else 00519 dir->_e->d_name 00520 #endif 00521 ) >= _TINYDIR_FILENAME_MAX) 00522 { 00523 errno = ENAMETOOLONG; 00524 return -1; 00525 } 00526 00527 _tinydir_strcpy(file->path, dir->path); 00528 _tinydir_strcat(file->path, TINYDIR_STRING("/")); 00529 _tinydir_strcpy(file->name, 00530 #ifdef _MSC_VER 00531 dir->_f.cFileName 00532 #else 00533 dir->_e->d_name 00534 #endif 00535 ); 00536 _tinydir_strcat(file->path, file->name); 00537 #ifndef _MSC_VER 00538 #ifdef __MINGW32__ 00539 if (_tstat( 00540 #else 00541 if (stat( 00542 #endif 00543 file->path, &file->_s) == -1) 00544 { 00545 return -1; 00546 } 00547 #endif 00548 _tinydir_get_ext(file); 00549 00550 file->is_dir = 00551 #ifdef _MSC_VER 00552 !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 00553 #else 00554 S_ISDIR(file->_s.st_mode); 00555 #endif 00556 file->is_reg = 00557 #ifdef _MSC_VER 00558 !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || 00559 ( 00560 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && 00561 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && 00562 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && 00563 #ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM 00564 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && 00565 #endif 00566 #ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA 00567 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && 00568 #endif 00569 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && 00570 !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); 00571 #else 00572 S_ISREG(file->_s.st_mode); 00573 #endif 00574 00575 return 0; 00576 } 00577 00578 _TINYDIR_FUNC 00579 int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) 00580 { 00581 if (dir == NULL || file == NULL) 00582 { 00583 errno = EINVAL; 00584 return -1; 00585 } 00586 if (i >= dir->n_files) 00587 { 00588 errno = ENOENT; 00589 return -1; 00590 } 00591 00592 memcpy(file, &dir->_files[i], sizeof(tinydir_file)); 00593 _tinydir_get_ext(file); 00594 00595 return 0; 00596 } 00597 00598 _TINYDIR_FUNC 00599 int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) 00600 { 00601 _tinydir_char_t path[_TINYDIR_PATH_MAX]; 00602 if (dir == NULL) 00603 { 00604 errno = EINVAL; 00605 return -1; 00606 } 00607 if (i >= dir->n_files || !dir->_files[i].is_dir) 00608 { 00609 errno = ENOENT; 00610 return -1; 00611 } 00612 00613 _tinydir_strcpy(path, dir->_files[i].path); 00614 tinydir_close(dir); 00615 if (tinydir_open_sorted(dir, path) == -1) 00616 { 00617 return -1; 00618 } 00619 00620 return 0; 00621 } 00622 00623 /* Open a single file given its path */ 00624 _TINYDIR_FUNC 00625 int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) 00626 { 00627 tinydir_dir dir; 00628 int result = 0; 00629 int found = 0; 00630 _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX]; 00631 _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX]; 00632 _tinydir_char_t *dir_name; 00633 _tinydir_char_t *base_name; 00634 #if (defined _MSC_VER || defined __MINGW32__) 00635 _tinydir_char_t drive_buf[_TINYDIR_PATH_MAX]; 00636 _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; 00637 #endif 00638 00639 if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) 00640 { 00641 errno = EINVAL; 00642 return -1; 00643 } 00644 if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 00645 { 00646 errno = ENAMETOOLONG; 00647 return -1; 00648 } 00649 00650 /* Get the parent path */ 00651 #if (defined _MSC_VER || defined __MINGW32__) 00652 #if ((defined _MSC_VER) && (_MSC_VER >= 1400)) 00653 _tsplitpath_s( 00654 path, 00655 drive_buf, _TINYDIR_DRIVE_MAX, 00656 dir_name_buf, _TINYDIR_FILENAME_MAX, 00657 file_name_buf, _TINYDIR_FILENAME_MAX, 00658 ext_buf, _TINYDIR_FILENAME_MAX); 00659 #else 00660 _tsplitpath( 00661 path, 00662 drive_buf, 00663 dir_name_buf, 00664 file_name_buf, 00665 ext_buf); 00666 #endif 00667 00668 /* _splitpath_s not work fine with only filename and widechar support */ 00669 #ifdef _UNICODE 00670 if (drive_buf[0] == L'\xFEFE') 00671 drive_buf[0] = '\0'; 00672 if (dir_name_buf[0] == L'\xFEFE') 00673 dir_name_buf[0] = '\0'; 00674 #endif 00675 00676 if (errno) 00677 { 00678 errno = EINVAL; 00679 return -1; 00680 } 00681 /* Emulate the behavior of dirname by returning "." for dir name if it's 00682 empty */ 00683 if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') 00684 { 00685 _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); 00686 } 00687 /* Concatenate the drive letter and dir name to form full dir name */ 00688 _tinydir_strcat(drive_buf, dir_name_buf); 00689 dir_name = drive_buf; 00690 /* Concatenate the file name and extension to form base name */ 00691 _tinydir_strcat(file_name_buf, ext_buf); 00692 base_name = file_name_buf; 00693 #else 00694 _tinydir_strcpy(dir_name_buf, path); 00695 dir_name = dirname(dir_name_buf); 00696 _tinydir_strcpy(file_name_buf, path); 00697 base_name =basename(file_name_buf); 00698 #endif 00699 00700 /* Open the parent directory */ 00701 if (tinydir_open(&dir, dir_name) == -1) 00702 { 00703 return -1; 00704 } 00705 00706 /* Read through the parent directory and look for the file */ 00707 while (dir.has_next) 00708 { 00709 if (tinydir_readfile(&dir, file) == -1) 00710 { 00711 result = -1; 00712 goto bail; 00713 } 00714 if (_tinydir_strcmp(file->name, base_name) == 0) 00715 { 00716 /* File found */ 00717 found = 1; 00718 break; 00719 } 00720 tinydir_next(&dir); 00721 } 00722 if (!found) 00723 { 00724 result = -1; 00725 errno = ENOENT; 00726 } 00727 00728 bail: 00729 tinydir_close(&dir); 00730 return result; 00731 } 00732 00733 _TINYDIR_FUNC 00734 void _tinydir_get_ext(tinydir_file *file) 00735 { 00736 _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); 00737 if (period == NULL) 00738 { 00739 file->extension = &(file->name[_tinydir_strlen(file->name)]); 00740 } 00741 else 00742 { 00743 file->extension = period + 1; 00744 } 00745 } 00746 00747 _TINYDIR_FUNC 00748 int _tinydir_file_cmp(const void *a, const void *b) 00749 { 00750 const tinydir_file *fa = (const tinydir_file *)a; 00751 const tinydir_file *fb = (const tinydir_file *)b; 00752 if (fa->is_dir != fb->is_dir) 00753 { 00754 return -(fa->is_dir - fb->is_dir); 00755 } 00756 return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); 00757 } 00758 00759 #ifndef _MSC_VER 00760 #ifndef _TINYDIR_USE_READDIR 00761 /* 00762 The following authored by Ben Hutchings <ben@decadent.org.uk> 00763 from https://womble.decadent.org.uk/readdir_r-advisory.html 00764 */ 00765 /* Calculate the required buffer size (in bytes) for directory * 00766 * entries read from the given directory handle. Return -1 if this * 00767 * this cannot be done. * 00768 * * 00769 * This code does not trust values of NAME_MAX that are less than * 00770 * 255, since some systems (including at least HP-UX) incorrectly * 00771 * define it to be a smaller value. */ 00772 _TINYDIR_FUNC 00773 size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) 00774 { 00775 long name_max; 00776 size_t name_end; 00777 /* parameter may be unused */ 00778 (void)dirp; 00779 00780 #if defined _TINYDIR_USE_FPATHCONF 00781 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); 00782 if (name_max == -1) 00783 #if defined(NAME_MAX) 00784 name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 00785 #else 00786 return (size_t)(-1); 00787 #endif 00788 #elif defined(NAME_MAX) 00789 name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 00790 #else 00791 #error "buffer size for readdir_r cannot be determined" 00792 #endif 00793 name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; 00794 return (name_end > sizeof(struct _tinydir_dirent) ? 00795 name_end : sizeof(struct _tinydir_dirent)); 00796 } 00797 #endif 00798 #endif 00799 00800 #ifdef __cplusplus 00801 } 00802 #endif 00803 00804 # if defined (_MSC_VER) 00805 # pragma warning(pop) 00806 # endif 00807 00808 #endif
Generated on Tue Jul 12 2022 13:55:00 by
