Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/cxong/tinydir.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCong <congusbongus@gmail.com>2016-03-12 14:11:18 +0300
committerCong <congusbongus@gmail.com>2016-03-12 14:11:18 +0300
commit899627ed8f9331e2605cc51b03f2973f92b3bee2 (patch)
tree2c6a0a60c159bdd60a249b3e4a7bb701d8ae2f4f
parent74564450519c965f9395f132d1425e904be2b41a (diff)
parent9a755a0e45766cc6a6d4d5b3f6d0a4ac867d0f67 (diff)
Merge pull request #26 from Andargor/master
Changed readdir to readdir_r for thread-safety
-rwxr-xr-x[-rw-r--r--]tinydir.h87
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
{