HuntnGather – Diff between revs 46 and 47

Subversion Repositories:
Rev:
Only display areas with differencesRegard whitespace
Rev 46 Rev 47
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.6" 36 #define PROGRAM_VERSION "1.7.6"
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 fprintf(stdout, "Pushing '%s'\n", (char *)paths->array[i]); 323 fprintf(stdout, "Pushing path '%s'\n", (char *)paths->array[i]);
-   324 }
323 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));
324 } 326 }
325   327  
326 while(PROGRAM_RUN && !stackIsEmpty(stack)) { 328 while(PROGRAM_RUN && !stackIsEmpty(stack)) {
327 #if defined ___AmigaOS___ 329 #if defined ___AmigaOS___
328 // Check if CTRL+C was pressed and abort the program. 330 // Check if CTRL+C was pressed and abort the program.
329 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 331 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
330 PROGRAM_RUN = FALSE; 332 PROGRAM_RUN = FALSE;
331 continue; 333 continue;
332 } 334 }
333 #endif 335 #endif
334 if((path = (char *)stackPop(stack)) == NULL) { 336 if((path = (char *)stackPop(stack)) == NULL) {
335 break; 337 break;
336 } 338 }
337   339  
338 #if defined ___AmigaOS___ 340 #if defined ___AmigaOS___
339 if((lock = Lock(path, ACCESS_READ)) == NULL) { 341 if((lock = Lock(path, ACCESS_READ)) == NULL) {
340 fprintf(stderr, "Could not lock path '%s' for reading.\n", path); 342 fprintf(stderr, "Could not lock path '%s' for reading.\n", path);
341 free(path); 343 free(path);
342 path = NULL; 344 path = NULL;
343 continue; 345 continue;
344 } 346 }
345   347  
346 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) { 348 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
347 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);
348 UnLock(lock); 350 UnLock(lock);
349 free(path); 351 free(path);
350 path = NULL; 352 path = NULL;
351 continue; 353 continue;
352 } 354 }
353   355  
354 if(Examine(lock, FIB) == FALSE) { 356 if(Examine(lock, FIB) == FALSE) {
355 fprintf(stderr, "Path '%s' could not be examined.\n", path); 357 fprintf(stderr, "Path '%s' could not be examined.\n", path);
356 FreeDosObject(DOS_FIB, FIB); 358 FreeDosObject(DOS_FIB, FIB);
357 FIB = NULL; 359 FIB = NULL;
358 UnLock(lock); 360 UnLock(lock);
359 free(path); 361 free(path);
360 path = NULL; 362 path = NULL;
361 continue; 363 continue;
362 } 364 }
363   365  
364 while(PROGRAM_RUN && ExNext(lock, FIB)) { 366 while(PROGRAM_RUN && ExNext(lock, FIB)) {
365 // Check if CTRL+C was pressed and abort the program. 367 // Check if CTRL+C was pressed and abort the program.
366 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 368 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
367 PROGRAM_RUN = FALSE; 369 PROGRAM_RUN = FALSE;
368 continue; 370 continue;
369 } 371 }
370 #else 372 #else
371   373  
372 if((dir = opendir(path)) == NULL) { 374 if((dir = opendir(path)) == NULL) {
373 fprintf(stderr, "Directory '%s' could not be opened.\n", path); 375 fprintf(stderr, "Directory '%s' could not be opened.\n", path);
374 free(path); 376 free(path);
375 path = NULL; 377 path = NULL;
376 continue; 378 continue;
377 } 379 }
378   380  
379 while(PROGRAM_RUN && (entry = readdir(dir)) != NULL) { 381 while(PROGRAM_RUN && (entry = readdir(dir)) != NULL) {
380 #endif 382 #endif
381 switch(path[strlen(path) - 1]) { 383 switch(path[strlen(path) - 1]) {
382 case '/': 384 case '/':
383 case ':': // This is a drive path. 385 case ':': // This is a drive path.
384 #if defined ___AmigaOS___ 386 #if defined ___AmigaOS___
385 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1)) == NULL) { 387 if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1)) == NULL) {
386 #else 388 #else
387 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) { 389 if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) {
388 #endif 390 #endif
389 fprintf(stderr, "Memory allocation failure.\n"); 391 fprintf(stderr, "Memory allocation failure.\n");
390 #if defined ___AmigaOS___ 392 #if defined ___AmigaOS___
391 FreeDosObject(DOS_FIB, FIB); 393 FreeDosObject(DOS_FIB, FIB);
392 FIB = NULL; 394 FIB = NULL;
393 UnLock(lock); 395 UnLock(lock);
394 #else 396 #else
395 closedir(dir); 397 closedir(dir);
396 #endif 398 #endif
397 free(path); 399 free(path);
398 path = NULL; 400 path = NULL;
399   401  
400 stackDestroy(stack); 402 stackDestroy(stack);
401 #if defined ___AsyncIO___ 403 #if defined ___AsyncIO___
402 CloseAsync(fp); 404 CloseAsync(fp);
403 #else 405 #else
404 fclose(fp); 406 fclose(fp);
405 #endif 407 #endif
406 return NULL; 408 return NULL;
407 } 409 }
408 #if defined ___AmigaOS___ 410 #if defined ___AmigaOS___
409 sprintf(sub, "%s%s", path, FIB->fib_FileName); 411 sprintf(sub, "%s%s", path, FIB->fib_FileName);
410 #else 412 #else
411 sprintf(sub, "%s%s", path, entry->d_name); 413 sprintf(sub, "%s%s", path, entry->d_name);
412 #endif 414 #endif
413 break; 415 break;
414 default: 416 default:
415 #if defined ___AmigaOS___ 417 #if defined ___AmigaOS___
416 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) {
417 #else 419 #else
418 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) {
419 #endif 421 #endif
420 fprintf(stderr, "Memory allocation failure.\n"); 422 fprintf(stderr, "Memory allocation failure.\n");
421 #if defined ___AmigaOS___ 423 #if defined ___AmigaOS___
422 FreeDosObject(DOS_FIB, FIB); 424 FreeDosObject(DOS_FIB, FIB);
423 FIB = NULL; 425 FIB = NULL;
424 UnLock(lock); 426 UnLock(lock);
425 #else 427 #else
426 closedir(dir); 428 closedir(dir);
427 #endif 429 #endif
428 free(path); 430 free(path);
429 path = NULL; 431 path = NULL;
430   432  
431 stackDestroy(stack); 433 stackDestroy(stack);
432 #if defined ___AsyncIO___ 434 #if defined ___AsyncIO___
433 CloseAsync(fp); 435 CloseAsync(fp);
434 #else 436 #else
435 fclose(fp); 437 fclose(fp);
436 #endif 438 #endif
437 return NULL; 439 return NULL;
438 } 440 }
439 #if defined ___AmigaOS___ 441 #if defined ___AmigaOS___
440 sprintf(sub, "%s/%s", path, FIB->fib_FileName); 442 sprintf(sub, "%s/%s", path, FIB->fib_FileName);
441 #else 443 #else
442 sprintf(sub, "%s/%s", path, entry->d_name); 444 sprintf(sub, "%s/%s", path, entry->d_name);
443 #endif 445 #endif
444 break; 446 break;
445 } 447 }
446   448  
447 switch(GetFsType(sub)) { 449 switch(GetFsType(sub)) {
448 case UNKNOWN: 450 case UNKNOWN:
449 free(sub); 451 free(sub);
450 sub = NULL; 452 sub = NULL;
451 continue; 453 continue;
452 case REGULAR: 454 case REGULAR:
453 ++stats->files; 455 ++stats->files;
454   456  
455 if(PROGRAM_VERBOSE) { 457 if(PROGRAM_VERBOSE) {
456 fprintf(stdout, 458 fprintf(stdout,
457 "Gathered '%d' directories and '%d' files.\r", 459 "Gathered '%d' directories and '%d' files.\r",
458 stats->dirs, 460 stats->dirs,
459 stats->files); 461 stats->files);
460 } 462 }
461 break; 463 break;
462 case DIRECTORY: 464 case DIRECTORY:
463 stackPush(stack, sub, (strlen(sub) + 1) * sizeof(char)); 465 stackPush(stack, sub, (strlen(sub) + 1) * sizeof(char));
464   466  
465 ++stats->dirs; 467 ++stats->dirs;
466   468  
467 if(PROGRAM_VERBOSE) { 469 if(PROGRAM_VERBOSE) {
468 fprintf(stdout, 470 fprintf(stdout,
469 "Gathered '%d' directories and '%d' files.\r", 471 "Gathered '%d' directories and '%d' files.\r",
470 stats->dirs, 472 stats->dirs,
471 stats->files); 473 stats->files);
472 } 474 }
473   475  
474 free(sub); 476 free(sub);
475 sub = NULL; 477 sub = NULL;
476 continue; 478 continue;
477 } 479 }
478   480  
479 #if defined ___NOCASE_FS___ 481 #if defined ___NOCASE_FS___
480 #if defined ___AmigaOS___ 482 #if defined ___AmigaOS___
481 StrUpr(FIB->fib_FileName); 483 StrUpr(FIB->fib_FileName);
482 #else 484 #else
483 StrUpr(entry->d_name); 485 StrUpr(entry->d_name);
484 #endif 486 #endif
485 #endif 487 #endif
486   488  
487 // Write to database file. 489 // Write to database file.
488 #if defined ___AsyncIO___ 490 #if defined ___AsyncIO___
489 #if defined ___AmigaOS___ 491 #if defined ___AmigaOS___
490 WriteAsync(fp, FIB->fib_FileName, (LONG)strlen(FIB->fib_FileName)); 492 WriteAsync(fp, FIB->fib_FileName, (LONG)strlen(FIB->fib_FileName));
491 stats->size = stats->size + strlen(FIB->fib_FileName); 493 stats->size = stats->size + strlen(FIB->fib_FileName);
492 #else 494 #else
493 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name)); 495 WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name));
494 stats->size = stats->size + strlen(entry->d_name); 496 stats->size = stats->size + strlen(entry->d_name);
495 #endif 497 #endif
496 WriteAsync(fp, "\t", 1); 498 WriteAsync(fp, "\t", 1);
497 ++stats->size; 499 ++stats->size;
498 WriteAsync(fp, sub, (LONG)strlen(sub)); 500 WriteAsync(fp, sub, (LONG)strlen(sub));
499 stats->size = stats->size + strlen(sub); 501 stats->size = stats->size + strlen(sub);
500 WriteAsync(fp, "\n", 1); 502 WriteAsync(fp, "\n", 1);
501 ++stats->size; 503 ++stats->size;
502 #else 504 #else
503 #if defined ___AmigaOS___ 505 #if defined ___AmigaOS___
504 fprintf(fp, "%s\t%s\n", FIB->fib_FileName, sub); 506 fprintf(fp, "%s\t%s\n", FIB->fib_FileName, sub);
505 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;
506 #else 508 #else
507 fprintf(fp, "%s\t%s\n", entry->d_name, sub); 509 fprintf(fp, "%s\t%s\n", entry->d_name, sub);
508 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;
509 #endif 511 #endif
510 #endif 512 #endif
511   513  
512 ++stats->lines; 514 ++stats->lines;
513   515  
514 free(sub); 516 free(sub);
515 sub = NULL; 517 sub = NULL;
516 } 518 }
517   519  
518 #if defined ___AmigaOS___ 520 #if defined ___AmigaOS___
519 FreeDosObject(DOS_FIB, FIB); 521 FreeDosObject(DOS_FIB, FIB);
520 FIB = NULL; 522 FIB = NULL;
521 UnLock(lock); 523 UnLock(lock);
522 #else 524 #else
523 closedir(dir); 525 closedir(dir);
524 #endif 526 #endif
525 free(path); 527 free(path);
526 path = NULL; 528 path = NULL;
527 } 529 }
528   530  
529 if(PROGRAM_VERBOSE) { 531 if(PROGRAM_VERBOSE) {
530 fprintf(stdout, "\n"); 532 fprintf(stdout, "\n");
531 } 533 }
532   534  
533 stackDestroy(stack); 535 stackDestroy(stack);
534   536  
535 #if defined ___AsyncIO___ 537 #if defined ___AsyncIO___
536 CloseAsync(fp); 538 CloseAsync(fp);
537 #else 539 #else
538 fclose(fp); 540 fclose(fp);
539 #endif 541 #endif
540   542  
541 return stats; 543 return stats;
542   544  
543 } 545 }
544   546  
545 /* 547 /*
546 * 548 *
547 * Writes lines from the database "dbFile" to temporary filenames "tmpNames". 549 * Writes lines from the database "dbFile" to temporary filenames "tmpNames".
548 */ 550 */
549 void WriteTemporaryFiles(char *dbFile, VECTOR *tmpNames, int tmpLines, int total) { 551 void WriteTemporaryFiles(char *dbFile, VECTOR *tmpNames, int tmpLines, int total) {
550 #if defined ___AsyncIO___ 552 #if defined ___AsyncIO___
551 struct AsyncFile *fp, *tp; 553 struct AsyncFile *fp, *tp;
552 #else 554 #else
553 FILE *fp, *tp; 555 FILE *fp, *tp;
554 #endif 556 #endif
555 int lines; 557 int lines;
556 int write; 558 int write;
557 int files; 559 int files;
558 dbLine *line = NULL; 560 dbLine *line = NULL;
559   561  
560 #if defined ___AsyncIO___ 562 #if defined ___AsyncIO___
561 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 563 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
562 #else 564 #else
563 if((fp = fopen(dbFile, "r")) == NULL) { 565 if((fp = fopen(dbFile, "r")) == NULL) {
564 #endif 566 #endif
565 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile); 567 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
566 return; 568 return;
567 } 569 }
568   570  
569 files = tmpNames->length; 571 files = tmpNames->length;
570 #if defined ___AsyncIO___ 572 #if defined ___AsyncIO___
571 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) { 573 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) {
572 #else 574 #else
573 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) { 575 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) {
574 #endif 576 #endif
575 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]);
576 #if defined ___AsyncIO___ 578 #if defined ___AsyncIO___
577 CloseAsync(fp); 579 CloseAsync(fp);
578 #else 580 #else
579 fclose(fp); 581 fclose(fp);
580 #endif 582 #endif
581 return; 583 return;
582 } 584 }
583   585  
584 if(PROGRAM_VERBOSE) { 586 if(PROGRAM_VERBOSE) {
585 fprintf(stdout, "Writing to temporary files...\r"); 587 fprintf(stdout, "Writing to temporary files...\r");
586 } 588 }
587   589  
588 write = 0; 590 write = 0;
589 lines = 0; 591 lines = 0;
590   592  
591 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) { 593 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
592 #if defined ___AmigaOS___ 594 #if defined ___AmigaOS___
593 // Check if CTRL+C was pressed and abort the program. 595 // Check if CTRL+C was pressed and abort the program.
594 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 596 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
595 free(line->string); 597 free(line->string);
596 free(line); 598 free(line);
597 line = NULL; 599 line = NULL;
598   600  
599 PROGRAM_RUN = FALSE; 601 PROGRAM_RUN = FALSE;
600 continue; 602 continue;
601 } 603 }
602 #endif 604 #endif
603   605  
604 #if defined ___AsyncIO___ 606 #if defined ___AsyncIO___
605 WriteAsync(tp, line->string, (LONG)line->length); 607 WriteAsync(tp, line->string, (LONG)line->length);
606 WriteAsync(tp, "\n", 1); 608 WriteAsync(tp, "\n", 1);
607 #else 609 #else
608 fprintf(tp, "%s\n", line->string); 610 fprintf(tp, "%s\n", line->string);
609 #endif 611 #endif
610   612  
611 ++write; 613 ++write;
612   614  
613 if(PROGRAM_VERBOSE) { 615 if(PROGRAM_VERBOSE) {
614 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));
615 } 617 }
616   618  
617 // Switch to the next temporary file. 619 // Switch to the next temporary file.
618 if(++lines >= tmpLines) { 620 if(++lines >= tmpLines) {
619 // 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.
620 if(files - 1 < 0) { 622 if(files - 1 < 0) {
621 free(line->string); 623 free(line->string);
622 free(line); 624 free(line);
623 line = NULL; 625 line = NULL;
624 continue; 626 continue;
625 } 627 }
626   628  
627 // 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.
628 #if defined ___AsyncIO___ 630 #if defined ___AsyncIO___
629 CloseAsync(tp); 631 CloseAsync(tp);
630 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) { 632 if((tp = OpenAsync(tmpNames->array[--files], MODE_WRITE, ASYNC_BUF)) == NULL) {
631 #else 633 #else
632 fclose(tp); 634 fclose(tp);
633 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) { 635 if((tp = fopen(tmpNames->array[--files], "w")) == NULL) {
634 #endif 636 #endif
635 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]);
636 #if defined ___AsyncIO___ 638 #if defined ___AsyncIO___
637 CloseAsync(fp); 639 CloseAsync(fp);
638 #else 640 #else
639 fclose(fp); 641 fclose(fp);
640 #endif 642 #endif
641 free(line->string); 643 free(line->string);
642 free(line); 644 free(line);
643 line = NULL; 645 line = NULL;
644 return; 646 return;
645 } 647 }
646 lines = 0; 648 lines = 0;
647 } 649 }
648   650  
649 free(line->string); 651 free(line->string);
650 free(line); 652 free(line);
651 line = NULL; 653 line = NULL;
652 } 654 }
653   655  
654 if(line != NULL) { 656 if(line != NULL) {
655 free(line->string); 657 free(line->string);
656 free(line); 658 free(line);
657 line = NULL; 659 line = NULL;
658 } 660 }
659   661  
660 if(PROGRAM_VERBOSE) { 662 if(PROGRAM_VERBOSE) {
661 fprintf(stdout, "\n"); 663 fprintf(stdout, "\n");
662 } 664 }
663   665  
664 #if defined ___AsyncIO___ 666 #if defined ___AsyncIO___
665 CloseAsync(tp); 667 CloseAsync(tp);
666 CloseAsync(fp); 668 CloseAsync(fp);
667 #else 669 #else
668 fclose(tp); 670 fclose(tp);
669 fclose(fp); 671 fclose(fp);
670 #endif 672 #endif
671 } 673 }
672   674  
673 /* 675 /*
674 * 676 *
675 * Merges temporary files "tmpNames" into a database "dbFile". 677 * Merges temporary files "tmpNames" into a database "dbFile".
676 */ 678 */
677 void MergeTemporaryFiles(char *dbFile, VECTOR *tmpNames, int lines) { 679 void MergeTemporaryFiles(char *dbFile, VECTOR *tmpNames, int lines) {
678 #if defined ___AsyncIO___ 680 #if defined ___AsyncIO___
679 struct AsyncFile *fp; 681 struct AsyncFile *fp;
680 struct AsyncFile **tp; 682 struct AsyncFile **tp;
681 #else 683 #else
682 FILE *fp; 684 FILE *fp;
683 FILE **tp; 685 FILE **tp;
684 #endif 686 #endif
685 int i; 687 int i;
686 int j; 688 int j;
687 dbLine *tmp; 689 dbLine *tmp;
688 char *rem; 690 char *rem;
689 char *min; 691 char *min;
690 int count; 692 int count;
691   693  
692 #if defined ___AsyncIO___ 694 #if defined ___AsyncIO___
693 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) { 695 if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
694 #else 696 #else
695 if((fp = fopen(dbFile, "w")) == NULL) { 697 if((fp = fopen(dbFile, "w")) == NULL) {
696 #endif 698 #endif
697 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile); 699 fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
698 return; 700 return;
699 } 701 }
700   702  
701 // Allocate as many file pointers as temporary files. 703 // Allocate as many file pointers as temporary files.
702 if((tp = malloc(tmpNames->length * sizeof(*tp))) == NULL) { 704 if((tp = malloc(tmpNames->length * sizeof(*tp))) == NULL) {
703 fprintf(stderr, "Memory allocation failure.\n"); 705 fprintf(stderr, "Memory allocation failure.\n");
704 #if defined ___AsyncIO___ 706 #if defined ___AsyncIO___
705 CloseAsync(fp); 707 CloseAsync(fp);
706 #else 708 #else
707 fclose(fp); 709 fclose(fp);
708 #endif 710 #endif
709 return; 711 return;
710 } 712 }
711   713  
712 // Open all temporary files for reading. 714 // Open all temporary files for reading.
713 for(i = 0; i < tmpNames->length; ++i) { 715 for(i = 0; i < tmpNames->length; ++i) {
714 #if defined ___AsyncIO___ 716 #if defined ___AsyncIO___
715 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) {
716 #else 718 #else
717 if((tp[i] = fopen(tmpNames->array[i], "r")) == NULL) { 719 if((tp[i] = fopen(tmpNames->array[i], "r")) == NULL) {
718 #endif 720 #endif
719 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]);
720 // Close all temporary files. 722 // Close all temporary files.
721 while(--i > -1) { 723 while(--i > -1) {
722 #if defined ___AsyncIO___ 724 #if defined ___AsyncIO___
723 CloseAsync(tp[i]); 725 CloseAsync(tp[i]);
724 #else 726 #else
725 fclose(tp[i]); 727 fclose(tp[i]);
726 #endif 728 #endif
727 } 729 }
728 #if defined ___AsyncIO___ 730 #if defined ___AsyncIO___
729 CloseAsync(fp); 731 CloseAsync(fp);
730 #else 732 #else
731 fclose(fp); 733 fclose(fp);
732 #endif 734 #endif
733 return; 735 return;
734 } 736 }
735 } 737 }
736   738  
737 if(PROGRAM_VERBOSE) { 739 if(PROGRAM_VERBOSE) {
738 fprintf(stdout, "Merging all files...\r"); 740 fprintf(stdout, "Merging all files...\r");
739 } 741 }
740   742  
741 rem = NULL; 743 rem = NULL;
742 count = lines; 744 count = lines;
743 j = 0; 745 j = 0;
744 while(PROGRAM_RUN && --count > -1) { 746 while(PROGRAM_RUN && --count > -1) {
745 #if defined ___AmigaOS___ 747 #if defined ___AmigaOS___
746 // Check if CTRL+C was pressed and abort the program. 748 // Check if CTRL+C was pressed and abort the program.
747 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 749 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
748 PROGRAM_RUN = FALSE; 750 PROGRAM_RUN = FALSE;
749 continue; 751 continue;
750 } 752 }
751 #endif 753 #endif
752 // Find the smallest line in all temporary files. 754 // Find the smallest line in all temporary files.
753 if(PROGRAM_VERBOSE) { 755 if(PROGRAM_VERBOSE) {
754 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));
755 } 757 }
756   758  
757 min = NULL; 759 min = NULL;
758 for(i = 0; i < tmpNames->length; ++i) { 760 for(i = 0; i < tmpNames->length; ++i) {
759 tmp = PeekLine(tp[i]); 761 tmp = PeekLine(tp[i]);
760 if(tmp == NULL) { 762 if(tmp == NULL) {
761 continue; 763 continue;
762 } 764 }
763 #if defined ___AmigaOS___ 765 #if defined ___AmigaOS___
764 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) {
765 #else 767 #else
766 if(min == NULL || strcmp(tmp->string, min) < 0) { 768 if(min == NULL || strcmp(tmp->string, min) < 0) {
767 #endif 769 #endif
768 if(min != NULL) { 770 if(min != NULL) {
769 // Free previous instance. 771 // Free previous instance.
770 free(min); 772 free(min);
771 min = NULL; 773 min = NULL;
772 } 774 }
773 if((min = malloc((strlen(tmp->string) + 1) * sizeof(*min))) == NULL) { 775 if((min = malloc((strlen(tmp->string) + 1) * sizeof(*min))) == NULL) {
774 fprintf(stderr, "Memory allocation failure.\n"); 776 fprintf(stderr, "Memory allocation failure.\n");
775   777  
776 free(tmp->string); 778 free(tmp->string);
777 free(tmp); 779 free(tmp);
778 tmp = NULL; 780 tmp = NULL;
779   781  
780 if(min != NULL) { 782 if(min != NULL) {
781 free(min); 783 free(min);
782 min = NULL; 784 min = NULL;
783 } 785 }
784 if(rem != NULL) { 786 if(rem != NULL) {
785 free(rem); 787 free(rem);
786 rem = NULL; 788 rem = NULL;
787 } 789 }
788 #if defined ___AsyncIO___ 790 #if defined ___AsyncIO___
789 CloseAsync(fp); 791 CloseAsync(fp);
790 #else 792 #else
791 fclose(fp); 793 fclose(fp);
792 #endif 794 #endif
793 return; 795 return;
794 } 796 }
795 sprintf(min, "%s", tmp->string); 797 sprintf(min, "%s", tmp->string);
796 // 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.
797 j = i; 799 j = i;
798 } 800 }
799 free(tmp->string); 801 free(tmp->string);
800 free(tmp); 802 free(tmp);
801 tmp = NULL; 803 tmp = NULL;
802 } 804 }
803   805  
804 // Forward the file where the smallest line was found. 806 // Forward the file where the smallest line was found.
805 SkipLine(tp[j]); 807 SkipLine(tp[j]);
806   808  
807 // Write the smallest line. 809 // Write the smallest line.
808 if(min != NULL) { 810 if(min != NULL) {
809 // 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.
810 if(rem != NULL) { 812 if(rem != NULL) {
811 #if defined ___AmigaOS___ 813 #if defined ___AmigaOS___
812 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) { 814 if(StrnCmp(locale, min, rem, -1, SC_ASCII) == 0) {
813 #else 815 #else
814 if(strcmp(min, rem) == 0) { 816 if(strcmp(min, rem) == 0) {
815 #endif 817 #endif
816 free(min); 818 free(min);
817 min = NULL; 819 min = NULL;
818 continue; 820 continue;
819 } 821 }
820 } 822 }
821   823  
822 #if defined ___AsyncIO___ 824 #if defined ___AsyncIO___
823 WriteAsync(fp, min, (LONG)strlen(min)); 825 WriteAsync(fp, min, (LONG)strlen(min));
824 WriteAsync(fp, "\n", 1); 826 WriteAsync(fp, "\n", 1);
825 #else 827 #else
826 fprintf(fp, "%s\n", min); 828 fprintf(fp, "%s\n", min);
827 #endif 829 #endif
828   830  
829 if(rem != NULL) { 831 if(rem != NULL) {
830 free(rem); 832 free(rem);
831 rem = NULL; 833 rem = NULL;
832 } 834 }
833   835  
834 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) { 836 if((rem = malloc((strlen(min) + 1) * sizeof(*rem))) == NULL) {
835 fprintf(stderr, "Memory allocation failure.\n"); 837 fprintf(stderr, "Memory allocation failure.\n");
836   838  
837 free(min); 839 free(min);
838 min = NULL; 840 min = NULL;
839   841  
840 #if defined ___AsyncIO___ 842 #if defined ___AsyncIO___
841 CloseAsync(fp); 843 CloseAsync(fp);
842 #else 844 #else
843 fclose(fp); 845 fclose(fp);
844 #endif 846 #endif
845 return; 847 return;
846 } 848 }
847   849  
848 // Remember the last minimal line. 850 // Remember the last minimal line.
849 sprintf(rem, "%s", min); 851 sprintf(rem, "%s", min);
850   852  
851 free(min); 853 free(min);
852 min = NULL; 854 min = NULL;
853 } 855 }
854 } 856 }
855   857  
856 if(rem != NULL) { 858 if(rem != NULL) {
857 free(rem); 859 free(rem);
858 rem = NULL; 860 rem = NULL;
859 } 861 }
860   862  
861 // Write out any remaining contents from the temporary files. 863 // Write out any remaining contents from the temporary files.
862 for(i = 0; PROGRAM_RUN && i < tmpNames->length; ++i) { 864 for(i = 0; PROGRAM_RUN && i < tmpNames->length; ++i) {
863 #if defined ___AmigaOS___ 865 #if defined ___AmigaOS___
864 // Check if CTRL+C was pressed and abort the program. 866 // Check if CTRL+C was pressed and abort the program.
865 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 867 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
866 PROGRAM_RUN = FALSE; 868 PROGRAM_RUN = FALSE;
867 continue; 869 continue;
868 } 870 }
869 #endif 871 #endif
870 tmp = ReadLine(tp[i]); 872 tmp = ReadLine(tp[i]);
871 if(tmp == NULL) { 873 if(tmp == NULL) {
872 continue; 874 continue;
873 } 875 }
874 #if defined ___AsyncIO___ 876 #if defined ___AsyncIO___
875 WriteAsync(fp, tmp->string, (LONG)strlen(tmp->string)); 877 WriteAsync(fp, tmp->string, (LONG)strlen(tmp->string));
876 WriteAsync(fp, "\n", 1); 878 WriteAsync(fp, "\n", 1);
877 #else 879 #else
878 fprintf(fp, "%s\n", tmp->string); 880 fprintf(fp, "%s\n", tmp->string);
879 #endif 881 #endif
880 free(tmp->string); 882 free(tmp->string);
881 free(tmp); 883 free(tmp);
882 tmp = NULL; 884 tmp = NULL;
883 } 885 }
884   886  
885 // Close all temporary files. 887 // Close all temporary files.
886 for(i = 0; i < tmpNames->length; ++i) { 888 for(i = 0; i < tmpNames->length; ++i) {
887 #if defined ___AsyncIO___ 889 #if defined ___AsyncIO___
888 CloseAsync(tp[i]); 890 CloseAsync(tp[i]);
889 #else 891 #else
890 fclose(tp[i]); 892 fclose(tp[i]);
891 #endif 893 #endif
892 } 894 }
893   895  
894 #if defined ___AsyncIO___ 896 #if defined ___AsyncIO___
895 CloseAsync(fp); 897 CloseAsync(fp);
896 #else 898 #else
897 fclose(fp); 899 fclose(fp);
898 #endif 900 #endif
899   901  
900 if(PROGRAM_VERBOSE) { 902 if(PROGRAM_VERBOSE) {
901 fprintf(stdout, "\n"); 903 fprintf(stdout, "\n");
902 } 904 }
903 } 905 }
904   906  
905 /* 907 /*
906 * 908 *
907 * Filter the paths inside the database with provided paths. 909 * Filter the paths inside the database with provided paths.
908 */ 910 */
909 void FilterDatabasePaths(char *dbFile, char *tmpName, VECTOR *paths) { 911 void FilterDatabasePaths(char *dbFile, char *tmpName, VECTOR *paths) {
910 #if defined ___AsyncIO___ 912 #if defined ___AsyncIO___
911 struct AsyncFile *fp; 913 struct AsyncFile *fp;
912 struct AsyncFile *tp; 914 struct AsyncFile *tp;
913 #else 915 #else
914 FILE *fp; 916 FILE *fp;
915 FILE *tp; 917 FILE *tp;
916 #endif 918 #endif
917 dbLine *line; 919 dbLine *line;
918 dbEntry *entry; 920 dbEntry *entry;
919 int lines; 921 int lines;
920 int i; 922 int i;
921   923  
922 // Open database file for reading. 924 // Open database file for reading.
923 #if defined ___AsyncIO___ 925 #if defined ___AsyncIO___
924 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) { 926 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
925 #else 927 #else
926 if((fp = fopen(dbFile, "r")) == NULL) { 928 if((fp = fopen(dbFile, "r")) == NULL) {
927 #endif 929 #endif
928 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile); 930 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
929 return; 931 return;
930 } 932 }
931   933  
932 // Open temporary file for writing. 934 // Open temporary file for writing.
933 #if defined ___AsyncIO___ 935 #if defined ___AsyncIO___
934 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) { 936 if((tp = OpenAsync(tmpName, MODE_WRITE, ASYNC_BUF)) == NULL) {
935 #else 937 #else
936 if((tp = fopen(tmpName, "w")) == NULL) { 938 if((tp = fopen(tmpName, "w")) == NULL) {
937 #endif 939 #endif
938 fprintf(stderr, "Copuld not open file '%s' for writing.\n", tmpName); 940 fprintf(stderr, "Copuld not open file '%s' for writing.\n", tmpName);
939   941  
940 // Close database file. 942 // Close database file.
941 #if defined ___AsyncIO___ 943 #if defined ___AsyncIO___
942 CloseAsync(fp); 944 CloseAsync(fp);
943 #else 945 #else
944 fclose(fp); 946 fclose(fp);
945 #endif 947 #endif
946   948  
947 return; 949 return;
948 } 950 }
949   951  
950 if(PROGRAM_VERBOSE) { 952 if(PROGRAM_VERBOSE) {
951 fprintf(stdout, "Removing lines...\r"); 953 fprintf(stdout, "Removing lines...\r");
952 } 954 }
953   955  
954 lines = 0; 956 lines = 0;
955 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) { 957 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
956 #if defined ___AmigaOS___ 958 #if defined ___AmigaOS___
957 // Check if CTRL+C was pressed and abort the program. 959 // Check if CTRL+C was pressed and abort the program.
958 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { 960 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
959 PROGRAM_RUN = FALSE; 961 PROGRAM_RUN = FALSE;
960 continue; 962 continue;
961 } 963 }
962 #endif 964 #endif
963   965  
964 if((entry = CreateDatabaseEntry(line)) == NULL) { 966 if((entry = CreateDatabaseEntry(line)) == NULL) {
965 fprintf(stderr, "Unable to create database entry.\n"); 967 fprintf(stderr, "Unable to create database entry.\n");
966 free(line->string); 968 free(line->string);
967 free(line); 969 free(line);
968 line = NULL; 970 line = NULL;
969 continue; 971 continue;
970 } 972 }
971   973  
972 for(i = 0; i < paths->length; ++i) { 974 for(i = 0; i < paths->length; ++i) {
973 if(PathCompare(entry->path, paths->array[i]) == TRUE) { 975 if(PathCompare(entry->path, paths->array[i]) == TRUE) {
974 ++lines; 976 ++lines;
975 if(PROGRAM_VERBOSE) { 977 if(PROGRAM_VERBOSE) {
976 fprintf(stdout, "Removing lines: %d.\r", lines); 978 fprintf(stdout, "Removing lines: %d.\r", lines);
977 } 979 }
978 continue; 980 continue;
979 } 981 }
980 #if defined ___AsyncIO___ 982 #if defined ___AsyncIO___
981 WriteAsync(tp, line->string, (LONG)strlen(line->string)); 983 WriteAsync(tp, line->string, (LONG)strlen(line->string));
982 WriteAsync(tp, "\n", 1); 984 WriteAsync(tp, "\n", 1);
983 #else 985 #else
984 fprintf(tp, "%s\n", line->string); 986 fprintf(tp, "%s\n", line->string);
985 #endif 987 #endif
986 break; 988 break;
987 } 989 }
988   990  
989 // Free up database entry. 991 // Free up database entry.
990 free(entry->name); 992 free(entry->name);
991 free(entry->path); 993 free(entry->path);
992 free(entry); 994 free(entry);
993 entry = NULL; 995 entry = NULL;
994   996  
995 // Free up line. 997 // Free up line.
996 free(line->string); 998 free(line->string);
997 free(line); 999 free(line);
998 line = NULL; 1000 line = NULL;
999 } 1001 }
1000   1002  
1001 #if defined ___AsyncIO___ 1003 #if defined ___AsyncIO___
1002 CloseAsync(fp); 1004 CloseAsync(fp);
1003 CloseAsync(tp); 1005 CloseAsync(tp);
1004 #else 1006 #else
1005 fclose(fp); 1007 fclose(fp);
1006 fclose(tp); 1008 fclose(tp);
1007 #endif 1009 #endif
1008   1010  
1009 if(PROGRAM_VERBOSE) { 1011 if(PROGRAM_VERBOSE) {
1010 fprintf(stdout, "\n"); 1012 fprintf(stdout, "\n");
1011 } 1013 }
1012 } 1014 }
1013   1015  
1014 /* 1016 /*
1015 * 1017 *
1016 * Indexes paths and adds to a database file. 1018 * Indexes paths and adds to a database file.
1017 */ 1019 */
1018 void GatherDatabaseFiles(char *dbFile, VECTOR *paths) { 1020 void GatherDatabaseFiles(char *dbFile, VECTOR *paths) {
1019 dbStats *stats; 1021 dbStats *stats;
1020 VECTOR *tmpNames; 1022 VECTOR *tmpNames;
1021 int tmpFiles; 1023 int tmpFiles;
1022 int tmpLines; 1024 int tmpLines;
1023 int i; 1025 int i;
1024 int line; 1026 int line;
1025 int size; 1027 int size;
1026   1028  
1027 // Generate the database file from the supplied paths. 1029 // Generate the database file from the supplied paths.
1028 if((stats = CollectFiles(dbFile, paths)) == NULL) { 1030 if((stats = CollectFiles(dbFile, paths)) == NULL) {
1029 fprintf(stderr, "Collecting files failed.\n"); 1031 fprintf(stderr, "Collecting files failed.\n");
1030 return; 1032 return;
1031 } 1033 }
1032   1034  
1033 // 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.
1034 size = GetFileSize(dbFile); 1036 size = GetFileSize(dbFile);
1035 line = CountFileLines(dbFile); 1037 line = CountFileLines(dbFile);
1036   1038  
1037 // Calculate the total number of temporary files required. 1039 // Calculate the total number of temporary files required.
1038 tmpFiles = size / maxmem; 1040 tmpFiles = size / maxmem;
1039   1041  
1040 /* In case no temporary files are required, 1042 /* In case no temporary files are required,
1041 * just sort the database and terminate. 1043 * just sort the database and terminate.
1042 */ 1044 */
1043 if(tmpFiles < 2) { 1045 if(tmpFiles < 2) {
1044 SortDatabase(dbFile, line); 1046 SortDatabase(dbFile, line);
1045 return; 1047 return;
1046 } 1048 }
1047   1049  
1048 // Calculate the number of lines per temporary file. 1050 // Calculate the number of lines per temporary file.
1049 tmpLines = ceil(((double)line) / ((double)tmpFiles)); 1051 tmpLines = ceil(((double)line) / ((double)tmpFiles));
1050   1052  
1051 // Create temporary files. 1053 // Create temporary files.
1052 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) { 1054 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
1053 fprintf(stderr, "Unable to create temporary files.\n"); 1055 fprintf(stderr, "Unable to create temporary files.\n");
1054 return; 1056 return;
1055 } 1057 }
1056   1058  
1057 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile". 1059 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
1058 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, line); 1060 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, line);
1059   1061  
1060 // Sort the temporary files. 1062 // Sort the temporary files.
1061 for(i = 0; i < tmpNames->length; ++i) { 1063 for(i = 0; i < tmpNames->length; ++i) {
1062 SortDatabase(tmpNames->array[i], tmpLines); 1064 SortDatabase(tmpNames->array[i], tmpLines);
1063 } 1065 }
1064   1066  
1065 // Merge all the temporary files to the database file. 1067 // Merge all the temporary files to the database file.
1066 MergeTemporaryFiles(dbFile, tmpNames, line); 1068 MergeTemporaryFiles(dbFile, tmpNames, line);
1067   1069  
1068 // Remove all temporary files. 1070 // Remove all temporary files.
1069 RemoveFiles(tmpNames); 1071 RemoveFiles(tmpNames);
1070   1072  
1071 // Free temporary file names. 1073 // Free temporary file names.
1072 free(tmpNames); 1074 free(tmpNames);
1073 tmpNames = NULL; 1075 tmpNames = NULL;
1074   1076  
1075 // Free statistics. 1077 // Free statistics.
1076 free(stats); 1078 free(stats);
1077 stats = NULL; 1079 stats = NULL;
1078 } 1080 }
1079   1081  
1080 /* 1082 /*
1081 * 1083 *
1082 * Indexes paths and creates a daabase file. 1084 * Indexes paths and creates a daabase file.
1083 */ 1085 */
1084 void CreateDatabaseFiles(char *dbFile, VECTOR *paths) { 1086 void CreateDatabaseFiles(char *dbFile, VECTOR *paths) {
1085 dbStats *stats; 1087 dbStats *stats;
1086 VECTOR *tmpNames; 1088 VECTOR *tmpNames;
1087 int tmpFiles; 1089 int tmpFiles;
1088 int tmpLines; 1090 int tmpLines;
1089 int i; 1091 int i;
1090   1092  
1091 // Generate the database file from the supplied paths. 1093 // Generate the database file from the supplied paths.
1092 if((stats = CollectFiles(dbFile, paths)) == NULL) { 1094 if((stats = CollectFiles(dbFile, paths)) == NULL) {
1093 fprintf(stderr, "Collecting files failed.\n"); 1095 fprintf(stderr, "Collecting files failed.\n");
1094 return; 1096 return;
1095 } 1097 }
1096   1098  
1097 // Calculate the total number of temporary files required. 1099 // Calculate the total number of temporary files required.
1098 tmpFiles = stats->size / maxmem; 1100 tmpFiles = stats->size / maxmem;
1099   1101  
1100 /* In case no temporary files are required, 1102 /* In case no temporary files are required,
1101 * just sort the database and terminate. 1103 * just sort the database and terminate.
1102 */ 1104 */
1103 if(tmpFiles < 2) { 1105 if(tmpFiles < 2) {
1104 SortDatabase(dbFile, stats->lines); 1106 SortDatabase(dbFile, stats->lines);
1105 return; 1107 return;
1106 } 1108 }
1107   1109  
1108 // Calculate the number of lines per temporary file. 1110 // Calculate the number of lines per temporary file.
1109 tmpLines = ceil(((double)stats->lines) / ((double)tmpFiles)); 1111 tmpLines = ceil(((double)stats->lines) / ((double)tmpFiles));
1110   1112  
1111 // Create temporary files. 1113 // Create temporary files.
1112 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) { 1114 if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
1113 fprintf(stderr, "Unable to create temporary files.\n"); 1115 fprintf(stderr, "Unable to create temporary files.\n");
1114 return; 1116 return;
1115 } 1117 }
1116   1118  
1117 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile". 1119 // Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
1118 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, stats->lines); 1120 WriteTemporaryFiles(dbFile, tmpNames, tmpLines, stats->lines);
1119   1121  
1120 // Sort the temporary files. 1122 // Sort the temporary files.
1121 for(i = 0; i < tmpNames->length; ++i) { 1123 for(i = 0; i < tmpNames->length; ++i) {
1122 SortDatabase(tmpNames->array[i], tmpLines); 1124 SortDatabase(tmpNames->array[i], tmpLines);
1123 } 1125 }
1124   1126  
1125 // Merge all the temporary files to the database file. 1127 // Merge all the temporary files to the database file.
1126 MergeTemporaryFiles(dbFile, tmpNames, stats->lines); 1128 MergeTemporaryFiles(dbFile, tmpNames, stats->lines);
1127   1129  
1128 // Remove all temporary files. 1130 // Remove all temporary files.
1129 RemoveFiles(tmpNames); 1131 RemoveFiles(tmpNames);
1130   1132  
1131 // Free temporary file names. 1133 // Free temporary file names.
1132 free(tmpNames); 1134 free(tmpNames);
1133 tmpNames = NULL; 1135 tmpNames = NULL;
1134   1136  
1135 // Free statistics. 1137 // Free statistics.
1136 free(stats); 1138 free(stats);
1137 stats = NULL; 1139 stats = NULL;
1138 } 1140 }
1139   1141  
1140 void RemoveDatabaseFiles(char *dbFile, VECTOR *paths) { 1142 void RemoveDatabaseFiles(char *dbFile, VECTOR *paths) {
1141 char *tmpName; 1143 char *tmpName;
1142   1144  
1143 // Create a temporary file to hold the changes. 1145 // Create a temporary file to hold the changes.
1144 if((tmpName = CreateTemporaryFile()) == NULL) { 1146 if((tmpName = CreateTemporaryFile()) == NULL) {
1145 fprintf(stderr, "Unable to create temporary file.\n"); 1147 fprintf(stderr, "Unable to create temporary file.\n");
1146 return; 1148 return;
1147 } 1149 }
1148   1150  
1149 // Filter the database of the provided paths. 1151 // Filter the database of the provided paths.
1150 FilterDatabasePaths(dbFile, tmpName, paths); 1152 FilterDatabasePaths(dbFile, tmpName, paths);
1151   1153  
1152 // Overwrite the database file with the filtered paths. 1154 // Overwrite the database file with the filtered paths.
1153 CopyLines(tmpName, dbFile); 1155 CopyLines(tmpName, dbFile);
1154   1156  
1155 // Remove temporary file. 1157 // Remove temporary file.
1156 if(RemoveFile(tmpName) == FALSE) { 1158 if(RemoveFile(tmpName) == FALSE) {
1157 fprintf(stderr, "Temporary file could not be removed.\n"); 1159 fprintf(stderr, "Temporary file could not be removed.\n");
1158 return; 1160 return;
1159 } 1161 }
1160 } 1162 }
1161   1163  
1162 void usage(char *name) { 1164 void usage(char *name) {
1163 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);
1164 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION); 1166 fprintf(stdout, "Version: %s \n", PROGRAM_VERSION);
1165 fprintf(stdout, " \n"); 1167 fprintf(stdout, " \n");
1166 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);
1167 fprintf(stdout, " \n"); 1169 fprintf(stdout, " \n");
1168 fprintf(stdout, "Required: \n"); 1170 fprintf(stdout, "Required: \n");
1169 fprintf(stdout, " -a [PATH...] Add files. \n"); 1171 fprintf(stdout, " -a [PATH...] Add files. \n");
1170 fprintf(stdout, " -c [PATH...] Create from scratch. \n"); 1172 fprintf(stdout, " -c [PATH...] Create from scratch. \n");
1171 fprintf(stdout, " -r [PATH...] Remove files. \n"); 1173 fprintf(stdout, " -r [PATH...] Remove files. \n");
1172 fprintf(stdout, " \n"); 1174 fprintf(stdout, " \n");
1173 fprintf(stdout, "Optional: \n"); 1175 fprintf(stdout, "Optional: \n");
1174 fprintf(stdout, " -d [FIILE] Where to store the database. \n"); 1176 fprintf(stdout, " -d [FIILE] Where to store the database. \n");
1175 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem); 1177 fprintf(stdout, " -m BYTES Memory to use (default: %d). \n", maxmem);
1176 fprintf(stdout, " -q Do not print out any messages. \n"); 1178 fprintf(stdout, " -q Do not print out any messages. \n");
1177 fprintf(stdout, " \n"); 1179 fprintf(stdout, " \n");
1178 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");
1179 fprintf(stdout, "stored for searching with the Hunt tool. \n"); 1181 fprintf(stdout, "stored for searching with the Hunt tool. \n");
1180 fprintf(stdout, " \n"); 1182 fprintf(stdout, " \n");
1181 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n"); 1183 fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n");
1182 } 1184 }
1183   1185  
1184 /* 1186 /*
1185 * 1187 *
1186 * Main entry point. 1188 * Main entry point.
1187 */ 1189 */
1188 int main(int argc, char **argv) { 1190 int main(int argc, char **argv) {
1189 int option; 1191 int option;
1190 int i; 1192 int i;
1191 char *dbFile; 1193 char *dbFile;
1192 char *path; 1194 char *path;
1193 VECTOR *paths; 1195 VECTOR *paths;
1194 OPERATION operation = NONE; 1196 OPERATION operation = NONE;
1195   1197  
1196 // Bind handler to SIGINT. 1198 // Bind handler to SIGINT.
1197 #if !defined ___AmigaOS___ 1199 #if !defined ___AmigaOS___
1198 signal(SIGINT, SignalHandler); 1200 signal(SIGINT, SignalHandler);
1199 #endif 1201 #endif
1200   1202  
1201 dbFile = DEFAULT_DATABASE_FILE; 1203 dbFile = DEFAULT_DATABASE_FILE;
1202 while((option = getopt(argc, argv, "hqdm:arc")) != -1) { 1204 while((option = getopt(argc, argv, "hqdm:arc")) != -1) {
1203 switch(option) { 1205 switch(option) {
1204 case 'a': 1206 case 'a':
1205 operation = GATHER; 1207 operation = GATHER;
1206 break; 1208 break;
1207 case 'r': 1209 case 'r':
1208 operation = REMOVE; 1210 operation = REMOVE;
1209 break; 1211 break;
1210 case 'c': 1212 case 'c':
1211 operation = CREATE; 1213 operation = CREATE;
1212 break; 1214 break;
1213 case 'm': 1215 case 'm':
1214 maxmem = strtoul(optarg, NULL, 10); 1216 maxmem = strtoul(optarg, NULL, 10);
1215 break; 1217 break;
1216 case 'd': 1218 case 'd':
1217 dbFile = optarg; 1219 dbFile = optarg;
1218 break; 1220 break;
1219 case 'q': 1221 case 'q':
1220 PROGRAM_VERBOSE = FALSE; 1222 PROGRAM_VERBOSE = FALSE;
1221 break; 1223 break;
1222 case 'h': 1224 case 'h':
1223 usage(argv[0]); 1225 usage(argv[0]);
1224 return 0; 1226 return 0;
1225 case '?': 1227 case '?':
1226 fprintf(stderr, "Invalid option %ct.\n", optopt); 1228 fprintf(stderr, "Invalid option %ct.\n", optopt);
1227 return 5; 1229 return 5;
1228 } 1230 }
1229 } 1231 }
1230   1232  
1231 if(operation == NONE) { 1233 if(operation == NONE) {
1232 usage(argv[0]); 1234 usage(argv[0]);
1233 return 5; 1235 return 5;
1234 } 1236 }
1235   1237  
1236 if(optind >= argc) { 1238 if(optind >= argc) {
1237 usage(argv[0]); 1239 usage(argv[0]);
1238 return 5; 1240 return 5;
1239 } 1241 }
1240   1242  
1241 // Build the path vector. 1243 // Build the path vector.
1242 if((paths = malloc(1 * sizeof(*paths))) == NULL) { 1244 if((paths = malloc(1 * sizeof(*paths))) == NULL) {
1243 fprintf(stderr, "Memory allocation failure.\n"); 1245 fprintf(stderr, "Memory allocation failure.\n");
1244 return 20; 1246 return 20;
1245 } 1247 }
1246   1248  
1247 // Go through all supplied arguments and add paths to search. 1249 // Go through all supplied arguments and add paths to search.
1248 if((paths->array = malloc((argc - optind) * sizeof(*paths))) == NULL) { 1250 if((paths->array = malloc((argc - optind) * sizeof(*paths))) == NULL) {
1249 fprintf(stderr, "Memory allocation failure.\n"); 1251 fprintf(stderr, "Memory allocation failure.\n");
1250 return 20; 1252 return 20;
1251 } 1253 }
1252   1254  
1253 for(i = optind, paths->length = 0; i < argc; ++i) { 1255 for(i = optind, paths->length = 0; i < argc; ++i) {
1254 if((path = PathToAbsolute(argv[i])) == NULL) { 1256 if((path = PathToAbsolute(argv[i])) == NULL) {
1255 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]);
1256 continue; 1258 continue;
1257 } 1259 }
1258   1260  
1259 switch(GetFsType(path)) { 1261 switch(GetFsType(path)) {
1260 case UNKNOWN: 1262 case UNKNOWN:
1261 case REGULAR: 1263 case REGULAR:
1262 fprintf(stderr, "Path '%s' is not a directory.\n", path); 1264 fprintf(stderr, "Path '%s' is not a directory.\n", path);
1263 free(path); 1265 free(path);
1264 path = NULL; 1266 path = NULL;
1265 continue; 1267 continue;
1266 case DIRECTORY: 1268 case DIRECTORY:
1267 break; 1269 break;
1268 } 1270 }
1269   1271  
1270 if(PROGRAM_VERBOSE) { 1272 if(PROGRAM_VERBOSE) {
1271 fprintf(stdout, "Will process path: '%s'\n", path); 1273 fprintf(stdout, "Will process path: '%s'\n", path);
1272 } 1274 }
1273   1275  
1274 // Add the path to the array of paths. 1276 // Add the path to the array of paths.
1275 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) {
1276 fprintf(stderr, "Memory allocation failure."); 1278 fprintf(stderr, "Memory allocation failure.");
1277 return 20; 1279 return 20;
1278 } 1280 }
1279   1281  
1280 sprintf(paths->array[paths->length], "%s", path); 1282 sprintf(paths->array[paths->length], "%s", path);
1281 ++paths->length; 1283 ++paths->length;
1282   1284  
1283 free(path); 1285 free(path);
1284 path = NULL; 1286 path = NULL;
1285   1287  
1286 } 1288 }
1287   1289  
1288 if(paths->length == 0) { 1290 if(paths->length == 0) {
1289 fprintf(stderr, "No valid paths are available.\n"); 1291 fprintf(stderr, "No valid paths are available.\n");
1290 free(paths->array); 1292 free(paths->array);
1291 free(paths); 1293 free(paths);
1292 paths = NULL; 1294 paths = NULL;
1293 return 5; 1295 return 5;
1294 } 1296 }
1295   1297  
1296 if(PROGRAM_VERBOSE) { 1298 if(PROGRAM_VERBOSE) {
1297 fprintf(stdout, "Gathering to: '%s'\n", dbFile); 1299 fprintf(stdout, "Gathering to: '%s'\n", dbFile);
1298 } 1300 }
1299   1301  
1300 #if defined ___AmigaOS___ 1302 #if defined ___AmigaOS___
1301 locale = OpenLocale(NULL); 1303 locale = OpenLocale(NULL);
1302 #endif 1304 #endif
1303   1305  
1304 switch(operation) { 1306 switch(operation) {
1305 case CREATE: 1307 case CREATE:
1306 if(PROGRAM_VERBOSE) { 1308 if(PROGRAM_VERBOSE) {
1307 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile); 1309 fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile);
1308 } 1310 }
1309 RemoveFile(dbFile); 1311 RemoveFile(dbFile);
1310 if(PROGRAM_VERBOSE) { 1312 if(PROGRAM_VERBOSE) {
1311 fprintf(stdout, "Gathering files to database...\n"); 1313 fprintf(stdout, "Gathering files to database...\n");
1312 } 1314 }
1313 CreateDatabaseFiles(dbFile, paths); 1315 CreateDatabaseFiles(dbFile, paths);
1314 break; 1316 break;
1315 case GATHER: 1317 case GATHER:
1316 if(PROGRAM_VERBOSE) { 1318 if(PROGRAM_VERBOSE) {
1317 fprintf(stdout, "Gathering files to database...\n"); 1319 fprintf(stdout, "Gathering files to database...\n");
1318 } 1320 }
1319 GatherDatabaseFiles(dbFile, paths); 1321 GatherDatabaseFiles(dbFile, paths);
1320 break; 1322 break;
1321 case REMOVE: 1323 case REMOVE:
1322 if(PROGRAM_VERBOSE) { 1324 if(PROGRAM_VERBOSE) {
1323 fprintf(stdout, "Removing files from database...\n"); 1325 fprintf(stdout, "Removing files from database...\n");
1324 } 1326 }
1325 RemoveDatabaseFiles(dbFile, paths); 1327 RemoveDatabaseFiles(dbFile, paths);
1326 break; 1328 break;
1327 default: 1329 default:
1328 fprintf(stderr, "Unknown operation.\n"); 1330 fprintf(stderr, "Unknown operation.\n");
1329 #if defined ___AmigaOS___ 1331 #if defined ___AmigaOS___
1330 CloseLocale(locale); 1332 CloseLocale(locale);
1331 #endif 1333 #endif
1332   1334  
1333 free(paths->array); 1335 free(paths->array);
1334 free(paths); 1336 free(paths);
1335 paths = NULL; 1337 paths = NULL;
1336 return 5; 1338 return 5;
1337 } 1339 }
1338   1340  
1339 #if defined ___AmigaOS___ 1341 #if defined ___AmigaOS___
1340 CloseLocale(locale); 1342 CloseLocale(locale);
1341 #endif 1343 #endif
1342   1344  
1343 if(paths != NULL) { 1345 if(paths != NULL) {
1344 free(paths->array); 1346 free(paths->array);
1345 free(paths); 1347 free(paths);
1346 paths = NULL; 1348 paths = NULL;
1347 } 1349 }
1348   1350  
1349 return 0; 1351 return 0;
1350 } 1352 }
1351   1353