From e2b9f432f0297e59d8bbac78989ab60e2b43f749 Mon Sep 17 00:00:00 2001 From: Peter Haag Date: Sun, 15 Oct 2023 13:21:28 +0200 Subject: [PATCH] Add multiple dir wildcard '@' for multiple dir argument -M --- man/nfdump.1 | 4 ++- src/lib/flist.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/man/nfdump.1 b/man/nfdump.1 index db8fa77c..121778d6 100755 --- a/man/nfdump.1 +++ b/man/nfdump.1 @@ -718,7 +718,9 @@ Read the same file hierarchy from multiple directories. This option is mainly us old NfSen and documented here as legacy option. Example: /any/path/to/dir1:dir2:dir3 etc. and will be expanded to the directories: /any/path/to/dir1, /any/path/to/dir2 and /any/path/to/dir3. Any number of colon separated -directories may be given. The files to read are specified by -r or -R and are expected to +directories may be given. A path ending with a wildcard '@' such as /any/path/to@ will +expand automatically in a list of all existing sub directories /any/path/to/dir1:dir2:dir3. +The files to read are specified by -r or -R and are expected to exist in all the given directories. The options -r and -R must not contain any directories when used in combination with -M. .It Fl T diff --git a/src/lib/flist.c b/src/lib/flist.c index f5fc858c..701dbff0 100755 --- a/src/lib/flist.c +++ b/src/lib/flist.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2022, Peter Haag + * Copyright (c) 2009-2023, Peter Haag * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung * All rights reserved. * @@ -219,8 +219,12 @@ static void Getsource_dirs(char *dirs); static int mkpath(char *path, char *p, mode_t mode, mode_t dir_mode, char *error, size_t errlen); +static char *SubDirList(char *path); + static char *GuessSubDir(char *channeldir, char *filename); +static char *ExpandWildcard(char *path); + static char *VerifyFileRange(char *path, char *last_file); static void *FileLister_thr(void *arg); @@ -363,6 +367,79 @@ static void CreateDirListFilter(char *first_path, char *last_path, int file_list } // End of CreateDirListFilter +static char *SubDirList(char *path) { + char *dirList = NULL; + struct dirent *dent; + DIR *srcdir = opendir(path); + + if (srcdir == NULL) { + LogError("opendir() - can not open directory %s", path); + return NULL; + } + + while ((dent = readdir(srcdir)) != NULL) { + struct stat st; + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; + + if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) { + LogError("fstatat() - can not stat %s", dent->d_name); + continue; + } + + if (S_ISDIR(st.st_mode)) { + if (dirList == NULL) { + dirList = strdup(dent->d_name); + } else { + size_t len = strlen(dirList) + strlen(dent->d_name) + 2; + dirList = realloc(dirList, len); + if (dirList == NULL) { + LogError("realloc() error in %s line %d: %s", __FILE__, __LINE__, strerror(errno)); + return NULL; + } + strcat(dirList, ":"); + strcat(dirList, dent->d_name); + } + } + } + closedir(srcdir); + return dirList; +} // Endof SubDirList + +/* + * Check for directory wildcard: + * path: /any/path/dir@ + * if wildcard is found - extend to directory list: + * /any/path/dir/dir1:dir2:dir3:dirN + * returns expanded directory string or NULL if no wildcard found + */ +static char *ExpandWildcard(char *path) { + char *q = strchr(path, ':'); + size_t dirLen = strlen(path); + int wildcard = path[dirLen - 1] == '@'; + + if (q && wildcard) { + LogError("Can not process wildcard '@' and dirlist ':' in %s", path); + LogError("Remove wildcard"); + path[dirLen - 1] = '\0'; + return NULL; + } + if (wildcard == 0) return NULL; + + // remove '@' and replace it by '/' + path[dirLen - 1] = '/'; + char *dirList = SubDirList(path); + if (dirList == NULL) { + LogError("Can not expand wildcard in %s", path); + return NULL; + } + path = realloc(path, strlen(path) + strlen(dirList) + 1); + if (path == NULL) { + LogError("realloc() error in %s line %d: %s", __FILE__, __LINE__, strerror(errno)); + return NULL; + } + return strcat(path, dirList); +} // End of ExpandWildcard + static void GetFileList(char *path, timeWindow_t *timeWindow) { struct stat stat_buf; char *last_file_ptr, *first_path, *last_path; @@ -847,7 +924,13 @@ static void *FileLister_thr(void *arg) { last_file = NULL; InitStringlist(&source_dirs, NUM_PTR); - if (flist->multiple_dirs) Getsource_dirs(flist->multiple_dirs); + if (flist->multiple_dirs) { + char *expanded = ExpandWildcard(flist->multiple_dirs); + if (expanded) { + flist->multiple_dirs = expanded; + } + Getsource_dirs(flist->multiple_dirs); + } if (flist->multiple_files) { // use multiple files