cmd: del /a: move parsing of attributes to helper function, use bitmasks.
This commit is contained in:
parent
87e9f32f6d
commit
65b27c9ecd
@ -532,6 +532,53 @@ void WCMD_create_dir (void) {
|
|||||||
if (!create_full_path(param1)) WCMD_print_error ();
|
if (!create_full_path(param1)) WCMD_print_error ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse the /A options given by the user on the commandline
|
||||||
|
* into a bitmask of wanted attributes (*wantSet),
|
||||||
|
* and a bitmask of unwanted attributes (*wantClear).
|
||||||
|
*/
|
||||||
|
static void WCMD_delete_parse_attributes(DWORD *wantSet, DWORD *wantClear) {
|
||||||
|
static const WCHAR parmA[] = {'/','A','\0'};
|
||||||
|
WCHAR *p;
|
||||||
|
|
||||||
|
/* both are strictly 'out' parameters */
|
||||||
|
*wantSet=0;
|
||||||
|
*wantClear=0;
|
||||||
|
|
||||||
|
/* For each /A argument */
|
||||||
|
for (p=strstrW(quals, parmA); p != NULL; p=strstrW(p, parmA)) {
|
||||||
|
/* Skip /A itself */
|
||||||
|
p += 2;
|
||||||
|
|
||||||
|
/* Skip optional : */
|
||||||
|
if (*p == ':') p++;
|
||||||
|
|
||||||
|
/* For each of the attribute specifier chars to this /A option */
|
||||||
|
for (; *p != 0 && *p != '/'; p++) {
|
||||||
|
BOOL negate = FALSE;
|
||||||
|
DWORD mask = 0;
|
||||||
|
|
||||||
|
if (*p == '-') {
|
||||||
|
negate=TRUE;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the attribute specifier to a bit in one of the masks */
|
||||||
|
switch (*p) {
|
||||||
|
case 'R': mask = FILE_ATTRIBUTE_READONLY; break;
|
||||||
|
case 'H': mask = FILE_ATTRIBUTE_HIDDEN; break;
|
||||||
|
case 'S': mask = FILE_ATTRIBUTE_SYSTEM; break;
|
||||||
|
case 'A': mask = FILE_ATTRIBUTE_ARCHIVE; break;
|
||||||
|
default:
|
||||||
|
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||||
|
}
|
||||||
|
if (negate)
|
||||||
|
*wantClear |= mask;
|
||||||
|
else
|
||||||
|
*wantSet |= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* WCMD_delete
|
* WCMD_delete
|
||||||
*
|
*
|
||||||
@ -551,11 +598,14 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
|
|||||||
int argsProcessed = 0;
|
int argsProcessed = 0;
|
||||||
WCHAR *argN = command;
|
WCHAR *argN = command;
|
||||||
BOOL foundAny = FALSE;
|
BOOL foundAny = FALSE;
|
||||||
static const WCHAR parmA[] = {'/','A','\0'};
|
|
||||||
static const WCHAR parmQ[] = {'/','Q','\0'};
|
static const WCHAR parmQ[] = {'/','Q','\0'};
|
||||||
static const WCHAR parmP[] = {'/','P','\0'};
|
static const WCHAR parmP[] = {'/','P','\0'};
|
||||||
static const WCHAR parmS[] = {'/','S','\0'};
|
static const WCHAR parmS[] = {'/','S','\0'};
|
||||||
static const WCHAR parmF[] = {'/','F','\0'};
|
static const WCHAR parmF[] = {'/','F','\0'};
|
||||||
|
DWORD wanted_attrs;
|
||||||
|
DWORD unwanted_attrs;
|
||||||
|
|
||||||
|
WCMD_delete_parse_attributes(&wanted_attrs, &unwanted_attrs);
|
||||||
|
|
||||||
/* If not recursing, clear error flag */
|
/* If not recursing, clear error flag */
|
||||||
if (expectDir) errorlevel = 0;
|
if (expectDir) errorlevel = 0;
|
||||||
@ -644,64 +694,11 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
|
|||||||
}
|
}
|
||||||
else strcpyW (fpath, fd.cFileName);
|
else strcpyW (fpath, fd.cFileName);
|
||||||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
BOOL ok = TRUE;
|
BOOL ok;
|
||||||
WCHAR *nextA = strstrW (quals, parmA);
|
|
||||||
|
|
||||||
/* Handle attribute matching (/A) */
|
/* Handle attribute matching (/A) */
|
||||||
if (nextA != NULL) {
|
ok = ((fd.dwFileAttributes & wanted_attrs) == wanted_attrs)
|
||||||
ok = FALSE;
|
&& ((fd.dwFileAttributes & unwanted_attrs) == 0);
|
||||||
while (nextA != NULL && !ok) {
|
|
||||||
|
|
||||||
WCHAR *thisA = (nextA+2);
|
|
||||||
BOOL stillOK = TRUE;
|
|
||||||
|
|
||||||
/* Skip optional : */
|
|
||||||
if (*thisA == ':') thisA++;
|
|
||||||
|
|
||||||
/* Parse each of the /A[:]xxx in turn */
|
|
||||||
while (*thisA && *thisA != '/') {
|
|
||||||
BOOL negate = FALSE;
|
|
||||||
BOOL attribute = FALSE;
|
|
||||||
|
|
||||||
/* Match negation of attribute first */
|
|
||||||
if (*thisA == '-') {
|
|
||||||
negate=TRUE;
|
|
||||||
thisA++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Match attribute */
|
|
||||||
switch (*thisA) {
|
|
||||||
case 'R': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
|
|
||||||
break;
|
|
||||||
case 'H': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
|
|
||||||
break;
|
|
||||||
case 'S': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM);
|
|
||||||
break;
|
|
||||||
case 'A': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check result, keeping a running boolean about whether it
|
|
||||||
matches all parsed attributes so far */
|
|
||||||
if (attribute && !negate) {
|
|
||||||
stillOK = stillOK;
|
|
||||||
} else if (!attribute && negate) {
|
|
||||||
stillOK = stillOK;
|
|
||||||
} else {
|
|
||||||
stillOK = FALSE;
|
|
||||||
}
|
|
||||||
thisA++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the running total as the final result */
|
|
||||||
ok = stillOK;
|
|
||||||
|
|
||||||
/* Step on to next /A set */
|
|
||||||
nextA = strstrW (nextA+1, parmA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* /P means prompt for each file */
|
/* /P means prompt for each file */
|
||||||
if (ok && strstrW (quals, parmP) != NULL) {
|
if (ok && strstrW (quals, parmP) != NULL) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user