Reinstate this patch, now I've fixed a double-free bug. Thanks to Rolf for
authorDick Porter <dick@acm.org>
Wed, 25 Apr 2007 13:52:35 +0000 (13:52 -0000)
committerDick Porter <dick@acm.org>
Wed, 25 Apr 2007 13:52:35 +0000 (13:52 -0000)
the test that showed the problem.

2007-04-05  Dick Porter  <dick@ximian.com>

* file-io.c (ves_icall_System_IO_MonoIO_GetFileSystemEntries): use
FindFirstFile()/FindNextFile() to find entries.  This lets the
io-layer versions use MONO_IOMAP compatibility helpers.  Fixes bug
81038.

2007-04-05  Dick Porter  <dick@ximian.com>

* io.c:
* io-portability.c (_wapi_io_scandir): Moved from io.c, and
changed to use a cut-down version of glob(3) that has been
extended to match with case-insensitivity if needed.

svn path=/trunk/mono/; revision=76249

mono/io-layer/ChangeLog
mono/io-layer/Makefile.am
mono/io-layer/io-portability.c
mono/io-layer/io-portability.h
mono/io-layer/io.c
mono/metadata/ChangeLog
mono/metadata/file-io.c
mono/metadata/file-io.h

index dffbff01ca30be0acef6c07b171ff46e973d9882..4fcda966e8efd384202bc198b4126726a080e1dd 100644 (file)
        * wapi_glob.c: remove reference to sys/cdefs.h, use glib instead.
        Fixes: 81326
 
+2007-04-05  Dick Porter  <dick@ximian.com>
+
+       * io.c:
+       * io-portability.c (_wapi_io_scandir): Moved from io.c, and
+       changed to use a cut-down version of glob(3) that has been
+       extended to match with case-insensitivity if needed.
+
+       * wapi_glob.h:
+       * wapi_glob.c: Cut down implementation of glob(3), based on
+       OpenBSD.
+
 2007-03-22  Dick Porter  <dick@ximian.com>
 
        * sockets.c (_wapi_connect): Do additional checks when connect(2)
index a824ba8bea0f0601bfa02c10619ce24922286a55..a65e8b81f51bb6be0a7d65204ccf4e11d34edc3d 100644 (file)
@@ -98,6 +98,8 @@ OTHER_SRC = \
        versioninfo.h           \
        wait.c                  \
        wait.h                  \
+       wapi_glob.h             \
+       wapi_glob.c             \
        wapi.h                  \
        wapi-private.h
 
index 17b5a60013b2ebfdfbaff429c334873e5f6b1cd1..c44a29b09e4f4b5b9e63f93c6b46f229e87c787f 100644 (file)
@@ -23,6 +23,8 @@
 #include <sys/stat.h>
 
 #include <mono/io-layer/mono-mutex.h>
+#include <mono/io-layer/error.h>
+#include <mono/io-layer/wapi_glob.h>
 #include <mono/io-layer/io-portability.h>
 
 #undef DEBUG
@@ -682,3 +684,187 @@ GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error)
        
        return(ret);
 }
