HuntnGather – Diff between revs 29 and 30

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 29 Rev 30
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2021 Wizardry and Steamworks - License: MIT // 2 // Copyright (C) 2021 Wizardry and Steamworks - License: MIT //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4   4  
5 #include <stdio.h> 5 #include <stdio.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #if !defined ___AmigaOS___ 8 #if !defined ___AmigaOS___
9 #include <dirent.h> 9 #include <dirent.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
11 #include <signal.h> 11 #include <signal.h>
12 #endif 12 #endif
13   13  
14 #include <sys/types.h> 14 #include <sys/types.h>
15 #include <sys/syslimits.h> 15 #include <sys/syslimits.h>
16   16  
17 #if defined ___AmigaOS___ 17 #if defined ___AmigaOS___
18 #include <proto/dos.h> 18 #include <proto/dos.h>
19 #include <proto/exec.h> 19 #include <proto/exec.h>
20 #include <proto/locale.h> 20 #include <proto/locale.h>
21 #endif 21 #endif
22   22  
23 #if defined ___AsyncIO___ 23 #if defined ___AsyncIO___
24 #include <asyncio.h> 24 #include <asyncio.h>
25 #endif 25 #endif
26   26  
27 #include "StringStack.h" 27 #include "StringStack.h"
28   28  
29 #if !defined ___HAVE_GETOPT___ 29 #if !defined ___HAVE_GETOPT___
30 #include "getopt.h" 30 #include "getopt.h"
31 #endif 31 #endif
32   32  
33 #define PROGRAM_VERSION "1.7.4" 33 #define PROGRAM_VERSION "1.7.4"
34   34  
35 #if defined ___AmigaOS___ 35 #if defined ___AmigaOS___
36 /*************************************************************************/ 36 /*************************************************************************/
37 /* Version string used for querrying the program version. */ 37 /* Version string used for querrying the program version. */
38 /*************************************************************************/ 38 /*************************************************************************/
39 TEXT version_string[] = 39 TEXT version_string[] =
40 "\0$VER: Gather " PROGRAM_VERSION " "__DATE__" by Wizardry and Steamworks"; 40 "\0$VER: Gather " PROGRAM_VERSION " "__DATE__" by Wizardry and Steamworks";
41 #endif 41 #endif
42   42  
43 #if !defined TRUE 43 #if !defined TRUE
44 #define TRUE 1; 44 #define TRUE 1;
45 #endif 45 #endif
46   46  
47 #if !defined FALSE 47 #if !defined FALSE
48 #define FALSE 0; 48 #define FALSE 0;
49 #endif 49 #endif
50   50  
51 #define ASYNC_BUF 8192 51 #define ASYNC_BUF 8192
52 #define MAX_MEM 262144 52 #define MAX_MEM 262144
53 #define LINE_BUF 256 53 #define LINE_BUF 256
54 #define DEFAULT_DATABASE_FILE "S:gather.db" 54 #define DEFAULT_DATABASE_FILE "S:gather.db"
55   55  
56 typedef struct { 56 typedef struct {
57 unsigned int dirs; 57 unsigned int dirs;
58 unsigned int files; 58 unsigned int files;
59 } stats; 59 } stats;
60   60  
61 typedef struct { 61 typedef struct {
62 char *name; 62 char *name;
63 char *path; 63 char *path;
64 } dbEntry; 64 } dbEntry;
65   65  
66 typedef struct { 66 typedef struct {
67 char **database; 67 char **database;
68 unsigned int count; 68 unsigned int count;
69 } dbArray; 69 } dbArray;
70   70  
71 enum MODE { 71 enum MODE {
72 NONE, 72 NONE,
73 GATHER, 73 GATHER,
74 REMOVE, 74 REMOVE,
75 CREATE 75 CREATE
76 } operation; 76 } operation;
77   77  
78 unsigned int run = TRUE; 78 unsigned int run = TRUE;
79 unsigned int verbose = TRUE; 79 unsigned int verbose = TRUE;
80 unsigned int maxmem = MAX_MEM; 80 unsigned int maxmem = MAX_MEM;
81 // Define global locale for string compare. 81 // Define global locale for string compare.
82 #if defined ___AmigaOS___ 82 #if defined ___AmigaOS___
83 struct Locale *locale; 83 struct Locale *locale;
84 #endif 84 #endif
85   85  
86 void SignalHandler(int sig) { 86 void SignalHandler(int sig) {
87 // Toggle the run flag to stop execution. 87 // Toggle the run flag to stop execution.
88 run = FALSE; 88 run = FALSE;
89 } 89 }
90   90  
91 /* 91 /*
92 * 92 *
93 * Used for sorting database lines. 93 * Used for sorting database lines.
94 */ 94 */
95 int QsortCompare(const void *a, const void *b) { 95 int QsortCompare(const void *a, const void *b) {
96 const char **p = (const char **)a; 96 const char **p = (const char **)a;
97 const char **q = (const char **)b; 97 const char **q = (const char **)b;
98 #if defined ___AmigaOS___ 98 #if defined ___AmigaOS___
99 return StrnCmp(locale, (STRPTR)*p, (STRPTR)*q, -1, SC_ASCII); 99 return StrnCmp(locale, (STRPTR)*p, (STRPTR)*q, -1, SC_ASCII);
100 #else 100 #else
101 return strcmp(*p, *q); 101 return strcmp(*p, *q);
102 #endif 102 #endif
103 } 103 }
104   104  
105 /* 105 /*
106 * 106 *
107 * Gets the absolute path to file by name. 107 * Gets the absolute path to file by name.
108 */ 108 */
109 char *PathToAbsolute(char *path) { 109 char *PathToAbsolute(char *path) {
110 char *abs; 110 char *abs;
111 #if defined ___AmigaOS___ 111 #if defined ___AmigaOS___
112 BPTR lock; 112 BPTR lock;
113 #endif 113 #endif
114   114  
115 #if defined ___AmigaOS___ 115 #if defined ___AmigaOS___
116 if((abs = malloc(PATH_MAX * sizeof(*abs))) == NULL) { 116 if((abs = malloc(PATH_MAX * sizeof(*abs))) == NULL) {
117 fprintf(stderr, "Memory allocation failure.\n"); 117 fprintf(stderr, "Memory allocation failure.\n");
118 return NULL; 118 return NULL;
119 } 119 }
120 if((lock = Lock(path, SHARED_LOCK)) == 0) { 120 if((lock = Lock(path, SHARED_LOCK)) == 0) {
121 fprintf(stderr, "Lock on %s failed.\n", path); 121 fprintf(stderr, "Lock on %s failed.\n", path);
122 return NULL; 122 return NULL;
123 } 123 }
124 if(NameFromLock(lock, abs, PATH_MAX) == FALSE) { 124 if(NameFromLock(lock, abs, PATH_MAX) == FALSE) {
125 fprintf(stderr, "Lock on %s failed.\n", path); 125 fprintf(stderr, "Lock on %s failed.\n", path);
126 UnLock(lock); 126 UnLock(lock);
127 return NULL; 127 return NULL;
128 } 128 }
129 UnLock(lock); 129 UnLock(lock);
130 #else 130 #else
131 abs = realpath(path, NULL); 131 //abs = realpath(path, NULL);
-   132 if((abs = malloc((strlen(path) + 1) * sizeof(*abs))) == NULL) {
-   133 fprintf(stderr, "Memory allocation failure.\n");
-   134 return NULL;
-   135 }
-   136 sprintf(abs, "%s", path);
132 #endif 137 #endif
133   138  
134 return abs; 139 return abs;
135 } 140 }
136   141  
137 /* 142 /*
138 * 143 *
139 * Compares path parts for equality. 144 * Compares path parts for equality.
140 */ 145 */
141 #if defined ___AmigaOS___ 146 #if defined ___AmigaOS___
142 BOOL PathCompare(char *path, char *look) { 147 BOOL PathCompare(char *path, char *look) {
143 #else 148 #else
144 int PathCompare(char *path, char *look) { 149 int PathCompare(char *path, char *look) {
145 #endif 150 #endif
146 char *a; 151 char *a;
147 char *b; 152 char *b;
148   153  
149 for(a = path, b = look; *a != '\0' && *b != '\0'; ++a, ++b) { 154 for(a = path, b = look; *a != '\0' && *b != '\0'; ++a, ++b) {
150 if(*b != '\0' && *a != *b) { 155 if(*b != '\0' && *a != *b) {
151 return FALSE; 156 return FALSE;
152 } 157 }
153 } 158 }
154   159  
155 return *b == '\0'; 160 return *b == '\0';
156 } 161 }
157   162  
158 /* 163 /*
159 * 164 *
160 * Gets the size of a file by name. 165 * Gets the size of a file by name.
161 */ 166 */
162 int GetFileSize(char *dbFile) { 167 int GetFileSize(char *dbFile) {
163 #if defined ___AsyncIO___ 168 #if defined ___AsyncIO___
164 struct AsyncFile *fp; 169 struct AsyncFile *fp;
165 LONG size; 170 LONG size;
166 #else 171 #else
167 FILE *fp; 172 FILE *fp;
168 int size; 173 int size;
169 #endif 174 #endif
170   175  
171 #if defined ___AsyncIO___ 176 #if defined ___AsyncIO___
172 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 177 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
173 #else 178 #else
174 if((fp = fopen(dbFile, "r")) == NULL) { 179 if((fp = fopen(dbFile, "r")) == NULL) {
175 #endif 180 #endif
176 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile); 181 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
177 return -1; 182 return -1;
178 } 183 }
179   184  
180 #if defined ___AsyncIO___ 185 #if defined ___AsyncIO___
181 if(SeekAsync(fp, 0, MODE_END) == -1) { 186 if(SeekAsync(fp, 0, MODE_END) == -1) {
182 #else 187 #else
183 if(fseek(fp, 0L, SEEK_END) == 0) { 188 if(fseek(fp, 0L, SEEK_END) != 0) {
184 #endif 189 #endif
185 fprintf(stderr, "Seek in file %s failed.\n", dbFile); 190 fprintf(stderr, "Seek in file %s failed.\n", dbFile);
186 #if defined ___AsyncIO___ 191 #if defined ___AsyncIO___
187 CloseAsync(fp); 192 CloseAsync(fp);
188 #else 193 #else
189 fclose(fp); 194 fclose(fp);
190 #endif 195 #endif
191 return -1; 196 return -1;
192 } 197 }
193 #if defined ___AsyncIO___ 198 #if defined ___AsyncIO___
194 if((size = SeekAsync(fp, 0, MODE_CURRENT)) == -1) { 199 if((size = SeekAsync(fp, 0, MODE_CURRENT)) == -1) {
195 fprintf(stderr, "Seek in file %s failed.\n", dbFile); 200 fprintf(stderr, "Seek in file %s failed.\n", dbFile);
196 CloseAsync(fp); 201 CloseAsync(fp);
197 return -1; 202 return -1;
198 } 203 }
199 #else 204 #else
200 size = ftell(fp); 205 size = ftell(fp);
201 #endif 206 #endif
202   207  
203 #if defined ___AsyncIO___ 208 #if defined ___AsyncIO___
204 CloseAsync(fp); 209 CloseAsync(fp);
205 #else 210 #else
206 fclose(fp); 211 fclose(fp);
207 #endif 212 #endif
208   213  
209 return size; 214 return size;
210 } 215 }
211   216  
212 /* 217 /*
213 * 218 *
214 * Counts the lines of a file. 219 * Counts the lines of a file.
215 */ 220 */
216 int CountFileLines(char *dbFile) { 221 int CountFileLines(char *dbFile) {
217 #if defined ___AsyncIO___ 222 #if defined ___AsyncIO___
218 struct AsyncFile *fp; 223 struct AsyncFile *fp;
219 LONG c; 224 LONG c;
220 #else 225 #else
221 FILE *fp; 226 FILE *fp;
222 char c; 227 char c;
223 #endif 228 #endif
224 int lines; 229 int lines;
225   230  
226 #if defined ___AsyncIO___ 231 #if defined ___AsyncIO___
227 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 232 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
228 #else 233 #else
229 if((fp = fopen(dbFile, "r")) == NULL) { 234 if((fp = fopen(dbFile, "r")) == NULL) {
230 #endif 235 #endif
231 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile); 236 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
232 return -1; 237 return -1;
233 } 238 }
234   239  
235 lines = 0; 240 lines = 0;
-   241 if(verbose) {
-   242 fprintf(stdout, "Lines in '%s' so far: %d\r", dbFile, lines);
-   243 }
-   244  
236 #if defined ___AsyncIO___ 245 #if defined ___AsyncIO___
237 while(run && (c = ReadCharAsync(fp)) != -1) { 246 while(run && (c = ReadCharAsync(fp)) != -1) {
238 #else 247 #else
239 while(run && fscanf(fp, "%c", &c) == 1) { 248 while(run && fscanf(fp, "%c", &c) == 1) {
240 #endif 249 #endif
241 #if defined ___AmigaOS___ 250 #if defined ___AmigaOS___
242 // Check if CTRL+C was pressed and abort the program. 251 // Check if CTRL+C was pressed and abort the program.
243 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 252 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
244 run = FALSE; 253 run = FALSE;
245 continue; 254 continue;
246 } 255 }
247 #endif 256 #endif
248 switch(c) { 257 switch(c) {
249 case '\n': 258 case '\n':
250 ++lines; 259 ++lines;
-   260  
-   261 if(verbose) {
-   262 fprintf(stdout, "Lines in '%s' so far: %d\r", dbFile, lines);
-   263 }
251 break; 264 break;
252 } 265 }
253 } 266 }
254   267  
255 #if defined ___AsyncIO___ 268 #if defined ___AsyncIO___
256 CloseAsync(fp); 269 CloseAsync(fp);
257 #else 270 #else
258 fclose(fp); 271 fclose(fp);
259 #endif 272 #endif
-   273  
-   274 if(verbose) {
-   275 fprintf(stdout, "\n");
-   276 }
260   277  
261 return lines; 278 return lines;
262 } 279 }
263   280  
264 /* 281 /*
265 * 282 *
266 * Creates a temporary file and returns its name. 283 * Creates a temporary file and returns its name.
267 */ 284 */
268 char *CreateTemporaryFile(void) { 285 char *CreateTemporaryFile(void) {
269 char *name; 286 char *name;
270   287  
271 name = tmpnam(NULL); 288 name = tmpnam(NULL);
272   289  
273 return name; 290 return name;
274 } 291 }
275   292  
276 /* 293 /*
277 * 294 *
278 * Create multiple temporary files and return their names. 295 * Create multiple temporary files and return their names.
279 */ 296 */
280 char **CreateTemporaryFiles(int files) { 297 char **CreateTemporaryFiles(int files) {
281 char **tmpNames; 298 char **tmpNames;
282 int count; 299 int count;
283   300  
284 if((tmpNames = malloc(files * sizeof(*tmpNames))) == NULL) { 301 if((tmpNames = malloc(files * sizeof(*tmpNames))) == NULL) {
285 fprintf(stderr, "Memory allocation failure.\n"); 302 fprintf(stderr, "Memory allocation failure.\n");
286 return NULL; 303 return NULL;
287 } 304 }
288   305  
289 if(verbose) { 306 if(verbose) {
290 fprintf(stdout, "Creating temporary files...\r"); 307 fprintf(stdout, "Creating temporary files...\r");
291 } 308 }
292   309  
293 count = files; 310 count = files;
294 while(run && --count > -1) { 311 while(run && --count > -1) {
295 #if defined ___AmigaOS___ 312 #if defined ___AmigaOS___
296 // Check if CTRL+C was pressed and abort the program. 313 // Check if CTRL+C was pressed and abort the program.
297 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 314 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
298 run = FALSE; 315 run = FALSE;
299 continue; 316 continue;
300 } 317 }
301 #endif 318 #endif
302 tmpNames[count] = CreateTemporaryFile(); 319 tmpNames[count] = CreateTemporaryFile();
303   320  
304 if(verbose) { 321 if(verbose) {
305 fprintf(stdout, "Creating temporary files: %d%%\r", 100 - (int)(((float)count / files) * 100.0)); 322 fprintf(stdout, "Creating temporary files: %d%%\r", 100 - (int)(((float)count / files) * 100.0));
306 } 323 }
307 } 324 }
308   325  
309 if(verbose) { 326 if(verbose) {
310 fprintf(stdout, "\n"); 327 fprintf(stdout, "\n");
311 } 328 }
312   329  
313 return tmpNames; 330 return tmpNames;
314 } 331 }
315   332  
316   333  
317 /* 334 /*
318 * 335 *
319 * Skips a line in a file. 336 * Skips a line in a file.
320 */ 337 */
321 #if defined ___AsyncIO___ 338 #if defined ___AsyncIO___
322 void SkipLine(struct AsyncFile *fp) { 339 void SkipLine(struct AsyncFile *fp) {
323 LONG c; 340 LONG c;
324 while(run && (c = ReadCharAsync(fp)) != -1) { 341 while(run && (c = ReadCharAsync(fp)) != -1) {
325 #else 342 #else
326 void SkipLine(FILE *fp) { 343 void SkipLine(FILE *fp) {
327 char c; 344 char c;
328 while(run && fscanf(fp, "%c", &c) == 1) { 345 while(run && fscanf(fp, "%c", &c) == 1) {
329 #endif 346 #endif
330 #if defined ___AmigaOS___ 347 #if defined ___AmigaOS___
331 // Check if CTRL+C was pressed and abort the program. 348 // Check if CTRL+C was pressed and abort the program.
332 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 349 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
333 run = FALSE; 350 run = FALSE;
334 continue; 351 continue;
335 } 352 }
336 #endif 353 #endif
337 switch(c) { 354 switch(c) {
338 case '\n': 355 case '\n':
339 return; 356 return;
340 } 357 }
341 } 358 }
342 } 359 }
343   360  
344 /* 361 /*
345 * 362 *
346 * Peeks at a line from a file. 363 * Peeks at a line from a file.
347 */ 364 */
348 #if defined ___AsyncIO___ 365 #if defined ___AsyncIO___
349 char *PeekLine(struct AsyncFile *fp) { 366 char *PeekLine(struct AsyncFile *fp) {
350 LONG c; 367 LONG c;
351 #else 368 #else
352 char *PeekLine(FILE *fp) { 369 char *PeekLine(FILE *fp) {
353 char c; 370 char c;
354 #endif 371 #endif
355 char *line; 372 char *line;
356 unsigned int size; 373 unsigned int size;
357 int i; 374 int i;
358   375  
359 size = LINE_BUF; 376 size = LINE_BUF;
360 if((line = malloc(size * sizeof(*line))) == NULL) { 377 if((line = malloc(size * sizeof(*line))) == NULL) {
361 fprintf(stderr, "Memory allocation failure.\n"); 378 fprintf(stderr, "Memory allocation failure.\n");
362 return NULL; 379 return NULL;
363 } 380 }
364   381  
365 i = 0; 382 i = 0;
366 #if defined ___AsyncIO___ 383 #if defined ___AsyncIO___
367 while(run && (c = ReadCharAsync(fp)) != -1) { 384 while(run && (c = ReadCharAsync(fp)) != -1) {
368 #else 385 #else
369 while(run && fscanf(fp, "%c", &c) == 1) { 386 while(run && fscanf(fp, "%c", &c) == 1) {
370 #endif 387 #endif
371 #if defined ___AmigaOS___ 388 #if defined ___AmigaOS___
372 // Check if CTRL+C was pressed and abort the program. 389 // Check if CTRL+C was pressed and abort the program.
373 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 390 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
374 run = FALSE; 391 run = FALSE;
375 continue; 392 continue;
376 } 393 }
377 #endif 394 #endif
378 switch(c) { 395 switch(c) {
379 case '\n': 396 case '\n':
380 // Rewind the file by the number of read characters. 397 // Rewind the file by the number of read characters.
381 #if defined ___AsyncIO___ 398 #if defined ___AsyncIO___
382 if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) { 399 if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) {
383 fprintf(stderr, "Could not seek in file.\n"); 400 fprintf(stderr, "Could not seek in file.\n");
384 free(line); 401 free(line);
385 return NULL; 402 return NULL;
386 } 403 }
387 #else 404 #else
388 fseek(fp, -(i + 1), SEEK_CUR); 405 if(fseek(fp, -(i + 1), SEEK_CUR) != 0) {
-   406 fprintf(stderr, "Could not seek in file.\n");
-   407 free(line);
-   408 return NULL;
-   409 }
389 #endif 410 #endif
390 return line; 411 return line;
391 default: 412 default:
392 if(strlen(line) == size) { 413 if(strlen(line) == size) {
393 size = size * 1.5; 414 size = size * 1.5;
394 line = realloc(line, size * sizeof(*line)); 415 line = realloc(line, size * sizeof(*line));
395 } 416 }
396 line[i] = c; 417 line[i] = c;
397 line[i + 1] = '\0'; 418 line[i + 1] = '\0';
398 break; 419 break;
399 } 420 }
400 ++i; 421 ++i;
401 } 422 }
402   423  
403 return NULL; 424 return NULL;
404 } 425 }
405   426  
406 /* 427 /*
407 * 428 *
408 * Read a line from a file. 429 * Read a line from a file.
409 */ 430 */
410 #if defined ___AsyncIO___ 431 #if defined ___AsyncIO___
411 char *ReadLine(struct AsyncFile *fp) { 432 char *ReadLine(struct AsyncFile *fp) {
412 LONG c; 433 LONG c;
413 #else 434 #else
414 char *ReadLine(FILE *fp) { 435 char *ReadLine(FILE *fp) {
415 char c; 436 char c;
416 #endif 437 #endif
417 char *line; 438 char *line;
418 unsigned int size; 439 unsigned int size;
419 unsigned int i; 440 unsigned int i;
420   441  
421 size = LINE_BUF; 442 size = LINE_BUF;
422 if((line = malloc(size * sizeof(*line))) == NULL) { 443 if((line = malloc(size * sizeof(*line))) == NULL) {
423 fprintf(stderr, "Memory allication failure.\n"); 444 fprintf(stderr, "Memory allication failure.\n");
424 return NULL; 445 return NULL;
425 } 446 }
426   447  
427 i = 0; 448 i = 0;
428 #if defined ___AsyncIO___ 449 #if defined ___AsyncIO___
429 while(run && (c = ReadCharAsync(fp)) != -1) { 450 while(run && (c = ReadCharAsync(fp)) != -1) {
430 #else 451 #else
431 while(run && fscanf(fp, "%c", &c) == 1) { 452 while(run && fscanf(fp, "%c", &c) == 1) {
432 #endif 453 #endif
433 #if defined ___AmigaOS___ 454 #if defined ___AmigaOS___
434 // Check if CTRL+C was pressed and abort the program. 455 // Check if CTRL+C was pressed and abort the program.
435 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 456 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
436 run = FALSE; 457 run = FALSE;
437 continue; 458 continue;
438 } 459 }
439 #endif 460 #endif
440 switch(c) { 461 switch(c) {
441 case '\n': 462 case '\n':
442 return line; 463 return line;
443 default: 464 default:
444 if(strlen(line) == size) { 465 if(strlen(line) == size) {
445 size = size * 1.5; 466 size = size * 1.5;
446 line = realloc(line, size * sizeof(*line)); 467 line = realloc(line, size * sizeof(*line));
447 } 468 }
448 line[i] = c; 469 line[i] = c;
449 line[i + 1] = '\0'; 470 line[i + 1] = '\0';
450 break; 471 break;
451 } 472 }
452 ++i; 473 ++i;
453 } 474 }
454   475  
455 return NULL; 476 return NULL;
456 } 477 }
457   478  
458 /* 479 /*
459 * 480 *
460 * Delete a file. 481 * Delete a file.
461 */ 482 */
462 #if defined ___AmigaOS___ 483 #if defined ___AmigaOS___
463 BOOL RemoveFile(char *name) { 484 BOOL RemoveFile(char *name) {
464 return DeleteFile(name); 485 return DeleteFile(name);
465 #else 486 #else
466 int RemoveFile(char *name) { 487 int RemoveFile(char *name) {
467 return remove(name) == 0; 488 return remove(name) == 0;
468 #endif 489 #endif
469 } 490 }
470   491  
471 /* 492 /*
472 * 493 *
473 * Deletes files. 494 * Deletes files.
474 */ 495 */
475 void RemoveFiles(char **names, int count) { 496 void RemoveFiles(char **names, int count) {
476 unsigned int i; 497 unsigned int i;
477 for(i = 0; i < count; ++i) { 498 for(i = 0; i < count; ++i) {
478 if(RemoveFile(names[i]) == FALSE) { 499 if(RemoveFile(names[i]) == FALSE) {
479 fprintf(stderr, "Unable to remove %s...\n", names[i]); 500 fprintf(stderr, "Unable to remove %s...\n", names[i]);
480 continue; 501 continue;
481 } 502 }
482 fprintf(stderr, "Removing file: %s\n", names[i]); 503 fprintf(stderr, "Removing file: %s\n", names[i]);
483 } 504 }
484 } 505 }
485   506  
486 /* 507 /*
487 * 508 *
488 * Copies a file to another file by name. 509 * Copies a file to another file by name.
489 */ 510 */
490 void CopyFile(char *a, char *b) { 511 void CopyFile(char *a, char *b) {
491 #if defined ___AsyncIO___ 512 #if defined ___AsyncIO___
492 struct AsyncFile *ap; 513 struct AsyncFile *ap;
493 struct AsyncFile *bp; 514 struct AsyncFile *bp;
494 LONG c; 515 LONG c;
495 #else 516 #else
496 FILE *ap; 517 FILE *ap;
497 FILE *bp; 518 FILE *bp;
498 char c; 519 char c;
499 #endif 520 #endif
500   -  
501   521  
502 // Open database file for writing. 522 // Open database file for writing.
503 #if defined ___AsyncIO___ 523 #if defined ___AsyncIO___
504 if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) { 524 if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) {
505 #else 525 #else
506 if((ap = fopen(a, "r")) == NULL) { 526 if((ap = fopen(a, "r")) == NULL) {
507 #endif 527 #endif
508 fprintf(stderr, "Unable to open '%s' for reading.\n", a); 528 fprintf(stderr, "Unable to open '%s' for reading.\n", a);
509 return; 529 return;
510 } 530 }
511   531  
512 // Open temporary file for reading. 532 // Open temporary file for reading.
513 #if defined ___AsyncIO___ 533 #if defined ___AsyncIO___
514 if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) { 534 if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) {
515 #else 535 #else
516 if((bp = fopen(b, "w+")) == NULL) { 536 if((bp = fopen(b, "w")) == NULL) {
517 #endif 537 #endif
518 fprintf(stderr, "Unable to open file '%s' for writing.\n", b); 538 fprintf(stderr, "Unable to open file '%s' for writing.\n", b);
519   539  
520 // Close database file. 540 // Close database file.
521 #if defined ___AsyncIO___ 541 #if defined ___AsyncIO___
522 CloseAsync(ap); 542 CloseAsync(ap);
523 #else 543 #else
524 fclose(ap); 544 fclose(ap);
525 #endif 545 #endif
526   546  
527 return; 547 return;
528 } 548 }
529   549  
530 #if defined ___AsyncIO___ 550 #if defined ___AsyncIO___
531 while(run && (c = ReadCharAsync(ap)) != -1) { 551 while(run && (c = ReadCharAsync(ap)) != -1) {
532 #else 552 #else
533 while(run && fscanf(ap, "%c", &c) == 1) { 553 while(run && fscanf(ap, "%c", &c) == 1) {
534 #endif 554 #endif
535 #if defined ___AmigaOS___ 555 #if defined ___AmigaOS___
536 // Check if CTRL+C was pressed and abort the program. 556 // Check if CTRL+C was pressed and abort the program.
537 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 557 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
538 run = FALSE; 558 run = FALSE;
539 continue; 559 continue;
540 } 560 }
541 #endif 561 #endif
542 #if defined ___AsyncIO___ 562 #if defined ___AsyncIO___
543 if(WriteCharAsync(bp, (UBYTE)c) != 1) { 563 if(WriteCharAsync(bp, (UBYTE)c) != 1) {
544 #else 564 #else
545 if(fprintf(bp, "%c", c) != 1) { 565 if(fprintf(bp, "%c", c) != 1) {
546 #endif 566 #endif
547 fprintf(stderr, "Unable to write to '%s'.\n", b); 567 fprintf(stderr, "Unable to write to '%s'.\n", b);
548 break; 568 break;
549 } 569 }
550 } 570 }
551   571  
552 #if defined ___AsyncIO___ 572 #if defined ___AsyncIO___
553 CloseAsync(ap); 573 CloseAsync(ap);
554 CloseAsync(bp); 574 CloseAsync(bp);
555 #else 575 #else
556 fclose(ap); 576 fclose(ap);
557 fclose(bp); 577 fclose(bp);
558 #endif 578 #endif
559 } 579 }
560   580  
561 /* 581 /*
562 * 582 *
563 * Write lines to a file. 583 * Write lines to a file.
564 */ 584 */
565 void WriteLinesToFile(char *dbFile, char **lines, unsigned int count) { 585 void WriteLinesToFile(char *dbFile, char **lines, unsigned int count) {
566 #if defined ___AsyncIO___ 586 #if defined ___AsyncIO___
567 struct AsyncFile *fp; 587 struct AsyncFile *fp;
568 #else 588 #else
569 FILE *fp; 589 FILE *fp;
570 #endif 590 #endif
571 int i; 591 unsigned int i;
572 char *rem; 592 char *rem;
573   593  
574 // Write the database lines back to the database. 594 // Write the database lines back to the database.
575 #if defined ___AsyncIO___ 595 #if defined ___AsyncIO___
576 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) { 596 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
577 #else 597 #else
578 if((fp = fopen(dbFile, "w")) == NULL) { 598 if((fp = fopen(dbFile, "w")) == NULL) {
579 #endif 599 #endif
580 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile); 600 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
581 return; 601 return;
582 } 602 }
583   603  
584 rem = NULL; 604 rem = NULL;
585 for(i = 0; i < count; ++i) { 605 for(i = 0; i < count; ++i) {
586 #if defined ___AmigaOS___ 606 #if defined ___AmigaOS___
587 // Check if CTRL+C was pressed and abort the program. 607 // Check if CTRL+C was pressed and abort the program.
588 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 608 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
589 run = FALSE; 609 run = FALSE;
590 continue; 610 continue;
591 } 611 }
592 #endif 612 #endif
593   613  
594 if(rem != NULL) { 614 if(rem != NULL) {
595 #if defined ___AmigaOS___ 615 #if defined ___AmigaOS___
596 if(StrnCmp(locale, lines[i], rem, -1, SC_ASCII) == 0) { 616 if(StrnCmp(locale, lines[i], rem, -1, SC_ASCII) == 0) {
597 #else 617 #else
598 if(strcmp(lines[i], rem) == 0) { 618 if(strcmp(lines[i], rem) == 0) {
599 #endif 619 #endif
600 continue; 620 continue;
601 } 621 }
602 } 622 }
603   623  
604 #if defined ___AsyncIO___ 624 #if defined ___AsyncIO___
605 WriteAsync(fp, lines[i], (LONG)strlen(lines[i])); 625 WriteAsync(fp, lines[i], (LONG)strlen(lines[i]));
606 WriteAsync(fp, "\n", 1); 626 WriteAsync(fp, "\n", 1);
607 #else 627 #else
608 fprintf(fp, "%s\n", lines[i]); 628 fprintf(fp, "%s\n", lines[i]);
609 #endif 629 #endif
610   630  
611 if(rem != NULL) { 631 if(rem != NULL) {
612 free(rem); 632 free(rem);
613 } 633 }
614   634  
615 rem = malloc(strlen(lines[i]) + 1); 635 rem = malloc(strlen(lines[i]) + 1);
616 sprintf(rem, "%s", lines[i]); 636 sprintf(rem, "%s", lines[i]);
617 } 637 }
618   638  
619 #if defined ___AsyncIO___ 639 #if defined ___AsyncIO___
620 CloseAsync(fp); 640 CloseAsync(fp);
621 #else 641 #else
622 fclose(fp); 642 fclose(fp);
623 #endif 643 #endif
624 } 644 }
625   645  
626 /* 646 /*
627 * 647 *
628 * Create a database entry from a line of text. 648 * Create a database entry from a line of text.
629 */ 649 */
630 dbEntry* CreateDataseEntry(char *line) { 650 dbEntry* CreateDataseEntry(char *line) {
631 dbEntry *entry; 651 dbEntry *entry;
632 char *ptr; 652 char *ptr;
633 unsigned int side; 653 unsigned int side;
634 unsigned int i; 654 unsigned int i;
635 unsigned int j; 655 unsigned int j;
636   656  
637 if((entry = malloc(1 * sizeof(*entry))) == NULL) { 657 if((entry = malloc(1 * sizeof(*entry))) == NULL) {
638 fprintf(stderr, "Memory allocation failure.\n"); 658 fprintf(stderr, "Memory allocation failure.\n");
639 return NULL; 659 return NULL;
640 } 660 }
641   661  
642 if((entry->name = malloc(strlen(line) * sizeof(*entry->name))) == NULL) { 662 if((entry->name = malloc(strlen(line) * sizeof(*entry->name))) == NULL) {
643 fprintf(stderr, "Memory allocation failure.\n"); 663 fprintf(stderr, "Memory allocation failure.\n");
644 return NULL; 664 return NULL;
645 } 665 }
646   666  
647 if((entry->path = malloc(strlen(line) * sizeof(*entry->path))) == NULL) { 667 if((entry->path = malloc(strlen(line) * sizeof(*entry->path))) == NULL) {
648 fprintf(stderr, "Memory allocation failure.\n"); 668 fprintf(stderr, "Memory allocation failure.\n");
649 return NULL; 669 return NULL;
650 } 670 }
651   671  
652 for(ptr = line, side = 0, i = 0, j = 0; run && *ptr != '\0'; ++ptr) { 672 for(ptr = line, side = 0, i = 0, j = 0; run && *ptr != '\0'; ++ptr) {
653 #if defined ___AmigaOS___ 673 #if defined ___AmigaOS___
654 // Check if CTRL+C was pressed and abort the program. 674 // Check if CTRL+C was pressed and abort the program.
655 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 675 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
656 run = FALSE; 676 run = FALSE;
657 continue; 677 continue;
658 } 678 }
659 #endif 679 #endif
660 switch(*ptr) { 680 switch(*ptr) {
661 case '\t': 681 case '\t':
662 entry->name[i] = '\0'; 682 entry->name[i] = '\0';
663 ++side; 683 ++side;
664 break; 684 break;
665 case '\n': 685 case '\n':
666 entry->path[j] = '\0'; 686 entry->path[j] = '\0';
667 return entry; 687 return entry;
668 default: 688 default:
669 switch(side) { 689 switch(side) {
670 case 0: 690 case 0:
671 entry->name[i++] = *ptr; 691 entry->name[i++] = *ptr;
672 break; 692 break;
673 case 1: 693 case 1:
674 entry->path[j++] = *ptr; 694 entry->path[j++] = *ptr;
675 break; 695 break;
676 } 696 }
677 break; 697 break;
678 } 698 }
679 } 699 }
680   700  
681 return entry; 701 return entry;
682 } 702 }
683   703  
684 /* 704 /*
685 * 705 *
686 * 706 *
687 */ 707 */
688 dbArray *GetDatabaseArray(char *dbFile) { 708 dbArray *GetDatabaseArray(char *dbFile) {
689 #if defined ___AsyncIO___ 709 #if defined ___AsyncIO___
690 struct AsyncFile *fp; 710 struct AsyncFile *fp;
691 #else 711 #else
692 FILE *fp; 712 FILE *fp;
693 #endif 713 #endif
694 dbArray *array; 714 dbArray *array;
695 dbEntry *entry; 715 dbEntry *entry;
696 char *line; 716 char *line;
697 unsigned int count; 717 unsigned int count;
698   718  
699 if((array = malloc(1 * sizeof(*array))) == NULL) { 719 if((array = malloc(1 * sizeof(*array))) == NULL) {
700 fprintf(stderr, "Memory allocation failure.\n"); 720 fprintf(stderr, "Memory allocation failure.\n");
701 return NULL; 721 return NULL;
702 } 722 }
703   723  
704 // Open database file for reading. 724 // Open database file for reading.
705 #if defined ___AsyncIO___ 725 #if defined ___AsyncIO___
706 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 726 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
707 #else 727 #else
708 if((fp = fopen(dbFile, "r")) == NULL) { 728 if((fp = fopen(dbFile, "r")) == NULL) {
709 #endif 729 #endif
710 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile); 730 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
711 return NULL; 731 return NULL;
712 } 732 }
713   733  
714 count = 0; 734 count = 0;
715 while(run && (line = ReadLine(fp)) != NULL) { 735 while(run && (line = ReadLine(fp)) != NULL) {
716 #if defined ___AmigaOS___ 736 #if defined ___AmigaOS___
717 // Check if CTRL+C was pressed and abort the program. 737 // Check if CTRL+C was pressed and abort the program.
718 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 738 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
719 run = FALSE; 739 run = FALSE;
720 continue; 740 continue;
721 } 741 }
722 #endif 742 #endif
723 if((entry = CreateDataseEntry(line)) == NULL) { 743 if((entry = CreateDataseEntry(line)) == NULL) {
724 fprintf(stderr, "Unable to create database entry.\n"); 744 fprintf(stderr, "Unable to create database entry.\n");
725 #if defined ___AsyncIO___ 745 #if defined ___AsyncIO___
726 CloseAsync(fp); 746 CloseAsync(fp);
727 #else 747 #else
728 fclose(fp); 748 fclose(fp);
729 #endif 749 #endif
730 return NULL; 750 return NULL;
731 } 751 }
732   752  
733 // Load up the name and path into the database variable. 753 // Load up the name and path into the database variable.
734 array->database = realloc(array->database, (count + 1) * sizeof(*array->database)); 754 array->database = realloc(array->database, (count + 1) * sizeof(*array->database));
735 if((array->database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*array->database[count]))) == NULL) { 755 if((array->database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*array->database[count]))) == NULL) {
736 fprintf(stderr, "Memory allocation failure.\n"); 756 fprintf(stderr, "Memory allocation failure.\n");
737 free(entry); 757 free(entry);
738 free(line); 758 free(line);
739 #if defined ___AsyncIO___ 759 #if defined ___AsyncIO___
740 CloseAsync(fp); 760 CloseAsync(fp);
741 #else 761 #else
742 fclose(fp); 762 fclose(fp);
743 #endif 763 #endif
744 return NULL; 764 return NULL;
745 } 765 }
746 sprintf(array->database[count], "%s\t%s", entry->name, entry->path); 766 sprintf(array->database[count], "%s\t%s", entry->name, entry->path);
747 ++count; 767 ++count;
-   768  
-   769 // Free the database entry.
-   770 free(entry->name);
748   771 free(entry->path);
-   772 free(entry);
749 free(entry); 773  
750 free(line); 774 free(line);
751 } 775 }
752   776  
753 #if defined ___AsyncIO___ 777 #if defined ___AsyncIO___
754 CloseAsync(fp); 778 CloseAsync(fp);
755 #else 779 #else
756 fclose(fp); 780 fclose(fp);
757 #endif 781 #endif
758   782  
759 array->count = count; 783 array->count = count;
760 return array; 784 return array;
761 } 785 }
762   786  
763 /* 787 /*
764 * 788 *
765 * Sorts a database file lexicographically. 789 * Sorts a database file lexicographically.
766 */ 790 */
767 void SortDatabase(char *dbFile) { 791 void SortDatabase(char *dbFile) {
768 dbArray *array; 792 dbArray *array;
-   793 int i;
769   794  
770 if(verbose) { 795 if(verbose) {
771 fprintf(stdout, "Sorting '%s'...\n", dbFile); 796 fprintf(stdout, "Sorting '%s'...\n", dbFile);
772 } 797 }
773   798  
774 // Retrieve the database as an array. 799 // Retrieve the database as an array.
775 if((array = GetDatabaseArray(dbFile)) == NULL) { 800 if((array = GetDatabaseArray(dbFile)) == NULL) {
776 fprintf(stderr, "Unable to read '%s' as a database file.\n", dbFile); 801 fprintf(stderr, "Unable to read '%s' as a database file.\n", dbFile);
777 return; 802 return;
778 } 803 }
779   804  
780 // Sort the database. 805 // Sort the database.
781 qsort(array->database, array->count, sizeof(char *), QsortCompare); 806 qsort(array->database, array->count, sizeof(char *), QsortCompare);
782   807  
783 // Write back the database to the database file. 808 // Write back the database to the database file.
784 WriteLinesToFile(dbFile, array->database, array->count); 809 WriteLinesToFile(dbFile, array->database, array->count);
-   810  
-   811 // Deallocate all the lines.
-   812 for(i = 0; i < array->count; ++i) {
-   813 free(array->database[i]);
-   814 }
785   815  
786 free(array); 816 free(array);
787 } 817 }
788   818  
789 /* 819 /*
790 * 820 *
791 * Updates a database file "dbFile". 821 * Updates a database file "dbFile".
792 */ 822 */
793 stats *CollectFiles(char *dbFile, char **paths, unsigned int count) { 823 stats *CollectFiles(char *dbFile, char **paths, unsigned int count) {
794 #if defined ___AsyncIO___ 824 #if defined ___AsyncIO___
795 struct AsyncFile *fp; 825 struct AsyncFile *fp;
796 #else 826 #else
797 FILE *fp; 827 FILE *fp;
798 #endif 828 #endif
799 #if defined ___AmigaOS___ 829 #if defined ___AmigaOS___
800 struct FileInfoBlock *FIBp, *FIBq; 830 struct FileInfoBlock *FIBp, *FIBq;
801 BPTR lockp, lockq; 831 BPTR lockp, lockq;
802 #else 832 #else
803 DIR *dir; 833 DIR *dir;
804 struct dirent *entry; 834 struct dirent *entry;
805 struct stat dirStat; 835 struct stat dirStat;
806 #endif 836 #endif
807 stringStack *stack; 837 stringStack *stack;
808 stats *stats; 838 stats *stats;
809 int i; 839 int i;
810 char *path; 840 char *path;
811 char *sub; 841 char *sub;
812   842  
813 // Initialize metrics. 843 // Initialize metrics.
814 if((stats = malloc(sizeof(stats))) == NULL) { 844 if((stats = malloc(sizeof(*stats))) == NULL) {
815 fprintf(stderr, "Memory allocation failure.\n"); 845 fprintf(stderr, "Memory allocation failure.\n");
816 return NULL; 846 return NULL;
817 } 847 }
818   848  
819 stats->dirs = 0; 849 stats->dirs = 0;
820 stats->files = 0; 850 stats->files = 0;
821   851  
822 #if defined ___AsyncIO___ 852 #if defined ___AsyncIO___
823 if((fp = OpenAsync(dbFile, MODE_APPEND, ASYNC_BUF)) == NULL) { 853 if((fp = OpenAsync(dbFile, MODE_APPEND, ASYNC_BUF)) == NULL) {
824 #else 854 #else
825 if((fp = fopen(dbFile, "r+")) == NULL) { 855 if((fp = fopen(dbFile, "a")) == NULL) {
826 #endif 856 #endif
827 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile); 857 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
828 return stats; 858 return stats;
829 } 859 }
830   -  
831 // Seek to the end of the database. -  
832 #if defined ___AsyncIO___ -  
833 if(SeekAsync(fp, 0, MODE_END) == -1) { -  
834 #else -  
835 if(fseek(fp, 0, SEEK_END) == 0) { -  
836 #endif -  
837 fprintf(stderr, "Unable to seek in '%s' for appending.\n", dbFile); -  
838 #if defined ___AsyncIO___ -  
839 CloseAsync(fp); -  
840 #else -  
841 fclose(fp); -  
842 #endif -  
843 return stats; -  
844 } -  
845   860  
846 if(verbose) { 861 if(verbose) {
847 fprintf(stdout, "Collecting files...\r"); 862 fprintf(stdout, "Collecting files...\r");
848 } 863 }
849   864  
850 // Push the first path onto the stack. 865 // Push the first path onto the stack.
851 stack = stringStackCreate(count); 866 stack = stringStackCreate(count);
852 for(i = 0; run && i < count; ++i) { 867 for(i = 0; run && i < count; ++i) {
853 stringStackPush(stack, paths[i]); 868 stringStackPush(stack, paths[i]);
854 } 869 }
855   870  
856 while(run && !stringStackIsEmpty(stack)) { 871 while(run && !stringStackIsEmpty(stack)) {
857 #if defined ___AmigaOS___ 872 #if defined ___AmigaOS___
858 // Check if CTRL+C was pressed and abort the program. 873 // Check if CTRL+C was pressed and abort the program.
859 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 874 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
860 run = FALSE; 875 run = FALSE;
861 continue; 876 continue;
862 } 877 }
863 #endif 878 #endif
864 if((path = stringStackPop(stack)) == NULL) { 879 if((path = stringStackPop(stack)) == NULL) {
865 break; 880 break;
866 } 881 }
867   882  
868 #if defined ___AmigaOS___ 883 #if defined ___AmigaOS___
869 if((lockp = Lock(path, ACCESS_READ)) == NULL) { 884 if((lockp = Lock(path, ACCESS_READ)) == NULL) {
870 fprintf(stderr, "Could not lock path '%s' for reading.\n", path); 885 fprintf(stderr, "Could not lock path '%s' for reading.\n", path);
871 free(path); 886 free(path);
872 continue; 887 continue;
873 } 888 }
874   889  
875 if((FIBp = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, NULL)) == NULL) { 890 if((FIBp = AllocDosObject(DOS_FIB, NULL)) == NULL) {
876 fprintf(stderr, "Path '%s' info block allocation failure.\n", path); 891 fprintf(stderr, "Path '%s' info block allocation failure.\n", path);
877 UnLock(lockp); 892 UnLock(lockp);
878 free(path); 893 free(path);
879 continue; 894 continue;
880 } 895 }
881   896  
882 if(Examine(lockp, FIBp) == FALSE) { 897 if(Examine(lockp, FIBp) == FALSE) {
883 fprintf(stderr, "Path '%s' could not be examined.\n", path); 898 fprintf(stderr, "Path '%s' could not be examined.\n", path);
884 FreeDosObject(DOS_FIB, FIBp); 899 FreeDosObject(DOS_FIB, FIBp);
885 UnLock(lockp); 900 UnLock(lockp);
886 free(path); 901 free(path);
887 continue; 902 continue;
888 } 903 }
889   904  
890 while(run && ExNext(lockp, FIBp)) { 905 while(run && ExNext(lockp, FIBp)) {
891 // Check if CTRL+C was pressed and abort the program. 906 // Check if CTRL+C was pressed and abort the program.
892 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 907 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
893 run = FALSE; 908 run = FALSE;
-   909 FreeDosObject(DOS_FIB, FIBp);
-   910 UnLock(lockp);
-   911 free(path);
894 continue; 912 break;
895 } 913 }
896 #else 914 #else
897   915  
898 if((dir = opendir(path)) == NULL) { 916 if((dir = opendir(path)) == NULL) {
899 fprintf(stderr, "Unable to open '%s' for reading.\n", path); 917 fprintf(stderr, "Unable to open '%s' for reading.\n", path);
900 free(path); 918 free(path);
901 continue; 919 continue;
902 } 920 }
903   921  
904 while(run && (entry = readdir(dir)) != NULL) { 922 while(run && (entry = readdir(dir)) != NULL) {
905 #endif 923 #endif
906 switch(path[strlen(path) - 1]) { 924 switch(path[strlen(path) - 1]) {
907 case '/': 925 case '/':
908 case ':': // This is a drive path. 926 case ':': // This is a drive path.
909 #if defined ___AmigaOS___ 927 #if defined ___AmigaOS___
910 if((sub = malloc(sizeof(path) + sizeof(FIBp->fib_FileName) + 1)) == NULL) { 928 if((sub = malloc(strlen(path) + strlen(FIBp->fib_FileName) + 1)) == NULL) {
911 #else 929 #else
912 if((sub = malloc(sizeof(path) + sizeof(entry->d_name) + 1)) == NULL) { 930 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) {
913 #endif 931 #endif
914 fprintf(stderr, "Memory allocation failure.\n"); 932 fprintf(stderr, "Memory allocation failure.\n");
915 #if defined ___AmigaOS___ 933 #if defined ___AmigaOS___
916 FreeDosObject(DOS_FIB, FIBp); 934 FreeDosObject(DOS_FIB, FIBp);
917 UnLock(lockp); 935 UnLock(lockp);
918 #else 936 #else
919 closedir(dir); 937 closedir(dir);
920 #endif 938 #endif
921 free(path); 939 free(path);
922 stringStackDestroy(stack); 940 stringStackDestroy(stack);
923 #if defined ___AsyncIO___ 941 #if defined ___AsyncIO___
924 CloseAsync(fp); 942 CloseAsync(fp);
925 #else 943 #else
926 fclose(fp); 944 fclose(fp);
927 #endif 945 #endif
928 return NULL; 946 return NULL;
929 } 947 }
930 #if defined ___AmigaOS___ 948 #if defined ___AmigaOS___
931 sprintf(sub, "%s%s", path, FIBp->fib_FileName); 949 sprintf(sub, "%s%s", path, FIBp->fib_FileName);
932 #else 950 #else
933 sprintf(sub, "%s%s", path, entry->d_name); 951 sprintf(sub, "%s%s", path, entry->d_name);
934 #endif 952 #endif
935 break; 953 break;
936 default: 954 default:
937 #if defined ___AmigaOS___ 955 #if defined ___AmigaOS___
938 if((sub = malloc(sizeof(path) + sizeof(FIBp->fib_FileName) + 1 + 1)) == NULL) { 956 if((sub = malloc(strlen(path) + strlen(FIBp->fib_FileName) + 1 + 1)) == NULL) {
939 #else 957 #else
940 if((sub = malloc(sizeof(path) + sizeof(entry->d_name) + 1 + 1)) == NULL) { 958 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1 + 1)) == NULL) {
941 #endif 959 #endif
942 fprintf(stderr, "Memory allocation failure.\n"); 960 fprintf(stderr, "Memory allocation failure.\n");
943 #if defined ___AmigaOS___ 961 #if defined ___AmigaOS___
944 FreeDosObject(DOS_FIB, FIBp); 962 FreeDosObject(DOS_FIB, FIBp);
945 UnLock(lockp); 963 UnLock(lockp);
946 #else 964 #else
947 closedir(dir); 965 closedir(dir);
948 #endif 966 #endif
949 free(path); 967 free(path);
950 stringStackDestroy(stack); 968 stringStackDestroy(stack);
951 #if defined ___AsyncIO___ 969 #if defined ___AsyncIO___
952 CloseAsync(fp); 970 CloseAsync(fp);
953 #else 971 #else
954 fclose(fp); 972 fclose(fp);
955 #endif 973 #endif
956 return NULL; 974 return NULL;
957 } 975 }
958 #if defined ___AmigaOS___ 976 #if defined ___AmigaOS___
959 sprintf(sub, "%s/%s", path, FIBp->fib_FileName); 977 sprintf(sub, "%s/%s", path, FIBp->fib_FileName);
960 #else 978 #else
961 sprintf(sub, "%s/%s", path, entry->d_name); 979 sprintf(sub, "%s/%s", path, entry->d_name);
962 #endif 980 #endif
963 break; 981 break;
964 } 982 }
-   983  
965   984  
966 #if defined ___AmigaOS___ 985 #if defined ___AmigaOS___
967 if((lockq = Lock(sub, ACCESS_READ)) == NULL) { 986 if((lockq = Lock(sub, ACCESS_READ)) == NULL) {
968 fprintf(stderr, "Could not lock path '%s' for reading.\n", sub); 987 fprintf(stderr, "Could not lock path '%s' for reading.\n", sub);
969 free(sub); 988 free(sub);
970 continue; 989 continue;
971 } 990 }
972   991  
973 if((FIBq = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, NULL)) == NULL) { 992 if((FIBq = AllocDosObject(DOS_FIB, NULL)) == NULL) {
974 fprintf(stderr, "Path '%s' info block allocation failure.\n", sub); 993 fprintf(stderr, "Path '%s' info block allocation failure.\n", sub);
975 UnLock(lockq); 994 UnLock(lockq);
976 free(sub); 995 free(sub);
977 continue; 996 continue;
978 } 997 }
979   998  
980 if(Examine(lockq, FIBq) == FALSE) { 999 if(Examine(lockq, FIBq) == FALSE) {
981 fprintf(stderr, "Path '%s' could not be examined.\n", sub); 1000 fprintf(stderr, "Path '%s' could not be examined.\n", sub);
982 FreeDosObject(DOS_FIB, FIBq); 1001 FreeDosObject(DOS_FIB, FIBq);
983 UnLock(lockq); 1002 UnLock(lockq);
984 free(sub); 1003 free(sub);
985 continue; 1004 continue;
986 } 1005 }
987   1006  
988 if(FIBq->fib_DirEntryType > 0) { 1007 if(FIBq->fib_DirEntryType > 0) {
989 #else 1008 #else
990 stat(sub, &dirStat); 1009 stat(sub, &dirStat);
991 if(S_ISDIR(dirStat.st_mode)) { 1010 if(S_ISDIR(dirStat.st_mode)) {
992 #endif 1011 #endif
993 stringStackPush(stack, sub); 1012 stringStackPush(stack, sub);
994   1013  
995 ++stats->dirs; 1014 ++stats->dirs;
996   1015  
997 if(verbose) { 1016 if(verbose) {
998 fprintf(stdout, 1017 fprintf(stdout,
999 "Gathered %d directories and %d files.\r", 1018 "Gathered %d directories and %d files.\r",
1000 stats->dirs, 1019 stats->dirs,
1001 stats->files); 1020 stats->files);
1002 } 1021 }
1003   1022  
1004 #if defined ___AmigaOS___ 1023 #if defined ___AmigaOS___
1005 FreeDosObject(DOS_FIB, FIBq); 1024 FreeDosObject(DOS_FIB, FIBq);
1006 UnLock(lockq); 1025 UnLock(lockq);
1007 #endif 1026 #endif
1008 free(sub); 1027 free(sub);
1009 continue; 1028 continue;
1010 } 1029 }
1011   1030  
1012 #if defined ___AmigaOS___ 1031 #if defined ___AmigaOS___
1013 FreeDosObject(DOS_FIB, FIBq); 1032 FreeDosObject(DOS_FIB, FIBq);
1014 UnLock(lockq); 1033 UnLock(lockq);
1015 #endif 1034 #endif
-   1035  
-   1036 ++stats->files;
-   1037  
-   1038 if(verbose) {
-   1039 fprintf(stdout,
-   1040 "Gathered %d directories and %d files.\r",
-   1041 stats->dirs,
-   1042 stats->files);
-   1043 }
1016   1044  
1017 #if defined ___NOCASE_FS___ 1045 #if defined ___NOCASE_FS___
1018 #if defined ___AmigaOS___ 1046 #if defined ___AmigaOS___
1019 strupr(FIBp->fib_FileName); 1047 strupr(FIBp->fib_FileName);
1020 #else 1048 #else
1021 strupr(entry->d_name); 1049 strupr(entry->d_name);
1022 #endif 1050 #endif
1023 #endif 1051 #endif
-   1052  
-   1053  
1024 // Write to database file. 1054 // Write to database file.
1025 #if defined ___AsyncIO___ 1055 #if defined ___AsyncIO___
1026 #if defined ___AmigaOS___ 1056 #if defined ___AmigaOS___
1027 WriteAsync(fp, FIBp->fib_FileName, (LONG)strlen(FIBp->fib_FileName)); 1057 WriteAsync(fp, FIBp->fib_FileName, (LONG)strlen(FIBp->fib_FileName));
1028 #else 1058 #else
1029 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name)); 1059 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name));
1030 #endif 1060 #endif
1031 WriteAsync(fp, "\t", 1); 1061 WriteAsync(fp, "\t", 1);
1032 WriteAsync(fp, sub, (LONG)strlen(sub)); 1062 WriteAsync(fp, sub, (LONG)strlen(sub));
1033 WriteAsync(fp, "\n", 1); 1063 WriteAsync(fp, "\n", 1);
1034 #else 1064 #else
1035 #if defined ___AmigaOS___ 1065 #if defined ___AmigaOS___
1036 fprintf(fp, "%s\t%s\n", FIBp->fib_FileName, sub); 1066 fprintf(fp, "%s\t%s\n", FIBp->fib_FileName, sub);
1037 #else 1067 #else
1038 fprintf(fp, "%s\t%s\n", entry->d_name, sub); 1068 fprintf(fp, "%s\t%s\n", entry->d_name, sub);
1039 #endif 1069 #endif
1040 #endif 1070 #endif
1041 ++stats->files; -  
1042   -  
1043 if(verbose) { -  
1044 fprintf(stdout, -  
1045 "Gathered %d directories and %d files.\r", -  
1046 stats->dirs, -  
1047 stats->files); -  
1048 } -  
1049   -  
1050 free(sub); 1071 free(sub);
1051 } 1072 }
1052   1073  
1053 #if defined ___AmigaOS___ 1074 #if defined ___AmigaOS___
1054 FreeDosObject(DOS_FIB, FIBp); 1075 FreeDosObject(DOS_FIB, FIBp);
1055 UnLock(lockp); 1076 UnLock(lockp);
1056 #else 1077 #else
1057 closedir(dir); 1078 closedir(dir);
1058 #endif 1079 #endif
1059 free(path); 1080 free(path);
1060 } 1081 }
1061   1082  
1062 if(verbose) { 1083 if(verbose) {
1063 fprintf(stdout, "\n"); 1084 fprintf(stdout, "\n");
1064 } 1085 }
1065   1086  
1066 stringStackDestroy(stack); 1087 stringStackDestroy(stack);
1067   1088  
1068 #if defined ___AsyncIO___ 1089 #if defined ___AsyncIO___
1069 CloseAsync(fp); 1090 CloseAsync(fp);
1070 #else 1091 #else
1071 fclose(fp); 1092 fclose(fp);
1072 #endif 1093 #endif
1073   1094  
1074 return stats; 1095 return stats;
1075   1096  
1076 } 1097 }
1077   1098  
1078 /* 1099 /*
1079 * 1100 *
1080 * Writes lines from the database "dbFile" to temporary filenames "tmpNames". 1101 * Writes lines from the database "dbFile" to temporary filenames "tmpNames".
1081 */ 1102 */
1082 void WriteTemporaryFiles(char *dbFile, char **tmpNames, int tmpFiles, int tmpLines, int total) { 1103 void WriteTemporaryFiles(char *dbFile, char **tmpNames, int tmpFiles, int tmpLines, int total) {
1083 #if defined ___AsyncIO___ 1104 #if defined ___AsyncIO___
1084 struct AsyncFile *fp, *tp; 1105 struct AsyncFile *fp, *tp;
1085 LONG c; 1106 LONG c;
1086 #else 1107 #else
1087 FILE *fp, *tp; 1108 FILE *fp, *tp;
1088 char c; 1109 char c;
1089 #endif 1110 #endif
1090 int lines; 1111 int lines;
1091 int write; 1112 int write;
1092   1113  
1093 #if defined ___AsyncIO___ 1114 #if defined ___AsyncIO___
1094 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 1115 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
1095 #else 1116 #else
1096 if((fp = fopen(dbFile, "r")) == NULL) { 1117 if((fp = fopen(dbFile, "r")) == NULL) {
1097 #endif 1118 #endif
1098 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile); 1119 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
1099 return; 1120 return;
1100 } 1121 }
1101   1122  
1102 #if defined ___AsyncIO___ 1123 #if defined ___AsyncIO___
1103 if((tp = OpenAsync(tmpNames[--tmpFiles], MODE_WRITE, ASYNC_BUF)) == NULL) { 1124 if((tp = OpenAsync(tmpNames[--tmpFiles], MODE_WRITE, ASYNC_BUF)) == NULL) {
1104 #else 1125 #else
1105 if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) { 1126 if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) {
1106 #endif 1127 #endif
1107 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]); 1128 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]);
1108 #if defined ___AsyncIO___ 1129 #if defined ___AsyncIO___
1109 CloseAsync(fp); 1130 CloseAsync(fp);
1110 #else 1131 #else
1111 fclose(fp); 1132 fclose(fp);
1112 #endif 1133 #endif
1113 return; 1134 return;
1114 } 1135 }
1115   1136  
1116 if(verbose) { 1137 if(verbose) {
1117 fprintf(stdout, "Writing to temporary files...\r"); 1138 fprintf(stdout, "Writing to temporary files...\r");
1118 } 1139 }
1119   1140  
1120 write = 0; 1141 write = 0;
1121 lines = 0; 1142 lines = 0;
1122 #if defined ___AsyncIO___ 1143 #if defined ___AsyncIO___
1123 while(run && (c = ReadCharAsync(fp)) != -1) { 1144 while(run && (c = ReadCharAsync(fp)) != -1) {
1124 #else 1145 #else
1125 while(run && fscanf(fp, "%c", &c) == 1) { 1146 while(run && fscanf(fp, "%c", &c) == 1) {
1126 #endif 1147 #endif
1127 #if defined ___AmigaOS___ 1148 #if defined ___AmigaOS___
1128 // Check if CTRL+C was pressed and abort the program. 1149 // Check if CTRL+C was pressed and abort the program.
1129 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 1150 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
1130 run = FALSE; 1151 run = FALSE;
1131 continue; 1152 continue;
1132 } 1153 }
1133 #endif 1154 #endif
1134 switch(c) { 1155 switch(c) {
1135 case '\n': 1156 case '\n':
1136 // Increment the total written lines. 1157 // Increment the total written lines.
1137 ++write; 1158 ++write;
1138   1159  
1139 if(verbose) { 1160 if(verbose) {
1140 fprintf(stdout, "Writing to temporary files: %d%%.\r", (int)(((float)write / total) * 100.0)); 1161 fprintf(stdout, "Writing to temporary files: %d%%.\r", (int)(((float)write / total) * 100.0));
1141 } 1162 }
1142   1163  
1143 // Write the newline character back. 1164 // Write the newline character back.
1144 #if defined ___AsyncIO___ 1165 #if defined ___AsyncIO___
1145 if(WriteCharAsync(tp, (UBYTE)c) != 1) { 1166 if(WriteCharAsync(tp, (UBYTE)c) != 1) {
1146 #else 1167 #else
1147 if(fprintf(tp, "%c", c) != 1) { 1168 if(fprintf(tp, "%c", c) != 1) {
1148 #endif 1169 #endif
1149 fprintf(stderr, "Unable to write to '%s'.\n", tmpNames[tmpFiles]); 1170 fprintf(stderr, "Unable to write to '%s'.\n", tmpNames[tmpFiles]);
1150 #if defined ___AsyncIO___ 1171 #if defined ___AsyncIO___
1151 CloseAsync(tp); 1172 CloseAsync(tp);
1152 CloseAsync(fp); 1173 CloseAsync(fp);
1153 #else 1174 #else
1154 fclose(tp); 1175 fclose(tp);
1155 fclose(fp); 1176 fclose(fp);
1156 #endif 1177 #endif
1157 return; 1178 return;
1158 } 1179 }
1159 // Switch to the next temporary file. 1180 // Switch to the next temporary file.
1160 if(++lines >= tmpLines) { 1181 if(++lines >= tmpLines) {
1161 // If there are no temporary files left then run till the end. 1182 // If there are no temporary files left then run till the end.
1162 if(tmpFiles - 1 < 0) { 1183 if(tmpFiles - 1 < 0) {
1163 break; 1184 break;
1164 } 1185 }
1165   1186  
1166 // Close the previous temporary file and write to the next temporary file. 1187 // Close the previous temporary file and write to the next temporary file.
1167 #if defined ___AsyncIO___ 1188 #if defined ___AsyncIO___
1168 CloseAsync(tp); 1189 CloseAsync(tp);
1169 if((tp = OpenAsync(tmpNames[--tmpFiles], MODE_WRITE, ASYNC_BUF)) == NULL) { 1190 if((tp = OpenAsync(tmpNames[--tmpFiles], MODE_WRITE, ASYNC_BUF)) == NULL) {
1170 #else 1191 #else
1171 fclose(tp); 1192 fclose(tp);
1172 if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) { 1193 if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) {
1173 #endif 1194 #endif
1174 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]); 1195 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]);
1175 #if defined ___AsyncIO___ 1196 #if defined ___AsyncIO___
1176 CloseAsync(fp); 1197 CloseAsync(fp);
1177 #else 1198 #else
1178 fclose(fp); 1199 fclose(fp);
1179 #endif 1200 #endif
1180 return; 1201 return;
1181 } 1202 }
1182 lines = 0; 1203 lines = 0;
1183 break; 1204 break;
1184 } 1205 }
1185 break; 1206 break;
1186 default: 1207 default:
1187 #if defined ___AsyncIO___ 1208 #if defined ___AsyncIO___
1188 if(WriteCharAsync(tp, (UBYTE)c) != 1) { 1209 if(WriteCharAsync(tp, (UBYTE)c) != 1) {
1189 #else 1210 #else
1190 if(fprintf(tp, "%c", c) != 1) { 1211 if(fprintf(tp, "%c", c) != 1) {
1191 #endif 1212 #endif
1192 fprintf(stderr, "Unable to write to '%s'.\n", tmpNames[tmpFiles]); 1213 fprintf(stderr, "Unable to write to '%s'.\n", tmpNames[tmpFiles]);
1193 #if defined ___AsyncIO___ 1214 #if defined ___AsyncIO___
1194 CloseAsync(tp); 1215 CloseAsync(tp);
1195 CloseAsync(fp); 1216 CloseAsync(fp);
1196 #else 1217 #else
1197 fclose(tp); 1218 fclose(tp);
1198 fclose(fp); 1219 fclose(fp);
1199 #endif 1220 #endif
1200 return; 1221 return;
1201 } 1222 }
1202 break; 1223 break;
1203 } 1224 }
1204 } 1225 }
1205   1226  
1206 if(verbose) { 1227 if(verbose) {
1207 fprintf(stdout, "\n"); 1228 fprintf(stdout, "\n");
1208 } 1229 }
1209   1230  
1210 #if defined ___AsyncIO___ 1231 #if defined ___AsyncIO___
1211 CloseAsync(tp); 1232 CloseAsync(tp);
1212 CloseAsync(fp); 1233 CloseAsync(fp);
1213 #else 1234 #else
1214 fclose(tp); 1235 fclose(tp);
1215 fclose(fp); 1236 fclose(fp);
1216 #endif 1237 #endif
1217 } 1238 }
1218   1239  
1219 /* 1240 /*
1220 * 1241 *
1221 * Merges temporary files "tmpNames" into a database "dbFile". 1242 * Merges temporary files "tmpNames" into a database "dbFile".
1222 */ 1243 */
1223 void MergeTemporaryFiles(char *dbFile, char **tmpNames, int files, int lines) { 1244 void MergeTemporaryFiles(char *dbFile, char **tmpNames, int files, int lines) {
1224 #if defined ___AsyncIO___ 1245 #if defined ___AsyncIO___
1225 struct AsyncFile *fp; 1246 struct AsyncFile *fp;
1226 struct AsyncFile **tp; 1247 struct AsyncFile **tp;
1227 #else 1248 #else
1228 FILE *fp; 1249 FILE *fp;
1229 FILE **tp; 1250 FILE **tp;
1230 #endif 1251 #endif
1231 int i; 1252 int i;
1232 int j; 1253 int j;
1233 char *tmp; 1254 char *tmp;
1234 char *rem; 1255 char *rem;
1235 char *min; 1256 char *min;
1236 int count; 1257 int count;
1237   1258  
1238 #if defined ___AsyncIO___ 1259 #if defined ___AsyncIO___
1239 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) { 1260 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
1240 #else 1261 #else
1241 if((fp = fopen(dbFile, "w")) == NULL) { 1262 if((fp = fopen(dbFile, "w")) == NULL) {
1242 #endif 1263 #endif
1243 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile); 1264 fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
1244 return; 1265 return;
1245 } 1266 }
1246   1267  
1247 // Allocate as many file pointers as temporary files. 1268 // Allocate as many file pointers as temporary files.
1248 if((tp = malloc(files * sizeof(*tp))) == NULL) { 1269 if((tp = malloc(files * sizeof(*tp))) == NULL) {
1249 fprintf(stderr, "Memory allocation failure.\n"); 1270 fprintf(stderr, "Memory allocation failure.\n");
1250 #if defined ___AsyncIO___ 1271 #if defined ___AsyncIO___
1251 CloseAsync(fp); 1272 CloseAsync(fp);
1252 #else 1273 #else
1253 fclose(fp); 1274 fclose(fp);
1254 #endif 1275 #endif
1255 return; 1276 return;
1256 } 1277 }
1257   1278  
1258 // Open all temporary files for reading. 1279 // Open all temporary files for reading.
1259 for(i = 0; i < files; ++i) { 1280 for(i = 0; i < files; ++i) {
1260 #if defined ___AsyncIO___ 1281 #if defined ___AsyncIO___
1261 if((tp[i] = OpenAsync(tmpNames[i], MODE_READ, ASYNC_BUF)) == NULL) { 1282 if((tp[i] = OpenAsync(tmpNames[i], MODE_READ, ASYNC_BUF)) == NULL) {
1262 #else 1283 #else
1263 if((tp[i] = fopen(tmpNames[i], "r")) == NULL) { 1284 if((tp[i] = fopen(tmpNames[i], "r")) == NULL) {
1264 #endif 1285 #endif
1265 fprintf(stderr, "Unable to open '%s' for reading.\n", tmpNames[i]); 1286 fprintf(stderr, "Unable to open '%s' for reading.\n", tmpNames[i]);
1266 // Close all temporary files. 1287 // Close all temporary files.
1267 while(--i > -1) { 1288 while(--i > -1) {
1268 #if defined ___AsyncIO___ 1289 #if defined ___AsyncIO___
1269 CloseAsync(tp[i]); 1290 CloseAsync(tp[i]);
1270 #else 1291 #else
1271 fclose(tp[i]); 1292 fclose(tp[i]);
1272 #endif 1293 #endif
1273 } 1294 }
1274 #if defined ___AsyncIO___ 1295 #if defined ___AsyncIO___
1275 CloseAsync(fp); 1296 CloseAsync(fp);
1276 #else 1297 #else
1277 fclose(fp); 1298 fclose(fp);
1278 #endif 1299 #endif
1279 return; 1300 return;
1280 } 1301 }
1281 } 1302 }
1282   1303  
1283 if(verbose) { 1304 if(verbose) {
1284 fprintf(stdout, "Merging all files...\r"); 1305 fprintf(stdout, "Merging all files...\r");
1285 } 1306 }
1286   1307  
1287 rem = NULL; 1308 rem = NULL;
1288 count = lines; 1309 count = lines;
1289 j = 0; 1310 j = 0;
1290 while(run && --count > -1) { 1311 while(run && --count > -1) {
1291 #if defined ___AmigaOS___ 1312 #if defined ___AmigaOS___
1292 // Check if CTRL+C was pressed and abort the program. 1313 // Check if CTRL+C was pressed and abort the program.
1293 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 1314 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
1294 run = FALSE; 1315 run = FALSE;
1295 continue; 1316 continue;
1296 } 1317 }
1297 #endif 1318 #endif
1298 // Find the smallest line in all temporary files. 1319 // Find the smallest line in all temporary files.
1299 if(verbose) { 1320 if(verbose) {
1300 fprintf(stdout, "Merging all files: %d%%.\r", 100 - (int)(((float)count / lines) * 100.0)); 1321 fprintf(stdout, "Merging all files: %d%%.\r", 100 - (int)(((float)count / lines) * 100.0));
1301 } 1322 }
1302   1323  
1303 min = NULL; 1324 min = NULL;
1304 for(i = 0; i < files; ++i) { 1325 for(i = 0; i < files; ++i) {
1305 tmp = PeekLine(tp[i]); 1326 tmp = PeekLine(tp[i]);
1306 if(tmp == NULL) { 1327 if(tmp == NULL) {
1307 continue; 1328 continue;
1308 } 1329 }
1309 #if defined ___AmigaOS___ 1330 #if defined ___AmigaOS___
1310 if(min == NULL || StrnCmp(locale, tmp, min, -1, SC_ASCII) < 0) { 1331 if(min == NULL || StrnCmp(locale, tmp, min, -1, SC_ASCII) < 0) {
1311 #else 1332 #else
1312 if(min == NULL || strcmp(tmp, min) < 0) { 1333 if(min == NULL || strcmp(tmp, min) < 0) {
1313 #endif 1334 #endif
1314 if(min != NULL) { 1335 if(min != NULL) {
1315 // Free previous instance. 1336 // Free previous instance.
1316 free(min); 1337 free(min);
1317 } 1338 }
1318 if((min = malloc((strlen(tmp) + 1) * sizeof(*min))) == NULL) { 1339 if((min = malloc((strlen(tmp) + 1) * sizeof(*min))) == NULL) {
1319 fprintf(stderr, "Memory allication failure.\n"); 1340 fprintf(stderr, "Memory allication failure.\n");
1320 free(tmp); 1341 free(tmp);
1321 if(min != NULL) { 1342 if(min != NULL) {
1322 free(min); 1343 free(min);
1323 } 1344 }
1324 if(rem != NULL) { 1345 if(rem != NULL) {
1325 free(rem); 1346 free(rem);
1326 } 1347 }
1327 #if defined ___AsyncIO___ 1348 #if defined ___AsyncIO___
1328 CloseAsync(fp); 1349 CloseAsync(fp);
1329 #else 1350 #else
1330 fclose(fp); 1351 fclose(fp);
1331 #endif 1352 #endif
1332 return; 1353 return;
1333 } 1354 }
1334 sprintf(min, "%s", tmp); 1355 sprintf(min, "%s", tmp);
1335 // Remember the index of the file where the smallest entry has been found. 1356 // Remember the index of the file where the smallest entry has been found.
1336 j = i; 1357 j = i;
1337 } 1358 }
1338 free(tmp); 1359 free(tmp);
1339 } 1360 }
1340   1361  
1341 // Forward the file where the smallest line was found. 1362 // Forward the file where the smallest line was found.
1342 SkipLine(tp[j]); 1363 SkipLine(tp[j]);
1343   1364  
1344 // Write the smallest line. 1365 // Write the smallest line.
1345 if(min != NULL) { 1366 if(min != NULL) {
1346 // If current minimum line is identical to previous minimum line then skip to remove duplicates. 1367 // If current minimum line is identical to previous minimum line then skip to remove duplicates.
1347 if(rem != NULL) { 1368 if(rem != NULL) {
1348 #if defined ___AmigaOS___ 1369 #if defined ___AmigaOS___
1349 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) { 1370 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) {
1350 #else 1371 #else
1351 if(strcmp(min, rem) == 0) { 1372 if(strcmp(min, rem) == 0) {
1352 #endif 1373 #endif
1353 free(min); 1374 free(min);
1354 continue; 1375 continue;
1355 } 1376 }
1356 } 1377 }
1357   1378  
1358 #if defined ___AsyncIO___ 1379 #if defined ___AsyncIO___
1359 WriteAsync(fp, min, (LONG)strlen(min)); 1380 WriteAsync(fp, min, (LONG)strlen(min));
1360 WriteAsync(fp, "\n", 1); 1381 WriteAsync(fp, "\n", 1);
1361 #else 1382 #else
1362 fprintf(fp, "%s\n", min); 1383 fprintf(fp, "%s\n", min);
1363 #endif 1384 #endif
1364   1385  
1365 if(rem != NULL) { 1386 if(rem != NULL) {
1366 free(rem); 1387 free(rem);
1367 } 1388 }
1368   1389  
1369 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) { 1390 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) {
1370 fprintf(stderr, "Memory allocation failure.\n"); 1391 fprintf(stderr, "Memory allocation failure.\n");
1371 free(min); 1392 free(min);
1372 #if defined ___AsyncIO___ 1393 #if defined ___AsyncIO___
1373 CloseAsync(fp); 1394 CloseAsync(fp);
1374 #else 1395 #else
1375 fclose(fp); 1396 fclose(fp);
1376 #endif 1397 #endif
1377 return; 1398 return;
1378 } 1399 }
1379   1400  
1380 sprintf(rem, "%s", min); 1401 sprintf(rem, "%s", min);
1381 free(min); 1402 free(min);
1382 } 1403 }
1383 } 1404 }
1384   1405  
1385 if(rem != NULL) { 1406 if(rem != NULL) {
1386 free(rem); 1407 free(rem);
1387 } 1408 }
1388   1409  
1389 // Write out any remaining contents from the temporary files. 1410 // Write out any remaining contents from the temporary files.
1390 for(i = 0; run && i < files; ++i) { 1411 for(i = 0; run && i < files; ++i) {
1391 #if defined ___AmigaOS___ 1412 #if defined ___AmigaOS___
1392 // Check if CTRL+C was pressed and abort the program. 1413 // Check if CTRL+C was pressed and abort the program.
1393 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 1414 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
1394 run = FALSE; 1415 run = FALSE;
1395 continue; 1416 continue;
1396 } 1417 }
1397 #endif 1418 #endif
1398 tmp = ReadLine(tp[i]); 1419 tmp = ReadLine(tp[i]);
1399 if(tmp == NULL) { 1420 if(tmp == NULL) {
1400 continue; 1421 continue;
1401 } 1422 }
1402 #if defined ___AsyncIO___ 1423 #if defined ___AsyncIO___
1403 WriteAsync(fp, tmp, (LONG)strlen(tmp)); 1424 WriteAsync(fp, tmp, (LONG)strlen(tmp));
1404 WriteAsync(fp, "\n", 1); 1425 WriteAsync(fp, "\n", 1);
1405 #else 1426 #else
1406 fprintf(fp, "%s\n", tmp); 1427 fprintf(fp, "%s\n", tmp);
1407 #endif 1428 #endif
1408 free(tmp); 1429 free(tmp);
1409 } 1430 }
1410   1431  
1411 // Close all temporary files. 1432 // Close all temporary files.
1412 for(i = 0; i < files; ++i) { 1433 for(i = 0; i < files; ++i) {
1413 #if defined ___AsyncIO___ 1434 #if defined ___AsyncIO___
1414 CloseAsync(tp[i]); 1435 CloseAsync(tp[i]);
1415 #else 1436 #else
1416 fclose(tp[i]); 1437 fclose(tp[i]);
1417 #endif 1438 #endif
1418 } 1439 }
1419   1440  
1420 if(verbose) { 1441 if(verbose) {
1421 fprintf(stdout, "\n"); 1442 fprintf(stdout, "\n");
1422 } 1443 }
1423   1444  
1424 #if defined ___AsyncIO___ 1445 #if defined ___AsyncIO___
1425 CloseAsync(fp); 1446 CloseAsync(fp);
1426 #else 1447 #else
1427 fclose(fp); 1448 fclose(fp);
1428 #endif 1449 #endif
1429 } 1450 }
1430   1451  
1431 /* 1452 /*
1432 * 1453 *
1433 * Filter the paths inside the database with provided paths. 1454 * Filter the paths inside the database with provided paths.
1434 */ 1455 */
1435 void FilterDatabasePaths(char *dbFile, char *tmpName, char **paths, unsigned int count) { 1456 void FilterDatabasePaths(char *dbFile, char *tmpName, char **paths, unsigned int count) {
1436 #if defined ___AsyncIO___ 1457 #if defined ___AsyncIO___
1437 struct AsyncFile *fp; 1458 struct AsyncFile *fp;
1438 struct AsyncFile *tp; 1459 struct AsyncFile *tp;
1439 #else 1460 #else
1440 FILE *fp; 1461 FILE *fp;
1441 FILE *tp; 1462 FILE *tp;
1442 #endif 1463 #endif
1443 char *line; 1464 char *line;
1444 int i; 1465 int i;
1445 dbEntry *entry; 1466 dbEntry *entry;
1446   1467  
1447 // Open database file for reading. 1468 // Open database file for reading.
1448 #if defined ___AsyncIO___ 1469 #if defined ___AsyncIO___
1449 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 1470 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
1450 #else 1471 #else
1451 if((fp = fopen(dbFile, "r")) == NULL) { 1472 if((fp = fopen(dbFile, "r")) == NULL) {
1452 #endif 1473 #endif
1453 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile); 1474 fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
1454 return; 1475 return;
1455 } 1476 }
1456   1477  
1457 // Open temporary file for writing. 1478 // Open temporary file for writing.
1458 #if defined ___AsyncIO___ 1479 #if defined ___AsyncIO___
1459 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) { 1480 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) {
1460 #else 1481 #else
1461 if((tp = fopen(tmpName, "w")) == NULL) { 1482 if((tp = fopen(tmpName, "w")) == NULL) {
1462 #endif 1483 #endif
1463 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpName); 1484 fprintf(stderr, "Unable to open '%s' for writing.\n", tmpName);
1464   1485  
1465 // Close database file. 1486 // Close database file.
1466 #if defined ___AsyncIO___ 1487 #if defined ___AsyncIO___
1467 CloseAsync(fp); 1488 CloseAsync(fp);
1468 #else 1489 #else
1469 fclose(fp); 1490 fclose(fp);
1470 #endif 1491 #endif
1471   1492  
1472 return; 1493 return;
1473 } 1494 }
1474   1495  
1475 while(run && (line = ReadLine(fp)) != NULL) { 1496 while(run && (line = ReadLine(fp)) != NULL) {
1476 #if defined ___AmigaOS___ 1497 #if defined ___AmigaOS___
1477 // Check if CTRL+C was pressed and abort the program. 1498 // Check if CTRL+C was pressed and abort the program.
1478 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 1499 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
1479 run = FALSE; 1500 run = FALSE;
1480 continue; 1501 continue;
1481 } 1502 }
1482 #endif 1503 #endif
1483 if((entry = CreateDataseEntry(line)) == NULL) { 1504 if((entry = CreateDataseEntry(line)) == NULL) {
1484 fprintf(stderr, "Unable to create database entry.\n"); 1505 fprintf(stderr, "Unable to create database entry.\n");
1485 continue; 1506 continue;
1486 } 1507 }
1487 for(i = 0; i < count; ++i) { 1508 for(i = 0; i < count; ++i) {
1488 if(PathCompare(entry->path, paths[i]) == TRUE) { 1509 if(PathCompare(entry->path, paths[i]) == TRUE) {
1489 continue; 1510 continue;
1490 } 1511 }
1491 #if defined ___AsyncIO___ 1512 #if defined ___AsyncIO___
1492 WriteAsync(tp, line, (LONG)strlen(line)); 1513 WriteAsync(tp, line, (LONG)strlen(line));
1493 WriteAsync(tp, "\n", 1); 1514 WriteAsync(tp, "\n", 1);
1494 #else 1515 #else
1495 fprintf(tp, "%s\n", line); 1516 fprintf(tp, "%s\n", line);
1496 #endif 1517 #endif
1497 break; 1518 break;
1498 } 1519 }
1499   1520  
1500 free(entry); 1521 free(entry);
1501 free(line); 1522 free(line);
1502 } 1523 }
1503   1524  
1504   1525  
1505 #if defined ___AsyncIO___ 1526 #if defined ___AsyncIO___
1506 CloseAsync(fp); 1527 CloseAsync(fp);
1507 CloseAsync(tp); 1528 CloseAsync(tp);
1508 #else 1529 #else
1509 fclose(fp); 1530 fclose(fp);
1510 fclose(tp); 1531 fclose(tp);
1511 #endif 1532 #endif
1512 } 1533 }
1513   1534  
1514 /* 1535 /*
1515 * 1536 *
1516 * Indexes a "path" by creating a database "dbFile". 1537 * Indexes a "path" by creating a database "dbFile".
1517 */ 1538 */
1518 void GatherDatabaseFiles(char *dbFile, char **paths, unsigned int count) { 1539 void GatherDatabaseFiles(char *dbFile, char **paths, unsigned int count) {
1519 stats *stats; 1540 stats *stats;
1520 char **tmpNames; 1541 char **tmpNames;
1521 int dbSize; 1542 int dbSize;
1522 int dbLines; 1543 int dbLines;
1523 int tmpFiles; 1544 int tmpFiles;
1524 int tmpLines; 1545 int tmpLines;
1525 int i; 1546 int i;
1526   1547  
1527 // Generate the database file from the supplied paths. 1548 // Generate the database file from the supplied paths.
1528 if((stats = CollectFiles(dbFile, paths, count)) == NULL) { 1549 if((stats = CollectFiles(dbFile, paths, count)) == NULL) {
1529 fprintf(stderr, "Collecting files failed.\n"); 1550 fprintf(stderr, "Collecting files failed.\n");
1530 return; 1551 return;
1531 } 1552 }
1532 free(stats); 1553 free(stats);
1533   1554  
1534 // Compute the amount of temporary files needed. 1555 // Compute the amount of temporary files needed.
1535 dbSize = GetFileSize(dbFile); 1556 dbSize = GetFileSize(dbFile);
1536 if(dbSize == -1) { 1557 if(dbSize == -1) {
1537 fprintf(stderr, "File size for '%s' failed.\n", dbFile); 1558 fprintf(stderr, "File size for '%s' failed.\n", dbFile);
1538 return; 1559 return;
1539 } 1560 }
1540 tmpFiles = dbSize / maxmem; 1561 tmpFiles = dbSize / maxmem;
1541   1562  
1542 /* In case no temporary files are required, 1563 /* In case no temporary files are required,
1543 * just sort the database and terminate. 1564 * just sort the database and terminate.
1544 */ 1565 */
1545 if(tmpFiles <= 1) { 1566 if(tmpFiles <= 1) {
1546 SortDatabase(dbFile); 1567 SortDatabase(dbFile);
1547 return; 1568 return;
1548 } 1569 }
1549   1570  
1550 // Get the database metrics. 1571 // Get the database metrics.
1551 dbLines = CountFileLines(dbFile); 1572 dbLines = CountFileLines(dbFile);
1552 if(dbLines == -1) { 1573 if(dbLines == -1) {
1553 fprintf(stderr, "Counting lines of '%s' failed.\n", dbFile); 1574 fprintf(stderr, "Counting lines of '%s' failed.\n", dbFile);
1554 } 1575 }
1555 tmpLines = dbLines / tmpFiles; 1576 tmpLines = dbLines / tmpFiles;
1556   1577  
1557 // Create temporary files. 1578 // Create temporary files.
1558 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) { 1579 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
1559 fprintf(stderr, "Unable to create temporary files.\n"); 1580 fprintf(stderr, "Unable to create temporary files.\n");
1560 return; 1581 return;
1561 } 1582 }
1562   1583  
1563 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile". 1584 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
1564 WriteTemporaryFiles(dbFile, tmpNames, tmpFiles, tmpLines, dbLines); 1585 WriteTemporaryFiles(dbFile, tmpNames, tmpFiles, tmpLines, dbLines);
1565   1586  
1566 // Sort the temporary files. 1587 // Sort the temporary files.
1567 for(i = 0; run && i < tmpFiles; ++i) { 1588 for(i = 0; run && i < tmpFiles; ++i) {
1568 SortDatabase(tmpNames[i]); 1589 SortDatabase(tmpNames[i]);
1569 } 1590 }
1570   1591  
1571 // Merge all the temporary files to the database file. 1592 // Merge all the temporary files to the database file.
1572 MergeTemporaryFiles(dbFile, tmpNames, tmpFiles, dbLines); 1593 MergeTemporaryFiles(dbFile, tmpNames, tmpFiles, dbLines);
1573   1594  
1574 // Remove all temporary files. 1595 // Remove all temporary files.
1575 RemoveFiles(tmpNames, tmpFiles); 1596 RemoveFiles(tmpNames, tmpFiles);
1576   1597  
1577 free(tmpNames); 1598 free(tmpNames);
1578 } 1599 }
1579   1600  
1580 void RemoveDatabaseFiles(char *dbFile, char **paths, unsigned int count) { 1601 void RemoveDatabaseFiles(char *dbFile, char **paths, unsigned int count) {
1581 char *tmpName; 1602 char *tmpName;
1582   1603  
1583 // Create a temporary file to hold the changes. 1604 // Create a temporary file to hold the changes.
1584 if((tmpName = CreateTemporaryFile()) == NULL) { 1605 if((tmpName = CreateTemporaryFile()) == NULL) {
1585 fprintf(stderr, "Unable to create temporary file.\n"); 1606 fprintf(stderr, "Unable to create temporary file.\n");
1586 return; 1607 return;
1587 } 1608 }
1588   1609  
1589 // Filter the database of the provided paths. 1610 // Filter the database of the provided paths.
1590 FilterDatabasePaths(dbFile, tmpName, paths, count); 1611 FilterDatabasePaths(dbFile, tmpName, paths, count);
1591   1612  
1592 // Overwrite the database file with the filtered paths. 1613 // Overwrite the database file with the filtered paths.
1593 CopyFile(tmpName, dbFile); 1614 CopyFile(tmpName, dbFile);
1594   1615  
1595 // Remove temporary file. 1616 // Remove temporary file.
1596 RemoveFile(tmpName); 1617 RemoveFile(tmpName);
1597 } 1618 }
1598   1619  
1599 void usage(char *name) { 1620 void usage(char *name) {
1600 fprintf(stdout, "Hunt & Gather - %s, a file index generating tool. \n", name); 1621 fprintf(stdout, "Hunt & Gather - %s, a file index generating tool. \n", name);
1601 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION); 1622 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION);
1602 fprintf(stdout, " \n"); 1623 fprintf(stdout, " \n");
1603 fprintf(stdout, "SYNTAX: %s [-q] <-a|-r|-c> <PATH PATH PATH...> \n", name); 1624 fprintf(stdout, "SYNTAX: %s [-q] <-a|-r|-c> <PATH PATH PATH...> \n", name);
1604 fprintf(stdout, " \n"); 1625 fprintf(stdout, " \n");
1605 fprintf(stdout, "Required: \n"); 1626 fprintf(stdout, "Required: \n");
1606 fprintf(stdout, " -a [PATH...] Add files. \n"); 1627 fprintf(stdout, " -a [PATH...] Add files. \n");
1607 fprintf(stdout, " -c [PATH...] Create from scratch. \n"); 1628 fprintf(stdout, " -c [PATH...] Create from scratch. \n");
1608 fprintf(stdout, " -r [PATH...] Remove files. \n"); 1629 fprintf(stdout, " -r [PATH...] Remove files. \n");
1609 fprintf(stdout, " \n"); 1630 fprintf(stdout, " \n");
1610 fprintf(stdout, "Optional: \n"); 1631 fprintf(stdout, "Optional: \n");
1611 fprintf(stdout, " -d [FIILE] Where to store the database. \n"); 1632 fprintf(stdout, " -d [FIILE] Where to store the database. \n");
1612 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem); 1633 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem);
1613 fprintf(stdout, " -q Do not print out any messages. \n"); 1634 fprintf(stdout, " -q Do not print out any messages. \n");
1614 fprintf(stdout, " \n"); 1635 fprintf(stdout, " \n");
1615 fprintf(stdout, "DATABASE is a path to where the indexed results will be \n"); 1636 fprintf(stdout, "DATABASE is a path to where the indexed results will be \n");
1616 fprintf(stdout, "stored for searching with the Hunt tool. \n"); 1637 fprintf(stdout, "stored for searching with the Hunt tool. \n");
1617 fprintf(stdout, " \n"); 1638 fprintf(stdout, " \n");
1618 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n"); 1639 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n");
1619 } 1640 }
1620   1641  
1621 /* 1642 /*
1622 * 1643 *
1623 * Main entry point. 1644 * Main entry point.
1624 */ 1645 */
1625 int main(int argc, char **argv) { 1646 int main(int argc, char **argv) {
1626 #if defined ___AmigaOS___ 1647 #if defined ___AmigaOS___
1627 struct FileInfoBlock *FIB; 1648 struct FileInfoBlock *FIB;
1628 BPTR lock; 1649 BPTR lock;
1629 #else 1650 #else
1630 struct stat dirStat; 1651 struct stat dirStat;
1631 #endif 1652 #endif
1632 int option; 1653 int option;
1633 unsigned int i; 1654 unsigned int i;
1634 unsigned int count; 1655 unsigned int count;
1635 char *dbFile; 1656 char *dbFile;
1636 char *path; 1657 char *path;
1637 char **paths; 1658 char **paths;
1638   1659  
1639 // Bind handler to SIGINT. 1660 // Bind handler to SIGINT.
1640 #if !defined ___AmigaOS___ 1661 #if !defined ___AmigaOS___
1641 signal(SIGINT, SignalHandler); 1662 signal(SIGINT, SignalHandler);
1642 #endif 1663 #endif
1643   1664  
1644 dbFile = DEFAULT_DATABASE_FILE; 1665 dbFile = DEFAULT_DATABASE_FILE;
1645 while((option = getopt(argc, argv, "hqdm:arc")) != -1) { 1666 while((option = getopt(argc, argv, "hqdm:arc")) != -1) {
1646 switch(option) { 1667 switch(option) {
1647 case 'a': 1668 case 'a':
1648 operation = GATHER; 1669 operation = GATHER;
1649 break; 1670 break;
1650 case 'r': 1671 case 'r':
1651 operation = REMOVE; 1672 operation = REMOVE;
1652 break; 1673 break;
1653 case 'c': 1674 case 'c':
1654 operation = CREATE; 1675 operation = CREATE;
1655 break; 1676 break;
1656 case 'm': 1677 case 'm':
1657 maxmem = strtoul(optarg, NULL, 10); 1678 maxmem = strtoul(optarg, NULL, 10);
1658 break; 1679 break;
1659 case 'd': 1680 case 'd':
1660 dbFile = optarg; 1681 dbFile = optarg;
1661 break; 1682 break;
1662 case 'q': 1683 case 'q':
1663 verbose = FALSE; 1684 verbose = FALSE;
1664 break; 1685 break;
1665 case 'h': 1686 case 'h':
1666 usage(argv[0]); 1687 usage(argv[0]);
1667 return 0; 1688 return 0;
1668 case '?': 1689 case '?':
1669 fprintf(stderr, "Invalid option %ct.\n", optopt); 1690 fprintf(stderr, "Invalid option %ct.\n", optopt);
1670 return 1; 1691 return 1;
1671 } 1692 }
1672 } 1693 }
1673   1694  
1674 if(operation == NONE) { 1695 if(operation == NONE) {
1675 usage(argv[0]); 1696 usage(argv[0]);
1676 return 1; 1697 return 1;
1677 } 1698 }
1678   1699  
1679 if(optind >= argc) { 1700 if(optind >= argc) {
1680 usage(argv[0]); 1701 usage(argv[0]);
1681 return 1; 1702 return 1;
1682 } 1703 }
1683   1704  
1684 // Go through all supplied arguments and add paths to search. 1705 // Go through all supplied arguments and add paths to search.
1685 if((paths = malloc((argc - optind) * sizeof(*paths))) == NULL) { 1706 if((paths = malloc((argc - optind) * sizeof(*paths))) == NULL) {
1686 fprintf(stderr, "Memory allocation failure.\n"); 1707 fprintf(stderr, "Memory allocation failure.\n");
1687 return 1; 1708 return 1;
1688 } 1709 }
1689 for(i = optind, count = 0; i < argc; ++i, ++count) { 1710 for(i = optind, count = 0; i < argc; ++i, ++count) {
1690 if((path = PathToAbsolute(argv[i])) == NULL) { 1711 if((path = PathToAbsolute(argv[i])) == NULL) {
1691 fprintf(stderr, "Absolute path for '%s' failed to resolve.\n", argv[optind]); 1712 fprintf(stderr, "Absolute path for '%s' failed to resolve.\n", argv[optind]);
1692 continue; 1713 continue;
1693 } 1714 }
1694   1715  
1695 // Check that the path is a directory. 1716 // Check that the path is a directory.
1696 #if defined ___AmigaOS___ 1717 #if defined ___AmigaOS___
1697 if((lock = Lock(path, ACCESS_READ)) == NULL) { 1718 if((lock = Lock(path, ACCESS_READ)) == NULL) {
1698 fprintf(stderr, "Path '%s' is not accessible.\n", path); 1719 fprintf(stderr, "Path '%s' is not accessible.\n", path);
1699 free(path); 1720 free(path);
1700 continue; 1721 continue;
1701 } 1722 }
1702   1723  
1703 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) { 1724 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
1704 fprintf(stderr, "Path '%s' file information block not accessible.\n", path); 1725 fprintf(stderr, "Path '%s' file information block not accessible.\n", path);
1705 UnLock(lock); 1726 UnLock(lock);
1706 free(path); 1727 free(path);
1707 continue; 1728 continue;
1708 } 1729 }
1709   1730  
1710 if(Examine(lock, FIB) == FALSE) { 1731 if(Examine(lock, FIB) == FALSE) {
1711 fprintf(stderr, "Path '%s' information unexaminable.\n", path); 1732 fprintf(stderr, "Path '%s' information unexaminable.\n", path);
1712 UnLock(lock); 1733 UnLock(lock);
1713 FreeDosObject(DOS_FIB, FIB); 1734 FreeDosObject(DOS_FIB, FIB);
1714 free(path); 1735 free(path);
1715 continue; 1736 continue;
1716 } 1737 }
1717   1738  
1718 if(FIB->fib_DirEntryType < 0) { 1739 if(FIB->fib_DirEntryType < 0) {
1719 #else 1740 #else
1720 stat(path, &dirStat); 1741 stat(path, &dirStat);
1721 if(!S_ISDIR(dirStat.st_mode)) { 1742 if(!S_ISDIR(dirStat.st_mode)) {
1722 #endif 1743 #endif
1723 fprintf(stderr, "Path '%s' is not a directory.\n", argv[optind]); 1744 fprintf(stderr, "Path '%s' is not a directory.\n", argv[optind]);
1724 #if defined ___AmigaOS___ 1745 #if defined ___AmigaOS___
1725 UnLock(lock); 1746 UnLock(lock);
1726 FreeDosObject(DOS_FIB, FIB); 1747 FreeDosObject(DOS_FIB, FIB);
1727 #endif 1748 #endif
1728 free(path); 1749 free(path);
1729 return 1; 1750 return 1;
1730 } 1751 }
1731   1752  
1732 if(verbose) { 1753 if(verbose) {
1733 fprintf(stdout, "Will process path: '%s'\n", path); 1754 fprintf(stdout, "Will process path: '%s'\n", path);
1734 } 1755 }
1735   1756  
1736 // Add the path to the array of paths. 1757 // Add the path to the array of paths.
1737 if((paths[count] = malloc(strlen(path) * sizeof(*paths[count]))) == NULL) { 1758 if((paths[count] = malloc((strlen(path) + 1) * sizeof(*paths[count]))) == NULL) {
1738 fprintf(stderr, "Memory allocation failure."); 1759 fprintf(stderr, "Memory allocation failure.");
1739 return 1; 1760 return 1;
1740 } 1761 }
1741   1762  
1742 sprintf(paths[count], "%s", path); 1763 sprintf(paths[count], "%s", path);
1743   1764  
1744 #if defined ___AmigaOS___ 1765 #if defined ___AmigaOS___
1745 UnLock(lock); 1766 UnLock(lock);
1746 FreeDosObject(DOS_FIB, FIB); 1767 FreeDosObject(DOS_FIB, FIB);
1747 #endif 1768 #endif
1748 free(path); 1769 free(path);
1749   1770  
1750 } 1771 }
1751   1772  
1752 if(verbose) { 1773 if(verbose) {
1753 fprintf(stdout, "Gathering to: '%s'\n", dbFile); 1774 fprintf(stdout, "Gathering to: '%s'\n", dbFile);
1754 } 1775 }
1755   1776  
1756 #if defined ___AmigaOS___ 1777 #if defined ___AmigaOS___
1757 locale = OpenLocale(NULL); 1778 locale = OpenLocale(NULL);
1758 #endif 1779 #endif
1759   1780  
1760 // Gather. 1781 // Gather.
1761 switch(operation) { 1782 switch(operation) {
1762 case CREATE: 1783 case CREATE:
1763 if(verbose) { 1784 if(verbose) {
1764 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile); 1785 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile);
1765 } 1786 }
1766 RemoveFile(dbFile); 1787 RemoveFile(dbFile);
1767 case GATHER: 1788 case GATHER:
1768 if(verbose) { 1789 if(verbose) {
1769 fprintf(stdout, "Gathering files to database...\n"); 1790 fprintf(stdout, "Gathering files to database...\n");
1770 } 1791 }
1771 GatherDatabaseFiles(dbFile, paths, count); 1792 GatherDatabaseFiles(dbFile, paths, count);
1772 break; 1793 break;
1773 case REMOVE: 1794 case REMOVE:
1774 if(verbose) { 1795 if(verbose) {
1775 fprintf(stdout, "Removing files from database...\n"); 1796 fprintf(stdout, "Removing files from database...\n");
1776 } 1797 }
1777 RemoveDatabaseFiles(dbFile, paths, count); 1798 RemoveDatabaseFiles(dbFile, paths, count);
1778 break; 1799 break;
1779 default: 1800 default:
1780 break; 1801 break;
1781 } 1802 }
1782   1803  
1783 #if defined ___AmigaOS___ 1804 #if defined ___AmigaOS___
1784 CloseLocale(locale); 1805 CloseLocale(locale);
1785 #endif 1806 #endif
1786   1807  
1787 free(paths); 1808 free(paths);
1788   1809  
1789 return 0; 1810 return 0;
1790 } 1811 }
1791   1812