]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
* dbus/dbus-sysdeps-util-unix.c (_dbus_directory_get_next_file):
authorJohn (J5) Palmieri <johnp@redhat.com>
Wed, 13 Sep 2006 19:13:17 +0000 (19:13 +0000)
committerJohn (J5) Palmieri <johnp@redhat.com>
Wed, 13 Sep 2006 19:13:17 +0000 (19:13 +0000)
  use threadsafe readdir_r instead of readdir

ChangeLog
configure.in
dbus/dbus-sysdeps-util-unix.c

index cc89708f658f476bab443f50b0629ff601ff94da..ae2e5c4afb90094f59ece9ebd42b55e37fd418e6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-09-13  John (J5) Palmieri  <johnp@redhat.com>
+
+       * dbus/dbus-sysdeps-util-unix.c (_dbus_directory_get_next_file):
+       use threadsafe readdir_r instead of readdir
+
 2006-09-13  John (J5) Palmieri  <johnp@redhat.com>
 
        * dbus-threads.c (dbus_threads_init_default): New method for
index 48708c82320ed14f82c5f543300d085d16e67222..399225eff6da9d6c079294cdcde0e4209aeb0fef 100644 (file)
@@ -489,7 +489,7 @@ fi
 AC_CHECK_LIB(socket,socket)
 AC_CHECK_LIB(nsl,gethostbyname)
 
-AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv unsetenv socketpair getgrouplist)
+AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv unsetenv socketpair getgrouplist fpathconf dirfd)
 
 AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
 
index 981d4e3ee72eae41896382a3be29784c43203ce9..9fc7645b1106b7e5d5baea3b5dc1c488b7cd0bfd 100644 (file)
@@ -490,14 +490,47 @@ _dbus_directory_open (const DBusString *filename,
   return iter;
 }
 
+/* Calculate the required buffer size (in bytes) for directory
+ * entries read from the given directory handle.  Return -1 if this
+ * this cannot be done. 
+ *
+ * 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 dbus_bool_t
+dirent_buf_size(DIR * dirp, size_t *size)
+{
+ long name_max;
+#   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;
+#           else
+            return FALSE;
+#           endif
+#   else
+#       if defined(NAME_MAX)
+        name_max = NAME_MAX;
+#       else
+#           error "buffer size for readdir_r cannot be determined"
+#       endif
+#   endif
+  if (size)
+    *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
+  else
+    return FALSE;
+
+  return TRUE;
+}
+
 /**
  * Get next file in the directory. Will not return "." or ".."  on
  * UNIX. If an error occurs, the contents of "filename" are
  * undefined. The error is never set if the function succeeds.
  *
- * @todo 1.0 for thread safety, I think we have to use
- * readdir_r(). (GLib has the same issue, should file a bug.)
- *
  * @param iter the iterator
  * @param filename string to be set to the next file in the dir
  * @param error return location for error
@@ -508,19 +541,37 @@ _dbus_directory_get_next_file (DBusDirIter      *iter,
                                DBusString       *filename,
                                DBusError        *error)
 {
-  struct dirent *ent;
+  struct dirent *d, *ent;
+  size_t buf_size;
+  int err;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
+  if (!dirent_buf_size (iter->d, &buf_size))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Can't calculate buffer size when reading directory");
+      return FALSE;
+    }
+
+  d = (struct dirent *)dbus_malloc (buf_size);
+  if (!d)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "No memory to read directory entry");
+      return FALSE;
+    }
+
  again:
-  errno = 0;
-  ent = readdir (iter->d);
-  if (ent == NULL)
+  err = readdir_r (iter->d, d, &ent);
+  if (err || !ent)
     {
-      if (errno != 0)
+      if (err != 0)
         dbus_set_error (error,
-                        _dbus_error_from_errno (errno),
-                        "%s", _dbus_strerror (errno));
+                        _dbus_error_from_errno (err),
+                        "%s", _dbus_strerror (err));
+
+      dbus_free (d);
       return FALSE;
     }
   else if (ent->d_name[0] == '.' &&
@@ -534,10 +585,14 @@ _dbus_directory_get_next_file (DBusDirIter      *iter,
         {
           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                           "No memory to read directory entry");
+          dbus_free (d);
           return FALSE;
         }
       else
-        return TRUE;
+        {
+          dbus_free (d);
+          return TRUE;
+        }
     }
 }