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