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

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.