diff options
| author | Paul Eggert | 2020-12-25 02:33:29 -0800 |
|---|---|---|
| committer | Paul Eggert | 2020-12-25 02:36:03 -0800 |
| commit | 42d58264db165d265cba68d6dbebc53a50738355 (patch) | |
| tree | 87543f2f0992a6b57a34dbd6ee04f48c3f6e7486 /lib/canonicalize-lgpl.c | |
| parent | 5880c7caab394eac55c44d4be42b2f45dbd9bc53 (diff) | |
| download | emacs-42d58264db165d265cba68d6dbebc53a50738355.tar.gz emacs-42d58264db165d265cba68d6dbebc53a50738355.zip | |
Update Gnulib.
All changes in this commit are autogenerated by running
admin/merge-gnulib.
Diffstat (limited to 'lib/canonicalize-lgpl.c')
| -rw-r--r-- | lib/canonicalize-lgpl.c | 213 |
1 files changed, 156 insertions, 57 deletions
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c index 584fce1cfa4..650d510f2d0 100644 --- a/lib/canonicalize-lgpl.c +++ b/lib/canonicalize-lgpl.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <stdlib.h> | 29 | #include <stdlib.h> |
| 30 | 30 | ||
| 31 | #include <errno.h> | 31 | #include <errno.h> |
| 32 | #include <fcntl.h> | ||
| 32 | #include <limits.h> | 33 | #include <limits.h> |
| 33 | #include <stdbool.h> | 34 | #include <stdbool.h> |
| 34 | #include <stddef.h> | 35 | #include <stddef.h> |
| @@ -36,23 +37,26 @@ | |||
| 36 | #include <sys/stat.h> | 37 | #include <sys/stat.h> |
| 37 | #include <unistd.h> | 38 | #include <unistd.h> |
| 38 | 39 | ||
| 40 | #include <eloop-threshold.h> | ||
| 41 | #include <filename.h> | ||
| 42 | #include <idx.h> | ||
| 39 | #include <scratch_buffer.h> | 43 | #include <scratch_buffer.h> |
| 40 | 44 | ||
| 41 | #ifdef _LIBC | 45 | #ifdef _LIBC |
| 42 | # include <eloop-threshold.h> | ||
| 43 | # include <shlib-compat.h> | 46 | # include <shlib-compat.h> |
| 44 | typedef ptrdiff_t idx_t; | 47 | # include <sysdep.h> |
| 45 | # define IDX_MAX PTRDIFF_MAX | 48 | # ifdef __ASSUME_FACCESSAT2 |
| 46 | # define FILE_SYSTEM_PREFIX_LEN(name) 0 | 49 | # define FACCESSAT_NEVER_EOVERFLOWS __ASSUME_FACCESSAT2 |
| 47 | # define IS_ABSOLUTE_FILE_NAME(name) ISSLASH(*(name)) | 50 | # else |
| 48 | # define ISSLASH(c) ((c) == '/') | 51 | # define FACCESSAT_NEVER_EOVERFLOWS true |
| 49 | # define freea(p) ((void) (p)) | 52 | # endif |
| 53 | # define GCC_LINT 1 | ||
| 54 | # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) | ||
| 50 | #else | 55 | #else |
| 51 | # define __canonicalize_file_name canonicalize_file_name | 56 | # define __canonicalize_file_name canonicalize_file_name |
| 52 | # define __realpath realpath | 57 | # define __realpath realpath |
| 53 | # include "idx.h" | ||
| 54 | # include "pathmax.h" | 58 | # include "pathmax.h" |
| 55 | # include "filename.h" | 59 | # define __faccessat faccessat |
| 56 | # if defined _WIN32 && !defined __CYGWIN__ | 60 | # if defined _WIN32 && !defined __CYGWIN__ |
| 57 | # define __getcwd _getcwd | 61 | # define __getcwd _getcwd |
| 58 | # elif HAVE_GETCWD | 62 | # elif HAVE_GETCWD |
| @@ -77,22 +81,95 @@ typedef ptrdiff_t idx_t; | |||
| 77 | # define __pathconf pathconf | 81 | # define __pathconf pathconf |
| 78 | # define __rawmemchr rawmemchr | 82 | # define __rawmemchr rawmemchr |
| 79 | # define __readlink readlink | 83 | # define __readlink readlink |
| 80 | # ifndef MAXSYMLINKS | 84 | # define __stat stat |
| 81 | # ifdef SYMLOOP_MAX | 85 | #endif |
| 82 | # define MAXSYMLINKS SYMLOOP_MAX | 86 | |
| 83 | # else | 87 | /* Suppress bogus GCC -Wmaybe-uninitialized warnings. */ |
| 84 | # define MAXSYMLINKS 20 | 88 | #if defined GCC_LINT || defined lint |
| 85 | # endif | 89 | # define IF_LINT(Code) Code |
| 86 | # endif | 90 | #else |
| 87 | # define __eloop_threshold() MAXSYMLINKS | 91 | # define IF_LINT(Code) /* empty */ |
| 88 | #endif | 92 | #endif |
| 89 | 93 | ||
| 90 | #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT | 94 | #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT |
| 91 | # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 | 95 | # define DOUBLE_SLASH_IS_DISTINCT_ROOT false |
| 96 | #endif | ||
| 97 | #ifndef FACCESSAT_NEVER_EOVERFLOWS | ||
| 98 | # define FACCESSAT_NEVER_EOVERFLOWS false | ||
| 92 | #endif | 99 | #endif |
| 93 | 100 | ||
| 94 | #if !FUNC_REALPATH_WORKS || defined _LIBC | 101 | #if !FUNC_REALPATH_WORKS || defined _LIBC |
| 95 | 102 | ||
| 103 | /* Return true if FILE's existence can be shown, false (setting errno) | ||
| 104 | otherwise. Follow symbolic links. */ | ||
| 105 | static bool | ||
| 106 | file_accessible (char const *file) | ||
| 107 | { | ||
| 108 | # if defined _LIBC || HAVE_FACCESSAT | ||
| 109 | int r = __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS); | ||
| 110 | # else | ||
| 111 | struct stat st; | ||
| 112 | int r = __stat (file, &st); | ||
| 113 | # endif | ||
| 114 | |||
| 115 | return ((!FACCESSAT_NEVER_EOVERFLOWS && r < 0 && errno == EOVERFLOW) | ||
| 116 | || r == 0); | ||
| 117 | } | ||
| 118 | |||
| 119 | /* True if concatenating END as a suffix to a file name means that the | ||
| 120 | code needs to check that the file name is that of a searchable | ||
| 121 | directory, since the canonicalize_filename_mode_stk code won't | ||
| 122 | check this later anyway when it checks an ordinary file name | ||
| 123 | component within END. END must either be empty, or start with a | ||
| 124 | slash. */ | ||
| 125 | |||
| 126 | static bool _GL_ATTRIBUTE_PURE | ||
| 127 | suffix_requires_dir_check (char const *end) | ||
| 128 | { | ||
| 129 | /* If END does not start with a slash, the suffix is OK. */ | ||
| 130 | while (ISSLASH (*end)) | ||
| 131 | { | ||
| 132 | /* Two or more slashes act like a single slash. */ | ||
| 133 | do | ||
| 134 | end++; | ||
| 135 | while (ISSLASH (*end)); | ||
| 136 | |||
| 137 | switch (*end++) | ||
| 138 | { | ||
| 139 | default: return false; /* An ordinary file name component is OK. */ | ||
| 140 | case '\0': return true; /* Trailing "/" is trouble. */ | ||
| 141 | case '.': break; /* Possibly "." or "..". */ | ||
| 142 | } | ||
| 143 | /* Trailing "/.", or "/.." even if not trailing, is trouble. */ | ||
| 144 | if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1])))) | ||
| 145 | return true; | ||
| 146 | } | ||
| 147 | |||
| 148 | return false; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Append this to a file name to test whether it is a searchable directory. | ||
| 152 | On POSIX platforms "/" suffices, but "/./" is sometimes needed on | ||
| 153 | macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on | ||
| 154 | platforms like AIX 7.2 that need at least "/.". */ | ||
| 155 | |||
| 156 | #if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK | ||
| 157 | static char const dir_suffix[] = "/"; | ||
| 158 | #else | ||
| 159 | static char const dir_suffix[] = "/./"; | ||
| 160 | #endif | ||
| 161 | |||
| 162 | /* Return true if DIR is a searchable dir, false (setting errno) otherwise. | ||
| 163 | DIREND points to the NUL byte at the end of the DIR string. | ||
| 164 | Store garbage into DIREND[0 .. strlen (dir_suffix)]. */ | ||
| 165 | |||
| 166 | static bool | ||
| 167 | dir_check (char *dir, char *dirend) | ||
| 168 | { | ||
| 169 | strcpy (dirend, dir_suffix); | ||
| 170 | return file_accessible (dir); | ||
| 171 | } | ||
| 172 | |||
| 96 | static idx_t | 173 | static idx_t |
| 97 | get_path_max (void) | 174 | get_path_max (void) |
| 98 | { | 175 | { |
| @@ -111,19 +188,27 @@ get_path_max (void) | |||
| 111 | return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX; | 188 | return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX; |
| 112 | } | 189 | } |
| 113 | 190 | ||
| 114 | /* Return the canonical absolute name of file NAME. A canonical name | 191 | /* Act like __realpath (see below), with an additional argument |
| 115 | does not contain any ".", ".." components nor any repeated file name | 192 | rname_buf that can be used as temporary storage. |
| 116 | separators ('/') or symlinks. All file name components must exist. If | 193 | |
| 117 | RESOLVED is null, the result is malloc'd; otherwise, if the | 194 | If GCC_LINT is defined, do not inline this function with GCC 10.1 |
| 118 | canonical name is PATH_MAX chars or more, returns null with 'errno' | 195 | and later, to avoid creating a pointer to the stack that GCC |
| 119 | set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, | 196 | -Wreturn-local-addr incorrectly complains about. See: |
| 120 | returns the name in RESOLVED. If the name cannot be resolved and | 197 | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644 |
| 121 | RESOLVED is non-NULL, it contains the name of the first component | 198 | Although the noinline attribute can hurt performance a bit, no better way |
| 122 | that cannot be resolved. If the name can be resolved, RESOLVED | 199 | to pacify GCC is known; even an explicit #pragma does not pacify GCC. |
| 123 | holds the same value as the value returned. */ | 200 | When the GCC bug is fixed this workaround should be limited to the |
| 124 | 201 | broken GCC versions. */ | |
| 125 | char * | 202 | #if __GNUC_PREREQ (10, 1) |
| 126 | __realpath (const char *name, char *resolved) | 203 | # if defined GCC_LINT || defined lint |
| 204 | __attribute__ ((__noinline__)) | ||
| 205 | # elif __OPTIMIZE__ && !__NO_INLINE__ | ||
| 206 | # define GCC_BOGUS_WRETURN_LOCAL_ADDR | ||
| 207 | # endif | ||
| 208 | #endif | ||
| 209 | static char * | ||
| 210 | realpath_stk (const char *name, char *resolved, | ||
| 211 | struct scratch_buffer *rname_buf) | ||
| 127 | { | 212 | { |
| 128 | char *dest; | 213 | char *dest; |
| 129 | char const *start; | 214 | char const *start; |
| @@ -149,8 +234,6 @@ __realpath (const char *name, char *resolved) | |||
| 149 | } | 234 | } |
| 150 | 235 | ||
| 151 | struct scratch_buffer extra_buffer, link_buffer; | 236 | struct scratch_buffer extra_buffer, link_buffer; |
| 152 | struct scratch_buffer rname_buffer; | ||
| 153 | struct scratch_buffer *rname_buf = &rname_buffer; | ||
| 154 | scratch_buffer_init (&extra_buffer); | 237 | scratch_buffer_init (&extra_buffer); |
| 155 | scratch_buffer_init (&link_buffer); | 238 | scratch_buffer_init (&link_buffer); |
| 156 | scratch_buffer_init (rname_buf); | 239 | scratch_buffer_init (rname_buf); |
| @@ -208,7 +291,9 @@ __realpath (const char *name, char *resolved) | |||
| 208 | name ends in '/'. */ | 291 | name ends in '/'. */ |
| 209 | idx_t startlen = end - start; | 292 | idx_t startlen = end - start; |
| 210 | 293 | ||
| 211 | if (startlen == 1 && start[0] == '.') | 294 | if (startlen == 0) |
| 295 | break; | ||
| 296 | else if (startlen == 1 && start[0] == '.') | ||
| 212 | /* nothing */; | 297 | /* nothing */; |
| 213 | else if (startlen == 2 && start[0] == '.' && start[1] == '.') | 298 | else if (startlen == 2 && start[0] == '.' && start[1] == '.') |
| 214 | { | 299 | { |
| @@ -226,7 +311,8 @@ __realpath (const char *name, char *resolved) | |||
| 226 | if (!ISSLASH (dest[-1])) | 311 | if (!ISSLASH (dest[-1])) |
| 227 | *dest++ = '/'; | 312 | *dest++ = '/'; |
| 228 | 313 | ||
| 229 | while (rname + rname_buf->length - dest <= startlen) | 314 | while (rname + rname_buf->length - dest |
| 315 | < startlen + sizeof dir_suffix) | ||
| 230 | { | 316 | { |
| 231 | idx_t dest_offset = dest - rname; | 317 | idx_t dest_offset = dest - rname; |
| 232 | if (!scratch_buffer_grow_preserve (rname_buf)) | 318 | if (!scratch_buffer_grow_preserve (rname_buf)) |
| @@ -238,28 +324,19 @@ __realpath (const char *name, char *resolved) | |||
| 238 | dest = __mempcpy (dest, start, startlen); | 324 | dest = __mempcpy (dest, start, startlen); |
| 239 | *dest = '\0'; | 325 | *dest = '\0'; |
| 240 | 326 | ||
| 241 | /* If STARTLEN == 0, RNAME ends in '/'; use stat rather than | 327 | char *buf; |
| 242 | readlink, because readlink might fail with EINVAL without | ||
| 243 | checking whether RNAME sans '/' is valid. */ | ||
| 244 | struct stat st; | ||
| 245 | char *buf = NULL; | ||
| 246 | ssize_t n; | 328 | ssize_t n; |
| 247 | if (startlen != 0) | 329 | while (true) |
| 248 | { | 330 | { |
| 249 | while (true) | 331 | buf = link_buffer.data; |
| 250 | { | 332 | idx_t bufsize = link_buffer.length; |
| 251 | buf = link_buffer.data; | 333 | n = __readlink (rname, buf, bufsize - 1); |
| 252 | idx_t bufsize = link_buffer.length; | 334 | if (n < bufsize - 1) |
| 253 | n = __readlink (rname, buf, bufsize - 1); | 335 | break; |
| 254 | if (n < bufsize - 1) | 336 | if (!scratch_buffer_grow (&link_buffer)) |
| 255 | break; | 337 | goto error_nomem; |
| 256 | if (!scratch_buffer_grow (&link_buffer)) | ||
| 257 | goto error_nomem; | ||
| 258 | } | ||
| 259 | if (n < 0) | ||
| 260 | buf = NULL; | ||
| 261 | } | 338 | } |
| 262 | if (buf) | 339 | if (0 <= n) |
| 263 | { | 340 | { |
| 264 | if (++num_links > __eloop_threshold ()) | 341 | if (++num_links > __eloop_threshold ()) |
| 265 | { | 342 | { |
| @@ -270,7 +347,7 @@ __realpath (const char *name, char *resolved) | |||
| 270 | buf[n] = '\0'; | 347 | buf[n] = '\0'; |
| 271 | 348 | ||
| 272 | char *extra_buf = extra_buffer.data; | 349 | char *extra_buf = extra_buffer.data; |
| 273 | idx_t end_idx; | 350 | idx_t end_idx IF_LINT (= 0); |
| 274 | if (end_in_extra_buffer) | 351 | if (end_in_extra_buffer) |
| 275 | end_idx = end - extra_buf; | 352 | end_idx = end - extra_buf; |
| 276 | idx_t len = strlen (end); | 353 | idx_t len = strlen (end); |
| @@ -315,8 +392,8 @@ __realpath (const char *name, char *resolved) | |||
| 315 | dest++; | 392 | dest++; |
| 316 | } | 393 | } |
| 317 | } | 394 | } |
| 318 | else if (! (startlen == 0 | 395 | else if (! (suffix_requires_dir_check (end) |
| 319 | ? stat (rname, &st) == 0 || errno == EOVERFLOW | 396 | ? dir_check (rname, dest) |
| 320 | : errno == EINVAL)) | 397 | : errno == EINVAL)) |
| 321 | goto error; | 398 | goto error; |
| 322 | } | 399 | } |
| @@ -355,6 +432,28 @@ error_nomem: | |||
| 355 | char *result = realloc (rname, rname_size); | 432 | char *result = realloc (rname, rname_size); |
| 356 | return result != NULL ? result : rname; | 433 | return result != NULL ? result : rname; |
| 357 | } | 434 | } |
| 435 | |||
| 436 | /* Return the canonical absolute name of file NAME. A canonical name | ||
| 437 | does not contain any ".", ".." components nor any repeated file name | ||
| 438 | separators ('/') or symlinks. All file name components must exist. If | ||
| 439 | RESOLVED is null, the result is malloc'd; otherwise, if the | ||
| 440 | canonical name is PATH_MAX chars or more, returns null with 'errno' | ||
| 441 | set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, | ||
| 442 | returns the name in RESOLVED. If the name cannot be resolved and | ||
| 443 | RESOLVED is non-NULL, it contains the name of the first component | ||
| 444 | that cannot be resolved. If the name can be resolved, RESOLVED | ||
| 445 | holds the same value as the value returned. */ | ||
| 446 | |||
| 447 | char * | ||
| 448 | __realpath (const char *name, char *resolved) | ||
| 449 | { | ||
| 450 | #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR | ||
| 451 | #warning "GCC might issue a bogus -Wreturn-local-addr warning here." | ||
| 452 | #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>." | ||
| 453 | #endif | ||
| 454 | struct scratch_buffer rname_buffer; | ||
| 455 | return realpath_stk (name, resolved, &rname_buffer); | ||
| 456 | } | ||
| 358 | libc_hidden_def (__realpath) | 457 | libc_hidden_def (__realpath) |
| 359 | versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); | 458 | versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); |
| 360 | #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */ | 459 | #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */ |