diff --git a/packages/base/any/onlp/src/onlplib/module/inc/onlplib/file.h b/packages/base/any/onlp/src/onlplib/module/inc/onlplib/file.h index ff1a6ca9..250047c3 100644 --- a/packages/base/any/onlp/src/onlplib/module/inc/onlplib/file.h +++ b/packages/base/any/onlp/src/onlplib/module/inc/onlplib/file.h @@ -141,6 +141,9 @@ int onlp_file_open(int flags, int log, const char* fmt, ...); int onlp_file_vopen(int flags, int log, const char* fmt, va_list vargs); - +/** + * @brief Search a directory tree for the given file. + */ +int onlp_file_find(char* root, char* fname, char** rpath); #endif /* __ONLPLIB_FILE_H__ */ diff --git a/packages/base/any/onlp/src/onlplib/module/src/file.c b/packages/base/any/onlp/src/onlplib/module/src/file.c index d0adce8e..1380c2f4 100644 --- a/packages/base/any/onlp/src/onlplib/module/src/file.c +++ b/packages/base/any/onlp/src/onlplib/module/src/file.c @@ -23,6 +23,7 @@ * ***********************************************************/ #include +#include "onlplib_log.h" #include #include #include @@ -74,8 +75,25 @@ vopen__(char** dst, int flags, const char* fmt, va_list vargs) int fd; struct stat sb; char fname[PATH_MAX]; + char* asterisk; ONLPLIB_VSNPRINTF(fname, sizeof(fname)-1, fmt, vargs); + + /** + * An asterisk in the filename separates a search root + * directory from a filename. + */ + if( (asterisk = strchr(fname, '*')) ) { + char* root = fname; + char* rpath = NULL; + *asterisk = 0; + if(onlp_file_find(root, asterisk+1, &rpath) < 0) { + return ONLP_STATUS_E_MISSING; + } + strcpy(fname, rpath); + aim_free(rpath); + } + if(dst) { *dst = aim_strdup(fname); } @@ -282,3 +300,40 @@ onlp_file_vopen(int flags, int log, const char* fmt, va_list vargs) aim_free(fname); return rv; } + +#include +#include +#include +#include + +int +onlp_file_find(char* root, char* fname, char** rpath) +{ + FTS *fs; + FTSENT *ent; + char* argv[] = { NULL, NULL }; + argv[0] = root; + + if ((fs = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_COMFOLLOW, + NULL)) == NULL) { + AIM_LOG_ERROR("fts_open(%s): %{errno}", argv[0], errno); + return ONLP_STATUS_E_INTERNAL; + } + + while ((ent = fts_read(fs)) != NULL) { + switch (ent->fts_info) + { + case FTS_F: + { + if(!strcmp(fname, ent->fts_name)) { + *rpath = realpath(ent->fts_path, NULL); + fts_close(fs); + return ONLP_STATUS_OK; + } + } + break; + } + } + fts_close(fs); + return ONLP_STATUS_E_MISSING; +}