From 290f240ee006fef9d65cf987ad5e0d99e956b936 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 23 Feb 2012 11:16:47 -0800 Subject: [PATCH] Fix readdir usage across platforms This fixes the missing readdir_r from win32 and fixes other platforms to always use the reentrant readdir_r form for reading directory contents. --- src/path.c | 6 +++--- src/unix/posix.h | 1 + src/win32/dir.c | 36 ++++++++++++++++++++++++------------ src/win32/dir.h | 3 +++ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/path.c b/src/path.c index 88ea95a97..ec40f4b06 100644 --- a/src/path.c +++ b/src/path.c @@ -491,7 +491,7 @@ int git_path_direach( { ssize_t wd_len; DIR *dir; - struct dirent *de; + struct dirent de_buf, *de; if (git_path_to_dir(path) < GIT_SUCCESS) return git_buf_lasterror(path); @@ -501,7 +501,7 @@ int git_path_direach( if (!dir) return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path->ptr); - while ((de = readdir(dir)) != NULL) { + while (p_readdir_r(dir, &de_buf, &de) == 0 && de != NULL) { int result; if (is_dot_or_dotdot(de->d_name)) @@ -547,7 +547,7 @@ int git_path_dirload( path_len -= prefix_len; need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0; - while ((error = readdir_r(dir, &de_buf, &de)) == 0 && de != NULL) { + while ((error = p_readdir_r(dir, &de_buf, &de)) == 0 && de != NULL) { char *entry_path; size_t entry_len; diff --git a/src/unix/posix.h b/src/unix/posix.h index 9973acf30..2b0d85bb5 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -21,5 +21,6 @@ #define p_snprintf(b, c, f, ...) snprintf(b, c, f, __VA_ARGS__) #define p_mkstemp(p) mkstemp(p) #define p_setenv(n,v,o) setenv(n,v,o) +#define p_readdir_r(d,e,r) readdir_r(d,e,r) #endif diff --git a/src/win32/dir.c b/src/win32/dir.c index 0a634f06f..23bc55558 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -58,25 +58,37 @@ git__DIR *git__opendir(const char *dir) return new; } -struct git__dirent *git__readdir(git__DIR *d) +int git__readdir_r( + git__DIR *d, struct git__dirent *entry, struct git__dirent **result) { - if (!d || d->h == INVALID_HANDLE_VALUE) - return NULL; + if (!d || !entry || !result || d->h == INVALID_HANDLE_VALUE) + return -1; if (d->first) d->first = 0; - else { - if (!FindNextFileW(d->h, &d->f)) - return NULL; + else if (!FindNextFileW(d->h, &d->f)) { + *result = NULL; + return 0; } - if (wcslen(d->f.cFileName) >= sizeof(d->entry.d_name)) + if (wcslen(d->f.cFileName) >= sizeof(entry->d_name)) + return -1; + + entry->d_ino = 0; + WideCharToMultiByte( + gitwin_get_codepage(), 0, d->f.cFileName, -1, + entry->d_name, GIT_PATH_MAX, NULL, NULL); + + *result = entry; + return 0; +} + +struct git__dirent *git__readdir(git__DIR *d) +{ + struct git__dirent *result; + if (git__readdir_r(d, &d->entry, &result) < 0) return NULL; - - d->entry.d_ino = 0; - WideCharToMultiByte(gitwin_get_codepage(), 0, d->f.cFileName, -1, d->entry.d_name, GIT_PATH_MAX, NULL, NULL); - - return &d->entry; + return result; } void git__rewinddir(git__DIR *d) diff --git a/src/win32/dir.h b/src/win32/dir.h index c16e136dd..fc54e2977 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -24,6 +24,7 @@ typedef struct { extern git__DIR *git__opendir(const char *); extern struct git__dirent *git__readdir(git__DIR *); +extern int git__readdir_r(git__DIR*, struct git__dirent*, struct git__dirent**); extern void git__rewinddir(git__DIR *); extern int git__closedir(git__DIR *); @@ -36,4 +37,6 @@ extern int git__closedir(git__DIR *); # define closedir git__closedir # endif +#define p_readdir_r(d,e,r) git__readdir_r(d,e,r) + #endif /* INCLUDE_dir_h__ */