diff options
author | Cong <congusbongus@gmail.com> | 2016-03-12 14:11:18 +0300 |
---|---|---|
committer | Cong <congusbongus@gmail.com> | 2016-03-12 14:11:18 +0300 |
commit | 899627ed8f9331e2605cc51b03f2973f92b3bee2 (patch) | |
tree | 2c6a0a60c159bdd60a249b3e4a7bb701d8ae2f4f | |
parent | 74564450519c965f9395f132d1425e904be2b41a (diff) | |
parent | 9a755a0e45766cc6a6d4d5b3f6d0a4ac867d0f67 (diff) |
Merge pull request #26 from Andargor/master
Changed readdir to readdir_r for thread-safety
-rwxr-xr-x[-rw-r--r--] | tinydir.h | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/tinydir.h b/tinydir.h index 01fdb39..e04fa41 100644..100755 --- a/tinydir.h +++ b/tinydir.h @@ -40,6 +40,7 @@ extern "C" { # include <dirent.h> # include <libgen.h> # include <sys/stat.h> +# include <stddef.h> #endif @@ -72,6 +73,61 @@ extern "C" { #define _TINYDIR_FREE(_ptr) free(_ptr) #endif //!defined(_TINYDIR_MALLOC) +/* avoid warnings due to unused variables or parameters */ +#ifndef _MSC_VER + #if !defined(_TINYDIR_UNUSED) + #ifdef __GNUC__ + #define _TINYDIR_UNUSED(x) _TINYDIR_UNUSED_ ## x __attribute__((__unused__)) + #else + #define _TINYDIR_UNUSED(x) _TINYDIR_UNUSED_ ## x + #endif + #endif +#endif + +#ifndef _MSC_VER + /* + The following authored by Ben Hutchings <ben@decadent.org.uk> + from https://womble.decadent.org.uk/readdir_r-advisory.html +*/ +/* Calculate the required buffer size (in bytes) for directory * + * entries read from the given directory handle. Return -1 if this * + * this cannot be done. * + * * + * This code does not trust values of NAME_MAX that are less than * + * 255, since some systems (including at least HP-UX) incorrectly * + * define it to be a smaller value. * + * * + * If you use autoconf, include fpathconf and dirfd in your * + * AC_CHECK_FUNCS list. Otherwise use some other method to detect * + * and use them where available. */ + +static size_t dirent_buf_size(DIR * _TINYDIR_UNUSED(dirp)) +{ + long name_max; + size_t name_end; + +# if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) \ + && defined(_PC_NAME_MAX) + name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); + if (name_max == -1) +# if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +# else + return (size_t)(-1); +# endif +# else +# if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +# else +# error "buffer size for readdir_r cannot be determined" +# endif +# endif + name_end = (size_t)offsetof(struct dirent, d_name) + name_max + 1; + return (name_end > sizeof(struct dirent) + ? name_end : sizeof(struct dirent)); +} +#endif + typedef struct { char path[_TINYDIR_PATH_MAX]; @@ -98,6 +154,7 @@ typedef struct #else DIR *_d; struct dirent *_e; + struct dirent *_ep; #endif } tinydir_dir; @@ -131,6 +188,11 @@ int _tinydir_file_cmp(const void *a, const void *b); _TINYDIR_FUNC int tinydir_open(tinydir_dir *dir, const char *path) { +#ifndef _MSC_VER + int error; + int size; /* using int size */ +#endif + if (dir == NULL || path == NULL || strlen(path) == 0) { errno = EINVAL; @@ -148,6 +210,7 @@ int tinydir_open(tinydir_dir *dir, const char *path) dir->_h = INVALID_HANDLE_VALUE; #else dir->_d = NULL; + dir->_ep = NULL; #endif tinydir_close(dir); @@ -169,7 +232,15 @@ int tinydir_open(tinydir_dir *dir, const char *path) /* read first file */ dir->has_next = 1; #ifndef _MSC_VER - dir->_e = readdir(dir->_d); + /* allocate dirent buffer for readdir_r */ + size = dirent_buf_size(dir->_d); /* conversion to int */ + if (size == -1) return -1; + dir->_ep = (struct dirent*)_TINYDIR_MALLOC(size); + if (dir->_ep == NULL) return -1; + + error = readdir_r(dir->_d, dir->_ep, &dir->_e); + if (error != 0) return -1; + if (dir->_e == NULL) { dir->has_next = 0; @@ -276,12 +347,21 @@ void tinydir_close(tinydir_dir *dir) } dir->_d = NULL; dir->_e = NULL; + if (dir->_ep != NULL) + { + _TINYDIR_FREE(dir->_ep); + } + dir->_ep = NULL; #endif } _TINYDIR_FUNC int tinydir_next(tinydir_dir *dir) { +#ifndef _MSC_VER + int error; +#endif + if (dir == NULL) { errno = EINVAL; @@ -296,7 +376,10 @@ int tinydir_next(tinydir_dir *dir) #ifdef _MSC_VER if (FindNextFileA(dir->_h, &dir->_f) == 0) #else - dir->_e = readdir(dir->_d); + if (dir->_ep == NULL) return -1; + error = readdir_r(dir->_d, dir->_ep, &dir->_e); + if (error != 0) return -1; + if (dir->_e == NULL) #endif { |