1*98cd9557SMatthias Ringwald /* 2*98cd9557SMatthias Ringwald Copyright (c) 2013-2017, tinydir authors: 3*98cd9557SMatthias Ringwald - Cong Xu 4*98cd9557SMatthias Ringwald - Lautis Sun 5*98cd9557SMatthias Ringwald - Baudouin Feildel 6*98cd9557SMatthias Ringwald - Andargor <[email protected]> 7*98cd9557SMatthias Ringwald All rights reserved. 8*98cd9557SMatthias Ringwald 9*98cd9557SMatthias Ringwald Redistribution and use in source and binary forms, with or without 10*98cd9557SMatthias Ringwald modification, are permitted provided that the following conditions are met: 11*98cd9557SMatthias Ringwald 12*98cd9557SMatthias Ringwald 1. Redistributions of source code must retain the above copyright notice, this 13*98cd9557SMatthias Ringwald list of conditions and the following disclaimer. 14*98cd9557SMatthias Ringwald 2. Redistributions in binary form must reproduce the above copyright notice, 15*98cd9557SMatthias Ringwald this list of conditions and the following disclaimer in the documentation 16*98cd9557SMatthias Ringwald and/or other materials provided with the distribution. 17*98cd9557SMatthias Ringwald 18*98cd9557SMatthias Ringwald THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19*98cd9557SMatthias Ringwald ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20*98cd9557SMatthias Ringwald WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21*98cd9557SMatthias Ringwald DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22*98cd9557SMatthias Ringwald ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23*98cd9557SMatthias Ringwald (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24*98cd9557SMatthias Ringwald LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25*98cd9557SMatthias Ringwald ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*98cd9557SMatthias Ringwald (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27*98cd9557SMatthias Ringwald SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*98cd9557SMatthias Ringwald */ 29*98cd9557SMatthias Ringwald #ifndef TINYDIR_H 30*98cd9557SMatthias Ringwald #define TINYDIR_H 31*98cd9557SMatthias Ringwald 32*98cd9557SMatthias Ringwald #ifdef __cplusplus 33*98cd9557SMatthias Ringwald extern "C" { 34*98cd9557SMatthias Ringwald #endif 35*98cd9557SMatthias Ringwald 36*98cd9557SMatthias Ringwald #if ((defined _UNICODE) && !(defined UNICODE)) 37*98cd9557SMatthias Ringwald #define UNICODE 38*98cd9557SMatthias Ringwald #endif 39*98cd9557SMatthias Ringwald 40*98cd9557SMatthias Ringwald #if ((defined UNICODE) && !(defined _UNICODE)) 41*98cd9557SMatthias Ringwald #define _UNICODE 42*98cd9557SMatthias Ringwald #endif 43*98cd9557SMatthias Ringwald 44*98cd9557SMatthias Ringwald #include <errno.h> 45*98cd9557SMatthias Ringwald #include <stdlib.h> 46*98cd9557SMatthias Ringwald #include <string.h> 47*98cd9557SMatthias Ringwald #ifdef _MSC_VER 48*98cd9557SMatthias Ringwald # define WIN32_LEAN_AND_MEAN 49*98cd9557SMatthias Ringwald # include <windows.h> 50*98cd9557SMatthias Ringwald # include <tchar.h> 51*98cd9557SMatthias Ringwald # pragma warning(push) 52*98cd9557SMatthias Ringwald # pragma warning (disable : 4996) 53*98cd9557SMatthias Ringwald #else 54*98cd9557SMatthias Ringwald # include <dirent.h> 55*98cd9557SMatthias Ringwald # include <libgen.h> 56*98cd9557SMatthias Ringwald # include <sys/stat.h> 57*98cd9557SMatthias Ringwald # include <stddef.h> 58*98cd9557SMatthias Ringwald #endif 59*98cd9557SMatthias Ringwald #ifdef __MINGW32__ 60*98cd9557SMatthias Ringwald # include <tchar.h> 61*98cd9557SMatthias Ringwald #endif 62*98cd9557SMatthias Ringwald 63*98cd9557SMatthias Ringwald 64*98cd9557SMatthias Ringwald /* types */ 65*98cd9557SMatthias Ringwald 66*98cd9557SMatthias Ringwald /* Windows UNICODE wide character support */ 67*98cd9557SMatthias Ringwald #if defined _MSC_VER || defined __MINGW32__ 68*98cd9557SMatthias Ringwald # define _tinydir_char_t TCHAR 69*98cd9557SMatthias Ringwald # define TINYDIR_STRING(s) _TEXT(s) 70*98cd9557SMatthias Ringwald # define _tinydir_strlen _tcslen 71*98cd9557SMatthias Ringwald # define _tinydir_strcpy _tcscpy 72*98cd9557SMatthias Ringwald # define _tinydir_strcat _tcscat 73*98cd9557SMatthias Ringwald # define _tinydir_strcmp _tcscmp 74*98cd9557SMatthias Ringwald # define _tinydir_strrchr _tcsrchr 75*98cd9557SMatthias Ringwald # define _tinydir_strncmp _tcsncmp 76*98cd9557SMatthias Ringwald #else 77*98cd9557SMatthias Ringwald # define _tinydir_char_t char 78*98cd9557SMatthias Ringwald # define TINYDIR_STRING(s) s 79*98cd9557SMatthias Ringwald # define _tinydir_strlen strlen 80*98cd9557SMatthias Ringwald # define _tinydir_strcpy strcpy 81*98cd9557SMatthias Ringwald # define _tinydir_strcat strcat 82*98cd9557SMatthias Ringwald # define _tinydir_strcmp strcmp 83*98cd9557SMatthias Ringwald # define _tinydir_strrchr strrchr 84*98cd9557SMatthias Ringwald # define _tinydir_strncmp strncmp 85*98cd9557SMatthias Ringwald #endif 86*98cd9557SMatthias Ringwald 87*98cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 88*98cd9557SMatthias Ringwald # include <windows.h> 89*98cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX MAX_PATH 90*98cd9557SMatthias Ringwald #elif defined __linux__ 91*98cd9557SMatthias Ringwald # include <limits.h> 92*98cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX PATH_MAX 93*98cd9557SMatthias Ringwald #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) 94*98cd9557SMatthias Ringwald # include <sys/param.h> 95*98cd9557SMatthias Ringwald # if defined(BSD) 96*98cd9557SMatthias Ringwald # include <limits.h> 97*98cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX PATH_MAX 98*98cd9557SMatthias Ringwald # endif 99*98cd9557SMatthias Ringwald #endif 100*98cd9557SMatthias Ringwald 101*98cd9557SMatthias Ringwald #ifndef _TINYDIR_PATH_MAX 102*98cd9557SMatthias Ringwald #define _TINYDIR_PATH_MAX 4096 103*98cd9557SMatthias Ringwald #endif 104*98cd9557SMatthias Ringwald 105*98cd9557SMatthias Ringwald #ifdef _MSC_VER 106*98cd9557SMatthias Ringwald /* extra chars for the "\\*" mask */ 107*98cd9557SMatthias Ringwald # define _TINYDIR_PATH_EXTRA 2 108*98cd9557SMatthias Ringwald #else 109*98cd9557SMatthias Ringwald # define _TINYDIR_PATH_EXTRA 0 110*98cd9557SMatthias Ringwald #endif 111*98cd9557SMatthias Ringwald 112*98cd9557SMatthias Ringwald #define _TINYDIR_FILENAME_MAX 256 113*98cd9557SMatthias Ringwald 114*98cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 115*98cd9557SMatthias Ringwald #define _TINYDIR_DRIVE_MAX 3 116*98cd9557SMatthias Ringwald #endif 117*98cd9557SMatthias Ringwald 118*98cd9557SMatthias Ringwald #ifdef _MSC_VER 119*98cd9557SMatthias Ringwald # define _TINYDIR_FUNC static __inline 120*98cd9557SMatthias Ringwald #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 121*98cd9557SMatthias Ringwald # define _TINYDIR_FUNC static __inline__ 122*98cd9557SMatthias Ringwald #else 123*98cd9557SMatthias Ringwald # define _TINYDIR_FUNC static inline 124*98cd9557SMatthias Ringwald #endif 125*98cd9557SMatthias Ringwald 126*98cd9557SMatthias Ringwald /* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */ 127*98cd9557SMatthias Ringwald #ifdef TINYDIR_USE_READDIR_R 128*98cd9557SMatthias Ringwald 129*98cd9557SMatthias Ringwald /* readdir_r is a POSIX-only function, and may not be available under various 130*98cd9557SMatthias Ringwald * environments/settings, e.g. MinGW. Use readdir fallback */ 131*98cd9557SMatthias Ringwald #if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\ 132*98cd9557SMatthias Ringwald _POSIX_SOURCE 133*98cd9557SMatthias Ringwald # define _TINYDIR_HAS_READDIR_R 134*98cd9557SMatthias Ringwald #endif 135*98cd9557SMatthias Ringwald #if _POSIX_C_SOURCE >= 200112L 136*98cd9557SMatthias Ringwald # define _TINYDIR_HAS_FPATHCONF 137*98cd9557SMatthias Ringwald # include <unistd.h> 138*98cd9557SMatthias Ringwald #endif 139*98cd9557SMatthias Ringwald #if _BSD_SOURCE || _SVID_SOURCE || \ 140*98cd9557SMatthias Ringwald (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) 141*98cd9557SMatthias Ringwald # define _TINYDIR_HAS_DIRFD 142*98cd9557SMatthias Ringwald # include <sys/types.h> 143*98cd9557SMatthias Ringwald #endif 144*98cd9557SMatthias Ringwald #if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\ 145*98cd9557SMatthias Ringwald defined _PC_NAME_MAX 146*98cd9557SMatthias Ringwald # define _TINYDIR_USE_FPATHCONF 147*98cd9557SMatthias Ringwald #endif 148*98cd9557SMatthias Ringwald #if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\ 149*98cd9557SMatthias Ringwald !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX) 150*98cd9557SMatthias Ringwald # define _TINYDIR_USE_READDIR 151*98cd9557SMatthias Ringwald #endif 152*98cd9557SMatthias Ringwald 153*98cd9557SMatthias Ringwald /* Use readdir by default */ 154*98cd9557SMatthias Ringwald #else 155*98cd9557SMatthias Ringwald # define _TINYDIR_USE_READDIR 156*98cd9557SMatthias Ringwald #endif 157*98cd9557SMatthias Ringwald 158*98cd9557SMatthias Ringwald /* MINGW32 has two versions of dirent, ASCII and UNICODE*/ 159*98cd9557SMatthias Ringwald #ifndef _MSC_VER 160*98cd9557SMatthias Ringwald #if (defined __MINGW32__) && (defined _UNICODE) 161*98cd9557SMatthias Ringwald #define _TINYDIR_DIR _WDIR 162*98cd9557SMatthias Ringwald #define _tinydir_dirent _wdirent 163*98cd9557SMatthias Ringwald #define _tinydir_opendir _wopendir 164*98cd9557SMatthias Ringwald #define _tinydir_readdir _wreaddir 165*98cd9557SMatthias Ringwald #define _tinydir_closedir _wclosedir 166*98cd9557SMatthias Ringwald #else 167*98cd9557SMatthias Ringwald #define _TINYDIR_DIR DIR 168*98cd9557SMatthias Ringwald #define _tinydir_dirent dirent 169*98cd9557SMatthias Ringwald #define _tinydir_opendir opendir 170*98cd9557SMatthias Ringwald #define _tinydir_readdir readdir 171*98cd9557SMatthias Ringwald #define _tinydir_closedir closedir 172*98cd9557SMatthias Ringwald #endif 173*98cd9557SMatthias Ringwald #endif 174*98cd9557SMatthias Ringwald 175*98cd9557SMatthias Ringwald /* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */ 176*98cd9557SMatthias Ringwald #if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE) 177*98cd9557SMatthias Ringwald #elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE) 178*98cd9557SMatthias Ringwald #else 179*98cd9557SMatthias Ringwald #error "Either define both alloc and free or none of them!" 180*98cd9557SMatthias Ringwald #endif 181*98cd9557SMatthias Ringwald 182*98cd9557SMatthias Ringwald #if !defined(_TINYDIR_MALLOC) 183*98cd9557SMatthias Ringwald #define _TINYDIR_MALLOC(_size) malloc(_size) 184*98cd9557SMatthias Ringwald #define _TINYDIR_FREE(_ptr) free(_ptr) 185*98cd9557SMatthias Ringwald #endif /* !defined(_TINYDIR_MALLOC) */ 186*98cd9557SMatthias Ringwald 187*98cd9557SMatthias Ringwald typedef struct tinydir_file 188*98cd9557SMatthias Ringwald { 189*98cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 190*98cd9557SMatthias Ringwald _tinydir_char_t name[_TINYDIR_FILENAME_MAX]; 191*98cd9557SMatthias Ringwald _tinydir_char_t *extension; 192*98cd9557SMatthias Ringwald int is_dir; 193*98cd9557SMatthias Ringwald int is_reg; 194*98cd9557SMatthias Ringwald 195*98cd9557SMatthias Ringwald #ifndef _MSC_VER 196*98cd9557SMatthias Ringwald #ifdef __MINGW32__ 197*98cd9557SMatthias Ringwald struct _stat _s; 198*98cd9557SMatthias Ringwald #else 199*98cd9557SMatthias Ringwald struct stat _s; 200*98cd9557SMatthias Ringwald #endif 201*98cd9557SMatthias Ringwald #endif 202*98cd9557SMatthias Ringwald } tinydir_file; 203*98cd9557SMatthias Ringwald 204*98cd9557SMatthias Ringwald typedef struct tinydir_dir 205*98cd9557SMatthias Ringwald { 206*98cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 207*98cd9557SMatthias Ringwald int has_next; 208*98cd9557SMatthias Ringwald size_t n_files; 209*98cd9557SMatthias Ringwald 210*98cd9557SMatthias Ringwald tinydir_file *_files; 211*98cd9557SMatthias Ringwald #ifdef _MSC_VER 212*98cd9557SMatthias Ringwald HANDLE _h; 213*98cd9557SMatthias Ringwald WIN32_FIND_DATA _f; 214*98cd9557SMatthias Ringwald #else 215*98cd9557SMatthias Ringwald _TINYDIR_DIR *_d; 216*98cd9557SMatthias Ringwald struct _tinydir_dirent *_e; 217*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 218*98cd9557SMatthias Ringwald struct _tinydir_dirent *_ep; 219*98cd9557SMatthias Ringwald #endif 220*98cd9557SMatthias Ringwald #endif 221*98cd9557SMatthias Ringwald } tinydir_dir; 222*98cd9557SMatthias Ringwald 223*98cd9557SMatthias Ringwald 224*98cd9557SMatthias Ringwald /* declarations */ 225*98cd9557SMatthias Ringwald 226*98cd9557SMatthias Ringwald _TINYDIR_FUNC 227*98cd9557SMatthias Ringwald int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path); 228*98cd9557SMatthias Ringwald _TINYDIR_FUNC 229*98cd9557SMatthias Ringwald int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path); 230*98cd9557SMatthias Ringwald _TINYDIR_FUNC 231*98cd9557SMatthias Ringwald void tinydir_close(tinydir_dir *dir); 232*98cd9557SMatthias Ringwald 233*98cd9557SMatthias Ringwald _TINYDIR_FUNC 234*98cd9557SMatthias Ringwald int tinydir_next(tinydir_dir *dir); 235*98cd9557SMatthias Ringwald _TINYDIR_FUNC 236*98cd9557SMatthias Ringwald int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file); 237*98cd9557SMatthias Ringwald _TINYDIR_FUNC 238*98cd9557SMatthias Ringwald int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i); 239*98cd9557SMatthias Ringwald _TINYDIR_FUNC 240*98cd9557SMatthias Ringwald int tinydir_open_subdir_n(tinydir_dir *dir, size_t i); 241*98cd9557SMatthias Ringwald 242*98cd9557SMatthias Ringwald _TINYDIR_FUNC 243*98cd9557SMatthias Ringwald int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path); 244*98cd9557SMatthias Ringwald _TINYDIR_FUNC 245*98cd9557SMatthias Ringwald void _tinydir_get_ext(tinydir_file *file); 246*98cd9557SMatthias Ringwald _TINYDIR_FUNC 247*98cd9557SMatthias Ringwald int _tinydir_file_cmp(const void *a, const void *b); 248*98cd9557SMatthias Ringwald #ifndef _MSC_VER 249*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 250*98cd9557SMatthias Ringwald _TINYDIR_FUNC 251*98cd9557SMatthias Ringwald size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp); 252*98cd9557SMatthias Ringwald #endif 253*98cd9557SMatthias Ringwald #endif 254*98cd9557SMatthias Ringwald 255*98cd9557SMatthias Ringwald 256*98cd9557SMatthias Ringwald /* definitions*/ 257*98cd9557SMatthias Ringwald 258*98cd9557SMatthias Ringwald _TINYDIR_FUNC 259*98cd9557SMatthias Ringwald int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) 260*98cd9557SMatthias Ringwald { 261*98cd9557SMatthias Ringwald #ifndef _MSC_VER 262*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 263*98cd9557SMatthias Ringwald int error; 264*98cd9557SMatthias Ringwald int size; /* using int size */ 265*98cd9557SMatthias Ringwald #endif 266*98cd9557SMatthias Ringwald #else 267*98cd9557SMatthias Ringwald _tinydir_char_t path_buf[_TINYDIR_PATH_MAX]; 268*98cd9557SMatthias Ringwald #endif 269*98cd9557SMatthias Ringwald _tinydir_char_t *pathp; 270*98cd9557SMatthias Ringwald 271*98cd9557SMatthias Ringwald if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) 272*98cd9557SMatthias Ringwald { 273*98cd9557SMatthias Ringwald errno = EINVAL; 274*98cd9557SMatthias Ringwald return -1; 275*98cd9557SMatthias Ringwald } 276*98cd9557SMatthias Ringwald if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 277*98cd9557SMatthias Ringwald { 278*98cd9557SMatthias Ringwald errno = ENAMETOOLONG; 279*98cd9557SMatthias Ringwald return -1; 280*98cd9557SMatthias Ringwald } 281*98cd9557SMatthias Ringwald 282*98cd9557SMatthias Ringwald /* initialise dir */ 283*98cd9557SMatthias Ringwald dir->_files = NULL; 284*98cd9557SMatthias Ringwald #ifdef _MSC_VER 285*98cd9557SMatthias Ringwald dir->_h = INVALID_HANDLE_VALUE; 286*98cd9557SMatthias Ringwald #else 287*98cd9557SMatthias Ringwald dir->_d = NULL; 288*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 289*98cd9557SMatthias Ringwald dir->_ep = NULL; 290*98cd9557SMatthias Ringwald #endif 291*98cd9557SMatthias Ringwald #endif 292*98cd9557SMatthias Ringwald tinydir_close(dir); 293*98cd9557SMatthias Ringwald 294*98cd9557SMatthias Ringwald _tinydir_strcpy(dir->path, path); 295*98cd9557SMatthias Ringwald /* Remove trailing slashes */ 296*98cd9557SMatthias Ringwald pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; 297*98cd9557SMatthias Ringwald while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) 298*98cd9557SMatthias Ringwald { 299*98cd9557SMatthias Ringwald *pathp = TINYDIR_STRING('\0'); 300*98cd9557SMatthias Ringwald pathp++; 301*98cd9557SMatthias Ringwald } 302*98cd9557SMatthias Ringwald #ifdef _MSC_VER 303*98cd9557SMatthias Ringwald _tinydir_strcpy(path_buf, dir->path); 304*98cd9557SMatthias Ringwald _tinydir_strcat(path_buf, TINYDIR_STRING("\\*")); 305*98cd9557SMatthias Ringwald #if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) 306*98cd9557SMatthias Ringwald dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0); 307*98cd9557SMatthias Ringwald #else 308*98cd9557SMatthias Ringwald dir->_h = FindFirstFile(path_buf, &dir->_f); 309*98cd9557SMatthias Ringwald #endif 310*98cd9557SMatthias Ringwald if (dir->_h == INVALID_HANDLE_VALUE) 311*98cd9557SMatthias Ringwald { 312*98cd9557SMatthias Ringwald errno = ENOENT; 313*98cd9557SMatthias Ringwald #else 314*98cd9557SMatthias Ringwald dir->_d = _tinydir_opendir(path); 315*98cd9557SMatthias Ringwald if (dir->_d == NULL) 316*98cd9557SMatthias Ringwald { 317*98cd9557SMatthias Ringwald #endif 318*98cd9557SMatthias Ringwald goto bail; 319*98cd9557SMatthias Ringwald } 320*98cd9557SMatthias Ringwald 321*98cd9557SMatthias Ringwald /* read first file */ 322*98cd9557SMatthias Ringwald dir->has_next = 1; 323*98cd9557SMatthias Ringwald #ifndef _MSC_VER 324*98cd9557SMatthias Ringwald #ifdef _TINYDIR_USE_READDIR 325*98cd9557SMatthias Ringwald dir->_e = _tinydir_readdir(dir->_d); 326*98cd9557SMatthias Ringwald #else 327*98cd9557SMatthias Ringwald /* allocate dirent buffer for readdir_r */ 328*98cd9557SMatthias Ringwald size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ 329*98cd9557SMatthias Ringwald if (size == -1) return -1; 330*98cd9557SMatthias Ringwald dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); 331*98cd9557SMatthias Ringwald if (dir->_ep == NULL) return -1; 332*98cd9557SMatthias Ringwald 333*98cd9557SMatthias Ringwald error = readdir_r(dir->_d, dir->_ep, &dir->_e); 334*98cd9557SMatthias Ringwald if (error != 0) return -1; 335*98cd9557SMatthias Ringwald #endif 336*98cd9557SMatthias Ringwald if (dir->_e == NULL) 337*98cd9557SMatthias Ringwald { 338*98cd9557SMatthias Ringwald dir->has_next = 0; 339*98cd9557SMatthias Ringwald } 340*98cd9557SMatthias Ringwald #endif 341*98cd9557SMatthias Ringwald 342*98cd9557SMatthias Ringwald return 0; 343*98cd9557SMatthias Ringwald 344*98cd9557SMatthias Ringwald bail: 345*98cd9557SMatthias Ringwald tinydir_close(dir); 346*98cd9557SMatthias Ringwald return -1; 347*98cd9557SMatthias Ringwald } 348*98cd9557SMatthias Ringwald 349*98cd9557SMatthias Ringwald _TINYDIR_FUNC 350*98cd9557SMatthias Ringwald int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) 351*98cd9557SMatthias Ringwald { 352*98cd9557SMatthias Ringwald /* Count the number of files first, to pre-allocate the files array */ 353*98cd9557SMatthias Ringwald size_t n_files = 0; 354*98cd9557SMatthias Ringwald if (tinydir_open(dir, path) == -1) 355*98cd9557SMatthias Ringwald { 356*98cd9557SMatthias Ringwald return -1; 357*98cd9557SMatthias Ringwald } 358*98cd9557SMatthias Ringwald while (dir->has_next) 359*98cd9557SMatthias Ringwald { 360*98cd9557SMatthias Ringwald n_files++; 361*98cd9557SMatthias Ringwald if (tinydir_next(dir) == -1) 362*98cd9557SMatthias Ringwald { 363*98cd9557SMatthias Ringwald goto bail; 364*98cd9557SMatthias Ringwald } 365*98cd9557SMatthias Ringwald } 366*98cd9557SMatthias Ringwald tinydir_close(dir); 367*98cd9557SMatthias Ringwald 368*98cd9557SMatthias Ringwald if (tinydir_open(dir, path) == -1) 369*98cd9557SMatthias Ringwald { 370*98cd9557SMatthias Ringwald return -1; 371*98cd9557SMatthias Ringwald } 372*98cd9557SMatthias Ringwald 373*98cd9557SMatthias Ringwald dir->n_files = 0; 374*98cd9557SMatthias Ringwald dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); 375*98cd9557SMatthias Ringwald if (dir->_files == NULL) 376*98cd9557SMatthias Ringwald { 377*98cd9557SMatthias Ringwald goto bail; 378*98cd9557SMatthias Ringwald } 379*98cd9557SMatthias Ringwald while (dir->has_next) 380*98cd9557SMatthias Ringwald { 381*98cd9557SMatthias Ringwald tinydir_file *p_file; 382*98cd9557SMatthias Ringwald dir->n_files++; 383*98cd9557SMatthias Ringwald 384*98cd9557SMatthias Ringwald p_file = &dir->_files[dir->n_files - 1]; 385*98cd9557SMatthias Ringwald if (tinydir_readfile(dir, p_file) == -1) 386*98cd9557SMatthias Ringwald { 387*98cd9557SMatthias Ringwald goto bail; 388*98cd9557SMatthias Ringwald } 389*98cd9557SMatthias Ringwald 390*98cd9557SMatthias Ringwald if (tinydir_next(dir) == -1) 391*98cd9557SMatthias Ringwald { 392*98cd9557SMatthias Ringwald goto bail; 393*98cd9557SMatthias Ringwald } 394*98cd9557SMatthias Ringwald 395*98cd9557SMatthias Ringwald /* Just in case the number of files has changed between the first and 396*98cd9557SMatthias Ringwald second reads, terminate without writing into unallocated memory */ 397*98cd9557SMatthias Ringwald if (dir->n_files == n_files) 398*98cd9557SMatthias Ringwald { 399*98cd9557SMatthias Ringwald break; 400*98cd9557SMatthias Ringwald } 401*98cd9557SMatthias Ringwald } 402*98cd9557SMatthias Ringwald 403*98cd9557SMatthias Ringwald qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp); 404*98cd9557SMatthias Ringwald 405*98cd9557SMatthias Ringwald return 0; 406*98cd9557SMatthias Ringwald 407*98cd9557SMatthias Ringwald bail: 408*98cd9557SMatthias Ringwald tinydir_close(dir); 409*98cd9557SMatthias Ringwald return -1; 410*98cd9557SMatthias Ringwald } 411*98cd9557SMatthias Ringwald 412*98cd9557SMatthias Ringwald _TINYDIR_FUNC 413*98cd9557SMatthias Ringwald void tinydir_close(tinydir_dir *dir) 414*98cd9557SMatthias Ringwald { 415*98cd9557SMatthias Ringwald if (dir == NULL) 416*98cd9557SMatthias Ringwald { 417*98cd9557SMatthias Ringwald return; 418*98cd9557SMatthias Ringwald } 419*98cd9557SMatthias Ringwald 420*98cd9557SMatthias Ringwald memset(dir->path, 0, sizeof(dir->path)); 421*98cd9557SMatthias Ringwald dir->has_next = 0; 422*98cd9557SMatthias Ringwald dir->n_files = 0; 423*98cd9557SMatthias Ringwald _TINYDIR_FREE(dir->_files); 424*98cd9557SMatthias Ringwald dir->_files = NULL; 425*98cd9557SMatthias Ringwald #ifdef _MSC_VER 426*98cd9557SMatthias Ringwald if (dir->_h != INVALID_HANDLE_VALUE) 427*98cd9557SMatthias Ringwald { 428*98cd9557SMatthias Ringwald FindClose(dir->_h); 429*98cd9557SMatthias Ringwald } 430*98cd9557SMatthias Ringwald dir->_h = INVALID_HANDLE_VALUE; 431*98cd9557SMatthias Ringwald #else 432*98cd9557SMatthias Ringwald if (dir->_d) 433*98cd9557SMatthias Ringwald { 434*98cd9557SMatthias Ringwald _tinydir_closedir(dir->_d); 435*98cd9557SMatthias Ringwald } 436*98cd9557SMatthias Ringwald dir->_d = NULL; 437*98cd9557SMatthias Ringwald dir->_e = NULL; 438*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 439*98cd9557SMatthias Ringwald _TINYDIR_FREE(dir->_ep); 440*98cd9557SMatthias Ringwald dir->_ep = NULL; 441*98cd9557SMatthias Ringwald #endif 442*98cd9557SMatthias Ringwald #endif 443*98cd9557SMatthias Ringwald } 444*98cd9557SMatthias Ringwald 445*98cd9557SMatthias Ringwald _TINYDIR_FUNC 446*98cd9557SMatthias Ringwald int tinydir_next(tinydir_dir *dir) 447*98cd9557SMatthias Ringwald { 448*98cd9557SMatthias Ringwald if (dir == NULL) 449*98cd9557SMatthias Ringwald { 450*98cd9557SMatthias Ringwald errno = EINVAL; 451*98cd9557SMatthias Ringwald return -1; 452*98cd9557SMatthias Ringwald } 453*98cd9557SMatthias Ringwald if (!dir->has_next) 454*98cd9557SMatthias Ringwald { 455*98cd9557SMatthias Ringwald errno = ENOENT; 456*98cd9557SMatthias Ringwald return -1; 457*98cd9557SMatthias Ringwald } 458*98cd9557SMatthias Ringwald 459*98cd9557SMatthias Ringwald #ifdef _MSC_VER 460*98cd9557SMatthias Ringwald if (FindNextFile(dir->_h, &dir->_f) == 0) 461*98cd9557SMatthias Ringwald #else 462*98cd9557SMatthias Ringwald #ifdef _TINYDIR_USE_READDIR 463*98cd9557SMatthias Ringwald dir->_e = _tinydir_readdir(dir->_d); 464*98cd9557SMatthias Ringwald #else 465*98cd9557SMatthias Ringwald if (dir->_ep == NULL) 466*98cd9557SMatthias Ringwald { 467*98cd9557SMatthias Ringwald return -1; 468*98cd9557SMatthias Ringwald } 469*98cd9557SMatthias Ringwald if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) 470*98cd9557SMatthias Ringwald { 471*98cd9557SMatthias Ringwald return -1; 472*98cd9557SMatthias Ringwald } 473*98cd9557SMatthias Ringwald #endif 474*98cd9557SMatthias Ringwald if (dir->_e == NULL) 475*98cd9557SMatthias Ringwald #endif 476*98cd9557SMatthias Ringwald { 477*98cd9557SMatthias Ringwald dir->has_next = 0; 478*98cd9557SMatthias Ringwald #ifdef _MSC_VER 479*98cd9557SMatthias Ringwald if (GetLastError() != ERROR_SUCCESS && 480*98cd9557SMatthias Ringwald GetLastError() != ERROR_NO_MORE_FILES) 481*98cd9557SMatthias Ringwald { 482*98cd9557SMatthias Ringwald tinydir_close(dir); 483*98cd9557SMatthias Ringwald errno = EIO; 484*98cd9557SMatthias Ringwald return -1; 485*98cd9557SMatthias Ringwald } 486*98cd9557SMatthias Ringwald #endif 487*98cd9557SMatthias Ringwald } 488*98cd9557SMatthias Ringwald 489*98cd9557SMatthias Ringwald return 0; 490*98cd9557SMatthias Ringwald } 491*98cd9557SMatthias Ringwald 492*98cd9557SMatthias Ringwald _TINYDIR_FUNC 493*98cd9557SMatthias Ringwald int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) 494*98cd9557SMatthias Ringwald { 495*98cd9557SMatthias Ringwald if (dir == NULL || file == NULL) 496*98cd9557SMatthias Ringwald { 497*98cd9557SMatthias Ringwald errno = EINVAL; 498*98cd9557SMatthias Ringwald return -1; 499*98cd9557SMatthias Ringwald } 500*98cd9557SMatthias Ringwald #ifdef _MSC_VER 501*98cd9557SMatthias Ringwald if (dir->_h == INVALID_HANDLE_VALUE) 502*98cd9557SMatthias Ringwald #else 503*98cd9557SMatthias Ringwald if (dir->_e == NULL) 504*98cd9557SMatthias Ringwald #endif 505*98cd9557SMatthias Ringwald { 506*98cd9557SMatthias Ringwald errno = ENOENT; 507*98cd9557SMatthias Ringwald return -1; 508*98cd9557SMatthias Ringwald } 509*98cd9557SMatthias Ringwald if (_tinydir_strlen(dir->path) + 510*98cd9557SMatthias Ringwald _tinydir_strlen( 511*98cd9557SMatthias Ringwald #ifdef _MSC_VER 512*98cd9557SMatthias Ringwald dir->_f.cFileName 513*98cd9557SMatthias Ringwald #else 514*98cd9557SMatthias Ringwald dir->_e->d_name 515*98cd9557SMatthias Ringwald #endif 516*98cd9557SMatthias Ringwald ) + 1 + _TINYDIR_PATH_EXTRA >= 517*98cd9557SMatthias Ringwald _TINYDIR_PATH_MAX) 518*98cd9557SMatthias Ringwald { 519*98cd9557SMatthias Ringwald /* the path for the file will be too long */ 520*98cd9557SMatthias Ringwald errno = ENAMETOOLONG; 521*98cd9557SMatthias Ringwald return -1; 522*98cd9557SMatthias Ringwald } 523*98cd9557SMatthias Ringwald if (_tinydir_strlen( 524*98cd9557SMatthias Ringwald #ifdef _MSC_VER 525*98cd9557SMatthias Ringwald dir->_f.cFileName 526*98cd9557SMatthias Ringwald #else 527*98cd9557SMatthias Ringwald dir->_e->d_name 528*98cd9557SMatthias Ringwald #endif 529*98cd9557SMatthias Ringwald ) >= _TINYDIR_FILENAME_MAX) 530*98cd9557SMatthias Ringwald { 531*98cd9557SMatthias Ringwald errno = ENAMETOOLONG; 532*98cd9557SMatthias Ringwald return -1; 533*98cd9557SMatthias Ringwald } 534*98cd9557SMatthias Ringwald 535*98cd9557SMatthias Ringwald _tinydir_strcpy(file->path, dir->path); 536*98cd9557SMatthias Ringwald _tinydir_strcat(file->path, TINYDIR_STRING("/")); 537*98cd9557SMatthias Ringwald _tinydir_strcpy(file->name, 538*98cd9557SMatthias Ringwald #ifdef _MSC_VER 539*98cd9557SMatthias Ringwald dir->_f.cFileName 540*98cd9557SMatthias Ringwald #else 541*98cd9557SMatthias Ringwald dir->_e->d_name 542*98cd9557SMatthias Ringwald #endif 543*98cd9557SMatthias Ringwald ); 544*98cd9557SMatthias Ringwald _tinydir_strcat(file->path, file->name); 545*98cd9557SMatthias Ringwald #ifndef _MSC_VER 546*98cd9557SMatthias Ringwald #ifdef __MINGW32__ 547*98cd9557SMatthias Ringwald if (_tstat( 548*98cd9557SMatthias Ringwald #else 549*98cd9557SMatthias Ringwald if (stat( 550*98cd9557SMatthias Ringwald #endif 551*98cd9557SMatthias Ringwald file->path, &file->_s) == -1) 552*98cd9557SMatthias Ringwald { 553*98cd9557SMatthias Ringwald return -1; 554*98cd9557SMatthias Ringwald } 555*98cd9557SMatthias Ringwald #endif 556*98cd9557SMatthias Ringwald _tinydir_get_ext(file); 557*98cd9557SMatthias Ringwald 558*98cd9557SMatthias Ringwald file->is_dir = 559*98cd9557SMatthias Ringwald #ifdef _MSC_VER 560*98cd9557SMatthias Ringwald !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 561*98cd9557SMatthias Ringwald #else 562*98cd9557SMatthias Ringwald S_ISDIR(file->_s.st_mode); 563*98cd9557SMatthias Ringwald #endif 564*98cd9557SMatthias Ringwald file->is_reg = 565*98cd9557SMatthias Ringwald #ifdef _MSC_VER 566*98cd9557SMatthias Ringwald !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || 567*98cd9557SMatthias Ringwald ( 568*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && 569*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && 570*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && 571*98cd9557SMatthias Ringwald #ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM 572*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && 573*98cd9557SMatthias Ringwald #endif 574*98cd9557SMatthias Ringwald #ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA 575*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && 576*98cd9557SMatthias Ringwald #endif 577*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && 578*98cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); 579*98cd9557SMatthias Ringwald #else 580*98cd9557SMatthias Ringwald S_ISREG(file->_s.st_mode); 581*98cd9557SMatthias Ringwald #endif 582*98cd9557SMatthias Ringwald 583*98cd9557SMatthias Ringwald return 0; 584*98cd9557SMatthias Ringwald } 585*98cd9557SMatthias Ringwald 586*98cd9557SMatthias Ringwald _TINYDIR_FUNC 587*98cd9557SMatthias Ringwald int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) 588*98cd9557SMatthias Ringwald { 589*98cd9557SMatthias Ringwald if (dir == NULL || file == NULL) 590*98cd9557SMatthias Ringwald { 591*98cd9557SMatthias Ringwald errno = EINVAL; 592*98cd9557SMatthias Ringwald return -1; 593*98cd9557SMatthias Ringwald } 594*98cd9557SMatthias Ringwald if (i >= dir->n_files) 595*98cd9557SMatthias Ringwald { 596*98cd9557SMatthias Ringwald errno = ENOENT; 597*98cd9557SMatthias Ringwald return -1; 598*98cd9557SMatthias Ringwald } 599*98cd9557SMatthias Ringwald 600*98cd9557SMatthias Ringwald memcpy(file, &dir->_files[i], sizeof(tinydir_file)); 601*98cd9557SMatthias Ringwald _tinydir_get_ext(file); 602*98cd9557SMatthias Ringwald 603*98cd9557SMatthias Ringwald return 0; 604*98cd9557SMatthias Ringwald } 605*98cd9557SMatthias Ringwald 606*98cd9557SMatthias Ringwald _TINYDIR_FUNC 607*98cd9557SMatthias Ringwald int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) 608*98cd9557SMatthias Ringwald { 609*98cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 610*98cd9557SMatthias Ringwald if (dir == NULL) 611*98cd9557SMatthias Ringwald { 612*98cd9557SMatthias Ringwald errno = EINVAL; 613*98cd9557SMatthias Ringwald return -1; 614*98cd9557SMatthias Ringwald } 615*98cd9557SMatthias Ringwald if (i >= dir->n_files || !dir->_files[i].is_dir) 616*98cd9557SMatthias Ringwald { 617*98cd9557SMatthias Ringwald errno = ENOENT; 618*98cd9557SMatthias Ringwald return -1; 619*98cd9557SMatthias Ringwald } 620*98cd9557SMatthias Ringwald 621*98cd9557SMatthias Ringwald _tinydir_strcpy(path, dir->_files[i].path); 622*98cd9557SMatthias Ringwald tinydir_close(dir); 623*98cd9557SMatthias Ringwald if (tinydir_open_sorted(dir, path) == -1) 624*98cd9557SMatthias Ringwald { 625*98cd9557SMatthias Ringwald return -1; 626*98cd9557SMatthias Ringwald } 627*98cd9557SMatthias Ringwald 628*98cd9557SMatthias Ringwald return 0; 629*98cd9557SMatthias Ringwald } 630*98cd9557SMatthias Ringwald 631*98cd9557SMatthias Ringwald /* Open a single file given its path */ 632*98cd9557SMatthias Ringwald _TINYDIR_FUNC 633*98cd9557SMatthias Ringwald int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) 634*98cd9557SMatthias Ringwald { 635*98cd9557SMatthias Ringwald tinydir_dir dir; 636*98cd9557SMatthias Ringwald int result = 0; 637*98cd9557SMatthias Ringwald int found = 0; 638*98cd9557SMatthias Ringwald _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX]; 639*98cd9557SMatthias Ringwald _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX]; 640*98cd9557SMatthias Ringwald _tinydir_char_t *dir_name; 641*98cd9557SMatthias Ringwald _tinydir_char_t *base_name; 642*98cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 643*98cd9557SMatthias Ringwald _tinydir_char_t drive_buf[_TINYDIR_PATH_MAX]; 644*98cd9557SMatthias Ringwald _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; 645*98cd9557SMatthias Ringwald #endif 646*98cd9557SMatthias Ringwald 647*98cd9557SMatthias Ringwald if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) 648*98cd9557SMatthias Ringwald { 649*98cd9557SMatthias Ringwald errno = EINVAL; 650*98cd9557SMatthias Ringwald return -1; 651*98cd9557SMatthias Ringwald } 652*98cd9557SMatthias Ringwald if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 653*98cd9557SMatthias Ringwald { 654*98cd9557SMatthias Ringwald errno = ENAMETOOLONG; 655*98cd9557SMatthias Ringwald return -1; 656*98cd9557SMatthias Ringwald } 657*98cd9557SMatthias Ringwald 658*98cd9557SMatthias Ringwald /* Get the parent path */ 659*98cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 660*98cd9557SMatthias Ringwald #if ((defined _MSC_VER) && (_MSC_VER >= 1400)) 661*98cd9557SMatthias Ringwald _tsplitpath_s( 662*98cd9557SMatthias Ringwald path, 663*98cd9557SMatthias Ringwald drive_buf, _TINYDIR_DRIVE_MAX, 664*98cd9557SMatthias Ringwald dir_name_buf, _TINYDIR_FILENAME_MAX, 665*98cd9557SMatthias Ringwald file_name_buf, _TINYDIR_FILENAME_MAX, 666*98cd9557SMatthias Ringwald ext_buf, _TINYDIR_FILENAME_MAX); 667*98cd9557SMatthias Ringwald #else 668*98cd9557SMatthias Ringwald _tsplitpath( 669*98cd9557SMatthias Ringwald path, 670*98cd9557SMatthias Ringwald drive_buf, 671*98cd9557SMatthias Ringwald dir_name_buf, 672*98cd9557SMatthias Ringwald file_name_buf, 673*98cd9557SMatthias Ringwald ext_buf); 674*98cd9557SMatthias Ringwald #endif 675*98cd9557SMatthias Ringwald 676*98cd9557SMatthias Ringwald /* _splitpath_s not work fine with only filename and widechar support */ 677*98cd9557SMatthias Ringwald #ifdef _UNICODE 678*98cd9557SMatthias Ringwald if (drive_buf[0] == L'\xFEFE') 679*98cd9557SMatthias Ringwald drive_buf[0] = '\0'; 680*98cd9557SMatthias Ringwald if (dir_name_buf[0] == L'\xFEFE') 681*98cd9557SMatthias Ringwald dir_name_buf[0] = '\0'; 682*98cd9557SMatthias Ringwald #endif 683*98cd9557SMatthias Ringwald 684*98cd9557SMatthias Ringwald if (errno) 685*98cd9557SMatthias Ringwald { 686*98cd9557SMatthias Ringwald errno = EINVAL; 687*98cd9557SMatthias Ringwald return -1; 688*98cd9557SMatthias Ringwald } 689*98cd9557SMatthias Ringwald /* Emulate the behavior of dirname by returning "." for dir name if it's 690*98cd9557SMatthias Ringwald empty */ 691*98cd9557SMatthias Ringwald if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') 692*98cd9557SMatthias Ringwald { 693*98cd9557SMatthias Ringwald _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); 694*98cd9557SMatthias Ringwald } 695*98cd9557SMatthias Ringwald /* Concatenate the drive letter and dir name to form full dir name */ 696*98cd9557SMatthias Ringwald _tinydir_strcat(drive_buf, dir_name_buf); 697*98cd9557SMatthias Ringwald dir_name = drive_buf; 698*98cd9557SMatthias Ringwald /* Concatenate the file name and extension to form base name */ 699*98cd9557SMatthias Ringwald _tinydir_strcat(file_name_buf, ext_buf); 700*98cd9557SMatthias Ringwald base_name = file_name_buf; 701*98cd9557SMatthias Ringwald #else 702*98cd9557SMatthias Ringwald _tinydir_strcpy(dir_name_buf, path); 703*98cd9557SMatthias Ringwald dir_name = dirname(dir_name_buf); 704*98cd9557SMatthias Ringwald _tinydir_strcpy(file_name_buf, path); 705*98cd9557SMatthias Ringwald base_name =basename(file_name_buf); 706*98cd9557SMatthias Ringwald #endif 707*98cd9557SMatthias Ringwald 708*98cd9557SMatthias Ringwald /* Open the parent directory */ 709*98cd9557SMatthias Ringwald if (tinydir_open(&dir, dir_name) == -1) 710*98cd9557SMatthias Ringwald { 711*98cd9557SMatthias Ringwald return -1; 712*98cd9557SMatthias Ringwald } 713*98cd9557SMatthias Ringwald 714*98cd9557SMatthias Ringwald /* Read through the parent directory and look for the file */ 715*98cd9557SMatthias Ringwald while (dir.has_next) 716*98cd9557SMatthias Ringwald { 717*98cd9557SMatthias Ringwald if (tinydir_readfile(&dir, file) == -1) 718*98cd9557SMatthias Ringwald { 719*98cd9557SMatthias Ringwald result = -1; 720*98cd9557SMatthias Ringwald goto bail; 721*98cd9557SMatthias Ringwald } 722*98cd9557SMatthias Ringwald if (_tinydir_strcmp(file->name, base_name) == 0) 723*98cd9557SMatthias Ringwald { 724*98cd9557SMatthias Ringwald /* File found */ 725*98cd9557SMatthias Ringwald found = 1; 726*98cd9557SMatthias Ringwald break; 727*98cd9557SMatthias Ringwald } 728*98cd9557SMatthias Ringwald tinydir_next(&dir); 729*98cd9557SMatthias Ringwald } 730*98cd9557SMatthias Ringwald if (!found) 731*98cd9557SMatthias Ringwald { 732*98cd9557SMatthias Ringwald result = -1; 733*98cd9557SMatthias Ringwald errno = ENOENT; 734*98cd9557SMatthias Ringwald } 735*98cd9557SMatthias Ringwald 736*98cd9557SMatthias Ringwald bail: 737*98cd9557SMatthias Ringwald tinydir_close(&dir); 738*98cd9557SMatthias Ringwald return result; 739*98cd9557SMatthias Ringwald } 740*98cd9557SMatthias Ringwald 741*98cd9557SMatthias Ringwald _TINYDIR_FUNC 742*98cd9557SMatthias Ringwald void _tinydir_get_ext(tinydir_file *file) 743*98cd9557SMatthias Ringwald { 744*98cd9557SMatthias Ringwald _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); 745*98cd9557SMatthias Ringwald if (period == NULL) 746*98cd9557SMatthias Ringwald { 747*98cd9557SMatthias Ringwald file->extension = &(file->name[_tinydir_strlen(file->name)]); 748*98cd9557SMatthias Ringwald } 749*98cd9557SMatthias Ringwald else 750*98cd9557SMatthias Ringwald { 751*98cd9557SMatthias Ringwald file->extension = period + 1; 752*98cd9557SMatthias Ringwald } 753*98cd9557SMatthias Ringwald } 754*98cd9557SMatthias Ringwald 755*98cd9557SMatthias Ringwald _TINYDIR_FUNC 756*98cd9557SMatthias Ringwald int _tinydir_file_cmp(const void *a, const void *b) 757*98cd9557SMatthias Ringwald { 758*98cd9557SMatthias Ringwald const tinydir_file *fa = (const tinydir_file *)a; 759*98cd9557SMatthias Ringwald const tinydir_file *fb = (const tinydir_file *)b; 760*98cd9557SMatthias Ringwald if (fa->is_dir != fb->is_dir) 761*98cd9557SMatthias Ringwald { 762*98cd9557SMatthias Ringwald return -(fa->is_dir - fb->is_dir); 763*98cd9557SMatthias Ringwald } 764*98cd9557SMatthias Ringwald return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); 765*98cd9557SMatthias Ringwald } 766*98cd9557SMatthias Ringwald 767*98cd9557SMatthias Ringwald #ifndef _MSC_VER 768*98cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 769*98cd9557SMatthias Ringwald /* 770*98cd9557SMatthias Ringwald The following authored by Ben Hutchings <[email protected]> 771*98cd9557SMatthias Ringwald from https://womble.decadent.org.uk/readdir_r-advisory.html 772*98cd9557SMatthias Ringwald */ 773*98cd9557SMatthias Ringwald /* Calculate the required buffer size (in bytes) for directory * 774*98cd9557SMatthias Ringwald * entries read from the given directory handle. Return -1 if this * 775*98cd9557SMatthias Ringwald * this cannot be done. * 776*98cd9557SMatthias Ringwald * * 777*98cd9557SMatthias Ringwald * This code does not trust values of NAME_MAX that are less than * 778*98cd9557SMatthias Ringwald * 255, since some systems (including at least HP-UX) incorrectly * 779*98cd9557SMatthias Ringwald * define it to be a smaller value. */ 780*98cd9557SMatthias Ringwald _TINYDIR_FUNC 781*98cd9557SMatthias Ringwald size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) 782*98cd9557SMatthias Ringwald { 783*98cd9557SMatthias Ringwald long name_max; 784*98cd9557SMatthias Ringwald size_t name_end; 785*98cd9557SMatthias Ringwald /* parameter may be unused */ 786*98cd9557SMatthias Ringwald (void)dirp; 787*98cd9557SMatthias Ringwald 788*98cd9557SMatthias Ringwald #if defined _TINYDIR_USE_FPATHCONF 789*98cd9557SMatthias Ringwald name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); 790*98cd9557SMatthias Ringwald if (name_max == -1) 791*98cd9557SMatthias Ringwald #if defined(NAME_MAX) 792*98cd9557SMatthias Ringwald name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 793*98cd9557SMatthias Ringwald #else 794*98cd9557SMatthias Ringwald return (size_t)(-1); 795*98cd9557SMatthias Ringwald #endif 796*98cd9557SMatthias Ringwald #elif defined(NAME_MAX) 797*98cd9557SMatthias Ringwald name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 798*98cd9557SMatthias Ringwald #else 799*98cd9557SMatthias Ringwald #error "buffer size for readdir_r cannot be determined" 800*98cd9557SMatthias Ringwald #endif 801*98cd9557SMatthias Ringwald name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; 802*98cd9557SMatthias Ringwald return (name_end > sizeof(struct _tinydir_dirent) ? 803*98cd9557SMatthias Ringwald name_end : sizeof(struct _tinydir_dirent)); 804*98cd9557SMatthias Ringwald } 805*98cd9557SMatthias Ringwald #endif 806*98cd9557SMatthias Ringwald #endif 807*98cd9557SMatthias Ringwald 808*98cd9557SMatthias Ringwald #ifdef __cplusplus 809*98cd9557SMatthias Ringwald } 810*98cd9557SMatthias Ringwald #endif 811*98cd9557SMatthias Ringwald 812*98cd9557SMatthias Ringwald # if defined (_MSC_VER) 813*98cd9557SMatthias Ringwald # pragma warning(pop) 814*98cd9557SMatthias Ringwald # endif 815*98cd9557SMatthias Ringwald 816*98cd9557SMatthias Ringwald #endif 817