+
+
+static gint
+file_compare (gconstpointer a, gconstpointer b)
+{
+       gchar *astr = *(gchar **) a;
+       gchar *bstr = *(gchar **) b;
+
+       return strcmp (astr, bstr);
+}
+
+static gint
+get_errno_from_g_file_error (gint error)
+{
+       switch (error) {
+#ifdef EACCESS
+       case G_FILE_ERROR_ACCES:
+               error = EACCES;
+               break;
+#endif
+#ifdef ENAMETOOLONG
+       case G_FILE_ERROR_NAMETOOLONG:
+               error = ENAMETOOLONG;
+               break;
+#endif
+#ifdef ENOENT
+       case G_FILE_ERROR_NOENT:
+               error = ENOENT;
+               break;
+#endif
+#ifdef ENOTDIR
+       case G_FILE_ERROR_NOTDIR:
+               error = ENOTDIR;
+               break;
+#endif
+#ifdef ENXIO
+       case G_FILE_ERROR_NXIO:
+               error = ENXIO;
+               break;
+#endif
+#ifdef ENODEV
+       case G_FILE_ERROR_NODEV:
+               error = ENODEV;
+               break;
+#endif
+#ifdef EROFS
+       case G_FILE_ERROR_ROFS:
+               error = EROFS;
+               break;
+#endif
+#ifdef ETXTBSY
+       case G_FILE_ERROR_TXTBSY:
+               error = ETXTBSY;
+               break;
+#endif
+#ifdef EFAULT
+       case G_FILE_ERROR_FAULT:
+               error = EFAULT;
+               break;
+#endif
+#ifdef ELOOP
+       case G_FILE_ERROR_LOOP:
+               error = ELOOP;
+               break;
+#endif
+#ifdef ENOSPC
+       case G_FILE_ERROR_NOSPC:
+               error = ENOSPC;
+               break;
+#endif
+#ifdef ENOMEM
+       case G_FILE_ERROR_NOMEM:
+               error = ENOMEM;
+               break;
+#endif
+#ifdef EMFILE
+       case G_FILE_ERROR_MFILE:
+               error = EMFILE;
+               break;
+#endif
+#ifdef ENFILE
+       case G_FILE_ERROR_NFILE:
+               error = ENFILE;
+               break;
+#endif
+#ifdef EBADF
+       case G_FILE_ERROR_BADF:
+               error = EBADF;
+               break;
+#endif
+#ifdef EINVAL
+       case G_FILE_ERROR_INVAL:
+               error = EINVAL;
+               break;
+#endif
+#ifdef EPIPE
+       case G_FILE_ERROR_PIPE:
+               error = EPIPE;
+               break;
+#endif
+#ifdef EAGAIN
+       case G_FILE_ERROR_AGAIN:
+               error = EAGAIN;
+               break;
+#endif
+#ifdef EINTR
+       case G_FILE_ERROR_INTR:
+               error = EINTR;
+               break;
+#endif
+#ifdef EWIO
+       case G_FILE_ERROR_IO:
+               error = EIO;
+               break;
+#endif
+#ifdef EPERM
+       case G_FILE_ERROR_PERM:
+               error = EPERM;
+               break;
+#endif
+       case G_FILE_ERROR_FAILED:
+               error = ERROR_INVALID_PARAMETER;
+               break;
+       }
+
+       return error;
+}
+
+/* scandir using glib */
+gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
+                      gchar ***namelist)
+{
+       GError *error = NULL;
+       GDir *dir;
+       GPtrArray *names;
+       gint result;
+       wapi_glob_t glob_buf;
+       int flags = 0, i;
+       
+       dir = _wapi_g_dir_open (dirname, 0, &error);
+       if (dir == NULL) {
+               /* g_dir_open returns ENOENT on directories on which we don't
+                * have read/x permission */
+               gint errnum = get_errno_from_g_file_error (error->code);
+               g_error_free (error);
+               if (errnum == ENOENT &&
+                   !_wapi_access (dirname, F_OK) &&
+                   _wapi_access (dirname, R_OK|X_OK)) {
+                       errnum = EACCES;
+               }
+
+               errno = errnum;
+               return -1;
+       }
+
+       if (portability_helpers & PORTABILITY_CASE) {
+               flags = WAPI_GLOB_IGNORECASE;
+       }
+       
+       result = _wapi_glob (dir, pattern, flags, &glob_buf);
+       g_dir_close (dir);
+       if (result == WAPI_GLOB_NOMATCH) {
+               return(0);
+       } else if (result != 0) {
+               return(-1);
+       }
+       
+       names = g_ptr_array_new ();
+       for (i = 0; i < glob_buf.gl_pathc; i++) {
+               g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
+       }
+
+       result = names->len;
+       if (result > 0) {
+               g_ptr_array_sort (names, file_compare);
+               g_ptr_array_set_size (names, result + 1);
+
+               *namelist = (gchar **) g_ptr_array_free (names, FALSE);
+       } else {
+               g_ptr_array_free (names, TRUE);
+       }
+
+       return result;
+}
index dfbe7771d8b49b25b0ec6b606ab3cc9220ba19c1..8beb367f2e638097cd9f3c6d1c5817b49f1fadc7 100644 (file)
@@ -33,6 +33,8 @@ extern int _wapi_chdir (const char *path);
 extern gchar *_wapi_basename (const gchar *filename);
 extern gchar *_wapi_dirname (const gchar *filename);
 extern GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error);
+extern gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
+                             gchar ***namelist);
 
 G_END_DECLS
 
index 7af0d0de06ee40e2b06e41421ce7928868e34556..6a4fefbb4d2b14120a8cbafd103151bfe110c9d6 100644 (file)
@@ -2610,181 +2610,6 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        return(TRUE);
 }
 
