2 * WCMD - Wine-compatible command line interface - Directory functions.
6 * On entry, global variables quals, param1, param2 contain
7 * the qualifiers (uppercased and concatenated) and parameters entered, with
8 * environment-variable and batch parameter substitution already done.
13 * - 32-bit limit on individual file sizes (directories and free space are 64-bit)
14 * - DIR /S fails if the starting directory is not the current default.
19 int WCMD_dir_sort (const void *a
, const void *b
);
20 void WCMD_list_directory (char *path
, int level
);
21 char * WCMD_filesize64 (__int64 n
);
22 char * WCMD_filesize32 (int n
);
23 char * WCMD_strrev (char *buff
);
27 extern char newline
[];
28 extern char version_string
[];
31 extern char quals
[MAX_PATH
], param1
[MAX_PATH
], param2
[MAX_PATH
];
33 int file_total
, dir_total
, line_count
, page_mode
, recurse
;
36 /*****************************************************************************
39 * List a file directory.
40 * FIXME: /S switch only works for the current directory
44 void WCMD_directory () {
46 char path
[MAX_PATH
], drive
[8];
49 DWORD spc
, bps
, fc
, capacity
;
52 page_mode
= (strstr(quals
, "/P") != NULL
);
53 recurse
= (strstr(quals
, "/S") != NULL
);
54 if (param1
[0] == '\0') strcpy (param1
, ".");
55 GetFullPathName (param1
, sizeof(path
), path
, NULL
);
56 lstrcpyn (drive
, path
, 3);
57 status
= WCMD_volume (0, drive
);
61 WCMD_list_directory (path
, 0);
62 lstrcpyn (drive
, path
, 4);
63 GetDiskFreeSpace (drive
, &spc
, &bps
, &fc
, &capacity
);
64 free_space
= bps
* spc
* fc
;
65 WCMD_output (" %18s bytes free\n\n", WCMD_filesize64 (free_space
));
67 WCMD_output ("Total files listed:\n%8d files%25s bytes\n%8d directories\n\n",
68 file_total
, WCMD_filesize64 (byte_total
), dir_total
);
72 /*****************************************************************************
75 * List a single file directory. This function (and those below it) can be called
76 * recursively when the /S switch is used.
78 * FIXME: Assumes individual files are less than 2**32 bytes.
79 * FIXME: Entries sorted by name only. Should we support DIRCMD??
80 * FIXME: Assumes 24-line display for the /P qualifier.
81 * FIXME: Other command qualifiers not supported.
82 * FIXME: DIR /S FILENAME fails if at least one matching file is not found in the top level.
85 void WCMD_list_directory (char *search_path
, int level
) {
87 char string
[1024], datestring
[32], timestring
[32];
88 char mem_err
[] = "Memory Allocation Error";
95 int status
, dir_count
, file_count
, entry_count
, i
;
104 * If the path supplied does not include a wildcard, and the endpoint of the
105 * path references a directory, we need to list the *contents* of that
106 * directory not the directory file itself.
109 if ((strchr(search_path
, '*') == NULL
) && (strchr(search_path
, '%') == NULL
)) {
110 status
= GetFileAttributes (search_path
);
111 if ((status
!= -1) && (status
& FILE_ATTRIBUTE_DIRECTORY
)) {
112 if (search_path
[strlen(search_path
)-1] == '\\') {
113 strcat (search_path
, "*");
116 strcat (search_path
, "\\*");
121 fd
= malloc (sizeof(WIN32_FIND_DATA
));
122 hff
= FindFirstFile (search_path
, fd
);
123 if (hff
== INVALID_HANDLE_VALUE
) {
124 WCMD_output ("File Not Found\n");
130 fd
= realloc (fd
, (entry_count
+1)*sizeof(WIN32_FIND_DATA
));
133 WCMD_output (mem_err
);
136 } while (FindNextFile(hff
, (fd
+entry_count
)) != 0);
138 qsort (fd
, entry_count
, sizeof(WIN32_FIND_DATA
), WCMD_dir_sort
);
139 if (level
!= 0) WCMD_output ("\n\n");
140 WCMD_output ("Directory of %s\n\n", search_path
);
143 if (line_count
> 23) {
145 WCMD_output (anykey
);
146 ReadFile (GetStdHandle(STD_INPUT_HANDLE
), string
, sizeof(string
), &count
, NULL
);
149 for (i
=0; i
<entry_count
; i
++) {
150 FileTimeToLocalFileTime (&(fd
+i
)->ftLastWriteTime
, &ft
);
151 FileTimeToSystemTime (&ft
, &st
);
152 GetDateFormat (0, DATE_SHORTDATE
, &st
, NULL
, datestring
,
154 GetTimeFormat (0, TIME_NOSECONDS
, &st
,
155 NULL
, timestring
, sizeof(timestring
));
156 if ((fd
+i
)->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
158 WCMD_output ("%8s %8s <DIR> %s\n",
159 datestring
, timestring
, (fd
+i
)->cFileName
);
163 byte_count
+= (fd
+i
)->nFileSizeLow
;
164 WCMD_output ("%8s %8s %10s %s\n",
165 datestring
, timestring
,
166 WCMD_filesize32((fd
+i
)->nFileSizeLow
), (fd
+i
)->cFileName
);
169 if (++line_count
> 23) {
171 WCMD_output (anykey
);
172 ReadFile (GetStdHandle(STD_INPUT_HANDLE
), string
, sizeof(string
), &count
, NULL
);
176 if (file_count
== 1) {
177 WCMD_output (" 1 file %25s bytes\n", WCMD_filesize64 (byte_count
));
180 WCMD_output ("%8d files %24s bytes\n", file_count
, WCMD_filesize64 (byte_count
));
183 if (++line_count
> 23) {
185 WCMD_output (anykey
);
186 ReadFile (GetStdHandle(STD_INPUT_HANDLE
), string
, sizeof(string
), &count
, NULL
);
189 byte_total
= byte_total
+ byte_count
;
190 file_total
= file_total
+ file_count
;
191 dir_total
= dir_total
+ dir_count
;
192 if (dir_count
== 1) WCMD_output ("1 directory ");
193 else WCMD_output ("%8d directories", dir_count
);
195 if (++line_count
> 23) {
197 WCMD_output (anykey
);
198 ReadFile (GetStdHandle(STD_INPUT_HANDLE
), string
, sizeof(string
), &count
, NULL
);
201 for (i
=0; i
<entry_count
; i
++) {
203 ((fd
+i
)->cFileName
[0] != '.') &&
204 ((fd
+i
)->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)) {
206 GetFullPathName ((fd
+i
)->cFileName
, sizeof(string
), string
, NULL
);
208 p
= strrchr (search_path
, '\\');
209 lstrcpyn (string
, search_path
, (p
-search_path
+2));
210 lstrcat (string
, (fd
+i
)->cFileName
);
212 WCMD_list_directory (string
, 1);
219 /*****************************************************************************
222 * Convert a 64-bit number into a character string, with commas every three digits.
223 * Result is returned in a static string overwritten with each call.
224 * FIXME: There must be a better algorithm!
227 char * WCMD_filesize64 (__int64 n
) {
232 static char buff
[32];
237 if ((++i
)%3 == 1) *p
++ = ',';
248 /*****************************************************************************
251 * Convert a 32-bit number into a character string, with commas every three digits.
252 * Result is returned in a static string overwritten with each call.
253 * FIXME: There must be a better algorithm!
256 char * WCMD_filesize32 (int n
) {
260 static char buff1
[16], buff2
[16];
262 wsprintf (buff1
, "%i", n
);
267 for (i
=0; i
<r
; i
++) {
268 if ((i
-2)%3 == 1) *q
++ = ',';
276 /*****************************************************************************
279 * Reverse a character string in-place (strrev() is not available under unixen :-( ).
282 char * WCMD_strrev (char *buff
) {
288 for (i
=0; i
<r
/2; i
++) {
290 buff
[i
] = buff
[r
-i
-1];
297 int WCMD_dir_sort (const void *a
, const void *b
) {
299 return (lstrcmpi(((WIN32_FIND_DATA
*)a
)->cFileName
,
300 ((WIN32_FIND_DATA
*)b
)->cFileName
));