📄 dir.c
字号:
/* Bare format */
DirPrintBareList(ptrFiles, dwCount, szCurPath, lpFlags);
}
else if(lpFlags->bShortName)
{
/* New list style / Short names */
DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
}
else if(lpFlags->bWideListColSort || lpFlags->bWideList)
{
/* Wide list */
DirPrintWideList(ptrFiles, dwCount, szCurPath, lpFlags);
}
else if (lpFlags->bNewLongList )
{
/* New list style*/
DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
}
else
{
/* If nothing is selected old list is the default */
DirPrintOldList(ptrFiles, dwCount, szCurPath, lpFlags);
}
}
/*
* CompareFiles
*
* Compares 2 files based on the order criteria
*/
static BOOL
CompareFiles(LPWIN32_FIND_DATA lpFile1, /* [IN] A pointer to WIN32_FIND_DATA of file 1 */
LPWIN32_FIND_DATA lpFile2, /* [IN] A pointer to WIN32_FIND_DATA of file 2 */
LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we use to list */
{
ULARGE_INTEGER u64File1;
ULARGE_INTEGER u64File2;
int i;
long iComp = 0; /* The comparison result */
/* Calculate critiries by order given from user */
for (i = 0;i < lpFlags->stOrderBy.sCriteriaCount;i++)
{
/* Calculate criteria */
switch(lpFlags->stOrderBy.eCriteria[i])
{
case ORDER_SIZE: /* Order by size /o:s */
/* concat the 32bit integers to a 64bit */
u64File1.LowPart = lpFile1->nFileSizeLow;
u64File1.HighPart = lpFile1->nFileSizeHigh;
u64File2.LowPart = lpFile2->nFileSizeLow;
u64File2.HighPart = lpFile2->nFileSizeHigh;
/* In case that differnce is too big for a long */
if (u64File1.QuadPart < u64File2.QuadPart)
iComp = -1;
else if (u64File1.QuadPart > u64File2.QuadPart)
iComp = 1;
else
iComp = 0;
break;
case ORDER_DIRECTORY: /* Order by directory attribute /o:g */
iComp = ((lpFile2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
(lpFile1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
break;
case ORDER_EXTENSION: /* Order by extension name /o:e */
iComp = _tcsicmp(getExt(lpFile1->cFileName),getExt(lpFile2->cFileName));
break;
case ORDER_NAME: /* Order by filename /o:n */
iComp = _tcsicmp(lpFile1->cFileName, lpFile2->cFileName);
break;
case ORDER_TIME: /* Order by file's time /o:t */
/* We compare files based on the time field selected by /t */
switch(lpFlags->stTimeField.eTimeField)
{
case TF_CREATIONDATE:
/* concat the 32bit integers to a 64bit */
u64File1.LowPart = lpFile1->ftCreationTime.dwLowDateTime;
u64File1.HighPart = lpFile1->ftCreationTime.dwHighDateTime ;
u64File2.LowPart = lpFile2->ftCreationTime.dwLowDateTime;
u64File2.HighPart = lpFile2->ftCreationTime.dwHighDateTime ;
break;
case TF_LASTACCESSEDDATE :
/* concat the 32bit integers to a 64bit */
u64File1.LowPart = lpFile1->ftLastAccessTime.dwLowDateTime;
u64File1.HighPart = lpFile1->ftLastAccessTime.dwHighDateTime ;
u64File2.LowPart = lpFile2->ftLastAccessTime.dwLowDateTime;
u64File2.HighPart = lpFile2->ftLastAccessTime.dwHighDateTime ;
break;
case TF_MODIFIEDDATE:
/* concat the 32bit integers to a 64bit */
u64File1.LowPart = lpFile1->ftLastWriteTime.dwLowDateTime;
u64File1.HighPart = lpFile1->ftLastWriteTime.dwHighDateTime ;
u64File2.LowPart = lpFile2->ftLastWriteTime.dwLowDateTime;
u64File2.HighPart = lpFile2->ftLastWriteTime.dwHighDateTime ;
break;
}
/* In case that differnce is too big for a long */
if (u64File1.QuadPart < u64File2.QuadPart)
iComp = -1;
else if (u64File1.QuadPart > u64File2.QuadPart)
iComp = 1;
else
iComp = 0;
break;
}
/* Reverse if desired */
if (lpFlags->stOrderBy.bCriteriaRev[i])
iComp *= -1;
/* If that criteria was enough for distinguishing
the files/dirs,there is no need to calculate the others*/
if (iComp != 0) break;
}
/* Translate the value of iComp to boolean */
if (iComp > 0)
return TRUE;
else
return FALSE;
}
/*
* QsortFiles
*
* Sort files by the order criterias using quicksort method
*/
static VOID
QsortFiles(LPWIN32_FIND_DATA ptrArray[], /* [IN/OUT] The array with file info pointers */
int i, /* [IN] The index of first item in array */
int j, /* [IN] The index to last item in array */
LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we will use to sort */
{
LPWIN32_FIND_DATA lpTemp; /* A temporary pointer */
int First, Last, Temp;
BOOL Way;
if (i < j)
{
First = i;
Last = j;
Way = TRUE;
while (i != j)
{
if (Way == CompareFiles(ptrArray[i], ptrArray[j], lpFlags))
{
/* Swap the pointers of the array */
lpTemp = ptrArray[i];
ptrArray[i]= ptrArray[j];
ptrArray[j] = lpTemp;
/* Swap the indexes for inverting sorting */
Temp = i;
i = j;
j =Temp;
Way = !Way;
}
j += (!Way - Way);
}
QsortFiles(ptrArray,First, i-1, lpFlags);
QsortFiles(ptrArray,i+1,Last, lpFlags);
}
}
/*
* DirList
*
* The functions that does everything except for printing results
*/
static INT
DirList(LPTSTR szPath, /* [IN] The path that dir starts */
LPTSTR szFilespec, /* [IN] The type of file that we are looking for */
LPINT pLine, /* FIXME: Maybe used for paginating */
LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags of the listing */
{
HANDLE hSearch; /* The handle of the search */
HANDLE hRecSearch; /* The handle for searching recursivly */
WIN32_FIND_DATA wfdFileInfo; /* The info of file that found */
LPWIN32_FIND_DATA * ptrFileArray; /* An array of pointers with all the files */
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\ */
DWORD dwCount; /* A counter of files found in directory */
DWORD dwCountFiles; /* Counter for files */
DWORD dwCountDirs; /* Counter for directories */
ULARGE_INTEGER u64CountBytes; /* Counter for bytes */
ULARGE_INTEGER u64Temp; /* A temporary counter */
/* Initialize Variables */
ptrStartNode = NULL;
ptrNextNode = NULL;
dwCount = 0;
dwCountFiles = 0;
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);
/* Prepare the linked list, first node is allocated */
ptrStartNode = malloc(sizeof(DIRFINDLISTNODE));
if (ptrStartNode == NULL)
{
#ifdef _DEBUG
ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrStartNode!\n"));
#endif
return 1; /* Error cannot allocate memory for 1st object */
}
ptrNextNode = ptrStartNode;
/* Collect the results for the current folder */
hSearch = FindFirstFile(szFullFileSpec, &wfdFileInfo);
do
{
if (hSearch != INVALID_HANDLE_VALUE)
{
/* Here we filter all the specified attributes */
if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
== (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
{
ptrNextNode->ptrNext = malloc(sizeof(DIRFINDLISTNODE));
if (ptrNextNode->ptrNext == NULL)
{
#ifdef _DEBUG
ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n"));
#endif
while (ptrStartNode)
{
ptrNextNode = ptrStartNode->ptrNext;
free(ptrStartNode);
ptrStartNode = ptrNextNode;
dwCount --;
}
return 1;
}
/* If malloc fails we go to next file in hope it works,
without braking the linked list! */
if (ptrNextNode->ptrNext)
{
/* Copy the info of search at linked list */
memcpy(&ptrNextNode->ptrNext->stFindInfo,
&wfdFileInfo,
sizeof(WIN32_FIND_DATA));
/* If lower case is selected do it here */
if (lpFlags->bLowerCase)
{
_tcslwr(ptrNextNode->ptrNext->stFindInfo.cAlternateFileName);
_tcslwr(ptrNextNode->ptrNext->stFindInfo.cFileName);
}
/* Continue at next node at linked list */
ptrNextNode = ptrNextNode->ptrNext;
dwCount ++;
/* Grab statistics */
if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* Directory */
dwCountDirs++;
}
else
{
/* File */
dwCountFiles++;
u64Temp.HighPart = wfdFileInfo.nFileSizeHigh;
u64Temp.LowPart = wfdFileInfo.nFileSizeLow;
u64CountBytes.QuadPart += u64Temp.QuadPart;
}
}
}
}
}while(FindNextFile(hSearch, &wfdFileInfo));
FindClose(hSearch);
/* Terminate list */
ptrNextNode->ptrNext = NULL;
/* Calculate and allocate space need for making an array of pointers */
ptrFileArray = malloc(sizeof(LPWIN32_FIND_DATA) * dwCount);
if (ptrFileArray == NULL)
{
#ifdef _DEBUG
ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrFileArray!\n"));
#endif
while (ptrStartNode)
{
ptrNextNode = ptrStartNode->ptrNext;
free(ptrStartNode);
ptrStartNode = ptrNextNode;
dwCount --;
}
return 1;
}
/*
* Create an array of pointers from the linked list
* this will be used to sort and print data, rather than the list
*/
ptrNextNode = ptrStartNode;
dwCount = 0;
while (ptrNextNode->ptrNext)
{
*(ptrFileArray + dwCount) = &ptrNextNode->ptrNext->stFindInfo;
ptrNextNode = ptrNextNode->ptrNext;
dwCount++;
}
/* Sort Data if requested*/
if (lpFlags->stOrderBy.sCriteriaCount > 0)
QsortFiles(ptrFileArray, 0, dwCount-1,lpFlags);
/* Print Data */
DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
/* Free array */
free(ptrFileArray);
if (CheckCtrlBreak(BREAK_INPUT))
return 1;
/* Add statistics to recursive statistics*/
recurse_dir_cnt += dwCountDirs;
recurse_file_cnt += dwCountFiles;
recurse_bytes.QuadPart += u64CountBytes.QuadPart;
/* Do the recursive job if requested
the recursive is be done on ALL(indepent of their attribs)
directoried of the current one.*/
if (lpFlags->bRecursive)
{
/* The new search is involving any *.* file */
_tcscpy(szFullFileSpec, szFullPath);
_tcscat(szFullFileSpec, _T("*.*"));
hRecSearch = FindFirstFile (szFullFileSpec, &wfdFileInfo);
do
{
if (hRecSearch != INVALID_HANDLE_VALUE)
{
/* We search for directories other than "." and ".." */
if ((_tcsicmp(wfdFileInfo.cFileName, _T(".")) != 0) &&
(_tcsicmp(wfdFileInfo.cFileName, _T("..")) != 0 ) &&
(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, pLine,lpFlags) != 0)
{
return 1;
}
}
}
}while(FindNextFile(hRecSearch,&wfdFileInfo));
FindClose(hRecSearch);
}
/* Free linked list */
while (ptrStartNode)
{
ptrNextNode = ptrStartNode->ptrNext;
free(ptrStartNode);
ptrStartNode = ptrNextNode;
dwCount --;
}
return 0;
}
/*
* dir
*
* internal dir command
*/
INT
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;
INT entries = 0;
INT nLine = 0;
UINT loop = 0;
DIRSWITCHFLAGS stFlags;
/* Initialize variables */
cDrive = 0;
recurse_dir_cnt = 0L;
recurse_file_cnt = 0L;
recurse_bytes.QuadPart = 0;
/* Initialize Switch Flags < Default switches are setted here!> */
stFlags.b4Digit = TRUE;
stFlags.bBareFormat = FALSE;
stFlags.bLowerCase = FALSE;
stFlags.bNewLongList = TRUE;
stFlags.bPause = FALSE;
stFlags.bRecursive = FALSE;
stFlags.bShortName = FALSE;
stFlags.bTSeperator = TRUE;
stFlags.bUser = FALSE;
stFlags.bWideList = FALSE;
stFlags.bWideListColSort = FALSE;
stFlags.stTimeField.eTimeField = TF_MODIFIEDDATE;
stFlags.stTimeField.bUnSet = FALSE;
stFlags.stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
stFlags.stAttribs.dwAttribVal = 0L;
stFlags.stAttribs.bUnSet = FALSE;
stFlags.stOrderBy.sCriteriaCount = 0;
stFlags.stOrderBy.bUnSet = FALSE;
nErrorLevel = 0;
/* read the parameters from the DIRCMD environment variable */
if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
if (!DirReadParam(dircmd, ¶ms, &entries, &stFlags))
{
nErrorLevel = 1;
return 1;
}
/* read the parameters */
if (!DirReadParam(rest, ¶ms, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
{
nErrorLevel = 1;
return 1;
}
/* default to current directory */
if(entries == 0) {
if(!add_entry(&entries, ¶ms, _T("."))) {
nErrorLevel = 1;
return 1;
}
}
for(loop = 0; loop < entries; loop++)
{
/* parse the directory info */
if (DirParsePathspec (params[loop], szPath, szFilespec) || CheckCtrlBreak(BREAK_INPUT))
{
nErrorLevel = 1;
return 1;
}
/* <Debug :>
Uncomment this to show the final state of switch flags*/
#ifdef _DEBUG
{
int i;
ConOutPrintf(_T("Attributes mask/value %x/%x\n"),stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal );
ConOutPrintf(_T("(B) Bare format : %i\n"), stFlags.bBareFormat );
ConOutPrintf(_T("(C) Thousand : %i\n"), stFlags.bTSeperator );
ConOutPrintf(_T("(W) Wide list : %i\n"), stFlags.bWideList );
ConOutPrintf(_T("(D) Wide list sort by column : %i\n"), stFlags.bWideListColSort );
ConOutPrintf(_T("(L) Lowercase : %i\n"), stFlags.bLowerCase );
ConOutPrintf(_T("(N) New : %i\n"), stFlags.bNewLongList );
ConOutPrintf(_T("(O) Order : %i\n"), stFlags.stOrderBy.sCriteriaCount );
for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
ConOutPrintf(_T(" Order Criteria [%i]: %i (Reversed: %i)\n"),i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
ConOutPrintf(_T("(P) Pause : %i\n"), stFlags.bPause );
ConOutPrintf(_T("(Q) Owner : %i\n"), stFlags.bUser );
ConOutPrintf(_T("(S) Recursive : %i\n"), stFlags.bRecursive );
ConOutPrintf(_T("(T) Time field : %i\n"), stFlags.stTimeField.eTimeField );
ConOutPrintf(_T("(X) Short names : %i\n"), stFlags.bShortName );
ConOutPrintf(_T("Parameter : %s\n"), params[loop] );
}
#endif
/* Print the drive header if the drive changed */
if(cDrive != szPath[0] && !stFlags.bBareFormat) {
if (!PrintDirectoryHeader (szPath, &nLine, &stFlags)) {
nErrorLevel = 1;
return 1;
}
cDrive = szPath[0];
}
/* do the actual dir */
if (DirList (szPath, szFilespec, &nLine, &stFlags))
{
nErrorLevel = 1;
return 1;
}
}
/* print the footer */
PrintSummary(szPath,
recurse_file_cnt,
recurse_dir_cnt,
recurse_bytes,
&nLine,
&stFlags);
return 0;
}
#endif
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -