aboutsummaryrefslogtreecommitdiffstats
path: root/lib/canonicalize-lgpl.c
diff options
context:
space:
mode:
authorPaul Eggert2020-12-25 02:33:29 -0800
committerPaul Eggert2020-12-25 02:36:03 -0800
commit42d58264db165d265cba68d6dbebc53a50738355 (patch)
tree87543f2f0992a6b57a34dbd6ee04f48c3f6e7486 /lib/canonicalize-lgpl.c
parent5880c7caab394eac55c44d4be42b2f45dbd9bc53 (diff)
downloademacs-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.c213
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>
44typedef 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. */
105static bool
106file_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
126static bool _GL_ATTRIBUTE_PURE
127suffix_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
157static char const dir_suffix[] = "/";
158#else
159static 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
166static bool
167dir_check (char *dir, char *dirend)
168{
169 strcpy (dirend, dir_suffix);
170 return file_accessible (dir);
171}
172
96static idx_t 173static idx_t
97get_path_max (void) 174get_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. */
125char * 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
209static char *
210realpath_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
447char *
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}
358libc_hidden_def (__realpath) 457libc_hidden_def (__realpath)
359versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); 458versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
360#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */ 459#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */