1 /* $Id: dir.c,v 1.9 1999/12/15 00:50:41 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.
117 #ifdef INCLUDE_CMD_DIR
129 /* flag definitions */
132 DIR_RECURSE
= 0x0001,
134 DIR_WIDE
= 0x0004, /* Rob Lake */
135 DIR_BARE
= 0x0008, /* Rob Lake */
136 DIR_ALL
= 0x0010, /* Rob Lake */
137 DIR_LWR
= 0x0020, /* Rob Lake */
138 DIR_SORT
= 0x0040, /* /O sort */
139 DIR_NEW
= 0x0080, /* /N new style */
140 DIR_FOUR
= 0x0100 /* /4 four digit year */
144 /* Globally save the # of dirs, files and bytes,
145 * probabaly later pass them to functions. Rob Lake */
146 static ULONG recurse_dir_cnt
;
147 static ULONG recurse_file_cnt
;
148 static ULARGE_INTEGER recurse_bytes
;
154 * displays help screen for dir
157 static VOID
Help (VOID
)
159 ConOutPuts (_T("Displays a list of files and subdirectories in a directory.\n"
161 "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
163 " [drive:][path][filename]\n"
164 " Specifies drive, directory, and/or files to list.\n"
166 " /A Displays files with HIDDEN SYSTEM attributes\n"
167 " default is ARCHIVE and READ ONLY\n"
168 " /B Uses bare format (no heading information or summary).\n"
169 " /L Uses lowercase.\n"
170 " /N New long list format where filenames are on the far right.\n"
171 " /S Displays files in specified directory and all subdirectories\n"
172 " /P Pauses after each screen full\n"
173 " /W Prints in wide format\n"
174 " /4 Display four digit years.\n"
176 "Switches may be present in the DIRCMD environment variable. Use\n"
177 "of the - (hyphen) can turn off defined swtiches. Ex. /-W would\n"
178 "turn off printing in wide format.\n"
186 * read the parameters from the command line
189 DirReadParam (LPTSTR line
, LPTSTR
*param
, LPDWORD lpFlags
)
198 /* scan the command line, processing switches */
202 if (*line
== _T('/') || slash
)
207 if (*line
== _T('-'))
210 if (_totupper (*line
) == _T('S'))
211 *lpFlags
&= ~DIR_RECURSE
;
212 else if (_totupper (*line
) == _T('P'))
213 *lpFlags
&= ~DIR_PAGE
;
214 else if (_totupper (*line
) == _T('W'))
215 *lpFlags
&= ~DIR_WIDE
;
216 else if (_totupper (*line
) == _T('B'))
217 *lpFlags
&= ~DIR_BARE
;
218 else if (_totupper (*line
) == _T('A'))
219 *lpFlags
&= ~DIR_ALL
;
220 else if (_totupper (*line
) == _T('L'))
221 *lpFlags
&= ~DIR_LWR
;
222 else if (_totupper (*line
) == _T('N'))
223 *lpFlags
&= ~DIR_NEW
;
224 else if (_totupper (*line
) == _T('O'))
225 *lpFlags
&= ~DIR_SORT
;
226 else if (_totupper (*line
) == _T('4'))
227 *lpFlags
&= ~DIR_FOUR
;
230 error_invalid_switch ((TCHAR
)_totupper (*line
));
238 if (_totupper (*line
) == _T('S'))
239 *lpFlags
|= DIR_RECURSE
;
240 else if (_totupper (*line
) == _T('P'))
241 *lpFlags
|= DIR_PAGE
;
242 else if (_totupper (*line
) == _T('W'))
243 *lpFlags
|= DIR_WIDE
;
244 else if (_totupper (*line
) == _T('B'))
245 *lpFlags
|= DIR_BARE
;
246 else if (_totupper (*line
) == _T('A'))
248 else if (_totupper (*line
) == _T('L'))
250 else if (_totupper (*line
) == _T('N'))
252 else if (_totupper (*line
) == _T('O'))
253 *lpFlags
|= DIR_SORT
;
254 else if (_totupper (*line
) == _T('4'))
255 *lpFlags
|= DIR_FOUR
;
256 else if (*line
== _T('?'))
263 error_invalid_switch ((TCHAR
)_totupper (*line
));
271 /* process parameter */
272 if (!_istspace (*line
))
276 error_too_many_parameters (*param
);
282 /* skip to end of line or next whitespace or next / */
283 while (*line
&& !_istspace (*line
) && *line
!= _T('/'))
286 /* if end of line, return */
290 /* if parameter, remember to process it later */
291 if (*line
== _T('/'))
303 error_invalid_switch ((TCHAR
)_totupper (*line
));
314 * extend the filespec, possibly adding wildcards
317 ExtendFilespec (LPTSTR file
)
324 /* if no file spec, change to "*.*" */
325 if (*file
== _T('\0'))
327 _tcscpy (file
, _T("*.*"));
331 /* if starts with . add * in front */
332 if (*file
== _T('.'))
334 memmove (&file
[1], &file
[0], (_tcslen (file
) + 1) * sizeof(TCHAR
));
339 if (!_tcschr (file
, _T('.')))
341 _tcscat (file
, _T(".*"));
345 /* if last character is '.' add '*' */
346 len
= _tcslen (file
);
347 if (file
[len
- 1] == _T('.'))
349 _tcscat (file
, _T("*"));
358 * split the pathspec into drive, directory, and filespec
361 DirParsePathspec (LPTSTR szPathspec
, LPTSTR szPath
, LPTSTR szFilespec
)
363 TCHAR szOrigPath
[MAX_PATH
];
367 BOOL bWildcards
= FALSE
;
369 GetCurrentDirectory (MAX_PATH
, szOrigPath
);
371 /* get the drive and change to it */
372 if (szPathspec
[1] == _T(':'))
374 TCHAR szRootPath
[] = _T("A:");
376 szRootPath
[0] = szPathspec
[0];
377 start
= szPathspec
+ 2;
378 SetCurrentDirectory (szRootPath
);
386 /* check for wildcards */
387 for (i
= 0; szPathspec
[i
]; i
++)
389 if (szPathspec
[i
] == _T('*') || szPathspec
[i
] == _T('?'))
393 /* check if this spec is a directory */
396 if (SetCurrentDirectory (szPathspec
))
398 _tcscpy (szFilespec
, _T("*.*"));
400 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
402 szFilespec
[0] = _T('\0');
403 SetCurrentDirectory (szOrigPath
);
404 error_out_of_memory();
408 SetCurrentDirectory (szOrigPath
);
413 /* find the file spec */
414 tmp
= _tcsrchr (start
, _T('\\'));
416 /* if no path is specified */
419 _tcscpy (szFilespec
, start
);
420 ExtendFilespec (szFilespec
);
421 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
423 szFilespec
[0] = _T('\0');
424 SetCurrentDirectory (szOrigPath
);
425 error_out_of_memory();
429 SetCurrentDirectory (szOrigPath
);
433 /* get the filename */
434 _tcscpy (szFilespec
, tmp
+1);
435 ExtendFilespec (szFilespec
);
439 /* change to this directory and get its full name */
440 if (!SetCurrentDirectory (start
))
443 szFilespec
[0] = _T('\0');
444 SetCurrentDirectory (szOrigPath
);
445 error_path_not_found ();
449 if (!GetCurrentDirectory (MAX_PATH
, szPath
))
452 szFilespec
[0] = _T('\0');
453 SetCurrentDirectory (szOrigPath
);
454 error_out_of_memory ();
460 SetCurrentDirectory (szOrigPath
);
469 * increment our line if paginating, display message at end of screen
472 IncLine (LPINT pLine
, DWORD dwFlags
)
474 if (!(dwFlags
& DIR_PAGE
))
479 if (*pLine
>= (int)maxy
- 2)
482 return (PagePrompt () == PROMPT_BREAK
);
490 * PrintDirectoryHeader
492 * print the header for the dir command
495 PrintDirectoryHeader (LPTSTR szPath
, LPINT pLine
, DWORD dwFlags
)
497 TCHAR szRootName
[] = _T("A:\\");
501 if (dwFlags
& DIR_BARE
)
504 /* get the media ID of the drive */
505 szRootName
[0] = szPath
[0];
506 if (!GetVolumeInformation (szRootName
, szVolName
, 80, &dwSerialNr
,
507 NULL
, NULL
, NULL
, 0))
509 error_invalid_drive();
513 /* print drive info */
514 ConOutPrintf (_T(" Volume in drive %c"), szRootName
[0]);
516 if (szVolName
[0] != _T('\0'))
517 ConOutPrintf (_T(" is %s\n"), szVolName
);
519 ConOutPrintf (_T(" has no label\n"));
521 if (IncLine (pLine
, dwFlags
))
524 /* print the volume serial number if the return was successful */
525 ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
528 if (IncLine (pLine
, dwFlags
))
538 * insert commas into a number
541 ConvertULong (ULONG num
, LPTSTR des
, INT len
)
558 if (((c
+ 1) % (nNumberGroups
+ 1)) == 0)
559 temp
[30 - c
++] = cThousandSeparator
;
560 temp
[30 - c
++] = (TCHAR
)(num
% 10) + _T('0');
564 for (n
= 0; n
<= c
; n
++)
565 des
[n
] = temp
[31 - c
+ n
];
573 ConvertULargeInteger (ULARGE_INTEGER num
, LPTSTR des
, INT len
)
579 if (num
.QuadPart
== 0)
588 while (num
.QuadPart
> 0)
590 if (((c
+ 1) % (nNumberGroups
+ 1)) == 0)
591 temp
[30 - c
++] = cThousandSeparator
;
592 temp
[30 - c
++] = (TCHAR
)(num
.QuadPart
% 10) + _T('0');
596 for (n
= 0; n
<= c
; n
++)
597 des
[n
] = temp
[31 - c
+ n
];
605 PrintFileDateTime (LPSYSTEMTIME dt
, DWORD dwFlags
)
607 WORD wYear
= (dwFlags
& DIR_FOUR
) ? dt
->wYear
: dt
->wYear
%100;
613 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
614 dt
->wMonth
, cDateSeparator
, dt
->wDay
, cDateSeparator
, wYear
);
618 ConOutPrintf (_T("%.2d%c%.2d%c%d"),
619 dt
->wDay
, cDateSeparator
, dt
->wMonth
, cDateSeparator
, wYear
);
623 ConOutPrintf (_T("%d%c%.2d%c%.2d"),
624 wYear
, cDateSeparator
, dt
->wMonth
, cDateSeparator
, dt
->wDay
);
630 case 0: /* 12 hour format */
632 ConOutPrintf (_T(" %2d%c%.2u%c"),
633 (dt
->wHour
== 0 ? 12 : (dt
->wHour
<= 12 ? dt
->wHour
: dt
->wHour
- 12)),
635 dt
->wMinute
, (dt
->wHour
<= 11 ? 'a' : 'p'));
638 case 1: /* 24 hour format */
639 ConOutPrintf (_T(" %2d%c%.2u"),
640 dt
->wHour
, cTimeSeparator
, dt
->wMinute
);
647 * print_summary: prints dir summary
648 * Added by Rob Lake 06/17/98 to compact code
649 * Just copied Tim's Code and patched it a bit
653 PrintSummary (LPTSTR szPath
, ULONG ulFiles
, ULONG ulDirs
, ULARGE_INTEGER bytes
,
654 LPINT pLine
, DWORD dwFlags
)
658 if (dwFlags
& DIR_BARE
)
661 /* print number of files and bytes */
662 ConvertULong (ulFiles
, buffer
, sizeof(buffer
));
663 ConOutPrintf (_T(" %6s File%c"),
664 buffer
, ulFiles
== 1 ? _T(' ') : _T('s'));
666 ConvertULargeInteger (bytes
, buffer
, sizeof(buffer
));
667 ConOutPrintf (_T(" %15s byte%c\n"),
668 buffer
, bytes
.QuadPart
== 1 ? _T(' ') : _T('s'));
670 if (IncLine (pLine
, dwFlags
))
673 /* print number of dirs and bytes free */
674 ConvertULong (ulDirs
, buffer
, sizeof(buffer
));
675 ConOutPrintf (_T(" %6s Dir%c"),
676 buffer
, ulDirs
== 1 ? _T(' ') : _T('s'));
679 if (!(dwFlags
& DIR_RECURSE
))
681 ULARGE_INTEGER uliFree
;
682 TCHAR szRoot
[] = _T("A:\\");
688 szRoot
[0] = szPath
[0];
689 GetDiskFreeSpace (szRoot
, &dwSecPerCl
, &dwBytPerSec
, &dwFreeCl
, &dwTotCl
);
690 uliFree
.QuadPart
= dwSecPerCl
* dwBytPerSec
* dwFreeCl
;
691 ConvertULargeInteger (uliFree
, buffer
, sizeof(buffer
));
692 ConOutPrintf (_T(" %15s bytes free\n"), buffer
);
695 if (IncLine (pLine
, dwFlags
))
705 * list the files in the directory
708 DirList (LPTSTR szPath
, LPTSTR szFilespec
, LPINT pLine
, DWORD dwFlags
)
710 TCHAR szFullPath
[MAX_PATH
];
711 WIN32_FIND_DATA file
;
712 ULARGE_INTEGER bytecount
;
721 bytecount
.QuadPart
= 0;
723 _tcscpy (szFullPath
, szPath
);
724 if (szFullPath
[_tcslen(szFullPath
) - 1] != _T('\\'))
725 _tcscat (szFullPath
, _T("\\"));
726 _tcscat (szFullPath
, szFilespec
);
728 hFile
= FindFirstFile (szFullPath
, &file
);
729 if (hFile
== INVALID_HANDLE_VALUE
)
731 /* Don't want to print anything if scanning recursively
734 if ((dwFlags
& DIR_RECURSE
) == 0)
737 error_file_not_found ();
738 if (IncLine (pLine
, dwFlags
))
746 /* moved down here because if we are recursively searching and
747 * don't find any files, we don't want just to print
748 * Directory of C:\SOMEDIR
752 if ((dwFlags
& DIR_BARE
) == 0)
754 ConOutPrintf (_T(" Directory of %s\n"), szPath
);
755 if (IncLine (pLine
, dwFlags
))
757 ConOutPrintf (_T("\n"));
758 if (IncLine (pLine
, dwFlags
))
762 /* For counting columns of output */
767 /* next file, if user doesn't want all files */
768 if (!(dwFlags
& DIR_ALL
) &&
769 ((file
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) ||
770 (file
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
)))
773 if (dwFlags
& DIR_LWR
)
775 _tcslwr (file
.cAlternateFileName
);
778 if (dwFlags
& DIR_WIDE
&& (dwFlags
& DIR_BARE
) == 0)
780 ULARGE_INTEGER uliSize
;
782 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
784 if (file
.cAlternateFileName
[0] == _T('\0'))
785 _stprintf (buffer
, _T("[%s]"), file
.cFileName
);
787 _stprintf (buffer
, _T("[%s]"), file
.cAlternateFileName
);
792 if (file
.cAlternateFileName
[0] == _T('\0'))
793 _stprintf (buffer
, _T("%s"), file
.cFileName
);
795 _stprintf (buffer
, _T("%s"), file
.cAlternateFileName
);
799 ConOutPrintf (_T("%-15s"), buffer
);
803 /* output 5 columns */
804 ConOutPrintf (_T("\n"));
805 if (IncLine (pLine
, dwFlags
))
810 uliSize
.u
.LowPart
= file
.nFileSizeLow
;
811 uliSize
.u
.HighPart
= file
.nFileSizeHigh
;
812 bytecount
.QuadPart
+= uliSize
.QuadPart
;
814 else if (dwFlags
& DIR_BARE
)
816 ULARGE_INTEGER uliSize
;
818 if (_tcscmp (file
.cFileName
, _T(".")) == 0 ||
819 _tcscmp (file
.cFileName
, _T("..")) == 0)
822 if (dwFlags
& DIR_RECURSE
)
826 _tcscpy (dir
, szPath
);
827 _tcscat (dir
, _T("\\"));
828 if (dwFlags
& DIR_LWR
)
833 ConOutPrintf (_T("%-13s\n"), file
.cFileName
);
834 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
838 if (IncLine (pLine
, dwFlags
))
841 uliSize
.u
.LowPart
= file
.nFileSizeLow
;
842 uliSize
.u
.HighPart
= file
.nFileSizeHigh
;
843 bytecount
.QuadPart
+= uliSize
.QuadPart
;
847 if (dwFlags
& DIR_NEW
)
849 /* print file date and time */
850 if (FileTimeToLocalFileTime (&file
.ftLastWriteTime
, &ft
))
852 FileTimeToSystemTime (&ft
, &dt
);
853 PrintFileDateTime (&dt
, dwFlags
);
856 /* print file size */
857 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
859 ConOutPrintf (_T(" <DIR> "));
864 ULARGE_INTEGER uliSize
;
866 uliSize
.u
.LowPart
= file
.nFileSizeLow
;
867 uliSize
.u
.HighPart
= file
.nFileSizeHigh
;
869 ConvertULargeInteger (uliSize
, buffer
, sizeof(buffer
));
870 ConOutPrintf (_T(" %20s"), buffer
);
872 bytecount
.QuadPart
+= uliSize
.QuadPart
;
876 /* print long filename */
877 ConOutPrintf (_T(" %s\n"), file
.cFileName
);
881 if (file
.cFileName
[0] == _T('.'))
882 ConOutPrintf (_T("%-13s "), file
.cFileName
);
883 else if (file
.cAlternateFileName
[0] == _T('\0'))
885 TCHAR szShortName
[13];
888 _tcsncpy (szShortName
, file
.cFileName
, 13);
889 ext
= _tcschr (szShortName
, _T('.'));
894 ConOutPrintf (_T("%-8s %-3s "), szShortName
, ext
);
900 ext
= _tcschr (file
.cAlternateFileName
, _T('.'));
905 ConOutPrintf (_T("%-8s %-3s "), file
.cAlternateFileName
, ext
);
908 /* print file size */
909 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
911 ConOutPrintf ("%-14s", "<DIR>");
916 ULARGE_INTEGER uliSize
;
918 uliSize
.u
.LowPart
= file
.nFileSizeLow
;
919 uliSize
.u
.HighPart
= file
.nFileSizeHigh
;
920 ConvertULargeInteger (uliSize
, buffer
, sizeof(buffer
));
921 ConOutPrintf (_T(" %10s "), buffer
);
922 bytecount
.QuadPart
+= uliSize
.QuadPart
;
926 /* print file date and time */
927 if (FileTimeToLocalFileTime (&file
.ftLastWriteTime
, &ft
))
929 FileTimeToSystemTime (&ft
, &dt
);
930 PrintFileDateTime (&dt
, dwFlags
);
933 /* print long filename */
934 ConOutPrintf (" %s\n", file
.cFileName
);
937 if (IncLine (pLine
, dwFlags
))
941 while (FindNextFile (hFile
, &file
));
944 /* Rob Lake, need to make clean output */
945 /* JPP 07/08/1998 added check for count != 0 */
946 if ((dwFlags
& DIR_WIDE
) && (count
!= 0))
948 ConOutPrintf (_T("\n"));
949 if (IncLine (pLine
, dwFlags
))
953 if (filecount
|| dircount
)
955 recurse_dir_cnt
+= dircount
;
956 recurse_file_cnt
+= filecount
;
957 recurse_bytes
.QuadPart
+= bytecount
.QuadPart
;
960 if (PrintSummary (szPath
, filecount
, dircount
, bytecount
, pLine
, dwFlags
))
965 error_file_not_found ();
974 * _Read_Dir: Actual function that does recursive listing
977 DirRead (LPTSTR szPath
, LPTSTR szFilespec
, LPINT pLine
, DWORD dwFlags
)
979 TCHAR szFullPath
[MAX_PATH
];
980 WIN32_FIND_DATA file
;
983 _tcscpy (szFullPath
, szPath
);
984 if (szFullPath
[_tcslen (szFullPath
) - 1] != _T('\\'))
985 _tcscat (szFullPath
, _T("\\"));
986 _tcscat (szFullPath
, szFilespec
);
988 hFile
= FindFirstFile (szFullPath
, &file
);
989 if (hFile
== INVALID_HANDLE_VALUE
)
994 /* don't list "." and ".." */
995 if (_tcscmp (file
.cFileName
, _T(".")) == 0 ||
996 _tcscmp (file
.cFileName
, _T("..")) == 0)
999 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1001 if (DirList (file
.cFileName
, szFilespec
, pLine
, dwFlags
))
1007 if ((dwFlags
& DIR_BARE
) == 0)
1009 ConOutPrintf ("\n");
1010 if (IncLine (pLine
, dwFlags
) != 0)
1014 if (DirRead (file
.cFileName
, szFilespec
, pLine
, dwFlags
) == 1)
1021 while (FindNextFile (hFile
, &file
));
1023 if (!FindClose (hFile
))
1031 * do_recurse: Sets up for recursive directory listing
1034 DirRecurse (LPTSTR szPath
, LPTSTR szSpec
, LPINT pLine
, DWORD dwFlags
)
1036 if (!PrintDirectoryHeader (szPath
, pLine
, dwFlags
))
1039 if (DirList (szPath
, szSpec
, pLine
, dwFlags
))
1042 if ((dwFlags
& DIR_BARE
) == 0)
1044 ConOutPrintf (_T("\n"));
1045 if (IncLine (pLine
, dwFlags
))
1049 if (DirRead (szPath
, szSpec
, pLine
, dwFlags
))
1052 if ((dwFlags
& DIR_BARE
) == 0)
1053 ConOutPrintf (_T("Total files listed:\n"));
1055 dwFlags
&= ~DIR_RECURSE
;
1057 if (PrintSummary (szPath
, recurse_file_cnt
,
1058 recurse_dir_cnt
, recurse_bytes
, pLine
, dwFlags
))
1061 if ((dwFlags
& DIR_BARE
) == 0)
1063 ConOutPrintf (_T("\n"));
1064 if (IncLine (pLine
, dwFlags
))
1075 * internal dir command
1077 INT
CommandDir (LPTSTR first
, LPTSTR rest
)
1079 DWORD dwFlags
= DIR_NEW
| DIR_FOUR
;
1081 TCHAR szPath
[MAX_PATH
];
1082 TCHAR szFilespec
[MAX_PATH
];
1087 recurse_dir_cnt
= 0L;
1088 recurse_file_cnt
= 0L;
1089 recurse_bytes
.QuadPart
= 0;
1091 /* read the parameters from the DIRCMD environment variable */
1092 if (GetEnvironmentVariable (_T("DIRCMD"), dircmd
, 256))
1094 if (!DirReadParam (dircmd
, ¶m
, &dwFlags
))
1098 /* read the parameters */
1099 if (!DirReadParam (rest
, ¶m
, &dwFlags
))
1102 /* default to current directory */
1106 /* parse the directory info */
1107 if (DirParsePathspec (param
, szPath
, szFilespec
))
1110 if (dwFlags
& DIR_RECURSE
)
1112 if (IncLine (&nLine
, dwFlags
))
1114 if (DirRecurse (szPath
, szFilespec
, &nLine
, dwFlags
))
1119 /* print the header */
1120 if (!PrintDirectoryHeader (szPath
, &nLine
, dwFlags
))
1123 if (DirList (szPath
, szFilespec
, &nLine
, dwFlags
))