changeset 191:d26bc1adfd14

Add internal directory reading and filename matching, plus optional subdirectory recursion via '-R' option.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 09 Jul 2018 16:46:08 +0300
parents 72c415154700
children c0849f47e10f
files Makefile.gen sidinfo.c
diffstat 2 files changed, 114 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Mon Jul 09 09:42:33 2018 +0300
+++ b/Makefile.gen	Mon Jul 09 16:46:08 2018 +0300
@@ -8,7 +8,7 @@
 # Objects
 #
 THLIBS_OBJ=th_util.o th_string.o th_ioctx.o \
-	th_args.o th_crypto.o th_datastruct.o
+	th_file.o th_args.o th_crypto.o th_datastruct.o
 
 SIDINFO_OBJ=sidlib.o sidinfo.o
 SIDINFO_BIN=$(BINPATH)sidinfo$(EXEEXT)
--- a/sidinfo.c	Mon Jul 09 09:42:33 2018 +0300
+++ b/sidinfo.c	Mon Jul 09 16:46:08 2018 +0300
@@ -8,6 +8,8 @@
 #include "th_file.h"
 #include "th_datastruct.h"
 #include "sidlib.h"
+#include <sys/types.h>
+#include <dirent.h>
 #ifdef HAVE_ICONV
 #  include <iconv.h>
 #endif
@@ -99,7 +101,8 @@
         optParsable = FALSE,
         optNoNamePrefix = FALSE,
         optHexadecimal = FALSE,
-        optFieldOutput = TRUE;
+        optFieldOutput = TRUE,
+        optRecurseDirs = FALSE;
 char    *optOneLineFieldSep = NULL,
         *optEscapeChars = NULL;
 int     optNFiles = 0;
@@ -130,6 +133,7 @@
     { 7, 'F', "format",     "Use given format string (see below)", OPT_ARGREQ },
     { 8, 'H', "hvsc",       "Specify path to HVSC documents directory", OPT_ARGREQ },
     { 9, 'S', "sldb",       "Specify Songlengths.txt file (use -H if possible)", OPT_ARGREQ },
+    {12, 'R', "recurse",    "Recurse into sub-directories", OPT_NONE },
 };
 
 static const int optListN = sizeof(optList) / sizeof(optList[0]);
@@ -726,6 +730,10 @@
         optEscapeChars = optArg;
         break;
 
+    case 12:
+        optRecurseDirs = TRUE;
+        break;
+
     default:
         THERR("Unknown option '%s'.\n", currArg);
         return FALSE;
@@ -970,7 +978,7 @@
 }
 
 
-BOOL argHandleFile(char *filename)
+BOOL siHandleSIDFile(const char *filename)
 {
     PSIDHeader *psid = NULL;
     th_ioctx *inFile = NULL;
@@ -978,7 +986,6 @@
     BOOL shown = FALSE;
     int res;
 
-    optNFiles++;
     outFile = stdout;
 
     if ((res = th_io_fopen(&inFile, &th_stdio_io_ops, filename, "rb")) != THERR_OK)
@@ -1032,6 +1039,107 @@
 }
 
 
+BOOL argHandleFileDir(const char *path, const char *filename, const char *pattern)
+{
+    th_stat_data sdata;
+    char *npath;
+    BOOL ret = TRUE;
+
+    if (filename != NULL)
+        npath = th_strdup_printf("%s%c%s", path, TH_DIR_SEPARATOR, filename);
+    else
+        npath = th_strdup(path);
+
+    if (!th_stat_path(npath, &sdata))
+    {
+        THERR("File or path '%s' does not exist.\n", npath);
+        ret = FALSE;
+        goto out;
+    }
+
+    optNFiles++;
+
+    if (sdata.flags & TH_IS_DIR)
+    {
+        DIR *dirh;
+        struct dirent *entry;
+
+        // Check if recursion is disabled
+        if (!optRecurseDirs && optNFiles > 1)
+            goto out;
+
+        if ((dirh = opendir(npath)) == NULL)
+        {
+            int err = th_get_error();
+            THERR("Could not open directory '%s': %s\n",
+                path, th_error_str(err));
+            ret = FALSE;
+            goto out;
+        }
+
+        while ((entry = readdir(dirh)) != NULL)
+        if (entry->d_name[0] != '.')
+        {
+            if (!argHandleFileDir(npath, entry->d_name, pattern))
+            {
+                ret = FALSE;
+                goto out;
+            }
+        }
+
+        closedir(dirh);
+    }
+    else
+    if (pattern == NULL || th_strmatch(filename, pattern))
+    {
+        siHandleSIDFile(npath);
+    }
+
+out:
+    th_free(npath);
+    return ret;
+}
+
+
+BOOL argHandleFile(char *path)
+{
+    char *pattern = NULL, *filename = NULL, *pt, *npath = th_strdup(path);
+    BOOL ret;
+
+    if (npath == NULL)
+        return FALSE;
+
+    // Check if we have path separators
+    if ((pt = strrchr(npath, '/')) != NULL ||
+        (pt = strrchr(npath, '\\')) != NULL)
+    {
+        *pt++ = 0;
+    }
+    else
+    {
+        th_free(npath);
+        npath = th_strdup(".");
+        pt = strcmp(path, npath) != 0 ? path : NULL;
+    }
+
+    // Check if we have glob pattern chars
+    if (pt != NULL && *pt != 0)
+    {
+        if (strchr(pt, '*') || strchr(pt, '?'))
+            pattern = th_strdup(pt);
+        else
+            filename = th_strdup(pt);
+    }
+
+    ret = argHandleFileDir(npath, filename, pattern);
+
+    th_free(pattern);
+    th_free(npath);
+    th_free(filename);
+    return ret;
+}
+
+
 int main(int argc, char *argv[])
 {
     // Initialize
@@ -1059,7 +1167,7 @@
 
     // Parse command line arguments
     if (!th_args_process(argc, argv, optList, optListN,
-        argHandleOpt, argHandleFile, OPTH_ONLY_OPTS))
+        argHandleOpt, NULL, OPTH_ONLY_OPTS))
         return -1;
 
     if (optOneLineFieldSep != NULL)
@@ -1137,7 +1245,7 @@
 
     // Process files
     if (!th_args_process(argc, argv, optList, optListN,
-        argHandleOpt, argHandleFile, OPTH_ONLY_OTHER))
+        NULL, argHandleFile, OPTH_ONLY_OTHER))
         goto out;
 
     if (optNFiles == 0)