Mercurial > gnulib
changeset 38782:b119238632f2
glob: simplify symlink detection
* lib/glob.c (dirent_type): New type. Use uint_fast8_t not
uint8_t, as C99 does not require uint8_t.
(DT_UNKNOWN, DT_DIR, DT_LNK) [!HAVE_STRUCT_DIRENT_D_TYPE]:
New macros.
(struct readdir_result): Use dirent_type. Do not define skip_entry
unless it is needed; this saves a byte on platforms lacking d_ino.
(readdir_result_type, readdir_result_skip_entry):
New functions, replacing ...
(readdir_result_might_be_symlink, readdir_result_might_be_dir):
... these functions, which were removed. This makes the callers
easier to read. All callers changed.
(D_INO_TO_RESULT): Now empty if there is no d_ino.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Thu, 31 Aug 2017 14:34:24 -0700 |
parents | 23b092891b25 |
children | 939112530b4c |
files | ChangeLog lib/glob.c |
diffstat | 2 files changed, 54 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Aug 30 22:32:23 2017 -0700 +++ b/ChangeLog Thu Aug 31 14:34:24 2017 -0700 @@ -1,3 +1,17 @@ +2017-08-31 Paul Eggert <eggert@cs.ucla.edu> + + glob: simplify symlink detection + * lib/glob.c (dirent_type): New type. Use uint_fast8_t not + uint8_t, as C99 does not require uint8_t. + (struct readdir_result): Use it. Do not define skip_entry unless + it is needed; this saves a byte on platforms lacking d_ino. + (readdir_result_type, readdir_result_skip_entry): + New functions, replacing ... + (readdir_result_might_be_symlink, readdir_result_might_be_dir): + ... these functions, which were removed. This makes the callers + easier to read. All callers changed. + (D_INO_TO_RESULT): Now empty if there is no d_ino. + 2017-08-30 Pádraig Brady <P@draigBrady.com> fts-tests: tag as a longrunning-test so not included by default
--- a/lib/glob.c Wed Aug 30 22:32:23 2017 -0700 +++ b/lib/glob.c Thu Aug 31 14:34:24 2017 -0700 @@ -92,61 +92,59 @@ static const char *next_brace_sub (const char *begin, int flags) __THROWNL; +typedef uint_fast8_t dirent_type; + +#ifndef HAVE_STRUCT_DIRENT_D_TYPE +/* Any distinct values will do here. + Undef any existing macros out of the way. */ +# undef DT_UNKNOWN +# undef DT_DIR +# undef DT_LNK +# define DT_UNKNOWN 0 +# define DT_DIR 1 +# define DT_LNK 2 +#endif + /* A representation of a directory entry which does not depend on the layout of struct dirent, or the size of ino_t. */ struct readdir_result { const char *name; #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE - uint8_t type; + dirent_type type; #endif +#if defined _LIBC || defined D_INO_IN_DIRENT bool skip_entry; +#endif }; +/* Initialize and return type member of struct readdir_result. */ +static dirent_type +readdir_result_type (struct readdir_result d) +{ #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE -/* Initializer based on the d_type member of struct dirent. */ # define D_TYPE_TO_RESULT(source) (source)->d_type, - -/* True if the directory entry D might be a symbolic link. */ -static bool -readdir_result_might_be_symlink (struct readdir_result d) -{ - return d.type == DT_UNKNOWN || d.type == DT_LNK; + return d.type; +#else +# define D_TYPE_TO_RESULT(source) + return DT_UNKNOWN; +#endif } -/* True if the directory entry D might be a directory. */ -static bool -readdir_result_might_be_dir (struct readdir_result d) -{ - return d.type == DT_DIR || readdir_result_might_be_symlink (d); -} -#else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ -# define D_TYPE_TO_RESULT(source) - -/* If we do not have type information, symbolic links and directories - are always a possibility. */ - +/* Initialize and return skip_entry member of struct readdir_result. */ static bool -readdir_result_might_be_symlink (struct readdir_result d) +readdir_result_skip_entry (struct readdir_result d) { - return true; -} - -static bool -readdir_result_might_be_dir (struct readdir_result d) -{ - return true; -} - -#endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ - /* Initializer for skip_entry. POSIX does not require that the d_ino field be present, and some systems do not provide it. */ #if defined _LIBC || defined D_INO_IN_DIRENT # define D_INO_TO_RESULT(source) (source)->d_ino == 0, + return d.skip_entry; #else -# define D_INO_TO_RESULT(source) false, +# define D_INO_TO_RESULT(source) + return false; #endif +} /* Construct an initializer for a struct readdir_result object from a struct dirent *. No copy of the name is made. */ @@ -1545,19 +1543,24 @@ } if (d.name == NULL) break; - if (d.skip_entry) + if (readdir_result_skip_entry (d)) continue; /* If we shall match only directories use the information provided by the dirent call if possible. */ - if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d)) - continue; + if (flags & GLOB_ONLYDIR) + switch (readdir_result_type (d)) + { + case DT_DIR: case DT_LNK: case DT_UNKNOWN: break; + default: continue; + } if (fnmatch (pattern, d.name, fnm_flags) == 0) { /* If the file we found is a symlink we have to make sure the target file exists. */ - if (!readdir_result_might_be_symlink (d) + dirent_type type = readdir_result_type (d); + if (! (type == DT_LNK || type == DT_UNKNOWN) || link_exists_p (dfd, directory, dirlen, d.name, pglob, flags)) {