mirror of
https://github.com/reactos/reactos.git
synced 2025-05-07 02:41:22 +00:00
[CMD] Fix the way the DIR-command pattern is interpreted when it contains paths or filenames with trailing dots.
Particular DIR commands like: "DIR .", "DIR .." now work as expected,
and we also correctly fix the behavior for files without extension,
that r38746 (2b06cfc0
) originally tried to fix but broke the previous
examples.
Therefore "DIR *." and "DIR noextfile." work too.
Pathological cases like "DIR \...", "DIR \...\.", "DIR ..\...\.." and
the like (and with more than 3 dots) now work as expected.
Adapted from PR #592 by Katayama Hirofumi MZ, but with extended bugfixing.
CORE-13961
This commit is contained in:
parent
c57d49d0c1
commit
17ebc8421a
1 changed files with 254 additions and 67 deletions
|
@ -121,20 +121,23 @@
|
||||||
*
|
*
|
||||||
* 27-Feb-2005 (Konstantinos Paliouras <squarious@gmail.com>)
|
* 27-Feb-2005 (Konstantinos Paliouras <squarious@gmail.com>)
|
||||||
* Implemented all the switches that were missing, and made
|
* Implemented all the switches that were missing, and made
|
||||||
* the ros dir very similar to windows dir. Major part of
|
* the ROS dir very similar to windows dir. Major part of
|
||||||
* the code is rewritten. /p is removed, to be rewritten in
|
* the code is rewritten. /p is removed, to be rewritten in
|
||||||
* the main cmd code.
|
* the main cmd code.
|
||||||
*
|
*
|
||||||
* 1-Jul-2004 (Brandon Turner <turnerb7@msu.edu>)
|
* 1-Jul-2004 (Brandon Turner <turnerb7@msu.edu>)
|
||||||
* Added /p back in using ConOutPrintfPaging
|
* Added /p back in using ConOutPrintfPaging
|
||||||
*
|
*
|
||||||
* 3-feb-2007 (Paolo Devoti devotip at gmail)
|
* 3-Feb-2007 (Paolo Devoti devotip at gmail)
|
||||||
* Removed variables formerly in use to handle pagination
|
* Removed variables formerly in use to handle pagination
|
||||||
* Pagination belongs to ConOutPrintfPaging
|
* Pagination belongs to ConOutPrintfPaging
|
||||||
* Removed already commented out code of old pagination
|
* Removed already commented out code of old pagination
|
||||||
*
|
*
|
||||||
* 25-Aug-2015 (Pierre Schweitzer)
|
* 25-Aug-2015 (Pierre Schweitzer)
|
||||||
* Implemented /R switch
|
* Implemented /R switch
|
||||||
|
*
|
||||||
|
* 6-Aug-2018 (Hermes Belusca-Maito and Katayama Hirofumi MZ)
|
||||||
|
* Fix handling of patterns containing trailing dots.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -572,23 +575,15 @@ static BOOL
|
||||||
PrintDirectoryHeader(LPCTSTR szPath, LPDIRSWITCHFLAGS lpFlags)
|
PrintDirectoryHeader(LPCTSTR szPath, LPDIRSWITCHFLAGS lpFlags)
|
||||||
{
|
{
|
||||||
TCHAR szMsg[RC_STRING_MAX_SIZE];
|
TCHAR szMsg[RC_STRING_MAX_SIZE];
|
||||||
TCHAR szFullDir[MAX_PATH];
|
LPCTSTR szFullDir;
|
||||||
TCHAR szRootName[MAX_PATH];
|
TCHAR szRootName[MAX_PATH];
|
||||||
TCHAR szVolName[80];
|
TCHAR szVolName[80];
|
||||||
LPTSTR pszFilePart;
|
|
||||||
DWORD dwSerialNr;
|
DWORD dwSerialNr;
|
||||||
|
|
||||||
if (lpFlags->bBareFormat)
|
if (lpFlags->bBareFormat)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (GetFullPathName(szPath, ARRAYSIZE(szFullDir), szFullDir, &pszFilePart) == 0)
|
szFullDir = szPath;
|
||||||
{
|
|
||||||
ErrorMessage(GetLastError(), _T("Failed to build full directory path"));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pszFilePart != NULL)
|
|
||||||
*pszFilePart = _T('\0');
|
|
||||||
|
|
||||||
/* Get the media ID of the drive */
|
/* Get the media ID of the drive */
|
||||||
if (!GetVolumePathName(szFullDir, szRootName, ARRAYSIZE(szRootName)) ||
|
if (!GetVolumePathName(szFullDir, szRootName, ARRAYSIZE(szRootName)) ||
|
||||||
|
@ -1339,10 +1334,10 @@ DirNodeCleanup(PDIRFINDLISTNODE ptrStartNode,
|
||||||
* The function that does everything except for printing results
|
* The function that does everything except for printing results
|
||||||
*/
|
*/
|
||||||
static INT
|
static INT
|
||||||
DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
DirList(IN OUT LPTSTR szFullPath, /* [IN] The full path we are listing with trailing '\', where dir starts */
|
||||||
|
IN LPTSTR pszFilePart, /* [IN] Pointer in the szFullPath buffer where the file (pattern) part starts*/
|
||||||
LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags of the listing */
|
LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags of the listing */
|
||||||
{
|
{
|
||||||
BOOL fPoint; /* If szPath is a file with extension fPoint will be True */
|
|
||||||
HANDLE hSearch; /* The handle of the search */
|
HANDLE hSearch; /* The handle of the search */
|
||||||
HANDLE hRecSearch; /* The handle for searching recursively */
|
HANDLE hRecSearch; /* The handle for searching recursively */
|
||||||
HANDLE hStreams; /* The handle for alternate streams */
|
HANDLE hStreams; /* The handle for alternate streams */
|
||||||
|
@ -1350,9 +1345,9 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
PDIRFINDINFO * ptrFileArray; /* An array of pointers with all the files */
|
PDIRFINDINFO * ptrFileArray; /* An array of pointers with all the files */
|
||||||
PDIRFINDLISTNODE ptrStartNode; /* The pointer to the first node */
|
PDIRFINDLISTNODE ptrStartNode; /* The pointer to the first node */
|
||||||
PDIRFINDLISTNODE ptrNextNode; /* A pointer used for relatives references */
|
PDIRFINDLISTNODE ptrNextNode; /* A pointer used for relatives references */
|
||||||
TCHAR szFullPath[MAX_PATH]; /* The full path that we are listing with trailing '\' */
|
TCHAR szSubPath[MAX_PATH]; /* The full path used for the recursive search */
|
||||||
TCHAR szSubPath[MAX_PATH];
|
LPTSTR pszSubFilePart;
|
||||||
LPTSTR pszFilePart;
|
TCHAR cPathSep;
|
||||||
DWORD dwCount; /* A counter of files found in directory */
|
DWORD dwCount; /* A counter of files found in directory */
|
||||||
DWORD dwCountFiles; /* Counter for files */
|
DWORD dwCountFiles; /* Counter for files */
|
||||||
DWORD dwCountDirs; /* Counter for directories */
|
DWORD dwCountDirs; /* Counter for directories */
|
||||||
|
@ -1370,24 +1365,6 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
dwCountFiles = 0;
|
dwCountFiles = 0;
|
||||||
dwCountDirs = 0;
|
dwCountDirs = 0;
|
||||||
u64CountBytes = 0;
|
u64CountBytes = 0;
|
||||||
fPoint= FALSE;
|
|
||||||
|
|
||||||
/* Create szFullPath */
|
|
||||||
if (GetFullPathName(szPath, ARRAYSIZE(szFullPath), szFullPath, &pszFilePart) == 0)
|
|
||||||
{
|
|
||||||
_tcscpy (szFullPath, szPath);
|
|
||||||
pszFilePart = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no wildcard or file was specified and this is a directory, then
|
|
||||||
display all files in it */
|
|
||||||
if (pszFilePart == NULL || IsExistingDirectory(szFullPath))
|
|
||||||
{
|
|
||||||
pszFilePart = &szFullPath[_tcslen(szFullPath)];
|
|
||||||
if (pszFilePart[-1] != _T('\\'))
|
|
||||||
*pszFilePart++ = _T('\\');
|
|
||||||
_tcscpy(pszFilePart, _T("*"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare the linked list, first node is allocated */
|
/* Prepare the linked list, first node is allocated */
|
||||||
ptrStartNode = cmd_alloc(sizeof(DIRFINDLISTNODE));
|
ptrStartNode = cmd_alloc(sizeof(DIRFINDLISTNODE));
|
||||||
|
@ -1399,24 +1376,14 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
ptrStartNode->stInfo.ptrHead = NULL;
|
ptrStartNode->stInfo.ptrHead = NULL;
|
||||||
ptrNextNode = ptrStartNode;
|
ptrNextNode = ptrStartNode;
|
||||||
|
|
||||||
/* Checking if szPath is a File with/wout extension */
|
|
||||||
if (szPath[_tcslen(szPath) - 1] == _T('.'))
|
|
||||||
fPoint= TRUE;
|
|
||||||
|
|
||||||
/* Collect the results for the current folder */
|
/* Collect the results for the current folder */
|
||||||
hSearch = FindFirstFile(szFullPath, &wfdFileInfo);
|
hSearch = FindFirstFile(szFullPath, &wfdFileInfo);
|
||||||
if (hSearch != INVALID_HANDLE_VALUE)
|
if (hSearch != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* If retrieved FileName has extension,and szPath doesnt have extension then JUMP the retrieved FileName */
|
if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask) ==
|
||||||
if (_tcschr(wfdFileInfo.cFileName,_T('.')) && (fPoint != FALSE))
|
(lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal))
|
||||||
{
|
|
||||||
continue;
|
|
||||||
/* Here we filter all the specified attributes */
|
|
||||||
}
|
|
||||||
else if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
|
|
||||||
== (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
|
|
||||||
{
|
{
|
||||||
ptrNextNode->ptrNext = cmd_alloc(sizeof(DIRFINDLISTNODE));
|
ptrNextNode->ptrNext = cmd_alloc(sizeof(DIRFINDLISTNODE));
|
||||||
if (ptrNextNode->ptrNext == NULL)
|
if (ptrNextNode->ptrNext == NULL)
|
||||||
|
@ -1548,9 +1515,9 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
QsortFiles(ptrFileArray, 0, dwCount-1, lpFlags);
|
QsortFiles(ptrFileArray, 0, dwCount-1, lpFlags);
|
||||||
|
|
||||||
/* Print Data */
|
/* Print Data */
|
||||||
pszFilePart[-1] = _T('\0'); /* truncate to directory name only */
|
cPathSep = pszFilePart[-1];
|
||||||
|
pszFilePart[-1] = _T('\0'); /* Truncate to directory name only */
|
||||||
DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
|
DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
|
||||||
pszFilePart[-1] = _T('\\');
|
|
||||||
|
|
||||||
if (lpFlags->bRecursive)
|
if (lpFlags->bRecursive)
|
||||||
{
|
{
|
||||||
|
@ -1561,6 +1528,7 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
lpFlags,
|
lpFlags,
|
||||||
FALSE);
|
FALSE);
|
||||||
}
|
}
|
||||||
|
pszFilePart[-1] = cPathSep;
|
||||||
|
|
||||||
/* Free array */
|
/* Free array */
|
||||||
cmd_free(ptrFileArray);
|
cmd_free(ptrFileArray);
|
||||||
|
@ -1601,10 +1569,11 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
|
memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
|
||||||
_tcscpy(&szSubPath[pszFilePart - szFullPath], wfdFileInfo.cFileName);
|
_tcscpy(&szSubPath[pszFilePart - szFullPath], wfdFileInfo.cFileName);
|
||||||
_tcscat(szSubPath, _T("\\"));
|
_tcscat(szSubPath, _T("\\"));
|
||||||
_tcscat(szSubPath, pszFilePart);
|
pszSubFilePart = &szSubPath[_tcslen(szSubPath)];
|
||||||
|
_tcscat(pszSubFilePart, pszFilePart);
|
||||||
|
|
||||||
/* We do the same for the folder */
|
/* We do the same for the folder */
|
||||||
if (DirList(szSubPath, lpFlags) != 0)
|
if (DirList(szSubPath, pszSubFilePart, lpFlags) != 0)
|
||||||
{
|
{
|
||||||
FindClose(hRecSearch);
|
FindClose(hRecSearch);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1618,6 +1587,225 @@ DirList(LPTSTR szPath, /* [IN] The path that dir starts */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
ResolvePattern(
|
||||||
|
IN LPTSTR pszPattern,
|
||||||
|
IN DWORD nBufferLength,
|
||||||
|
OUT LPTSTR pszFullPath,
|
||||||
|
OUT LPTSTR* ppszPatternPart OPTIONAL)
|
||||||
|
{
|
||||||
|
LPTSTR pCurDir, pNextDir, ptr;
|
||||||
|
LPTSTR pszPatternPart;
|
||||||
|
TCHAR szNewPattern[MAX_PATH];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are going to use GetFullPathName() to properly determine the actual
|
||||||
|
* full path from the pattern. However, due to the fact GetFullPathName()
|
||||||
|
* strips parts of the file name component in case the pattern contains
|
||||||
|
* path specification with trailing dots, it is required to perform a
|
||||||
|
* pre-treatment on the pattern and a post-treatment on the obtained path.
|
||||||
|
* This is mandatory in order to use the correct file search criterion.
|
||||||
|
*
|
||||||
|
* One particular case is when the pattern specifies a dots-only directory
|
||||||
|
* followed by either the "." or ".." special directories. In this case the
|
||||||
|
* GetFullPathName() function may completely miss the dots-only directory.
|
||||||
|
* An example is given by the pattern (C-string notation) "\\...\\." .
|
||||||
|
* To cope with this problem we need to partially canonicalize the pattern
|
||||||
|
* by collapsing any "." or ".." special directory that immediately follows
|
||||||
|
* a dots-only directory. We collapse in addition consecutive backslashes.
|
||||||
|
*
|
||||||
|
* Finally, trailing dots are skipped by GetFullPathName(). Therefore
|
||||||
|
* a pattern that matches files with no extension, for example: "*." ,
|
||||||
|
* or: "dir\\noextfile." , are reduced to simply "*" or "dir\\noextfile",
|
||||||
|
* that match files with extensions. Or, a pattern specifying a trailing
|
||||||
|
* dots-only directory: "dir\\..." gets completely ignored and only the
|
||||||
|
* full path to "dir" is returned.
|
||||||
|
* To fix this second problem we need to restore the last part of the path
|
||||||
|
* pattern using the pattern that has been first partially canonicalized.
|
||||||
|
*
|
||||||
|
* Note however that the "." or ".." special directories are always
|
||||||
|
* interpreted correctly by GetFullPathName().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Make a copy of the path pattern */
|
||||||
|
ASSERT(_tcslen(pszPattern) < ARRAYSIZE(szNewPattern));
|
||||||
|
_tcscpy(szNewPattern, pszPattern);
|
||||||
|
pszPattern = szNewPattern;
|
||||||
|
|
||||||
|
TRACE("Original pszPattern: %S\n", pszPattern);
|
||||||
|
|
||||||
|
/* Convert slashes into backslashes */
|
||||||
|
pNextDir = pszPattern;
|
||||||
|
while ((pNextDir = _tcschr(pNextDir, _T('/'))))
|
||||||
|
*pNextDir++ = _T('\\');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find any dots-only directory and collapse any "." or ".." special
|
||||||
|
* directory that immediately follows it.
|
||||||
|
* Note that we just start looking after the first path separator. Indeed,
|
||||||
|
* dots-only directories that are not preceded by a path separator, and so
|
||||||
|
* appear first in the pattern, for example: "...\dir", or: "..." , are
|
||||||
|
* either correctly handled by GetFullPathName() because they are followed
|
||||||
|
* by a non-pathological directory, or because they are handled when we
|
||||||
|
* restore the trailing dots pattern piece in the next step.
|
||||||
|
*/
|
||||||
|
pNextDir = pszPattern;
|
||||||
|
while (pNextDir)
|
||||||
|
{
|
||||||
|
pCurDir = pNextDir;
|
||||||
|
|
||||||
|
/* Find the next path separator in the pattern */
|
||||||
|
pNextDir = _tcschr(pNextDir, _T('\\'));
|
||||||
|
if (!pNextDir)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Ignore the special "." and ".." directories that are correctly handled */
|
||||||
|
if ((pNextDir - pCurDir == 0) ||
|
||||||
|
(pNextDir - pCurDir == 1 && pCurDir[0] == _T('.')) ||
|
||||||
|
(pNextDir - pCurDir == 2 && pCurDir[0] == _T('.') && pCurDir[1] == _T('.')))
|
||||||
|
{
|
||||||
|
/* Found such a directory, ignore */
|
||||||
|
++pNextDir;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether this is a dots-only directory */
|
||||||
|
for (ptr = pCurDir; ptr < pNextDir; ++ptr)
|
||||||
|
{
|
||||||
|
if (*ptr != _T('.'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ptr < pNextDir)
|
||||||
|
{
|
||||||
|
/* Not a dots-only directory, ignore */
|
||||||
|
++pNextDir;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip any consecutive backslashes */
|
||||||
|
for (ptr = pNextDir; *ptr == _T('\\'); ++ptr) ;
|
||||||
|
|
||||||
|
/* pCurDir is a dots-only directory, perform partial canonicalization */
|
||||||
|
|
||||||
|
/* Remove any following "." directory */
|
||||||
|
if (ptr[0] == _T('.') && (ptr[1] == _T('\\') || ptr[1] == 0))
|
||||||
|
{
|
||||||
|
memmove(pNextDir, ptr + 1, (_tcslen(ptr + 1) + 1) * sizeof(TCHAR));
|
||||||
|
}
|
||||||
|
/* Remove any following ".." directory */
|
||||||
|
else if (ptr[0] == _T('.') && ptr[1] == _T('.') && (ptr[2] == _T('\\') || ptr[2] == 0))
|
||||||
|
{
|
||||||
|
/* Skip any consecutive backslashes before the next directory */
|
||||||
|
for (ptr = ptr + 2; *ptr == _T('\\'); ++ptr) ;
|
||||||
|
|
||||||
|
memmove(pCurDir, ptr, (_tcslen(ptr) + 1) * sizeof(TCHAR));
|
||||||
|
pNextDir = pCurDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++pNextDir;
|
||||||
|
|
||||||
|
/* Collapse consecutive backslashes */
|
||||||
|
if (ptr > pNextDir)
|
||||||
|
memmove(pNextDir, ptr, (_tcslen(ptr) + 1) * sizeof(TCHAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An empty pattern means we enumerate all files in the current directory */
|
||||||
|
if (!*pszPattern)
|
||||||
|
_tcscpy(pszPattern, _T("*"));
|
||||||
|
|
||||||
|
TRACE("New pszPattern: %S\n", pszPattern);
|
||||||
|
|
||||||
|
/* Create the full path */
|
||||||
|
if (GetFullPathName(pszPattern, nBufferLength, pszFullPath, &pszPatternPart) == 0)
|
||||||
|
{
|
||||||
|
_tcscpy(pszFullPath, pszPattern);
|
||||||
|
pszPatternPart = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("pszFullPath (1): %S\n", pszFullPath);
|
||||||
|
TRACE("pszPatternPart (1): %S\n", pszPatternPart);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the correct file name component in case the pattern contained
|
||||||
|
* trailing dots that have been skipped by GetFullPathName().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Find the last path separator in the original szPath */
|
||||||
|
pNextDir = _tcsrchr(pszPattern, _T('\\'));
|
||||||
|
if (pNextDir)
|
||||||
|
{
|
||||||
|
/* Skip past the separator and look at the path */
|
||||||
|
++pNextDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The pattern is the path we need to look at */
|
||||||
|
pNextDir = pszPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When pszPatternPart == NULL this means that pszFullPath should be a
|
||||||
|
* directory; however it might have happened that the original pattern
|
||||||
|
* was specifying a dots-only directory, that has been stripped off by
|
||||||
|
* GetFullPathName(). In both these cases we need to restore these as
|
||||||
|
* they are part of the actual directory path; the exception being if
|
||||||
|
* these are the special "." or ".." directories.
|
||||||
|
*/
|
||||||
|
if (pszPatternPart == NULL)
|
||||||
|
{
|
||||||
|
ASSERT(pszFullPath[_tcslen(pszFullPath)-1] == _T('\\'));
|
||||||
|
|
||||||
|
/* Anything NOT being "." or ".." (the special directories) must be fully restored */
|
||||||
|
if (*pNextDir &&
|
||||||
|
(_tcsicmp(pNextDir, _T(".")) != 0) &&
|
||||||
|
(_tcsicmp(pNextDir, _T("..")) != 0))
|
||||||
|
{
|
||||||
|
pszPatternPart = &pszFullPath[_tcslen(pszFullPath)];
|
||||||
|
_tcscpy(pszPatternPart, pNextDir);
|
||||||
|
pszPatternPart = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_tcscmp(pNextDir, pszPatternPart) != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For example, pszPatternPart == "." or ".." and we do not need to
|
||||||
|
* do anything for these, or pszPatternPart == "dir\\noextfile." and
|
||||||
|
* we need to restore all the trailing points.
|
||||||
|
*/
|
||||||
|
TRACE("pszPatternPart: %S is DIFFERENT from file criterion: %S\n", pszPatternPart, pNextDir);
|
||||||
|
|
||||||
|
/* Anything NOT being "." or ".." (the special directories) must be fully restored */
|
||||||
|
if (*pNextDir &&
|
||||||
|
(_tcsicmp(pNextDir, _T(".")) != 0) &&
|
||||||
|
(_tcsicmp(pNextDir, _T("..")) != 0))
|
||||||
|
{
|
||||||
|
/* Restore the correct file criterion */
|
||||||
|
_tcscpy(pszPatternPart, pNextDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("pszFullPath (2): %S\n", pszFullPath);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no wildcard or file was specified and this is a directory,
|
||||||
|
* display all files in it.
|
||||||
|
*/
|
||||||
|
if (pszPatternPart == NULL || IsExistingDirectory(pszFullPath))
|
||||||
|
{
|
||||||
|
pszPatternPart = &pszFullPath[_tcslen(pszFullPath)];
|
||||||
|
if (pszPatternPart[-1] != _T('\\'))
|
||||||
|
*pszPatternPart++ = _T('\\');
|
||||||
|
_tcscpy(pszPatternPart, _T("*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("pszPatternPart (2): %S\n", pszPatternPart);
|
||||||
|
|
||||||
|
if (ppszPatternPart)
|
||||||
|
*ppszPatternPart = pszPatternPart;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dir
|
* dir
|
||||||
*
|
*
|
||||||
|
@ -1627,10 +1815,11 @@ INT
|
||||||
CommandDir(LPTSTR rest)
|
CommandDir(LPTSTR rest)
|
||||||
{
|
{
|
||||||
TCHAR dircmd[MAX_PATH]; /* A variable to store the DIRCMD environment variable */
|
TCHAR dircmd[MAX_PATH]; /* A variable to store the DIRCMD environment variable */
|
||||||
TCHAR path[MAX_PATH];
|
|
||||||
TCHAR prev_volume[MAX_PATH];
|
TCHAR prev_volume[MAX_PATH];
|
||||||
|
TCHAR szFullPath[MAX_PATH];
|
||||||
LPTSTR* params = NULL;
|
LPTSTR* params = NULL;
|
||||||
LPTSTR pszFilePart;
|
LPTSTR pszFilePart;
|
||||||
|
TCHAR cPathSep;
|
||||||
INT entries = 0;
|
INT entries = 0;
|
||||||
UINT loop = 0;
|
UINT loop = 0;
|
||||||
DIRSWITCHFLAGS stFlags;
|
DIRSWITCHFLAGS stFlags;
|
||||||
|
@ -1729,40 +1918,38 @@ CommandDir(LPTSTR rest)
|
||||||
ChangedVolume = TRUE;
|
ChangedVolume = TRUE;
|
||||||
|
|
||||||
if (!stFlags.bBareFormat &&
|
if (!stFlags.bBareFormat &&
|
||||||
GetVolumePathName(params[loop], path, ARRAYSIZE(path)))
|
GetVolumePathName(params[loop], szFullPath, ARRAYSIZE(szFullPath)))
|
||||||
{
|
{
|
||||||
if (!_tcscmp(path, prev_volume))
|
if (!_tcscmp(szFullPath, prev_volume))
|
||||||
ChangedVolume = FALSE;
|
ChangedVolume = FALSE;
|
||||||
else
|
else
|
||||||
_tcscpy(prev_volume, path);
|
_tcscpy(prev_volume, szFullPath);
|
||||||
}
|
|
||||||
else if (GetFullPathName(params[loop], ARRAYSIZE(path), path, &pszFilePart) != 0)
|
|
||||||
{
|
|
||||||
if (pszFilePart != NULL)
|
|
||||||
*pszFilePart = _T('\0');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_tcscpy(path, params[loop]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resolve the pattern */
|
||||||
|
ResolvePattern(params[loop], ARRAYSIZE(szFullPath), szFullPath, &pszFilePart);
|
||||||
|
|
||||||
/* Print the header */
|
/* Print the header */
|
||||||
|
cPathSep = pszFilePart[-1];
|
||||||
|
pszFilePart[-1] = _T('\0'); /* Truncate to directory name only */
|
||||||
if (ChangedVolume && !stFlags.bBareFormat &&
|
if (ChangedVolume && !stFlags.bBareFormat &&
|
||||||
!PrintDirectoryHeader(params[loop], &stFlags))
|
!PrintDirectoryHeader(szFullPath, &stFlags))
|
||||||
{
|
{
|
||||||
nErrorLevel = 1;
|
nErrorLevel = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
pszFilePart[-1] = cPathSep;
|
||||||
|
|
||||||
/* Perform the actual directory listing */
|
/* Perform the actual directory listing */
|
||||||
if (DirList(params[loop], &stFlags) != 0)
|
if (DirList(szFullPath, pszFilePart, &stFlags) != 0)
|
||||||
{
|
{
|
||||||
nErrorLevel = 1;
|
nErrorLevel = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the footer */
|
/* Print the footer */
|
||||||
PrintSummary(path,
|
pszFilePart[-1] = _T('\0'); /* Truncate to directory name only */
|
||||||
|
PrintSummary(szFullPath,
|
||||||
recurse_file_cnt,
|
recurse_file_cnt,
|
||||||
recurse_dir_cnt,
|
recurse_dir_cnt,
|
||||||
recurse_bytes,
|
recurse_bytes,
|
||||||
|
|
Loading…
Reference in a new issue