# HG changeset patch # User Matti Hamalainen # Date 1531143968 -10800 # Node ID d26bc1adfd1463d17574fbb28d0bc4b8229360ff # Parent 72c415154700a3fe677d0ca12e2bf05830b69be2 Add internal directory reading and filename matching, plus optional subdirectory recursion via '-R' option. diff -r 72c415154700 -r d26bc1adfd14 Makefile.gen --- 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) diff -r 72c415154700 -r d26bc1adfd14 sidinfo.c --- 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 +#include #ifdef HAVE_ICONV # include #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)