dbus/dbus dbus-sysdeps-util-unix.c,1.3,1.4

John Palmieri johnp at kemper.freedesktop.org
Wed Sep 13 12:13:19 PDT 2006


Update of /cvs/dbus/dbus/dbus
In directory kemper:/tmp/cvs-serv32673/dbus

Modified Files:
	dbus-sysdeps-util-unix.c 
Log Message:
* dbus/dbus-sysdeps-util-unix.c (_dbus_directory_get_next_file):
  use threadsafe readdir_r instead of readdir


Index: dbus-sysdeps-util-unix.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-util-unix.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dbus-sysdeps-util-unix.c	11 Sep 2006 17:41:21 -0000	1.3
+++ dbus-sysdeps-util-unix.c	13 Sep 2006 19:13:17 -0000	1.4
@@ -490,14 +490,47 @@
   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 @@
                                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_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;
+        }
     }
 }
 



More information about the dbus-commit mailing list