📄 dir.c
字号:
/* $Id: dir.c,v 1.1.1.1 2004/02/15 23:24:43 pfalcon Exp $ * * 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 <ekohl@abo.rhein-zeitung.de>) * Converted source code to Win32, except recursive dir ("dir /s"). * * 10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Fixed recursive dir ("dir /s"). * * 14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Converted to Win32 directory functions and * fixed some output bugs. There are still some more ;) * * 10-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Added "/N" and "/4" options, "/O" is a dummy. * Added locale support. * * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Redirection safe! * * 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 */#include "config.h"#ifdef INCLUDE_CMD_DIR#include "cmd.h"/* flag definitions */enum{ 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 */};/* 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 Help (VOID){ ConOutPuts (_T("Displays a list of files and subdirectories in a directory.\n") _T("\n") _T("DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n") _T("\n") _T(" [drive:][path][filename]\n") _T(" Specifies drive, directory, and/or files to list.\n") _T("\n") _T(" /A Displays files with HIDDEN SYSTEM attributes\n") _T(" default is ARCHIVE and READ ONLY\n") _T(" /B Uses bare format (no heading information or summary).\n") _T(" /L Uses lowercase.\n") _T(" /N New long list format where filenames are on the far right.\n") _T(" /S Displays files in specified directory and all subdirectories\n") _T(" /P Pauses after each screen full\n") _T(" /W Prints in wide format\n") _T(" /4 Display four digit years.\n") _T("\n") _T("Switches may be present in the DIRCMD environment variable. Use\n") _T("of the - (hyphen) can turn off defined swtiches. Ex. /-W would\n") _T("turn off printing in wide format.\n") );}/* * DirReadParam * * read the parameters from the command line */static BOOLDirReadParam (LPTSTR line, LPTSTR *param, LPDWORD lpFlags){ INT slash = 0; if (!line) return TRUE; *param = NULL; /* scan the command line, processing switches */ while (*line) { /* process switch */ if (*line == _T('/') || slash) { 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 { error_invalid_switch ((TCHAR)_totupper (*line)); return FALSE; } line++; continue; } 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('?')) { Help(); return FALSE; } else { error_invalid_switch ((TCHAR)_totupper (*line)); return FALSE; } line++; continue; } } /* process parameter */ if (!_istspace (*line)) { if (*param) { error_too_many_parameters (*param); return FALSE; } *param = line; /* skip to end of line or next whitespace or next / */ while (*line && !_istspace (*line) && *line != _T('/')) line++; /* if end of line, return */ if (!*line) return TRUE; /* if parameter, remember to process it later */ if (*line == _T('/')) slash = 1; *line++ = 0; continue; } line++; } if (slash) { error_invalid_switch ((TCHAR)_totupper (*line)); return FALSE; } return TRUE;}/* * ExtendFilespec * * extend the filespec, possibly adding wildcards */static VOIDExtendFilespec (LPTSTR file){ INT len = 0; if (!file) return; /* if no file spec, change to "*.*" */ if (*file == _T('\0')) { _tcscpy (file, _T("*.*")); return; } /* if starts with . add * in front */ if (*file == _T('.')) { memmove (&file[1], &file[0], (_tcslen (file) + 1) * sizeof(TCHAR)); file[0] = _T('*'); } /* if no . add .* */ if (!_tcschr (file, _T('.'))) { _tcscat (file, _T(".*")); return; } /* if last character is '.' add '*' */ len = _tcslen (file); if (file[len - 1] == _T('.')) { _tcscat (file, _T("*")); return; }}/* * dir_parse_pathspec * * split the pathspec into drive, directory, and filespec */static INTDirParsePathspec (LPTSTR szPathspec, LPTSTR szPath, LPTSTR szFilespec){ TCHAR szOrigPath[MAX_PATH]; LPTSTR start; LPTSTR tmp; INT i; BOOL bWildcards = FALSE; GetCurrentDirectory (MAX_PATH, szOrigPath); /* get the drive and change to it */ if (szPathspec[1] == _T(':')) { TCHAR szRootPath[] = _T("A:"); szRootPath[0] = szPathspec[0]; start = szPathspec + 2; SetCurrentDirectory (szRootPath); } else { start = szPathspec; } /* check for wildcards */ for (i = 0; szPathspec[i]; i++) { if (szPathspec[i] == _T('*') || szPathspec[i] == _T('?')) bWildcards = TRUE; } /* check if this spec is a directory */ if (!bWildcards) { if (SetCurrentDirectory (szPathspec)) { _tcscpy (szFilespec, _T("*.*")); if (!GetCurrentDirectory (MAX_PATH, szPath)) { szFilespec[0] = _T('\0'); SetCurrentDirectory (szOrigPath); error_out_of_memory(); return 1; } SetCurrentDirectory (szOrigPath); return 0; } } /* find the file spec */ tmp = _tcsrchr (start, _T('\\')); /* if no path is specified */ if (!tmp) { _tcscpy (szFilespec, start); ExtendFilespec (szFilespec); if (!GetCurrentDirectory (MAX_PATH, szPath)) { szFilespec[0] = _T('\0'); SetCurrentDirectory (szOrigPath); error_out_of_memory(); return 1; } SetCurrentDirectory (szOrigPath); return 0; } /* get the filename */ _tcscpy (szFilespec, tmp+1); ExtendFilespec (szFilespec); *tmp = _T('\0'); /* change to this directory and get its full name */ if (!SetCurrentDirectory (start)) { *tmp = _T('\\'); szFilespec[0] = _T('\0'); SetCurrentDirectory (szOrigPath); error_path_not_found (); return 1; } if (!GetCurrentDirectory (MAX_PATH, szPath)) { *tmp = _T('\\'); szFilespec[0] = _T('\0'); SetCurrentDirectory (szOrigPath); error_out_of_memory (); return 1; } *tmp = _T('\\'); SetCurrentDirectory (szOrigPath); return 0;}/* * incline * * increment our line if paginating, display message at end of screen */static BOOLIncLine (LPINT pLine, DWORD dwFlags){ if (!(dwFlags & DIR_PAGE)) return FALSE; (*pLine)++; if (*pLine >= (int)maxy - 2) { *pLine = 0; return (PagePrompt () == PROMPT_BREAK); } return FALSE;}/* * PrintDirectoryHeader * * print the header for the dir command */static BOOLPrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags){#ifndef _WIN32 TCHAR szRootName[] = _T("A:\\"); TCHAR szVolName[80]; DWORD dwSerialNr; if (dwFlags & DIR_BARE) return TRUE; /* get the media ID of the drive */ szRootName[0] = szPath[0]; if (!GetVolumeInformation (szRootName, szVolName, 80, &dwSerialNr, NULL, NULL, NULL, 0)) {c error_invalid_drive(); return FALSE; } /* print drive info */ ConOutPrintf (_T(" Volume in drive %c"), szRootName[0]); if (szVolName[0] != _T('\0')) ConOutPrintf (_T(" is %s\n"), szVolName); 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;#endif return TRUE;}/* * convert * * insert commas into a number */static INTConvertULong (ULONG num, LPTSTR des, INT len){ TCHAR temp[32]; INT c = 0; INT n = 0; if (num == 0) { des[0] = _T('0'); des[1] = _T('\0'); n = 1; } else { temp[31] = 0; while (num > 0) { if (((c + 1) % (nNumberGroups + 1)) == 0) temp[30 - c++] = cThousandSeparator; temp[30 - c++] = (TCHAR)(num % 10) + _T('0'); num /= 10; } for (n = 0; n <= c; n++) des[n] = temp[31 - c + n]; } return n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -