[PATCH 9/9] Fix dir filename /s and resolve many output differences

Jason Edmeades us at edmeades.me.uk
Thu Apr 5 20:43:49 CDT 2007


Note: dir a.* /s finds a.a in all subdirectories not just in those matching
a*, hence need to recurse through all directories. While fixing this,
this patch resolves many formatting differences in terms of output and
newlines between native cmd.
---
 programs/cmd/directory.c |  372 ++++++++++++++++++++++++++--------------------
 1 files changed, 211 insertions(+), 161 deletions(-)

diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
index 08c5a3f..eccff20 100644
--- a/programs/cmd/directory.c
+++ b/programs/cmd/directory.c
@@ -57,6 +57,12 @@ typedef enum _DISPLAYORDER
     Date
 } DISPLAYORDER;
 
+struct directory_stack
+{
+  struct directory_stack *next;
+  char  *name;
+};
+
 static int file_total, dir_total, recurse, wide, bare, max_width, lower;
 static int shortname, usernames;
 static ULONGLONG byte_total;
@@ -286,7 +292,7 @@ void WCMD_directory (void) {
 
   if (errorlevel==0 && !bare) {
      if (recurse) {
-       WCMD_output ("\n\n     Total files listed:\n%8d files%25s bytes\n",
+       WCMD_output ("\n     Total files listed:\n%8d files%25s bytes\n",
             file_total, WCMD_filesize64 (byte_total));
        WCMD_output ("%8d directories %18s bytes free\n\n",
             dir_total, WCMD_filesize64 (free.QuadPart));
@@ -333,10 +339,12 @@ void WCMD_list_directory (char *search_path, int level) {
 /*
  *  If the path supplied does not include a wildcard, and the endpoint of the
  *  path references a directory, we need to list the *contents* of that
- *  directory not the directory file itself.
+ *  directory not the directory file itself. However, only do this on first
+ *  entry and not subsequent recursion
  */
 
-  if ((strchr(search_path, '*') == NULL) && (strchr(search_path, '%') == NULL)) {
+  if ((level == 0) &&
+      (strchr(search_path, '*') == NULL) && (strchr(search_path, '%') == NULL)) {
     status = GetFileAttributes (search_path);
     if ((status != INVALID_FILE_ATTRIBUTES) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
       if (search_path[strlen(search_path)-1] == '\\') {
@@ -355,196 +363,238 @@ void WCMD_list_directory (char *search_path, int level) {
 
   /* Load all files into an in memory structure */
   fd = HeapAlloc(GetProcessHeap(),0,sizeof(WIN32_FIND_DATA));
+  WINE_TRACE("Looking for matches to '%s'\n", search_path);
   hff = FindFirstFile (search_path, fd);
   if (hff == INVALID_HANDLE_VALUE) {
-    SetLastError (ERROR_FILE_NOT_FOUND);
-    WCMD_print_error ();
-    HeapFree(GetProcessHeap(),0,fd);
-    errorlevel = 1;
-    return;
-  }
-  do {
-    /* Skip any which are filtered out by attribute */
-    if (((fd+entry_count)->dwFileAttributes & attrsbits) != showattrs) continue;
-
-    entry_count++;
+    entry_count = 0;
+  } else {
+    do {
+      /* Skip any which are filtered out by attribute */
+      if (((fd+entry_count)->dwFileAttributes & attrsbits) != showattrs) continue;
 
-    /* Keep running track of longest filename for wide output */
-    if (wide || orderByCol) {
-       int tmpLen = strlen((fd+(entry_count-1))->cFileName) + 3;
-       if ((fd+(entry_count-1))->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) tmpLen = tmpLen + 2;
-       if (tmpLen > widest) widest = tmpLen;
-    }
+      entry_count++;
 
-    fd = HeapReAlloc(GetProcessHeap(),0,fd,(entry_count+1)*sizeof(WIN32_FIND_DATA));
-    if (fd == NULL) {
-      FindClose (hff);
-      WCMD_output ("Memory Allocation Error");
-      errorlevel = 1;
-      return;
-    }
-  } while (FindNextFile(hff, (fd+entry_count)) != 0);
-  FindClose (hff);
+      /* Keep running track of longest filename for wide output */
+      if (wide || orderByCol) {
+         int tmpLen = strlen((fd+(entry_count-1))->cFileName) + 3;
+         if ((fd+(entry_count-1))->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) tmpLen = tmpLen + 2;
+         if (tmpLen > widest) widest = tmpLen;
+      }
 
-  /* Handle case where everything is filtered out */
-  if (entry_count == 0) {
-    SetLastError (ERROR_FILE_NOT_FOUND);
-    WCMD_print_error ();
-    HeapFree(GetProcessHeap(),0,fd);
-    errorlevel = 1;
-    return;
+      fd = HeapReAlloc(GetProcessHeap(),0,fd,(entry_count+1)*sizeof(WIN32_FIND_DATA));
+      if (fd == NULL) {
+        FindClose (hff);
+        WCMD_output ("Memory Allocation Error");
+        errorlevel = 1;
+        return;
+      }
+    } while (FindNextFile(hff, (fd+entry_count)) != 0);
+    FindClose (hff);
   }
 
-  /* Sort the list of files */
-  qsort (fd, entry_count, sizeof(WIN32_FIND_DATA), WCMD_dir_sort);
-
   /* Output the results */
   if (!bare) {
-     if (level != 0) WCMD_output ("\n\n");
-     WCMD_output ("Directory of %s\n\n", real_path);
+     if (level != 0 && (entry_count > 0)) WCMD_output ("\n");
+     if ((entry_count > 0) || (!recurse && level == 0)) WCMD_output ("Directory of %s\n\n", real_path);
   }
 
-  /* Work out the number of columns */
-  WINE_TRACE("%d entries, maxwidth=%d, widest=%d\n", entry_count, max_width, widest);
-  if (wide || orderByCol) {
-    numCols = max(1, (int)max_width / widest);
-    numRows = entry_count / numCols;
-    if (entry_count % numCols) numRows++;
-  } else {
-    numCols = 1;
-    numRows = entry_count;
-  }
-  WINE_TRACE("cols=%d, rows=%d\n", numCols, numRows);
+  /* Handle case where everything is filtered out */
+  if (entry_count > 0) {
 
-  for (rows=0; rows<numRows; rows++) {
-   for (cols=0; cols<numCols; cols++) {
-    char username[24];
+    /* Sort the list of files */
+    qsort (fd, entry_count, sizeof(WIN32_FIND_DATA), WCMD_dir_sort);
 
-    /* Work out the index of the entry being pointed to */
-    if (orderByCol) {
-      i = (cols * numRows) + rows;
-      if (i >= entry_count) continue;
+    /* Work out the number of columns */
+    WINE_TRACE("%d entries, maxwidth=%d, widest=%d\n", entry_count, max_width, widest);
+    if (wide || orderByCol) {
+      numCols = max(1, (int)max_width / widest);
+      numRows = entry_count / numCols;
+      if (entry_count % numCols) numRows++;
     } else {
-      i = (rows * numCols) + cols;
-      if (i >= entry_count) continue;
-    }
-
-    /* /L convers all names to lower case */
-    if (lower) {
-        char *p = (fd+i)->cFileName;
-        while ( (*p = tolower(*p)) ) ++p;
+      numCols = 1;
+      numRows = entry_count;
     }
+    WINE_TRACE("cols=%d, rows=%d\n", numCols, numRows);
 
-    /* /Q gets file ownership information */
-    if (usernames) {
-        p = strrchr (search_path, '\\');
-        lstrcpyn (string, search_path, (p-search_path+2));
-        lstrcat (string, (fd+i)->cFileName);
-        WCMD_getfileowner(string, username, sizeof(username));
-    }
+    for (rows=0; rows<numRows; rows++) {
+     BOOL addNewLine = TRUE;
+     for (cols=0; cols<numCols; cols++) {
+      char username[24];
 
-    if (dirTime == Written) {
-      FileTimeToLocalFileTime (&(fd+i)->ftLastWriteTime, &ft);
-    } else if (dirTime == Access) {
-      FileTimeToLocalFileTime (&(fd+i)->ftLastAccessTime, &ft);
-    } else {
-      FileTimeToLocalFileTime (&(fd+i)->ftCreationTime, &ft);
-    }
-    FileTimeToSystemTime (&ft, &st);
-    GetDateFormat (0, DATE_SHORTDATE, &st, NULL, datestring,
-      		sizeof(datestring));
-    GetTimeFormat (0, TIME_NOSECONDS, &st,
-      		NULL, timestring, sizeof(timestring));
-
-    if (wide) {
-
-      tmp_width = cur_width;
-      if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-          WCMD_output ("[%s]", (fd+i)->cFileName);
-          dir_count++;
-          tmp_width = tmp_width + strlen((fd+i)->cFileName) + 2;
+      /* Work out the index of the entry being pointed to */
+      if (orderByCol) {
+        i = (cols * numRows) + rows;
+        if (i >= entry_count) continue;
       } else {
-          WCMD_output ("%s", (fd+i)->cFileName);
-          tmp_width = tmp_width + strlen((fd+i)->cFileName) ;
-          file_count++;
-          file_size.u.LowPart = (fd+i)->nFileSizeLow;
-          file_size.u.HighPart = (fd+i)->nFileSizeHigh;
-      byte_count.QuadPart += file_size.QuadPart;
+        i = (rows * numCols) + cols;
+        if (i >= entry_count) continue;
       }
-      cur_width = cur_width + widest;
 
-      if ((cur_width + widest) > max_width) {
-          cur_width = 0;
-      } else {
-          WCMD_output ("%*.s", (tmp_width - cur_width) ,"");
+      /* /L convers all names to lower case */
+      if (lower) {
+          char *p = (fd+i)->cFileName;
+          while ( (*p = tolower(*p)) ) ++p;
       }
 
-    } else if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-      dir_count++;
+      /* /Q gets file ownership information */
+      if (usernames) {
+          p = strrchr (search_path, '\\');
+          lstrcpyn (string, search_path, (p-search_path+2));
+          lstrcat (string, (fd+i)->cFileName);
+          WCMD_getfileowner(string, username, sizeof(username));
+      }
 
-      if (!bare) {
-         WCMD_output ("%10s  %8s  <DIR>         ", datestring, timestring);
-         if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
-         if (usernames) WCMD_output ("%-23s", username);
-         WCMD_output("%s",(fd+i)->cFileName);
+      if (dirTime == Written) {
+        FileTimeToLocalFileTime (&(fd+i)->ftLastWriteTime, &ft);
+      } else if (dirTime == Access) {
+        FileTimeToLocalFileTime (&(fd+i)->ftLastAccessTime, &ft);
       } else {
-         if (!((strcmp((fd+i)->cFileName, ".") == 0) ||
-               (strcmp((fd+i)->cFileName, "..") == 0))) {
-            WCMD_output ("%s%s", recurse?real_path:"", (fd+i)->cFileName);
-         }
+        FileTimeToLocalFileTime (&(fd+i)->ftCreationTime, &ft);
       }
-    }
-    else {
-      file_count++;
-      file_size.u.LowPart = (fd+i)->nFileSizeLow;
-      file_size.u.HighPart = (fd+i)->nFileSizeHigh;
-      byte_count.QuadPart += file_size.QuadPart;
-      if (!bare) {
-         WCMD_output ("%10s  %8s    %10s  ", datestring, timestring,
-                      WCMD_filesize64(file_size.QuadPart));
-         if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
-         if (usernames) WCMD_output ("%-23s", username);
-         WCMD_output("%s",(fd+i)->cFileName);
-      } else {
-         WCMD_output ("%s%s", recurse?real_path:"", (fd+i)->cFileName);
+      FileTimeToSystemTime (&ft, &st);
+      GetDateFormat (0, DATE_SHORTDATE, &st, NULL, datestring,
+        		sizeof(datestring));
+      GetTimeFormat (0, TIME_NOSECONDS, &st,
+        		NULL, timestring, sizeof(timestring));
+
+      if (wide) {
+
+        tmp_width = cur_width;
+        if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            WCMD_output ("[%s]", (fd+i)->cFileName);
+            dir_count++;
+            tmp_width = tmp_width + strlen((fd+i)->cFileName) + 2;
+        } else {
+            WCMD_output ("%s", (fd+i)->cFileName);
+            tmp_width = tmp_width + strlen((fd+i)->cFileName) ;
+            file_count++;
+            file_size.u.LowPart = (fd+i)->nFileSizeLow;
+            file_size.u.HighPart = (fd+i)->nFileSizeHigh;
+        byte_count.QuadPart += file_size.QuadPart;
+        }
+        cur_width = cur_width + widest;
+
+        if ((cur_width + widest) > max_width) {
+            cur_width = 0;
+        } else {
+            WCMD_output ("%*.s", (tmp_width - cur_width) ,"");
+        }
+
+      } else if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+        dir_count++;
+
+        if (!bare) {
+           WCMD_output ("%10s  %8s  <DIR>         ", datestring, timestring);
+           if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
+           if (usernames) WCMD_output ("%-23s", username);
+           WCMD_output("%s",(fd+i)->cFileName);
+        } else {
+           if (!((strcmp((fd+i)->cFileName, ".") == 0) ||
+                 (strcmp((fd+i)->cFileName, "..") == 0))) {
+              WCMD_output ("%s%s", recurse?real_path:"", (fd+i)->cFileName);
+           } else {
+              addNewLine = FALSE;
+           }
+        }
       }
+      else {
+        file_count++;
+        file_size.u.LowPart = (fd+i)->nFileSizeLow;
+        file_size.u.HighPart = (fd+i)->nFileSizeHigh;
+        byte_count.QuadPart += file_size.QuadPart;
+        if (!bare) {
+           WCMD_output ("%10s  %8s    %10s  ", datestring, timestring,
+                        WCMD_filesize64(file_size.QuadPart));
+           if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
+           if (usernames) WCMD_output ("%-23s", username);
+           WCMD_output("%s",(fd+i)->cFileName);
+        } else {
+           WCMD_output ("%s%s", recurse?real_path:"", (fd+i)->cFileName);
+        }
+      }
+     }
+     if (addNewLine) WCMD_output ("\n");
+     cur_width = 0;
     }
-   }
-   WCMD_output ("\n");
-   cur_width = 0;
-  }
 
-  if (!bare) {
-     if (file_count == 1) {
-       WCMD_output ("       1 file %25s bytes\n", WCMD_filesize64 (byte_count.QuadPart));
-     }
-     else {
-       WCMD_output ("%8d files %24s bytes\n", file_count, WCMD_filesize64 (byte_count.QuadPart));
-     }
-  }
-  byte_total = byte_total + byte_count.QuadPart;
-  file_total = file_total + file_count;
-  dir_total = dir_total + dir_count;
+    if (!bare) {
+       if (file_count == 1) {
+         WCMD_output ("       1 file %25s bytes\n", WCMD_filesize64 (byte_count.QuadPart));
+       }
+       else {
+         WCMD_output ("%8d files %24s bytes\n", file_count, WCMD_filesize64 (byte_count.QuadPart));
+       }
+    }
+    byte_total = byte_total + byte_count.QuadPart;
+    file_total = file_total + file_count;
+    dir_total = dir_total + dir_count;
 
-  if (!bare) {
-     if (dir_count == 1) WCMD_output ("1 directory         ");
-     else WCMD_output ("%8d directories", dir_count);
+    if (!bare && !recurse) {
+       if (dir_count == 1) WCMD_output ("%8d directory         ", 1);
+       else WCMD_output ("%8d directories", dir_count);
+    }
   }
-  for (i=0; i<entry_count; i++) {
-    if ((recurse) &&
-          ((fd+i)->cFileName[0] != '.') &&
-      	  ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
-#if 0
-      GetFullPathName ((fd+i)->cFileName, sizeof(string), string, NULL);
-#endif
-      p = strrchr (search_path, '\\');
-      lstrcpyn (string, search_path, (p-search_path+2));
-      lstrcat (string, (fd+i)->cFileName);
-      lstrcat (string, p);
-      WCMD_list_directory (string, 1);
+  free(fd);
+
+  /* When recursing, look in all subdirectories for matches */
+  if (recurse) {
+    struct directory_stack *dirStack = NULL;
+    struct directory_stack *lastEntry = NULL;
+    WIN32_FIND_DATA finddata;
+
+    /* Build path to search */
+    strcpy(string, search_path);
+    p = strrchr (string, '\\');
+    strcpy(p+1, "*");
+
+    WINE_TRACE("Recursive, looking for '%s'\n", string);
+    hff = FindFirstFile (string, &finddata);
+    if (hff != INVALID_HANDLE_VALUE) {
+      do {
+        if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+            (strcmp(finddata.cFileName, "..") != 0) &&
+            (strcmp(finddata.cFileName, ".") != 0)) {
+
+          struct directory_stack *thisDir;
+
+          /* Work out search parameter in sub dir */
+          p = strrchr (search_path, '\\');
+          lstrcpyn (string, search_path, (p-search_path+2));
+          string[(p-search_path+2)] = 0x00;
+          lstrcat (string, finddata.cFileName);
+          lstrcat (string, p);
+          WINE_TRACE("Recursive, Adding to search list '%s'\n", string);
+
+          /* Allocate memory, add to list */
+          thisDir = (struct directory_stack *) malloc (sizeof(struct directory_stack));
+          if (dirStack == NULL) dirStack = thisDir;
+          if (lastEntry != NULL) lastEntry->next = thisDir;
+          lastEntry = thisDir;
+          thisDir->next = NULL;
+          thisDir->name = malloc(strlen(string)+1);
+          strcpy(thisDir->name, string);
+        }
+      } while (FindNextFile(hff, &finddata) != 0);
+      FindClose (hff);
+
+      while (dirStack != NULL) {
+        struct directory_stack *thisDir = dirStack;
+        dirStack = thisDir->next;
+
+        WCMD_list_directory (thisDir->name, 1);
+        free(thisDir->name);
+        free(thisDir);
+      }
     }
   }
-  HeapFree(GetProcessHeap(),0,fd);
+
+  /* Handle case where everything is filtered out */
+  if ((file_total + dir_total == 0) && (level == 0)) {
+    SetLastError (ERROR_FILE_NOT_FOUND);
+    WCMD_print_error ();
+    errorlevel = 1;
+  }
+
   return;
 }
 
-- 
1.5.0




More information about the wine-patches mailing list