HuntnGather – Diff between revs 28 and 29

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