diff options
| author | John (J5) Palmieri <johnp@redhat.com> | 2006-09-13 19:13:17 +0000 | 
|---|---|---|
| committer | John (J5) Palmieri <johnp@redhat.com> | 2006-09-13 19:13:17 +0000 | 
| commit | f82bdd3ab39cc5741189a4ab16dc3533a79c6617 (patch) | |
| tree | 86cb3648bc8adb776e00284f58957f5a9c6aa4a5 | |
| parent | 642335f681c26b78a1a0e2f2167d2f0e7beb6807 (diff) | |
* dbus/dbus-sysdeps-util-unix.c (_dbus_directory_get_next_file):
  use threadsafe readdir_r instead of readdir
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | configure.in | 2 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps-util-unix.c | 79 | 
3 files changed, 73 insertions, 13 deletions
@@ -1,5 +1,10 @@  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  	initializing the internal thread implementation (Patch from  	Alexander Larsson <alexl at redhat dot com>) diff --git a/configure.in b/configure.in index 48708c82..399225ef 100644 --- a/configure.in +++ b/configure.in @@ -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)]) diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 981d4e3e..9fc7645b 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -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; +        }      }  }  | 
