27-Feb-2005 (Konstantinos Paliouras <squarious(a)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(a)volny.cz>)
* Fix /w to print long names.
+ *
+ * 27-Feb-2005 (Konstantinos Paliouras <squarious(a)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]