-static gint
-file_compare (gconstpointer a, gconstpointer b)
-{
-       gchar *astr = *(gchar **) a;
-       gchar *bstr = *(gchar **) b;
-
-       return strcmp (astr, bstr);
-}
-
-static gint
-get_errno_from_g_file_error (gint error)
-{
-       switch (error) {
-#ifdef EACCESS
-       case G_FILE_ERROR_ACCES:
-               error = EACCES;
-               break;
-#endif
-#ifdef ENAMETOOLONG
-       case G_FILE_ERROR_NAMETOOLONG:
-               error = ENAMETOOLONG;
-               break;
-#endif
-#ifdef ENOENT
-       case G_FILE_ERROR_NOENT:
-               error = ENOENT;
-               break;
-#endif
-#ifdef ENOTDIR
-       case G_FILE_ERROR_NOTDIR:
-               error = ENOTDIR;
-               break;
-#endif
-#ifdef ENXIO
-       case G_FILE_ERROR_NXIO:
-               error = ENXIO;
-               break;
-#endif
-#ifdef ENODEV
-       case G_FILE_ERROR_NODEV:
-               error = ENODEV;
-               break;
-#endif
-#ifdef EROFS
-       case G_FILE_ERROR_ROFS:
-               error = EROFS;
-               break;
-#endif
-#ifdef ETXTBSY
-       case G_FILE_ERROR_TXTBSY:
-               error = ETXTBSY;
-               break;
-#endif
-#ifdef EFAULT
-       case G_FILE_ERROR_FAULT:
-               error = EFAULT;
-               break;
-#endif
-#ifdef ELOOP
-       case G_FILE_ERROR_LOOP:
-               error = ELOOP;
-               break;
-#endif
-#ifdef ENOSPC
-       case G_FILE_ERROR_NOSPC:
-               error = ENOSPC;
-               break;
-#endif
-#ifdef ENOMEM
-       case G_FILE_ERROR_NOMEM:
-               error = ENOMEM;
-               break;
-#endif
-#ifdef EMFILE
-       case G_FILE_ERROR_MFILE:
-               error = EMFILE;
-               break;
-#endif
-#ifdef ENFILE
-       case G_FILE_ERROR_NFILE:
-               error = ENFILE;
-               break;
-#endif
-#ifdef EBADF
-       case G_FILE_ERROR_BADF:
-               error = EBADF;
-               break;
-#endif
-#ifdef EINVAL
-       case G_FILE_ERROR_INVAL:
-               error = EINVAL;
-               break;
-#endif
-#ifdef EPIPE
-       case G_FILE_ERROR_PIPE:
-               error = EPIPE;
-               break;
-#endif
-#ifdef EAGAIN
-       case G_FILE_ERROR_AGAIN:
-               error = EAGAIN;
-               break;
-#endif
-#ifdef EINTR
-       case G_FILE_ERROR_INTR:
-               error = EINTR;
-               break;
-#endif
-#ifdef EWIO
-       case G_FILE_ERROR_IO:
-               error = EIO;
-               break;
-#endif
-#ifdef EPERM
-       case G_FILE_ERROR_PERM:
-               error = EPERM;
-               break;
-#endif
-       case G_FILE_ERROR_FAILED:
-               error = ERROR_INVALID_PARAMETER;
-               break;
-       }
-
-       return error;
-}
-
-/* scandir using glib */
-static gint
-mono_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
-{
-       GError *error = NULL;
-       GDir *dir;
-       GPtrArray *names;
-       const gchar *name;
-       gint result;
-       GPatternSpec *patspec;
-
-       dir = _wapi_g_dir_open (dirname, 0, &error);
-       if (dir == NULL) {
-               /* g_dir_open returns ENOENT on directories on which we don't
-                * have read/x permission */
-               gint errnum = get_errno_from_g_file_error (error->code);
-               g_error_free (error);
-               if (errnum == ENOENT &&
-                   !_wapi_access (dirname, F_OK) &&
-                   _wapi_access (dirname, R_OK|X_OK)) {
-                       errnum = EACCES;
-               }
-
-               errno = errnum;
-               return -1;
-       }
-
-       patspec = g_pattern_spec_new (pattern);
-       names = g_ptr_array_new ();
-       while ((name = g_dir_read_name (dir)) != NULL) {
-               if (g_pattern_match_string (patspec, name))
-                       g_ptr_array_add (names, g_strdup (name));
-       }
-       
-       g_pattern_spec_free (patspec);
-       g_dir_close (dir);
-       result = names->len;
-       if (result > 0) {
-               g_ptr_array_sort (names, file_compare);
-               g_ptr_array_set_size (names, result + 1);
-
-               *namelist = (gchar **) g_ptr_array_free (names, FALSE);
-       } else {
-               g_ptr_array_free (names, TRUE);
-       }
-
-       return result;
-}
-
 gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 {
        struct _WapiHandle_find find_handle = {0};
@@ -2854,7 +2679,8 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
         */
 
        find_handle.namelist = NULL;
-       result = mono_io_scandir (dir_part, entry_part, &find_handle.namelist);
+       result = _wapi_io_scandir (dir_part, entry_part,
+                                  &find_handle.namelist);
        
        if (result == 0) {
                /* No files, which windows seems to call
@@ -2965,6 +2791,8 @@ retry:
                 * encoding of the name wasn't convertible), so just
                 * ignore it.
                 */
+               g_warning ("%s: Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n", __func__, filename);
+               
                g_free (filename);
                goto retry;
        }
index 8813770423bf2e7377fe23836e99a36dc4d8a5bf..c2a97a648616f73a628924e6b34a2f91445f1326 100644 (file)
@@ -77,6 +77,17 @@ Wed Apr 18 18:28:41 BST 2007 Paolo Molaro <lupus@ximian.com>
        * threads.c (start_wrapper): Call push_appdomain_ref () earlier to fix races where
        the thread is aborted early.
 
+2007-04-05  Dick Porter  <dick@ximian.com>
+
+       * file-io.c (ves_icall_System_IO_MonoIO_GetFileSystemEntries): use
+       FindFirstFile()/FindNextFile() to find entries.  This lets the
+       io-layer versions use MONO_IOMAP compatibility helpers.  Fixes bug
+       81038.
+
+       * appdomain.c (MONO_CORLIB_VERSION): Increment, as the usage of
+       the parameters of
+       ves_icall_System_IO_MonoIO_GetFileSystemEntries() has changed.
+
 2007-04-04  Martin Baulig  <martin@ximian.com>
 
        * debug-helpers.c
index 6538e72a69bdceeaaf653855d064729562b7143c..c6410f2f42c169d0036b8ceafef3c1db64f7803d 100644 (file)
@@ -239,272 +239,83 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
        return(ret);
 }
 
