using readdir_r instead of readdir

Wed, 28 Oct 2015 17:59:34 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 28 Oct 2015 17:59:34 +0100
changeset 105
63d9051fe35c
parent 104
a8acbb12f27c
child 106
b122f34ddc80

using readdir_r instead of readdir

src/server/daemon/vfs.c file | annotate | diff | comparison | revisions
src/server/daemon/vfs.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/vfs.c	Fri Oct 23 17:28:09 2015 +0200
+++ b/src/server/daemon/vfs.c	Wed Oct 28 17:59:34 2015 +0100
@@ -26,6 +26,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define _POSIX_PTHREAD_SEMANTIS
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -325,6 +327,22 @@
         return NULL;
     }
     
+    SysVFSDir *dir_data = pool ?
+            pool_malloc(pool, sizeof(SysVFSDir)) : malloc(sizeof(SysVFSDir));
+    if(!dir_data) {
+        closedir(sys_dir);
+        return NULL;
+    }
+    long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX);
+    size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1;
+    dir_data->cur = pool ?
+            pool_malloc(pool, entry_len) : malloc(entry_len);
+    if(!dir_data->cur) {
+        closedir(sys_dir);
+        return NULL;
+    }
+    dir_data->dir = sys_dir;
+    
     VFSDir *dir = pool ?
             pool_malloc(pool, sizeof(VFSDir)) : malloc(sizeof(VFSDir));
     if(!dir) {
@@ -332,7 +350,7 @@
         return NULL;
     }
     dir->ctx = ctx;
-    dir->data = sys_dir;
+    dir->data = dir_data;
     dir->fd = dir_fd;
     dir->io = &sys_dir_io;
     return dir;
@@ -473,9 +491,11 @@
 }
 
 int sys_dir_read(VFS_DIR dir, VFS_ENTRY *entry, int getstat) {
-    struct dirent *e = readdir(dir->data);
-    if(e) {
-        char *name = e->d_name;
+    SysVFSDir *dirdata = dir->data;
+    struct dirent *result = NULL;
+    int s = readdir_r(dirdata->dir, dirdata->cur, &result);
+    if(!s && result) {
+        char *name = result->d_name;
         if(!strcmp(name, ".") || !strcmp(name, "..")) {
             return sys_dir_read(dir, entry, getstat);
         } else {
@@ -487,7 +507,7 @@
              */
             if(getstat) {
                 // TODO: check ACLs again for new path
-                if(fstatat(dir->fd, e->d_name, &entry->stat, 0)) {
+                if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) {
                     entry->stat_errno = errno;
                 }
                 entry->stat_extra = NULL;
@@ -501,7 +521,19 @@
 }
 
 void sys_dir_close(VFS_DIR dir) {
-    closedir(dir->data);
+    SysVFSDir *dirdata = dir->data;
+    closedir(dirdata->dir);
+    
+    pool_handle_t *pool = dir->ctx->pool;
+    if(pool) {
+        pool_free(pool, dirdata->cur);
+        pool_free(pool, dirdata);
+        pool_free(pool, dir);
+    } else {
+        free(dirdata->cur);
+        free(dirdata);
+        free(dir);
+    }
 }
 
 int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl) {
--- a/src/server/daemon/vfs.h	Fri Oct 23 17:28:09 2015 +0200
+++ b/src/server/daemon/vfs.h	Wed Oct 28 17:59:34 2015 +0100
@@ -35,6 +35,11 @@
 #ifdef	__cplusplus
 extern "C" {
 #endif
+
+typedef struct SysVFSDir {
+    DIR           *dir;
+    struct dirent *cur;
+} SysVFSDir;
     
 int vfs_init();
 

mercurial