-/* $Id: dir.c,v 1.6 2004/01/16 19:57:13 weiden Exp $
- *
+/*
* DIR.C - dir internal command.
*
*
*
* 01-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
* Replaced all runtime io functions by their Win32 counterparts.
- *
+ *
* 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
* dir /s now works in deeper trees
+ *
+ * 28-Jan-2004 (Michael Fritscher <michael@fritscher.net>)
+ * Fix for /p, so it is working under Windows in GUI-mode, too.
+ *
+ * 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.
+ *
+ * 1-Jul-2004 (Brandon Turner <turnerb7@msu.edu>)
+ * Added /p back in using ConOutPrintfPaging
*/
-#include "config.h"
+#include <precomp.h>
+#include "resource.h"
#ifdef INCLUDE_CMD_DIR
-#include <windows.h>
-#include <tchar.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "cmd.h"
-typedef BOOL STDCALL
-(*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+/* Time Field enumeration */
+enum ETimeField
+{
+ TF_CREATIONDATE = 0,
+ TF_MODIFIEDDATE = 1,
+ TF_LASTACCESSEDDATE = 2
+};
-/* flag definitions */
-enum
+/* Ordered by enumeration */
+enum EOrderBy
{
- 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 */
+ ORDER_NAME = 0,
+ ORDER_SIZE = 1,
+ ORDER_DIRECTORY = 2,
+ ORDER_EXTENSION = 3,
+ ORDER_TIME = 4
};
+/* The struct for holding the switches */
+typedef struct _DirSwitchesFlags
+{
+ 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 struct _DIRFINDLISTNODE
+{
+ WIN32_FIND_DATA stFindInfo;
+ struct _DIRFINDLISTNODE *ptrNext;
+} DIRFINDLISTNODE, *PDIRFINDLISTNODE;
+
+
+typedef BOOL
+(WINAPI *PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+
/* Globally save the # of dirs, files and bytes,
* probabaly later pass them to functions. Rob Lake */
* 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"
- ));
+ ConOutResPaging(TRUE, STRING_DIR_HELP1);
}
+
/*
- * 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** params, /* [OUT] The parameters after parsing */
+ LPINT entries, /* [OUT] The number of 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 ptrStart; /* A pointer to the first character of a parameter */
+ LPTSTR ptrEnd; /* A pointer to the last character of a parameter */
+ LPTSTR temp;
+
+ /* Initialize parameter array */
+ *params = malloc(sizeof(LPTSTR));
+ if(!params)
+ return FALSE;
+ *params = NULL;
+ *entries = 0;
+ ptrStart = NULL;
+ ptrEnd = NULL;
+
+ /* Initialize variables; */
+ cCurSwitch = _T(' ');
+ bNegative = FALSE;
+ bPNegative = FALSE;
+ bIntoQuotes = FALSE;
+
+ /* 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;
+
+
+ /* Main Loop (see README_DIR.txt) */
+ /* scan the command line char per char, and we process its char */
+ while (*Line)
+ {
+ /* we save current character as it is and its upper case */
+ cCurChar = *Line;
+ cCurUChar = _totupper(*Line);
- if (!line)
- return TRUE;
+ /* 1st section (see README_DIR.txt) */
+ /* When a switch is expecting */
+ if (cCurSwitch == _T('/'))
+ {
+ if ((cCurUChar == _T('A')) ||(cCurUChar == _T('T')) || (cCurUChar == _T('O')))
+ {
+ cCurSwitch = cCurUChar;
+ switch (cCurUChar)
+ {
+ 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;
+ }
+ }
+ 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('?'))
+ {
+ DirHelp();
+ return FALSE;
+ }
+ else if (cCurChar == _T('-'))
+ {
+ bNegative = TRUE;
+ }
+ else
+ {
+ error_invalid_switch ((TCHAR)_totupper (*Line));
+ return FALSE;
+ }
- *param = NULL;
+ /* We check if we calculated the negative value and realese the flag */
+ if ((cCurChar != _T('-')) && bNegative)
+ bNegative = FALSE;
- /* scan the command line, processing switches */
- while (*line)
- {
- /* process switch */
- if (*line == _T('/') || slash)
+ /* if not a,o,t or - option then next parameter is not a switch */
+ if ((cCurSwitch == _T('/')) && (!bNegative))
+ cCurSwitch = _T(' ');
+
+ }
+ else if ((cCurSwitch == _T(' ')) || (cCurSwitch == _T('P')))
{
- if (!slash)
- line++;
- slash = 0;
- if (*line == _T('-'))
+ /* 2nd section (see README_DIR.txt) */
+ /* We are expecting parameter or the unknown */
+
+ if (cCurChar == _T('/'))
+ cCurSwitch = _T('/');
+
+ /* Process a spacer */
+ else if (cCurChar == _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 (!bIntoQuotes)
{
- error_invalid_switch ((TCHAR)_totupper (*line));
- return FALSE;
+ cCurSwitch = _T(' ');
+ if(ptrStart && ptrEnd)
+ {
+ temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ if(!temp)
+ return FALSE;
+ memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+ if(!add_entry(entries, params, temp))
+ {
+ free(temp);
+ freep(*params);
+ return FALSE;
+ }
+
+ free(temp);
+
+ ptrStart = NULL;
+ ptrEnd = NULL;
+ }
}
- line++;
- continue;
+
+ }
+ else if (cCurChar == _T('\"'))
+ {
+ /* Process a quote */
+ bIntoQuotes = !bIntoQuotes;
+ if(!bIntoQuotes)
+ ptrEnd = Line;
}
else
{
- 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('?'))
+ /* Process a character for parameter */
+ if ((cCurSwitch == _T(' ')) && ptrStart && ptrEnd)
+ {
+ temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ if(!temp)
+ return FALSE;
+ memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+ if(!add_entry(entries, params, temp))
+ {
+ free(temp);
+ freep(*params);
+ return FALSE;
+ }
+
+ free(temp);
+
+ ptrStart = NULL;
+ ptrEnd = NULL;
+ }
+ cCurSwitch = _T('P');
+ if(!ptrStart)
+ ptrStart = ptrEnd = Line;
+ ptrEnd = Line;
+ }
+ }
+ else
+ {
+ /* 3rd section (see README_DIR.txt) */
+ /* We are waiting for switch parameters */
+
+ /* Check if there are no more switch parameters */
+ if ((cCurChar == _T('/')) || ( cCurChar == _T(' ')))
+ {
+ /* 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;
+
+ 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'))
{
- Help();
+ 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) */
+
+ /* Ok a switch parameter was given */
+ lpFlags->stTimeField.bParSetted = TRUE;
+
+ 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_invalid_switch ((TCHAR)_totupper (*line));
+ error_parameter_format((TCHAR)_totupper (*Line));
return FALSE;
}
- line++;
- continue;
- }
- }
-
- /* process parameter */
- if (!_istspace (*line))
- {
- if (*param)
- {
- error_too_many_parameters (*param);
- return FALSE;
- }
-
- *param = line;
+ break;
+ case _T('O'): /* Switch parameters for /O (order) */
+ /* Ok a switch parameter was given */
+ lpFlags->stOrderBy.bParSetted = TRUE;
+
+ 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;
+ }
- /* skip to end of line or next whitespace or next / */
- while (*line && !_istspace (*line) && *line != _T('/'))
- line++;
+ else
+ {
+ error_parameter_format((TCHAR)_totupper (*Line));
+ return FALSE;
+ }
- /* if end of line, return */
- if (!*line)
- return TRUE;
- /* if parameter, remember to process it later */
- if (*line == _T('/'))
- slash = 1;
+ }
+ /* We check if we calculated the negative value and realese the flag */
+ if ((cCurChar != _T('-')) && bPNegative)
+ bPNegative = FALSE;
+ }
- *line++ = 0;
- continue;
+ Line++;
+ }
+ /* Terminate the parameters */
+ if(ptrStart && ptrEnd)
+ {
+ temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ if(!temp)
+ return FALSE;
+ memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+ temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+ if(!add_entry(entries, params, temp))
+ {
+ free(temp);
+ freep(*params);
+ return FALSE;
}
- line++;
+ free(temp);
+
+ ptrStart = NULL;
+ ptrEnd = NULL;
}
- 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;
}
if (!file)
return;
+
/* if no file spec, change to "*.*" */
if (*file == _T('\0'))
{
return;
}
+ // add support for *.
+ if ((file[0] == _T('*')) && (file[1] == _T('.') ))
+ {
+ return;
+ }
+
/* if starts with . add * in front */
if (*file == _T('.'))
{
return;
}
+
+
/* if last character is '.' add '*' */
len = _tcslen (file);
if (file[len - 1] == _T('.'))
}
else
{
-
*tmp = _T('\0');
/* change to this directory */
return 1;
}
}
- /* get the full name of the directory */
+
+ /* get the full name of the directory */
if (!GetCurrentDirectory (MAX_PATH, szPath))
{
*tmp = _T('\\');
*
* increment our line if paginating, display message at end of screen
*/
+#if 0
static BOOL
-IncLine (LPINT pLine, DWORD dwFlags)
+IncLine (LPINT pLine, LPDIRSWITCHFLAGS lpFlags)
{
- if (!(dwFlags & DIR_PAGE))
+ BOOL bError;
+ CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo;
+ LONG WindowHeight;
+
+ bError = GetConsoleScreenBufferInfo(hConsole, &lpConsoleScreenBufferInfo);
+
+ WindowHeight = lpConsoleScreenBufferInfo.srWindow.Bottom - lpConsoleScreenBufferInfo.srWindow.Top;
+
+ /* That prevents bad behiour if WindowHeight could not be calculated */
+ if (!WindowHeight)
+ {
+ WindowHeight= 1000000;
+ }
+
+ if (!(lpFlags->bPause))
return FALSE;
(*pLine)++;
- if (*pLine >= (int)maxy - 2)
+ /*
+ * Because I don't know if WindowsHeight work in all cases,
+ * perhaps then maxy is the right value
+ */
+ if (*pLine >= (int)maxy - 2 || *pLine >= WindowHeight)
{
*pLine = 0;
return (PagePrompt () == PROMPT_BREAK);
return FALSE;
}
-
+#endif
/*
* 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 szMsg[RC_STRING_MAX_SIZE];
TCHAR szRootName[MAX_PATH];
TCHAR szVolName[80];
DWORD dwSerialNr;
LPTSTR p;
- if (dwFlags & DIR_BARE)
- return(TRUE);
+ if (lpFlags->bBareFormat)
+ return TRUE;
/* build usable root path */
if (szPath[1] == _T(':') && szPath[2] == _T('\\'))
}
/* print drive info */
- ConOutPrintf(_T(" Volume in drive %c"), szRootName[0]);
-
if (szVolName[0] != _T('\0'))
- ConOutPrintf(_T(" is %s\n"), szVolName);
+ {
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP2, szMsg, RC_STRING_MAX_SIZE);
+ //needs to have first paramter as TRUE because
+ //this is the first output and need to clear the static
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(TRUE,szMsg, szRootName[0], szVolName);
+ else
+ ConOutPrintf(szMsg, szRootName[0], szVolName);
+
+ }
else
- ConOutPrintf(_T(" has no label\n"));
-
- if (IncLine(pLine, dwFlags))
- return(FALSE);
+ {
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP3, szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(TRUE,szMsg, szRootName[0]);
+ else
+ ConOutPrintf(szMsg, szRootName[0]);
+ }
/* 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);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP4, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg,
+ HIWORD(dwSerialNr),
+ LOWORD(dwSerialNr));
+ else
+ ConOutPrintf(szMsg,
+ HIWORD(dwSerialNr),
+ LOWORD(dwSerialNr));
+
- return(TRUE);
+ return TRUE;
}
* convert
*
* insert commas into a number
+ *
*/
+#if 0
static INT
ConvertULong (ULONG num, LPTSTR des, INT len)
{
return n;
}
+#endif
-
-static INT
-ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
+static VOID
+DirPrintFileDateTime(TCHAR *lpDate,
+ TCHAR *lpTime,
+ LPWIN32_FIND_DATA lpFile,
+ LPDIRSWITCHFLAGS lpFlags)
{
- TCHAR temp[32];
- INT c = 0;
- INT n = 0;
+ FILETIME ft;
+ SYSTEMTIME dt;
+ TCHAR szDate[30];
+ TCHAR szTime[30];
+ WORD wYear;
- if (num.QuadPart == 0)
- {
- des[0] = _T('0');
- des[1] = _T('\0');
- n = 1;
- }
- else
+ /* Select the right time field */
+ switch (lpFlags->stTimeField.eTimeField)
{
- temp[31] = 0;
- while (num.QuadPart > 0)
- {
- if (((c + 1) % (nNumberGroups + 1)) == 0)
- temp[30 - c++] = cThousandSeparator;
- temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
- num.QuadPart /= 10;
- }
-
- for (n = 0; n <= c; n++)
- des[n] = temp[31 - c + n];
- }
-
- return n;
-}
+ 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;
-static VOID
-PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags)
-{
- WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100;
+ 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 ? _T('a') : _T('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);
}
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 szMsg[RC_STRING_MAX_SIZE];
+ 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;
+ }
+
- ConvertULargeInteger (bytes, buffer, sizeof(buffer));
- ConOutPrintf (_T(" %15s byte%c\n"),
- buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
+ /* In bare format we don't print results */
+ if (lpFlags->bBareFormat)
+ return 0;
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* Print recursive specific results */
+
+ /* Take this code offline to fix /S does not print duoble info */
+ if (lpFlags->bRecursive)
+ {
+ ConvertULargeInteger(u64Bytes, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
- /* Print number of dirs and bytes free */
- ConvertULong (ulDirs, buffer, sizeof(buffer));
- ConOutPrintf (_T(" %6s Dir%c"),
- buffer, ulDirs == 1 ? _T(' ') : _T('s'));
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP5, szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+ else
+ ConOutPrintf(szMsg,ulFiles, szBuffer);
+
+ if (ulFiles > 0)
+ {
+ ConvertULargeInteger(u64Bytes, szBuffer, 20, lpFlags->bTSeperator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+ else
+ ConOutPrintf(szMsg,ulFiles, szBuffer);
- if (!(dwFlags & DIR_RECURSE))
+ }
+
+ }
+ else
+ {
+
+ /* Print File Summary */
+ /* Condition to print summary is:
+ If we are not in bare format and if we have results! */
+ if (ulFiles > 0)
+ {
+ ConvertULargeInteger(u64Bytes, szBuffer, 20, lpFlags->bTSeperator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+ else
+ ConOutPrintf(szMsg,ulFiles, szBuffer);
+
+ }
+
+}
+ /* Print total directories and freespace */
+ szRoot[0] = szPath[0];
+ GetUserDiskFreeSpace(szRoot, &uliFree);
+ ConvertULargeInteger(uliFree, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP6, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg,ulDirs, szBuffer);
+ else
+ ConOutPrintf(szMsg,ulDirs, szBuffer);
+
+ return 0;
+}
+
+/*
+ * getExt
+ *
+ * Get the extension of a filename
+ */
+TCHAR* getExt(const TCHAR* file)
+{
+ static TCHAR *NoExt = _T("");
+ TCHAR* lastdot = _tcsrchr(file, _T('.'));
+ return (lastdot != NULL ? lastdot + 1 : NoExt);
+}
+
+/*
+ * getName
+ *
+ * Get the name of the file without extension
+ */
+static LPTSTR
+getName(const TCHAR* file, TCHAR * dest)
+{
+ int iLen;
+ LPTSTR end;
+
+ /* Check for "." and ".." folders */
+ if ((_tcscmp(file, _T(".")) == 0) ||
+ (_tcscmp(file, _T("..")) == 0))
+ {
+ _tcscpy(dest,file);
+ return dest;
+ }
+
+ end = _tcsrchr(file, _T('.'));
+ if (!end)
+ iLen = _tcslen(file);
+ else
+ iLen = (end - file);
+
+
+ _tcsncpy(dest, file, iLen);
+ *(dest + iLen) = _T('\0');
+
+ return dest;
+}
+
+
+/*
+ * DirPrintNewList
+ *
+ * The function that prints in new style
+ */
+static VOID
+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;
+ TCHAR szSize[30];
+ TCHAR szShortName[15];
+ TCHAR szDate[20];
+ TCHAR szTime[20];
+ INT iSizeFormat;
+ ULARGE_INTEGER u64FileSize;
+
+ for (i = 0;i < dwCount;i++)
+ {
+ /* Calculate size */
+ if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
- 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;
+ /* Directory */
+ iSizeFormat = -14;
+ _tcscpy(szSize, _T("<DIR>"));
}
- else
+ else
{
- if ((dwFlags & DIR_BARE) == 0)
- {
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
- ConOutPrintf (_T("\n"));
- }
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* File */
+ iSizeFormat = 14;
+ u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
+ u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
+ ConvertULargeInteger(u64FileSize, szSize, 20, lpFlags->bTSeperator);
}
- return 0;
+ /* Calculate short name */
+ szShortName[0] = _T('\0');
+ if (lpFlags->bShortName)
+ _stprintf(szShortName, _T(" %-12s"), ptrFiles[i]->cAlternateFileName);
+
+ /* Format date and time */
+ DirPrintFileDateTime(szDate, szTime, ptrFiles[i], lpFlags);
+
+ /* Print the line */
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%10s %-8s %*s%s %s\n"),
+ szDate,
+ szTime,
+ iSizeFormat,
+ szSize,
+ szShortName,
+ ptrFiles[i]->cFileName);
+ else
+ ConOutPrintf(_T("%10s %-8s %*s%s %s\n"),
+ szDate,
+ szTime,
+ iSizeFormat,
+ szSize,
+ szShortName,
+ ptrFiles[i]->cFileName);
+ }
}
/*
- * dir_list
+ * DirPrintWideList
*
- * list the files in the directory
+ * The function that prints in wide list
*/
-static INT
-DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+static VOID
+DirPrintWideList(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 */
{
- 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;
+ SHORT iScreenWidth;
+ USHORT iColumns;
+ USHORT iLines;
+ UINT iLongestName;
+ TCHAR szTempFname[MAX_PATH];
+ DWORD i;
+ DWORD j;
+ DWORD temp;
+
+ /* Calculate longest name */
+ iLongestName = 1;
+ for (i = 0; i < dwCount; i++)
+ {
+ if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directories need 2 additinal characters for brackets */
+ if ((_tcslen(ptrFiles[i]->cFileName) + 2) > iLongestName)
+ iLongestName = _tcslen(ptrFiles[i]->cFileName) + 2;
+ }
+ else
+ {
+ if (_tcslen(ptrFiles[i]->cFileName) > iLongestName)
+ iLongestName = _tcslen(ptrFiles[i]->cFileName);
+ }
+ }
- bytecount.QuadPart = 0;
+ /* Count the highest number of columns */
+ GetScreenSize(&iScreenWidth, 0);
+ iColumns = iScreenWidth / iLongestName;
- _tcscpy (szFullPath, szPath);
- if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
- _tcscat (szFullPath, _T("\\"));
- _tcscat (szFullPath, szFilespec);
+ /* Check if there is enough space for spaces between names */
+ if (((iLongestName * iColumns) + iColumns) >= (UINT)iScreenWidth)
+ iColumns --;
+
+ /* A last check at iColumns to avoid division by zero */
+ if (!(iColumns))
+ iColumns = 1;
- hFile = FindFirstFile (szFullPath, &file);
- if (hFile == INVALID_HANDLE_VALUE)
+ /* Print Column sorted */
+ if (lpFlags->bWideListColSort)
+ {
+ /* Calculate the lines that will be printed */
+// iLines = ceil((float)dwCount/(float)iColumns);
+ iLines = (USHORT)(dwCount / iColumns);
+
+ for (i = 0;i < iLines;i++)
+ {
+ for (j = 0; j < iColumns; j++)
+ {
+ temp = (j * iLines) + i;
+ if (temp >= dwCount)
+ break;
+
+ if (ptrFiles[temp]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ _stprintf(szTempFname, _T("[%s]"), ptrFiles[temp]->cFileName);
+ else
+ _stprintf(szTempFname, _T("%s"), ptrFiles[temp]->cFileName);
+
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%-*s"), iLongestName + 1 , szTempFname);
+ else
+ ConOutPrintf(_T("%-*s"), iLongestName + 1 , szTempFname);
+ }
+
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("\n"));
+ else
+ ConOutPrintf(_T("\n"));
+ }
+ }
+ else
+ {
+ /* Print Line sorted */
+ for (i = 0; i < dwCount; i++)
+ {
+ if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ _stprintf(szTempFname, _T("[%s]"), ptrFiles[i]->cFileName);
+ else
+ _stprintf(szTempFname, _T("%s"), ptrFiles[i]->cFileName);
+
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%-*s"), iLongestName + 1, szTempFname );
+ else
+ ConOutPrintf(_T("%-*s"), iLongestName + 1, szTempFname );
+
+ /*
+ * We print a new line at the end of each column
+ * except for the case that it is the last item.
+ */
+ if (!((i + 1) % iColumns) && (i < (dwCount - 1)))
+ {
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("\n"));
+ else
+ ConOutPrintf(_T("\n"));
+ }
+ }
+
+ /* Add a new line after the last item */
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("\n"));
+ else
+ ConOutPrintf(_T("\n"));
+ }
+}
+
+
+/*
+ * DirPrintOldList
+ *
+ * The function that prints in old style
+ */
+static VOID
+DirPrintOldList(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 szName[10]; /* The name of file */
+TCHAR szExt[5]; /* The extension of file */
+TCHAR szDate[30],szTime[30]; /* Used to format time and date */
+TCHAR szSize[30]; /* The size of file */
+int iSizeFormat; /* The format of size field */
+ULARGE_INTEGER u64FileSize; /* The file size */
+
+ for(i = 0;i < dwCount;i++)
{
- /* Don't want to print anything if scanning recursively
- * for a file. RL
- */
- if ((dwFlags & DIR_RECURSE) == 0)
+ /* Broke 8.3 format */
+ if (*ptrFiles[i]->cAlternateFileName )
{
- FindClose (hFile);
- error_file_not_found ();
- if (IncLine (pLine, dwFlags))
- return 0;
- return 1;
+ /* If the file is long named then we read the alter name */
+ getName( ptrFiles[i]->cAlternateFileName, szName);
+ _tcscpy(szExt, getExt( ptrFiles[i]->cAlternateFileName));
+ }
+ else
+ {
+ /* If the file is not long name we read its original name */
+ getName( ptrFiles[i]->cFileName, szName);
+ _tcscpy(szExt, getExt( ptrFiles[i]->cFileName));
}
- FindClose (hFile);
- return 0;
- }
- /* moved down here because if we are recursively searching and
- * don't find any files, we don't want just to print
- * Directory of C:\SOMEDIR
- * with nothing else
- * Rob Lake 06/13/98
- */
- if ((dwFlags & DIR_BARE) == 0)
- {
- ConOutPrintf (_T(" Directory of %s\n"), szPath);
- if (IncLine (pLine, dwFlags))
- return 1;
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* Calculate size */
+ if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directory, no size it's a directory*/
+ iSizeFormat = -17;
+ _tcscpy(szSize, _T("<DIR>"));
+ }
+ else
+ {
+ /* File */
+ iSizeFormat = 17;
+ u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
+ u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
+ ConvertULargeInteger(u64FileSize, szSize, 20, lpFlags->bTSeperator);
+ }
+
+ /* Format date and time */
+ DirPrintFileDateTime(szDate,szTime,ptrFiles[i],lpFlags);
+
+ /* Print the line */
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%-8s %-3s %*s %s %s\n"),
+ szName, /* The file's 8.3 name */
+ szExt, /* The file's 8.3 extension */
+ iSizeFormat, /* print format for size column */
+ szSize, /* The size of file or "<DIR>" for dirs */
+ szDate, /* The date of file/dir */
+ szTime); /* The time of file/dir */
+ else
+ ConOutPrintf(_T("%-8s %-3s %*s %s %s\n"),
+ szName, /* The file's 8.3 name */
+ szExt, /* The file's 8.3 extension */
+ iSizeFormat, /* print format for size column */
+ szSize, /* The size of file or "<DIR>" for dirs */
+ szDate, /* The date of file/dir */
+ szTime); /* The time of file/dir */
}
+}
- /* For counting columns of output */
- count = 0;
+/*
+ * DirPrintBareList
+ *
+ * The function that prints in bare format
+ */
+static VOID
+DirPrintBareList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
+ DWORD dwCount, /* [IN] The number of files */
+ LPTSTR lpCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+{
+ TCHAR szFullName[MAX_PATH];
+ DWORD i;
- do
+ for (i = 0; i < dwCount; i++)
{
- /* next file, if user doesn't want all files */
- if (!(dwFlags & DIR_ALL) &&
- ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
- (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
- continue;
-
- if (dwFlags & DIR_LWR)
+ if ((_tcscmp(ptrFiles[i]->cFileName, _T(".")) == 0) ||
+ (_tcscmp(ptrFiles[i]->cFileName, _T("..")) == 0))
{
- _tcslwr (file.cAlternateFileName);
+ /* at bare format we don't print "." and ".." folder */
+ continue;
}
-
- if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
+ if (lpFlags->bRecursive)
{
- ULARGE_INTEGER uliSize;
-
- if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- if (file.cAlternateFileName[0] == _T('\0'))
- _stprintf (buffer, _T("[%s]"), file.cFileName);
- else
- _stprintf (buffer, _T("[%s]"), file.cAlternateFileName);
- dircount++;
- }
+ /* at recursive mode we print full path of file */
+ _tcscpy(szFullName, lpCurPath);
+ _tcscat(szFullName, ptrFiles[i]->cFileName);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%s\n"), szFullName);
else
- {
- if (file.cAlternateFileName[0] == _T('\0'))
- _stprintf (buffer, _T("%s"), file.cFileName);
- else
- _stprintf (buffer, _T("%s"), file.cAlternateFileName);
- filecount++;
- }
-
- ConOutPrintf (_T("%-15s"), buffer);
- count++;
- if (count == 5)
- {
- /* output 5 columns */
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
- count = 0;
- }
-
- uliSize.LowPart = file.nFileSizeLow;
- uliSize.HighPart = file.nFileSizeHigh;
- bytecount.QuadPart += uliSize.QuadPart;
+ ConOutPrintf(_T("%s\n"), szFullName);
}
- else if (dwFlags & DIR_BARE)
+ else
{
- ULARGE_INTEGER uliSize;
+ /* if we are not in recursive mode we print the file names */
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,_T("%s\n"),ptrFiles[i]->cFileName);
+ else
+ ConOutPrintf(_T("%s\n"),ptrFiles[i]->cFileName);
+ }
+ }
+}
- if (_tcscmp (file.cFileName, _T(".")) == 0 ||
- _tcscmp (file.cFileName, _T("..")) == 0)
- continue;
- if (dwFlags & DIR_RECURSE)
- {
- TCHAR dir[MAX_PATH];
+/*
+ * DirPrintFiles
+ *
+ * The functions that prints the files list
+ */
+static VOID
+DirPrintFiles(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 */
+{
+ TCHAR szMsg[RC_STRING_MAX_SIZE];
+ TCHAR szTemp[MAX_PATH]; /* A buffer to format the directory header */
- _tcscpy (dir, szPath);
- _tcscat (dir, _T("\\"));
- if (dwFlags & DIR_LWR)
- _tcslwr (dir);
- ConOutPrintf (dir);
- }
+ /* Print directory header */
+ _tcscpy(szTemp, szCurPath);
- ConOutPrintf (_T("%-13s\n"), file.cFileName);
- if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- dircount++;
- else
- filecount++;
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* We cut the trailing \ of the full path */
+ szTemp[_tcslen(szTemp)-1] = _T('\0');
- uliSize.LowPart = file.nFileSizeLow;
- uliSize.HighPart = file.nFileSizeHigh;
- bytecount.QuadPart += uliSize.QuadPart;
- }
+ /* Condition to print header:
+ We are not printing in bare format
+ and if we are in recursive mode... we must have results */
+ if (!(lpFlags->bBareFormat ) && !((lpFlags->bRecursive) && (dwCount <= 0)))
+ {
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP7, szMsg, RC_STRING_MAX_SIZE);
+ if(lpFlags->bPause)
+ ConOutPrintfPaging(FALSE,szMsg, szTemp);
else
- {
- if (dwFlags & DIR_NEW)
- {
- /* print file date and time */
- if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
- {
- FileTimeToSystemTime (&ft, &dt);
- PrintFileDateTime (&dt, dwFlags);
- }
+ ConOutPrintf(szMsg, szTemp);
+ }
- /* print file size */
- if (file.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- {
- ConOutPrintf (_T(" <JUNCTION> "));
- dircount++;
- }
- else if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- ConOutPrintf (_T(" <DIR> "));
- dircount++;
- }
- else
- {
- ULARGE_INTEGER uliSize;
+ if (lpFlags->bBareFormat)
+ {
+ /* 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);
+ }
+}
- uliSize.LowPart = file.nFileSizeLow;
- uliSize.HighPart = file.nFileSizeHigh;
- ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
- ConOutPrintf (_T(" %20s"), buffer);
- bytecount.QuadPart += uliSize.QuadPart;
- filecount++;
- }
+/*
+ * 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 */
- /* print long filename */
- ConOutPrintf (_T(" %s\n"), file.cFileName);
- }
- else
- {
- if (file.cFileName[0] == _T('.'))
- ConOutPrintf (_T("%-13s "), file.cFileName);
- else if (file.cAlternateFileName[0] == _T('\0'))
- {
- TCHAR szShortName[13];
- LPTSTR ext;
+ /* Calculate critiries by order given from user */
+ for (i = 0;i < lpFlags->stOrderBy.sCriteriaCount;i++)
+ {
- _tcsncpy (szShortName, file.cFileName, 13);
- ext = _tcschr (szShortName, _T('.'));
- if (!ext)
- ext = _T("");
- else
- *ext++ = _T('\0');
- ConOutPrintf (_T("%-8s %-3s "), szShortName, ext);
- }
- else
- {
- LPTSTR ext;
+ /* 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;
- ext = _tcschr (file.cAlternateFileName, _T('.'));
- if (!ext)
- ext = _T("");
- else
- *ext++ = _T('\0');
- ConOutPrintf (_T("%-8s %-3s "), file.cAlternateFileName, ext);
- }
+ case ORDER_DIRECTORY: /* Order by directory attribute /o:g */
+ iComp = ((lpFile2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
+ (lpFile1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+ break;
- /* print file size */
- if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- ConOutPrintf (_T("%-14s"), _T("<DIR>"));
- dircount++;
- }
- else
- {
- ULARGE_INTEGER uliSize;
-
- uliSize.LowPart = file.nFileSizeLow;
- uliSize.HighPart = file.nFileSizeHigh;
- ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
- ConOutPrintf (_T(" %10s "), buffer);
- bytecount.QuadPart += uliSize.QuadPart;
- filecount++;
- }
+ case ORDER_EXTENSION: /* Order by extension name /o:e */
+ iComp = _tcsicmp(getExt(lpFile1->cFileName),getExt(lpFile2->cFileName));
+ break;
- /* print file date and time */
- if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
- {
- FileTimeToSystemTime (&ft, &dt);
- PrintFileDateTime (&dt, dwFlags);
- }
+ case ORDER_NAME: /* Order by filename /o:n */
+ iComp = _tcsicmp(lpFile1->cFileName, lpFile2->cFileName);
+ break;
- /* print long filename */
- ConOutPrintf (_T(" %s\n"), file.cFileName);
+ 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;
}
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* 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;
}
- }
- while (FindNextFile (hFile, &file));
- FindClose (hFile);
- /* Rob Lake, need to make clean output */
- /* JPP 07/08/1998 added check for count != 0 */
- if ((dwFlags & DIR_WIDE) && (count != 0))
- {
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
- }
+ /* Reverse if desired */
+ if (lpFlags->stOrderBy.bCriteriaRev[i])
+ iComp *= -1;
- if (filecount || dircount)
- {
- recurse_dir_cnt += dircount;
- recurse_file_cnt += filecount;
- recurse_bytes.QuadPart += bytecount.QuadPart;
-
- /* print_summary */
- if (PrintSummary (szPath, filecount, dircount, bytecount, pLine, dwFlags))
- return 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)
{
- error_file_not_found ();
- return 1;
- }
+ 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;
- return 0;
+ /* 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);
+ }
}
+
/*
- * _Read_Dir: Actual function that does recursive listing
+ * DirList
+ *
+ * The functions that does everything except for printing results
*/
static INT
-DirRead (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+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 */
{
- TCHAR szFullPath[MAX_PATH];
- WIN32_FIND_DATA file;
- HANDLE hFile;
-
+ 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('\\'))
+ if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
_tcscat (szFullPath, _T("\\"));
- _tcscat (szFullPath, _T("*"));
+ _tcscpy (szFullFileSpec, szFullPath);
+ _tcscat (szFullFileSpec, szFilespec);
- hFile = FindFirstFile (szFullPath, &file);
- if (hFile == INVALID_HANDLE_VALUE)
- return 1;
+ /* 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
{
- /* don't list "." and ".." */
- if (_tcscmp (file.cFileName, _T(".")) == 0 ||
- _tcscmp (file.cFileName, _T("..")) == 0)
- continue;
-
- if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ if (hSearch != INVALID_HANDLE_VALUE)
{
- _tcscpy (szFullPath, szPath);
- if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
- _tcscat (szFullPath, _T("\\"));
- _tcscat (szFullPath, file.cFileName);
-
- if (DirList (szFullPath, szFilespec, pLine, dwFlags))
- {
- FindClose (hFile);
- return 1;
- }
- if (DirRead (szFullPath, szFilespec, pLine, dwFlags) == 1)
+ /* Here we filter all the specified attributes */
+ if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
+ == (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
{
- FindClose (hFile);
- return 1;
+ 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 (hFile, &file));
+ }while(FindNextFile(hSearch, &wfdFileInfo));
+ FindClose(hSearch);
- if (!FindClose (hFile))
- return 1;
+ /* Terminate list */
+ ptrNextNode->ptrNext = NULL;
- return 0;
-}
-
-
-/*
- * do_recurse: Sets up for recursive directory listing
- */
-static INT
-DirRecurse (LPTSTR szPath, LPTSTR szSpec, LPINT pLine, DWORD dwFlags)
-{
- if (!PrintDirectoryHeader (szPath, pLine, dwFlags))
- return 1;
-
- if (DirList (szPath, szSpec, pLine, dwFlags))
+ /* 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;
+ }
- if ((dwFlags & DIR_BARE) == 0)
+ /*
+ * 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)
{
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
+ *(ptrFileArray + dwCount) = &ptrNextNode->ptrNext->stFindInfo;
+ ptrNextNode = ptrNextNode->ptrNext;
+ dwCount++;
}
- if (DirRead (szPath, szSpec, pLine, dwFlags))
- return 1;
+ /* Sort Data if requested*/
+ if (lpFlags->stOrderBy.sCriteriaCount > 0)
+ QsortFiles(ptrFileArray, 0, dwCount-1,lpFlags);
- if ((dwFlags & DIR_BARE) == 0)
- ConOutPrintf (_T("Total files listed:\n"));
+ /* Print Data */
+ DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
- dwFlags &= ~DIR_RECURSE;
+ /* Free array */
+ free(ptrFileArray);
- if (PrintSummary (szPath, recurse_file_cnt,
- recurse_dir_cnt, recurse_bytes, pLine, dwFlags))
- return 1;
+ /* Add statistics to recursive statistics*/
+ recurse_dir_cnt += dwCountDirs;
+ recurse_file_cnt += dwCountFiles;
+ recurse_bytes.QuadPart += u64CountBytes.QuadPart;
- if ((dwFlags & DIR_BARE) == 0)
+ /* 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)
{
- ConOutPrintf (_T("\n"));
- if (IncLine (pLine, dwFlags))
- return 1;
+ /* 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 */
+ DirList(szFullFileSpec, szFilespec, pLine,lpFlags);
+ }
+ }
+ }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)
+INT
+CommandDir(LPTSTR first, LPTSTR rest)
{
- DWORD dwFlags = DIR_NEW | DIR_FOUR;
- TCHAR dircmd[256];
- TCHAR szPath[MAX_PATH];
- TCHAR szFilespec[MAX_PATH];
- LPTSTR param;
- INT nLine = 0;
-
-
+ 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, ¶m, &dwFlags))
+ if (!DirReadParam(dircmd, ¶ms, &entries, &stFlags))
+ {
+ nErrorLevel = 1;
return 1;
- }
+ }
/* read the parameters */
- if (!DirReadParam (rest, ¶m, &dwFlags))
+ if (!DirReadParam(rest, ¶ms, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
+ {
+ nErrorLevel = 1;
return 1;
+ }
/* default to current directory */
- if (!param)
- param = _T(".");
-
- /* parse the directory info */
- if (DirParsePathspec (param, szPath, szFilespec))
- return 1;
+ if(entries == 0) {
+ if(!add_entry(&entries, ¶ms, _T("."))) {
+ nErrorLevel = 1;
+ return 1;
+ }
+ }
- if (dwFlags & DIR_RECURSE)
+ for(loop = 0; loop < entries; loop++)
{
- if (IncLine (&nLine, dwFlags))
- return 0;
- if (DirRecurse (szPath, szFilespec, &nLine, dwFlags))
+ /* parse the directory info */
+ if (DirParsePathspec (params[loop], szPath, szFilespec) || CheckCtrlBreak(BREAK_INPUT))
+ {
+ nErrorLevel = 1;
return 1;
- return 0;
- }
+ }
- /* print the header */
- if (!PrintDirectoryHeader (szPath, &nLine, dwFlags))
- 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
- if (DirList (szPath, szFilespec, &nLine, dwFlags))
- return 1;
+ /* 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;
}