HuntnGather

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 32  →  ?path2? @ 33
/trunk/HuntnGather/Gather/Gather.c
@@ -18,6 +18,7 @@
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/locale.h>
#include <clib/utility_protos.h>
#endif
 
#if defined ___AsyncIO___
@@ -25,10 +26,11 @@
#endif
 
#if !defined ___HAVE_GETOPT___
#include "getopt.h"
#include "/shared/getopt.h"
#endif
 
#include "StringStack.h"
#include "/shared/utilities.h"
 
#define PROGRAM_VERSION "1.7.4"
 
@@ -40,44 +42,10 @@
"\0$VER: Gather " PROGRAM_VERSION " "__DATE__" by Wizardry and Steamworks";
#endif
 
#if !defined TRUE
#define TRUE 1;
#endif
int PROGRAM_RUN = TRUE;
int PROGRAM_VERBOSE = TRUE;
int maxmem = MAX_MEM;
 
#if !defined FALSE
#define FALSE 0;
#endif
 
#define ASYNC_BUF 8192
#define MAX_MEM 262144
#define LINE_BUF 256
#define DEFAULT_DATABASE_FILE "S:gather.db"
 
typedef struct {
unsigned int dirs;
unsigned int files;
} stats;
 
typedef struct {
char *name;
char *path;
} dbEntry;
 
typedef struct {
char **database;
unsigned int count;
} dbArray;
 
enum MODE {
NONE,
GATHER,
REMOVE,
CREATE
} operation;
 
unsigned int run = TRUE;
unsigned int verbose = TRUE;
unsigned int maxmem = MAX_MEM;
// Define global locale for string compare.
#if defined ___AmigaOS___
struct Locale *locale;
@@ -84,8 +52,8 @@
#endif
 
void SignalHandler(int sig) {
// Toggle the run flag to stop execution.
run = FALSE;
/* Toggle the run flag to stop execution. */
PROGRAM_RUN = FALSE;
}
 
/*
@@ -108,515 +76,111 @@
 
/*
*
* Gets the absolute path to file by name.
* Sorts a database file lexicographically.
*/
char *PathToAbsolute(char *path) {
char *abs;
#if defined ___AmigaOS___
BPTR lock;
#endif
 
#if defined ___AmigaOS___
if((abs = malloc(PATH_MAX * sizeof(*abs))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
}
if((lock = Lock(path, SHARED_LOCK)) == 0) {
fprintf(stderr, "Lock on %s failed.\n", path);
return NULL;
}
if(NameFromLock(lock, abs, PATH_MAX) == FALSE) {
fprintf(stderr, "Lock on %s failed.\n", path);
UnLock(lock);
return NULL;
}
UnLock(lock);
#else
//abs = realpath(path, NULL);
if((abs = malloc((strlen(path) + 1) * sizeof(*abs))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
}
sprintf(abs, "%s", path);
#endif
 
return abs;
}
 
/*
*
* Compares path parts for equality.
*/
#if defined ___AmigaOS___
BOOL PathCompare(char *path, char *look) {
#else
int PathCompare(char *path, char *look) {
#endif
char *a;
char *b;
 
for(a = path, b = look; *a != '\0' && *b != '\0'; ++a, ++b) {
if(*b != '\0' && *a != *b) {
return FALSE;
}
}
 
return *b == '\0';
}
 
/*
*
* Gets the size of a file by name.
*/
int GetFileSize(char *dbFile) {
void SortDatabase(char *dbFile, int lines) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
LONG size;
#else
FILE *fp;
int size;
#endif
char **database;
dbEntry *entry;
char *line = NULL;
char *rem;
int count;
int i;
 
// Open database file for reading.
#if defined ___AsyncIO___
if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
#else
if((fp = fopen(dbFile, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
return -1;
fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
return;
}
 
if((database = malloc(lines * sizeof(*database))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
#if defined ___AsyncIO___
if(SeekAsync(fp, 0, MODE_END) == -1) {
CloseAsync(fp);
#else
if(fseek(fp, 0L, SEEK_END) != 0) {
#endif
fprintf(stderr, "Seek in file %s failed.\n", dbFile);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
return -1;
return;
}
#if defined ___AsyncIO___
if((size = SeekAsync(fp, 0, MODE_CURRENT)) == -1) {
fprintf(stderr, "Seek in file %s failed.\n", dbFile);
CloseAsync(fp);
return -1;
}
#else
size = ftell(fp);
#endif
 
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
 
return size;
}
 
/*
*
* Counts the lines of a file.
*/
int CountFileLines(char *dbFile) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
LONG c;
#else
FILE *fp;
char c;
#endif
int lines;
 
#if defined ___AsyncIO___
if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
#else
if((fp = fopen(dbFile, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
return -1;
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Reading lines from file '%s' to array...\n", dbFile);
}
 
lines = 0;
if(verbose) {
fprintf(stdout, "Lines in '%s' so far: %d\r", dbFile, lines);
}
 
#if defined ___AsyncIO___
while(run && (c = ReadCharAsync(fp)) != -1) {
#else
while(run && fscanf(fp, "%c", &c) == 1) {
#endif
count = 0;
while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
PROGRAM_RUN = FALSE;
continue;
}
#endif
switch(c) {
case '\n':
++lines;
 
if(verbose) {
fprintf(stdout, "Lines in '%s' so far: %d\r", dbFile, lines);
}
break;
}
}
 
if((entry = CreateDatabaseEntry(line)) == NULL) {
fprintf(stderr, "Unable to create database entry.\n");
free(line);
#if defined ___AsyncIO___
CloseAsync(fp);
CloseAsync(fp);
#else
fclose(fp);
fclose(fp);
#endif
 
if(verbose) {
fprintf(stdout, "\n");
}
 
return lines;
}
 
/*
*
* Creates a temporary file and returns its name.
*/
char *CreateTemporaryFile(void) {
char *name;
 
name = tmpnam(NULL);
 
return name;
}
 
/*
*
* Create multiple temporary files and return their names.
*/
char **CreateTemporaryFiles(int files) {
char **tmpNames;
int count;
 
if((tmpNames = malloc(files * sizeof(*tmpNames))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
}
 
if(verbose) {
fprintf(stdout, "Creating temporary files...\r");
}
 
count = files;
while(run && --count > -1) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
return;
}
#endif
tmpNames[count] = CreateTemporaryFile();
 
if(verbose) {
fprintf(stdout, "Creating temporary files: %d%%\r", 100 - (int)(((float)count / files) * 100.0));
}
}
 
if(verbose) {
fprintf(stdout, "\n");
}
 
return tmpNames;
}
 
 
/*
*
* Skips a line in a file.
*/
if((database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*database[count]))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
free(entry->name);
free(entry->path);
free(entry);
free(line);
#if defined ___AsyncIO___
void SkipLine(struct AsyncFile *fp) {
LONG c;
while(run && (c = ReadCharAsync(fp)) != -1) {
CloseAsync(fp);
#else
void SkipLine(FILE *fp) {
char c;
while(run && fscanf(fp, "%c", &c) == 1) {
fclose(fp);
#endif
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
return;
}
#endif
switch(c) {
case '\n':
return;
}
}
}
 
/*
*
* Peeks at a line from a file.
*/
#if defined ___AsyncIO___
char *PeekLine(struct AsyncFile *fp) {
LONG c;
#else
char *PeekLine(FILE *fp) {
char c;
#endif
char *line = NULL;
char *real = NULL;
unsigned int size;
int i;
sprintf(database[count], "%s\t%s", entry->name, entry->path);
++count;
 
size = LINE_BUF;
if((line = malloc(size * sizeof(*line))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
}
// Free the database entry.
free(entry->name);
free(entry->path);
free(entry);
 
i = 0;
#if defined ___AsyncIO___
while(run && (c = ReadCharAsync(fp)) != -1) {
#else
while(run && fscanf(fp, "%c", &c) == 1) {
#endif
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
}
#endif
switch(c) {
case '\n':
// Rewind the file by the number of read characters.
#if defined ___AsyncIO___
if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) {
fprintf(stderr, "Could not seek in file.\n");
free(line);
return NULL;
}
#else
if(fseek(fp, -(i + 1), SEEK_CUR) != 0) {
fprintf(stderr, "Could not seek in file.\n");
free(line);
return NULL;
}
#endif
return line;
default:
if(strlen(line) == size) {
size = size * 1.5;
real = realloc(line, size * sizeof(*line));
if(real == NULL) {
fprintf(stderr, "Memory reallocation failure.\n");
free(line);
return NULL;
}
line = real;
}
line[i] = c;
line[i + 1] = '\0';
break;
}
++i;
}
 
if(line != NULL) {
free(line);
}
 
return NULL;
}
 
/*
*
* Read a line from a file.
*/
#if defined ___AsyncIO___
char *ReadLine(struct AsyncFile *fp) {
LONG c;
#else
char *ReadLine(FILE *fp) {
char c;
#endif
char *line = NULL;
char *real = NULL;
unsigned int size;
unsigned int i;
 
size = LINE_BUF;
if((line = malloc(size * sizeof(*line))) == NULL) {
fprintf(stderr, "Memory allication failure.\n");
return NULL;
}
 
i = 0;
#if defined ___AsyncIO___
while(run && (c = ReadCharAsync(fp)) != -1) {
#else
while(run && fscanf(fp, "%c", &c) == 1) {
#endif
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
}
#endif
switch(c) {
case '\n':
return line;
default:
if(strlen(line) == size) {
size = size * 1.5;
real = realloc(line, size * sizeof(*line));
if(real == NULL) {
fprintf(stderr, "Memory reallocation failure.\n");
free(line);
return NULL;
}
line = real;
}
line[i] = c;
line[i + 1] = '\0';
break;
}
++i;
}
 
if(line != NULL) {
free(line);
}
 
return NULL;
}
 
/*
*
* Delete a file.
*/
#if defined ___AmigaOS___
BOOL RemoveFile(char *name) {
return DeleteFile(name);
#else
int RemoveFile(char *name) {
return remove(name) == 0;
#endif
}
 
/*
*
* Deletes files.
*/
void RemoveFiles(char **names, int count) {
unsigned int i;
for(i = 0; i < count; ++i) {
if(RemoveFile(names[i]) == FALSE) {
fprintf(stderr, "Unable to remove %s...\n", names[i]);
continue;
}
fprintf(stderr, "Removing file: %s\n", names[i]);
}
}
 
/*
*
* Copies a file to another file by name.
*/
void CopyFile(char *a, char *b) {
#if defined ___AsyncIO___
struct AsyncFile *ap;
struct AsyncFile *bp;
LONG c;
CloseAsync(fp);
#else
FILE *ap;
FILE *bp;
char c;
fclose(fp);
#endif
 
// Open database file for writing.
#if defined ___AsyncIO___
if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) {
#else
if((ap = fopen(a, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", a);
return;
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Sorting %d lines in '%s'...\n", count, dbFile);
}
 
// Open temporary file for reading.
#if defined ___AsyncIO___
if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) {
#else
if((bp = fopen(b, "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open file '%s' for writing.\n", b);
// Sort the database.
qsort(database, (unsigned int)count, sizeof(char *), QsortCompare);
 
// Close database file.
#if defined ___AsyncIO___
CloseAsync(ap);
#else
fclose(ap);
#endif
 
return;
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Writing %d sorted lines to '%s'...\n", count, dbFile);
}
 
#if defined ___AsyncIO___
while(run && (c = ReadCharAsync(ap)) != -1) {
#else
while(run && fscanf(ap, "%c", &c) == 1) {
#endif
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
}
#endif
#if defined ___AsyncIO___
if(WriteCharAsync(bp, (UBYTE)c) != 1) {
#else
if(fprintf(bp, "%c", c) != 1) {
#endif
fprintf(stderr, "Unable to write to '%s'.\n", b);
break;
}
}
 
#if defined ___AsyncIO___
CloseAsync(ap);
CloseAsync(bp);
#else
fclose(ap);
fclose(bp);
#endif
}
 
/*
*
* Write lines to a file.
*/
void WriteLinesToFile(char *dbFile, char **lines, unsigned int count) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
#else
FILE *fp;
#endif
unsigned int i;
char *rem;
 
// Write the database lines back to the database.
#if defined ___AsyncIO___
if((fp = OpenAsync(dbFile, MODE_WRITE, ASYNC_BUF)) == NULL) {
@@ -623,16 +187,16 @@
#else
if((fp = fopen(dbFile, "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
return;
}
 
rem = NULL;
for(i = 0; i < count; ++i) {
for(i = 0; PROGRAM_RUN && i < count; ++i) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
@@ -639,9 +203,9 @@
 
if(rem != NULL) {
#if defined ___AmigaOS___
if(StrnCmp(locale, lines[i], rem, -1, SC_ASCII) == 0) {
if(StrnCmp(locale, database[i], rem, -1, SC_ASCII) == 0) {
#else
if(strcmp(lines[i], rem) == 0) {
if(strcmp(database[i], rem) == 0) {
#endif
continue;
}
@@ -648,10 +212,10 @@
}
 
#if defined ___AsyncIO___
WriteAsync(fp, lines[i], (LONG)strlen(lines[i]));
WriteAsync(fp, database[i], (LONG)strlen(database[i]));
WriteAsync(fp, "\n", 1);
#else
fprintf(fp, "%s\n", lines[i]);
fprintf(fp, "%s\n", database[i]);
#endif
 
if(rem != NULL) {
@@ -658,8 +222,8 @@
free(rem);
}
 
rem = malloc(strlen(lines[i]) + 1);
sprintf(rem, "%s", lines[i]);
rem = malloc((strlen(database[i]) + 1) * sizeof(*rem));
sprintf(rem, "%s", database[i]);
}
 
if(rem != NULL) {
@@ -671,214 +235,24 @@
#else
fclose(fp);
#endif
}
 
/*
*
* Create a database entry from a line of text.
*/
dbEntry* CreateDatabaseEntry(char *line) {
dbEntry *entry;
char *ptr;
unsigned int side;
unsigned int i;
unsigned int j;
 
if((entry = malloc(1 * sizeof(*entry))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Disposing %d lines of file '%s'...\n", count, dbFile);
}
 
if((entry->name = malloc((strlen(line) + 1) * sizeof(*entry->name))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
// Free up database.
for(i = 0; i < count; ++i) {
free(database[i]);
}
 
if((entry->path = malloc((strlen(line) + 1) * sizeof(*entry->path))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
return NULL;
}
 
for(ptr = line, side = 0, i = 0, j = 0; run && *ptr != '\0'; ++ptr) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
}
#endif
switch(*ptr) {
case '\t':
entry->name[i] = '\0';
++side;
break;
case '\n':
entry->path[j] = '\0';
return entry;
default:
switch(side) {
case 0:
entry->name[i++] = *ptr;
break;
case 1:
entry->path[j++] = *ptr;
break;
}
break;
}
}
 
return entry;
free(database);
}
 
/*
*
*
*/
dbArray *GetDatabaseArray(char *dbFile) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
#else
FILE *fp;
#endif
dbArray *array;
char **real = NULL;
dbEntry *entry;
char *line = NULL;
unsigned int count;
 
// Open database file for reading.
#if defined ___AsyncIO___
if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
#else
if((fp = fopen(dbFile, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
return NULL;
}
 
if((array = malloc(1 * sizeof(*array))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
return NULL;
}
 
count = 0;
while(run && (line = ReadLine(fp)) != NULL) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
continue;
}
#endif
if((entry = CreateDatabaseEntry(line)) == NULL) {
fprintf(stderr, "Unable to create database entry.\n");
free(line);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
return NULL;
}
 
// Load up the name and path into the database variable.
real = realloc(array->database, (count + 1) * sizeof(*array->database));
if(real == NULL) {
fprintf(stderr, "Memory reallocation failure.\n");
free(entry->name);
free(entry->path);
free(entry);
free(line);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
return NULL;
}
array->database = real;
 
if((array->database[count] = malloc((strlen(entry->name) + strlen(entry->path) + 1 + 1) * sizeof(*array->database[count]))) == NULL) {
fprintf(stderr, "Memory allocation failure.\n");
free(entry->name);
free(entry->path);
free(entry);
free(line);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
return NULL;
}
sprintf(array->database[count], "%s\t%s", entry->name, entry->path);
++count;
 
// Free the database entry.
free(entry->name);
free(entry->path);
free(entry);
 
free(line);
}
 
if(line != NULL) {
free(line);
}
 
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
 
array->count = count;
return array;
}
 
/*
*
* Sorts a database file lexicographically.
*/
void SortDatabase(char *dbFile) {
dbArray *array;
int i;
 
if(verbose) {
fprintf(stdout, "Sorting '%s'...\n", dbFile);
}
 
// Retrieve the database as an array.
if((array = GetDatabaseArray(dbFile)) == NULL) {
fprintf(stderr, "Unable to read '%s' as a database file.\n", dbFile);
return;
}
 
// Sort the database.
qsort(array->database, array->count, sizeof(char *), QsortCompare);
 
// Write back the database to the database file.
WriteLinesToFile(dbFile, array->database, array->count);
 
// Deallocate all the lines.
for(i = 0; i < array->count; ++i) {
free(array->database[i]);
}
 
free(array);
}
 
/*
*
* Updates a database file "dbFile".
*/
stats *CollectFiles(char *dbFile, char **paths, unsigned int count) {
dbStats *CollectFiles(char *dbFile, char **paths, int count) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
#else
@@ -885,8 +259,8 @@
FILE *fp;
#endif
#if defined ___AmigaOS___
struct FileInfoBlock *FIBp, *FIBq;
BPTR lockp, lockq;
struct FileInfoBlock *FIB;
BPTR lock;
#else
DIR *dir;
struct dirent *entry;
@@ -893,7 +267,7 @@
struct stat dirStat;
#endif
stringStack *stack;
stats *stats = NULL;
dbStats *stats = NULL;
int i;
char *path;
char *sub;
@@ -903,11 +277,11 @@
#else
if((fp = fopen(dbFile, "a")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
return NULL;
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Collecting files...\r");
}
 
@@ -924,18 +298,20 @@
 
stats->dirs = 0;
stats->files = 0;
stats->lines = 0;
stats->size = 0;
 
// Push the first path onto the stack.
stack = stringStackCreate(count);
for(i = 0; run && i < count; ++i) {
stack = stringStackCreate((unsigned int)count);
for(i = 0; PROGRAM_RUN && i < count; ++i) {
stringStackPush(stack, paths[i]);
}
 
while(run && !stringStackIsEmpty(stack)) {
while(PROGRAM_RUN && !stringStackIsEmpty(stack)) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
@@ -944,55 +320,55 @@
}
 
#if defined ___AmigaOS___
if((lockp = Lock(path, ACCESS_READ)) == NULL) {
if((lock = Lock(path, ACCESS_READ)) == NULL) {
fprintf(stderr, "Could not lock path '%s' for reading.\n", path);
free(path);
continue;
}
 
if((FIBp = AllocDosObject(DOS_FIB, NULL)) == NULL) {
fprintf(stderr, "Path '%s' info block allocation failure.\n", path);
UnLock(lockp);
if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
fprintf(stderr, "File information block for path '%s' could not be allocated.\n", path);
UnLock(lock);
free(path);
continue;
}
 
if(Examine(lockp, FIBp) == FALSE) {
if(Examine(lock, FIB) == FALSE) {
fprintf(stderr, "Path '%s' could not be examined.\n", path);
FreeDosObject(DOS_FIB, FIBp);
UnLock(lockp);
FreeDosObject(DOS_FIB, FIB);
UnLock(lock);
free(path);
continue;
}
 
while(run && ExNext(lockp, FIBp)) {
while(PROGRAM_RUN && ExNext(lock, FIB)) {
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#else
 
if((dir = opendir(path)) == NULL) {
fprintf(stderr, "Unable to open '%s' for reading.\n", path);
fprintf(stderr, "Directory '%s' could not be opened.\n", path);
free(path);
continue;
}
 
while(run && (entry = readdir(dir)) != NULL) {
while(PROGRAM_RUN && (entry = readdir(dir)) != NULL) {
#endif
switch(path[strlen(path) - 1]) {
case '/':
case ':': // This is a drive path.
#if defined ___AmigaOS___
if((sub = malloc(strlen(path) + strlen(FIBp->fib_FileName) + 1)) == NULL) {
if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1)) == NULL) {
#else
if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1)) == NULL) {
#endif
fprintf(stderr, "Memory allocation failure.\n");
#if defined ___AmigaOS___
FreeDosObject(DOS_FIB, FIBp);
UnLock(lockp);
FreeDosObject(DOS_FIB, FIB);
UnLock(lock);
#else
closedir(dir);
#endif
@@ -1006,7 +382,7 @@
return NULL;
}
#if defined ___AmigaOS___
sprintf(sub, "%s%s", path, FIBp->fib_FileName);
sprintf(sub, "%s%s", path, FIB->fib_FileName);
#else
sprintf(sub, "%s%s", path, entry->d_name);
#endif
@@ -1013,14 +389,14 @@
break;
default:
#if defined ___AmigaOS___
if((sub = malloc(strlen(path) + strlen(FIBp->fib_FileName) + 1 + 1)) == NULL) {
if((sub = malloc(strlen(path) + strlen(FIB->fib_FileName) + 1 + 1)) == NULL) {
#else
if((sub = malloc(strlen(path) + strlen(entry->d_name) + 1 + 1)) == NULL) {
#endif
fprintf(stderr, "Memory allocation failure.\n");
#if defined ___AmigaOS___
FreeDosObject(DOS_FIB, FIBp);
UnLock(lockp);
FreeDosObject(DOS_FIB, FIB);
UnLock(lock);
#else
closedir(dir);
#endif
@@ -1034,7 +410,7 @@
return NULL;
}
#if defined ___AmigaOS___
sprintf(sub, "%s/%s", path, FIBp->fib_FileName);
sprintf(sub, "%s/%s", path, FIB->fib_FileName);
#else
sprintf(sub, "%s/%s", path, entry->d_name);
#endif
@@ -1041,99 +417,77 @@
break;
}
 
switch(GetFsType(sub)) {
case UNKNOWN:
free(sub);
continue;
case REGULAR:
++stats->files;
 
#if defined ___AmigaOS___
if((lockq = Lock(sub, ACCESS_READ)) == NULL) {
fprintf(stderr, "Could not lock path '%s' for reading.\n", sub);
free(sub);
continue;
}
 
if((FIBq = AllocDosObject(DOS_FIB, NULL)) == NULL) {
fprintf(stderr, "Path '%s' info block allocation failure.\n", sub);
UnLock(lockq);
free(sub);
continue;
}
 
if(Examine(lockq, FIBq) == FALSE) {
fprintf(stderr, "Path '%s' could not be examined.\n", sub);
FreeDosObject(DOS_FIB, FIBq);
UnLock(lockq);
free(sub);
continue;
}
 
if(FIBq->fib_DirEntryType > 0) {
#else
stat(sub, &dirStat);
if(S_ISDIR(dirStat.st_mode)) {
#endif
stringStackPush(stack, sub);
 
++stats->dirs;
 
if(verbose) {
fprintf(stdout,
if(PROGRAM_VERBOSE) {
fprintf(stdout,
"Gathered %d directories and %d files.\r",
stats->dirs,
stats->files);
}
}
break;
case DIRECTORY:
stringStackPush(stack, sub);
 
#if defined ___AmigaOS___
FreeDosObject(DOS_FIB, FIBq);
UnLock(lockq);
#endif
free(sub);
continue;
}
++stats->dirs;
 
#if defined ___AmigaOS___
FreeDosObject(DOS_FIB, FIBq);
UnLock(lockq);
#endif
if(PROGRAM_VERBOSE) {
fprintf(stdout,
"Gathered %d directories and %d files.\r",
stats->dirs,
stats->files);
}
 
++stats->files;
free(sub);
continue;
}
 
if(verbose) {
fprintf(stdout,
"Gathered %d directories and %d files.\r",
stats->dirs,
stats->files);
}
 
#if defined ___NOCASE_FS___
#if defined ___AmigaOS___
strupr(FIBp->fib_FileName);
StrUpr(FIB->fib_FileName);
#else
strupr(entry->d_name);
StrUpr(entry->d_name);
#endif
#endif
 
 
// Write to database file.
#if defined ___AsyncIO___
#if defined ___AmigaOS___
WriteAsync(fp, FIBp->fib_FileName, (LONG)strlen(FIBp->fib_FileName));
WriteAsync(fp, FIB->fib_FileName, (LONG)strlen(FIB->fib_FileName));
stats->size = stats->size + strlen(FIB->fib_FileName);
#else
WriteAsync(fp, entry->d_name, (LONG)strlen(entry->d_name));
stats->size = stats->size + strlen(entry->d_name);
#endif
WriteAsync(fp, "\t", 1);
++stats->size;
WriteAsync(fp, sub, (LONG)strlen(sub));
stats->size = stats->size + strlen(sub);
WriteAsync(fp, "\n", 1);
++stats->size;
#else
#if defined ___AmigaOS___
fprintf(fp, "%s\t%s\n", FIBp->fib_FileName, sub);
fprintf(fp, "%s\t%s\n", FIB->fib_FileName, sub);
stats->size = stats->size + strlen(FIB->fib_FileName) + strlen(sub) + 1 + 1 + 1;
#else
fprintf(fp, "%s\t%s\n", entry->d_name, sub);
stats->size = stats->size + strlen(entry->d_name) + strlen(sub) + 1 + 1 + 1;
#endif
#endif
 
++stats->lines;
 
free(sub);
}
 
#if defined ___AmigaOS___
FreeDosObject(DOS_FIB, FIBp);
UnLock(lockp);
FreeDosObject(DOS_FIB, FIB);
UnLock(lock);
#else
closedir(dir);
#endif
@@ -1140,7 +494,7 @@
free(path);
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "\n");
}
 
@@ -1176,7 +530,7 @@
#else
if((fp = fopen(dbFile, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
return;
}
 
@@ -1185,7 +539,7 @@
#else
if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]);
fprintf(stderr, "Could not open file '%s' for writing.\n", tmpNames[tmpFiles]);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
@@ -1194,7 +548,7 @@
return;
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Writing to temporary files...\r");
}
 
@@ -1201,14 +555,14 @@
write = 0;
lines = 0;
#if defined ___AsyncIO___
while(run && (c = ReadCharAsync(fp)) != -1) {
while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
#else
while(run && fscanf(fp, "%c", &c) == 1) {
while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
#endif
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
@@ -1217,7 +571,7 @@
// Increment the total written lines.
++write;
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Writing to temporary files: %d%%.\r", (int)(((float)write / total) * 100.0));
}
 
@@ -1252,7 +606,7 @@
fclose(tp);
if((tp = fopen(tmpNames[--tmpFiles], "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", tmpNames[tmpFiles]);
fprintf(stderr, "Could not open '%s' for writing.\n", tmpNames[tmpFiles]);
#if defined ___AsyncIO___
CloseAsync(fp);
#else
@@ -1270,7 +624,7 @@
#else
if(fprintf(tp, "%c", c) != 1) {
#endif
fprintf(stderr, "Unable to write to '%s'.\n", tmpNames[tmpFiles]);
fprintf(stderr, "Could not write to file '%s'.\n", tmpNames[tmpFiles]);
#if defined ___AsyncIO___
CloseAsync(tp);
CloseAsync(fp);
@@ -1284,7 +638,7 @@
}
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "\n");
}
 
@@ -1309,8 +663,8 @@
FILE *fp;
FILE **tp;
#endif
unsigned int i;
unsigned int j;
int i;
int j;
char *tmp;
char *rem;
char *min;
@@ -1321,7 +675,7 @@
#else
if((fp = fopen(dbFile, "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", dbFile);
fprintf(stderr, "Could not open file '%s' for writing.\n", dbFile);
return;
}
 
@@ -1343,7 +697,7 @@
#else
if((tp[i] = fopen(tmpNames[i], "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", tmpNames[i]);
fprintf(stderr, "Could not open file '%s' for reading.\n", tmpNames[i]);
// Close all temporary files.
while(--i > -1) {
#if defined ___AsyncIO___
@@ -1361,7 +715,7 @@
}
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Merging all files...\r");
}
 
@@ -1368,16 +722,16 @@
rem = NULL;
count = lines;
j = 0;
while(run && --count > -1) {
while(PROGRAM_RUN && --count > -1) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
// Find the smallest line in all temporary files.
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Merging all files: %d%%.\r", 100 - (int)(((float)count / lines) * 100.0));
}
 
@@ -1397,7 +751,7 @@
free(min);
}
if((min = malloc((strlen(tmp) + 1) * sizeof(*min))) == NULL) {
fprintf(stderr, "Memory allication failure.\n");
fprintf(stderr, "Memory allocation failure.\n");
free(tmp);
if(min != NULL) {
free(min);
@@ -1468,11 +822,11 @@
}
 
// Write out any remaining contents from the temporary files.
for(i = 0; run && i < files; ++i) {
for(i = 0; PROGRAM_RUN && i < files; ++i) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
@@ -1498,15 +852,15 @@
#endif
}
 
if(verbose) {
fprintf(stdout, "\n");
}
 
#if defined ___AsyncIO___
CloseAsync(fp);
#else
fclose(fp);
#endif
 
if(PROGRAM_VERBOSE) {
fprintf(stdout, "\n");
}
}
 
/*
@@ -1513,7 +867,7 @@
*
* Filter the paths inside the database with provided paths.
*/
void FilterDatabasePaths(char *dbFile, char *tmpName, char **paths, unsigned int count) {
void FilterDatabasePaths(char *dbFile, char *tmpName, char **paths, int count) {
#if defined ___AsyncIO___
struct AsyncFile *fp;
struct AsyncFile *tp;
@@ -1522,7 +876,7 @@
FILE *tp;
#endif
char *line;
unsigned int lines;
int lines;
int i;
dbEntry *entry;
 
@@ -1532,7 +886,7 @@
#else
if((fp = fopen(dbFile, "r")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for reading.\n", dbFile);
fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
return;
}
 
@@ -1542,7 +896,7 @@
#else
if((tp = fopen(tmpName, "w")) == NULL) {
#endif
fprintf(stderr, "Unable to open '%s' for writing.\n", tmpName);
fprintf(stderr, "Copuld not open file '%s' for writing.\n", tmpName);
 
// Close database file.
#if defined ___AsyncIO___
@@ -1554,16 +908,16 @@
return;
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Removing lines...\r");
}
 
lines = 0;
while(run && (line = ReadLine(fp)) != NULL) {
while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
#if defined ___AmigaOS___
// Check if CTRL+C was pressed and abort the program.
if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
run = FALSE;
PROGRAM_RUN = FALSE;
continue;
}
#endif
@@ -1576,8 +930,8 @@
for(i = 0; i < count; ++i) {
if(PathCompare(entry->path, paths[i]) == TRUE) {
++lines;
if(verbose) {
fprintf(stdout, "Removing lines: %d\r", lines);
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Removing lines: %d.\r", lines);
}
continue;
}
@@ -1598,11 +952,6 @@
free(line);
}
 
if(verbose) {
fprintf(stdout, "\n");
}
 
 
#if defined ___AsyncIO___
CloseAsync(fp);
CloseAsync(tp);
@@ -1610,6 +959,10 @@
fclose(fp);
fclose(tp);
#endif
 
if(PROGRAM_VERBOSE) {
fprintf(stdout, "\n");
}
}
 
/*
@@ -1616,11 +969,9 @@
*
* Indexes a "path" by creating a database "dbFile".
*/
void GatherDatabaseFiles(char *dbFile, char **paths, unsigned int count) {
stats *stats;
void GatherDatabaseFiles(char *dbFile, char **paths, int count) {
dbStats *stats;
char **tmpNames;
int dbSize;
int dbLines;
int tmpFiles;
int tmpLines;
int i;
@@ -1630,30 +981,20 @@
fprintf(stderr, "Collecting files failed.\n");
return;
}
free(stats);
 
// Compute the amount of temporary files needed.
dbSize = GetFileSize(dbFile);
if(dbSize == -1) {
fprintf(stderr, "File size for '%s' failed.\n", dbFile);
return;
}
tmpFiles = dbSize / maxmem;
// Calculate the total number of temporary files required.
tmpFiles = stats->size / maxmem;
 
/* In case no temporary files are required,
* just sort the database and terminate.
*/
if(tmpFiles <= 1) {
SortDatabase(dbFile);
if(tmpFiles < 2) {
SortDatabase(dbFile, stats->lines);
return;
}
 
// Get the database metrics.
dbLines = CountFileLines(dbFile);
if(dbLines == -1) {
fprintf(stderr, "Counting lines of '%s' failed.\n", dbFile);
}
tmpLines = dbLines / tmpFiles;
// Calculate the number of lines per temporary file.
tmpLines = stats->lines / tmpFiles;
 
// Create temporary files.
if((tmpNames = CreateTemporaryFiles(tmpFiles)) == NULL) {
@@ -1662,15 +1003,16 @@
}
 
// Write "tmpLines" to temporary files in "tmpNames" from "dbFile".
WriteTemporaryFiles(dbFile, tmpNames, tmpFiles, tmpLines, dbLines);
WriteTemporaryFiles(dbFile, tmpNames, tmpFiles, tmpLines, stats->lines);
 
// Sort the temporary files.
for(i = 0; i < tmpFiles; ++i) {
SortDatabase(tmpNames[i]);
tmpLines = CountFileLines(tmpNames[i]);
SortDatabase(tmpNames[i], tmpLines);
}
 
// Merge all the temporary files to the database file.
MergeTemporaryFiles(dbFile, tmpNames, tmpFiles, dbLines);
MergeTemporaryFiles(dbFile, tmpNames, tmpFiles, stats->lines);
 
// Remove all temporary files.
RemoveFiles(tmpNames, tmpFiles);
@@ -1677,9 +1019,12 @@
 
// Free temporary file names.
free(tmpNames);
 
// Free statistics.
free(stats);
}
 
void RemoveDatabaseFiles(char *dbFile, char **paths, unsigned int count) {
void RemoveDatabaseFiles(char *dbFile, char **paths, int count) {
char *tmpName;
 
// Create a temporary file to hold the changes.
@@ -1728,18 +1073,13 @@
* Main entry point.
*/
int main(int argc, char **argv) {
#if defined ___AmigaOS___
struct FileInfoBlock *FIB;
BPTR lock;
#else
struct stat dirStat;
#endif
int option;
unsigned int i;
unsigned int count;
int i;
int count;
char *dbFile;
char *path;
char **paths;
OPERATION operation = NONE;
 
// Bind handler to SIGINT.
#if !defined ___AmigaOS___
@@ -1765,7 +1105,7 @@
dbFile = optarg;
break;
case 'q':
verbose = FALSE;
PROGRAM_VERBOSE = FALSE;
break;
case 'h':
usage(argv[0]);
@@ -1799,44 +1139,18 @@
continue;
}
 
// Check that the path is a directory.
#if defined ___AmigaOS___
if((lock = Lock(path, ACCESS_READ)) == NULL) {
fprintf(stderr, "Path '%s' is not accessible.\n", path);
free(path);
continue;
switch(GetFsType(path)) {
case UNKNOWN:
case REGULAR:
fprintf(stderr, "Path '%s' is not a directory.\n", path);
free(path);
continue;
break;
case DIRECTORY:
break;
}
 
if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
fprintf(stderr, "Path '%s' file information block not accessible.\n", path);
UnLock(lock);
free(path);
continue;
}
 
if(Examine(lock, FIB) == FALSE) {
fprintf(stderr, "Path '%s' information unexaminable.\n", path);
UnLock(lock);
FreeDosObject(DOS_FIB, FIB);
free(path);
continue;
}
 
if(FIB->fib_DirEntryType < 0) {
#else
stat(path, &dirStat);
if(!S_ISDIR(dirStat.st_mode)) {
#endif
fprintf(stderr, "Path '%s' is not a directory.\n", argv[optind]);
#if defined ___AmigaOS___
UnLock(lock);
FreeDosObject(DOS_FIB, FIB);
#endif
free(path);
return 1;
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Will process path: '%s'\n", path);
}
 
@@ -1849,10 +1163,6 @@
sprintf(paths[count], "%s", path);
++count;
 
#if defined ___AmigaOS___
UnLock(lock);
FreeDosObject(DOS_FIB, FIB);
#endif
free(path);
 
}
@@ -1863,7 +1173,7 @@
return 1;
}
 
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Gathering to: '%s'\n", dbFile);
}
 
@@ -1873,7 +1183,7 @@
 
switch(operation) {
case CREATE:
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Removing '%s' and creating a new database.\n", dbFile);
}
if(RemoveFile(dbFile) == FALSE) {
@@ -1881,13 +1191,13 @@
break;
}
case GATHER:
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Gathering files to database...\n");
}
GatherDatabaseFiles(dbFile, paths, count);
break;
case REMOVE:
if(verbose) {
if(PROGRAM_VERBOSE) {
fprintf(stdout, "Removing files from database...\n");
}
RemoveDatabaseFiles(dbFile, paths, count);
@@ -1903,10 +1213,5 @@
 
free(paths);
 
#if defined MWDEBUG
/* Generate a memory usage report */
MWReport("At end of main()", MWR_FULL);
#endif
 
return 0;
}