DOSFS_MatchLong ignored several things about file mask matching for
long file names.

diff --git a/files/dos_fs.c b/files/dos_fs.c
index 70cc9c0..d7a6bcd 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -289,10 +289,24 @@
  *           DOSFS_MatchLong
  *
  * Check a long file name against a mask.
+ *
+ * Tests (done in W95 DOS shell - case insensitive):
+ * *.txt			test1.test.txt				*
+ * *st1*			test1.txt				*
+ * *.t??????.t*			test1.ta.tornado.txt			*
+ * *tornado*			test1.ta.tornado.txt			*
+ * t*t				test1.ta.tornado.txt			*
+ * ?est*			test1.txt				*
+ * ?est???			test1.txt				-
+ * *test1.txt*			test1.txt				* 
+ * h?l?o*t.dat			hellothisisatest.dat			*
  */
 static int DOSFS_MatchLong( const char *mask, const char *name,
                             int case_sensitive )
 {
+    const char *lastjoker = NULL;
+    const char *next_to_retry = NULL;
+
     if (!strcmp( mask, "*.*" )) return 1;
     while (*name && *mask)
     {
@@ -300,23 +314,62 @@
         {
             mask++;
             while (*mask == '*') mask++;  /* Skip consecutive '*' */
-            if (!*mask) return 1;
+            lastjoker = mask;
+            if (!*mask) return 1; /* end of mask is all '*', so match */
+
+            /* skip to the next match after the joker(s) */
             if (case_sensitive) while (*name && (*name != *mask)) name++;
             else while (*name && (toupper(*name) != toupper(*mask))) name++;
+
             if (!*name) break;
+            next_to_retry = name;
         }
         else if (*mask != '?')
         {
+            int mismatch = 0;
             if (case_sensitive)
             {
-                if (*mask != *name) return 0;
+                if (*mask != *name) mismatch = 1;
             }
-            else if (toupper(*mask) != toupper(*name)) return 0;
+            else
+            {
+                if (toupper(*mask) != toupper(*name)) mismatch = 1;
+            }
+            if (!mismatch)
+            {
+                mask++;
+                name++;
+                if (*mask == '\0')
+                {
+                    if (*name == '\0')
+                        return 1;
+                    if (lastjoker)
+                        mask = lastjoker;
+                }
+            }
+            else /* mismatch ! */
+            {
+                if (lastjoker) /* we had an '*', so we can try unlimitedly */
+                {
+                    mask = lastjoker;
+
+                    /* this scan sequence was a mismatch, so restart
+                     * 1 char after the first char we checked last time */
+                    next_to_retry++;
+                    name = next_to_retry;
+                }
+                else
+                    return 0; /* bad luck */
+            }
         }
-        mask++;
-        name++;
+        else /* '?' */
+        {
+            mask++;
+            name++;
+        }
     }
-    if (*mask == '.') mask++;  /* Ignore trailing '.' in mask */
+    while ((*mask == '.') || (*mask == '*'))
+        mask++;  /* Ignore trailing '.' or '*' in mask */
     return (!*name && !*mask);
 }