-static gint
-get_error_from_g_file_error (gint error)
-{
-       switch (error) {
-       case G_FILE_ERROR_ACCES:
-               error = ERROR_ACCESS_DENIED;
-               break;
-       case G_FILE_ERROR_NAMETOOLONG:
-               error = ERROR_FILENAME_EXCED_RANGE;
-               break;
-       case G_FILE_ERROR_NOENT:
-               error = ERROR_FILE_NOT_FOUND;
-               break;
-       case G_FILE_ERROR_NOTDIR:
-               error = ERROR_FILE_NOT_FOUND;
-               break;
-       case G_FILE_ERROR_ROFS:
-               error = ERROR_ACCESS_DENIED;
-               break;
-       case G_FILE_ERROR_TXTBSY:
-               error = ERROR_SHARING_VIOLATION;
-               break;
-       case G_FILE_ERROR_NOSPC:
-               error = ERROR_HANDLE_DISK_FULL;
-               break;
-       case G_FILE_ERROR_NFILE:
-       case G_FILE_ERROR_MFILE:
-               error = ERROR_TOO_MANY_OPEN_FILES;
-               break;
-       case G_FILE_ERROR_BADF:
-               error = ERROR_INVALID_HANDLE;
-               break;
-       case G_FILE_ERROR_INVAL:
-               error = ERROR_INVALID_PARAMETER;
-               break;
-       case G_FILE_ERROR_AGAIN:
-               error = ERROR_SHARING_VIOLATION;
-               break;
-       case G_FILE_ERROR_INTR:
-               error = ERROR_IO_PENDING;
-               break;
-       case G_FILE_ERROR_PERM:
-               error = ERROR_ACCESS_DENIED;
-               break;
-       case G_FILE_ERROR_FAILED:
-               error = ERROR_INVALID_PARAMETER;
-               break;
-       case G_FILE_ERROR_NXIO:
-       case G_FILE_ERROR_NOMEM:
-       case G_FILE_ERROR_NODEV:
-       case G_FILE_ERROR_FAULT:
-       case G_FILE_ERROR_LOOP:
-       case G_FILE_ERROR_PIPE:
-       case G_FILE_ERROR_IO:
-       default:
-               error = ERROR_GEN_FAILURE;
-               break;
-
-       }
-
-       return error;
-}
-
-static gint
-file_compare (gconstpointer a, gconstpointer b)
-{
-       gchar *astr = *(gchar **) a;
-       gchar *bstr = *(gchar **) b;
-
-       return strcmp (astr, bstr);
-}
-
-static gint
-get_file_attributes (const char *filename)
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+                                                MonoString *path_with_pattern,
+                                                gint attrs, gint mask,
+                                                gint32 *error)
 {
-#ifdef PLATFORM_WIN32
-       gunichar2 *full16;
-       gint result;
-
-       full16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-       if (full16 == NULL) {
-               g_message ("Bad encoding for '%s'\n", filename);
-               return FALSE;
-       }
-
-       result = GetFileAttributes (full16);
-       g_free (full16);
-       return result;
-#else
-       struct stat buf;
-       struct stat linkbuf;
-       int result;
-       int file_attrs;
-       gboolean issymlink = FALSE;
-       
-       result = lstat (filename, &buf);
-       if (result == -1)
-               return FALSE;
-
-       if (S_ISLNK (buf.st_mode)) {
-               issymlink = TRUE;
-               result = stat (filename, &linkbuf);
-               if (result != -1) {
-                       buf = linkbuf;
-               }
-       }
-
-       /* Sockets (0140000) != Directory (040000) + Regular file (0100000) */
-       if (S_ISSOCK (buf.st_mode))
-               buf.st_mode &= ~S_IFSOCK; /* don't consider socket protection */
-
-       file_attrs = 0;
-       if (S_ISDIR (buf.st_mode))
-               file_attrs |= FILE_ATTRIBUTE_DIRECTORY;
-       else
-               file_attrs |= FILE_ATTRIBUTE_ARCHIVE;
-
-       if ((buf.st_mode & S_IWUSR) == 0)
-               file_attrs |= FILE_ATTRIBUTE_READONLY;
-
-       if (*filename == '.')
-               file_attrs |= FILE_ATTRIBUTE_HIDDEN;
-
-       if (issymlink) {
-               file_attrs |= FILE_ATTRIBUTE_REPARSE_POINT;
-       }
+       MonoDomain *domain;
+       MonoArray *result;
+       int i;
+       WIN32_FIND_DATA data;
+       HANDLE find_handle;
+       GPtrArray *names;
+       gchar *utf8_path, *utf8_result, *full_name;
        
-       return file_attrs;
-#endif
-}
-
-static gboolean
-test_file (const char *filename, int attrs, int mask)
-{
-       int file_attr;
-
-       file_attr = get_file_attributes (filename);
-       if (file_attr == FALSE)
-               return FALSE;
-
-       return ((file_attr & mask) == attrs);
-}
+       MONO_ARCH_SAVE_REGS;
 
-/* scandir using glib */
-static gint
-mono_io_scandir (const gchar *dirname, const gchar *pattern, int attrs,
-               int mask, gchar ***namelist)
-{
-       GError *error = NULL;
-       GDir *dir;
-       GPtrArray *names;
-       const gchar *name;
-       gint result;
-       GPatternSpec *patspec;
-       gchar *full_name;
+       *error = ERROR_SUCCESS;
 
+       domain = mono_domain_get ();
        mask = convert_attrs (mask);
-       *namelist = NULL;
-       dir = g_dir_open (dirname, 0, &error);
-       if (dir == NULL) {
-               /* g_dir_open returns ENOENT on directories on which we don't
-                * have read/x permission */
-               gint errnum = get_error_from_g_file_error (error->code);
-               g_error_free (error);
-               if (errnum == ERROR_FILE_NOT_FOUND && g_file_test (dirname, G_FILE_TEST_IS_DIR))
-                       errnum = ERROR_ACCESS_DENIED;
-
-               SetLastError (errnum);
-               return -1;
+       
+       find_handle = FindFirstFile (mono_string_chars (path_with_pattern),
+                                    &data);
+       if (find_handle == INVALID_HANDLE_VALUE) {
+               gint32 find_error = GetLastError ();
+               
+               if (find_error == ERROR_FILE_NOT_FOUND) {
+                       /* No files, so just return an empty array */
+                       result = mono_array_new (domain,
+                                                mono_defaults.string_class,
+                                                0);
+
+                       return(result);
+               }
+               
+               *error = find_error;
+               return(NULL);
        }
 
-       patspec = g_pattern_spec_new (pattern);
        names = g_ptr_array_new ();
-       while ((name = g_dir_read_name (dir)) != NULL) {
-               if (!g_pattern_match_string (patspec, name))
-                       continue;
+       utf8_path = mono_string_to_utf8 (path);
 
-               full_name = g_build_filename (dirname, name, NULL);
-               if (FALSE == test_file (full_name, attrs, mask)) {
-                       g_free (full_name);
+       do {
+               if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
+                   (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
                        continue;
                }
+               
+               if ((data.dwFileAttributes & mask) == attrs) {
+                       utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
+                       if (utf8_result == NULL) {
+                               continue;
+                       }
+                       
+                       full_name = g_build_filename (utf8_path, utf8_result, NULL);
+                       g_ptr_array_add (names, full_name);
+
+                       g_free (utf8_result);
+               }
+       } while(FindNextFile (find_handle, &data));
 
-               g_ptr_array_add (names, full_name);
-       }
-       
-       g_pattern_spec_free (patspec);
-       g_dir_close (dir);
-       result = names->len;
-       if (result > 0) {
-               g_ptr_array_sort (names, file_compare);
-               g_ptr_array_set_size (names, result + 1);
-
-               *namelist = (gchar **) g_ptr_array_free (names, FALSE);
-       } else {
-               g_ptr_array_free (names, TRUE);
-       }
-
-       return result;
-}
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *_path, MonoString *_pattern,
-                                       gint attrs, gint mask, gint32 *error)
-{
-       MonoDomain *domain;
-       MonoArray *result;
-       gchar **namelist;
-       gchar *path;
-       gchar *pattern;
-       int i, nnames;
-       int removed;
-       MonoString *str_name;
-#ifndef PLATFORM_WIN32
-       gunichar2 *utf16;
-       gsize nbytes;
-#endif
-
-       MONO_ARCH_SAVE_REGS;
-
-       *error = ERROR_SUCCESS;
-
-       path = mono_string_to_utf8 (_path);
-       pattern = mono_string_to_utf8 (_pattern);
-       nnames = mono_io_scandir (path, pattern, attrs, mask, &namelist);
-       if (nnames < 0) {
+       if (FindClose (find_handle) == FALSE) {
                *error = GetLastError ();
-               g_free (pattern);
-               g_free (path);
-               return NULL;
-       }
-
-       domain = mono_domain_get ();
-       result = mono_array_new (domain, mono_defaults.string_class, nnames);
-       removed = 0;
-       for (i = 0; i < nnames; i++) {
-#if PLATFORM_WIN32
-               str_name = mono_string_new (domain, namelist [i]);
-#else
-               utf16 = mono_unicode_from_external (namelist [i], &nbytes);
-               if (utf16 == NULL) {
-                       g_message ("Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n",
-                               namelist [i]);
-                       removed++;
-                       continue;
-               }
-               str_name = mono_string_from_utf16 (utf16);
-               g_free (utf16);
-#endif
-               mono_array_setref (result, i - removed, str_name);
+               g_ptr_array_free (names, TRUE);
+               g_free (utf8_path);
+               return(NULL);
        }
 
-       if (removed > 0) {
-               MonoArray *shrinked;
-               shrinked = mono_array_new (domain, mono_defaults.string_class, nnames - removed);
-               for (i = 0; i < (nnames - removed); i++) {
-                       MonoString *str;
-                       str = mono_array_get (result, MonoString *, i);
-                       mono_array_setref (shrinked, i, str);
-               }
-               result = shrinked;
+       result = mono_array_new (domain, mono_defaults.string_class,
+                                names->len);
+       for (i = 0; i < names->len; i++) {
+               mono_array_setref (result, i, mono_string_new (domain, g_ptr_array_index (names, i)));
        }
 
-       g_strfreev (namelist);
-       g_free (pattern);
-       g_free (path);
+       g_ptr_array_free (names, TRUE);
+       g_free (utf8_path);
+       
        return result;
 }
 
index 43d829b3769837de83577b82b34f5d8be4f0d119..d5e9c6f13597c0a50aa6fc866187c3eb86fbf8da 100644 (file)
@@ -119,8 +119,10 @@ extern MonoBoolean
 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error) MONO_INTERNAL;
 
 MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *_path, MonoString *_pattern,
-                                       gint mask, gint attrs, gint32 *error) MONO_INTERNAL;
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+                                                MonoString *path_with_pattern,
+                                                gint mask, gint attrs,
+                                                gint32 *error) MONO_INTERNAL;
 
 extern MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error) MONO_INTERNAL;