1 /* $Id: dir.c,v 1.11 2001/07/11 20:26:58 ekohl Exp $
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 /* flag definitions */
135 DIR_RECURSE
= 0x0001,
137 DIR_WIDE
= 0x0004, /* Rob Lake */
138 DIR_BARE
= 0x0008, /* Rob Lake */
139 DIR_ALL
= 0x0010, /* Rob Lake */
140 DIR_LWR
= 0x0020, /* Rob Lake */
141 DIR_SORT
= 0x0040, /* /O sort */
142 DIR_NEW
= 0x0080, /* /N new style */
143 DIR_FOUR
= 0x0100 /* /4 four digit year */
147 /* Globally save the # of dirs, files and bytes,
148 * probabaly later pass them to functions. Rob Lake */
149 static ULONG recurse_dir_cnt
;
150 static ULONG recurse_file_cnt
;
151 static ULARGE_INTEGER recurse_bytes
;
157 * displays help screen for dir
160 static VOID
Help (VOID
)
162 ConOutPuts (_T("Displays a list of files and subdirectories in a directory.\n"
164 "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
166 " [drive:][path][filename]\n"
167 " Specifies drive, directory, and/or files to list.\n"
169 " /A Displays files with HIDDEN SYSTEM attributes\n"
170 " default is ARCHIVE and READ ONLY\n"
171 " /B Uses bare format (no heading information or summary).\n"
172 " /L Uses lowercase.\n"
173 " /N New long list format where filenames are on the far right.\n"
174 " /S Displays files in specified directory and all subdirectories\n"
175 " /P Pauses after each screen full\n"
176 " /W Prints in wide format\n"
177 " /4 Display four digit years.\n"
179 "Switches may be present in the DIRCMD environment variable. Use\n"
180 "of the - (hyphen) can turn off defined swtiches. Ex. /-W would\n"
181 "turn off printing in wide format.\n"
189 * read the parameters from the command line
192 DirReadParam (LPTSTR line
, LPTSTR
*param
, LPDWORD lpFlags
)
201 /* scan the command line, processing switches */
205 if (*line
== _T('/') || slash
)
210 if (*line
== _T('-'))
213 if (_totupper (*line
) == _T('S'))
214 *lpFlags
&= ~DIR_RECURSE
;
215 else if (_totupper (*line
) == _T('P'))
216 *lpFlags
&= ~DIR_PAGE
;
217 else if (_totupper (*line
) == _T('W'))
218 *lpFlags
&= ~DIR_WIDE
;
219 else if (_totupper (*line
) == _T('B'))
220 *lpFlags
&= ~DIR_BARE
;
221 else if (_totupper (*line
) == _T('A'))
222 *lpFlags
&= ~DIR_ALL
;
223 else if (_totupper (*line
) == _T('L'))
224 *lpFlags
&= ~DIR_LWR
;
225 else if (_totupper (*line
) == _T('N'))
226 *lpFlags
&= ~DIR_NEW
;
227 else if (_totupper (*line
) == _T('O'))
228 *lpFlags
&= ~DIR_SORT
;
229 else if (_totupper (*line
) == _T('4'))
230 *lpFlags
&= ~DIR_FOUR
;
233 error_invalid_switch ((TCHAR
)_totupper (*line
));
241 if (_totupper (*line
) == _T('S'))
242 *lpFlags
|= DIR_RECURSE
;
243 else if (_totupper (*line
) == _T('P'))
244 *lpFlags
|= DIR_PAGE
;
245 else if (_totupper (*line
) == _T('W'))
246 *lpFlags
|= DIR_WIDE
;
247 else if (_totupper (*line
) == _T('B'))
248 *lpFlags
|= DIR_BARE
;
249 else if (_totupper (*line
) == _T('A'))
251 else if (_totupper (*line
) == _T('L'))
253 else if (_totupper (*line
) == _T('N'))
255 else if (_totupper (*line
) == _T('O'))
256 *lpFlags
|= DIR_SORT
;
257 else if (_totupper (*line
) == _T('4'))
258 *lpFlags
|= DIR_FOUR
;
259 else if (*line
== _T('?'))
266 error_invalid_switch ((TCHAR
)_totupper (*line
));
274 /* process parameter */
275 if (!_istspace (*line
))
279 error_too_many_parameters (*param
);
285 /* skip to end of line or next whitespace or next / */
286 while (*line
&& !_istspace (*line
) && *line
!= _T('/'))
289 /* if end of line, return */
293 /* if parameter, remember to process it later */
294 if (*line
== _T('/'))
306 error_invalid_switch ((TCHAR
)_totupper (*line
));
317 * extend the filespec, possibly adding wildcards
320 ExtendFilespec (LPTSTR file
)
327 /* if no file spec, change to "*.*" */
328 if (*file
== _T('\0'))
330 _tcscpy (file
, _T("*.*"));
334 /* if starts with . add * in front */
335 if (*file
== _T('.'))
337 memmove (&file
[1], &file
[0], (_tcslen (file
) + 1) * sizeof(TCHAR
));
342 if (!_tcschr (file
, _T('.')))
344 _tcscat (file
, _T(".*"));
348 /* if last character is '.' add '*' */
349 len
= _tcslen (file
);
350 if (file
[len
- 1] == _T('.'))
352 _tcscat (file
, _T("*"));
361 * split the pathspec into drive, directory, and filespec
364 DirParsePathspec (LPTSTR szPathspec
, LPTSTR szPath
, LPTSTR szFilespec
)
366 TCHAR szOrigPath
[MAX_PATH
];
370 BOOL bWildcards
= FALSE
;
372 GetCurrentDirectory (MAX_PATH
, szOrigPath
);
374 /* get the drive and change to it */
375 if (szPathspec
[1] == _T(':'))
377 TCHAR szRootPath
[] = _T("A:");
379 szRootPath
[0] = szPathspec
[0];
380 start
= szPathspec
+ 2;
381 SetCurrentDirectory (szRootPath
);
389 /* check for wildcards */
390 for (i
= 0; szPathspec
[i
]; i
++)
392 if (szPathspec
[i
] == _T('*') || szPathspec
[i
] == _T('?'))
396 /* check if this spec is a directory */
399 if (SetCurrentDirectory (szPathspec
))
401 _tcscpy (szFilespec
, _T("*.*"));
403 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
405 szFilespec
[0] = _T('\0');
406 SetCurrentDirectory (szOrigPath
);
407 error_out_of_memory();
411 SetCurrentDirectory (szOrigPath
);
416 /* find the file spec */
417 tmp
= _tcsrchr (start
, _T('\\'));
419 /* if no path is specified */
422 _tcscpy (szFilespec
, start
);
423 ExtendFilespec (szFilespec
);
424 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
426 szFilespec
[0] = _T('\0');
427 SetCurrentDirectory (szOrigPath
);
428 error_out_of_memory();
432 SetCurrentDirectory (szOrigPath
);
436 /* get the filename */
437 _tcscpy (szFilespec
, tmp
+1);
438 ExtendFilespec (szFilespec
);
442 /* change to this directory and get its full name */
443 if (!SetCurrentDirectory (start
))
446 szFilespec
[0] = _T('\0');
447 SetCurrentDirectory (szOrigPath
);
448 error_path_not_found ();
452 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
455 szFilespec
[0] = _T('\0');
456 SetCurrentDirectory (szOrigPath
);
457 error_out_of_memory ();
463 SetCurrentDirectory (szOrigPath
);
472 * increment our line if paginating, display message at end of screen
475 IncLine (LPINT pLine
, DWORD dwFlags
)
477 if (!(dwFlags
& DIR_PAGE
))
482 if (*pLine
>= (int)maxy
- 2)
485 return (PagePrompt () == PROMPT_BREAK
);
493 * PrintDirectoryHeader
495 * print the header for the dir command
498 PrintDirectoryHeader (LPTSTR szPath
, LPINT pLine
, DWORD dwFlags
)
500 TCHAR szRootName
[] = _T("A:\\");
504 if (dwFlags
& DIR_BARE
)
507 /* get the media ID of the drive */
508 szRootName
[0] = szPath
[0];
509 if (!GetVolumeInformation (szRootName
, szVolName
, 80, &dwSerialNr
,
510 NULL
, NULL
, NULL
, 0))
512 error_invalid_drive();
516 /* print drive info */
517 ConOutPrintf (_T(" Volume in drive %c"), szRootName
[0]);
519 if (szVolName
[0] != _T('\0'))
520 ConOutPrintf (_T(" is %s\n"), szVolName
);
522 ConOutPrintf (_T(" has no label\n"));
524 if (IncLine (pLine
, dwFlags
))
527 /* print the volume serial number if the return was successful */
528 ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
531 if (IncLine (pLine
, dwFlags
))
541 * insert commas into a number
544 ConvertULong (ULONG num
, LPTSTR des
, INT len
)
561 if (((c
+ 1) % (nNumberGroups
+ 1)) == 0)
562 temp
[30 - c
++] = cThousandSeparator
;
563 temp
[30 - c
++] = (TCHAR
)(num
% 10) + _T('0');
567 for (n
= 0; n
<= c
; n
++)
568 des
[n
] = temp
[31 - c
+ n
];
576 ConvertULargeInteger (ULARGE_INTEGER num
, LPTSTR des
, INT len
)
582 if (num
.QuadPart
== 0)
591 while (num
.QuadPart
> 0)
593 if (((c
+ 1) % (nNumberGroups
+ 1)) == 0)
594 temp
[30 - c
++] = cThousandSeparator
;
595 temp
[30 - c
++] = (TCHAR
)(num
.QuadPart
% 10) + _T('0');
599 for (n
= 0; n
<= c
; n
++)
600 des
[n
] = temp
[31 - c
+ n
];
608 PrintFileDateTime (LPSYSTEMTIME dt
, DWORD dwFlags
)
610 WORD wYear
= (dwFlags
& DIR_FOUR
) ? dt
->wYear
: dt
->wYear
%100;
616 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
617 dt
->wMonth
, cDateSeparator
, dt
->wDay
, cDateSeparator
, wYear
);
621 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
622 dt
->wDay
, cDateSeparator
, dt
->wMonth
, cDateSeparator
, wYear
);
626 ConOutPrintf (_T("%d%c%.2d%c%.2d"),
627 wYear
, cDateSeparator
, dt
->wMonth
, cDateSeparator
, dt
->wDay
);
633 case 0: /* 12 hour format */
635 ConOutPrintf (_T(" %2d%c%.2u%c"),
636 (dt
->wHour
== 0 ? 12 : (dt
->wHour
<= 12 ? dt
->wHour
: dt
->wHour
- 12)),
638 dt
->wMinute
, (dt
->wHour
<= 11 ? 'a' : 'p'));
641 case 1: /* 24 hour format */
642 ConOutPrintf (_T(" %2d%c%.2u"),
643 dt
->wHour
, cTimeSeparator
, dt
->wMinute
);
650 * print_summary: prints dir summary
651 * Added by Rob Lake 06/17/98 to compact code
652 * Just copied Tim's Code and patched it a bit
656 PrintSummary (LPTSTR szPath
, ULONG ulFiles
, ULONG ulDirs
, ULARGE_INTEGER bytes
,
657 LPINT pLine
, DWORD dwFlags
)
661 if (dwFlags
& DIR_BARE
)
664 /* print number of files and bytes */
665 ConvertULong (ulFiles
, buffer
, sizeof(buffer
));
666 ConOutPrintf (_T(" %6s File%c"),
667 buffer
, ulFiles
== 1 ? _T(' ') : _T('s'));
669 ConvertULargeInteger (bytes
, buffer
, sizeof(buffer
));
670 ConOutPrintf (_T(" %15s byte%c\n"),
671 buffer
, bytes
.QuadPart
== 1 ? _T(' ') : _T('s'));
673 if (IncLine (pLine
, dwFlags
))
676 /* print number of dirs and bytes free */
677 ConvertULong (ulDirs
, buffer
, sizeof(buffer
));
678 ConOutPrintf (_T(" %6s Dir%c"),
679 buffer
, ulDirs
== 1 ? _T(' ') : _T('s'));
682 if (!(dwFlags
& DIR_RECURSE
))
684 ULARGE_INTEGER uliFree
;
685 TCHAR szRoot
[] = _T("A:\\");
691 szRoot
[0] = szPath
[0];
692 GetDiskFreeSpace (szRoot
, &dwSecPerCl
, &dwBytPerSec
, &dwFreeCl
, &dwTotCl
);
693 uliFree
.QuadPart
= dwSecPerCl
* dwBytPerSec
* dwFreeCl
;
694 ConvertULargeInteger (uliFree
, buffer
, sizeof(buffer
));
695 ConOutPrintf (_T(" %15s bytes free\n"), buffer
);
698 if (IncLine (pLine
, dwFlags
))
708 * list the files in the directory
711 DirList (LPTSTR szPath
, LPTSTR szFilespec
, LPINT pLine
, DWORD dwFlags
)
713 TCHAR szFullPath
[MAX_PATH
];
714 WIN32_FIND_DATA file
;
715 ULARGE_INTEGER bytecount
;
724 bytecount
.QuadPart
= 0;
726 _tcscpy (szFullPath
, szPath
);
727 if (szFullPath
[_tcslen(szFullPath
) - 1] != _T('\\'))
728 _tcscat (szFullPath
, _T("\\"));
729 _tcscat (szFullPath
, szFilespec
);
731 hFile
= FindFirstFile (szFullPath
, &file
);
732 if (hFile
== INVALID_HANDLE_VALUE
)
734 /* Don't want to print anything if scanning recursively
737 if ((dwFlags
& DIR_RECURSE
) == 0)
740 error_file_not_found ();
741 if (IncLine (pLine
, dwFlags
))
749 /* moved down here because if we are recursively searching and
750 * don't find any files, we don't want just to print
751 * Directory of C:\SOMEDIR
755 if ((dwFlags
& DIR_BARE
) == 0)
757 ConOutPrintf (_T(" Directory of %s\n"), szPath
);
758 if (IncLine (pLine
, dwFlags
))
760 ConOutPrintf (_T("\n"));
761 if (IncLine (pLine
, dwFlags
))
765 /* For counting columns of output */
770 /* next file, if user doesn't want all files */
771 if (!(dwFlags
& DIR_ALL
) &&
772 ((file
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ||
773 (file
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
)))
776 if (dwFlags
& DIR_LWR
)
778 _tcslwr (file
.cAlternateFileName
);
781 if (dwFlags
& DIR_WIDE
&& (dwFlags
& DIR_BARE
) == 0)
783 ULARGE_INTEGER uliSize
;
785 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
787 if (file
.cAlternateFileName
[0] == _T('\0'))
788 _stprintf (buffer
, _T("[%s]"), file
.cFileName
);
790 _stprintf (buffer
, _T("[%s]"), file
.cAlternateFileName
);
795 if (file
.cAlternateFileName
[0] == _T('\0'))
796 _stprintf (buffer
, _T("%s"), file
.cFileName
);
798 _stprintf (buffer
, _T("%s"), file
.cAlternateFileName
);
802 ConOutPrintf (_T("%-15s"), buffer
);
806 /* output 5 columns */
807 ConOutPrintf (_T("\n"));
808 if (IncLine (pLine
, dwFlags
))
813 uliSize
.LowPart
= file
.nFileSizeLow
;
814 uliSize
.HighPart
= file
.nFileSizeHigh
;
815 bytecount
.QuadPart
+= uliSize
.QuadPart
;
817 else if (dwFlags
& DIR_BARE
)
819 ULARGE_INTEGER uliSize
;
821 if (_tcscmp (file
.cFileName
, _T(".")) == 0 ||
822 _tcscmp (file
.cFileName
, _T("..")) == 0)
825 if (dwFlags
& DIR_RECURSE
)
829 _tcscpy (dir
, szPath
);
830 _tcscat (dir
, _T("\\"));
831 if (dwFlags
& DIR_LWR
)
836 ConOutPrintf (_T("%-13s\n"), file
.cFileName
);
837 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
841 if (IncLine (pLine
, dwFlags
))
844 uliSize
.LowPart
= file
.nFileSizeLow
;
845 uliSize
.HighPart
= file
.nFileSizeHigh
;
846 bytecount
.QuadPart
+= uliSize
.QuadPart
;
850 if (dwFlags
& DIR_NEW
)
852 /* print file date and time */
853 if (FileTimeToLocalFileTime (&file
.ftLastWriteTime
, &ft
))
855 FileTimeToSystemTime (&ft
, &dt
);
856 PrintFileDateTime (&dt
, dwFlags
);
859 /* print file size */
860 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
862 ConOutPrintf (_T(" <DIR> "));
867 ULARGE_INTEGER uliSize
;
869 uliSize
.LowPart
= file
.nFileSizeLow
;
870 uliSize
.HighPart
= file
.nFileSizeHigh
;
872 ConvertULargeInteger (uliSize
, buffer
, sizeof(buffer
));
873 ConOutPrintf (_T(" %20s"), buffer
);
875 bytecount
.QuadPart
+= uliSize
.QuadPart
;
879 /* print long filename */
880 ConOutPrintf (_T(" %s\n"), file
.cFileName
);
884 if (file
.cFileName
[0] == _T('.'))
885 ConOutPrintf (_T("%-13s "), file
.cFileName
);
886 else if (file
.cAlternateFileName
[0] == _T('\0'))
888 TCHAR szShortName
[13];
891 _tcsncpy (szShortName
, file
.cFileName
, 13);
892 ext
= _tcschr (szShortName
, _T('.'));
897 ConOutPrintf (_T("%-8s %-3s "), szShortName
, ext
);
903 ext
= _tcschr (file
.cAlternateFileName
, _T('.'));
908 ConOutPrintf (_T("%-8s %-3s "), file
.cAlternateFileName
, ext
);
911 /* print file size */
912 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
914 ConOutPrintf ("%-14s", "<DIR>");
919 ULARGE_INTEGER uliSize
;
921 uliSize
.LowPart
= file
.nFileSizeLow
;
922 uliSize
.HighPart
= file
.nFileSizeHigh
;
923 ConvertULargeInteger (uliSize
, buffer
, sizeof(buffer
));
924 ConOutPrintf (_T(" %10s "), buffer
);
925 bytecount
.QuadPart
+= uliSize
.QuadPart
;
929 /* print file date and time */
930 if (FileTimeToLocalFileTime (&file
.ftLastWriteTime
, &ft
))
932 FileTimeToSystemTime (&ft
, &dt
);
933 PrintFileDateTime (&dt
, dwFlags
);
936 /* print long filename */
937 ConOutPrintf (" %s\n", file
.cFileName
);
940 if (IncLine (pLine
, dwFlags
))
944 while (FindNextFile (hFile
, &file
));
947 /* Rob Lake, need to make clean output */
948 /* JPP 07/08/1998 added check for count != 0 */
949 if ((dwFlags
& DIR_WIDE
) && (count
!= 0))
951 ConOutPrintf (_T("\n"));
952 if (IncLine (pLine
, dwFlags
))
956 if (filecount
|| dircount
)
958 recurse_dir_cnt
+= dircount
;
959 recurse_file_cnt
+= filecount
;
960 recurse_bytes
.QuadPart
+= bytecount
.QuadPart
;
963 if (PrintSummary (szPath
, filecount
, dircount
, bytecount
, pLine
, dwFlags
))
968 error_file_not_found ();
977 * _Read_Dir: Actual function that does recursive listing
980 DirRead (LPTSTR szPath
, LPTSTR szFilespec
, LPINT pLine
, DWORD dwFlags
)
982 TCHAR szFullPath
[MAX_PATH
];
983 WIN32_FIND_DATA file
;
986 _tcscpy (szFullPath
, szPath
);
987 if (szFullPath
[_tcslen (szFullPath
) - 1] != _T('\\'))
988 _tcscat (szFullPath
, _T("\\"));
989 _tcscat (szFullPath
, szFilespec
);
991 hFile
= FindFirstFile (szFullPath
, &file
);
992 if (hFile
== INVALID_HANDLE_VALUE
)
997 /* don't list "." and ".." */
998 if (_tcscmp (file
.cFileName
, _T(".")) == 0 ||
999 _tcscmp (file
.cFileName
, _T("..")) == 0)
1002 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1004 _tcscpy (szFullPath
, szPath
);
1005 if (szFullPath
[_tcslen (szFullPath
) - 1] != _T('\\'))
1006 _tcscat (szFullPath
, _T("\\"));
1007 _tcscat (szFullPath
, file
.cFileName
);
1009 if (DirList (szFullPath
, szFilespec
, pLine
, dwFlags
))
1015 if ((dwFlags
& DIR_BARE
) == 0)
1017 ConOutPrintf ("\n");
1018 if (IncLine (pLine
, dwFlags
) != 0)
1020 ConOutPrintf ("\n");
1021 if (IncLine (pLine
, dwFlags
) != 0)
1025 if (DirRead (szFullPath
, szFilespec
, pLine
, dwFlags
) == 1)
1032 while (FindNextFile (hFile
, &file
));
1034 if (!FindClose (hFile
))
1042 * do_recurse: Sets up for recursive directory listing
1045 DirRecurse (LPTSTR szPath
, LPTSTR szSpec
, LPINT pLine
, DWORD dwFlags
)
1047 if (!PrintDirectoryHeader (szPath
, pLine
, dwFlags
))
1050 if (DirList (szPath
, szSpec
, pLine
, dwFlags
))
1053 if ((dwFlags
& DIR_BARE
) == 0)
1055 ConOutPrintf (_T("\n"));
1056 if (IncLine (pLine
, dwFlags
))
1060 if (DirRead (szPath
, szSpec
, pLine
, dwFlags
))
1063 if ((dwFlags
& DIR_BARE
) == 0)
1064 ConOutPrintf (_T("Total files listed:\n"));
1066 dwFlags
&= ~DIR_RECURSE
;
1068 if (PrintSummary (szPath
, recurse_file_cnt
,
1069 recurse_dir_cnt
, recurse_bytes
, pLine
, dwFlags
))
1072 if ((dwFlags
& DIR_BARE
) == 0)
1074 ConOutPrintf (_T("\n"));
1075 if (IncLine (pLine
, dwFlags
))
1086 * internal dir command
1088 INT
CommandDir (LPTSTR first
, LPTSTR rest
)
1090 DWORD dwFlags
= DIR_NEW
| DIR_FOUR
;
1092 TCHAR szPath
[MAX_PATH
];
1093 TCHAR szFilespec
[MAX_PATH
];
1098 recurse_dir_cnt
= 0L;
1099 recurse_file_cnt
= 0L;
1100 recurse_bytes
.QuadPart
= 0;
1102 /* read the parameters from the DIRCMD environment variable */
1103 if (GetEnvironmentVariable (_T("DIRCMD"), dircmd
, 256))
1105 if (!DirReadParam (dircmd
, ¶m
, &dwFlags
))
1109 /* read the parameters */
1110 if (!DirReadParam (rest
, ¶m
, &dwFlags
))
1113 /* default to current directory */
1117 /* parse the directory info */
1118 if (DirParsePathspec (param
, szPath
, szFilespec
))
1121 if (dwFlags
& DIR_RECURSE
)
1123 if (IncLine (&nLine
, dwFlags
))
1125 if (DirRecurse (szPath
, szFilespec
, &nLine
, dwFlags
))
1130 /* print the header */
1131 if (!PrintDirectoryHeader (szPath
, &nLine
, dwFlags
))
1134 if (DirList (szPath
, szFilespec
, &nLine
, dwFlags
))