3 * DIR.C - dir internal command.
8 * 01/29/97 (Tim Norman)
11 * 06/13/97 (Tim Norman)
14 * 07/12/97 (Tim Norman)
15 * Fixed bug that caused the root directory to be unlistable
17 * 07/12/97 (Marc Desrochers)
18 * Changed to use maxx, maxy instead of findxy()
21 * Added compatibility for /w in dir
24 * Compatibility for dir/s started
25 * Tested that program finds directories off root fine
28 * do_recurse saves the cwd and also stores it in Root
29 * build_tree adds the cwd to the beginning of its' entries
30 * Program runs fine, added print_tree -- works fine.. as EXE,
31 * program won't work properly as COM.
34 * Found problem that caused COM not to work
38 * added free mem routine
41 * debugged the free mem routine
42 * debugged whole thing some more
44 * ReadDir stores Root name and _Read_Dir does the hard work
45 * PrintDir prints Root and _Print_Dir does the hard work
46 * KillDir kills Root _after_ _Kill_Dir does the hard work
47 * Integrated program into DIR.C(this file) and made some same
51 * Cleaned up code a bit, added comments
54 * Added error checking to my previously added routines
57 * Rewrote recursive functions, again! Most other recursive
58 * functions are now obsolete -- ReadDir, PrintDir, _Print_Dir,
59 * KillDir and _Kill_Dir. do_recurse does what PrintDir did
60 * and _Read_Dir did what it did before along with what _Print_Dir
61 * did. Makes /s a lot faster!
62 * Reports 2 more files/dirs that MS-DOS actually reports
63 * when used in root directory(is this because dir defaults
64 * to look for read only files?)
65 * Added support for /b, /a and /l
66 * Made error message similar to DOS error messages
70 * Added check for /-(switch) to turn off previously defined
72 * Added ability to check for DIRCMD in environment and
77 * Now can dir *.ext/X, no spaces!
80 * error message now found in command.h
82 * 07/08/1998 (John P. Price)
83 * removed extra returns; closer to MSDOS
84 * fixed wide display so that an extra return is not displayed
85 * when there is five filenames in the last line.
88 * Changed error messages
90 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
91 * added config.h include
94 * 04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
95 * Converted source code to Win32, except recursive dir ("dir /s").
97 * 10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
98 * Fixed recursive dir ("dir /s").
100 * 14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
101 * Converted to Win32 directory functions and
102 * fixed some output bugs. There are still some more ;)
104 * 10-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
105 * Added "/N" and "/4" options, "/O" is a dummy.
106 * Added locale support.
108 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
111 * 01-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
112 * Replaced all runtime io functions by their Win32 counterparts.
114 * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
115 * dir /s now works in deeper trees
120 #ifdef INCLUDE_CMD_DIR
132 (*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
135 /* flag definitions */
138 DIR_RECURSE = 0x0001,
140 DIR_WIDE = 0x0004, /* Rob Lake */
141 DIR_BARE = 0x0008, /* Rob Lake */
142 DIR_ALL = 0x0010, /* Rob Lake */
143 DIR_LWR = 0x0020, /* Rob Lake */
144 DIR_SORT = 0x0040, /* /O sort */
145 DIR_NEW = 0x0080, /* /N new style */
146 DIR_FOUR = 0x0100 /* /4 four digit year */
150 /* Globally save the # of dirs, files and bytes,
151 * probabaly later pass them to functions. Rob Lake */
152 static ULONG recurse_dir_cnt;
153 static ULONG recurse_file_cnt;
154 static ULARGE_INTEGER recurse_bytes;
160 * displays help screen for dir
163 static VOID Help (VOID)
165 ConOutPuts(_T("Displays a list of files and subdirectories in a directory.\n"
167 "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
169 " [drive:][path][filename]\n"
170 " Specifies drive, directory, and/or files to list.\n"
172 " /A Displays files with HIDDEN SYSTEM attributes\n"
173 " default is ARCHIVE and READ ONLY\n"
174 " /B Uses bare format (no heading information or summary).\n"
175 " /L Uses lowercase.\n"
176 " /N New long list format where filenames are on the far right.\n"
177 " /S Displays files in specified directory and all subdirectories\n"
178 " /P Pauses after each screen full\n"
179 " /W Prints in wide format\n"
180 " /4 Display four digit years.\n"
182 "Switches may be present in the DIRCMD environment variable. Use\n"
183 "of the - (hyphen) can turn off defined swtiches. Ex. /-W would\n"
184 "turn off printing in wide format.\n"
192 * read the parameters from the command line
195 DirReadParam (LPTSTR line, LPTSTR *param, LPDWORD lpFlags)
204 /* scan the command line, processing switches */
208 if (*line == _T('/') || slash)
213 if (*line == _T('-'))
216 if (_totupper (*line) == _T('S'))
217 *lpFlags &= ~DIR_RECURSE;
218 else if (_totupper (*line) == _T('P'))
219 *lpFlags &= ~DIR_PAGE;
220 else if (_totupper (*line) == _T('W'))
221 *lpFlags &= ~DIR_WIDE;
222 else if (_totupper (*line) == _T('B'))
223 *lpFlags &= ~DIR_BARE;
224 else if (_totupper (*line) == _T('A'))
225 *lpFlags &= ~DIR_ALL;
226 else if (_totupper (*line) == _T('L'))
227 *lpFlags &= ~DIR_LWR;
228 else if (_totupper (*line) == _T('N'))
229 *lpFlags &= ~DIR_NEW;
230 else if (_totupper (*line) == _T('O'))
231 *lpFlags &= ~DIR_SORT;
232 else if (_totupper (*line) == _T('4'))
233 *lpFlags &= ~DIR_FOUR;
236 error_invalid_switch ((TCHAR)_totupper (*line));
244 if (_totupper (*line) == _T('S'))
245 *lpFlags |= DIR_RECURSE;
246 else if (_totupper (*line) == _T('P'))
247 *lpFlags |= DIR_PAGE;
248 else if (_totupper (*line) == _T('W'))
249 *lpFlags |= DIR_WIDE;
250 else if (_totupper (*line) == _T('B'))
251 *lpFlags |= DIR_BARE;
252 else if (_totupper (*line) == _T('A'))
254 else if (_totupper (*line) == _T('L'))
256 else if (_totupper (*line) == _T('N'))
258 else if (_totupper (*line) == _T('O'))
259 *lpFlags |= DIR_SORT;
260 else if (_totupper (*line) == _T('4'))
261 *lpFlags |= DIR_FOUR;
262 else if (*line == _T('?'))
269 error_invalid_switch ((TCHAR)_totupper (*line));
277 /* process parameter */
278 if (!_istspace (*line))
282 error_too_many_parameters (*param);
288 /* skip to end of line or next whitespace or next / */
289 while (*line && !_istspace (*line) && *line != _T('/'))
292 /* if end of line, return */
296 /* if parameter, remember to process it later */
297 if (*line == _T('/'))
309 error_invalid_switch ((TCHAR)_totupper (*line));
320 * extend the filespec, possibly adding wildcards
323 ExtendFilespec (LPTSTR file)
330 /* if no file spec, change to "*.*" */
331 if (*file == _T('\0'))
333 _tcscpy (file, _T("*.*"));
337 /* if starts with . add * in front */
338 if (*file == _T('.'))
340 memmove (&file[1], &file[0], (_tcslen (file) + 1) * sizeof(TCHAR));
345 if (!_tcschr (file, _T('.')))
347 _tcscat (file, _T(".*"));
351 /* if last character is '.' add '*' */
352 len = _tcslen (file);
353 if (file[len - 1] == _T('.'))
355 _tcscat (file, _T("*"));
364 * split the pathspec into drive, directory, and filespec
367 DirParsePathspec (LPTSTR szPathspec, LPTSTR szPath, LPTSTR szFilespec)
369 TCHAR szOrigPath[MAX_PATH];
373 BOOL bWildcards = FALSE;
375 GetCurrentDirectory (MAX_PATH, szOrigPath);
377 /* get the drive and change to it */
378 if (szPathspec[1] == _T(':'))
380 TCHAR szRootPath[] = _T("A:");
382 szRootPath[0] = szPathspec[0];
383 start = szPathspec + 2;
384 SetCurrentDirectory (szRootPath);
392 /* check for wildcards */
393 for (i = 0; szPathspec[i]; i++)
395 if (szPathspec[i] == _T('*') || szPathspec[i] == _T('?'))
399 /* check if this spec is a directory */
402 if (SetCurrentDirectory (szPathspec))
404 _tcscpy (szFilespec, _T("*.*"));
406 if (!GetCurrentDirectory (MAX_PATH, szPath))
408 szFilespec[0] = _T('\0');
409 SetCurrentDirectory (szOrigPath);
410 error_out_of_memory();
414 SetCurrentDirectory (szOrigPath);
419 /* find the file spec */
420 tmp = _tcsrchr (start, _T('\\'));
422 /* if no path is specified */
425 _tcscpy (szFilespec, start);
426 ExtendFilespec (szFilespec);
427 if (!GetCurrentDirectory (MAX_PATH, szPath))
429 szFilespec[0] = _T('\0');
430 SetCurrentDirectory (szOrigPath);
431 error_out_of_memory();
435 SetCurrentDirectory (szOrigPath);
439 /* get the filename */
440 _tcscpy (szFilespec, tmp+1);
441 ExtendFilespec (szFilespec);
445 /* change to this directory and get its full name */
446 if (!SetCurrentDirectory (start))
449 szFilespec[0] = _T('\0');
450 SetCurrentDirectory (szOrigPath);
451 error_path_not_found ();
455 if (!GetCurrentDirectory (MAX_PATH, szPath))
458 szFilespec[0] = _T('\0');
459 SetCurrentDirectory (szOrigPath);
460 error_out_of_memory ();
466 SetCurrentDirectory (szOrigPath);
475 * increment our line if paginating, display message at end of screen
478 IncLine (LPINT pLine, DWORD dwFlags)
480 if (!(dwFlags & DIR_PAGE))
485 if (*pLine >= (int)maxy - 2)
488 return (PagePrompt () == PROMPT_BREAK);
496 * PrintDirectoryHeader
498 * print the header for the dir command
501 PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags)
503 TCHAR szRootName[MAX_PATH];
508 if (dwFlags & DIR_BARE)
511 /* build usable root path */
512 if (szPath[1] == _T(':') && szPath[2] == _T('\\'))
515 szRootName[0] = szPath[0];
516 szRootName[1] = _T(':');
517 szRootName[2] = _T('\\');
520 else if (szPath[0] == _T('\\') && szPath[1] == _T('\\'))
523 p = _tcschr(&szPath[2], _T('\\'));
526 error_invalid_drive();
529 p = _tcschr(p+1, _T('\\'));
532 _tcscpy(szRootName, szPath);
533 _tcscat(szRootName, _T("\\"));
538 _tcscpy(szRootName, szPath);
539 _tcscat(szRootName, _T("\\"));
545 error_invalid_drive();
549 /* get the media ID of the drive */
550 if (!GetVolumeInformation(szRootName, szVolName, 80, &dwSerialNr,
551 NULL, NULL, NULL, 0))
553 error_invalid_drive();
557 /* print drive info */
558 ConOutPrintf(_T(" Volume in drive %c"), szRootName[0]);
560 if (szVolName[0] != _T('\0'))
561 ConOutPrintf(_T(" is %s\n"), szVolName);
563 ConOutPrintf(_T(" has no label\n"));
565 if (IncLine(pLine, dwFlags))
568 /* print the volume serial number if the return was successful */
569 ConOutPrintf(_T(" Volume Serial Number is %04X-%04X\n"),
572 if (IncLine(pLine, dwFlags))
582 * insert commas into a number
585 ConvertULong (ULONG num, LPTSTR des, INT len)
602 if (((c + 1) % (nNumberGroups + 1)) == 0)
603 temp[30 - c++] = cThousandSeparator;
604 temp[30 - c++] = (TCHAR)(num % 10) + _T('0');
608 for (n = 0; n <= c; n++)
609 des[n] = temp[31 - c + n];
617 ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
623 if (num.QuadPart == 0)
632 while (num.QuadPart > 0)
634 if (((c + 1) % (nNumberGroups + 1)) == 0)
635 temp[30 - c++] = cThousandSeparator;
636 temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
640 for (n = 0; n <= c; n++)
641 des[n] = temp[31 - c + n];
649 PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags)
651 WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100;
657 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
658 dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear);
662 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
663 dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear);
667 ConOutPrintf (_T("%d%c%.2d%c%.2d"),
668 wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay);
674 case 0: /* 12 hour format */
676 ConOutPrintf (_T(" %2d%c%.2u%c"),
677 (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
679 dt->wMinute, (dt->wHour <= 11 ? 'a' : 'p'));
682 case 1: /* 24 hour format */
683 ConOutPrintf (_T(" %2d%c%.2u"),
684 dt->wHour, cTimeSeparator, dt->wMinute);
691 GetUserDiskFreeSpace(LPCTSTR lpRoot,
692 PULARGE_INTEGER lpFreeSpace)
694 PGETFREEDISKSPACEEX pGetFreeDiskSpaceEx;
701 lpFreeSpace->QuadPart = 0;
703 hInstance = LoadLibrary(_T("KERNEL32"));
704 if (hInstance != NULL)
706 pGetFreeDiskSpaceEx = (PGETFREEDISKSPACEEX)GetProcAddress(hInstance,
708 _T("GetDiskFreeSpaceExW"));
710 _T("GetDiskFreeSpaceExA"));
712 if (pGetFreeDiskSpaceEx != NULL)
714 if (pGetFreeDiskSpaceEx(lpRoot, lpFreeSpace, NULL, NULL) == TRUE)
717 FreeLibrary(hInstance);
720 GetDiskFreeSpace(lpRoot,
726 lpFreeSpace->QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
731 * print_summary: prints dir summary
732 * Added by Rob Lake 06/17/98 to compact code
733 * Just copied Tim's Code and patched it a bit
737 PrintSummary(LPTSTR szPath,
740 ULARGE_INTEGER bytes,
745 ULARGE_INTEGER uliFree;
746 TCHAR szRoot[] = _T("A:\\");
748 if (dwFlags & DIR_BARE)
751 /* Print number of files and bytes */
752 ConvertULong (ulFiles, buffer, sizeof(buffer));
753 ConOutPrintf (_T(" %6s File%c"),
754 buffer, ulFiles == 1 ? _T(' ') : _T('s'));
756 ConvertULargeInteger (bytes, buffer, sizeof(buffer));
757 ConOutPrintf (_T(" %15s byte%c\n"),
758 buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
760 if (IncLine (pLine, dwFlags))
763 /* Print number of dirs and bytes free */
764 ConvertULong (ulDirs, buffer, sizeof(buffer));
765 ConOutPrintf (_T(" %6s Dir%c"),
766 buffer, ulDirs == 1 ? _T(' ') : _T('s'));
768 if (!(dwFlags & DIR_RECURSE))
770 szRoot[0] = szPath[0];
771 GetUserDiskFreeSpace(szRoot, &uliFree);
772 ConvertULargeInteger (uliFree, buffer, sizeof(buffer));
773 ConOutPrintf (_T(" %15s bytes free\n"), buffer);
776 if (IncLine (pLine, dwFlags))
786 * list the files in the directory
789 DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
791 TCHAR szFullPath[MAX_PATH];
792 WIN32_FIND_DATA file;
793 ULARGE_INTEGER bytecount;
802 bytecount.QuadPart = 0;
804 _tcscpy (szFullPath, szPath);
805 if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
806 _tcscat (szFullPath, _T("\\"));
807 _tcscat (szFullPath, szFilespec);
809 hFile = FindFirstFile (szFullPath, &file);
810 if (hFile == INVALID_HANDLE_VALUE)
812 /* Don't want to print anything if scanning recursively
815 if ((dwFlags & DIR_RECURSE) == 0)
818 error_file_not_found ();
819 if (IncLine (pLine, dwFlags))
827 /* moved down here because if we are recursively searching and
828 * don't find any files, we don't want just to print
829 * Directory of C:\SOMEDIR
833 if ((dwFlags & DIR_BARE) == 0)
835 ConOutPrintf (_T(" Directory of %s\n"), szPath);
836 if (IncLine (pLine, dwFlags))
838 ConOutPrintf (_T("\n"));
839 if (IncLine (pLine, dwFlags))
843 /* For counting columns of output */
848 /* next file, if user doesn't want all files */
849 if (!(dwFlags & DIR_ALL) &&
850 ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
851 (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
854 if (dwFlags & DIR_LWR)
856 _tcslwr (file.cAlternateFileName);
859 if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
861 ULARGE_INTEGER uliSize;
863 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
865 if (file.cAlternateFileName[0] == _T('\0'))
866 _stprintf (buffer, _T("[%s]"), file.cFileName);
868 _stprintf (buffer, _T("[%s]"), file.cAlternateFileName);
873 if (file.cAlternateFileName[0] == _T('\0'))
874 _stprintf (buffer, _T("%s"), file.cFileName);
876 _stprintf (buffer, _T("%s"), file.cAlternateFileName);
880 ConOutPrintf (_T("%-15s"), buffer);
884 /* output 5 columns */
885 ConOutPrintf (_T("\n"));
886 if (IncLine (pLine, dwFlags))
891 uliSize.LowPart = file.nFileSizeLow;
892 uliSize.HighPart = file.nFileSizeHigh;
893 bytecount.QuadPart += uliSize.QuadPart;
895 else if (dwFlags & DIR_BARE)
897 ULARGE_INTEGER uliSize;
899 if (_tcscmp (file.cFileName, _T(".")) == 0 ||
900 _tcscmp (file.cFileName, _T("..")) == 0)
903 if (dwFlags & DIR_RECURSE)
907 _tcscpy (dir, szPath);
908 _tcscat (dir, _T("\\"));
909 if (dwFlags & DIR_LWR)
914 ConOutPrintf (_T("%-13s\n"), file.cFileName);
915 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
919 if (IncLine (pLine, dwFlags))
922 uliSize.LowPart = file.nFileSizeLow;
923 uliSize.HighPart = file.nFileSizeHigh;
924 bytecount.QuadPart += uliSize.QuadPart;
928 if (dwFlags & DIR_NEW)
930 /* print file date and time */
931 if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
933 FileTimeToSystemTime (&ft, &dt);
934 PrintFileDateTime (&dt, dwFlags);
937 /* print file size */
938 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
940 ConOutPrintf (_T(" <DIR> "));
945 ULARGE_INTEGER uliSize;
947 uliSize.LowPart = file.nFileSizeLow;
948 uliSize.HighPart = file.nFileSizeHigh;
950 ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
951 ConOutPrintf (_T(" %20s"), buffer);
953 bytecount.QuadPart += uliSize.QuadPart;
957 /* print long filename */
958 ConOutPrintf (_T(" %s\n"), file.cFileName);
962 if (file.cFileName[0] == _T('.'))
963 ConOutPrintf (_T("%-13s "), file.cFileName);
964 else if (file.cAlternateFileName[0] == _T('\0'))
966 TCHAR szShortName[13];
969 _tcsncpy (szShortName, file.cFileName, 13);
970 ext = _tcschr (szShortName, _T('.'));
975 ConOutPrintf (_T("%-8s %-3s "), szShortName, ext);
981 ext = _tcschr (file.cAlternateFileName, _T('.'));
986 ConOutPrintf (_T("%-8s %-3s "), file.cAlternateFileName, ext);
989 /* print file size */
990 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
992 ConOutPrintf (_T("%-14s"), _T("<DIR>"));
997 ULARGE_INTEGER uliSize;
999 uliSize.LowPart = file.nFileSizeLow;
1000 uliSize.HighPart = file.nFileSizeHigh;
1001 ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
1002 ConOutPrintf (_T(" %10s "), buffer);
1003 bytecount.QuadPart += uliSize.QuadPart;
1007 /* print file date and time */
1008 if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
1010 FileTimeToSystemTime (&ft, &dt);
1011 PrintFileDateTime (&dt, dwFlags);
1014 /* print long filename */
1015 ConOutPrintf (_T(" %s\n"), file.cFileName);
1018 if (IncLine (pLine, dwFlags))
1022 while (FindNextFile (hFile, &file));
1025 /* Rob Lake, need to make clean output */
1026 /* JPP 07/08/1998 added check for count != 0 */
1027 if ((dwFlags & DIR_WIDE) && (count != 0))
1029 ConOutPrintf (_T("\n"));
1030 if (IncLine (pLine, dwFlags))
1034 if (filecount || dircount)
1036 recurse_dir_cnt += dircount;
1037 recurse_file_cnt += filecount;
1038 recurse_bytes.QuadPart += bytecount.QuadPart;
1041 if (PrintSummary (szPath, filecount, dircount, bytecount, pLine, dwFlags))
1046 error_file_not_found ();
1055 * _Read_Dir: Actual function that does recursive listing
1058 DirRead (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
1060 TCHAR szFullPath[MAX_PATH];
1061 WIN32_FIND_DATA file;
1064 _tcscpy (szFullPath, szPath);
1065 if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
1066 _tcscat (szFullPath, _T("\\"));
1067 _tcscat (szFullPath, szFilespec);
1069 hFile = FindFirstFile (szFullPath, &file);
1070 if (hFile == INVALID_HANDLE_VALUE)
1075 /* don't list "." and ".." */
1076 if (_tcscmp (file.cFileName, _T(".")) == 0 ||
1077 _tcscmp (file.cFileName, _T("..")) == 0)
1080 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1082 _tcscpy (szFullPath, szPath);
1083 if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
1084 _tcscat (szFullPath, _T("\\"));
1085 _tcscat (szFullPath, file.cFileName);
1087 if (DirList (szFullPath, szFilespec, pLine, dwFlags))
1093 if ((dwFlags & DIR_BARE) == 0)
1095 ConOutPrintf (_T("\n"));
1096 if (IncLine (pLine, dwFlags) != 0)
1098 ConOutPrintf (_T("\n"));
1099 if (IncLine (pLine, dwFlags) != 0)
1103 if (DirRead (szFullPath, szFilespec, pLine, dwFlags) == 1)
1110 while (FindNextFile (hFile, &file));
1112 if (!FindClose (hFile))
1120 * do_recurse: Sets up for recursive directory listing
1123 DirRecurse (LPTSTR szPath, LPTSTR szSpec, LPINT pLine, DWORD dwFlags)
1125 if (!PrintDirectoryHeader (szPath, pLine, dwFlags))
1128 if (DirList (szPath, szSpec, pLine, dwFlags))
1131 if ((dwFlags & DIR_BARE) == 0)
1133 ConOutPrintf (_T("\n"));
1134 if (IncLine (pLine, dwFlags))
1138 if (DirRead (szPath, szSpec, pLine, dwFlags))
1141 if ((dwFlags & DIR_BARE) == 0)
1142 ConOutPrintf (_T("Total files listed:\n"));
1144 dwFlags &= ~DIR_RECURSE;
1146 if (PrintSummary (szPath, recurse_file_cnt,
1147 recurse_dir_cnt, recurse_bytes, pLine, dwFlags))
1150 if ((dwFlags & DIR_BARE) == 0)
1152 ConOutPrintf (_T("\n"));
1153 if (IncLine (pLine, dwFlags))
1164 * internal dir command
1166 INT CommandDir (LPTSTR first, LPTSTR rest)
1168 DWORD dwFlags = DIR_NEW | DIR_FOUR;
1170 TCHAR szPath[MAX_PATH];
1171 TCHAR szFilespec[MAX_PATH];
1176 recurse_dir_cnt = 0L;
1177 recurse_file_cnt = 0L;
1178 recurse_bytes.QuadPart = 0;
1180 /* read the parameters from the DIRCMD environment variable */
1181 if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
1183 if (!DirReadParam (dircmd, ¶m, &dwFlags))
1187 /* read the parameters */
1188 if (!DirReadParam (rest, ¶m, &dwFlags))
1191 /* default to current directory */
1195 /* parse the directory info */
1196 if (DirParsePathspec (param, szPath, szFilespec))
1199 if (dwFlags & DIR_RECURSE)
1201 if (IncLine (&nLine, dwFlags))
1203 if (DirRecurse (szPath, szFilespec, &nLine, dwFlags))
1208 /* print the header */
1209 if (!PrintDirectoryHeader (szPath, &nLine, dwFlags))
1212 if (DirList (szPath, szFilespec, &nLine, dwFlags))