📄 dir.c
字号:
/*
* DIR.C - dir internal command.
*
*
* History:
*
* 01/29/97 (Tim Norman)
* started.
*
* 06/13/97 (Tim Norman)
* Fixed code.
*
* 07/12/97 (Tim Norman)
* Fixed bug that caused the root directory to be unlistable
*
* 07/12/97 (Marc Desrochers)
* Changed to use maxx, maxy instead of findxy()
*
* 06/08/98 (Rob Lake)
* Added compatibility for /w in dir
*
* 06/09/98 (Rob Lake)
* Compatibility for dir/s started
* Tested that program finds directories off root fine
*
* 06/10/98 (Rob Lake)
* do_recurse saves the cwd and also stores it in Root
* build_tree adds the cwd to the beginning of its' entries
* Program runs fine, added print_tree -- works fine.. as EXE,
* program won't work properly as COM.
*
* 06/11/98 (Rob Lake)
* Found problem that caused COM not to work
*
* 06/12/98 (Rob Lake)
* debugged...
* added free mem routine
*
* 06/13/98 (Rob Lake)
* debugged the free mem routine
* debugged whole thing some more
* Notes:
* ReadDir stores Root name and _Read_Dir does the hard work
* PrintDir prints Root and _Print_Dir does the hard work
* KillDir kills Root _after_ _Kill_Dir does the hard work
* Integrated program into DIR.C(this file) and made some same
* changes throughout
*
* 06/14/98 (Rob Lake)
* Cleaned up code a bit, added comments
*
* 06/16/98 (Rob Lake)
* Added error checking to my previously added routines
*
* 06/17/98 (Rob Lake)
* Rewrote recursive functions, again! Most other recursive
* functions are now obsolete -- ReadDir, PrintDir, _Print_Dir,
* KillDir and _Kill_Dir. do_recurse does what PrintDir did
* and _Read_Dir did what it did before along with what _Print_Dir
* did. Makes /s a lot faster!
* Reports 2 more files/dirs that MS-DOS actually reports
* when used in root directory(is this because dir defaults
* to look for read only files?)
* Added support for /b, /a and /l
* Made error message similar to DOS error messages
* Added help screen
*
* 06/20/98 (Rob Lake)
* Added check for /-(switch) to turn off previously defined
* switches.
* Added ability to check for DIRCMD in environment and
* process it
*
* 06/21/98 (Rob Lake)
* Fixed up /B
* Now can dir *.ext/X, no spaces!
*
* 06/29/98 (Rob Lake)
* error message now found in command.h
*
* 07/08/1998 (John P. Price)
* removed extra returns; closer to MSDOS
* fixed wide display so that an extra return is not displayed
* when there is five filenames in the last line.
*
* 07/12/98 (Rob Lake)
* Changed error messages
*
* 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
* added config.h include
*
*
* 04-Dec-1998 (Eric Kohl)
* Converted source code to Win32, except recursive dir ("dir /s").
*
* 10-Dec-1998 (Eric Kohl)
* Fixed recursive dir ("dir /s").
*
* 14-Dec-1998 (Eric Kohl)
* Converted to Win32 directory functions and
* fixed some output bugs. There are still some more ;)
*
* 10-Jan-1999 (Eric Kohl)
* Added "/N" and "/4" options, "/O" is a dummy.
* Added locale support.
*
* 20-Jan-1999 (Eric Kohl)
* Redirection safe!
*
* 01-Mar-1999 (Eric Kohl)
* 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
*
* 3-feb-2007 (Paolo Devoti devotip at gmail)
* Removed variables formerly in use to handle pagination
* Pagination belongs to ConOutPrintfPaging
* Removed already commented out code of old pagination
*/
#include <precomp.h>
#ifdef INCLUDE_CMD_DIR
/* Time Field enumeration */
enum ETimeField
{
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 _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 */
static ULONG recurse_dir_cnt;
static ULONG recurse_file_cnt;
static ULARGE_INTEGER recurse_bytes;
/*
* help
*
* displays help screen for dir
* Rob Lake
*/
static VOID
DirHelp(VOID)
{
ConOutResPaging(TRUE, STRING_DIR_HELP1);
}
/*
* DirReadParameters
*
* Parse the parameters and switches of the command line and exports them
*/
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 */
{
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 */
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);
/* 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;
}
/* 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(' ');
}
else if ((cCurSwitch == _T(' ')) || (cCurSwitch == _T('P')))
{
/* 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(' '))
{
if (!bIntoQuotes)
{
cCurSwitch = _T(' ');
if(ptrStart && ptrEnd)
{
temp = cmd_alloc(((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))
{
cmd_free(temp);
freep(*params);
return FALSE;
}
cmd_free(temp);
ptrStart = NULL;
ptrEnd = NULL;
}
}
}
else if (cCurChar == _T('\"'))
{
/* Process a quote */
bIntoQuotes = !bIntoQuotes;
if(!bIntoQuotes)
ptrEnd = Line;
}
else
{
/* Process a character for parameter */
if ((cCurSwitch == _T(' ')) && ptrStart && ptrEnd)
{
temp = cmd_alloc(((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))
{
cmd_free(temp);
freep(*params);
return FALSE;
}
cmd_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'))
{
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
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -