HuntnGather – Rev 15

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2021 Wizardry and Steamworks - License: MIT          //
///////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <signal.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <proto/dos.h>
#include <proto/exec.h>

#if !defined ___HAVE_GETOPT___
#include "getopt.h"
#endif

#if defined ___AmigaOS___
/*************************************************************************/
/*        Version string used for querrying the program version.         */
/*************************************************************************/
TEXT version_string[] =
        "\0$VER: Hunt 1.7 "__DATE__" by Wizardry and Steamworks";
#endif

#if !defined TRUE
#define TRUE 1;
#endif

#if !defined FALSE
#define FALSE 0;
#endif

#define NAME_BUF 32
#define PATH_BUF 128
#define DEFAULT_DATABASE_FILE "S:gather.db"

int run = TRUE;

void SignalHandler(int sig) {
        // Toggle the run flag to stop execution.
        run = FALSE;
}

/*
        * Compare "name" and "needle" for equality.
        */
int compare(char *name, char *need) {
#if defined ___AmigaOS___
        ULONG size;
        int success;
        UBYTE *pattern;

#if !defined ___NOCASE_FS___
        strupr(need);
        strupr(name);
#endif

        size = strlen(need) * 3;

        success = FALSE;

        if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {

                if(ParsePatternNoCase(need, pattern, (LONG)size) > 0) {
                        success = MatchPatternNoCase(pattern, name);

                        FreeVec(pattern);

                        return success;
                }

                FreeVec(pattern);
        }

        return success;
#else
        int success;

        success = FALSE;

#if !defined ___NOCASE_FS___
        strupr(need);
        strupr(name);
#endif

        success = (strstr(name, need) != NULL);

        free(upe);
        free(upn);
        return success;
#endif
}


/*
        *
        * Search the database for a matching string.
        */
void SearchDatabase(char *dbFile, char* need) {
        FILE *fp;
        char *name;
        int name_size;
        char *path;
        int path_size;
        char c;
        int i;
        int side;
        int match;
        int total;

        if((fp = fopen(dbFile, "r")) == NULL) {
                fprintf(stderr, "Unable to open gather database for reading.\n");
                return;
        }

        name_size = NAME_BUF;
        name = malloc(name_size * sizeof(char));
        path_size = PATH_BUF;
        path = malloc(path_size * sizeof(char));

        i = 0;
        side = 0;
        match = FALSE;
        total = 0;

        while(run && fscanf(fp, "%c", &c) == 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;
                        break;
                }
#endif

                switch(c) {
                        case '\n':
                                ++total;
                                if(match) {
                                        fprintf(stdout, "%s\n", path);
                                        match = FALSE;
                                }
                                if(name != NULL) {
                                        free(name);
                                        name_size = NAME_BUF;
                                        name = malloc(name_size * sizeof(char));
                                }
                                --side;
                                i = 0;
                                break;
                        case '\t':
                                // Case insensitive match.
                                if(compare(name, need)) {
                                        match = TRUE;
                                }
                                if(path != NULL) {
                                        free(path);
                                        path_size = PATH_BUF;
                                        path = malloc(path_size * sizeof(char));
                                }
                                ++side;
                                i = 0;
                                break;
                        default:
                                switch(side) {
                                        case 0:
                                                if(strlen(name) == name_size) {
                                                        name_size = 1.5 * name_size;
                                                        name = realloc(name, name_size * sizeof(char));
                                                }
                                                //name = realloc(name, (i + 1 + 1) * sizeof(char));
                                                name[i] = c;
                                                name[i + 1] = '\0';
                                                break;
                                        case 1:
                                                if(strlen(path) == path_size) {
                                                        path_size = 1.5 * path_size;
                                                        path = realloc(path, path_size * sizeof(char));
                                                }
                                                //path = realloc(path, (i + 1 + 1) * sizeof(char));
                                                path[i] = c;
                                                path[i + 1] = '\0';
                                                break;
                                        default:
                                                fprintf(stderr, "Database corrupted.\n");
                                                break;
                                }
                                ++i;
                                break;
                }
        }

        free(name);
        free(path);

        fclose(fp);
}

/*
        *
        * Search the database for the matching string.
        */
void Hunt(char *dbFile, char *need) {
        // Search the database for the matching string.
        SearchDatabase(dbFile, need);
}

void usage(char *name) {
        fprintf(stdout, "Hunt & Gather - %s, a file index search tool.            \n", name);
   fprintf(stdout, "                                                         \n");
        fprintf(stdout, "SYNTAX: %s [-d DATABASE] PATTERN                         \n", name);
   fprintf(stdout, "                                                         \n");
        fprintf(stdout, "    -d DATABASE    A path to a database generated by the \n");
        fprintf(stdout, "                   Gather tool that should be searched.  \n");
   fprintf(stdout, "                                                         \n");
        fprintf(stdout, "PATTERN is an AmigaOS DOS pattern to match file names.   \n");
        fprintf(stdout, "                                                         \n");
        fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT.                   \n");
}

int main(int argc, char **argv) {
        int option;
        char *dbFile;
        struct stat path;

        // Bind handler to SIGINT.
        signal(SIGINT, SignalHandler);

        dbFile = DEFAULT_DATABASE_FILE;
        while((option = getopt(argc, argv, "hd:")) != -1) {
                switch(option) {
                        case 'd':
                                dbFile = optarg;
                                break;
                        case 'h':
                                usage(argv[0]);
                                return 0;
                        case '?':
                                fprintf(stderr, "Invalid option %c.\n", optopt);;
                                return 1;
                }
        }

        if(optind >= argc) {
                usage(argv[0]);
                return 1;
        }

        stat(dbFile, &path);
        if(!S_ISREG(path.st_mode)) {
                fprintf(stderr, "Database file '%s' is not a file.\n", dbFile);
                return 1;
        }

        Hunt(dbFile, argv[optind]);

   return 0;
}