2007-08-01 Dick Porter <dick@ximian.com>
authorDick Porter <dick@acm.org>
Wed, 1 Aug 2007 13:59:54 +0000 (13:59 -0000)
committerDick Porter <dick@acm.org>
Wed, 1 Aug 2007 13:59:54 +0000 (13:59 -0000)
* io-portability.c (_wapi_io_scandir): Special-case patterns
ending in '.*' so that files with no extension are also matched.
Fixes bug 82212.

* wapi_glob.h:
* wapi_glob.c: Reinstate WAPI_GLOB_APPEND, and add
WAPI_GLOB_UNIQUE to avoid matching the same entry twice when
appending.

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

mono/io-layer/ChangeLog
mono/io-layer/io-portability.c
mono/io-layer/wapi_glob.c
mono/io-layer/wapi_glob.h

index 2447d75e345b6733637c415a28a98aeff9dbb136..05ef519b1eb79013f35ddf04583efb7ed199ad79 100644 (file)
@@ -1,3 +1,14 @@
+2007-08-01  Dick Porter  <dick@ximian.com>
+
+       * io-portability.c (_wapi_io_scandir): Special-case patterns
+       ending in '.*' so that files with no extension are also matched.
+       Fixes bug 82212.
+
+       * wapi_glob.h: 
+       * wapi_glob.c: Reinstate WAPI_GLOB_APPEND, and add
+       WAPI_GLOB_UNIQUE to avoid matching the same entry twice when
+       appending.
+
 2007-07-26  Dick Porter  <dick@ximian.com>
 
        * handles-private.h: 
index 1ec9912ca0925824bd2bfa3b6dddc8fd06b95b56..0cb30805a42d347392d46d55185d3d496dcc0cfa 100644 (file)
@@ -844,8 +844,23 @@ gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
        }
        
        result = _wapi_glob (dir, pattern, flags, &glob_buf);
+       if (g_str_has_suffix (pattern, ".*")) {
+               /* Special-case the patterns ending in '.*', as
+                * windows also matches entries with no extension with
+                * this pattern.
+                * 
+                * TODO: should this be a MONO_IOMAP option?
+                */
+               gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
+               
+               g_dir_rewind (dir);
+               result = _wapi_glob (dir, pattern2, flags | WAPI_GLOB_APPEND | WAPI_GLOB_UNIQUE, &glob_buf);
+
+               g_free (pattern2);
+       }
+       
        g_dir_close (dir);
-       if (result == WAPI_GLOB_NOMATCH) {
+       if (glob_buf.gl_pathc == 0) {
                return(0);
        } else if (result != 0) {
                return(-1);
@@ -856,6 +871,8 @@ gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
                g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
        }
 
+       _wapi_globfree (&glob_buf);
+
        result = names->len;
        if (result > 0) {
                g_ptr_array_sort (names, file_compare);
index b407d4d73aecdfeb57c6a42364c215398066d0c4..c48a66e1a1f76dd7fb4f2e4c4e60e3c6711b8406 100644 (file)
@@ -89,9 +89,12 @@ typedef char Char;
 
 
 static int      g_Ctoc(const gchar *, char *, u_int);
-static int      glob0(GDir *dir, const gchar *, wapi_glob_t *, gboolean);
-static int      glob1(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *, gboolean);
-static int      glob3(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *, gboolean);
+static int      glob0(GDir *dir, const gchar *, wapi_glob_t *, gboolean,
+                      gboolean);
+static int      glob1(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
+                      gboolean, gboolean);
+static int      glob3(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
+                      gboolean, gboolean);
 static int      globextend(const gchar *, wapi_glob_t *, size_t *);
 static int      match(const gchar *, gchar *, gchar *, gboolean);
 #ifdef DEBUG
@@ -106,9 +109,11 @@ _wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob)
        gchar *bufnext, *bufend, patbuf[MAXPATHLEN];
 
        patnext = (u_char *) pattern;
-       pglob->gl_pathc = 0;
-       pglob->gl_pathv = NULL;
-       pglob->gl_offs = 0;
+       if (!(flags & WAPI_GLOB_APPEND)) {
+               pglob->gl_pathc = 0;
+               pglob->gl_pathv = NULL;
+               pglob->gl_offs = 0;
+       }
        pglob->gl_flags = flags & ~WAPI_GLOB_MAGCHAR;
 
        bufnext = patbuf;
@@ -127,7 +132,8 @@ _wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob)
 
        *bufnext = EOS;
 
-       return glob0(dir, patbuf, pglob, flags & WAPI_GLOB_IGNORECASE);
+       return glob0(dir, patbuf, pglob, flags & WAPI_GLOB_IGNORECASE,
+                    flags & WAPI_GLOB_UNIQUE);
 }
 
 /*
@@ -138,7 +144,8 @@ _wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob)
  * to find no matches.
  */
 static int
-glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase)
+glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase,
+       gboolean unique)
 {
        const gchar *qpatnext;
        int c, err, oldpathc;
@@ -175,7 +182,7 @@ glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase)
 #endif
 
        if ((err = glob1(dir, patbuf, patbuf+MAXPATHLEN-1, pglob, &limit,
-                        ignorecase)) != 0)
+                        ignorecase, unique)) != 0)
                return(err);
 
        if (pglob->gl_pathc == oldpathc) {
@@ -187,17 +194,37 @@ glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase)
 
 static int
 glob1(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
-      size_t *limitp, gboolean ignorecase)
+      size_t *limitp, gboolean ignorecase, gboolean unique)
 {
        /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
        if (*pattern == EOS)
                return(0);
-       return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase));
+       return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase,
+                    unique));
+}
+
+static gboolean contains (wapi_glob_t *pglob, const gchar *name)
+{
+       int i;
+       char **pp;
+       
+       if (pglob->gl_pathv != NULL) {
+               pp = pglob->gl_pathv + pglob->gl_offs;
+               for (i = pglob->gl_pathc; i--; ++pp) {
+                       if (*pp) {
+                               if (!strcmp (*pp, name)) {
+                                       return(TRUE);
+                               }
+                       }
+               }
+       }
+       
+       return(FALSE);
 }
 
 static int
 glob3(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
-      size_t *limitp, gboolean ignorecase)
+      size_t *limitp, gboolean ignorecase, gboolean unique)
 {
        const gchar *name;
 
@@ -207,7 +234,10 @@ glob3(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
                           ignorecase)) {
                        continue;
                }
-               globextend (name, pglob, limitp);
+               if (!unique ||
+                   !contains (pglob, name)) {
+                       globextend (name, pglob, limitp);
+               }
        }
 
        return(0);
index aa78ab26adefa21e4684967bc9f034e6868e074b..fc9d7ba8870bbac909e2498a5377e3b3b945e0ce 100644 (file)
@@ -48,7 +48,8 @@ typedef struct {
        char **gl_pathv;        /* List of paths matching pattern. */
 } wapi_glob_t;
 
-
+#define WAPI_GLOB_APPEND       0x0001  /* Append to output from previous call. */
+#define WAPI_GLOB_UNIQUE       0x0040  /* When appending only add items that aren't already in the list */
 #define        WAPI_GLOB_NOSPACE       (-1)    /* Malloc call failed. */
 #define        WAPI_GLOB_ABORTED       (-2)    /* Unignored error. */
 #define        WAPI_GLOB_NOMATCH       (-3)    /* No match and WAPI_GLOB_NOCHECK not set. */