|
|
Message-ID: <20190806020320.GR9017@brightrain.aerifal.cx>
Date: Mon, 5 Aug 2019 22:03:20 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: [PATCH] In glob(), do not require that the target of a
symlink exists.
On Mon, Jul 22, 2019 at 08:37:38PM -0400, James Y Knight wrote:
> Previously, when given a trailing path component with no
> metacharacters, glob would call stat to check if the provided filename
> existed, which would fail on a broken symlink. When expanding a
> pattern however, glob would trust the list of files returned by
> readdir, and thus would return broken symlinks.
>
> Now, be consistent and allow broken symlinks in both cases, by using
> lstat to determine file existence.
>
> If GLOB_MARK is specified, stat must still be used to determine
> whether a given name refers to a directory or file. But if that fails,
> a symlink is simply considered to be a file for marking purposes.
> From 7ef0fabf173f4d29461b01ccfb05c1f19977ba37 Mon Sep 17 00:00:00 2001
> From: James Y Knight <jyknight@...gle.com>
> Date: Thu, 11 Jul 2019 16:55:17 -0400
> Subject: [PATCH] In glob(), do not require that the target of a symlink
> exists.
>
> Previously, when given a trailing path component with no
> metacharacters, glob would call stat to check if the provided filename
> existed, which would fail on a broken symlink. When expanding a
> pattern however, glob would trust the list of files returned by
> readdir, and thus would return broken symlinks.
>
> Now, be consistent and allow broken symlinks in both cases, by using
> lstat to determine file existence.
>
> If GLOB_MARK is specified, stat must still be used to determine
> whether a given name refers to a directory or file. But if that fails,
> a symlink is simply considered to be a file for marking purposes.
> ---
> src/regex/glob.c | 35 +++++++++++++++++++++++++----------
> 1 file changed, 25 insertions(+), 10 deletions(-)
>
> diff --git a/src/regex/glob.c b/src/regex/glob.c
> index aa1c6a44..01b178dc 100644
> --- a/src/regex/glob.c
> +++ b/src/regex/glob.c
> @@ -88,18 +88,33 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*
> }
> buf[pos] = 0;
> if (!*pat) {
> - /* If we consumed any components above, or if GLOB_MARK is
> - * requested and we don't yet know if the match is a dir,
> - * we must call stat to confirm the file exists and/or
> - * determine its type. */
> + /* If we're in at the end of the pattern, check if the file
> + * exists. And, if GLOB_MARK is requested, determine if it's a
> + * directory. */
This is one of the comment changes I was confused about; it seems less
informative. The point of the original comment was not describing the
controlling expression just above it, but the conditions on not being
able to use the caller-passed type -- having consumed any new literal
components from the pattern above is what precludes it.
> struct stat st;
> - if ((flags & GLOB_MARK) && type==DT_LNK) type = 0;
> - if (!type && stat(buf, &st)) {
> - if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR)))
> - return GLOB_ABORTED;
> - return 0;
> + if (flags & GLOB_MARK) {
> + /* We need to know if the name refers to a directory
> + * (after resolving symlinks).
> + *
> + * However, broken symlinks should be considered to be a
> + * file, rather than non-existent or an error, so if
> + * stat fails, we just don't modify type. (And lstat
> + * will be called below if required.)
> + */
> + if ((!type || type==DT_LNK) && stat(buf, &st) == 0) {
!stat
> + if(S_ISDIR(st.st_mode)) type = DT_DIR;
> + else type = DT_REG;
> + }
> + }
> + if (!type) {
> + /* If we're don't already know that the file exists,
> + * confirm its presence. */
> + if (lstat(buf, &st)) {
This could be "!type && lstat(..." to avoid the excessively long lines
below and to better mimic the old structure so that stylistic change
doesn't obscure reading of functional change.
Now that I look at it, the same applies to the above too.
> + if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR)))
> + return GLOB_ABORTED;
> + return 0;
> + }
> }
> - if (!type && S_ISDIR(st.st_mode)) type = DT_DIR;
> if (append(tail, buf, pos, (flags & GLOB_MARK) && type==DT_DIR))
> return GLOB_NOSPACE;
> return 0;
> --
> 2.22.0.657.g960e92d24f-goog
>
Otherwise I think this looks ok.
Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.