cmd: del /a: move parsing of attributes to helper function, use bitmasks.

oldstable
Dan Kegel 2011-05-22 07:59:22 -07:00 committed by Alexandre Julliard
parent 87e9f32f6d
commit 65b27c9ecd
1 changed files with 54 additions and 57 deletions

View File

@ -532,6 +532,53 @@ void WCMD_create_dir (void) {
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
*
@ -551,11 +598,14 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
int argsProcessed = 0;
WCHAR *argN = command;
BOOL foundAny = FALSE;
static const WCHAR parmA[] = {'/','A','\0'};
static const WCHAR parmQ[] = {'/','Q','\0'};
static const WCHAR parmP[] = {'/','P','\0'};
static const WCHAR parmS[] = {'/','S','\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 (expectDir) errorlevel = 0;
@ -644,64 +694,11 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
}
else strcpyW (fpath, fd.cFileName);
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
BOOL ok = TRUE;
WCHAR *nextA = strstrW (quals, parmA);
BOOL ok;
/* Handle attribute matching (/A) */
if (nextA != NULL) {
ok = FALSE;
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);
}
}
ok = ((fd.dwFileAttributes & wanted_attrs) == wanted_attrs)
&& ((fd.dwFileAttributes & unwanted_attrs) == 0);
/* /P means prompt for each file */
if (ok && strstrW (quals, parmP) != NULL) {