HuntnGather – Diff between revs 52 and 53

Subversion Repositories:
Rev:
Only display areas with differencesRegard whitespace
Rev 52 Rev 53
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 <math.h> 8 #include <math.h>
9 #if !defined ___AmigaOS___ 9 #if !defined ___AmigaOS___
10 #include <dirent.h> 10 #include <dirent.h>
11 #include <sys/stat.h> 11 #include <sys/stat.h>
12 #include <signal.h> 12 #include <signal.h>
13 #endif 13 #endif
14   14  
15 #include <sys/types.h> 15 #include <sys/types.h>
16 #include <sys/syslimits.h> 16 #include <sys/syslimits.h>
17   17  
18 #if defined ___AmigaOS___ 18 #if defined ___AmigaOS___
19 #include <proto/dos.h> 19 #include <proto/dos.h>
20 #include <proto/exec.h> 20 #include <proto/exec.h>
21 #include <proto/locale.h> 21 #include <proto/locale.h>
22 #include <clib/utility_protos.h> 22 #include <clib/utility_protos.h>
23 #endif 23 #endif
24   24  
25 #if defined ___AsyncIO___ 25 #if defined ___AsyncIO___
26 #include <asyncio.h> 26 #include <asyncio.h>
27 #endif 27 #endif
28   28  
29 #if !defined ___HAVE_GETOPT___ 29 #if !defined ___HAVE_GETOPT___
30 #include "/shared/getopt.h" 30 #include "/shared/getopt.h"
31 #endif 31 #endif
32   32  
33 #include "stack.h" 33 #include "stack.h"
34 #include "/shared/utilities.h" 34 #include "/shared/utilities.h"
35   35  
36 #define PROGRAM_VERSION "1.7.7" 36 #define PROGRAM_VERSION "1.7.7"
37   37  
38 #if defined ___AmigaOS___ 38 #if defined ___AmigaOS___
39 /*************************************************************************/ 39 /*************************************************************************/
40 /* Version string used for querrying the program version. */ 40 /* Version string used for querrying the program version. */
41 /*************************************************************************/ 41 /*************************************************************************/
42 TEXT version_string[] = 42 TEXT version_string[] =
43 "\0$VER: Gather " PROGRAM_VERSION " "__DATE__" by Wizardry and Steamworks"; 43 "\0$VER: Gather " PROGRAM_VERSION " "__DATE__" by Wizardry and Steamworks";
44 #endif 44 #endif
45   45  
46 int PROGRAM_RUN = TRUE; 46 int PROGRAM_RUN = TRUE;
47 int PROGRAM_VERBOSE = TRUE; 47 int PROGRAM_VERBOSE = TRUE;
48 int maxmem = MAX_MEM; 48 int maxmem = MAX_MEM;
49   49  
50 // Define global locale for string compare. 50 // Define global locale for string compare.
51 #if defined ___AmigaOS___ 51 #if defined ___AmigaOS___
52 struct Locale *locale; 52 struct Locale *locale;
53 #endif 53 #endif
54   54  
55 void SignalHandler(int sig) { 55 void SignalHandler(int sig) {
56 /* Toggle the run flag to stop execution. */ 56 /* Toggle the run flag to stop execution. */
57 PROGRAM_RUN = FALSE; 57 PROGRAM_RUN = FALSE;
58 } 58 }
59   59  
60 /* 60 /*
61 * 61 *
62 * Used for sorting database lines. 62 * Used for sorting database lines.
63 */ 63 */
64 int QsortCompare(const void *a, const void *b) { 64 int QsortCompare(const void *a, const void *b) {
65 #if defined ___AmigaOS___ 65 #if defined ___AmigaOS___
66 return StrnCmp( 66 return StrnCmp(
67 locale, 67 locale,
68 (STRPTR)(*(const char **)a), 68 (STRPTR)(*(const char **)a),
69 (STRPTR)*((const char **)b), 69 (STRPTR)*((const char **)b),
70 -1, 70 -1,
71 SC_ASCII 71 SC_ASCII
72 ); 72 );
73 #else 73 #else
74 return strcmp(*(const char **)a, *(const char **)b); 74 return strcmp(*(const char **)a, *(const char **)b);
75 #endif 75 #endif
76 } 76 }
77   77  
78 /* 78 /*
79 * 79 *
80 * Sorts a database file lexicographically. 80 * Sorts a database file lexicographically.
81 */ 81 */
82 void SortDatabase(char *dbFile, int lines) { 82 void SortDatabase(char *dbFile, int lines) {
83 #if defined ___AsyncIO___ 83 #if defined ___AsyncIO___
84 struct AsyncFile *fp; 84 struct AsyncFile *fp;
85 #else 85 #else
86 FILE *fp; 86 FILE *fp;
87 #endif 87 #endif
88 char **database; 88 char **database;
89 dbEntry *entry; 89 dbEntry *entry;
90 dbLine *line; 90 dbLine *line;
91 char *rem; 91 char *rem;
92 int count; 92 int count;
93 int i; 93 int i;
94   94  
95 // Open database file for reading. 95 // Open database file for reading.
96 #if defined ___AsyncIO___ 96 #if defined ___AsyncIO___
97 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 97 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
98 #else 98 #else
99 if((fp = fopen(dbFile, "r")) == NULL) { 99 if((fp = fopen(dbFile, "r")) == NULL) {
100 #endif 100 #endif
101 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile); 101 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
102 return; 102 return;
103 } 103 }
104   104  
105 if((database = malloc(lines * sizeof(*database))) == NULL) { 105 if((database = malloc(lines * sizeof(*database))) == NULL) {
106 fprintf(stderr, "Memory allocation failure.\n"); 106 fprintf(stderr, "Memory allocation failure.\n");
107 #if defined ___AsyncIO___ 107 #if defined ___AsyncIO___
108 CloseAsync(fp); 108 CloseAsync(fp);
109 #else 109 #else
110 fclose(fp); 110 fclose(fp);
111 #endif 111 #endif
112 return; 112 return;
113 } 113 }
114   114  
115 if(PROGRAM_VERBOSE) { 115 if(PROGRAM_VERBOSE) {
116 fprintf(stdout, "Reading lines from file '%s' to array...\n", dbFile); 116 fprintf(stdout, "Reading lines from file '%s' to array...\n", dbFile);
117 } 117 }
118   118  
119 count = 0; 119 count = 0;
120 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) { 120 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
121 #if defined ___AmigaOS___ 121 #if defined ___AmigaOS___
122 // Check if CTRL+C was pressed and abort the program. 122 // Check if CTRL+C was pressed and abort the program.
123 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 123 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
124 PROGRAM_RUN = FALSE; 124 PROGRAM_RUN = FALSE;
125 continue; 125 continue;
126 } 126 }
127 #endif 127 #endif
128 if((entry = CreateDatabaseEntry(line)) == NULL) { 128 if((entry = CreateDatabaseEntry(line)) == NULL) {
129 fprintf(stderr, "Unable to create database entry.\n"); 129 fprintf(stderr, "Unable to create database entry.\n");
130   130  
131 free(line->string); 131 free(line->string);
132 free(line); 132 free(line);
133 line = NULL; 133 line = NULL;
134   134  
135 #if defined ___AsyncIO___ 135 #if defined ___AsyncIO___
136 CloseAsync(fp); 136 CloseAsync(fp);
137 #else 137 #else
138 fclose(fp); 138 fclose(fp);
139 #endif 139 #endif
140 return; 140 return;
141 } 141 }
142   142  
143 if((database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*database[count]))) == NULL) { 143 if((database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*database[count]))) == NULL) {
144 fprintf(stderr, "Memory allocation failure.\n"); 144 fprintf(stderr, "Memory allocation failure.\n");
145   145  
146 // Free database entry. 146 // Free database entry.
147 free(entry->name); 147 free(entry->name);
148 free(entry->path); 148 free(entry->path);
149 free(entry); 149 free(entry);
150 entry = NULL; 150 entry = NULL;
151   151  
152 // Free the line. 152 // Free the line.
153 free(line->string); 153 free(line->string);
154 free(line); 154 free(line);
155 line = NULL; 155 line = NULL;
156   156  
157 #if defined ___AsyncIO___ 157 #if defined ___AsyncIO___
158 CloseAsync(fp); 158 CloseAsync(fp);
159 #else 159 #else
160 fclose(fp); 160 fclose(fp);
161 #endif 161 #endif
162 return; 162 return;
163 } 163 }
164   164  
165 sprintf(database[count], "%s\t%s", entry->name, entry->path); 165 sprintf(database[count], "%s\t%s", entry->name, entry->path);
166 ++count; 166 ++count;
167   167  
168 // Free the database entry. 168 // Free the database entry.
169 free(entry->name); 169 free(entry->name);
170 free(entry->path); 170 free(entry->path);
171 free(entry); 171 free(entry);
172 entry = NULL; 172 entry = NULL;
173   173  
174 // Free the line. 174 // Free the line.
175 free(line->string); 175 free(line->string);
176 free(line); 176 free(line);
177 line = NULL; 177 line = NULL;
178 } 178 }
179   179  
180 #if defined ___AsyncIO___ 180 #if defined ___AsyncIO___
181 CloseAsync(fp); 181 CloseAsync(fp);
182 #else 182 #else
183 fclose(fp); 183 fclose(fp);
184 #endif 184 #endif
185   185  
186 if(PROGRAM_VERBOSE) { 186 if(PROGRAM_VERBOSE) {
187 fprintf(stdout, "Sorting %d lines in '%s'...\n", count, dbFile); 187 fprintf(stdout, "Sorting %d lines in '%s'...\n", count, dbFile);
188 } 188 }
189   189  
190 // Sort the database. 190 // Sort the database.
191 qsort(database, (unsigned int)count, sizeof(char *), QsortCompare); 191 qsort(database, (unsigned int)count, sizeof(char *), QsortCompare);
192   192  
193 if(PROGRAM_VERBOSE) { 193 if(PROGRAM_VERBOSE) {
194 fprintf(stdout, "Writing %d sorted lines to '%s'...\n", count, dbFile); 194 fprintf(stdout, "Writing %d sorted lines to '%s'...\n", count, dbFile);
195 } 195 }
196   196  
197 // Write the database lines back to the database. 197 // Write the database lines back to the database.
198 #if defined ___AsyncIO___ 198 #if defined ___AsyncIO___
199 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) { 199 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
200 #else 200 #else
201 if((fp = fopen(dbFile, "w")) == NULL) { 201 if((fp = fopen(dbFile, "w")) == NULL) {
202 #endif 202 #endif
203 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile); 203 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
204 return; 204 return;
205 } 205 }
206   206  
207 rem = NULL; 207 rem = NULL;
208 for(i = 0; PROGRAM_RUN && i < count; ++i) { 208 for(i = 0; PROGRAM_RUN && i < count; ++i) {
209 #if defined ___AmigaOS___ 209 #if defined ___AmigaOS___
210 // Check if CTRL+C was pressed and abort the program. 210 // Check if CTRL+C was pressed and abort the program.
211 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 211 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
212 PROGRAM_RUN = FALSE; 212 PROGRAM_RUN = FALSE;
213 continue; 213 continue;
214 } 214 }
215 #endif 215 #endif
216   216  
217 if(rem != NULL) { 217 if(rem != NULL) {
218 #if defined ___AmigaOS___ 218 #if defined ___AmigaOS___
219 if(StrnCmp(locale, database[i], rem, -1, SC_ASCII) == 0) { 219 if(StrnCmp(locale, database[i], rem, -1, SC_ASCII) == 0) {
220 #else 220 #else
221 if(strcmp(database[i], rem) == 0) { 221 if(strcmp(database[i], rem) == 0) {
222 #endif 222 #endif
223 continue; 223 continue;
224 } 224 }
225 } 225 }
226   226  
227 #if defined ___AsyncIO___ 227 #if defined ___AsyncIO___
228 WriteAsync(fp, database[i], (LONG)strlen(database[i])); 228 WriteAsync(fp, database[i], (LONG)strlen(database[i]));
229 WriteAsync(fp, "\n", 1); 229 WriteAsync(fp, "\n", 1);
230 #else 230 #else
231 fprintf(fp, "%s\n", database[i]); 231 fprintf(fp, "%s\n", database[i]);
232 #endif 232 #endif
233   233  
234 if(rem != NULL) { 234 if(rem != NULL) {
235 free(rem); 235 free(rem);
236 rem = NULL; 236 rem = NULL;
237 } 237 }
238   238  
239 rem = malloc((strlen(database[i]) + 1) * sizeof(*rem)); 239 rem = malloc((strlen(database[i]) + 1) * sizeof(*rem));
240 sprintf(rem, "%s", database[i]); 240 sprintf(rem, "%s", database[i]);
241 } 241 }
242   242  
243 if(rem != NULL) { 243 if(rem != NULL) {
244 free(rem); 244 free(rem);
245 rem = NULL; 245 rem = NULL;
246 } 246 }
247   247  
248 #if defined ___AsyncIO___ 248 #if defined ___AsyncIO___
249 CloseAsync(fp); 249 CloseAsync(fp);
250 #else 250 #else
251 fclose(fp); 251 fclose(fp);
252 #endif 252 #endif
253   253  
254 if(PROGRAM_VERBOSE) { 254 if(PROGRAM_VERBOSE) {
255 fprintf(stdout, "Disposing %d lines of file '%s'...\n", count, dbFile); 255 fprintf(stdout, "Disposing %d lines of file '%s'...\n", count, dbFile);
256 } 256 }
257   257  
258 // Free up database. 258 // Free up database.
259 for(i = 0; i < count; ++i) { 259 for(i = 0; i < count; ++i) {
260 free(database[i]); 260 free(database[i]);
261 database[i] = NULL; 261 database[i] = NULL;
262 } 262 }
263   263  
264 free(database); 264 free(database);
265 } 265 }
266   266  
267 /* 267 /*
268 * 268 *
269 * Updates a database file "dbFile". 269 * Updates a database file "dbFile".
270 */ 270 */
271 dbStats *CollectFiles(char *dbFile, VECTOR *paths) { 271 dbStats *CollectFiles(char *dbFile, VECTOR *paths) {
272 #if defined ___AsyncIO___ 272 #if defined ___AsyncIO___
273 struct AsyncFile *fp; 273 struct AsyncFile *fp;
274 #else 274 #else
275 FILE *fp; 275 FILE *fp;
276 #endif 276 #endif
277 #if defined ___AmigaOS___ 277 #if defined ___AmigaOS___
278 struct FileInfoBlock *FIB; 278 struct FileInfoBlock *FIB;
279 BPTR lock; 279 BPTR lock;
280 #else 280 #else
281 DIR *dir; 281 DIR *dir;
282 struct dirent *entry; 282 struct dirent *entry;
283 #endif 283 #endif
284 stack *stack; 284 stack *stack;
285 dbStats *stats = NULL; 285 dbStats *stats = NULL;
286 int i; 286 int i;
287 char *path; 287 char *path;
288 char *sub; 288 char *sub;
289   289  
290 #if defined ___AsyncIO___ 290 #if defined ___AsyncIO___
291 if((fp = OpenAsync(dbFile, MODE_APPEND, ASYNC_BUF)) == NULL) { 291 if((fp = OpenAsync(dbFile, MODE_APPEND, ASYNC_BUF)) == NULL) {
292 #else 292 #else
293 if((fp = fopen(dbFile, "a")) == NULL) { 293 if((fp = fopen(dbFile, "a")) == NULL) {
294 #endif 294 #endif
295 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile); 295 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
296 return NULL; 296 return NULL;
297 } 297 }
298   298  
299 if(PROGRAM_VERBOSE) { 299 if(PROGRAM_VERBOSE) {
300 fprintf(stdout, "Collecting files...\r"); 300 fprintf(stdout, "Collecting files...\r");
301 } 301 }
302   302  
303 // Initialize metrics. 303 // Initialize metrics.
304 if((stats = malloc(sizeof(*stats))) == NULL) { 304 if((stats = malloc(sizeof(*stats))) == NULL) {
305 fprintf(stderr, "Memory allocation failure.\n"); 305 fprintf(stderr, "Memory allocation failure.\n");
306 #if defined ___AsyncIO___ 306 #if defined ___AsyncIO___
307 CloseAsync(fp); 307 CloseAsync(fp);
308 #else 308 #else
309 fclose(fp); 309 fclose(fp);
310 #endif 310 #endif
311 return NULL; 311 return NULL;
312 } 312 }
313   313  
314 stats->dirs = 0; 314 stats->dirs = 0;
315 stats->files = 0; 315 stats->files = 0;
316 stats->lines = 0; 316 stats->lines = 0;
317 stats->size = 0; 317 stats->size = 0;
318   318  
319 // Push the first path onto the stack. 319 // Push the first path onto the stack.
320 stack = stackCreate((unsigned int)paths->length); 320 stack = stackCreate((unsigned int)paths->length);
321 for(i = 0; PROGRAM_RUN && i < paths->length; ++i) { 321 for(i = 0; PROGRAM_RUN && i < paths->length; ++i) {
322 if(PROGRAM_VERBOSE) { 322 if(PROGRAM_VERBOSE) {
323 fprintf(stdout, "Pushing path '%s'\n", (char *)paths->array[i]); 323 fprintf(stdout, "Pushing path '%s'\n", (char *)paths->array[i]);
324 } 324 }
325 stackPush(stack, paths->array[i], (strlen(paths->array[i]) + 1) * sizeof(char)); 325 stackPush(stack, paths->array[i], (strlen(paths->array[i]) + 1) * sizeof(char));
326 } 326 }
327   327  
328 while(PROGRAM_RUN && !stackIsEmpty(stack)) { 328 while(PROGRAM_RUN && !stackIsEmpty(stack)) {
329 #if defined ___AmigaOS___ 329 #if defined ___AmigaOS___
330 // Check if CTRL+C was pressed and abort the program. 330 // Check if CTRL+C was pressed and abort the program.
331 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 331 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
332 PROGRAM_RUN = FALSE; 332 PROGRAM_RUN = FALSE;
333 continue; 333 continue;
334 } 334 }
335 #endif 335 #endif
336 if((path = (char *)stackPop(stack)) == NULL) { 336 if((path = (char *)stackPop(stack)) == NULL) {
337 break; 337 break;
338 } 338 }
339   339  
340 #if defined ___AmigaOS___ 340 #if defined ___AmigaOS___
341 if((lock = Lock(path, ACCESS_READ)) == NULL) { 341 if((lock = Lock(path, ACCESS_READ)) == NULL) {
342 fprintf(stderr, "Could not lock path '%s' for reading.\n", path); 342 fprintf(stderr, "Could not lock path '%s' for reading.\n", path);
343 free(path); 343 free(path);
344 path = NULL; 344 path = NULL;
345 continue; 345 continue;
346 } 346 }
347   347  
348 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) { 348 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
349 fprintf(stderr, "File information block for path '%s' could not be allocated.\n", path); 349 fprintf(stderr, "File information block for path '%s' could not be allocated.\n", path);
350 UnLock(lock); 350 UnLock(lock);
351 free(path); 351 free(path);
352 path = NULL; 352 path = NULL;
353 continue; 353 continue;
354 } 354 }
355   355  
356 if(Examine(lock, FIB) == FALSE) { 356 if(Examine(lock, FIB) == FALSE) {
357 fprintf(stderr, "Path '%s' could not be examined.\n", path); 357 fprintf(stderr, "Path '%s' could not be examined.\n", path);
358 FreeDosObject(DOS_FIB, FIB); 358 FreeDosObject(DOS_FIB, FIB);
359 FIB = NULL; 359 FIB = NULL;
360 UnLock(lock); 360 UnLock(lock);
361 free(path); 361 free(path);
362 path = NULL; 362 path = NULL;
363 continue; 363 continue;
364 } 364 }
365   365  
366 while(PROGRAM_RUN && ExNext(lock, FIB)) { 366 while(PROGRAM_RUN && ExNext(lock, FIB)) {
367 // Check if CTRL+C was pressed and abort the program. 367 // Check if CTRL+C was pressed and abort the program.
368 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 368 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
369 PROGRAM_RUN = FALSE; 369 PROGRAM_RUN = FALSE;
370 continue; 370 continue;
371 } 371 }
372 #else 372 #else
373   373  
374 if((dir = opendir(path)) == NULL) { 374 if((dir = opendir(path)) == NULL) {
375 fprintf(stderr, "Directory '%s' could not be opened.\n", path); 375 fprintf(stderr, "Directory '%s' could not be opened.\n", path);
376 free(path); 376 free(path);
377 path = NULL; 377 path = NULL;
378 continue; 378 continue;
379 } 379 }
380   380  
381 while(PROGRAM_RUN && (entry = readdir(dir)) != NULL) { 381 while(PROGRAM_RUN && (entry = readdir(dir)) != NULL) {
382 #endif 382 #endif
383 switch(path[strlen(path) - 1]) { 383 switch(path[strlen(path) - 1]) {
384 case '/': 384 case '/':
385 case ':': // This is a drive path. 385 case ':': // This is a drive path.
386 #if defined ___AmigaOS___ 386 #if defined ___AmigaOS___
387 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1)) == NULL) { 387 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1)) == NULL) {
388 #else 388 #else
389 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) { 389 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) {
390 #endif 390 #endif
391 fprintf(stderr, "Memory allocation failure.\n"); 391 fprintf(stderr, "Memory allocation failure.\n");
392 #if defined ___AmigaOS___ 392 #if defined ___AmigaOS___
393 FreeDosObject(DOS_FIB, FIB); 393 FreeDosObject(DOS_FIB, FIB);
394 FIB = NULL; 394 FIB = NULL;
395 UnLock(lock); 395 UnLock(lock);
396 #else 396 #else
397 closedir(dir); 397 closedir(dir);
398 #endif 398 #endif
399 free(path); 399 free(path);
400 path = NULL; 400 path = NULL;
401   401  
402 stackDestroy(stack); 402 stackDestroy(stack);
403 #if defined ___AsyncIO___ 403 #if defined ___AsyncIO___
404 CloseAsync(fp); 404 CloseAsync(fp);
405 #else 405 #else
406 fclose(fp); 406 fclose(fp);
407 #endif 407 #endif
408 return NULL; 408 return NULL;
409 } 409 }
410 #if defined ___AmigaOS___ 410 #if defined ___AmigaOS___
411 sprintf(sub, "%s%s", path, FIB->fib_FileName); 411 sprintf(sub, "%s%s", path, FIB->fib_FileName);
412 #else 412 #else
413 sprintf(sub, "%s%s", path, entry->d_name); 413 sprintf(sub, "%s%s", path, entry->d_name);
414 #endif 414 #endif
415 break; 415 break;
416 default: 416 default:
417 #if defined ___AmigaOS___ 417 #if defined ___AmigaOS___
418 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1 + 1)) == NULL) { 418 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1 + 1)) == NULL) {
419 #else 419 #else
420 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1 + 1)) == NULL) { 420 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1 + 1)) == NULL) {
421 #endif 421 #endif
422 fprintf(stderr, "Memory allocation failure.\n"); 422 fprintf(stderr, "Memory allocation failure.\n");
423 #if defined ___AmigaOS___ 423 #if defined ___AmigaOS___
424 FreeDosObject(DOS_FIB, FIB); 424 FreeDosObject(DOS_FIB, FIB);
425 FIB = NULL; 425 FIB = NULL;
426 UnLock(lock); 426 UnLock(lock);
427 #else 427 #else
428 closedir(dir); 428 closedir(dir);
429 #endif 429 #endif
430 free(path); 430 free(path);
431 path = NULL; 431 path = NULL;
432   432  
433 stackDestroy(stack); 433 stackDestroy(stack);
434 #if defined ___AsyncIO___ 434 #if defined ___AsyncIO___
435 CloseAsync(fp); 435 CloseAsync(fp);
436 #else 436 #else
437 fclose(fp); 437 fclose(fp);
438 #endif 438 #endif
439 return NULL; 439 return NULL;
440 } 440 }
441 #if defined ___AmigaOS___ 441 #if defined ___AmigaOS___
442 sprintf(sub, "%s/%s", path, FIB->fib_FileName); 442 sprintf(sub, "%s/%s", path, FIB->fib_FileName);
443 #else 443 #else
444 sprintf(sub, "%s/%s", path, entry->d_name); 444 sprintf(sub, "%s/%s", path, entry->d_name);
445 #endif 445 #endif
446 break; 446 break;
447 } 447 }
448   448  
449 switch(GetFsType(sub)) { 449 switch(GetFsType(sub)) {
450 case UNKNOWN: 450 case UNKNOWN:
451 free(sub); 451 free(sub);
452 sub = NULL; 452 sub = NULL;
453 continue; 453 continue;
454 case REGULAR: 454 case REGULAR:
455 ++stats->files; 455 ++stats->files;
456   456  
457 if(PROGRAM_VERBOSE) { 457 if(PROGRAM_VERBOSE) {
458 fprintf(stdout, 458 fprintf(stdout,
459 "Gathered '%d' directories and '%d' files.\r", 459 "Gathered '%d' directories and '%d' files.\r",
460 stats->dirs, 460 stats->dirs,
461 stats->files); 461 stats->files);
462 } 462 }
463 break; 463 break;
464 case DIRECTORY: 464 case DIRECTORY:
465 stackPush(stack, sub, (strlen(sub) + 1) * sizeof(char)); 465 stackPush(stack, sub, (strlen(sub) + 1) * sizeof(char));
466   466  
467 ++stats->dirs; 467 ++stats->dirs;
468   468  
469 if(PROGRAM_VERBOSE) { 469 if(PROGRAM_VERBOSE) {
470 fprintf(stdout, 470 fprintf(stdout,
471 "Gathered '%d' directories and '%d' files.\r", 471 "Gathered '%d' directories and '%d' files.\r",
472 stats->dirs, 472 stats->dirs,
473 stats->files); 473 stats->files);
474 } 474 }
475   475  
476 free(sub); 476 free(sub);
477 sub = NULL; 477 sub = NULL;
478 continue; 478 continue;
479 } 479 }
480   480  
481 #if defined ___NOCASE_FS___ 481 #if defined ___NOCASE_FS___
482 #if defined ___AmigaOS___ 482 #if defined ___AmigaOS___
483 StrUpr(FIB->fib_FileName); 483 StrUpr(FIB->fib_FileName);
484 #else 484 #else
485 StrUpr(entry->d_name); 485 StrUpr(entry->d_name);
486 #endif 486 #endif
487 #endif 487 #endif
488   488  
489 // Write to database file. 489 // Write to database file.
490 #if defined ___AsyncIO___ 490 #if defined ___AsyncIO___
491 #if defined ___AmigaOS___ 491 #if defined ___AmigaOS___
492 WriteAsync(fp, FIB->fib_FileName, (LONG)strlen(FIB->fib_FileName)); 492 WriteAsync(fp, FIB->fib_FileName, (LONG)strlen(FIB->fib_FileName));
493 stats->size = stats->size + strlen(FIB->fib_FileName); 493 stats->size = stats->size + strlen(FIB->fib_FileName);
494 #else 494 #else
495 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name)); 495 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name));
496 stats->size = stats->size + strlen(entry->d_name); 496 stats->size = stats->size + strlen(entry->d_name);
497 #endif 497 #endif
498 WriteAsync(fp, "\t", 1); 498 WriteAsync(fp, "\t", 1);
499 ++stats->size; 499 ++stats->size;
500 WriteAsync(fp, sub, (LONG)strlen(sub)); 500 WriteAsync(fp, sub, (LONG)strlen(sub));
501 stats->size = stats->size + strlen(sub); 501 stats->size = stats->size + strlen(sub);
502 WriteAsync(fp, "\n", 1); 502 WriteAsync(fp, "\n", 1);
503 ++stats->size; 503 ++stats->size;
504 #else 504 #else
505 #if defined ___AmigaOS___ 505 #if defined ___AmigaOS___
506 fprintf(fp, "%s\t%s\n", FIB->fib_FileName, sub); 506 fprintf(fp, "%s\t%s\n", FIB->fib_FileName, sub);
507 stats->size = stats->size + strlen(FIB->fib_FileName) + strlen(sub) + 1 + 1 + 1; 507 stats->size = stats->size + strlen(FIB->fib_FileName) + strlen(sub) + 1 + 1 + 1;
508 #else 508 #else
509 fprintf(fp, "%s\t%s\n", entry->d_name, sub); 509 fprintf(fp, "%s\t%s\n", entry->d_name, sub);
510 stats->size = stats->size + strlen(entry->d_name) + strlen(sub) + 1 + 1 + 1; 510 stats->size = stats->size + strlen(entry->d_name) + strlen(sub) + 1 + 1 + 1;
511 #endif 511 #endif
512 #endif 512 #endif
513   513  
514 ++stats->lines; 514 ++stats->lines;
515   515  
516 free(sub); 516 free(sub);
517 sub = NULL; 517 sub = NULL;
518 } 518 }
519   519  
520 #if defined ___AmigaOS___ 520 #if defined ___AmigaOS___
521 FreeDosObject(DOS_FIB, FIB); 521 FreeDosObject(DOS_FIB, FIB);
522 FIB = NULL; 522 FIB = NULL;
523 UnLock(lock); 523 UnLock(lock);
524 #else 524 #else
525 closedir(dir); 525 closedir(dir);
526 #endif 526 #endif
527 free(path); 527 free(path);
528 path = NULL; 528 path = NULL;
529 } 529 }
530   530  
531 if(PROGRAM_VERBOSE) { 531 if(PROGRAM_VERBOSE) {
532 fprintf(stdout, "\n"); 532 fprintf(stdout, "\n");
533 } 533 }
534   534  
535 stackDestroy(stack); 535 stackDestroy(stack);
536   536  
537 #if defined ___AsyncIO___ 537 #if defined ___AsyncIO___
538 CloseAsync(fp); 538 CloseAsync(fp);
539 #else 539 #else
540 fclose(fp); 540 fclose(fp);
541 #endif 541 #endif
542   542  
543 return stats; 543 return stats;
544   544  
545 } 545 }
546   546  
547 /* 547 /*
548 * 548 *
549 * Writes lines from the database "dbFile" to temporary filenames "tmpNames". 549 * Writes lines from the database "dbFile" to temporary filenames "tmpNames".
550 */ 550 */
551 void WriteTemporaryFiles(char *dbFile, VECTOR *tmpNames, int tmpLines, int total) { 551 void WriteTemporaryFiles(char *dbFile, VECTOR *tmpNames, int tmpLines, int total) {
552 #if defined ___AsyncIO___ 552 #if defined ___AsyncIO___
553 struct AsyncFile *fp, *tp; 553 struct AsyncFile *fp, *tp;
554 #else 554 #else
555 FILE *fp, *tp; 555 FILE *fp, *tp;
556 #endif 556 #endif
557 int lines; 557 int lines;
558 int write; 558 int write;
559 int files; 559 int files;
560 dbLine *line = NULL; 560 dbLine *line = NULL;
561   561  
562 #if defined ___AsyncIO___ 562 #if defined ___AsyncIO___
563 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 563 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
564 #else 564 #else
565 if((fp = fopen(dbFile, "r")) == NULL) { 565 if((fp = fopen(dbFile, "r")) == NULL) {
566 #endif 566 #endif
567 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile); 567 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
568 return; 568 return;
569 } 569 }
570   570  
571 files = tmpNames->length; 571 files = tmpNames->length;
572 #if defined ___AsyncIO___ 572 #if defined ___AsyncIO___
573 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) { 573 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) {
574 #else 574 #else
575 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) { 575 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) {
576 #endif 576 #endif
577 fprintf(stderr, "Could not open file '%s' for writing.\n", (char *)tmpNames->array[files]); 577 fprintf(stderr, "Could not open file '%s' for writing.\n", (char *)tmpNames->array[files]);
578 #if defined ___AsyncIO___ 578 #if defined ___AsyncIO___
579 CloseAsync(fp); 579 CloseAsync(fp);
580 #else 580 #else
581 fclose(fp); 581 fclose(fp);
582 #endif 582 #endif
583 return; 583 return;
584 } 584 }
585   585  
586 if(PROGRAM_VERBOSE) { 586 if(PROGRAM_VERBOSE) {
587 fprintf(stdout, "Writing to temporary files...\r"); 587 fprintf(stdout, "Writing to temporary files...\r");
588 } 588 }
589   589  
590 write = 0; 590 write = 0;
591 lines = 0; 591 lines = 0;
592   592  
593 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) { 593 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
594 #if defined ___AmigaOS___ 594 #if defined ___AmigaOS___
595 // Check if CTRL+C was pressed and abort the program. 595 // Check if CTRL+C was pressed and abort the program.
596 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 596 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
597 free(line->string); 597 free(line->string);
598 free(line); 598 free(line);
599 line = NULL; 599 line = NULL;
600   600  
601 PROGRAM_RUN = FALSE; 601 PROGRAM_RUN = FALSE;
602 continue; 602 continue;
603 } 603 }
604 #endif 604 #endif
605   605  
606 #if defined ___AsyncIO___ 606 #if defined ___AsyncIO___
607 WriteAsync(tp, line->string, (LONG)line->length); 607 WriteAsync(tp, line->string, (LONG)line->length);
608 WriteAsync(tp, "\n", 1); 608 WriteAsync(tp, "\n", 1);
609 #else 609 #else
610 fprintf(tp, "%s\n", line->string); 610 fprintf(tp, "%s\n", line->string);
611 #endif 611 #endif
612   612  
613 ++write; 613 ++write;
614   614  
615 if(PROGRAM_VERBOSE) { 615 if(PROGRAM_VERBOSE) {
616 fprintf(stdout, "Writing to temporary files: %d%%.\r", (int)(((float)write / total) * 100.0)); 616 fprintf(stdout, "Writing to temporary files: %d%%.\r", (int)(((float)write / total) * 100.0));
617 } 617 }
618   618  
619 // Switch to the next temporary file. 619 // Switch to the next temporary file.
620 if(++lines >= tmpLines) { 620 if(++lines >= tmpLines) {
621 // If there are no temporary files left then run till the end. 621 // If there are no temporary files left then run till the end.
622 if(files - 1 < 0) { 622 if(files - 1 < 0) {
623 free(line->string); 623 free(line->string);
624 free(line); 624 free(line);
625 line = NULL; 625 line = NULL;
626 continue; 626 continue;
627 } 627 }
628   628  
629 // Close the previous temporary file and write to the next temporary file. 629 // Close the previous temporary file and write to the next temporary file.
630 #if defined ___AsyncIO___ 630 #if defined ___AsyncIO___
631 CloseAsync(tp); 631 CloseAsync(tp);
632 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) { 632 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) {
633 #else 633 #else
634 fclose(tp); 634 fclose(tp);
635 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) { 635 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) {
636 #endif 636 #endif
637 fprintf(stderr, "Could not open '%s' for writing.\n", (char *)tmpNames->array[files]); 637 fprintf(stderr, "Could not open '%s' for writing.\n", (char *)tmpNames->array[files]);
638 #if defined ___AsyncIO___ 638 #if defined ___AsyncIO___
639 CloseAsync(fp); 639 CloseAsync(fp);
640 #else 640 #else
641 fclose(fp); 641 fclose(fp);
642 #endif 642 #endif
643 free(line->string); 643 free(line->string);
644 free(line); 644 free(line);
645 line = NULL; 645 line = NULL;
646 return; 646 return;
647 } 647 }
648 lines = 0; 648 lines = 0;
649 } 649 }
650   650  
651 free(line->string); 651 free(line->string);
652 free(line); 652 free(line);
653 line = NULL; 653 line = NULL;
654 } 654 }
655   655  
656 if(line != NULL) { 656 if(line != NULL) {
657 free(line->string); 657 free(line->string);
658 free(line); 658 free(line);
659 line = NULL; 659 line = NULL;
660 } 660 }
661   661  
662 if(PROGRAM_VERBOSE) { 662 if(PROGRAM_VERBOSE) {
663 fprintf(stdout, "\n"); 663 fprintf(stdout, "\n");
664 } 664 }
665   665  
666 #if defined ___AsyncIO___ 666 #if defined ___AsyncIO___
667 CloseAsync(tp); 667 CloseAsync(tp);
668 CloseAsync(fp); 668 CloseAsync(fp);
669 #else 669 #else
670 fclose(tp); 670 fclose(tp);
671 fclose(fp); 671 fclose(fp);
672 #endif 672 #endif
673 } 673 }
674   674  
675 /* 675 /*
676 * 676 *
677 * Merges temporary files "tmpNames" into a database "dbFile". 677 * Merges temporary files "tmpNames" into a database "dbFile".
678 */ 678 */
679 void MergeTemporaryFiles(char *dbFile, VECTOR *tmpNames, int lines) { 679 void MergeTemporaryFiles(char *dbFile, VECTOR *tmpNames, int lines) {
680 #if defined ___AsyncIO___ 680 #if defined ___AsyncIO___
681 struct AsyncFile *fp; 681 struct AsyncFile *fp;
682 struct AsyncFile **tp; 682 struct AsyncFile **tp;
683 #else 683 #else
684 FILE *fp; 684 FILE *fp;
685 FILE **tp; 685 FILE **tp;
686 #endif 686 #endif
687 int i; 687 int i;
688 int j; 688 int j;
689 dbLine *tmp; 689 dbLine *tmp;
690 char *rem; 690 char *rem;
691 char *min; 691 char *min;
692 int count; 692 int count;
693   693  
694 #if defined ___AsyncIO___ 694 #if defined ___AsyncIO___
695 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) { 695 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
696 #else 696 #else
697 if((fp = fopen(dbFile, "w")) == NULL) { 697 if((fp = fopen(dbFile, "w")) == NULL) {
698 #endif 698 #endif
699 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile); 699 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
700 return; 700 return;
701 } 701 }
702   702  
703 // Allocate as many file pointers as temporary files. 703 // Allocate as many file pointers as temporary files.
704 if((tp = malloc(tmpNames->length * sizeof(*tp))) == NULL) { 704 if((tp = malloc(tmpNames->length * sizeof(*tp))) == NULL) {
705 fprintf(stderr, "Memory allocation failure.\n"); 705 fprintf(stderr, "Memory allocation failure.\n");
706 #if defined ___AsyncIO___ 706 #if defined ___AsyncIO___
707 CloseAsync(fp); 707 CloseAsync(fp);
708 #else 708 #else
709 fclose(fp); 709 fclose(fp);
710 #endif 710 #endif
711 return; 711 return;
712 } 712 }
713   713  
714 // Open all temporary files for reading. 714 // Open all temporary files for reading.
715 for(i = 0; i < tmpNames->length; ++i) { 715 for(i = 0; i < tmpNames->length; ++i) {
716 #if defined ___AsyncIO___ 716 #if defined ___AsyncIO___
717 if((tp[i] = OpenAsync(tmpNames->array[i], MODE_READ, ASYNC_BUF)) == NULL) { 717 if((tp[i] = OpenAsync(tmpNames->array[i], MODE_READ, ASYNC_BUF)) == NULL) {
718 #else 718 #else
719 if((tp[i] = fopen(tmpNames->array[i], "r")) == NULL) { 719 if((tp[i] = fopen(tmpNames->array[i], "r")) == NULL) {
720 #endif 720 #endif
721 fprintf(stderr, "Could not open file '%s' for reading.\n", (char *)tmpNames->array[i]); 721 fprintf(stderr, "Could not open file '%s' for reading.\n", (char *)tmpNames->array[i]);
722 // Close all temporary files. 722 // Close all temporary files.
723 while(--i > -1) { 723 while(--i > -1) {
724 #if defined ___AsyncIO___ 724 #if defined ___AsyncIO___
725 CloseAsync(tp[i]); 725 CloseAsync(tp[i]);
726 #else 726 #else
727 fclose(tp[i]); 727 fclose(tp[i]);
728 #endif 728 #endif
729 } 729 }
730 #if defined ___AsyncIO___ 730 #if defined ___AsyncIO___
731 CloseAsync(fp); 731 CloseAsync(fp);
732 #else 732 #else
733 fclose(fp); 733 fclose(fp);
734 #endif 734 #endif
735 return; 735 return;
736 } 736 }
737 } 737 }
738   738  
739 if(PROGRAM_VERBOSE) { 739 if(PROGRAM_VERBOSE) {
740 fprintf(stdout, "Merging all files...\r"); 740 fprintf(stdout, "Merging all files...\r");
741 } 741 }
742   742  
743 rem = NULL; 743 rem = NULL;
744 count = lines; 744 count = lines;
745 j = 0; 745 j = 0;
746 while(PROGRAM_RUN && --count > -1) { 746 while(PROGRAM_RUN && --count > -1) {
747 #if defined ___AmigaOS___ 747 #if defined ___AmigaOS___
748 // Check if CTRL+C was pressed and abort the program. 748 // Check if CTRL+C was pressed and abort the program.
749 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 749 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
750 PROGRAM_RUN = FALSE; 750 PROGRAM_RUN = FALSE;
751 continue; 751 continue;
752 } 752 }
753 #endif 753 #endif
754 // Find the smallest line in all temporary files. 754 // Find the smallest line in all temporary files.
755 if(PROGRAM_VERBOSE) { 755 if(PROGRAM_VERBOSE) {
756 fprintf(stdout, "Merging all files: %d%%.\r", 100 - (int)(((float)count / lines) * 100.0)); 756 fprintf(stdout, "Merging all files: %d%%.\r", 100 - (int)(((float)count / lines) * 100.0));
757 } 757 }
758   758  
759 min = NULL; 759 min = NULL;
760 for(i = 0; i < tmpNames->length; ++i) { 760 for(i = 0; i < tmpNames->length; ++i) {
761 tmp = PeekLine(tp[i]); 761 tmp = PeekLine(tp[i]);
762 if(tmp == NULL) { 762 if(tmp == NULL) {
763 continue; 763 continue;
764 } 764 }
765 #if defined ___AmigaOS___ 765 #if defined ___AmigaOS___
766 if(min == NULL || StrnCmp(locale, tmp->string, min, -1, SC_ASCII) < 0) { 766 if(min == NULL || StrnCmp(locale, tmp->string, min, -1, SC_ASCII) < 0) {
767 #else 767 #else
768 if(min == NULL || strcmp(tmp->string, min) < 0) { 768 if(min == NULL || strcmp(tmp->string, min) < 0) {
769 #endif 769 #endif
770 if(min != NULL) { 770 if(min != NULL) {
771 // Free previous instance. 771 // Free previous instance.
772 free(min); 772 free(min);
773 min = NULL; 773 min = NULL;
774 } 774 }
775 if((min = malloc((strlen(tmp->string) + 1) * sizeof(*min))) == NULL) { 775 if((min = malloc((strlen(tmp->string) + 1) * sizeof(*min))) == NULL) {
776 fprintf(stderr, "Memory allocation failure.\n"); 776 fprintf(stderr, "Memory allocation failure.\n");
777   777  
778 free(tmp->string); 778 free(tmp->string);
779 free(tmp); 779 free(tmp);
780 tmp = NULL; 780 tmp = NULL;
781   781  
782 if(min != NULL) { 782 if(min != NULL) {
783 free(min); 783 free(min);
784 min = NULL; 784 min = NULL;
785 } 785 }
786 if(rem != NULL) { 786 if(rem != NULL) {
787 free(rem); 787 free(rem);
788 rem = NULL; 788 rem = NULL;
789 } 789 }
790 #if defined ___AsyncIO___ 790 #if defined ___AsyncIO___
791 CloseAsync(fp); 791 CloseAsync(fp);
792 #else 792 #else
793 fclose(fp); 793 fclose(fp);
794 #endif 794 #endif
795 return; 795 return;
796 } 796 }
797 sprintf(min, "%s", tmp->string); 797 sprintf(min, "%s", tmp->string);
798 // Remember the index of the file where the smallest entry has been found. 798 // Remember the index of the file where the smallest entry has been found.
799 j = i; 799 j = i;
800 } 800 }
801 free(tmp->string); 801 free(tmp->string);
802 free(tmp); 802 free(tmp);
803 tmp = NULL; 803 tmp = NULL;
804 } 804 }
805   805  
806 // Forward the file where the smallest line was found. 806 // Forward the file where the smallest line was found.
807 SkipLine(tp[j]); 807 SkipLine(tp[j]);
808   808  
809 // Write the smallest line. 809 // Write the smallest line.
810 if(min != NULL) { 810 if(min != NULL) {
811 // If current minimum line is identical to previous minimum line then skip to remove duplicates. 811 // If current minimum line is identical to previous minimum line then skip to remove duplicates.
812 if(rem != NULL) { 812 if(rem != NULL) {
813 #if defined ___AmigaOS___ 813 #if defined ___AmigaOS___
814 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) { 814 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) {
815 #else 815 #else
816 if(strcmp(min, rem) == 0) { 816 if(strcmp(min, rem) == 0) {
817 #endif 817 #endif
818 free(min); 818 free(min);
819 min = NULL; 819 min = NULL;
820 continue; 820 continue;
821 } 821 }
822 } 822 }
823   823  
824 #if defined ___AsyncIO___ 824 #if defined ___AsyncIO___
825 WriteAsync(fp, min, (LONG)strlen(min)); 825 WriteAsync(fp, min, (LONG)strlen(min));
826 WriteAsync(fp, "\n", 1); 826 WriteAsync(fp, "\n", 1);
827 #else 827 #else
828 fprintf(fp, "%s\n", min); 828 fprintf(fp, "%s\n", min);
829 #endif 829 #endif
830   830  
831 if(rem != NULL) { 831 if(rem != NULL) {
832 free(rem); 832 free(rem);
833 rem = NULL; 833 rem = NULL;
834 } 834 }
835   835  
836 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) { 836 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) {
837 fprintf(stderr, "Memory allocation failure.\n"); 837 fprintf(stderr, "Memory allocation failure.\n");
838   838  
839 free(min); 839 free(min);
840 min = NULL; 840 min = NULL;
841   841  
842 #if defined ___AsyncIO___ 842 #if defined ___AsyncIO___
843 CloseAsync(fp); 843 CloseAsync(fp);
844 #else 844 #else
845 fclose(fp); 845 fclose(fp);
846 #endif 846 #endif
847 return; 847 return;
848 } 848 }
849   849  
850 // Remember the last minimal line. 850 // Remember the last minimal line.
851 sprintf(rem, "%s", min); 851 sprintf(rem, "%s", min);
852   852  
853 free(min); 853 free(min);
854 min = NULL; 854 min = NULL;
855 } 855 }
856 } 856 }
857   857  
858 if(rem != NULL) { 858 if(rem != NULL) {
859 free(rem); 859 free(rem);
860 rem = NULL; 860 rem = NULL;
861 } 861 }
862   862  
863 // Write out any remaining contents from the temporary files. 863 // Write out any remaining contents from the temporary files.
864 for(i = 0; PROGRAM_RUN && i < tmpNames->length; ++i) { 864 for(i = 0; PROGRAM_RUN && i < tmpNames->length; ++i) {
865 #if defined ___AmigaOS___ 865 #if defined ___AmigaOS___
866 // Check if CTRL+C was pressed and abort the program. 866 // Check if CTRL+C was pressed and abort the program.
867 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 867 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
868 PROGRAM_RUN = FALSE; 868 PROGRAM_RUN = FALSE;
869 continue; 869 continue;
870 } 870 }
871 #endif 871 #endif
872 tmp = ReadLine(tp[i]); 872 tmp = ReadLine(tp[i]);
873 if(tmp == NULL) { 873 if(tmp == NULL) {
874 continue; 874 continue;
875 } 875 }
876 #if defined ___AsyncIO___ 876 #if defined ___AsyncIO___
877 WriteAsync(fp, tmp->string, (LONG)strlen(tmp->string)); 877 WriteAsync(fp, tmp->string, (LONG)strlen(tmp->string));
878 WriteAsync(fp, "\n", 1); 878 WriteAsync(fp, "\n", 1);
879 #else 879 #else
880 fprintf(fp, "%s\n", tmp->string); 880 fprintf(fp, "%s\n", tmp->string);
881 #endif 881 #endif
882 free(tmp->string); 882 free(tmp->string);
883 free(tmp); 883 free(tmp);
884 tmp = NULL; 884 tmp = NULL;
885 } 885 }
886   886  
887 // Close all temporary files. 887 // Close all temporary files.
888 for(i = 0; i < tmpNames->length; ++i) { 888 for(i = 0; i < tmpNames->length; ++i) {
889 #if defined ___AsyncIO___ 889 #if defined ___AsyncIO___
890 CloseAsync(tp[i]); 890 CloseAsync(tp[i]);
891 #else 891 #else
892 fclose(tp[i]); 892 fclose(tp[i]);
893 #endif 893 #endif
894 } 894 }
895   895  
896 #if defined ___AsyncIO___ 896 #if defined ___AsyncIO___
897 CloseAsync(fp); 897 CloseAsync(fp);
898 #else 898 #else
899 fclose(fp); 899 fclose(fp);
900 #endif 900 #endif
901   901  
902 if(PROGRAM_VERBOSE) { 902 if(PROGRAM_VERBOSE) {
903 fprintf(stdout, "\n"); 903 fprintf(stdout, "\n");
904 } 904 }
905 } 905 }
906   906  
907 /* 907 /*
908 * 908 *
909 * Filter the paths inside the database with provided paths. 909 * Filter the paths inside the database with provided paths.
910 */ 910 */
911 void FilterDatabasePaths(char *dbFile, char *tmpName, VECTOR *paths) { 911 void FilterDatabasePaths(char *dbFile, char *tmpName, VECTOR *paths) {
912 #if defined ___AsyncIO___ 912 #if defined ___AsyncIO___
913 struct AsyncFile *fp; 913 struct AsyncFile *fp;
914 struct AsyncFile *tp; 914 struct AsyncFile *tp;
915 #else 915 #else
916 FILE *fp; 916 FILE *fp;
917 FILE *tp; 917 FILE *tp;
918 #endif 918 #endif
919 dbLine *line; 919 dbLine *line;
920 dbEntry *entry; 920 dbEntry *entry;
921 int lines; 921 int lines;
922 int i; 922 int i;
923   923  
924 // Open database file for reading. 924 // Open database file for reading.
925 #if defined ___AsyncIO___ 925 #if defined ___AsyncIO___
926 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 926 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
927 #else 927 #else
928 if((fp = fopen(dbFile, "r")) == NULL) { 928 if((fp = fopen(dbFile, "r")) == NULL) {
929 #endif 929 #endif
930 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile); 930 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
931 return; 931 return;
932 } 932 }
933   933  
934 // Open temporary file for writing. 934 // Open temporary file for writing.
935 #if defined ___AsyncIO___ 935 #if defined ___AsyncIO___
936 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) { 936 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) {
937 #else 937 #else
938 if((tp = fopen(tmpName, "w")) == NULL) { 938 if((tp = fopen(tmpName, "w")) == NULL) {
939 #endif 939 #endif
940 fprintf(stderr, "Copuld not open file '%s' for writing.\n", tmpName); 940 fprintf(stderr, "Could not open file '%s' for writing.\n", tmpName);
941   941  
942 // Close database file. 942 // Close database file.
943 #if defined ___AsyncIO___ 943 #if defined ___AsyncIO___
944 CloseAsync(fp); 944 CloseAsync(fp);
945 #else 945 #else
946 fclose(fp); 946 fclose(fp);
947 #endif 947 #endif
948   948  
949 return; 949 return;
950 } 950 }
951   951  
952 if(PROGRAM_VERBOSE) { 952 if(PROGRAM_VERBOSE) {
953 fprintf(stdout, "Removing lines...\r"); 953 fprintf(stdout, "Removing lines...\r");
954 } 954 }
955   955  
956 lines = 0; 956 lines = 0;
957 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) { 957 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
958 #if defined ___AmigaOS___ 958 #if defined ___AmigaOS___
959 // Check if CTRL+C was pressed and abort the program. 959 // Check if CTRL+C was pressed and abort the program.
960 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 960 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
961 PROGRAM_RUN = FALSE; 961 PROGRAM_RUN = FALSE;
962 continue; 962 continue;
963 } 963 }
964 #endif 964 #endif
965   965  
966 if((entry = CreateDatabaseEntry(line)) == NULL) { 966 if((entry = CreateDatabaseEntry(line)) == NULL) {
967 fprintf(stderr, "Unable to create database entry.\n"); 967 fprintf(stderr, "Unable to create database entry.\n");
968 free(line->string); 968 free(line->string);
969 free(line); 969 free(line);
970 line = NULL; 970 line = NULL;
971 continue; 971 continue;
972 } 972 }
973   973  
974 for(i = 0; i < paths->length; ++i) { 974 for(i = 0; i < paths->length; ++i) {
975 if(PathCompare(entry->path, paths->array[i]) == TRUE) { 975 if(PathCompare(entry->path, paths->array[i]) == TRUE) {
976 ++lines; 976 ++lines;
977 if(PROGRAM_VERBOSE) { 977 if(PROGRAM_VERBOSE) {
978 fprintf(stdout, "Removing lines: %d.\r", lines); 978 fprintf(stdout, "Removing lines: %d.\r", lines);
979 } 979 }
980 continue; 980 continue;
981 } 981 }
982 #if defined ___AsyncIO___ 982 #if defined ___AsyncIO___
983 WriteAsync(tp, line->string, (LONG)strlen(line->string)); 983 WriteAsync(tp, line->string, (LONG)strlen(line->string));
984 WriteAsync(tp, "\n", 1); 984 WriteAsync(tp, "\n", 1);
985 #else 985 #else
986 fprintf(tp, "%s\n", line->string); 986 fprintf(tp, "%s\n", line->string);
987 #endif 987 #endif
988 break; 988 break;
989 } 989 }
990   990  
991 // Free up database entry. 991 // Free up database entry.
992 free(entry->name); 992 free(entry->name);
993 free(entry->path); 993 free(entry->path);
994 free(entry); 994 free(entry);
995 entry = NULL; 995 entry = NULL;
996   996  
997 // Free up line. 997 // Free up line.
998 free(line->string); 998 free(line->string);
999 free(line); 999 free(line);
1000 line = NULL; 1000 line = NULL;
1001 } 1001 }
1002   1002  
1003 #if defined ___AsyncIO___ 1003 #if defined ___AsyncIO___
1004 CloseAsync(fp); 1004 CloseAsync(fp);
1005 CloseAsync(tp); 1005 CloseAsync(tp);
1006 #else 1006 #else
1007 fclose(fp); 1007 fclose(fp);
1008 fclose(tp); 1008 fclose(tp);
1009 #endif 1009 #endif
1010   1010  
1011 if(PROGRAM_VERBOSE) { 1011 if(PROGRAM_VERBOSE) {
1012 fprintf(stdout, "\n"); 1012 fprintf(stdout, "\n");
1013 } 1013 }
1014 } 1014 }
1015   1015  
1016 /* 1016 /*
1017 * 1017 *
1018 * Indexes paths and adds to a database file. 1018 * Indexes paths and adds to a database file.
1019 */ 1019 */
1020 void GatherDatabaseFiles(char *dbFile, VECTOR *paths) { 1020 void GatherDatabaseFiles(char *dbFile, VECTOR *paths) {
1021 dbStats *stats; 1021 dbStats *stats;
1022 VECTOR *tmpNames; 1022 VECTOR *tmpNames;
1023 int tmpFiles; 1023 int tmpFiles;
1024 int tmpLines; 1024 int tmpLines;
1025 int i; 1025 int i;
1026 int line; 1026 int line;
1027 int size; 1027 int size;
1028   1028  
1029 // Generate the database file from the supplied paths. 1029 // Generate the database file from the supplied paths.
1030 if((stats = CollectFiles(dbFile, paths)) == NULL) { 1030 if((stats = CollectFiles(dbFile, paths)) == NULL) {
1031 fprintf(stderr, "Collecting files failed.\n"); 1031 fprintf(stderr, "Collecting files failed.\n");
1032 return; 1032 return;
1033 } 1033 }
1034   1034  
1035 // The size and amount of lines are not necessarily what has been gathered now. 1035 // The size and amount of lines are not necessarily what has been gathered now.
1036 size = GetFileSize(dbFile); 1036 size = GetFileSize(dbFile);
1037 line = CountFileLines(dbFile); 1037 line = CountFileLines(dbFile);
1038   1038  
1039 // Calculate the total number of temporary files required. 1039 // Calculate the total number of temporary files required.
1040 tmpFiles = size / maxmem; 1040 tmpFiles = size / maxmem;
1041   1041  
1042 /* In case no temporary files are required, 1042 /* In case no temporary files are required,
1043 * just sort the database and terminate. 1043 * just sort the database and terminate.
1044 */ 1044 */
1045 if(tmpFiles < 2) { 1045 if(tmpFiles < 2) {
1046 SortDatabase(dbFile, line); 1046 SortDatabase(dbFile, line);
1047 return; 1047 return;
1048 } 1048 }
1049   1049  
1050 // Calculate the number of lines per temporary file. 1050 // Calculate the number of lines per temporary file.
1051 tmpLines = ceil(((double)line) / ((double)tmpFiles)); 1051 tmpLines = ceil(((double)line) / ((double)tmpFiles));
1052   1052  
1053 // Create temporary files. 1053 // Create temporary files.
1054 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) { 1054 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
1055 fprintf(stderr, "Unable to create temporary files.\n"); 1055 fprintf(stderr, "Unable to create temporary files.\n");
1056 return; 1056 return;
1057 } 1057 }
1058   1058  
1059 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile". 1059 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
1060 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, line); 1060 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, line);
1061   1061  
1062 // Sort the temporary files. 1062 // Sort the temporary files.
1063 for(i = 0; i < tmpNames->length; ++i) { 1063 for(i = 0; i < tmpNames->length; ++i) {
1064 SortDatabase(tmpNames->array[i], tmpLines); 1064 SortDatabase(tmpNames->array[i], tmpLines);
1065 } 1065 }
1066   1066  
1067 // Merge all the temporary files to the database file. 1067 // Merge all the temporary files to the database file.
1068 MergeTemporaryFiles(dbFile, tmpNames, line); 1068 MergeTemporaryFiles(dbFile, tmpNames, line);
1069   1069  
1070 // Remove all temporary files. 1070 // Remove all temporary files.
1071 RemoveFiles(tmpNames); 1071 RemoveFiles(tmpNames);
1072   1072  
1073 // Free temporary file names. 1073 // Free temporary file names.
1074 free(tmpNames); 1074 free(tmpNames);
1075 tmpNames = NULL; 1075 tmpNames = NULL;
1076   1076  
1077 // Free statistics. 1077 // Free statistics.
1078 free(stats); 1078 free(stats);
1079 stats = NULL; 1079 stats = NULL;
1080 } 1080 }
1081   1081  
1082 /* 1082 /*
1083 * 1083 *
1084 * Indexes paths and creates a daabase file. 1084 * Indexes paths and creates a daabase file.
1085 */ 1085 */
1086 void CreateDatabaseFiles(char *dbFile, VECTOR *paths) { 1086 void CreateDatabaseFiles(char *dbFile, VECTOR *paths) {
1087 dbStats *stats; 1087 dbStats *stats;
1088 VECTOR *tmpNames; 1088 VECTOR *tmpNames;
1089 int tmpFiles; 1089 int tmpFiles;
1090 int tmpLines; 1090 int tmpLines;
1091 int i; 1091 int i;
1092   1092  
1093 // Generate the database file from the supplied paths. 1093 // Generate the database file from the supplied paths.
1094 if((stats = CollectFiles(dbFile, paths)) == NULL) { 1094 if((stats = CollectFiles(dbFile, paths)) == NULL) {
1095 fprintf(stderr, "Collecting files failed.\n"); 1095 fprintf(stderr, "Collecting files failed.\n");
1096 return; 1096 return;
1097 } 1097 }
1098   1098  
1099 // Calculate the total number of temporary files required. 1099 // Calculate the total number of temporary files required.
1100 tmpFiles = stats->size / maxmem; 1100 tmpFiles = stats->size / maxmem;
1101   1101  
1102 /* In case no temporary files are required, 1102 /* In case no temporary files are required,
1103 * just sort the database and terminate. 1103 * just sort the database and terminate.
1104 */ 1104 */
1105 if(tmpFiles < 2) { 1105 if(tmpFiles < 2) {
1106 SortDatabase(dbFile, stats->lines); 1106 SortDatabase(dbFile, stats->lines);
1107 return; 1107 return;
1108 } 1108 }
1109   1109  
1110 // Calculate the number of lines per temporary file. 1110 // Calculate the number of lines per temporary file.
1111 tmpLines = ceil(((double)stats->lines) / ((double)tmpFiles)); 1111 tmpLines = ceil(((double)stats->lines) / ((double)tmpFiles));
1112   1112  
1113 // Create temporary files. 1113 // Create temporary files.
1114 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) { 1114 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
1115 fprintf(stderr, "Unable to create temporary files.\n"); 1115 fprintf(stderr, "Unable to create temporary files.\n");
1116 return; 1116 return;
1117 } 1117 }
1118   1118  
1119 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile". 1119 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
1120 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, stats->lines); 1120 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, stats->lines);
1121   1121  
1122 // Sort the temporary files. 1122 // Sort the temporary files.
1123 for(i = 0; i < tmpNames->length; ++i) { 1123 for(i = 0; i < tmpNames->length; ++i) {
1124 SortDatabase(tmpNames->array[i], tmpLines); 1124 SortDatabase(tmpNames->array[i], tmpLines);
1125 } 1125 }
1126   1126  
1127 // Merge all the temporary files to the database file. 1127 // Merge all the temporary files to the database file.
1128 MergeTemporaryFiles(dbFile, tmpNames, stats->lines); 1128 MergeTemporaryFiles(dbFile, tmpNames, stats->lines);
1129   1129  
1130 // Remove all temporary files. 1130 // Remove all temporary files.
1131 RemoveFiles(tmpNames); 1131 RemoveFiles(tmpNames);
1132   1132  
1133 // Free temporary file names. 1133 // Free temporary file names.
1134 free(tmpNames); 1134 free(tmpNames);
1135 tmpNames = NULL; 1135 tmpNames = NULL;
1136   1136  
1137 // Free statistics. 1137 // Free statistics.
1138 free(stats); 1138 free(stats);
1139 stats = NULL; 1139 stats = NULL;
1140 } 1140 }
1141   1141  
1142 void RemoveDatabaseFiles(char *dbFile, VECTOR *paths) { 1142 void RemoveDatabaseFiles(char *dbFile, VECTOR *paths) {
1143 char *tmpName; 1143 char *tmpName;
1144   1144  
1145 // Create a temporary file to hold the changes. 1145 // Create a temporary file to hold the changes.
1146 if((tmpName = CreateTemporaryFile()) == NULL) { 1146 if((tmpName = CreateTemporaryFile()) == NULL) {
1147 fprintf(stderr, "Unable to create temporary file.\n"); 1147 fprintf(stderr, "Unable to create temporary file.\n");
1148 return; 1148 return;
1149 } 1149 }
1150   1150  
1151 // Filter the database of the provided paths. 1151 // Filter the database of the provided paths.
1152 FilterDatabasePaths(dbFile, tmpName, paths); 1152 FilterDatabasePaths(dbFile, tmpName, paths);
1153   1153  
1154 // Overwrite the database file with the filtered paths. 1154 // Overwrite the database file with the filtered paths.
1155 CopyLines(tmpName, dbFile); 1155 CopyLines(tmpName, dbFile);
1156   1156  
1157 // Remove temporary file. 1157 // Remove temporary file.
1158 if(RemoveFile(tmpName) == FALSE) { 1158 if(RemoveFile(tmpName) == FALSE) {
1159 fprintf(stderr, "Temporary file could not be removed.\n"); 1159 fprintf(stderr, "Temporary file could not be removed.\n");
1160 return; 1160 return;
1161 } 1161 }
1162 } 1162 }
1163   1163  
1164 void usage(char *name) { 1164 void usage(char *name) {
1165 fprintf(stdout, "Hunt & Gather - %s, a file index generating tool. \n", name); 1165 fprintf(stdout, "Hunt & Gather - %s, a file index generating tool. \n", name);
1166 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION); 1166 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION);
1167 fprintf(stdout, " \n"); 1167 fprintf(stdout, " \n");
1168 fprintf(stdout, "SYNTAX: %s [-q] <-a|-r|-c> <PATH PATH PATH...> \n", name); 1168 fprintf(stdout, "SYNTAX: %s [-q] <-a|-r|-c> <PATH PATH PATH...> \n", name);
1169 fprintf(stdout, " \n"); 1169 fprintf(stdout, " \n");
1170 fprintf(stdout, "Required: \n"); 1170 fprintf(stdout, "Required: \n");
1171 fprintf(stdout, " -a [PATH...] Add files. \n"); 1171 fprintf(stdout, " -a [PATH...] Add files. \n");
1172 fprintf(stdout, " -c [PATH...] Create from scratch. \n"); 1172 fprintf(stdout, " -c [PATH...] Create from scratch. \n");
1173 fprintf(stdout, " -r [PATH...] Remove files. \n"); 1173 fprintf(stdout, " -r [PATH...] Remove files. \n");
1174 fprintf(stdout, " \n"); 1174 fprintf(stdout, " \n");
1175 fprintf(stdout, "Optional: \n"); 1175 fprintf(stdout, "Optional: \n");
1176 fprintf(stdout, " -d [FIILE] Where to store the database. \n"); 1176 fprintf(stdout, " -d [FIILE] Where to store the database. \n");
1177 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem); 1177 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem);
1178 fprintf(stdout, " -q Do not print out any messages. \n"); 1178 fprintf(stdout, " -q Do not print out any messages. \n");
1179 fprintf(stdout, " \n"); 1179 fprintf(stdout, " \n");
1180 fprintf(stdout, "DATABASE is a path to where the indexed results will be \n"); 1180 fprintf(stdout, "DATABASE is a path to where the indexed results will be \n");
1181 fprintf(stdout, "stored for searching with the Hunt tool. \n"); 1181 fprintf(stdout, "stored for searching with the Hunt tool. \n");
1182 fprintf(stdout, " \n"); 1182 fprintf(stdout, " \n");
1183 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n"); 1183 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n");
1184 } 1184 }
1185   1185  
1186 /* 1186 /*
1187 * 1187 *
1188 * Main entry point. 1188 * Main entry point.
1189 */ 1189 */
1190 int main(int argc, char **argv) { 1190 int main(int argc, char **argv) {
1191 int option; 1191 int option;
1192 int i; 1192 int i;
1193 char *dbFile; 1193 char *dbFile;
1194 char *path; 1194 char *path;
1195 VECTOR *paths; 1195 VECTOR *paths;
1196 OPERATION operation = NONE; 1196 OPERATION operation = NONE;
1197   1197  
1198 // Bind handler to SIGINT. 1198 // Bind handler to SIGINT.
1199 #if !defined ___AmigaOS___ 1199 #if !defined ___AmigaOS___
1200 signal(SIGINT, SignalHandler); 1200 signal(SIGINT, SignalHandler);
1201 #endif 1201 #endif
1202   1202  
1203 dbFile = DEFAULT_DATABASE_FILE; 1203 dbFile = DEFAULT_DATABASE_FILE;
1204 while((option = getopt(argc, argv, "hqdm:arc")) != -1) { 1204 while((option = getopt(argc, argv, "hqdm:arc")) != -1) {
1205 switch(option) { 1205 switch(option) {
1206 case 'a': 1206 case 'a':
1207 operation = GATHER; 1207 operation = GATHER;
1208 break; 1208 break;
1209 case 'r': 1209 case 'r':
1210 operation = REMOVE; 1210 operation = REMOVE;
1211 break; 1211 break;
1212 case 'c': 1212 case 'c':
1213 operation = CREATE; 1213 operation = CREATE;
1214 break; 1214 break;
1215 case 'm': 1215 case 'm':
1216 maxmem = strtoul(optarg, NULL, 10); 1216 maxmem = strtoul(optarg, NULL, 10);
1217 break; 1217 break;
1218 case 'd': 1218 case 'd':
1219 dbFile = optarg; 1219 dbFile = optarg;
1220 break; 1220 break;
1221 case 'q': 1221 case 'q':
1222 PROGRAM_VERBOSE = FALSE; 1222 PROGRAM_VERBOSE = FALSE;
1223 break; 1223 break;
1224 case 'h': 1224 case 'h':
1225 usage(argv[0]); 1225 usage(argv[0]);
1226 return 0; 1226 return 0;
1227 case '?': 1227 case '?':
1228 fprintf(stderr, "Invalid option %ct.\n", optopt); 1228 fprintf(stderr, "Invalid option %ct.\n", optopt);
1229 return 5; 1229 return 5;
1230 } 1230 }
1231 } 1231 }
1232   1232  
1233 if(operation == NONE) { 1233 if(operation == NONE) {
1234 usage(argv[0]); 1234 usage(argv[0]);
1235 return 5; 1235 return 5;
1236 } 1236 }
1237   1237  
1238 if(optind >= argc) { 1238 if(optind >= argc) {
1239 usage(argv[0]); 1239 usage(argv[0]);
1240 return 5; 1240 return 5;
1241 } 1241 }
1242   1242  
1243 // Build the path vector. 1243 // Build the path vector.
1244 if((paths = malloc(1 * sizeof(*paths))) == NULL) { 1244 if((paths = malloc(1 * sizeof(*paths))) == NULL) {
1245 fprintf(stderr, "Memory allocation failure.\n"); 1245 fprintf(stderr, "Memory allocation failure.\n");
1246 return 20; 1246 return 20;
1247 } 1247 }
1248   1248  
1249 // Go through all supplied arguments and add paths to search. 1249 // Go through all supplied arguments and add paths to search.
1250 if((paths->array = malloc((argc - optind) * sizeof(*paths))) == NULL) { 1250 if((paths->array = malloc((argc - optind) * sizeof(*paths))) == NULL) {
1251 fprintf(stderr, "Memory allocation failure.\n"); 1251 fprintf(stderr, "Memory allocation failure.\n");
1252 return 20; 1252 return 20;
1253 } 1253 }
1254   1254  
1255 for(i = optind, paths->length = 0; i < argc; ++i) { 1255 for(i = optind, paths->length = 0; i < argc; ++i) {
1256 if((path = PathToAbsolute(argv[i])) == NULL) { 1256 if((path = PathToAbsolute(argv[i])) == NULL) {
1257 fprintf(stderr, "Absolute path for '%s' failed to resolve.\n", argv[optind]); 1257 fprintf(stderr, "Absolute path for '%s' failed to resolve.\n", argv[optind]);
1258 continue; 1258 continue;
1259 } 1259 }
1260   1260  
1261 switch(GetFsType(path)) { 1261 switch(GetFsType(path)) {
1262 case UNKNOWN: 1262 case UNKNOWN:
1263 case REGULAR: 1263 case REGULAR:
1264 fprintf(stderr, "Path '%s' is not a directory.\n", path); 1264 fprintf(stderr, "Path '%s' is not a directory.\n", path);
1265 free(path); 1265 free(path);
1266 path = NULL; 1266 path = NULL;
1267 continue; 1267 continue;
1268 case DIRECTORY: 1268 case DIRECTORY:
1269 break; 1269 break;
1270 } 1270 }
1271   1271  
1272 if(PROGRAM_VERBOSE) { 1272 if(PROGRAM_VERBOSE) {
1273 fprintf(stdout, "Will process path: '%s'\n", path); 1273 fprintf(stdout, "Will process path: '%s'\n", path);
1274 } 1274 }
1275   1275  
1276 // Add the path to the array of paths. 1276 // Add the path to the array of paths.
1277 if((paths->array[paths->length] = malloc((strlen(path) + 1) * sizeof(*paths->array[paths->length]))) == NULL) { 1277 if((paths->array[paths->length] = malloc((strlen(path) + 1) * sizeof(*paths->array[paths->length]))) == NULL) {
1278 fprintf(stderr, "Memory allocation failure."); 1278 fprintf(stderr, "Memory allocation failure.");
1279 return 20; 1279 return 20;
1280 } 1280 }
1281   1281  
1282 sprintf(paths->array[paths->length], "%s", path); 1282 sprintf(paths->array[paths->length], "%s", path);
1283 ++paths->length; 1283 ++paths->length;
1284   1284  
1285 free(path); 1285 free(path);
1286 path = NULL; 1286 path = NULL;
1287   1287  
1288 } 1288 }
1289   1289  
1290 if(paths->length == 0) { 1290 if(paths->length == 0) {
1291 fprintf(stderr, "No valid paths are available.\n"); 1291 fprintf(stderr, "No valid paths are available.\n");
1292 free(paths->array); 1292 free(paths->array);
1293 free(paths); 1293 free(paths);
1294 paths = NULL; 1294 paths = NULL;
1295 return 5; 1295 return 5;
1296 } 1296 }
1297   1297  
1298 if(PROGRAM_VERBOSE) { 1298 if(PROGRAM_VERBOSE) {
1299 fprintf(stdout, "Gathering to: '%s'\n", dbFile); 1299 fprintf(stdout, "Gathering to: '%s'\n", dbFile);
1300 } 1300 }
1301   1301  
1302 #if defined ___AmigaOS___ 1302 #if defined ___AmigaOS___
1303 locale = OpenLocale(NULL); 1303 locale = OpenLocale(NULL);
1304 #endif 1304 #endif
1305   1305  
1306 switch(operation) { 1306 switch(operation) {
1307 case CREATE: 1307 case CREATE:
1308 if(PROGRAM_VERBOSE) { 1308 if(PROGRAM_VERBOSE) {
1309 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile); 1309 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile);
1310 } 1310 }
1311 RemoveFile(dbFile); 1311 RemoveFile(dbFile);
1312 if(PROGRAM_VERBOSE) { 1312 if(PROGRAM_VERBOSE) {
1313 fprintf(stdout, "Gathering files to database...\n"); 1313 fprintf(stdout, "Gathering files to database...\n");
1314 } 1314 }
1315 CreateDatabaseFiles(dbFile, paths); 1315 CreateDatabaseFiles(dbFile, paths);
1316 break; 1316 break;
1317 case GATHER: 1317 case GATHER:
1318 if(PROGRAM_VERBOSE) { 1318 if(PROGRAM_VERBOSE) {
1319 fprintf(stdout, "Gathering files to database...\n"); 1319 fprintf(stdout, "Gathering files to database...\n");
1320 } 1320 }
1321 GatherDatabaseFiles(dbFile, paths); 1321 GatherDatabaseFiles(dbFile, paths);
1322 break; 1322 break;
1323 case REMOVE: 1323 case REMOVE:
1324 if(PROGRAM_VERBOSE) { 1324 if(PROGRAM_VERBOSE) {
1325 fprintf(stdout, "Removing files from database...\n"); 1325 fprintf(stdout, "Removing files from database...\n");
1326 } 1326 }
1327 RemoveDatabaseFiles(dbFile, paths); 1327 RemoveDatabaseFiles(dbFile, paths);
1328 break; 1328 break;
1329 default: 1329 default:
1330 fprintf(stderr, "Unknown operation.\n"); 1330 fprintf(stderr, "Unknown operation.\n");
1331 #if defined ___AmigaOS___ 1331 #if defined ___AmigaOS___
1332 CloseLocale(locale); 1332 CloseLocale(locale);
1333 #endif 1333 #endif
1334   1334  
1335 free(paths->array); 1335 free(paths->array);
1336 free(paths); 1336 free(paths);
1337 paths = NULL; 1337 paths = NULL;
1338 return 5; 1338 return 5;
1339 } 1339 }
1340   1340  
1341 #if defined ___AmigaOS___ 1341 #if defined ___AmigaOS___
1342 CloseLocale(locale); 1342 CloseLocale(locale);
1343 #endif 1343 #endif
1344   1344  
1345 if(paths != NULL) { 1345 if(paths != NULL) {
1346 free(paths->array); 1346 free(paths->array);
1347 free(paths); 1347 free(paths);
1348 paths = NULL; 1348 paths = NULL;
1349 } 1349 }
1350   1350  
1351 return 0; 1351 return 0;
1352 } 1352 }
1353   1353