mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 00:45:43 +00:00
[ATTRIB] Improve command-line parsing. (#5288)
Fix arguments parsing and redundant code in case no file specification has been given. (Handles both "attrib" and "attrib +h /s" as given in example.)
This commit is contained in:
parent
7f45cac9ab
commit
e2b04fe75d
1 changed files with 100 additions and 113 deletions
|
@ -283,162 +283,149 @@ ChangeAttribute(
|
||||||
|
|
||||||
int wmain(int argc, WCHAR *argv[])
|
int wmain(int argc, WCHAR *argv[])
|
||||||
{
|
{
|
||||||
INT i;
|
INT i;
|
||||||
WCHAR szPath[MAX_PATH] = L""; // For case we only use 'attrib +h /s' there is no szPath
|
BOOL bRecurse = FALSE;
|
||||||
WCHAR szFileName [MAX_PATH];
|
BOOL bDirectories = FALSE;
|
||||||
BOOL bRecurse = FALSE;
|
DWORD dwAttrib = 0;
|
||||||
BOOL bDirectories = FALSE;
|
DWORD dwMask = 0;
|
||||||
DWORD dwAttrib = 0;
|
BOOL bFound = FALSE;
|
||||||
DWORD dwMask = 0;
|
PWSTR pszFileName;
|
||||||
LPWSTR p;
|
WCHAR szFilePath[MAX_PATH + 2] = L""; // + 2 to reserve an extra path separator and a NULL-terminator.
|
||||||
|
|
||||||
/* Initialize the Console Standard Streams */
|
/* Initialize the Console Standard Streams */
|
||||||
ConInitStdStreams();
|
ConInitStdStreams();
|
||||||
|
|
||||||
/* Print help */
|
/* Check for options and file specifications */
|
||||||
if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
|
|
||||||
{
|
|
||||||
ConResPuts(StdOut, STRING_ATTRIB_HELP);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for options */
|
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (wcsicmp(argv[i], L"/s") == 0)
|
if (*argv[i] == L'/')
|
||||||
bRecurse = TRUE;
|
|
||||||
else if (wcsicmp(argv[i], L"/d") == 0)
|
|
||||||
bDirectories = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create attributes and mask */
|
|
||||||
for (i = 1; i < argc; i++)
|
|
||||||
{
|
|
||||||
if (*argv[i] == L'+')
|
|
||||||
{
|
{
|
||||||
|
/* Print help and bail out if needed */
|
||||||
|
if (wcscmp(argv[i], L"/?") == 0)
|
||||||
|
{
|
||||||
|
ConResPuts(StdOut, STRING_ATTRIB_HELP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Retrieve the enumeration modes */
|
||||||
|
if (wcsicmp(argv[i], L"/s") == 0)
|
||||||
|
bRecurse = TRUE;
|
||||||
|
else if (wcsicmp(argv[i], L"/d") == 0)
|
||||||
|
bDirectories = TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Unknown option */
|
||||||
|
ConResPrintf(StdErr, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Build attributes and mask */
|
||||||
|
if ((*argv[i] == L'+') || (*argv[i] == L'-'))
|
||||||
|
{
|
||||||
|
BOOL bAdd = (*argv[i] == L'+');
|
||||||
|
|
||||||
if (wcslen(argv[i]) != 2)
|
if (wcslen(argv[i]) != 2)
|
||||||
{
|
{
|
||||||
ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
ConResPrintf(StdErr, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (towupper(argv[i][1]))
|
switch (towupper(argv[i][1]))
|
||||||
{
|
{
|
||||||
case L'A':
|
case L'A':
|
||||||
dwMask |= FILE_ATTRIBUTE_ARCHIVE;
|
dwMask |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
|
if (bAdd)
|
||||||
break;
|
dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
else
|
||||||
case L'H':
|
dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
|
||||||
dwMask |= FILE_ATTRIBUTE_HIDDEN;
|
|
||||||
dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case L'R':
|
|
||||||
dwMask |= FILE_ATTRIBUTE_READONLY;
|
|
||||||
dwAttrib |= FILE_ATTRIBUTE_READONLY;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'S':
|
case L'S':
|
||||||
dwMask |= FILE_ATTRIBUTE_SYSTEM;
|
dwMask |= FILE_ATTRIBUTE_SYSTEM;
|
||||||
dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
|
if (bAdd)
|
||||||
break;
|
dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
|
||||||
|
else
|
||||||
default:
|
dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
|
||||||
ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*argv[i] == L'-')
|
|
||||||
{
|
|
||||||
if (wcslen(argv[i]) != 2)
|
|
||||||
{
|
|
||||||
ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (towupper(argv[i][1]))
|
|
||||||
{
|
|
||||||
case L'A':
|
|
||||||
dwMask |= FILE_ATTRIBUTE_ARCHIVE;
|
|
||||||
dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'H':
|
case L'H':
|
||||||
dwMask |= FILE_ATTRIBUTE_HIDDEN;
|
dwMask |= FILE_ATTRIBUTE_HIDDEN;
|
||||||
dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
|
if (bAdd)
|
||||||
|
dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
|
||||||
|
else
|
||||||
|
dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'R':
|
case L'R':
|
||||||
dwMask |= FILE_ATTRIBUTE_READONLY;
|
dwMask |= FILE_ATTRIBUTE_READONLY;
|
||||||
dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
|
if (bAdd)
|
||||||
break;
|
dwAttrib |= FILE_ATTRIBUTE_READONLY;
|
||||||
|
else
|
||||||
case L'S':
|
dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
|
||||||
dwMask |= FILE_ATTRIBUTE_SYSTEM;
|
|
||||||
dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
ConResPrintf(StdErr, STRING_ERROR_INVALID_PARAM_FORMAT, argv[i]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
DWORD len;
|
|
||||||
|
|
||||||
len = GetCurrentDirectory(MAX_PATH, szPath);
|
|
||||||
if (szPath[len-1] != L'\\')
|
|
||||||
{
|
{
|
||||||
szPath[len] = L'\\';
|
/* At least one file specification found */
|
||||||
szPath[len + 1] = UNICODE_NULL;
|
bFound = TRUE;
|
||||||
}
|
}
|
||||||
wcscpy(szFileName, L"*.*");
|
|
||||||
PrintAttribute(szPath, szFileName, bRecurse, bDirectories);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get full file name */
|
/* If no file specification was found, operate on all files of the current directory */
|
||||||
for (i = 1; i < argc; i++)
|
if (!bFound)
|
||||||
{
|
{
|
||||||
if (*argv[i] == L'+' || *argv[i] == L'-' || *argv[i] == L'/')
|
DWORD len = GetCurrentDirectoryW(_countof(szFilePath) - 2, szFilePath);
|
||||||
continue;
|
if (szFilePath[len - 1] != L'\\')
|
||||||
|
{
|
||||||
GetFullPathNameW(argv[i], MAX_PATH, szPath, &p);
|
szFilePath[len] = L'\\';
|
||||||
wcscpy(szFileName, p);
|
szFilePath[len + 1] = UNICODE_NULL;
|
||||||
*p = 0;
|
}
|
||||||
|
pszFileName = L"*.*";
|
||||||
|
|
||||||
if (dwMask == 0)
|
if (dwMask == 0)
|
||||||
{
|
bFound = PrintAttribute(szFilePath, pszFileName, bRecurse, bDirectories);
|
||||||
if (!PrintAttribute(szPath, szFileName, bRecurse, bDirectories))
|
else
|
||||||
{
|
bFound = ChangeAttribute(szFilePath, pszFileName, bRecurse, bDirectories, dwMask, dwAttrib);
|
||||||
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
|
|
||||||
}
|
if (!bFound)
|
||||||
}
|
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, pszFileName);
|
||||||
else if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, dwMask, dwAttrib))
|
|
||||||
{
|
return 0;
|
||||||
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code below handles the special case of 'attrib +h /s' and similar
|
/* Operate on each file specification */
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
if (bRecurse && dwMask && (wcscmp(szPath, L"") == 0))
|
|
||||||
{
|
{
|
||||||
DWORD len;
|
/* Skip options */
|
||||||
|
if (*argv[i] == L'/' || *argv[i] == L'+' || *argv[i] == L'-')
|
||||||
|
continue;
|
||||||
|
|
||||||
len = GetCurrentDirectory(MAX_PATH, szPath);
|
GetFullPathNameW(argv[i], _countof(szFilePath) - 2, szFilePath, &pszFileName);
|
||||||
if (szPath[len-1] != L'\\')
|
if (pszFileName)
|
||||||
{
|
{
|
||||||
szPath[len] = L'\\';
|
/* Move the file part so as to separate and NULL-terminate the directory */
|
||||||
szPath[len + 1] = UNICODE_NULL;
|
MoveMemory(pszFileName + 1, pszFileName,
|
||||||
|
sizeof(szFilePath) - (pszFileName -szFilePath + 1) * sizeof(*szFilePath));
|
||||||
|
*pszFileName++ = UNICODE_NULL;
|
||||||
}
|
}
|
||||||
wcscpy(szFileName, L"*.*");
|
else
|
||||||
if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, dwMask, dwAttrib))
|
{
|
||||||
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, szFileName);
|
pszFileName = L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwMask == 0)
|
||||||
|
bFound = PrintAttribute(szFilePath, pszFileName, bRecurse, bDirectories);
|
||||||
|
else
|
||||||
|
bFound = ChangeAttribute(szFilePath, pszFileName, bRecurse, bDirectories, dwMask, dwAttrib);
|
||||||
|
|
||||||
|
if (!bFound)
|
||||||
|
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue