Simplify and fix code by using GetFullPathName and GetVolumePathName instead of re...
authorThomas Bluemel <thomas@reactsoft.com>
Wed, 1 Aug 2007 16:20:16 +0000 (16:20 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Wed, 1 Aug 2007 16:20:16 +0000 (16:20 +0000)
See issue #2041 for more details.

svn path=/trunk/; revision=28074

reactos/base/shell/cmd/dir.c

index 491d117..c1529be 100644 (file)
@@ -621,189 +621,6 @@ DirReadParam(LPTSTR Line,                         /* [IN] The line with the parameters & switches */
 }
 
 
-/*
- * ExtendFilespec
- *
- * extend the filespec, possibly adding wildcards
- */
-static VOID
-ExtendFilespec (LPTSTR file)
-{
-       INT len = 0;
-
-       if (!file)
-               return;
-
-
-       /* if no file spec, change to "*.*" */
-       if (*file == _T('\0'))
-       {
-               _tcscpy (file, _T("*.*"));
-               return;
-       }
-
-       // add support for *.
-       if ((file[0] == _T('*')) && (file[1] == _T('.') ))
-        {
-                return;
-        }
-
-       /* if starts with . add * in front */
-       if (*file == _T('.'))
-       {
-               memmove (&file[1], &file[0], (_tcslen (file) + 1) * sizeof(TCHAR));
-               file[0] = _T('*');
-       }
-
-       /* if no . add .* */
-       if (!_tcschr (file, _T('.')))
-       {
-               _tcscat (file, _T(".*"));
-               return;
-       }
-
-
-
-       /* if last character is '.' add '*' */
-       len = _tcslen (file);
-       if (file[len - 1] == _T('.'))
-       {
-               _tcscat (file, _T("*"));
-               return;
-       }
-}
-
-
-/*
- * dir_parse_pathspec
- *
- * split the pathspec into drive, directory, and filespec
- */
-static INT
-DirParsePathspec (LPTSTR szPathspec, LPTSTR szPath, LPTSTR szFilespec)
-{
-       TCHAR  szOrigPath[MAX_PATH];
-       LPTSTR start;
-       LPTSTR tmp;
-       INT    i;
-       BOOL   bWildcards = FALSE;
-
-       GetCurrentDirectory (MAX_PATH, szOrigPath);
-
-       /* get the drive and change to it */
-       if (szPathspec[1] == _T(':'))
-       {
-               TCHAR szRootPath[] = _T("A:");
-
-               szRootPath[0] = szPathspec[0];
-               start = szPathspec + 2;
-               if (!SetCurrentDirectory (szRootPath))
-               {
-                       ErrorMessage (GetLastError(), NULL);
-                       return 1;
-               }
-       }
-       else
-       {
-               start = szPathspec;
-       }
-
-
-       /* check for wildcards */
-       for (i = 0; szPathspec[i]; i++)
-       {
-               if (szPathspec[i] == _T('*') || szPathspec[i] == _T('?'))
-                       bWildcards = TRUE;
-       }
-
-       /* check if this spec is a directory */
-       if (!bWildcards)
-       {
-               if (SetCurrentDirectory (szPathspec))
-               {
-                       _tcscpy (szFilespec, _T("*.*"));
-
-                       if (!GetCurrentDirectory (MAX_PATH, szPath))
-                       {
-                               szFilespec[0] = _T('\0');
-                               SetCurrentDirectory (szOrigPath);
-                               error_out_of_memory();
-                               return 1;
-                       }
-
-                       SetCurrentDirectory (szOrigPath);
-                       return 0;
-               }
-       }
-
-       /* find the file spec */
-       tmp = _tcsrchr (start, _T('\\'));
-
-       /* if no path is specified */
-       if (!tmp)
-       {
-               _tcscpy (szFilespec, start);
-               ExtendFilespec (szFilespec);
-               if (!GetCurrentDirectory (MAX_PATH, szPath))
-               {
-                       szFilespec[0] = _T('\0');
-                       SetCurrentDirectory (szOrigPath);
-                       error_out_of_memory();
-                       return 1;
-               }
-
-               SetCurrentDirectory (szOrigPath);
-               return 0;
-       }
-
-       /* get the filename */
-       _tcscpy (szFilespec, tmp+1);
-       ExtendFilespec (szFilespec);
-
-       if (tmp == start)
-       {
-               /* change to the root directory */
-               if (!SetCurrentDirectory (_T("\\")))
-               {
-                       szFilespec[0] = _T('\0');
-                       SetCurrentDirectory (szOrigPath);
-                       error_path_not_found ();
-                       return 1;
-               }
-       }
-       else
-       {
-               *tmp = _T('\0');
-
-               /* change to this directory */
-               if (!SetCurrentDirectory (start))
-               {
-                       *tmp = _T('\\');
-                       szFilespec[0] = _T('\0');
-                       SetCurrentDirectory (szOrigPath);
-                       error_path_not_found ();
-                       return 1;
-               }
-       }
-
-       /* get the full name of the directory */
-       if (!GetCurrentDirectory (MAX_PATH, szPath))
-       {
-               *tmp = _T('\\');
-               szFilespec[0] = _T('\0');
-               SetCurrentDirectory (szOrigPath);
-               error_out_of_memory ();
-               return 1;
-       }
-
-       *tmp = _T('\\');
-
-       SetCurrentDirectory (szOrigPath);
-
-       return 0;
-}
-
-
 /*
  * PrintDirectoryHeader
  *
@@ -813,58 +630,30 @@ static BOOL
 PrintDirectoryHeader(LPTSTR szPath, LPDIRSWITCHFLAGS lpFlags)
 {
   TCHAR szMsg[RC_STRING_MAX_SIZE];
+  TCHAR szFullDir[MAX_PATH];
   TCHAR szRootName[MAX_PATH];
   TCHAR szVolName[80];
+  LPTSTR pszFilePart;
   DWORD dwSerialNr;
-  LPTSTR p;
 
   if (lpFlags->bBareFormat)
     return TRUE;
 
-  /* build usable root path */
-  if (szPath[1] == _T(':') && szPath[2] == _T('\\'))
-    {
-      /* normal path */
-      szRootName[0] = szPath[0];
-      szRootName[1] = _T(':');
-      szRootName[2] = _T('\\');
-      szRootName[3] = 0;
-    }
-  else if (szPath[0] == _T('\\') && szPath[1] == _T('\\'))
-    {
-      /* UNC path */
-      p = _tcschr(&szPath[2], _T('\\'));
-      if (p == NULL)
-       {
-         error_invalid_drive();
-         return(FALSE);
-       }
-      p = _tcschr(p+1, _T('\\'));
-      if (p == NULL)
-       {
-         _tcscpy(szRootName, szPath);
-         _tcscat(szRootName, _T("\\"));
-       }
-      else
-       {
-         *p = 0;
-         _tcscpy(szRootName, szPath);
-         _tcscat(szRootName, _T("\\"));
-         *p = _T('\\');
-       }
-    }
-  else
+  if (GetFullPathName(szPath, sizeof(szFullDir) / sizeof(TCHAR), szFullDir, &pszFilePart) == 0)
     {
-      error_invalid_drive();
-      return(FALSE);
+      ErrorMessage(GetLastError(), _T("Failed to build full directory path"));
+      return FALSE;
     }
 
+  if (pszFilePart != NULL)
+      *pszFilePart = _T('\0');
+
   /* get the media ID of the drive */
-  if (!GetVolumeInformation(szRootName, szVolName, 80, &dwSerialNr,
+  if (!GetVolumePathName(szFullDir, szRootName, sizeof(szRootName) / sizeof(TCHAR)) ||
+      !GetVolumeInformation(szRootName, szVolName, 80, &dwSerialNr,
                            NULL, NULL, NULL, 0))
     {
-      error_invalid_drive();
-      return(FALSE);
+      return(TRUE);
     }
 
   /* print drive info */
@@ -1522,12 +1311,18 @@ DirPrintFiles(LPWIN32_FIND_DATA ptrFiles[],     /* [IN] Files' Info */
 {
        TCHAR szMsg[RC_STRING_MAX_SIZE];
        TCHAR szTemp[MAX_PATH];                 /* A buffer to format the directory header */
+       LPTSTR pszFilePart;
        SIZE_T len;
 
-       /* Print directory header */
-       _tcscpy(szTemp, szCurPath);
-
        /* We cut the trailing \ of the full path, unless the path is a drive */
+       if (GetFullPathName(szCurPath, sizeof(szTemp) / sizeof(TCHAR), szTemp, &pszFilePart) == 0)
+       {
+               pszFilePart = NULL;
+               _tcscpy(szTemp, szCurPath);
+       }
+       else if (pszFilePart != NULL)
+               *pszFilePart = _T('\0');
+
        len = _tcslen(szTemp);
        if ((len != 3 || szTemp[len - 2] != _T(':')) && szTemp[len - 1] == _T('\\'))
                szTemp[len-1] = _T('\0');
@@ -1736,7 +1531,6 @@ QsortFiles(LPWIN32_FIND_DATA ptrArray[],  /* [IN/OUT] The array with file info po
  */
 static INT
 DirList(LPTSTR szPath,                 /* [IN] The path that dir starts */
-               LPTSTR szFilespec,              /* [IN] The type of file that we are looking for */
                LPDIRSWITCHFLAGS lpFlags)       /* [IN] The flags of the listing */
 {
        HANDLE hSearch;                                                 /* The handle of the search */
@@ -1746,7 +1540,8 @@ DirList(LPTSTR szPath,                    /* [IN] The path that dir starts */
        PDIRFINDLISTNODE ptrStartNode;  /* The pointer to the first node */
        PDIRFINDLISTNODE ptrNextNode;   /* A pointer used for relatives refernces */
 TCHAR szFullPath[MAX_PATH];                            /* The full path that we are listing with trailing \ */
-TCHAR szFullFileSpec[MAX_PATH];                        /* The full path with file specs that we ll request\ */
+TCHAR szSubPath[MAX_PATH];
+LPTSTR pszFilePart;
 DWORD dwCount;                                                 /* A counter of files found in directory */
 DWORD dwCountFiles;                                            /* Counter for files */
 DWORD dwCountDirs;                                             /* Counter for directories */
@@ -1761,12 +1556,14 @@ ULARGE_INTEGER u64Temp;                                 /* A temporary counter */
        dwCountDirs = 0;
        u64CountBytes.QuadPart = 0;
 
-       /* Create szFullPath and szFullFileSpec */
-       _tcscpy (szFullPath, szPath);
-       if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
-               _tcscat (szFullPath, _T("\\"));
-       _tcscpy (szFullFileSpec, szFullPath);
-       _tcscat (szFullFileSpec, szFilespec);
+       /* Create szFullPath */
+       if (GetFullPathName(szPath, sizeof(szFullPath) / sizeof(TCHAR), szFullPath, &pszFilePart) == 0)
+       {
+               _tcscpy (szFullPath, szPath);
+               if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
+                       _tcscat (szFullPath, _T("\\"));
+               pszFilePart = NULL;
+       }
 
        /* Prepare the linked list, first node is allocated */
        ptrStartNode = cmd_alloc(sizeof(DIRFINDLISTNODE));
@@ -1780,7 +1577,7 @@ ULARGE_INTEGER u64Temp;                                   /* A temporary counter */
        ptrNextNode = ptrStartNode;
 
        /* Collect the results for the current folder */
-       hSearch = FindFirstFile(szFullFileSpec, &wfdFileInfo);
+       hSearch = FindFirstFile(szFullPath, &wfdFileInfo);
        do
        {
                if (hSearch != INVALID_HANDLE_VALUE)
@@ -1902,9 +1699,17 @@ ULARGE_INTEGER u64Temp;                                  /* A temporary counter */
        if (lpFlags->bRecursive)
        {
                /* The new search is involving any *.* file */
-               _tcscpy(szFullFileSpec, szFullPath);
-               _tcscat(szFullFileSpec, _T("*.*"));
-               hRecSearch = FindFirstFile (szFullFileSpec, &wfdFileInfo);
+               if (pszFilePart != NULL)
+               {
+                       memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
+                       szSubPath[pszFilePart - szFullPath] = _T('\0');
+               }
+               else
+                       _tcscpy(szSubPath, szFullPath);
+
+               _tcscat(szSubPath, _T("*.*"));
+
+               hRecSearch = FindFirstFile (szSubPath, &wfdFileInfo);
                do
                {
                        if (hRecSearch != INVALID_HANDLE_VALUE)
@@ -1915,10 +1720,21 @@ ULARGE_INTEGER u64Temp;                                 /* A temporary counter */
                                    (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                                {
                                        /* Concat the path and the directory to do recursive */
-                                       _tcscpy(szFullFileSpec, szFullPath);
-                                       _tcscat(szFullFileSpec, wfdFileInfo.cFileName);
-                                       /* We do the same for tha folder */
-                                       if (DirList(szFullFileSpec, szFilespec, lpFlags) != 0)
+                                       if (pszFilePart != NULL)
+                                       {
+                                               memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
+                                               szSubPath[pszFilePart - szFullPath] = _T('\0');
+                                       }
+                                       else
+                                               _tcscpy(szSubPath, szFullPath);
+
+                                       _tcscat(szSubPath, wfdFileInfo.cFileName);
+                                       _tcscat(szSubPath, _T("\\"));
+                                       if (pszFilePart != NULL)
+                                               _tcscat(szSubPath, pszFilePart);
+
+                                       /* We do the same for the folder */
+                                       if (DirList(szSubPath, lpFlags) != 0)
                                        {
                                                return 1;
                                        }
@@ -1953,7 +1769,6 @@ CommandDir(LPTSTR first, LPTSTR rest)
        TCHAR   dircmd[256];    /* A variable to store the DIRCMD enviroment variable */
        TCHAR   cDrive;
        TCHAR   szPath[MAX_PATH];
-       TCHAR   szFilespec[MAX_PATH];
        LPTSTR* params = NULL;
        INT             entries = 0;
        UINT    loop = 0;
@@ -1987,7 +1802,7 @@ CommandDir(LPTSTR first, LPTSTR rest)
        stFlags.stOrderBy.bUnSet = FALSE;
 
        nErrorLevel = 0;
-       
+
        /* read the parameters from the DIRCMD environment variable */
        if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
                if (!DirReadParam(dircmd, &params, &entries, &stFlags))
@@ -2005,21 +1820,23 @@ CommandDir(LPTSTR first, LPTSTR rest)
 
        /* default to current directory */
        if(entries == 0) {
-               if(!add_entry(&entries, &params, _T("."))) {
+               if(!add_entry(&entries, &params, _T("*"))) {
                        nErrorLevel = 1;
                        goto cleanup;
                }
        }
+       szPath[0] = _T('\0');
 
        for(loop = 0; loop < entries; loop++)
        {
-               /* parse the directory info */
-               if (DirParsePathspec (params[loop], szPath, szFilespec) || CheckCtrlBreak(BREAK_INPUT))
+               if (CheckCtrlBreak(BREAK_INPUT))
                {
                        nErrorLevel = 1;
                        goto cleanup;
                }
 
+               _tcscpy(szPath, params[loop]);
+
        /* <Debug :>
           Uncomment this to show the final state of switch flags*/
        #ifdef _DEBUG
@@ -2045,26 +1862,27 @@ CommandDir(LPTSTR first, LPTSTR rest)
        #endif
 
                /* Print the drive header if the drive changed */
-               if(cDrive != szPath[0] && !stFlags.bBareFormat) {
-                       if (!PrintDirectoryHeader (szPath, &stFlags)) {
+               if(cDrive != params[loop][0] && !stFlags.bBareFormat) {
+                       if (!PrintDirectoryHeader (params[loop], &stFlags)) {
                                nErrorLevel = 1;
                                goto cleanup;
                        }
 
-                       cDrive = szPath[0];
+                       cDrive = params[loop][0];
                }
                
 
                /* do the actual dir */
-               if (DirList (szPath, szFilespec, &stFlags))
+               if (DirList (params[loop], &stFlags))
                {
                        nErrorLevel = 1;
                        goto cleanup;
                }
+
        }
 
        /* print the footer */
-       PrintSummary(szPath,
+       PrintSummary(szPath, // FIXME: root of initial dir?
                recurse_file_cnt,
                recurse_dir_cnt,
                recurse_bytes,