https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e2b04fe75da490448b3eb49806163003bce097c6

commit e2b04fe75da490448b3eb49806163003bce097c6
Author:     Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org>
AuthorDate: Thu May 18 12:43:23 2023 +0200
Commit:     Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org>
CommitDate: Thu May 18 13:07:31 2023 +0200

    [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.)
---
 base/applications/cmdutils/attrib/attrib.c | 197 ++++++++++++++---------------
 1 file changed, 92 insertions(+), 105 deletions(-)

diff --git a/base/applications/cmdutils/attrib/attrib.c 
b/base/applications/cmdutils/attrib/attrib.c
index 9d22255d8eb..821bfd52faf 100644
--- a/base/applications/cmdutils/attrib/attrib.c
+++ b/base/applications/cmdutils/attrib/attrib.c
@@ -283,162 +283,149 @@ ChangeAttribute(
 
 int wmain(int argc, WCHAR *argv[])
 {
-    INT    i;
-    WCHAR  szPath[MAX_PATH] = L""; // For case we only use 'attrib +h /s' 
there is no szPath
-    WCHAR  szFileName [MAX_PATH];
-    BOOL   bRecurse = FALSE;
-    BOOL   bDirectories = FALSE;
-    DWORD  dwAttrib = 0;
-    DWORD  dwMask = 0;
-    LPWSTR p;
+    INT i;
+    BOOL bRecurse = FALSE;
+    BOOL bDirectories = FALSE;
+    DWORD dwAttrib = 0;
+    DWORD dwMask = 0;
+    BOOL bFound = FALSE;
+    PWSTR pszFileName;
+    WCHAR szFilePath[MAX_PATH + 2] = L""; // + 2 to reserve an extra path 
separator and a NULL-terminator.
 
     /* Initialize the Console Standard Streams */
     ConInitStdStreams();
 
-    /* Print help */
-    if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
-    {
-        ConResPuts(StdOut, STRING_ATTRIB_HELP);
-        return 0;
-    }
-
-    /* check for options */
-    for (i = 1; i < argc; i++)
-    {
-        if (wcsicmp(argv[i], L"/s") == 0)
-            bRecurse = TRUE;
-        else if (wcsicmp(argv[i], L"/d") == 0)
-            bDirectories = TRUE;
-    }
-
-    /* create attributes and mask */
+    /* Check for options and file specifications */
     for (i = 1; i < argc; i++)
     {
-        if (*argv[i] == L'+')
+        if (*argv[i] == L'/')
         {
-            if (wcslen(argv[i]) != 2)
+            /* Print help and bail out if needed */
+            if (wcscmp(argv[i], L"/?") == 0)
             {
-                ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, 
argv[i]);
-                return -1;
+                ConResPuts(StdOut, STRING_ATTRIB_HELP);
+                return 0;
             }
-
-            switch (towupper(argv[i][1]))
+            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
             {
-                case L'A':
-                    dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
-                    dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
-                    break;
-
-                case L'H':
-                    dwMask   |= FILE_ATTRIBUTE_HIDDEN;
-                    dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
-                    break;
-
-                case L'R':
-                    dwMask   |= FILE_ATTRIBUTE_READONLY;
-                    dwAttrib |= FILE_ATTRIBUTE_READONLY;
-                    break;
-
-                case L'S':
-                    dwMask   |= FILE_ATTRIBUTE_SYSTEM;
-                    dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
-                    break;
-
-                default:
-                    ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, 
argv[i]);
-                    return -1;
+                /* Unknown option */
+                ConResPrintf(StdErr, STRING_ERROR_INVALID_PARAM_FORMAT, 
argv[i]);
+                return -1;
             }
         }
-        else if (*argv[i] == L'-')
+        else
+        /* Build attributes and mask */
+        if ((*argv[i] == L'+') || (*argv[i] == L'-'))
         {
+            BOOL bAdd = (*argv[i] == L'+');
+
             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;
             }
 
             switch (towupper(argv[i][1]))
             {
                 case L'A':
-                    dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
-                    dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
+                    dwMask |= FILE_ATTRIBUTE_ARCHIVE;
+                    if (bAdd)
+                        dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
+                    else
+                        dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
                     break;
 
-                case L'H':
-                    dwMask   |= FILE_ATTRIBUTE_HIDDEN;
-                    dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
+                case L'S':
+                    dwMask |= FILE_ATTRIBUTE_SYSTEM;
+                    if (bAdd)
+                        dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
+                    else
+                        dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
                     break;
 
-                case L'R':
-                    dwMask   |= FILE_ATTRIBUTE_READONLY;
-                    dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
+                case L'H':
+                    dwMask |= FILE_ATTRIBUTE_HIDDEN;
+                    if (bAdd)
+                        dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
+                    else
+                        dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
                     break;
 
-                case L'S':
-                    dwMask   |= FILE_ATTRIBUTE_SYSTEM;
-                    dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
+                case L'R':
+                    dwMask |= FILE_ATTRIBUTE_READONLY;
+                    if (bAdd)
+                        dwAttrib |= FILE_ATTRIBUTE_READONLY;
+                    else
+                        dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
                     break;
 
                 default:
-                    ConResPrintf(StdOut, STRING_ERROR_INVALID_PARAM_FORMAT, 
argv[i]);
+                    ConResPrintf(StdErr, STRING_ERROR_INVALID_PARAM_FORMAT, 
argv[i]);
                     return -1;
             }
         }
