27-Feb-2005 (Konstantinos Paliouras squarious@gmail.com) Implemented all the switches that were missing, and made the ros dir very similar to windows dir. Major part of the code is rewritten. /p is removed, to be rewriten in the main cmd code. Modified: trunk/reactos/subsys/system/cmd/dir.c Modified: trunk/reactos/subsys/system/cmd/precomp.h _____
Modified: trunk/reactos/subsys/system/cmd/dir.c --- trunk/reactos/subsys/system/cmd/dir.c 2005-03-08 15:02:41 UTC (rev 13876) +++ trunk/reactos/subsys/system/cmd/dir.c 2005-03-08 15:08:01 UTC (rev 13877) @@ -119,6 +119,13 @@
* * 30-Apr-2004 (Filip Navara xnavara@volny.cz) * Fix /w to print long names. + * + * 27-Feb-2005 (Konstantinos Paliouras squarious@gmail.com) + * Implemented all the switches that were missing, and made + * the ros dir very similar to windows dir. Major part of + * the code is rewritten. /p is removed, to be rewriten in + * the main cmd code. + * */
#include "precomp.h" @@ -126,21 +133,62 @@ #ifdef INCLUDE_CMD_DIR
-/* flag definitions */ -enum + +/* Time Field enumeration */ +enum ETimeField { - DIR_RECURSE = 0x0001, - DIR_PAGE = 0x0002, - DIR_WIDE = 0x0004, /* Rob Lake */ - DIR_BARE = 0x0008, /* Rob Lake */ - DIR_ALL = 0x0010, /* Rob Lake */ - DIR_LWR = 0x0020, /* Rob Lake */ - DIR_SORT = 0x0040, /* /O sort */ - DIR_NEW = 0x0080, /* /N new style */ - DIR_FOUR = 0x0100 /* /4 four digit year */ + TF_CREATIONDATE = 0, + TF_MODIFIEDDATE = 1, + TF_LASTACCESSEDDATE = 2 };
+/* Ordered by enumeration */ +enum EOrderBy +{ + ORDER_NAME = 0, + ORDER_SIZE = 1, + ORDER_DIRECTORY = 2, + ORDER_EXTENSION = 3, + ORDER_TIME = 4 +};
+/* The struct for holding the switches */ +typedef struct TDirSwitchesFlags +{ + BOOL bBareFormat; /* Bare Format */ + BOOL bTSeperator; /* Thousands seperator */ + BOOL bWideList; /* Wide list format */ + BOOL bWideListColSort; /* Wide list format but sorted by column */ + BOOL bLowerCase; /* Uses lower case */ + BOOL bNewLongList; /* New long list */ + BOOL bPause; /* Pause per page */ + BOOL bUser; /* Displays the owner of file */ + BOOL bRecursive; /* Displays files in specified directory and all sub */ + BOOL bShortName; /* Displays the sort name of files if exist */ + BOOL b4Digit; /* Four digit year */ + struct + { + DWORD dwAttribVal; /* The desired state of attribute */ + DWORD dwAttribMask; /* Which attributes to check */ + BOOL bUnSet; /* A helper flag if "-" was given with the switch */ + BOOL bParSetted; /* A helper flag if parameters of switch were given */ + } stAttribs; /* Displays files with this attributes only */ + struct + { + enum EOrderBy eCriteria[3]; /* Criterias used to order by */ + BOOL bCriteriaRev[3]; /* If the criteria is in reversed order */ + short sCriteriaCount; /* The quantity of criterias */ + BOOL bUnSet; /* A helper flag if "-" was given with the switch */ + BOOL bParSetted; /* A helper flag if parameters of switch were given */ + } stOrderBy; /* Ordered by criterias */ + struct + { + enum ETimeField eTimeField; /* The time field that will be used for */ + BOOL bUnSet; /* A helper flag if "-" was given with the switch */ + BOOL bParSetted; /* A helper flag if parameters of switch were given */ + } stTimeField; /* The time field to display or use for sorting */ +}DIRSWITCHFLAGS, * LPDIRSWITCHFLAGS; + typedef BOOL STDCALL (*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
@@ -158,177 +206,382 @@ * displays help screen for dir * Rob Lake */ -static VOID Help (VOID) +static VOID + DirHelp (VOID) { - ConOutPuts(_T("Displays a list of files and subdirectories in a directory.\n" - "\n" - "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n" - "\n" - " [drive:][path][filename]\n" - " Specifies drive, directory, and/or files to list.\n" - "\n" - " /A Displays files with HIDDEN SYSTEM attributes\n" - " default is ARCHIVE and READ ONLY\n" - " /B Uses bare format (no heading information or summary).\n" - " /L Uses lowercase.\n" - " /N New long list format where filenames are on the far right.\n" - " /S Displays files in specified directory and all subdirectories\n" - " /P Pauses after each screen full\n" - " /W Prints in wide format\n" - " /4 Display four digit years.\n" - "\n" - "Switches may be present in the DIRCMD environment variable. Use\n" - "of the - (hyphen) can turn off defined swtiches. Ex. /-W would\n" - "turn off printing in wide format.\n" + ConOutPuts(_T( + "DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]\n" + " [/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]\n" + "\n" + " [drive:][path][filename]\n" + " Specifies drive, directory, and/or files to list.\n" + "\n" + " /A Displays files with specified attributes.\n" + " attributes D Directories R Read-only files\n" + " H Hidden files A Files ready for archiving\n" + " S System files - Prefix meaning not\n" + " /B Uses bare format (no heading information or summary).\n" + " /C Display the thousand separator in file sizes. This is the\n" + " default. Use /-C to disable display of separator.\n" + " /D Same as wide but files are list sorted by column.\n" + " /L Uses lowercase.\n" + " /N New long list format where filenames are on the far right.\n" + " /O List by files in sorted order.\n" + " sortorder N By name (alphabetic) S By size (smallest first)\n" + " E By extension (alphabetic) D By date/time (oldest first)\n" + " G Group directories first - Prefix to reverse order\n" + " /P Pauses after each screenful of information.\n" + " /Q Display the owner of the file.\n" + " /S Displays files in specified directory and all subdirectories.\n" + " /T Controls which time field displayed or used for sorting\n" + " timefield C Creation\n" + " A Last Access\n" + " W Last Written\n" + " /W Uses wide list format.\n" + " /X This displays the short names generated for non-8dot3 file\n" + " names. The format is that of /N with the short name inserted\n" + " before the long name. If no short name is present, blanks are\n" + " displayed in its place.\n" + " /4 Displays four-digit years\n" + " \n" + "Switches may be preset in the DIRCMD environment variable. Override\n" + "preset switches by prefixing any switch with - (hyphen)--for example, /-W.\n" )); }
+ /* - * DirReadParam + * DirReadParameters * - * read the parameters from the command line + * Parse the parameters and switches of the command line and exports them */ -static BOOL -DirReadParam (LPTSTR line, LPTSTR *param, LPDWORD lpFlags) +static BOOL +DirReadParam (LPTSTR line, /* [IN] The line with the parameters & switches */ + LPTSTR *param, /* [OUT] The parameters after parsing */ + LPDIRSWITCHFLAGS lpFlags /* [IN/OUT] The flags after calculating switches */ + ) { - INT slash = 0; +TCHAR cCurSwitch; /* The current switch */ +TCHAR cCurChar; /* Current examing character */ +TCHAR cCurUChar; /* Current upper examing character */ +BOOL bNegative; /* Negative switch */ +BOOL bPNegative; /* Negative switch parameter */ +BOOL bIntoQuotes; /* A flag showing if we are in quotes (") */ +LPTSTR ptrLast; /* A pointer to the last character of param */
- if (!line) - return TRUE; + /* Initialize variables; */ + cCurSwitch = _T(' '); + bNegative = FALSE; + bPNegative = FALSE; + bIntoQuotes = FALSE;
+ /* No parameters yet */ *param = NULL; + ptrLast = NULL; + + /* We suppose that switch parameters + were given to avoid setting them to default + if the switch was not given */ + lpFlags->stAttribs.bParSetted = TRUE; + lpFlags->stOrderBy.bParSetted = TRUE; + lpFlags->stTimeField.bParSetted = TRUE;
- /* scan the command line, processing switches */ + /* Main Loop (see README_DIR.txt) */ + /* scan the command line char per char, and we process its char */ while (*line) { - /* process switch */ - if (*line == _T('/') || slash) + /* we save current character as it is and its upper case */ + cCurChar = *line; + cCurUChar = _toupper(*line); + + /* 1st section (see README_DIR.txt) */ + /* When a switch is expecting */ + if (cCurSwitch == _T('/')) { - if (!slash) - line++; - slash = 0; - if (*line == _T('-')) - { - line++; - if (_totupper (*line) == _T('S')) - *lpFlags &= ~DIR_RECURSE; - else if (_totupper (*line) == _T('P')) - *lpFlags &= ~DIR_PAGE; - else if (_totupper (*line) == _T('W')) - *lpFlags &= ~DIR_WIDE; - else if (_totupper (*line) == _T('B')) - *lpFlags &= ~DIR_BARE; - else if (_totupper (*line) == _T('A')) - *lpFlags &= ~DIR_ALL; - else if (_totupper (*line) == _T('L')) - *lpFlags &= ~DIR_LWR; - else if (_totupper (*line) == _T('N')) - *lpFlags &= ~DIR_NEW; - else if (_totupper (*line) == _T('O')) - *lpFlags &= ~DIR_SORT; - else if (_totupper (*line) == _T('4')) - *lpFlags &= ~DIR_FOUR; - else + if ((cCurUChar == _T('A')) ||(cCurUChar == _T('T')) || (cCurUChar == _T('O'))) + { + cCurSwitch = cCurUChar; + switch (cCurUChar) { - error_invalid_switch ((TCHAR)_totupper (*line)); - return FALSE; + case _T('A'): + lpFlags->stAttribs.bUnSet = bNegative; + lpFlags->stAttribs.bParSetted = FALSE; + break; + case _T('T'): + lpFlags->stTimeField.bUnSet = bNegative; + lpFlags->stTimeField.bParSetted = FALSE; + break; + case _T('O'): + lpFlags->stOrderBy.bUnSet = bNegative; + lpFlags->stOrderBy.bParSetted = FALSE; + break; } - line++; - continue; } - else + else if (cCurUChar == _T('L')) + lpFlags->bLowerCase = ! bNegative; + else if (cCurUChar == _T('B')) + lpFlags->bBareFormat = ! bNegative; + else if (cCurUChar == _T('C')) + lpFlags->bTSeperator = ! bNegative; + else if (cCurUChar == _T('W')) + lpFlags->bWideList = ! bNegative; + else if (cCurUChar == _T('D')) + lpFlags->bWideListColSort = ! bNegative; + else if (cCurUChar == _T('N')) + lpFlags->bNewLongList = ! bNegative; + else if (cCurUChar == _T('P')) + lpFlags->bPause = ! bNegative; + else if (cCurUChar == _T('Q')) + lpFlags->bUser = ! bNegative; + else if (cCurUChar == _T('S')) + lpFlags->bRecursive = ! bNegative; + else if (cCurUChar == _T('X')) + lpFlags->bShortName = ! bNegative; + else if (cCurChar == _T('4')) + lpFlags->b4Digit = ! bNegative; + else if (cCurChar == _T('?')) { - if (_totupper (*line) == _T('S')) - *lpFlags |= DIR_RECURSE; - else if (_totupper (*line) == _T('P')) - *lpFlags |= DIR_PAGE; - else if (_totupper (*line) == _T('W')) - *lpFlags |= DIR_WIDE; - else if (_totupper (*line) == _T('B')) - *lpFlags |= DIR_BARE; - else if (_totupper (*line) == _T('A')) - *lpFlags |= DIR_ALL; - else if (_totupper (*line) == _T('L')) - *lpFlags |= DIR_LWR; - else if (_totupper (*line) == _T('N')) - *lpFlags |= DIR_NEW; - else if (_totupper (*line) == _T('O')) - *lpFlags |= DIR_SORT; - else if (_totupper (*line) == _T('4')) - *lpFlags |= DIR_FOUR; - else if (*line == _T('?')) + DirHelp(); + return FALSE; + } + else if (cCurChar == _T('-')) + bNegative = TRUE; + else + { + error_invalid_switch ((TCHAR)_totupper (*line)); + return FALSE; + } + + /* We check if we calculated the negative value and realese the flag */ + if ((cCurChar != _T('-')) && bNegative) + bNegative = FALSE; + + /* if not a,o,t or - option then next parameter is not a switch */ + if ((cCurSwitch == _T('/')) && (!bNegative)) + cCurSwitch = _T(' '); + + } + /* 2nd section (see README_DIR.txt) */ + /* We are expecting parameter or the unknown */ + else if ((cCurSwitch == _T(' ')) || (cCurSwitch == _T('P'))) + { + if (cCurChar == _T('/')) + cCurSwitch = _T('/'); + + /* Process a spacer */ + else if (cCurChar == _T(' ')) + { + if (!bIntoQuotes) { - Help(); - return FALSE; - } - else + cCurSwitch = _T(' '); + if ((*param) && !(ptrLast)) + ptrLast = line; + } + + } + /* Process a quote */ + else if (cCurChar == _T('"')) + { + bIntoQuotes = !bIntoQuotes; + if (!bIntoQuotes) ptrLast = line; + } + /* Process a character for parameter */ + else + { + if ((cCurSwitch == _T(' ')) && (*param)) { - error_invalid_switch ((TCHAR)_totupper (*line)); + error_too_many_parameters(line); return FALSE; } - line++; - continue; + cCurSwitch = _T('P'); + if (!(*param)) + *param = line; } + } - - /* process parameter */ - if (!_istspace (*line)) + /* 3rd section (see README_DIR.txt) */ + /* We are waiting for switch parameters */ + else { - if (*param) + /* Check if there are no more switch parameters */ + if ((cCurChar == _T('/')) || ( cCurChar == _T(' '))) { - error_too_many_parameters (line); - return FALSE; + /* Wrong desicion path, reprocess current character */ + cCurSwitch = cCurChar; + continue; } + /* Process parameter switch */ + switch(cCurSwitch) + { + case _T('A'): /* Switch parameters for /A (attributes filter) */ + /* Ok a switch parameter was given */ + lpFlags->stAttribs.bParSetted = TRUE;
- *param = line; + if (cCurChar == _T(':')) + /* =V= dead command, used to make the "if" work */ + cCurChar = cCurChar; + else if(cCurChar == _T('-')) + bPNegative = TRUE; + else if(cCurUChar == _T('D')) + { + lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_DIRECTORY; + if (bPNegative) + lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_DIRECTORY; + else + lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_DIRECTORY; + } + else if(cCurUChar == _T('R')) + { + lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_READONLY; + if (bPNegative) + lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_READONLY; + else + lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_READONLY; + } + else if(cCurUChar == _T('H')) + { + lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_HIDDEN; + if (bPNegative) + lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_HIDDEN; + else + lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_HIDDEN; + } + else if(cCurUChar == _T('A')) + { + lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_ARCHIVE; + if (bPNegative) + lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_ARCHIVE; + else + lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_ARCHIVE; + } + else if(cCurUChar == _T('S')) + { + lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_SYSTEM; + if (bPNegative) + lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_SYSTEM; + else + lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_SYSTEM; + } + else + { + error_parameter_format((TCHAR)_totupper (*line)); + return FALSE; + } + break; + case _T('T'): /* Switch parameters for /T (time field) */
- /* skip to end of line or next whitespace or next / */ - if (*line != _T('"')) - { - while (*line && !_istspace (*line) && *line != _T('/')) - line++; + /* Ok a switch parameter was given */ + lpFlags->stTimeField.bParSetted = TRUE;
- /* if end of line, return */ - if (!*line) - return TRUE; - } - else - { - /* skip over the initial quote */ - (*param)++; - line++; + if (cCurChar == _T(':')) + /* =V= dead command, used to make the "if" work */ + cCurChar = cCurChar; + else if(cCurUChar == _T('C')) + lpFlags->stTimeField.eTimeField= TF_CREATIONDATE ; + else if(cCurUChar == _T('A')) + lpFlags->stTimeField.eTimeField= TF_LASTACCESSEDDATE ; + else if(cCurUChar == _T('W')) + lpFlags->stTimeField.eTimeField= TF_MODIFIEDDATE ; + else + { + error_parameter_format((TCHAR)_totupper (*line)); + return FALSE; + } + break; + case _T('O'): /* Switch parameters for /O (order) */ + /* Ok a switch parameter was given */ + lpFlags->stOrderBy.bParSetted = TRUE;
- while (*line && *line != _T('"')) - line++; + if (cCurChar == _T(':')) + /* <== dead command, used to make the "if" work */ + cCurChar = cCurChar; + else if(cCurChar == _T('-')) + bPNegative = TRUE; + else if(cCurUChar == _T('N')) + { + if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++; + lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative; + lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_NAME; + } + else if(cCurUChar == _T('S')) + { + if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++; + lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative; + lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_SIZE; + } + else if(cCurUChar == _T('G')) + { + if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++; + lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative; + lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_DIRECTORY; + } + else if(cCurUChar == _T('E')) + { + if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++; + lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative; + lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_EXTENSION; + } + else if(cCurUChar == _T('D')) + { + if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++; + lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative; + lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_TIME; + }
- if (*line == _T('"')) - *line = 0; else - return TRUE; - } + { + error_parameter_format((TCHAR)_totupper (*line)); + return FALSE; + }
- /* if parameter, remember to process it later */ - if (*line == _T('/')) - slash = 1;
- *line++ = 0; - continue; + } + /* We check if we calculated the negative value and realese the flag */ + if ((cCurChar != _T('-')) && bPNegative) + bPNegative = FALSE; } - + line++; } + /* Terminate the parameters */ + if (ptrLast) *ptrLast = 0;
- if (slash) + /* Calculate the switches with no switch paramater */ + if (!(lpFlags->stAttribs.bParSetted)) { - error_invalid_switch ((TCHAR)_totupper (*line)); - return FALSE; + lpFlags->stAttribs.dwAttribVal = 0L; + lpFlags->stAttribs.dwAttribMask = lpFlags->stAttribs.dwAttribVal; } + if (!(lpFlags->stOrderBy.bParSetted)) + { + lpFlags->stOrderBy.sCriteriaCount = 1; + lpFlags->stOrderBy.eCriteria[0] = ORDER_NAME; + lpFlags->stOrderBy.bCriteriaRev[0] = FALSE; + } + if (!(lpFlags->stOrderBy.bParSetted)) + lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE ;
+ /* Calculate the unsetted switches (the "-" prefixed)*/ + if (lpFlags->stAttribs.bUnSet) + { + lpFlags->stAttribs.bUnSet = FALSE; + lpFlags->stAttribs.dwAttribVal = 0L; + lpFlags->stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; + } + if (lpFlags->stOrderBy.bUnSet) + { + lpFlags->stOrderBy.bUnSet = FALSE; + lpFlags->stOrderBy.sCriteriaCount = 0; + } + if (lpFlags->stTimeField.bUnSet ) + { + lpFlags->stTimeField.bUnSet = FALSE; + lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE; + } return TRUE; }
- /* * ExtendFilespec * @@ -507,9 +760,9 @@ * incline * * increment our line if paginating, display message at end of screen - */ + *//*Maybe needed in future static BOOL -IncLine (LPINT pLine, DWORD dwFlags) +IncLine (LPINT pLine, LPDIRSWITCHFLAGS lpFlags) { BOOL error; CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo; @@ -518,16 +771,21 @@ WindowHeight= lpConsoleScreenBufferInfo.srWindow.Bottom - lpConsoleScreenBufferInfo.srWindow.Top;
- if (!WindowHeight) //That prevents bad behave if WindowHeight couln't calc + //That prevents bad behave if WindowHeight couln't calc + if (!WindowHeight) { WindowHeight= 1000000; } - if (!(dwFlags & DIR_PAGE)) + if (!(lpFlags->bPause)) return FALSE;
(*pLine)++;
- if (*pLine >= (int)maxy - 2 || *pLine >= WindowHeight) //Because I don't know if WindowsHeight work under all cases, perhaps then maxy is the right value + // Because I don't know if WindowsHeight + work under all cases, perhaps then maxy + is the right value + + if (*pLine >= (int)maxy - 2 || *pLine >= WindowHeight) { *pLine = 0; return (PagePrompt () == PROMPT_BREAK); @@ -535,22 +793,22 @@
return FALSE; } +*/
- /* * PrintDirectoryHeader * * print the header for the dir command */ static BOOL -PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags) +PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, LPDIRSWITCHFLAGS lpFlags) { TCHAR szRootName[MAX_PATH]; TCHAR szVolName[80]; DWORD dwSerialNr; LPTSTR p;
- if (dwFlags & DIR_BARE) + if (lpFlags->bBareFormat) return(TRUE);
/* build usable root path */ @@ -607,15 +865,10 @@ else ConOutPrintf(_T(" has no label\n"));
- if (IncLine(pLine, dwFlags)) - return(FALSE); - /* print the volume serial number if the return was successful */ ConOutPrintf(_T(" Volume Serial Number is %04X-%04X\n"), HIWORD(dwSerialNr), LOWORD(dwSerialNr)); - if (IncLine(pLine, dwFlags)) - return(FALSE);
return(TRUE); } @@ -625,7 +878,7 @@ * convert * * insert commas into a number - */ + *//* Maybe needed in future static INT ConvertULong (ULONG num, LPTSTR des, INT len) { @@ -656,10 +909,10 @@
return n; } +*/
- static INT -ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len) +ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len, BOOL bPutSeperator) { TCHAR temp[32]; INT c = 0; @@ -676,7 +929,7 @@ temp[31] = 0; while (num.QuadPart > 0) { - if (((c + 1) % (nNumberGroups + 1)) == 0) + if ((((c + 1) % (nNumberGroups + 1)) == 0) && (bPutSeperator)) temp[30 - c++] = cThousandSeparator; temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0'); num.QuadPart /= 10; @@ -691,44 +944,80 @@
static VOID -PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags) +DirPrintFileDateTime (TCHAR * lpDate, + TCHAR * lpTime, + LPWIN32_FIND_DATA lpFile, + LPDIRSWITCHFLAGS lpFlags) { - WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100; +FILETIME ft; +SYSTEMTIME dt; +TCHAR szDate[30]; +TCHAR szTime[30]; +WORD wYear;
+ /* Select the right time field */ + switch (lpFlags->stTimeField.eTimeField) + { + case TF_CREATIONDATE: + if (!FileTimeToLocalFileTime(&lpFile->ftCreationTime, &ft)) + return; + FileTimeToSystemTime(&ft, &dt); + break; + case TF_LASTACCESSEDDATE : + if (!FileTimeToLocalFileTime(&lpFile->ftLastAccessTime, &ft)) + return; + FileTimeToSystemTime(&ft, &dt); + break; + case TF_MODIFIEDDATE: + if (!FileTimeToLocalFileTime(&lpFile->ftLastWriteTime, &ft)) + return; + FileTimeToSystemTime(&ft, &dt); + break; + } + + /* Format date */ + wYear = (lpFlags->b4Digit) ? dt.wYear : dt.wYear%100; switch (nDateFormat) { case 0: /* mmddyy */ default: - ConOutPrintf (_T("%.2d%c%.2d%c%d"), - dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear); + _stprintf (szDate,_T("%02d%c%02d%c%0*d"), + dt.wMonth, cDateSeparator, + dt.wDay, cDateSeparator, + lpFlags->b4Digit?4:2, wYear); break;
case 1: /* ddmmyy */ - ConOutPrintf (_T("%.2d%c%.2d%c%d"), - dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear); + _stprintf (szDate, _T("%02d%c%02d%c%0*d"), + dt.wDay, cDateSeparator, dt.wMonth, + cDateSeparator,lpFlags->b4Digit?4:2, wYear); break;
case 2: /* yymmdd */ - ConOutPrintf (_T("%d%c%.2d%c%.2d"), - wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay); + _stprintf (szDate, _T("%0*d%c%02d%c%02d"), + lpFlags->b4Digit?4:2, wYear, cDateSeparator, + dt.wMonth, cDateSeparator, dt.wDay); break; } - + /* Format Time */ switch (nTimeFormat) { case 0: /* 12 hour format */ default: - ConOutPrintf (_T(" %2d%c%.2u%c"), - (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)), + _stprintf (szTime,_T(" %02d%c%02u%c"), + (dt.wHour == 0 ? 12 : (dt.wHour <= 12 ? dt.wHour : dt.wHour - 12)), cTimeSeparator, - dt->wMinute, (dt->wHour <= 11 ? 'a' : 'p')); + dt.wMinute, (dt.wHour <= 11 ? 'a' : 'p')); break;
case 1: /* 24 hour format */ - ConOutPrintf (_T(" %2d%c%.2u"), - dt->wHour, cTimeSeparator, dt->wMinute); + _stprintf (szTime, _T(" %02d%c%02u"), + dt.wHour, cTimeSeparator, dt.wMinute); break; } + /* Copy results */ + _tcscpy(lpDate, szDate); + _tcscpy(lpTime, szTime); }
@@ -783,457 +1072,734 @@ PrintSummary(LPTSTR szPath, ULONG ulFiles, ULONG ulDirs, - ULARGE_INTEGER bytes, + ULARGE_INTEGER u64Bytes, LPINT pLine, - DWORD dwFlags) + LPDIRSWITCHFLAGS lpFlags) { - TCHAR buffer[64]; - ULARGE_INTEGER uliFree; - TCHAR szRoot[] = _T("A:\"); +TCHAR szBuffer[64]; +ULARGE_INTEGER uliFree; +TCHAR szRoot[] = _T("A:\");
- if (dwFlags & DIR_BARE) - return(0);
- /* Print number of files and bytes */ - ConvertULong (ulFiles, buffer, sizeof(buffer)); - ConOutPrintf (_T(" %6s File%c"), - buffer, ulFiles == 1 ? _T(' ') : _T('s')); + /* Here we check if we didn't find anything */ + if (!(ulFiles + ulDirs)) + { + error_file_not_found(); + return 1; + } + /* In bare format we don't print results */ + if (lpFlags->bBareFormat) + return 0;
- ConvertULargeInteger (bytes, buffer, sizeof(buffer)); - ConOutPrintf (_T(" %15s byte%c\n"), - buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s')); + /* Print recursive specific results */ + if (lpFlags->bRecursive) + { + ConvertULargeInteger (u64Bytes, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator); + ConOutPrintf (_T("\n Total Files Listed:\n")); + ConOutPrintf(_T("%16i File(s)% 14s bytes\n"),ulFiles, szBuffer); + }
- if (IncLine (pLine, dwFlags)) - return 1; + /* Print total directories and freespace */ + szRoot[0] = szPath[0]; + GetUserDiskFreeSpace(szRoot, &uliFree); + ConvertULargeInteger (uliFree, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator); + ConOutPrintf (_T("%16i Dir(s)% 15s bytes\n"),ulDirs, szBuffer);
- /* Print number of dirs and bytes free */ - ConvertULong (ulDirs, buffer, sizeof(buffer)); - ConOutPrintf (_T(" %6s Dir%c"), - buffer, ulDirs == 1 ? _T(' ') : _T('s')); - - if (!(dwFlags & DIR_RECURSE)) - { - szRoot[0] = szPath[0]; - GetUserDiskFreeSpace(szRoot, &uliFree); - ConvertULargeInteger (uliFree, buffer, sizeof(buffer)); - ConOutPrintf (_T(" %15s bytes free\n"), buffer); - if (IncLine (pLine, dwFlags)) - return 1; - } - else - { - if ((dwFlags & DIR_BARE) == 0) - { - ConOutPrintf (_T("\n")); - if (IncLine (pLine, dwFlags)) - return 1; - ConOutPrintf (_T("\n")); - } - if (IncLine (pLine, dwFlags)) - return 1; - } - return 0; }
+/* + * getExt + * + * Get the extension of a filename + */ +TCHAR* getExt(const TCHAR* file) +{ + + TCHAR* tmp = _tcsrchr(file,'.'); + return tmp?tmp+1:""; +}
/* - * dir_list + * getName * - * list the files in the directory + * Get the name of the file without extension */ -static INT -DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags) +TCHAR * getName(const TCHAR* file, TCHAR * dest) { - TCHAR szFullPath[MAX_PATH]; - WIN32_FIND_DATA file; - ULARGE_INTEGER bytecount; - FILETIME ft; - SYSTEMTIME dt; - HANDLE hFile; - TCHAR buffer[32]; - ULONG filecount = 0; - ULONG dircount = 0; - INT count = 0; - SHORT screenwidth; - INT longestfname = 0; +int iLen; +TCHAR* end; + + /* Check for "." and ".." folders */ + if ((_tcscmp(file, _T(".")) == 0) + || (_tcscmp(file, _T("..")) == 0)) + { + _tcscpy(dest,file); + return dest; + }
- bytecount.QuadPart = 0; + end = _tcsrchr(file,'.'); + if (!end) + iLen = _tcslen(file); + else + iLen = (end - file); +
- _tcscpy (szFullPath, szPath); - if (szFullPath[_tcslen(szFullPath) - 1] != _T('\')) - _tcscat (szFullPath, _T("\")); - _tcscat (szFullPath, szFilespec); + _tcsncpy(dest, file, iLen); + *(dest + iLen) = _T('\0'); + + return dest; +} +/* + * DirPrintNewList + * + * The function that prints in new style + */ +static int +DirPrintNewList(LPWIN32_FIND_DATA ptrFiles[], /* [IN]Files' Info */ + DWORD dwCount, /* [IN] The quantity of files */ + TCHAR * szCurPath, /* [IN] Full path of current directory */ + LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */ +{ +DWORD i; /* An indexer for "for"s */ +TCHAR szSize[30]; /* The size of file */ +TCHAR szShortName[15]; /* The sort name */ +TCHAR szDate[20], szTime[20]; /* Date and time strings */ +int iSizeFormat; /* The format of size field */ +ULARGE_INTEGER u64FileSize; /* The file size */
- hFile = FindFirstFile (szFullPath, &file); - if (hFile == INVALID_HANDLE_VALUE) + for(i = 0;i < dwCount;i++) { - /* Don't want to print anything if scanning recursively - * for a file. RL - */ - if ((dwFlags & DIR_RECURSE) == 0) + + /* Calculate size */ + if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + /* Directory */ { - FindClose (hFile); - error_file_not_found (); - if (IncLine (pLine, dwFlags)) - return 0; - return 1; + iSizeFormat = -14; + _tcscpy(szSize, _T("<DIR>")); } - FindClose (hFile); - return 0; + else + /* File */ + { + iSizeFormat = 14; + u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh; + u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow; + ConvertULargeInteger(u64FileSize, szSize, 20,lpFlags->bTSeperator); + } + /* Calculate short name */ [truncated at 1000 lines; 1015 more skipped]