]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
Port dbus_directory_...() function to use win32 native api instead of opendir()/readd...
authorRalf Habacker <ralf.habacker@freenet.de>
Fri, 5 Sep 2014 12:36:52 +0000 (14:36 +0200)
committerRalf Habacker <ralf.habacker@freenet.de>
Mon, 8 Sep 2014 14:38:16 +0000 (14:38 +0000)
This fixes a license issue introduced by the initial win32 port.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=57272
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
dbus/dbus-sysdeps-util-win.c

index 4678b11ee1a355b65675fa37a32d2c5caceb993e..dd53417f561311ceef5975d0545c11d14eeb550f 100644 (file)
@@ -424,155 +424,15 @@ _dbus_stat(const DBusString *filename,
   return TRUE;
 }
 
-
-/* This file is part of the KDE project
-Copyright (C) 2000 Werner Almesberger
-
-libc/sys/linux/sys/dirent.h - Directory entry as returned by readdir
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
-*/
-#define HAVE_NO_D_NAMLEN       /* no struct dirent->d_namlen */
-#define HAVE_DD_LOCK           /* have locking mechanism */
-
-#define MAXNAMLEN 255          /* sizeof(struct dirent.d_name)-1 */
-
-#define __dirfd(dir) (dir)->dd_fd
-
-/* struct dirent - same as Unix */
-struct dirent
-  {
-    long d_ino;                    /* inode (always 1 in WIN32) */
-    off_t d_off;                /* offset to this dirent */
-    unsigned short d_reclen;    /* length of d_name */
-    char d_name[_MAX_FNAME+1];    /* filename (null terminated) */
-  };
-
-/* typedef DIR - not the same as Unix */
-typedef struct
-  {
-    HANDLE handle;              /* FindFirst/FindNext handle */
-    short offset;               /* offset into directory */
-    short finished;             /* 1 if there are not more files */
-    WIN32_FIND_DATAA fileinfo;  /* from FindFirst/FindNext */
-    char *dir;                  /* the dir we are reading */
-    struct dirent dent;         /* the dirent to return */
-  }
-DIR;
-
-/**********************************************************************
-* Implement dirent-style opendir/readdir/closedir on Window 95/NT
-*
-* Functions defined are opendir(), readdir() and closedir() with the
-* same prototypes as the normal dirent.h implementation.
-*
-* Does not implement telldir(), seekdir(), rewinddir() or scandir().
-* The dirent struct is compatible with Unix, except that d_ino is
-* always 1 and d_off is made up as we go along.
-*
-* Error codes are not available with errno but GetLastError.
-*
-* The DIR typedef is not compatible with Unix.
-**********************************************************************/
-
-static DIR * _dbus_opendir(const char *dir)
-{
-  DIR *dp;
-  char *filespec;
-  HANDLE handle;
-  int index;
-
-  filespec = malloc(strlen(dir) + 2 + 1);
-  strcpy(filespec, dir);
-  index = strlen(filespec) - 1;
-  if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
-    filespec[index] = '\0';
-  strcat(filespec, "\\*");
-
-  dp = (DIR *)malloc(sizeof(DIR));
-  dp->offset = 0;
-  dp->finished = 0;
-  dp->dir = strdup(dir);
-
-  handle = FindFirstFileA(filespec, &(dp->fileinfo));
-  if (handle == INVALID_HANDLE_VALUE)
-    {
-      if (GetLastError() == ERROR_NO_MORE_FILES)
-        dp->finished = 1;
-      else
-        return NULL;
-    }
-
-  dp->handle = handle;
-  free(filespec);
-
-  return dp;
-}
-
-static struct dirent * _dbus_readdir(DIR *dp)
-{
-  int saved_err = GetLastError();
-
-  if (!dp || dp->finished)
-    return NULL;
-
-  if (dp->offset != 0)
-    {
-      if (FindNextFileA(dp->handle, &(dp->fileinfo)) == 0)
-        {
-          if (GetLastError() == ERROR_NO_MORE_FILES)
-            {
-              SetLastError(saved_err);
-              dp->finished = 1;
-            }
-          return NULL;
-        }
-    }
-  dp->offset++;
-  
-  strncpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME);
-  dp->dent.d_ino = 1;
-  dp->dent.d_reclen = strlen(dp->dent.d_name);
-  dp->dent.d_off = dp->offset;
-  
-  return &(dp->dent);
-}
-
-
-static int _dbus_closedir(DIR *dp)
-{
-  if (!dp)
-    return 0;
-  FindClose(dp->handle);
-  if (dp->dir)
-    free(dp->dir);
-  if (dp)
-    free(dp);
-
-  return 0;
-}
-
-
 /**
  * Internals of directory iterator
  */
 struct DBusDirIter
   {
-    DIR *d; /**< The DIR* from opendir() */
-
+    HANDLE handle;
+    WIN32_FIND_DATAA fileinfo;  /* from FindFirst/FindNext */
+    dbus_bool_t finished;       /* true if there are no more entries */
+    int offset;
   };
 
 /**
@@ -586,35 +446,66 @@ DBusDirIter*
 _dbus_directory_open (const DBusString *filename,
                       DBusError        *error)
 {
-  DIR *d;
   DBusDirIter *iter;
-  const char *filename_c;
+  DBusString filespec;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
-  filename_c = _dbus_string_get_const_data (filename);
-
-  d = _dbus_opendir (filename_c);
-  if (d == NULL)
+  if (!_dbus_string_init_from_string (&filespec, filename))
     {
-      char *emsg = _dbus_win_error_string (GetLastError ());
-      dbus_set_error (error, _dbus_win_error_from_last_error (),
-                      "Failed to read directory \"%s\": %s",
-                      filename_c, emsg);
-      _dbus_win_free_error_string (emsg);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Could not allocate memory for directory filename copy");
       return NULL;
     }
+
+  if (_dbus_string_ends_with_c_str (&filespec, "/") || _dbus_string_ends_with_c_str (&filespec, "\\") )
+    {
+      if (!_dbus_string_append (&filespec, "*"))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                          "Could not append filename wildcard");
+          return NULL;
+        }
+    }
+  else if (!_dbus_string_ends_with_c_str (&filespec, "*"))
+    {
+      if (!_dbus_string_append (&filespec, "\\*"))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                          "Could not append filename wildcard 2");
+          return NULL;
+        }
+    }
+
   iter = dbus_new0 (DBusDirIter, 1);
   if (iter == NULL)
     {
-      _dbus_closedir (d);
+      _dbus_string_free (&filespec);
       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                       "Could not allocate memory for directory iterator");
       return NULL;
     }
 
-  iter->d = d;
-
+  iter->finished = FALSE;
+  iter->offset = 0;
+  iter->handle = FindFirstFileA (_dbus_string_get_const_data (&filespec), &(iter->fileinfo));
+  if (iter->handle == INVALID_HANDLE_VALUE)
+    {
+      if (GetLastError () == ERROR_NO_MORE_FILES)
+        iter->finished = TRUE;
+      else
+        {
+          char *emsg = _dbus_win_error_string (GetLastError ());
+          dbus_set_error (error, _dbus_win_error_from_last_error (),
+                          "Failed to read directory \"%s\": %s",
+                          _dbus_string_get_const_data (filename), emsg);
+          _dbus_win_free_error_string (emsg);
+          dbus_free ( iter );
+          _dbus_string_free (&filespec);
+          return NULL;
+        }
+    }
+  _dbus_string_free (&filespec);
   return iter;
 }
 
@@ -623,9 +514,6 @@ _dbus_directory_open (const DBusString *filename,
  * UNIX. If an error occurs, the contents of "filename" are
  * undefined. The error is never set if the function succeeds.
  *
- * @todo 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
@@ -636,40 +524,55 @@ _dbus_directory_get_next_file (DBusDirIter      *iter,
                                DBusString       *filename,
                                DBusError        *error)
 {
-  struct dirent *ent;
+  int saved_err = GetLastError();
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
 again:
   SetLastError (0);
-  ent = _dbus_readdir (iter->d);
-  if (ent == NULL)
+
+  if (!iter || iter->finished)
+      return FALSE;
+
+  if (iter->offset > 0)
     {
-      if (GetLastError() != 0)
+      if (FindNextFileA (iter->handle, &(iter->fileinfo)) == 0)
         {
-          char *emsg = _dbus_win_error_string (GetLastError ());
-          dbus_set_error (error, _dbus_win_error_from_last_error (),
-                          "Failed to get next in directory: %s", emsg);
-          _dbus_win_free_error_string (emsg);
+          if (GetLastError() == ERROR_NO_MORE_FILES)
+            {
+              SetLastError(saved_err);
+              iter->finished = 1;
+            }
+          else
+            {
+              char *emsg = _dbus_win_error_string (GetLastError ());
+              dbus_set_error (error, _dbus_win_error_from_last_error (),
+                             "Failed to get next in directory: %s", emsg);
+              _dbus_win_free_error_string (emsg);
+              return FALSE;
+            }
         }
-      return FALSE;
     }
-  else if (ent->d_name[0] == '.' &&
-           (ent->d_name[1] == '\0' ||
-            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
-    goto again;
-  else
+
+  iter->offset++;
+
+  if (iter->finished)
+      return FALSE;
+
+  if (iter->fileinfo.cFileName[0] == '.' &&
+     (iter->fileinfo.cFileName[1] == '\0' ||
+        (iter->fileinfo.cFileName[1] == '.' && iter->fileinfo.cFileName[2] == '\0')))
+      goto again;
+
+  _dbus_string_set_length (filename, 0);
+  if (!_dbus_string_append (filename, iter->fileinfo.cFileName))
     {
-      _dbus_string_set_length (filename, 0);
-      if (!_dbus_string_append (filename, ent->d_name))
-        {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
-                          "No memory to read directory entry");
-          return FALSE;
-        }
-      else
-        return TRUE;
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "No memory to read directory entry");
+      return FALSE;
     }
+
+  return TRUE;
 }
 
 /**
@@ -678,7 +581,9 @@ again:
 void
 _dbus_directory_close (DBusDirIter *iter)
 {
-  _dbus_closedir (iter->d);
+  if (!iter)
+      return;
+  FindClose(iter->handle);
   dbus_free (iter);
 }