+        else
+        {
+            /* At least one file specification found */
+            bFound = TRUE;
+        }
     }
 
-    if (argc == 1)
+    /* If no file specification was found, operate on all files of the current 
directory */
+    if (!bFound)
     {
-        DWORD len;
-
-        len = GetCurrentDirectory(MAX_PATH, szPath);
-        if (szPath[len-1] != L'\\')
+        DWORD len = GetCurrentDirectoryW(_countof(szFilePath) - 2, szFilePath);
+        if (szFilePath[len - 1] != L'\\')
         {
-            szPath[len] = L'\\';
-            szPath[len + 1] = UNICODE_NULL;
+            szFilePath[len] = L'\\';
+            szFilePath[len + 1] = UNICODE_NULL;
         }
-        wcscpy(szFileName, L"*.*");
-        PrintAttribute(szPath, szFileName, bRecurse, bDirectories);
+        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, pszFileName);
+
         return 0;
     }
 
-    /* get full file name */
+    /* Operate on each file specification */
     for (i = 1; i < argc; i++)
     {
-        if (*argv[i] == L'+' || *argv[i] == L'-' || *argv[i] == L'/')
+        /* Skip options */
+        if (*argv[i] == L'/' || *argv[i] == L'+' || *argv[i] == L'-')
             continue;
 
-        GetFullPathNameW(argv[i], MAX_PATH, szPath, &p);
-        wcscpy(szFileName, p);
-        *p = 0;
-
-        if (dwMask == 0)
+        GetFullPathNameW(argv[i], _countof(szFilePath) - 2, szFilePath, 
&pszFileName);
+        if (pszFileName)
         {
-            if (!PrintAttribute(szPath, szFileName, bRecurse, bDirectories))
-            {
-                ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
-            }
+            /* Move the file part so as to separate and NULL-terminate the 
directory */
+            MoveMemory(pszFileName + 1, pszFileName,
+                       sizeof(szFilePath) - (pszFileName -szFilePath + 1) * 
sizeof(*szFilePath));
+            *pszFileName++ = UNICODE_NULL;
         }
-        else if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, 
dwMask, dwAttrib))
+        else
         {
-            ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
+            pszFileName = L"";
         }
-    }
 
-// Code below handles the special case of 'attrib +h /s' and similar
-
-    if (bRecurse && dwMask && (wcscmp(szPath, L"") == 0))
-    {
-        DWORD len;
+        if (dwMask == 0)
+            bFound = PrintAttribute(szFilePath, pszFileName, bRecurse, 
bDirectories);
+        else
+            bFound = ChangeAttribute(szFilePath, pszFileName, bRecurse, 
bDirectories, dwMask, dwAttrib);
 
-        len = GetCurrentDirectory(MAX_PATH, szPath);
-        if (szPath[len-1] != L'\\')
-        {
-            szPath[len] = L'\\';
-            szPath[len + 1] = UNICODE_NULL;
-        }
-        wcscpy(szFileName, L"*.*");
-        if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, 
dwMask, dwAttrib))
-            ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, szFileName);
+        if (!bFound)
+            ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
     }
 
     return 0;

Reply via email to