This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit c6b8afe7992eaedd1be9ee41cb0dca4c2aa0b28e Author: Marco Casaroli <[email protected]> AuthorDate: Fri Oct 23 16:37:14 2026 +0200 libs/libc/misc: Add GLOB_TILDE and GLOB_TILDE_CHECK to glob(). Programs from other systems use glob() with GLOB_TILDE to find files in a home directory, for example "~/.config/name", and did not compile. A "~" at the start of the pattern is the value of HOME, or else the home directory of the user in the password database. "~name" is the home directory of the user name. When the home directory is not known, GLOB_TILDE uses the pattern as it is, and GLOB_TILDE_CHECK returns GLOB_NOMATCH, as in other C libraries. The flags have the values of glibc and musl. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- include/glob.h | 8 +++ libs/libc/misc/lib_glob.c | 121 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/include/glob.h b/include/glob.h index cb4de40fa2e..731bd27dc96 100644 --- a/include/glob.h +++ b/include/glob.h @@ -50,6 +50,14 @@ #define GLOB_NOESCAPE 0x20 /* Disable backslash escaping. */ #define GLOB_NOSORT 0x40 /* Do not sort the pathnames returned. */ +/* Extensions, with the values of other C libraries: */ + +#define GLOB_TILDE 0x1000 /* Expand a "~" or "~name" at the start + * of the pattern to a home directory. */ +#define GLOB_TILDE_CHECK 0x4000 /* As GLOB_TILDE, but fail with + * GLOB_NOMATCH if the home directory is + * not known. */ + /* The following constants shall be defined as error return values: */ diff --git a/libs/libc/misc/lib_glob.c b/libs/libc/misc/lib_glob.c index 9514f0da9c3..cd0c2de0118 100644 --- a/libs/libc/misc/lib_glob.c +++ b/libs/libc/misc/lib_glob.c @@ -58,6 +58,7 @@ static int do_glob(FAR char *buf, size_t pos, int type, FAR char *pat, int flags, CODE int (*errfunc)(FAR const char *path, int err), FAR struct match_s **tail); +static int glob_home(FAR const char *user, FAR char *home); static int ignore_err(FAR const char *path, int err); static void freelist(FAR struct match_s *head); static int sort(FAR const void *a, FAR const void *b); @@ -403,6 +404,73 @@ static int sort(FAR const void *a, FAR const void *b) return strcmp(*(FAR const char**)a, *(FAR const char**)b); } +/**************************************************************************** + * Name: glob_home + * + * Description: + * Copy the home directory of a user to home (PATH_MAX bytes). An empty + * user name is the calling user: then HOME is used when it is set, else + * the password database. + * + * Returned Value: + * Zero on success, GLOB_NOMATCH when the home directory is not known, + * GLOB_NOSPACE when there is no memory. + * + ****************************************************************************/ + +static int glob_home(FAR const char *user, FAR char *home) +{ + FAR const char *dir = NULL; + FAR struct passwd *entry = NULL; + FAR char *pwbuf = NULL; + struct passwd pwd; + int ret = 0; + + if (user[0] == '\0') + { + dir = getenv("HOME"); + } + + if (dir == NULL) + { + pwbuf = lib_get_tempbuffer(NSS_BUFLEN_PASSWD); + if (pwbuf == NULL) + { + return GLOB_NOSPACE; + } + + if (user[0] == '\0') + { + ret = getpwuid_r(getuid(), &pwd, pwbuf, NSS_BUFLEN_PASSWD, &entry); + } + else + { + ret = getpwnam_r(user, &pwd, pwbuf, NSS_BUFLEN_PASSWD, &entry); + } + + if (ret == 0 && entry != NULL) + { + dir = entry->pw_dir; + } + } + + if (dir == NULL) + { + ret = ret == ENOMEM ? GLOB_NOSPACE : GLOB_NOMATCH; + } + else if (strlcpy(home, dir, PATH_MAX) >= PATH_MAX - 1) + { + ret = GLOB_NOMATCH; + } + + if (pwbuf != NULL) + { + lib_put_tempbuffer(pwbuf); + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -459,7 +527,58 @@ int glob(FAR const char *pat, int flags, buf[0] = 0; s = p; - error = do_glob(buf, pos, 0, s, flags, errfunc, &tail); + /* "~" or "~user" at the start of the pattern: the home directory + * goes to buf, and the rest of the pattern after the "/" is matched + * in it. + */ + + if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) != 0 && s[0] == '~') + { + FAR char *slash = strchr(s, '/'); + + if (slash != NULL) + { + *slash = '\0'; + } + + error = glob_home(s + 1, buf); + if (error == 0) + { + pos = strlen(buf); + if (slash != NULL) + { + buf[pos++] = '/'; + buf[pos] = '\0'; + s = slash + 1; + } + else + { + s += strlen(s); + } + } + else + { + /* Without GLOB_TILDE_CHECK an unknown home directory is not + * an error: the pattern is used as it is. + */ + + if (slash != NULL) + { + *slash = '/'; + } + + buf[0] = '\0'; + if (error == GLOB_NOMATCH && (flags & GLOB_TILDE_CHECK) == 0) + { + error = 0; + } + } + } + + if (error == 0) + { + error = do_glob(buf, pos, 0, s, flags, errfunc, &tail); + } lib_free(p); }
