[PATCH 5/6] CMD.EXE: Make dir a* b* or dir a* b* /s mirror windows
Jason Edmeades
us at edmeades.me.uk
Thu Apr 5 16:47:57 CDT 2007
Windows 'intelligently' merges the search output for consecutive
parms on the command line. For example if in y:\test:
dir y:c* y:\test\b* y:\test\f\..\a* c:z* y:d*
Lists the output of y:\test merging a*, b* and c* files
(with multiple Directory headers, wierdly), then lists
c:z*, then y:\test\d*
When /s is added, the behaviour is the same into the subdirs
except the multiple banners disappears.
Hopefully thats it for the DIR command now!
---
programs/cmd/directory.c | 169 ++++++++++++++++++++++++++--------------------
1 files changed, 97 insertions(+), 72 deletions(-)
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
index 736a8b1..8739a68 100644
--- a/programs/cmd/directory.c
+++ b/programs/cmd/directory.c
@@ -33,7 +33,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
int WCMD_dir_sort (const void *a, const void *b);
-static void WCMD_list_directory (DIRECTORY_STACK *parms, int level);
char * WCMD_filesize64 (ULONGLONG free);
char * WCMD_strrev (char *buff);
static void WCMD_getfileowner(char *filename, char *owner, int ownerlen);
@@ -65,6 +64,7 @@ typedef struct _DIRECTORY_STACK
char *fileName;
} DIRECTORY_STACK;
+static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *parms, int level);
static int file_total, dir_total, recurse, wide, bare, max_width, lower;
static int shortname, usernames;
static ULONGLONG byte_total;
@@ -406,11 +406,8 @@ void WCMD_directory (char *cmd) {
/* Clear any errors from previous invocations, and process it */
errorlevel = 0;
- WCMD_list_directory (thisEntry, 0);
-
- /* Step to next parm */
prevEntry = thisEntry;
- thisEntry = thisEntry->next;
+ thisEntry = WCMD_list_directory (thisEntry, 0);
}
/* Trailer Information */
@@ -440,7 +437,7 @@ exit:
* FIXME: Assumes 24-line display for the /P qualifier.
*/
-static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
+static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int level) {
char string[1024], datestring[32], timestring[32];
char real_path[MAX_PATH];
@@ -452,6 +449,10 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
int numCols, numRows;
int rows, cols;
ULARGE_INTEGER byte_count, file_size;
+ DIRECTORY_STACK *parms;
+ int concurrentDirs = 0;
+ BOOL done_header = FALSE;
+
dir_count = 0;
file_count = 0;
@@ -460,49 +461,61 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
widest = 0;
cur_width = 0;
- /* Work out the full path + filename */
- strcpy(real_path, parms->dirName);
- strcat(real_path, parms->fileName);
-
- /* Load all files into an in memory structure */
+ /* Loop merging all the files from consecutive parms which relate to the
+ same directory. Note issuing a directory header with no contents
+ mirrors what windows does */
+ parms = inputparms;
fd = HeapAlloc(GetProcessHeap(),0,sizeof(WIN32_FIND_DATA));
- WINE_TRACE("Looking for matches to '%s'\n", real_path);
- hff = FindFirstFile (real_path, fd);
- if (hff == INVALID_HANDLE_VALUE) {
- entry_count = 0;
- } else {
- do {
- /* Skip any which are filtered out by attribute */
- if (((fd+entry_count)->dwFileAttributes & attrsbits) != showattrs) continue;
-
- entry_count++;
-
- /* 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;
- }
+ while (parms && strcmp(inputparms->dirName, parms->dirName) == 0) {
+ concurrentDirs++;
- 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);
- }
+ /* Work out the full path + filename */
+ strcpy(real_path, parms->dirName);
+ strcat(real_path, parms->fileName);
- /* Work out the actual current directory name without a trailing \ */
- strcpy(real_path, parms->dirName);
- real_path[strlen(parms->dirName)-1] = 0x00;
+ /* Load all files into an in memory structure */
+ WINE_TRACE("Looking for matches to '%s'\n", real_path);
+ hff = FindFirstFile (real_path, (fd+entry_count));
+ if (hff != INVALID_HANDLE_VALUE) {
+ do {
+ /* Skip any which are filtered out by attribute */
+ if (((fd+entry_count)->dwFileAttributes & attrsbits) != showattrs) continue;
+
+ entry_count++;
+
+ /* 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;
+ }
- /* Output the results */
- if (!bare) {
- 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);
+ 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 parms->next;
+ }
+ } while (FindNextFile(hff, (fd+entry_count)) != 0);
+ FindClose (hff);
+ }
+
+ /* Work out the actual current directory name without a trailing \ */
+ strcpy(real_path, parms->dirName);
+ real_path[strlen(parms->dirName)-1] = 0x00;
+
+ /* Output the results */
+ if (!bare) {
+ if (level != 0 && (entry_count > 0)) WCMD_output ("\n");
+ if (!recurse || ((entry_count > 0) && done_header==FALSE)) {
+ WCMD_output ("Directory of %s\n\n", real_path);
+ done_header = TRUE;
+ }
+ }
+
+ /* Move to next parm */
+ parms = parms->next;
}
/* Handle case where everything is filtered out */
@@ -545,7 +558,7 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
/* /Q gets file ownership information */
if (usernames) {
- lstrcpy (string, parms->dirName);
+ lstrcpy (string, inputparms->dirName);
lstrcat (string, (fd+i)->cFileName);
WCMD_getfileowner(string, username, sizeof(username));
}
@@ -597,7 +610,7 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
} else {
if (!((strcmp((fd+i)->cFileName, ".") == 0) ||
(strcmp((fd+i)->cFileName, "..") == 0))) {
- WCMD_output ("%s%s", recurse?parms->dirName:"", (fd+i)->cFileName);
+ WCMD_output ("%s%s", recurse?inputparms->dirName:"", (fd+i)->cFileName);
} else {
addNewLine = FALSE;
}
@@ -615,7 +628,7 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
if (usernames) WCMD_output ("%-23s", username);
WCMD_output("%s",(fd+i)->cFileName);
} else {
- WCMD_output ("%s%s", recurse?parms->dirName:"", (fd+i)->cFileName);
+ WCMD_output ("%s%s", recurse?inputparms->dirName:"", (fd+i)->cFileName);
}
}
}
@@ -649,7 +662,7 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
WIN32_FIND_DATA finddata;
/* Build path to search */
- strcpy(string, parms->dirName);
+ strcpy(string, inputparms->dirName);
strcat(string, "*");
WINE_TRACE("Recursive, looking for '%s'\n", string);
@@ -661,35 +674,45 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
(strcmp(finddata.cFileName, ".") != 0)) {
DIRECTORY_STACK *thisDir;
-
- /* Work out search parameter in sub dir */
- strcpy (string, parms->dirName);
- strcat (string, finddata.cFileName);
- strcat (string, "\\");
- WINE_TRACE("Recursive, Adding to search list '%s'\n", string);
-
- /* Allocate memory, add to list */
- thisDir = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
- if (dirStack == NULL) dirStack = thisDir;
- if (lastEntry != NULL) lastEntry->next = thisDir;
- lastEntry = thisDir;
- thisDir->next = NULL;
- thisDir->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(string)+1));
- strcpy(thisDir->dirName, string);
- thisDir->fileName = HeapAlloc(GetProcessHeap(),0,(strlen(parms->fileName)+1));
- strcpy(thisDir->fileName, parms->fileName);
+ int dirsToCopy = concurrentDirs;
+
+ /* Loop creating list of subdirs for all concurrent entries */
+ parms = inputparms;
+ while (dirsToCopy > 0) {
+ dirsToCopy--;
+
+ /* Work out search parameter in sub dir */
+ strcpy (string, inputparms->dirName);
+ strcat (string, finddata.cFileName);
+ strcat (string, "\\");
+ WINE_TRACE("Recursive, Adding to search list '%s'\n", string);
+
+ /* Allocate memory, add to list */
+ thisDir = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
+ if (dirStack == NULL) dirStack = thisDir;
+ if (lastEntry != NULL) lastEntry->next = thisDir;
+ lastEntry = thisDir;
+ thisDir->next = NULL;
+ thisDir->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(string)+1));
+ strcpy(thisDir->dirName, string);
+ thisDir->fileName = HeapAlloc(GetProcessHeap(),0,(strlen(parms->fileName)+1));
+ strcpy(thisDir->fileName, parms->fileName);
+ parms = parms->next;
+ }
}
} while (FindNextFile(hff, &finddata) != 0);
FindClose (hff);
while (dirStack != NULL) {
DIRECTORY_STACK *thisDir = dirStack;
- dirStack = thisDir->next;
-
- WCMD_list_directory (thisDir, 1);
- HeapFree(GetProcessHeap(),0,thisDir->dirName);
- HeapFree(GetProcessHeap(),0,thisDir->fileName);
- HeapFree(GetProcessHeap(),0,thisDir);
+ dirStack = WCMD_list_directory (thisDir, 1);
+ while (thisDir != dirStack) {
+ DIRECTORY_STACK *tempDir = thisDir->next;
+ HeapFree(GetProcessHeap(),0,thisDir->dirName);
+ HeapFree(GetProcessHeap(),0,thisDir->fileName);
+ HeapFree(GetProcessHeap(),0,thisDir);
+ thisDir = tempDir;
+ }
}
}
}
@@ -700,6 +723,8 @@ static void WCMD_list_directory (DIRECTORY_STACK *parms, int level) {
WCMD_print_error ();
errorlevel = 1;
}
+
+ return parms;
}
/*****************************************************************************
--
1.5.0
More information about the wine-patches
mailing list