Bump to m4 1.4.19
[platform/upstream/m4.git] / lib / canonicalize-lgpl.c
1 /* Return the canonical absolute name of a given file.
2    Copyright (C) 1996-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public
7    License as published by the Free Software Foundation; either
8    version 3 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #ifndef _LIBC
20 /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
21    optimizes away the name == NULL test below.  */
22 # define _GL_ARG_NONNULL(params)
23
24 # include <libc-config.h>
25 #endif
26
27 /* Specification.  */
28 #include <stdlib.h>
29
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #include <stdbool.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #include <eloop-threshold.h>
39 #include <filename.h>
40 #include <idx.h>
41 #include <intprops.h>
42 #include <scratch_buffer.h>
43
44 #ifdef _LIBC
45 # include <shlib-compat.h>
46 # define GCC_LINT 1
47 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
48 #else
49 # define __canonicalize_file_name canonicalize_file_name
50 # define __realpath realpath
51 # include "pathmax.h"
52 # define __faccessat faccessat
53 # if defined _WIN32 && !defined __CYGWIN__
54 #  define __getcwd _getcwd
55 # elif HAVE_GETCWD
56 #  if IN_RELOCWRAPPER
57     /* When building the relocatable program wrapper, use the system's getcwd
58        function, not the gnulib override, otherwise we would get a link error.
59      */
60 #   undef getcwd
61 #  endif
62 #  if defined VMS && !defined getcwd
63     /* We want the directory in Unix syntax, not in VMS syntax.
64        The gnulib override of 'getcwd' takes 2 arguments; the original VMS
65        'getcwd' takes 3 arguments.  */
66 #   define __getcwd(buf, max) getcwd (buf, max, 0)
67 #  else
68 #   define __getcwd getcwd
69 #  endif
70 # else
71 #  define __getcwd(buf, max) getwd (buf)
72 # endif
73 # define __mempcpy mempcpy
74 # define __pathconf pathconf
75 # define __rawmemchr rawmemchr
76 # define __readlink readlink
77 # define __stat stat
78 # if IN_RELOCWRAPPER
79     /* When building the relocatable program wrapper, use the system's memmove
80        function, not the gnulib override, otherwise we would get a link error.
81      */
82 #  undef memmove
83 # endif
84 #endif
85
86 /* Suppress bogus GCC -Wmaybe-uninitialized warnings.  */
87 #if defined GCC_LINT || defined lint
88 # define IF_LINT(Code) Code
89 #else
90 # define IF_LINT(Code) /* empty */
91 #endif
92
93 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
94 # define DOUBLE_SLASH_IS_DISTINCT_ROOT false
95 #endif
96
97 #if defined _LIBC || !FUNC_REALPATH_WORKS
98
99 /* Return true if FILE's existence can be shown, false (setting errno)
100    otherwise.  Follow symbolic links.  */
101 static bool
102 file_accessible (char const *file)
103 {
104 # if defined _LIBC || HAVE_FACCESSAT
105   return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
106 # else
107   struct stat st;
108   return __stat (file, &st) == 0 || errno == EOVERFLOW;
109 # endif
110 }
111
112 /* True if concatenating END as a suffix to a file name means that the
113    code needs to check that the file name is that of a searchable
114    directory, since the canonicalize_filename_mode_stk code won't
115    check this later anyway when it checks an ordinary file name
116    component within END.  END must either be empty, or start with a
117    slash.  */
118
119 static bool _GL_ATTRIBUTE_PURE
120 suffix_requires_dir_check (char const *end)
121 {
122   /* If END does not start with a slash, the suffix is OK.  */
123   while (ISSLASH (*end))
124     {
125       /* Two or more slashes act like a single slash.  */
126       do
127         end++;
128       while (ISSLASH (*end));
129
130       switch (*end++)
131         {
132         default: return false;  /* An ordinary file name component is OK.  */
133         case '\0': return true; /* Trailing "/" is trouble.  */
134         case '.': break;        /* Possibly "." or "..".  */
135         }
136       /* Trailing "/.", or "/.." even if not trailing, is trouble.  */
137       if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
138         return true;
139     }
140
141   return false;
142 }
143
144 /* Append this to a file name to test whether it is a searchable directory.
145    On POSIX platforms "/" suffices, but "/./" is sometimes needed on
146    macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
147    platforms like AIX 7.2 that need at least "/.".  */
148
149 # if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
150 static char const dir_suffix[] = "/";
151 # else
152 static char const dir_suffix[] = "/./";
153 # endif
154
155 /* Return true if DIR is a searchable dir, false (setting errno) otherwise.
156    DIREND points to the NUL byte at the end of the DIR string.
157    Store garbage into DIREND[0 .. strlen (dir_suffix)].  */
158
159 static bool
160 dir_check (char *dir, char *dirend)
161 {
162   strcpy (dirend, dir_suffix);
163   return file_accessible (dir);
164 }
165
166 static idx_t
167 get_path_max (void)
168 {
169 # ifdef PATH_MAX
170   long int path_max = PATH_MAX;
171 # else
172   /* The caller invoked realpath with a null RESOLVED, even though
173      PATH_MAX is not defined as a constant.  The glibc manual says
174      programs should not do this, and POSIX says the behavior is undefined.
175      Historically, glibc here used the result of pathconf, or 1024 if that
176      failed; stay consistent with this (dubious) historical practice.  */
177   int err = errno;
178   long int path_max = __pathconf ("/", _PC_PATH_MAX);
179   __set_errno (err);
180 # endif
181   return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
182 }
183
184 /* Act like __realpath (see below), with an additional argument
185    rname_buf that can be used as temporary storage.
186
187    If GCC_LINT is defined, do not inline this function with GCC 10.1
188    and later, to avoid creating a pointer to the stack that GCC
189    -Wreturn-local-addr incorrectly complains about.  See:
190    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
191    Although the noinline attribute can hurt performance a bit, no better way
192    to pacify GCC is known; even an explicit #pragma does not pacify GCC.
193    When the GCC bug is fixed this workaround should be limited to the
194    broken GCC versions.  */
195 # if __GNUC_PREREQ (10, 1)
196 #  if defined GCC_LINT || defined lint
197 __attribute__ ((__noinline__))
198 #  elif __OPTIMIZE__ && !__NO_INLINE__
199 #   define GCC_BOGUS_WRETURN_LOCAL_ADDR
200 #  endif
201 # endif
202 static char *
203 realpath_stk (const char *name, char *resolved,
204               struct scratch_buffer *rname_buf)
205 {
206   char *dest;
207   char const *start;
208   char const *end;
209   int num_links = 0;
210
211   if (name == NULL)
212     {
213       /* As per Single Unix Specification V2 we must return an error if
214          either parameter is a null pointer.  We extend this to allow
215          the RESOLVED parameter to be NULL in case the we are expected to
216          allocate the room for the return value.  */
217       __set_errno (EINVAL);
218       return NULL;
219     }
220
221   if (name[0] == '\0')
222     {
223       /* As per Single Unix Specification V2 we must return an error if
224          the name argument points to an empty string.  */
225       __set_errno (ENOENT);
226       return NULL;
227     }
228
229   struct scratch_buffer extra_buffer, link_buffer;
230   scratch_buffer_init (&extra_buffer);
231   scratch_buffer_init (&link_buffer);
232   scratch_buffer_init (rname_buf);
233   char *rname_on_stack = rname_buf->data;
234   char *rname = rname_on_stack;
235   bool end_in_extra_buffer = false;
236   bool failed = true;
237
238   /* This is always zero for Posix hosts, but can be 2 for MS-Windows
239      and MS-DOS X:/foo/bar file names.  */
240   idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
241
242   if (!IS_ABSOLUTE_FILE_NAME (name))
243     {
244       while (!__getcwd (rname, rname_buf->length))
245         {
246           if (errno != ERANGE)
247             {
248               dest = rname;
249               goto error;
250             }
251           if (!scratch_buffer_grow (rname_buf))
252             goto error_nomem;
253           rname = rname_buf->data;
254         }
255       dest = __rawmemchr (rname, '\0');
256       start = name;
257       prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
258     }
259   else
260     {
261       dest = __mempcpy (rname, name, prefix_len);
262       *dest++ = '/';
263       if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
264         {
265           if (prefix_len == 0 /* implies ISSLASH (name[0]) */
266               && ISSLASH (name[1]) && !ISSLASH (name[2]))
267             *dest++ = '/';
268           *dest = '\0';
269         }
270       start = name + prefix_len;
271     }
272
273   for ( ; *start; start = end)
274     {
275       /* Skip sequence of multiple file name separators.  */
276       while (ISSLASH (*start))
277         ++start;
278
279       /* Find end of component.  */
280       for (end = start; *end && !ISSLASH (*end); ++end)
281         /* Nothing.  */;
282
283       /* Length of this file name component; it can be zero if a file
284          name ends in '/'.  */
285       idx_t startlen = end - start;
286
287       if (startlen == 0)
288         break;
289       else if (startlen == 1 && start[0] == '.')
290         /* nothing */;
291       else if (startlen == 2 && start[0] == '.' && start[1] == '.')
292         {
293           /* Back up to previous component, ignore if at root already.  */
294           if (dest > rname + prefix_len + 1)
295             for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
296               continue;
297           if (DOUBLE_SLASH_IS_DISTINCT_ROOT
298               && dest == rname + 1 && !prefix_len
299               && ISSLASH (*dest) && !ISSLASH (dest[1]))
300             dest++;
301         }
302       else
303         {
304           if (!ISSLASH (dest[-1]))
305             *dest++ = '/';
306
307           while (rname + rname_buf->length - dest
308                  < startlen + sizeof dir_suffix)
309             {
310               idx_t dest_offset = dest - rname;
311               if (!scratch_buffer_grow_preserve (rname_buf))
312                 goto error_nomem;
313               rname = rname_buf->data;
314               dest = rname + dest_offset;
315             }
316
317           dest = __mempcpy (dest, start, startlen);
318           *dest = '\0';
319
320           char *buf;
321           ssize_t n;
322           while (true)
323             {
324               buf = link_buffer.data;
325               idx_t bufsize = link_buffer.length;
326               n = __readlink (rname, buf, bufsize - 1);
327               if (n < bufsize - 1)
328                 break;
329               if (!scratch_buffer_grow (&link_buffer))
330                 goto error_nomem;
331             }
332           if (0 <= n)
333             {
334               if (++num_links > __eloop_threshold ())
335                 {
336                   __set_errno (ELOOP);
337                   goto error;
338                 }
339
340               buf[n] = '\0';
341
342               char *extra_buf = extra_buffer.data;
343               idx_t end_idx IF_LINT (= 0);
344               if (end_in_extra_buffer)
345                 end_idx = end - extra_buf;
346               size_t len = strlen (end);
347               if (INT_ADD_OVERFLOW (len, n))
348                 {
349                   __set_errno (ENOMEM);
350                   goto error_nomem;
351                 }
352               while (extra_buffer.length <= len + n)
353                 {
354                   if (!scratch_buffer_grow_preserve (&extra_buffer))
355                     goto error_nomem;
356                   extra_buf = extra_buffer.data;
357                 }
358               if (end_in_extra_buffer)
359                 end = extra_buf + end_idx;
360
361               /* Careful here, end may be a pointer into extra_buf... */
362               memmove (&extra_buf[n], end, len + 1);
363               name = end = memcpy (extra_buf, buf, n);
364               end_in_extra_buffer = true;
365
366               if (IS_ABSOLUTE_FILE_NAME (buf))
367                 {
368                   idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
369
370                   dest = __mempcpy (rname, buf, pfxlen);
371                   *dest++ = '/'; /* It's an absolute symlink */
372                   if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
373                     {
374                       if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
375                         *dest++ = '/';
376                       *dest = '\0';
377                     }
378                   /* Install the new prefix to be in effect hereafter.  */
379                   prefix_len = pfxlen;
380                 }
381               else
382                 {
383                   /* Back up to previous component, ignore if at root
384                      already: */
385                   if (dest > rname + prefix_len + 1)
386                     for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
387                       continue;
388                   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
389                       && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
390                     dest++;
391                 }
392             }
393           else if (! (suffix_requires_dir_check (end)
394                       ? dir_check (rname, dest)
395                       : errno == EINVAL))
396             goto error;
397         }
398     }
399   if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
400     --dest;
401   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
402       && ISSLASH (*dest) && !ISSLASH (dest[1]))
403     dest++;
404   failed = false;
405
406 error:
407   *dest++ = '\0';
408   if (resolved != NULL && dest - rname <= get_path_max ())
409     rname = strcpy (resolved, rname);
410
411 error_nomem:
412   scratch_buffer_free (&extra_buffer);
413   scratch_buffer_free (&link_buffer);
414
415   if (failed || rname == resolved)
416     {
417       scratch_buffer_free (rname_buf);
418       return failed ? NULL : resolved;
419     }
420
421   return scratch_buffer_dupfree (rname_buf, dest - rname);
422 }
423
424 /* Return the canonical absolute name of file NAME.  A canonical name
425    does not contain any ".", ".." components nor any repeated file name
426    separators ('/') or symlinks.  All file name components must exist.  If
427    RESOLVED is null, the result is malloc'd; otherwise, if the
428    canonical name is PATH_MAX chars or more, returns null with 'errno'
429    set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
430    returns the name in RESOLVED.  If the name cannot be resolved and
431    RESOLVED is non-NULL, it contains the name of the first component
432    that cannot be resolved.  If the name can be resolved, RESOLVED
433    holds the same value as the value returned.  */
434
435 char *
436 __realpath (const char *name, char *resolved)
437 {
438   #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
439    #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
440    #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
441   #endif
442   struct scratch_buffer rname_buffer;
443   return realpath_stk (name, resolved, &rname_buffer);
444 }
445 libc_hidden_def (__realpath)
446 versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
447
448 #endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
449
450
451 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
452 char *
453 attribute_compat_text_section
454 __old_realpath (const char *name, char *resolved)
455 {
456   if (resolved == NULL)
457     {
458       __set_errno (EINVAL);
459       return NULL;
460     }
461
462   return __realpath (name, resolved);
463 }
464 compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
465 #endif
466
467
468 char *
469 __canonicalize_file_name (const char *name)
470 {
471   return __realpath (name, NULL);
472 }
473 weak_alias (__canonicalize_file_name, canonicalize_file_name)