enumerator: Enumerate glob(3) matches using gl_pathc

While glob should return a NULL terminated gl_pathv when having no matches,
at least on OS X this is not true when using GLOB_DOOFFS. Rely on the
number of matches returned in gl_pathc, which seems to be more reliable in
error cases.
This commit is contained in:
Martin Willi
2014-07-07 16:14:17 +02:00
parent 44870e5313
commit c1490c649a
+6 -9
View File
@@ -171,8 +171,8 @@ typedef struct {
enumerator_t public; enumerator_t public;
/** glob data */ /** glob data */
glob_t glob; glob_t glob;
/** current match */ /** iteration count */
char **match; u_int pos;
/** absolute path of current file */ /** absolute path of current file */
char full[PATH_MAX]; char full[PATH_MAX];
} glob_enum_t; } glob_enum_t;
@@ -191,12 +191,13 @@ static void destroy_glob_enum(glob_enum_t *this)
*/ */
static bool enumerate_glob_enum(glob_enum_t *this, char **file, struct stat *st) static bool enumerate_glob_enum(glob_enum_t *this, char **file, struct stat *st)
{ {
char *match = *(++this->match); char *match;
if (!match) if (this->pos >= this->glob.gl_pathc)
{ {
return FALSE; return FALSE;
} }
match = this->glob.gl_pathv[this->pos++];
if (file) if (file)
{ {
*file = match; *file = match;
@@ -231,12 +232,9 @@ enumerator_t* enumerator_create_glob(const char *pattern)
.enumerate = (void*)enumerate_glob_enum, .enumerate = (void*)enumerate_glob_enum,
.destroy = (void*)destroy_glob_enum, .destroy = (void*)destroy_glob_enum,
}, },
.glob = {
.gl_offs = 1, /* reserve one slot so we can enumerate easily */
}
); );
status = glob(pattern, GLOB_DOOFFS | GLOB_ERR, NULL, &this->glob); status = glob(pattern, GLOB_ERR, NULL, &this->glob);
if (status == GLOB_NOMATCH) if (status == GLOB_NOMATCH)
{ {
DBG1(DBG_LIB, "no files found matching '%s'", pattern); DBG1(DBG_LIB, "no files found matching '%s'", pattern);
@@ -246,7 +244,6 @@ enumerator_t* enumerator_create_glob(const char *pattern)
DBG1(DBG_LIB, "expanding file pattern '%s' failed: %s", pattern, DBG1(DBG_LIB, "expanding file pattern '%s' failed: %s", pattern,
strerror(errno)); strerror(errno));
} }
this->match = this->glob.gl_pathv;
return &this->public; return &this->public;
} }