forked from Mirrors/wine-wine
cmd.exe: Support for DEL filename /s.
parent
67fff3959f
commit
68b11d1290
|
@ -11,7 +11,6 @@ WHAT'S INCLUDED
|
||||||
|
|
||||||
WHAT'S MISSING
|
WHAT'S MISSING
|
||||||
- Command-line qualifiers for most builtin commands
|
- Command-line qualifiers for most builtin commands
|
||||||
- Wildcards and relative paths in COPY, MOVE and RENAME
|
|
||||||
- Set functionality in DATE, TIME, ATTRIB, LABEL
|
- Set functionality in DATE, TIME, ATTRIB, LABEL
|
||||||
- Full internationalisation of the text (and commands?).
|
- Full internationalisation of the text (and commands?).
|
||||||
|
|
||||||
|
@ -26,11 +25,6 @@ US date-time format is used. Set eg "LANG=en_GB" for DD/MM/YY dates and 24-hour
|
||||||
times.
|
times.
|
||||||
- Line editing and command recall doesn't work due to missing functionality in
|
- Line editing and command recall doesn't work due to missing functionality in
|
||||||
Wine.
|
Wine.
|
||||||
- DIR/S only works if no file specification is given, ie "DIR C:\TEMP /S" works
|
|
||||||
but "DIR C:\TEMP\*.C" doesn't work if a matching file exists in a lower
|
|
||||||
directory.
|
|
||||||
- Copy, rename, move, need the source and destination to be specified fully
|
|
||||||
with an absolute or relative path but no wildcards or partial filenames.
|
|
||||||
- Redirection is implemented as a command line is parsed. This means that ">"
|
- Redirection is implemented as a command line is parsed. This means that ">"
|
||||||
and "<" symbols cannot appear in command arguments even within quotes.
|
and "<" symbols cannot appear in command arguments even within quotes.
|
||||||
- In many cases parsing and syntax checking is less rigorous than DOS. Thus an
|
- In many cases parsing and syntax checking is less rigorous than DOS. Thus an
|
||||||
|
@ -43,4 +37,3 @@ image. The Wine binary is simpler to invoke from the U**x command line or from
|
||||||
a GUI such as KDE, however it is not possible to invoke a second shell using the
|
a GUI such as KDE, however it is not possible to invoke a second shell using the
|
||||||
"CMD /C filename" syntax. Conversely a Win32 application can be invoked from a
|
"CMD /C filename" syntax. Conversely a Win32 application can be invoked from a
|
||||||
Win32 GUI such as Program Manager but that needs starting under Wine first.
|
Win32 GUI such as Program Manager but that needs starting under Wine first.
|
||||||
|
|
||||||
|
|
|
@ -239,24 +239,32 @@ void WCMD_create_dir (void) {
|
||||||
* non-hidden files
|
* non-hidden files
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void WCMD_delete (char *command) {
|
BOOL WCMD_delete (char *command, BOOL expectDir) {
|
||||||
|
|
||||||
int argno = 0;
|
int argno = 0;
|
||||||
int argsProcessed = 0;
|
int argsProcessed = 0;
|
||||||
char *argN = command;
|
char *argN = command;
|
||||||
|
BOOL foundAny = FALSE;
|
||||||
|
|
||||||
|
/* If not recursing, clear error flag */
|
||||||
|
if (expectDir) errorlevel = 0;
|
||||||
|
|
||||||
/* Loop through all args */
|
/* Loop through all args */
|
||||||
while (argN) {
|
while (argN) {
|
||||||
char *thisArg = WCMD_parameter (command, argno++, &argN);
|
char *thisArg = WCMD_parameter (command, argno++, &argN);
|
||||||
|
char argCopy[MAX_PATH];
|
||||||
|
|
||||||
if (argN && argN[0] != '/') {
|
if (argN && argN[0] != '/') {
|
||||||
|
|
||||||
WIN32_FIND_DATA fd;
|
WIN32_FIND_DATA fd;
|
||||||
HANDLE hff;
|
HANDLE hff;
|
||||||
char fpath[MAX_PATH];
|
char fpath[MAX_PATH];
|
||||||
char *p;
|
char *p;
|
||||||
|
BOOL handleParm = TRUE;
|
||||||
|
BOOL found = FALSE;
|
||||||
|
|
||||||
|
strcpy(argCopy, thisArg);
|
||||||
WINE_TRACE("del: Processing arg %s (quals:%s)\n", thisArg, quals);
|
WINE_TRACE("del: Processing arg %s (quals:%s)\n", argCopy, quals);
|
||||||
argsProcessed++;
|
argsProcessed++;
|
||||||
|
|
||||||
/* If filename part of parameter is * or *.*, prompt unless
|
/* If filename part of parameter is * or *.*, prompt unless
|
||||||
|
@ -269,7 +277,7 @@ void WCMD_delete (char *command) {
|
||||||
char ext[MAX_PATH];
|
char ext[MAX_PATH];
|
||||||
|
|
||||||
/* Convert path into actual directory spec */
|
/* Convert path into actual directory spec */
|
||||||
GetFullPathName (thisArg, sizeof(fpath), fpath, NULL);
|
GetFullPathName (argCopy, sizeof(fpath), fpath, NULL);
|
||||||
WCMD_splitpath(fpath, drive, dir, fname, ext);
|
WCMD_splitpath(fpath, drive, dir, fname, ext);
|
||||||
|
|
||||||
/* Only prompt for * and *.*, not *a, a*, *.a* etc */
|
/* Only prompt for * and *.*, not *a, a*, *.a* etc */
|
||||||
|
@ -278,6 +286,9 @@ void WCMD_delete (char *command) {
|
||||||
BOOL ok;
|
BOOL ok;
|
||||||
char question[MAXSTRING];
|
char question[MAXSTRING];
|
||||||
|
|
||||||
|
/* Note: Flag as found, to avoid file not found message */
|
||||||
|
found = TRUE;
|
||||||
|
|
||||||
/* Ask for confirmation */
|
/* Ask for confirmation */
|
||||||
sprintf(question, "%s, ", fpath);
|
sprintf(question, "%s, ", fpath);
|
||||||
ok = WCMD_ask_confirm(question, TRUE);
|
ok = WCMD_ask_confirm(question, TRUE);
|
||||||
|
@ -287,25 +298,28 @@ void WCMD_delete (char *command) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hff = FindFirstFile (thisArg, &fd);
|
/* First, try to delete in the current directory */
|
||||||
|
hff = FindFirstFile (argCopy, &fd);
|
||||||
if (hff == INVALID_HANDLE_VALUE) {
|
if (hff == INVALID_HANDLE_VALUE) {
|
||||||
WCMD_output ("%s :File Not Found\n", thisArg);
|
handleParm = FALSE;
|
||||||
continue;
|
} else {
|
||||||
|
found = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Support del <dirname> by just deleting all files dirname\* */
|
/* Support del <dirname> by just deleting all files dirname\* */
|
||||||
if ((strchr(thisArg,'*') == NULL) && (strchr(thisArg,'?') == NULL)
|
if (handleParm && (strchr(argCopy,'*') == NULL) && (strchr(argCopy,'?') == NULL)
|
||||||
&& (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
&& (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
char modifiedParm[MAX_PATH];
|
char modifiedParm[MAX_PATH];
|
||||||
strcpy(modifiedParm, thisArg);
|
strcpy(modifiedParm, argCopy);
|
||||||
strcat(modifiedParm, "\\*");
|
strcat(modifiedParm, "\\*");
|
||||||
FindClose(hff);
|
FindClose(hff);
|
||||||
WCMD_delete(modifiedParm);
|
found = TRUE;
|
||||||
continue;
|
WCMD_delete(modifiedParm, FALSE);
|
||||||
|
|
||||||
} else {
|
} else if (handleParm) {
|
||||||
|
|
||||||
/* Build the filename to delete as <supplied directory>\<findfirst filename> */
|
/* Build the filename to delete as <supplied directory>\<findfirst filename> */
|
||||||
strcpy (fpath, thisArg);
|
strcpy (fpath, argCopy);
|
||||||
do {
|
do {
|
||||||
p = strrchr (fpath, '\\');
|
p = strrchr (fpath, '\\');
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
|
@ -399,14 +413,100 @@ void WCMD_delete (char *command) {
|
||||||
} while (FindNextFile(hff, &fd) != 0);
|
} while (FindNextFile(hff, &fd) != 0);
|
||||||
FindClose (hff);
|
FindClose (hff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now recurse into all subdirectories handling the paramater in the same way */
|
||||||
|
if (strstr (quals, "/S") != NULL) {
|
||||||
|
|
||||||
|
char thisDir[MAX_PATH];
|
||||||
|
int cPos;
|
||||||
|
|
||||||
|
char drive[10];
|
||||||
|
char dir[MAX_PATH];
|
||||||
|
char fname[MAX_PATH];
|
||||||
|
char ext[MAX_PATH];
|
||||||
|
|
||||||
|
/* Convert path into actual directory spec */
|
||||||
|
GetFullPathName (argCopy, sizeof(thisDir), thisDir, NULL);
|
||||||
|
WCMD_splitpath(thisDir, drive, dir, fname, ext);
|
||||||
|
|
||||||
|
strcpy(thisDir, drive);
|
||||||
|
strcat(thisDir, dir);
|
||||||
|
cPos = strlen(thisDir);
|
||||||
|
|
||||||
|
WINE_TRACE("Searching recursively in '%s'\n", thisDir);
|
||||||
|
|
||||||
|
/* Append '*' to the directory */
|
||||||
|
thisDir[cPos] = '*';
|
||||||
|
thisDir[cPos+1] = 0x00;
|
||||||
|
|
||||||
|
hff = FindFirstFile (thisDir, &fd);
|
||||||
|
|
||||||
|
/* Remove residual '*' */
|
||||||
|
thisDir[cPos] = 0x00;
|
||||||
|
|
||||||
|
if (hff != INVALID_HANDLE_VALUE) {
|
||||||
|
DIRECTORY_STACK *allDirs = NULL;
|
||||||
|
DIRECTORY_STACK *lastEntry = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
|
(strcmp(fd.cFileName, "..") != 0) &&
|
||||||
|
(strcmp(fd.cFileName, ".") != 0)) {
|
||||||
|
|
||||||
|
DIRECTORY_STACK *nextDir;
|
||||||
|
char subParm[MAX_PATH];
|
||||||
|
|
||||||
|
/* Work out search parameter in sub dir */
|
||||||
|
strcpy (subParm, thisDir);
|
||||||
|
strcat (subParm, fd.cFileName);
|
||||||
|
strcat (subParm, "\\");
|
||||||
|
strcat (subParm, fname);
|
||||||
|
strcat (subParm, ext);
|
||||||
|
WINE_TRACE("Recursive, Adding to search list '%s'\n", subParm);
|
||||||
|
|
||||||
|
/* Allocate memory, add to list */
|
||||||
|
nextDir = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
|
||||||
|
if (allDirs == NULL) allDirs = nextDir;
|
||||||
|
if (lastEntry != NULL) lastEntry->next = nextDir;
|
||||||
|
lastEntry = nextDir;
|
||||||
|
nextDir->next = NULL;
|
||||||
|
nextDir->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(subParm)+1));
|
||||||
|
strcpy(nextDir->dirName, subParm);
|
||||||
|
}
|
||||||
|
} while (FindNextFile(hff, &fd) != 0);
|
||||||
|
FindClose (hff);
|
||||||
|
|
||||||
|
/* Go through each subdir doing the delete */
|
||||||
|
while (allDirs != NULL) {
|
||||||
|
DIRECTORY_STACK *tempDir;
|
||||||
|
|
||||||
|
tempDir = allDirs->next;
|
||||||
|
found |= WCMD_delete (allDirs->dirName, FALSE);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(),0,allDirs->dirName);
|
||||||
|
HeapFree(GetProcessHeap(),0,allDirs);
|
||||||
|
allDirs = tempDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Keep running total to see if any found, and if not recursing
|
||||||
|
issue error message */
|
||||||
|
if (expectDir) {
|
||||||
|
if (!found) {
|
||||||
|
errorlevel = 1;
|
||||||
|
WCMD_output ("%s : File Not Found\n", argCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundAny |= found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle no valid args */
|
/* Handle no valid args */
|
||||||
if (argsProcessed == 0) {
|
if (argsProcessed == 0) {
|
||||||
WCMD_output ("Argument missing\n");
|
WCMD_output ("Argument missing\n");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return foundAny;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -57,13 +57,6 @@ typedef enum _DISPLAYORDER
|
||||||
Date
|
Date
|
||||||
} DISPLAYORDER;
|
} DISPLAYORDER;
|
||||||
|
|
||||||
typedef struct _DIRECTORY_STACK
|
|
||||||
{
|
|
||||||
struct _DIRECTORY_STACK *next;
|
|
||||||
char *dirName;
|
|
||||||
char *fileName;
|
|
||||||
} DIRECTORY_STACK;
|
|
||||||
|
|
||||||
static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *parms, int level);
|
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 file_total, dir_total, recurse, wide, bare, max_width, lower;
|
||||||
static int shortname, usernames;
|
static int shortname, usernames;
|
||||||
|
|
|
@ -35,7 +35,7 @@ void WCMD_clear_screen (void);
|
||||||
void WCMD_color (void);
|
void WCMD_color (void);
|
||||||
void WCMD_copy (void);
|
void WCMD_copy (void);
|
||||||
void WCMD_create_dir (void);
|
void WCMD_create_dir (void);
|
||||||
void WCMD_delete (char *);
|
BOOL WCMD_delete (char *, BOOL);
|
||||||
void WCMD_directory (char *);
|
void WCMD_directory (char *);
|
||||||
void WCMD_echo (const char *);
|
void WCMD_echo (const char *);
|
||||||
void WCMD_endlocal (void);
|
void WCMD_endlocal (void);
|
||||||
|
@ -109,6 +109,15 @@ struct env_stack
|
||||||
WCHAR *strings;
|
WCHAR *strings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Data structure to handle building lists during recursive calls */
|
||||||
|
|
||||||
|
typedef struct _DIRECTORY_STACK
|
||||||
|
{
|
||||||
|
struct _DIRECTORY_STACK *next;
|
||||||
|
char *dirName;
|
||||||
|
char *fileName;
|
||||||
|
} DIRECTORY_STACK;
|
||||||
|
|
||||||
#endif /* !RC_INVOKED */
|
#endif /* !RC_INVOKED */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -620,7 +620,7 @@ void WCMD_process_command (char *command)
|
||||||
break;
|
break;
|
||||||
case WCMD_DEL:
|
case WCMD_DEL:
|
||||||
case WCMD_ERASE:
|
case WCMD_ERASE:
|
||||||
WCMD_delete (p);
|
WCMD_delete (p, TRUE);
|
||||||
break;
|
break;
|
||||||
case WCMD_DIR:
|
case WCMD_DIR:
|
||||||
WCMD_directory (p);
|
WCMD_directory (p);
|
||||||
|
|
Loading…
Reference in New Issue