HuntnGather – Rev 49

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if !defined ___AmigaOS___
#include <signal.h>
#include <dirent.h>
#include <sys/stat.h>
#endif

#include <sys/types.h>

#if defined ___AmigaOS___

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

#if defined ___AsyncIO___
#include <asyncio.h>
#endif

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

#include "/shared/utilities.h"

#define PROGRAM_VERSION "1.7.6"

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

int PROGRAM_RUN = TRUE;
int PROGRAM_VERBOSE = FALSE;

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

/*
        *
        * Search the database for a matching string.
        */
void SearchDatabaseExact(char *dbFile, char *needle) {
#if defined ___AsyncIO___
        struct AsyncFile *fp;
#else
        FILE *fp;
#endif
        dbEntry *entry;
        dbLine *line = NULL;

        // 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, "Could not open file '%s' for reading.\n", dbFile);
                return;
        }

        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) {
                        PROGRAM_RUN = FALSE;
                        continue;
                }
#endif

                if((entry = CreateDatabaseEntry(line)) == NULL) {
                        fprintf(stderr, "Unable to create database entry.\n");
                        free(line->string);
                        free(line);
                        line = NULL;

#if defined ___AsyncIO___
                        CloseAsync(fp);
#else
                        fclose(fp);
#endif
                        return;
                }

#if defined ___AmigaOS___
#if defined ___NOCASE_FS___
                if(Strnicmp(entry->name, needle, StringLenMax(entry->name, needle)) == 0) {
#else
                if(StrnCmp(entry->name, needle, StringLenMax(entry->name, needle)) == 0) {
#endif
#else
                if(strstr(entry->name, needle) != NULL) {
#endif
                        fprintf(stdout, "%s\n", entry->path);
                }

                free(entry->name);
                free(entry->path);
                free(entry);
                entry = NULL;

                free(line->string);
                free(line);
                line = NULL;
        }

        if(line != NULL) {
                free(line->string);
                free(line);
                line = NULL;
        }

#if defined ___AsyncIO___
        CloseAsync(fp);
#else
        fclose(fp);
#endif
}

/*
        *
        * Search the database for a matching string.
        */
void SearchDatabasePattern(char *dbFile, UBYTE *pattern) {
#if defined ___AsyncIO___
        struct AsyncFile *fp;
#else
        FILE *fp;
#endif
        dbEntry *entry;
        dbLine *line = NULL;

        // 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, "Could not open file '%s' for reading.\n", dbFile);
                return;
        }

        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) {
                        PROGRAM_RUN = FALSE;
                        continue;
                }
#endif

                if((entry = CreateDatabaseEntry(line)) == NULL) {
                        fprintf(stderr, "Unable to create database entry.\n");
                        free(line->string);
                        free(line);
                        line = NULL;

#if defined ___AsyncIO___
                        CloseAsync(fp);
#else
                        fclose(fp);
#endif
                        return;
                }

                if(MatchPatternNoCase(pattern, entry->name)) {
                        fprintf(stdout, "%s\n", entry->path);
                }

                free(entry->name);
                free(entry->path);
                free(entry);
                entry = NULL;

                free(line->string);
                free(line);
                line = NULL;
        }

        if(line != NULL) {
                free(line->string);
                free(line);
                line = NULL;
        }

#if defined ___AsyncIO___
        CloseAsync(fp);
#else
        fclose(fp);
#endif
}

/*
        *
        * Search the database for the matching string.
        */
void Hunt(char *dbFile, char *needle) {
#if defined ___AmigaOS___
        UBYTE *pattern;
        ULONG size;

#if defined ___NOCASE_FS___
        StrUpr(needle);
#endif

        size = strlen(needle) * 2 + 2;

        if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {
                switch(ParsePatternNoCase(needle, pattern, (LONG)size)) {
                        case 1: // the needle contains wildcards
                                SearchDatabasePattern(dbFile, pattern);
                                break;
                        case 0: // no wildcards contained in needle
                                SearchDatabaseExact(dbFile, needle);
                                break;
                        case -1: // overflow condition
                                fprintf(stderr, "Pattern '%s' could not be parsed.\n", needle);
                                break;
                }
                FreeVec(pattern);
                pattern = NULL;
                return;
        }
#endif

        // Search the database for the matching string.
        SearchDatabaseExact(dbFile, needle);
}

void usage(char *name) {
        fprintf(stdout, "Hunt & Gather - %s, a file index search tool.            \n", name);
        fprintf(stdout, "Version: %s                                              \n", PROGRAM_VERSION);
   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;

        // Bind handler to SIGINT.
#if !defined ___AmigaOS___
        signal(SIGINT, SignalHandler);
#endif

        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 5;
                }
        }

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

        switch(GetFsType(dbFile)) {
                case UNKNOWN:
                case DIRECTORY:
                        fprintf(stderr, "'%s' is not a file.\n", dbFile);
                        return 10;
                case REGULAR:
                        Hunt(dbFile, argv[optind]);
                        break;
        }

   return 0;
}