198cd9557SMatthias Ringwald /* 2*ec8ca29fSMatthias Ringwald Copyright (c) 2013-2018, tinydir authors: 398cd9557SMatthias Ringwald - Cong Xu 498cd9557SMatthias Ringwald - Lautis Sun 598cd9557SMatthias Ringwald - Baudouin Feildel 698cd9557SMatthias Ringwald - Andargor <[email protected]> 798cd9557SMatthias Ringwald All rights reserved. 898cd9557SMatthias Ringwald 998cd9557SMatthias Ringwald Redistribution and use in source and binary forms, with or without 1098cd9557SMatthias Ringwald modification, are permitted provided that the following conditions are met: 1198cd9557SMatthias Ringwald 1298cd9557SMatthias Ringwald 1. Redistributions of source code must retain the above copyright notice, this 1398cd9557SMatthias Ringwald list of conditions and the following disclaimer. 1498cd9557SMatthias Ringwald 2. Redistributions in binary form must reproduce the above copyright notice, 1598cd9557SMatthias Ringwald this list of conditions and the following disclaimer in the documentation 1698cd9557SMatthias Ringwald and/or other materials provided with the distribution. 1798cd9557SMatthias Ringwald 1898cd9557SMatthias Ringwald THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1998cd9557SMatthias Ringwald ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2098cd9557SMatthias Ringwald WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2198cd9557SMatthias Ringwald DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 2298cd9557SMatthias Ringwald ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2398cd9557SMatthias Ringwald (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2498cd9557SMatthias Ringwald LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2598cd9557SMatthias Ringwald ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2698cd9557SMatthias Ringwald (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2798cd9557SMatthias Ringwald SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2898cd9557SMatthias Ringwald */ 2998cd9557SMatthias Ringwald #ifndef TINYDIR_H 3098cd9557SMatthias Ringwald #define TINYDIR_H 3198cd9557SMatthias Ringwald 3298cd9557SMatthias Ringwald #ifdef __cplusplus 3398cd9557SMatthias Ringwald extern "C" { 3498cd9557SMatthias Ringwald #endif 3598cd9557SMatthias Ringwald 3698cd9557SMatthias Ringwald #if ((defined _UNICODE) && !(defined UNICODE)) 3798cd9557SMatthias Ringwald #define UNICODE 3898cd9557SMatthias Ringwald #endif 3998cd9557SMatthias Ringwald 4098cd9557SMatthias Ringwald #if ((defined UNICODE) && !(defined _UNICODE)) 4198cd9557SMatthias Ringwald #define _UNICODE 4298cd9557SMatthias Ringwald #endif 4398cd9557SMatthias Ringwald 4498cd9557SMatthias Ringwald #include <errno.h> 4598cd9557SMatthias Ringwald #include <stdlib.h> 4698cd9557SMatthias Ringwald #include <string.h> 4798cd9557SMatthias Ringwald #ifdef _MSC_VER 4898cd9557SMatthias Ringwald # define WIN32_LEAN_AND_MEAN 4998cd9557SMatthias Ringwald # include <windows.h> 5098cd9557SMatthias Ringwald # include <tchar.h> 5198cd9557SMatthias Ringwald # pragma warning(push) 5298cd9557SMatthias Ringwald # pragma warning (disable : 4996) 5398cd9557SMatthias Ringwald #else 5498cd9557SMatthias Ringwald # include <dirent.h> 5598cd9557SMatthias Ringwald # include <libgen.h> 5698cd9557SMatthias Ringwald # include <sys/stat.h> 5798cd9557SMatthias Ringwald # include <stddef.h> 5898cd9557SMatthias Ringwald #endif 5998cd9557SMatthias Ringwald #ifdef __MINGW32__ 6098cd9557SMatthias Ringwald # include <tchar.h> 6198cd9557SMatthias Ringwald #endif 6298cd9557SMatthias Ringwald 6398cd9557SMatthias Ringwald 6498cd9557SMatthias Ringwald /* types */ 6598cd9557SMatthias Ringwald 6698cd9557SMatthias Ringwald /* Windows UNICODE wide character support */ 6798cd9557SMatthias Ringwald #if defined _MSC_VER || defined __MINGW32__ 6898cd9557SMatthias Ringwald # define _tinydir_char_t TCHAR 6998cd9557SMatthias Ringwald # define TINYDIR_STRING(s) _TEXT(s) 7098cd9557SMatthias Ringwald # define _tinydir_strlen _tcslen 7198cd9557SMatthias Ringwald # define _tinydir_strcpy _tcscpy 7298cd9557SMatthias Ringwald # define _tinydir_strcat _tcscat 7398cd9557SMatthias Ringwald # define _tinydir_strcmp _tcscmp 7498cd9557SMatthias Ringwald # define _tinydir_strrchr _tcsrchr 7598cd9557SMatthias Ringwald # define _tinydir_strncmp _tcsncmp 7698cd9557SMatthias Ringwald #else 7798cd9557SMatthias Ringwald # define _tinydir_char_t char 7898cd9557SMatthias Ringwald # define TINYDIR_STRING(s) s 7998cd9557SMatthias Ringwald # define _tinydir_strlen strlen 8098cd9557SMatthias Ringwald # define _tinydir_strcpy strcpy 8198cd9557SMatthias Ringwald # define _tinydir_strcat strcat 8298cd9557SMatthias Ringwald # define _tinydir_strcmp strcmp 8398cd9557SMatthias Ringwald # define _tinydir_strrchr strrchr 8498cd9557SMatthias Ringwald # define _tinydir_strncmp strncmp 8598cd9557SMatthias Ringwald #endif 8698cd9557SMatthias Ringwald 8798cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 8898cd9557SMatthias Ringwald # include <windows.h> 8998cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX MAX_PATH 9098cd9557SMatthias Ringwald #elif defined __linux__ 9198cd9557SMatthias Ringwald # include <limits.h> 92*ec8ca29fSMatthias Ringwald /* BK - only use PATH_MAX if defined */ 93*ec8ca29fSMatthias Ringwald # if defined(PATH_MAX) 9498cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX PATH_MAX 95*ec8ca29fSMatthias Ringwald # endif 9698cd9557SMatthias Ringwald #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) 9798cd9557SMatthias Ringwald # include <sys/param.h> 9898cd9557SMatthias Ringwald # if defined(BSD) 9998cd9557SMatthias Ringwald # include <limits.h> 10098cd9557SMatthias Ringwald # define _TINYDIR_PATH_MAX PATH_MAX 10198cd9557SMatthias Ringwald # endif 10298cd9557SMatthias Ringwald #endif 10398cd9557SMatthias Ringwald 10498cd9557SMatthias Ringwald #ifndef _TINYDIR_PATH_MAX 10598cd9557SMatthias Ringwald #define _TINYDIR_PATH_MAX 4096 10698cd9557SMatthias Ringwald #endif 10798cd9557SMatthias Ringwald 10898cd9557SMatthias Ringwald #ifdef _MSC_VER 10998cd9557SMatthias Ringwald /* extra chars for the "\\*" mask */ 11098cd9557SMatthias Ringwald # define _TINYDIR_PATH_EXTRA 2 11198cd9557SMatthias Ringwald #else 11298cd9557SMatthias Ringwald # define _TINYDIR_PATH_EXTRA 0 11398cd9557SMatthias Ringwald #endif 11498cd9557SMatthias Ringwald 11598cd9557SMatthias Ringwald #define _TINYDIR_FILENAME_MAX 256 11698cd9557SMatthias Ringwald 11798cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 11898cd9557SMatthias Ringwald #define _TINYDIR_DRIVE_MAX 3 11998cd9557SMatthias Ringwald #endif 12098cd9557SMatthias Ringwald 12198cd9557SMatthias Ringwald #ifdef _MSC_VER 12298cd9557SMatthias Ringwald # define _TINYDIR_FUNC static __inline 12398cd9557SMatthias Ringwald #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 12498cd9557SMatthias Ringwald # define _TINYDIR_FUNC static __inline__ 12598cd9557SMatthias Ringwald #else 12698cd9557SMatthias Ringwald # define _TINYDIR_FUNC static inline 12798cd9557SMatthias Ringwald #endif 12898cd9557SMatthias Ringwald 12998cd9557SMatthias Ringwald /* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */ 13098cd9557SMatthias Ringwald #ifdef TINYDIR_USE_READDIR_R 13198cd9557SMatthias Ringwald 13298cd9557SMatthias Ringwald /* readdir_r is a POSIX-only function, and may not be available under various 13398cd9557SMatthias Ringwald * environments/settings, e.g. MinGW. Use readdir fallback */ 13498cd9557SMatthias Ringwald #if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\ 13598cd9557SMatthias Ringwald _POSIX_SOURCE 13698cd9557SMatthias Ringwald # define _TINYDIR_HAS_READDIR_R 13798cd9557SMatthias Ringwald #endif 13898cd9557SMatthias Ringwald #if _POSIX_C_SOURCE >= 200112L 13998cd9557SMatthias Ringwald # define _TINYDIR_HAS_FPATHCONF 14098cd9557SMatthias Ringwald # include <unistd.h> 14198cd9557SMatthias Ringwald #endif 14298cd9557SMatthias Ringwald #if _BSD_SOURCE || _SVID_SOURCE || \ 14398cd9557SMatthias Ringwald (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) 14498cd9557SMatthias Ringwald # define _TINYDIR_HAS_DIRFD 14598cd9557SMatthias Ringwald # include <sys/types.h> 14698cd9557SMatthias Ringwald #endif 14798cd9557SMatthias Ringwald #if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\ 14898cd9557SMatthias Ringwald defined _PC_NAME_MAX 14998cd9557SMatthias Ringwald # define _TINYDIR_USE_FPATHCONF 15098cd9557SMatthias Ringwald #endif 15198cd9557SMatthias Ringwald #if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\ 15298cd9557SMatthias Ringwald !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX) 15398cd9557SMatthias Ringwald # define _TINYDIR_USE_READDIR 15498cd9557SMatthias Ringwald #endif 15598cd9557SMatthias Ringwald 15698cd9557SMatthias Ringwald /* Use readdir by default */ 15798cd9557SMatthias Ringwald #else 15898cd9557SMatthias Ringwald # define _TINYDIR_USE_READDIR 15998cd9557SMatthias Ringwald #endif 16098cd9557SMatthias Ringwald 16198cd9557SMatthias Ringwald /* MINGW32 has two versions of dirent, ASCII and UNICODE*/ 16298cd9557SMatthias Ringwald #ifndef _MSC_VER 16398cd9557SMatthias Ringwald #if (defined __MINGW32__) && (defined _UNICODE) 16498cd9557SMatthias Ringwald #define _TINYDIR_DIR _WDIR 16598cd9557SMatthias Ringwald #define _tinydir_dirent _wdirent 16698cd9557SMatthias Ringwald #define _tinydir_opendir _wopendir 16798cd9557SMatthias Ringwald #define _tinydir_readdir _wreaddir 16898cd9557SMatthias Ringwald #define _tinydir_closedir _wclosedir 16998cd9557SMatthias Ringwald #else 17098cd9557SMatthias Ringwald #define _TINYDIR_DIR DIR 17198cd9557SMatthias Ringwald #define _tinydir_dirent dirent 17298cd9557SMatthias Ringwald #define _tinydir_opendir opendir 17398cd9557SMatthias Ringwald #define _tinydir_readdir readdir 17498cd9557SMatthias Ringwald #define _tinydir_closedir closedir 17598cd9557SMatthias Ringwald #endif 17698cd9557SMatthias Ringwald #endif 17798cd9557SMatthias Ringwald 17898cd9557SMatthias Ringwald /* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */ 17998cd9557SMatthias Ringwald #if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE) 18098cd9557SMatthias Ringwald #elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE) 18198cd9557SMatthias Ringwald #else 18298cd9557SMatthias Ringwald #error "Either define both alloc and free or none of them!" 18398cd9557SMatthias Ringwald #endif 18498cd9557SMatthias Ringwald 18598cd9557SMatthias Ringwald #if !defined(_TINYDIR_MALLOC) 18698cd9557SMatthias Ringwald #define _TINYDIR_MALLOC(_size) malloc(_size) 18798cd9557SMatthias Ringwald #define _TINYDIR_FREE(_ptr) free(_ptr) 18898cd9557SMatthias Ringwald #endif /* !defined(_TINYDIR_MALLOC) */ 18998cd9557SMatthias Ringwald 19098cd9557SMatthias Ringwald typedef struct tinydir_file 19198cd9557SMatthias Ringwald { 19298cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 19398cd9557SMatthias Ringwald _tinydir_char_t name[_TINYDIR_FILENAME_MAX]; 19498cd9557SMatthias Ringwald _tinydir_char_t *extension; 19598cd9557SMatthias Ringwald int is_dir; 19698cd9557SMatthias Ringwald int is_reg; 19798cd9557SMatthias Ringwald 19898cd9557SMatthias Ringwald #ifndef _MSC_VER 19998cd9557SMatthias Ringwald #ifdef __MINGW32__ 20098cd9557SMatthias Ringwald struct _stat _s; 20198cd9557SMatthias Ringwald #else 20298cd9557SMatthias Ringwald struct stat _s; 20398cd9557SMatthias Ringwald #endif 20498cd9557SMatthias Ringwald #endif 20598cd9557SMatthias Ringwald } tinydir_file; 20698cd9557SMatthias Ringwald 20798cd9557SMatthias Ringwald typedef struct tinydir_dir 20898cd9557SMatthias Ringwald { 20998cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 21098cd9557SMatthias Ringwald int has_next; 21198cd9557SMatthias Ringwald size_t n_files; 21298cd9557SMatthias Ringwald 21398cd9557SMatthias Ringwald tinydir_file *_files; 21498cd9557SMatthias Ringwald #ifdef _MSC_VER 21598cd9557SMatthias Ringwald HANDLE _h; 21698cd9557SMatthias Ringwald WIN32_FIND_DATA _f; 21798cd9557SMatthias Ringwald #else 21898cd9557SMatthias Ringwald _TINYDIR_DIR *_d; 21998cd9557SMatthias Ringwald struct _tinydir_dirent *_e; 22098cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 22198cd9557SMatthias Ringwald struct _tinydir_dirent *_ep; 22298cd9557SMatthias Ringwald #endif 22398cd9557SMatthias Ringwald #endif 22498cd9557SMatthias Ringwald } tinydir_dir; 22598cd9557SMatthias Ringwald 22698cd9557SMatthias Ringwald 22798cd9557SMatthias Ringwald /* declarations */ 22898cd9557SMatthias Ringwald 22998cd9557SMatthias Ringwald _TINYDIR_FUNC 23098cd9557SMatthias Ringwald int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path); 23198cd9557SMatthias Ringwald _TINYDIR_FUNC 23298cd9557SMatthias Ringwald int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path); 23398cd9557SMatthias Ringwald _TINYDIR_FUNC 23498cd9557SMatthias Ringwald void tinydir_close(tinydir_dir *dir); 23598cd9557SMatthias Ringwald 23698cd9557SMatthias Ringwald _TINYDIR_FUNC 23798cd9557SMatthias Ringwald int tinydir_next(tinydir_dir *dir); 23898cd9557SMatthias Ringwald _TINYDIR_FUNC 23998cd9557SMatthias Ringwald int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file); 24098cd9557SMatthias Ringwald _TINYDIR_FUNC 24198cd9557SMatthias Ringwald int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i); 24298cd9557SMatthias Ringwald _TINYDIR_FUNC 24398cd9557SMatthias Ringwald int tinydir_open_subdir_n(tinydir_dir *dir, size_t i); 24498cd9557SMatthias Ringwald 24598cd9557SMatthias Ringwald _TINYDIR_FUNC 24698cd9557SMatthias Ringwald int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path); 24798cd9557SMatthias Ringwald _TINYDIR_FUNC 24898cd9557SMatthias Ringwald void _tinydir_get_ext(tinydir_file *file); 24998cd9557SMatthias Ringwald _TINYDIR_FUNC 25098cd9557SMatthias Ringwald int _tinydir_file_cmp(const void *a, const void *b); 25198cd9557SMatthias Ringwald #ifndef _MSC_VER 25298cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 25398cd9557SMatthias Ringwald _TINYDIR_FUNC 25498cd9557SMatthias Ringwald size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp); 25598cd9557SMatthias Ringwald #endif 25698cd9557SMatthias Ringwald #endif 25798cd9557SMatthias Ringwald 25898cd9557SMatthias Ringwald 25998cd9557SMatthias Ringwald /* definitions*/ 26098cd9557SMatthias Ringwald 26198cd9557SMatthias Ringwald _TINYDIR_FUNC 26298cd9557SMatthias Ringwald int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) 26398cd9557SMatthias Ringwald { 26498cd9557SMatthias Ringwald #ifndef _MSC_VER 26598cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 26698cd9557SMatthias Ringwald int error; 26798cd9557SMatthias Ringwald int size; /* using int size */ 26898cd9557SMatthias Ringwald #endif 26998cd9557SMatthias Ringwald #else 27098cd9557SMatthias Ringwald _tinydir_char_t path_buf[_TINYDIR_PATH_MAX]; 27198cd9557SMatthias Ringwald #endif 27298cd9557SMatthias Ringwald _tinydir_char_t *pathp; 27398cd9557SMatthias Ringwald 27498cd9557SMatthias Ringwald if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) 27598cd9557SMatthias Ringwald { 27698cd9557SMatthias Ringwald errno = EINVAL; 27798cd9557SMatthias Ringwald return -1; 27898cd9557SMatthias Ringwald } 27998cd9557SMatthias Ringwald if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 28098cd9557SMatthias Ringwald { 28198cd9557SMatthias Ringwald errno = ENAMETOOLONG; 28298cd9557SMatthias Ringwald return -1; 28398cd9557SMatthias Ringwald } 28498cd9557SMatthias Ringwald 28598cd9557SMatthias Ringwald /* initialise dir */ 28698cd9557SMatthias Ringwald dir->_files = NULL; 28798cd9557SMatthias Ringwald #ifdef _MSC_VER 28898cd9557SMatthias Ringwald dir->_h = INVALID_HANDLE_VALUE; 28998cd9557SMatthias Ringwald #else 29098cd9557SMatthias Ringwald dir->_d = NULL; 29198cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 29298cd9557SMatthias Ringwald dir->_ep = NULL; 29398cd9557SMatthias Ringwald #endif 29498cd9557SMatthias Ringwald #endif 29598cd9557SMatthias Ringwald tinydir_close(dir); 29698cd9557SMatthias Ringwald 29798cd9557SMatthias Ringwald _tinydir_strcpy(dir->path, path); 29898cd9557SMatthias Ringwald /* Remove trailing slashes */ 29998cd9557SMatthias Ringwald pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; 30098cd9557SMatthias Ringwald while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) 30198cd9557SMatthias Ringwald { 30298cd9557SMatthias Ringwald *pathp = TINYDIR_STRING('\0'); 30398cd9557SMatthias Ringwald pathp++; 30498cd9557SMatthias Ringwald } 30598cd9557SMatthias Ringwald #ifdef _MSC_VER 30698cd9557SMatthias Ringwald _tinydir_strcpy(path_buf, dir->path); 30798cd9557SMatthias Ringwald _tinydir_strcat(path_buf, TINYDIR_STRING("\\*")); 30898cd9557SMatthias Ringwald #if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) 30998cd9557SMatthias Ringwald dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0); 31098cd9557SMatthias Ringwald #else 31198cd9557SMatthias Ringwald dir->_h = FindFirstFile(path_buf, &dir->_f); 31298cd9557SMatthias Ringwald #endif 31398cd9557SMatthias Ringwald if (dir->_h == INVALID_HANDLE_VALUE) 31498cd9557SMatthias Ringwald { 31598cd9557SMatthias Ringwald errno = ENOENT; 31698cd9557SMatthias Ringwald #else 31798cd9557SMatthias Ringwald dir->_d = _tinydir_opendir(path); 31898cd9557SMatthias Ringwald if (dir->_d == NULL) 31998cd9557SMatthias Ringwald { 32098cd9557SMatthias Ringwald #endif 32198cd9557SMatthias Ringwald goto bail; 32298cd9557SMatthias Ringwald } 32398cd9557SMatthias Ringwald 32498cd9557SMatthias Ringwald /* read first file */ 32598cd9557SMatthias Ringwald dir->has_next = 1; 32698cd9557SMatthias Ringwald #ifndef _MSC_VER 32798cd9557SMatthias Ringwald #ifdef _TINYDIR_USE_READDIR 32898cd9557SMatthias Ringwald dir->_e = _tinydir_readdir(dir->_d); 32998cd9557SMatthias Ringwald #else 33098cd9557SMatthias Ringwald /* allocate dirent buffer for readdir_r */ 33198cd9557SMatthias Ringwald size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ 33298cd9557SMatthias Ringwald if (size == -1) return -1; 33398cd9557SMatthias Ringwald dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); 33498cd9557SMatthias Ringwald if (dir->_ep == NULL) return -1; 33598cd9557SMatthias Ringwald 33698cd9557SMatthias Ringwald error = readdir_r(dir->_d, dir->_ep, &dir->_e); 33798cd9557SMatthias Ringwald if (error != 0) return -1; 33898cd9557SMatthias Ringwald #endif 33998cd9557SMatthias Ringwald if (dir->_e == NULL) 34098cd9557SMatthias Ringwald { 34198cd9557SMatthias Ringwald dir->has_next = 0; 34298cd9557SMatthias Ringwald } 34398cd9557SMatthias Ringwald #endif 34498cd9557SMatthias Ringwald 34598cd9557SMatthias Ringwald return 0; 34698cd9557SMatthias Ringwald 34798cd9557SMatthias Ringwald bail: 34898cd9557SMatthias Ringwald tinydir_close(dir); 34998cd9557SMatthias Ringwald return -1; 35098cd9557SMatthias Ringwald } 35198cd9557SMatthias Ringwald 35298cd9557SMatthias Ringwald _TINYDIR_FUNC 35398cd9557SMatthias Ringwald int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) 35498cd9557SMatthias Ringwald { 35598cd9557SMatthias Ringwald /* Count the number of files first, to pre-allocate the files array */ 35698cd9557SMatthias Ringwald size_t n_files = 0; 35798cd9557SMatthias Ringwald if (tinydir_open(dir, path) == -1) 35898cd9557SMatthias Ringwald { 35998cd9557SMatthias Ringwald return -1; 36098cd9557SMatthias Ringwald } 36198cd9557SMatthias Ringwald while (dir->has_next) 36298cd9557SMatthias Ringwald { 36398cd9557SMatthias Ringwald n_files++; 36498cd9557SMatthias Ringwald if (tinydir_next(dir) == -1) 36598cd9557SMatthias Ringwald { 36698cd9557SMatthias Ringwald goto bail; 36798cd9557SMatthias Ringwald } 36898cd9557SMatthias Ringwald } 36998cd9557SMatthias Ringwald tinydir_close(dir); 37098cd9557SMatthias Ringwald 371*ec8ca29fSMatthias Ringwald if (n_files == 0 || tinydir_open(dir, path) == -1) 37298cd9557SMatthias Ringwald { 37398cd9557SMatthias Ringwald return -1; 37498cd9557SMatthias Ringwald } 37598cd9557SMatthias Ringwald 37698cd9557SMatthias Ringwald dir->n_files = 0; 37798cd9557SMatthias Ringwald dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); 37898cd9557SMatthias Ringwald if (dir->_files == NULL) 37998cd9557SMatthias Ringwald { 38098cd9557SMatthias Ringwald goto bail; 38198cd9557SMatthias Ringwald } 38298cd9557SMatthias Ringwald while (dir->has_next) 38398cd9557SMatthias Ringwald { 38498cd9557SMatthias Ringwald tinydir_file *p_file; 38598cd9557SMatthias Ringwald dir->n_files++; 38698cd9557SMatthias Ringwald 38798cd9557SMatthias Ringwald p_file = &dir->_files[dir->n_files - 1]; 38898cd9557SMatthias Ringwald if (tinydir_readfile(dir, p_file) == -1) 38998cd9557SMatthias Ringwald { 39098cd9557SMatthias Ringwald goto bail; 39198cd9557SMatthias Ringwald } 39298cd9557SMatthias Ringwald 39398cd9557SMatthias Ringwald if (tinydir_next(dir) == -1) 39498cd9557SMatthias Ringwald { 39598cd9557SMatthias Ringwald goto bail; 39698cd9557SMatthias Ringwald } 39798cd9557SMatthias Ringwald 39898cd9557SMatthias Ringwald /* Just in case the number of files has changed between the first and 39998cd9557SMatthias Ringwald second reads, terminate without writing into unallocated memory */ 40098cd9557SMatthias Ringwald if (dir->n_files == n_files) 40198cd9557SMatthias Ringwald { 40298cd9557SMatthias Ringwald break; 40398cd9557SMatthias Ringwald } 40498cd9557SMatthias Ringwald } 40598cd9557SMatthias Ringwald 40698cd9557SMatthias Ringwald qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp); 40798cd9557SMatthias Ringwald 40898cd9557SMatthias Ringwald return 0; 40998cd9557SMatthias Ringwald 41098cd9557SMatthias Ringwald bail: 41198cd9557SMatthias Ringwald tinydir_close(dir); 41298cd9557SMatthias Ringwald return -1; 41398cd9557SMatthias Ringwald } 41498cd9557SMatthias Ringwald 41598cd9557SMatthias Ringwald _TINYDIR_FUNC 41698cd9557SMatthias Ringwald void tinydir_close(tinydir_dir *dir) 41798cd9557SMatthias Ringwald { 41898cd9557SMatthias Ringwald if (dir == NULL) 41998cd9557SMatthias Ringwald { 42098cd9557SMatthias Ringwald return; 42198cd9557SMatthias Ringwald } 42298cd9557SMatthias Ringwald 42398cd9557SMatthias Ringwald memset(dir->path, 0, sizeof(dir->path)); 42498cd9557SMatthias Ringwald dir->has_next = 0; 42598cd9557SMatthias Ringwald dir->n_files = 0; 42698cd9557SMatthias Ringwald _TINYDIR_FREE(dir->_files); 42798cd9557SMatthias Ringwald dir->_files = NULL; 42898cd9557SMatthias Ringwald #ifdef _MSC_VER 42998cd9557SMatthias Ringwald if (dir->_h != INVALID_HANDLE_VALUE) 43098cd9557SMatthias Ringwald { 43198cd9557SMatthias Ringwald FindClose(dir->_h); 43298cd9557SMatthias Ringwald } 43398cd9557SMatthias Ringwald dir->_h = INVALID_HANDLE_VALUE; 43498cd9557SMatthias Ringwald #else 43598cd9557SMatthias Ringwald if (dir->_d) 43698cd9557SMatthias Ringwald { 43798cd9557SMatthias Ringwald _tinydir_closedir(dir->_d); 43898cd9557SMatthias Ringwald } 43998cd9557SMatthias Ringwald dir->_d = NULL; 44098cd9557SMatthias Ringwald dir->_e = NULL; 44198cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 44298cd9557SMatthias Ringwald _TINYDIR_FREE(dir->_ep); 44398cd9557SMatthias Ringwald dir->_ep = NULL; 44498cd9557SMatthias Ringwald #endif 44598cd9557SMatthias Ringwald #endif 44698cd9557SMatthias Ringwald } 44798cd9557SMatthias Ringwald 44898cd9557SMatthias Ringwald _TINYDIR_FUNC 44998cd9557SMatthias Ringwald int tinydir_next(tinydir_dir *dir) 45098cd9557SMatthias Ringwald { 45198cd9557SMatthias Ringwald if (dir == NULL) 45298cd9557SMatthias Ringwald { 45398cd9557SMatthias Ringwald errno = EINVAL; 45498cd9557SMatthias Ringwald return -1; 45598cd9557SMatthias Ringwald } 45698cd9557SMatthias Ringwald if (!dir->has_next) 45798cd9557SMatthias Ringwald { 45898cd9557SMatthias Ringwald errno = ENOENT; 45998cd9557SMatthias Ringwald return -1; 46098cd9557SMatthias Ringwald } 46198cd9557SMatthias Ringwald 46298cd9557SMatthias Ringwald #ifdef _MSC_VER 46398cd9557SMatthias Ringwald if (FindNextFile(dir->_h, &dir->_f) == 0) 46498cd9557SMatthias Ringwald #else 46598cd9557SMatthias Ringwald #ifdef _TINYDIR_USE_READDIR 46698cd9557SMatthias Ringwald dir->_e = _tinydir_readdir(dir->_d); 46798cd9557SMatthias Ringwald #else 46898cd9557SMatthias Ringwald if (dir->_ep == NULL) 46998cd9557SMatthias Ringwald { 47098cd9557SMatthias Ringwald return -1; 47198cd9557SMatthias Ringwald } 47298cd9557SMatthias Ringwald if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) 47398cd9557SMatthias Ringwald { 47498cd9557SMatthias Ringwald return -1; 47598cd9557SMatthias Ringwald } 47698cd9557SMatthias Ringwald #endif 47798cd9557SMatthias Ringwald if (dir->_e == NULL) 47898cd9557SMatthias Ringwald #endif 47998cd9557SMatthias Ringwald { 48098cd9557SMatthias Ringwald dir->has_next = 0; 48198cd9557SMatthias Ringwald #ifdef _MSC_VER 48298cd9557SMatthias Ringwald if (GetLastError() != ERROR_SUCCESS && 48398cd9557SMatthias Ringwald GetLastError() != ERROR_NO_MORE_FILES) 48498cd9557SMatthias Ringwald { 48598cd9557SMatthias Ringwald tinydir_close(dir); 48698cd9557SMatthias Ringwald errno = EIO; 48798cd9557SMatthias Ringwald return -1; 48898cd9557SMatthias Ringwald } 48998cd9557SMatthias Ringwald #endif 49098cd9557SMatthias Ringwald } 49198cd9557SMatthias Ringwald 49298cd9557SMatthias Ringwald return 0; 49398cd9557SMatthias Ringwald } 49498cd9557SMatthias Ringwald 49598cd9557SMatthias Ringwald _TINYDIR_FUNC 49698cd9557SMatthias Ringwald int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) 49798cd9557SMatthias Ringwald { 49898cd9557SMatthias Ringwald if (dir == NULL || file == NULL) 49998cd9557SMatthias Ringwald { 50098cd9557SMatthias Ringwald errno = EINVAL; 50198cd9557SMatthias Ringwald return -1; 50298cd9557SMatthias Ringwald } 50398cd9557SMatthias Ringwald #ifdef _MSC_VER 50498cd9557SMatthias Ringwald if (dir->_h == INVALID_HANDLE_VALUE) 50598cd9557SMatthias Ringwald #else 50698cd9557SMatthias Ringwald if (dir->_e == NULL) 50798cd9557SMatthias Ringwald #endif 50898cd9557SMatthias Ringwald { 50998cd9557SMatthias Ringwald errno = ENOENT; 51098cd9557SMatthias Ringwald return -1; 51198cd9557SMatthias Ringwald } 51298cd9557SMatthias Ringwald if (_tinydir_strlen(dir->path) + 51398cd9557SMatthias Ringwald _tinydir_strlen( 51498cd9557SMatthias Ringwald #ifdef _MSC_VER 51598cd9557SMatthias Ringwald dir->_f.cFileName 51698cd9557SMatthias Ringwald #else 51798cd9557SMatthias Ringwald dir->_e->d_name 51898cd9557SMatthias Ringwald #endif 51998cd9557SMatthias Ringwald ) + 1 + _TINYDIR_PATH_EXTRA >= 52098cd9557SMatthias Ringwald _TINYDIR_PATH_MAX) 52198cd9557SMatthias Ringwald { 52298cd9557SMatthias Ringwald /* the path for the file will be too long */ 52398cd9557SMatthias Ringwald errno = ENAMETOOLONG; 52498cd9557SMatthias Ringwald return -1; 52598cd9557SMatthias Ringwald } 52698cd9557SMatthias Ringwald if (_tinydir_strlen( 52798cd9557SMatthias Ringwald #ifdef _MSC_VER 52898cd9557SMatthias Ringwald dir->_f.cFileName 52998cd9557SMatthias Ringwald #else 53098cd9557SMatthias Ringwald dir->_e->d_name 53198cd9557SMatthias Ringwald #endif 53298cd9557SMatthias Ringwald ) >= _TINYDIR_FILENAME_MAX) 53398cd9557SMatthias Ringwald { 53498cd9557SMatthias Ringwald errno = ENAMETOOLONG; 53598cd9557SMatthias Ringwald return -1; 53698cd9557SMatthias Ringwald } 53798cd9557SMatthias Ringwald 53898cd9557SMatthias Ringwald _tinydir_strcpy(file->path, dir->path); 53998cd9557SMatthias Ringwald _tinydir_strcat(file->path, TINYDIR_STRING("/")); 54098cd9557SMatthias Ringwald _tinydir_strcpy(file->name, 54198cd9557SMatthias Ringwald #ifdef _MSC_VER 54298cd9557SMatthias Ringwald dir->_f.cFileName 54398cd9557SMatthias Ringwald #else 54498cd9557SMatthias Ringwald dir->_e->d_name 54598cd9557SMatthias Ringwald #endif 54698cd9557SMatthias Ringwald ); 54798cd9557SMatthias Ringwald _tinydir_strcat(file->path, file->name); 54898cd9557SMatthias Ringwald #ifndef _MSC_VER 54998cd9557SMatthias Ringwald #ifdef __MINGW32__ 55098cd9557SMatthias Ringwald if (_tstat( 55198cd9557SMatthias Ringwald #else 55298cd9557SMatthias Ringwald if (stat( 55398cd9557SMatthias Ringwald #endif 55498cd9557SMatthias Ringwald file->path, &file->_s) == -1) 55598cd9557SMatthias Ringwald { 55698cd9557SMatthias Ringwald return -1; 55798cd9557SMatthias Ringwald } 55898cd9557SMatthias Ringwald #endif 55998cd9557SMatthias Ringwald _tinydir_get_ext(file); 56098cd9557SMatthias Ringwald 56198cd9557SMatthias Ringwald file->is_dir = 56298cd9557SMatthias Ringwald #ifdef _MSC_VER 56398cd9557SMatthias Ringwald !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 56498cd9557SMatthias Ringwald #else 56598cd9557SMatthias Ringwald S_ISDIR(file->_s.st_mode); 56698cd9557SMatthias Ringwald #endif 56798cd9557SMatthias Ringwald file->is_reg = 56898cd9557SMatthias Ringwald #ifdef _MSC_VER 56998cd9557SMatthias Ringwald !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || 57098cd9557SMatthias Ringwald ( 57198cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && 57298cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && 57398cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && 57498cd9557SMatthias Ringwald #ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM 57598cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && 57698cd9557SMatthias Ringwald #endif 57798cd9557SMatthias Ringwald #ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA 57898cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && 57998cd9557SMatthias Ringwald #endif 58098cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && 58198cd9557SMatthias Ringwald !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); 58298cd9557SMatthias Ringwald #else 58398cd9557SMatthias Ringwald S_ISREG(file->_s.st_mode); 58498cd9557SMatthias Ringwald #endif 58598cd9557SMatthias Ringwald 58698cd9557SMatthias Ringwald return 0; 58798cd9557SMatthias Ringwald } 58898cd9557SMatthias Ringwald 58998cd9557SMatthias Ringwald _TINYDIR_FUNC 59098cd9557SMatthias Ringwald int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) 59198cd9557SMatthias Ringwald { 59298cd9557SMatthias Ringwald if (dir == NULL || file == NULL) 59398cd9557SMatthias Ringwald { 59498cd9557SMatthias Ringwald errno = EINVAL; 59598cd9557SMatthias Ringwald return -1; 59698cd9557SMatthias Ringwald } 59798cd9557SMatthias Ringwald if (i >= dir->n_files) 59898cd9557SMatthias Ringwald { 59998cd9557SMatthias Ringwald errno = ENOENT; 60098cd9557SMatthias Ringwald return -1; 60198cd9557SMatthias Ringwald } 60298cd9557SMatthias Ringwald 60398cd9557SMatthias Ringwald memcpy(file, &dir->_files[i], sizeof(tinydir_file)); 60498cd9557SMatthias Ringwald _tinydir_get_ext(file); 60598cd9557SMatthias Ringwald 60698cd9557SMatthias Ringwald return 0; 60798cd9557SMatthias Ringwald } 60898cd9557SMatthias Ringwald 60998cd9557SMatthias Ringwald _TINYDIR_FUNC 61098cd9557SMatthias Ringwald int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) 61198cd9557SMatthias Ringwald { 61298cd9557SMatthias Ringwald _tinydir_char_t path[_TINYDIR_PATH_MAX]; 61398cd9557SMatthias Ringwald if (dir == NULL) 61498cd9557SMatthias Ringwald { 61598cd9557SMatthias Ringwald errno = EINVAL; 61698cd9557SMatthias Ringwald return -1; 61798cd9557SMatthias Ringwald } 61898cd9557SMatthias Ringwald if (i >= dir->n_files || !dir->_files[i].is_dir) 61998cd9557SMatthias Ringwald { 62098cd9557SMatthias Ringwald errno = ENOENT; 62198cd9557SMatthias Ringwald return -1; 62298cd9557SMatthias Ringwald } 62398cd9557SMatthias Ringwald 62498cd9557SMatthias Ringwald _tinydir_strcpy(path, dir->_files[i].path); 62598cd9557SMatthias Ringwald tinydir_close(dir); 62698cd9557SMatthias Ringwald if (tinydir_open_sorted(dir, path) == -1) 62798cd9557SMatthias Ringwald { 62898cd9557SMatthias Ringwald return -1; 62998cd9557SMatthias Ringwald } 63098cd9557SMatthias Ringwald 63198cd9557SMatthias Ringwald return 0; 63298cd9557SMatthias Ringwald } 63398cd9557SMatthias Ringwald 63498cd9557SMatthias Ringwald /* Open a single file given its path */ 63598cd9557SMatthias Ringwald _TINYDIR_FUNC 63698cd9557SMatthias Ringwald int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) 63798cd9557SMatthias Ringwald { 63898cd9557SMatthias Ringwald tinydir_dir dir; 63998cd9557SMatthias Ringwald int result = 0; 64098cd9557SMatthias Ringwald int found = 0; 64198cd9557SMatthias Ringwald _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX]; 64298cd9557SMatthias Ringwald _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX]; 64398cd9557SMatthias Ringwald _tinydir_char_t *dir_name; 64498cd9557SMatthias Ringwald _tinydir_char_t *base_name; 64598cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 64698cd9557SMatthias Ringwald _tinydir_char_t drive_buf[_TINYDIR_PATH_MAX]; 64798cd9557SMatthias Ringwald _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; 64898cd9557SMatthias Ringwald #endif 64998cd9557SMatthias Ringwald 65098cd9557SMatthias Ringwald if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) 65198cd9557SMatthias Ringwald { 65298cd9557SMatthias Ringwald errno = EINVAL; 65398cd9557SMatthias Ringwald return -1; 65498cd9557SMatthias Ringwald } 65598cd9557SMatthias Ringwald if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) 65698cd9557SMatthias Ringwald { 65798cd9557SMatthias Ringwald errno = ENAMETOOLONG; 65898cd9557SMatthias Ringwald return -1; 65998cd9557SMatthias Ringwald } 66098cd9557SMatthias Ringwald 66198cd9557SMatthias Ringwald /* Get the parent path */ 66298cd9557SMatthias Ringwald #if (defined _MSC_VER || defined __MINGW32__) 66398cd9557SMatthias Ringwald #if ((defined _MSC_VER) && (_MSC_VER >= 1400)) 664*ec8ca29fSMatthias Ringwald errno = _tsplitpath_s( 66598cd9557SMatthias Ringwald path, 66698cd9557SMatthias Ringwald drive_buf, _TINYDIR_DRIVE_MAX, 66798cd9557SMatthias Ringwald dir_name_buf, _TINYDIR_FILENAME_MAX, 66898cd9557SMatthias Ringwald file_name_buf, _TINYDIR_FILENAME_MAX, 66998cd9557SMatthias Ringwald ext_buf, _TINYDIR_FILENAME_MAX); 67098cd9557SMatthias Ringwald #else 67198cd9557SMatthias Ringwald _tsplitpath( 67298cd9557SMatthias Ringwald path, 67398cd9557SMatthias Ringwald drive_buf, 67498cd9557SMatthias Ringwald dir_name_buf, 67598cd9557SMatthias Ringwald file_name_buf, 67698cd9557SMatthias Ringwald ext_buf); 67798cd9557SMatthias Ringwald #endif 67898cd9557SMatthias Ringwald 679*ec8ca29fSMatthias Ringwald if (errno) 680*ec8ca29fSMatthias Ringwald { 681*ec8ca29fSMatthias Ringwald return -1; 682*ec8ca29fSMatthias Ringwald } 683*ec8ca29fSMatthias Ringwald 68498cd9557SMatthias Ringwald /* _splitpath_s not work fine with only filename and widechar support */ 68598cd9557SMatthias Ringwald #ifdef _UNICODE 68698cd9557SMatthias Ringwald if (drive_buf[0] == L'\xFEFE') 68798cd9557SMatthias Ringwald drive_buf[0] = '\0'; 68898cd9557SMatthias Ringwald if (dir_name_buf[0] == L'\xFEFE') 68998cd9557SMatthias Ringwald dir_name_buf[0] = '\0'; 69098cd9557SMatthias Ringwald #endif 69198cd9557SMatthias Ringwald 69298cd9557SMatthias Ringwald /* Emulate the behavior of dirname by returning "." for dir name if it's 69398cd9557SMatthias Ringwald empty */ 69498cd9557SMatthias Ringwald if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') 69598cd9557SMatthias Ringwald { 69698cd9557SMatthias Ringwald _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); 69798cd9557SMatthias Ringwald } 69898cd9557SMatthias Ringwald /* Concatenate the drive letter and dir name to form full dir name */ 69998cd9557SMatthias Ringwald _tinydir_strcat(drive_buf, dir_name_buf); 70098cd9557SMatthias Ringwald dir_name = drive_buf; 70198cd9557SMatthias Ringwald /* Concatenate the file name and extension to form base name */ 70298cd9557SMatthias Ringwald _tinydir_strcat(file_name_buf, ext_buf); 70398cd9557SMatthias Ringwald base_name = file_name_buf; 70498cd9557SMatthias Ringwald #else 70598cd9557SMatthias Ringwald _tinydir_strcpy(dir_name_buf, path); 70698cd9557SMatthias Ringwald dir_name = dirname(dir_name_buf); 70798cd9557SMatthias Ringwald _tinydir_strcpy(file_name_buf, path); 70898cd9557SMatthias Ringwald base_name =basename(file_name_buf); 70998cd9557SMatthias Ringwald #endif 71098cd9557SMatthias Ringwald 71198cd9557SMatthias Ringwald /* Open the parent directory */ 71298cd9557SMatthias Ringwald if (tinydir_open(&dir, dir_name) == -1) 71398cd9557SMatthias Ringwald { 71498cd9557SMatthias Ringwald return -1; 71598cd9557SMatthias Ringwald } 71698cd9557SMatthias Ringwald 71798cd9557SMatthias Ringwald /* Read through the parent directory and look for the file */ 71898cd9557SMatthias Ringwald while (dir.has_next) 71998cd9557SMatthias Ringwald { 72098cd9557SMatthias Ringwald if (tinydir_readfile(&dir, file) == -1) 72198cd9557SMatthias Ringwald { 72298cd9557SMatthias Ringwald result = -1; 72398cd9557SMatthias Ringwald goto bail; 72498cd9557SMatthias Ringwald } 72598cd9557SMatthias Ringwald if (_tinydir_strcmp(file->name, base_name) == 0) 72698cd9557SMatthias Ringwald { 72798cd9557SMatthias Ringwald /* File found */ 72898cd9557SMatthias Ringwald found = 1; 72998cd9557SMatthias Ringwald break; 73098cd9557SMatthias Ringwald } 73198cd9557SMatthias Ringwald tinydir_next(&dir); 73298cd9557SMatthias Ringwald } 73398cd9557SMatthias Ringwald if (!found) 73498cd9557SMatthias Ringwald { 73598cd9557SMatthias Ringwald result = -1; 73698cd9557SMatthias Ringwald errno = ENOENT; 73798cd9557SMatthias Ringwald } 73898cd9557SMatthias Ringwald 73998cd9557SMatthias Ringwald bail: 74098cd9557SMatthias Ringwald tinydir_close(&dir); 74198cd9557SMatthias Ringwald return result; 74298cd9557SMatthias Ringwald } 74398cd9557SMatthias Ringwald 74498cd9557SMatthias Ringwald _TINYDIR_FUNC 74598cd9557SMatthias Ringwald void _tinydir_get_ext(tinydir_file *file) 74698cd9557SMatthias Ringwald { 74798cd9557SMatthias Ringwald _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); 74898cd9557SMatthias Ringwald if (period == NULL) 74998cd9557SMatthias Ringwald { 75098cd9557SMatthias Ringwald file->extension = &(file->name[_tinydir_strlen(file->name)]); 75198cd9557SMatthias Ringwald } 75298cd9557SMatthias Ringwald else 75398cd9557SMatthias Ringwald { 75498cd9557SMatthias Ringwald file->extension = period + 1; 75598cd9557SMatthias Ringwald } 75698cd9557SMatthias Ringwald } 75798cd9557SMatthias Ringwald 75898cd9557SMatthias Ringwald _TINYDIR_FUNC 75998cd9557SMatthias Ringwald int _tinydir_file_cmp(const void *a, const void *b) 76098cd9557SMatthias Ringwald { 76198cd9557SMatthias Ringwald const tinydir_file *fa = (const tinydir_file *)a; 76298cd9557SMatthias Ringwald const tinydir_file *fb = (const tinydir_file *)b; 76398cd9557SMatthias Ringwald if (fa->is_dir != fb->is_dir) 76498cd9557SMatthias Ringwald { 76598cd9557SMatthias Ringwald return -(fa->is_dir - fb->is_dir); 76698cd9557SMatthias Ringwald } 76798cd9557SMatthias Ringwald return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); 76898cd9557SMatthias Ringwald } 76998cd9557SMatthias Ringwald 77098cd9557SMatthias Ringwald #ifndef _MSC_VER 77198cd9557SMatthias Ringwald #ifndef _TINYDIR_USE_READDIR 77298cd9557SMatthias Ringwald /* 77398cd9557SMatthias Ringwald The following authored by Ben Hutchings <[email protected]> 77498cd9557SMatthias Ringwald from https://womble.decadent.org.uk/readdir_r-advisory.html 77598cd9557SMatthias Ringwald */ 77698cd9557SMatthias Ringwald /* Calculate the required buffer size (in bytes) for directory * 77798cd9557SMatthias Ringwald * entries read from the given directory handle. Return -1 if this * 77898cd9557SMatthias Ringwald * this cannot be done. * 77998cd9557SMatthias Ringwald * * 78098cd9557SMatthias Ringwald * This code does not trust values of NAME_MAX that are less than * 78198cd9557SMatthias Ringwald * 255, since some systems (including at least HP-UX) incorrectly * 78298cd9557SMatthias Ringwald * define it to be a smaller value. */ 78398cd9557SMatthias Ringwald _TINYDIR_FUNC 78498cd9557SMatthias Ringwald size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) 78598cd9557SMatthias Ringwald { 78698cd9557SMatthias Ringwald long name_max; 78798cd9557SMatthias Ringwald size_t name_end; 78898cd9557SMatthias Ringwald /* parameter may be unused */ 78998cd9557SMatthias Ringwald (void)dirp; 79098cd9557SMatthias Ringwald 79198cd9557SMatthias Ringwald #if defined _TINYDIR_USE_FPATHCONF 79298cd9557SMatthias Ringwald name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); 79398cd9557SMatthias Ringwald if (name_max == -1) 79498cd9557SMatthias Ringwald #if defined(NAME_MAX) 79598cd9557SMatthias Ringwald name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 79698cd9557SMatthias Ringwald #else 79798cd9557SMatthias Ringwald return (size_t)(-1); 79898cd9557SMatthias Ringwald #endif 79998cd9557SMatthias Ringwald #elif defined(NAME_MAX) 80098cd9557SMatthias Ringwald name_max = (NAME_MAX > 255) ? NAME_MAX : 255; 80198cd9557SMatthias Ringwald #else 80298cd9557SMatthias Ringwald #error "buffer size for readdir_r cannot be determined" 80398cd9557SMatthias Ringwald #endif 80498cd9557SMatthias Ringwald name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; 80598cd9557SMatthias Ringwald return (name_end > sizeof(struct _tinydir_dirent) ? 80698cd9557SMatthias Ringwald name_end : sizeof(struct _tinydir_dirent)); 80798cd9557SMatthias Ringwald } 80898cd9557SMatthias Ringwald #endif 80998cd9557SMatthias Ringwald #endif 81098cd9557SMatthias Ringwald 81198cd9557SMatthias Ringwald #ifdef __cplusplus 81298cd9557SMatthias Ringwald } 81398cd9557SMatthias Ringwald #endif 81498cd9557SMatthias Ringwald 81598cd9557SMatthias Ringwald # if defined (_MSC_VER) 81698cd9557SMatthias Ringwald # pragma warning(pop) 81798cd9557SMatthias Ringwald # endif 81898cd9557SMatthias Ringwald 81998cd9557SMatthias Ringwald #endif 820