HuntnGather – Diff between revs 30 and 31

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