summaryrefslogtreecommitdiff
path: root/elf/chroot_canon.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-09-30 00:54:42 +0000
committerUlrich Drepper <drepper@redhat.com>2000-09-30 00:54:42 +0000
commitb4a555d6f48fac3c71c2f8022c1fb8e23919d94a (patch)
treeea55480096126155a32520d4fb39c9f7d02e112b /elf/chroot_canon.c
parent955821742eeae476da6e658f3f14c1af30630d1a (diff)
Update.
2000-09-29 Ulrich Drepper <drepper@redhat.com> * elf/chroot_canon.c: Don't report a failure if the last path component is not available. * elf/ldconfig.c (parse_conf): Use canonicalized name when reporting error. * elf/cache.c (print_cache): Use stat64 instead of stat. * elf/ldconfig.c (chroot_stat): Likewise. (create_links): Likewise. (manual_link): Likewise. (search_dir): Likewise. * elf/readlib.c (process_file): Likewise. * Makefile (install): Set LC_ALL and LANGUAGE to C before running ldconfig. 2000-09-29 Jakub Jelinek <jakub@redhat.com> * elf/chroot_canon.c: New file. * elf/Makefile: Build and distribute it. * elf/ldconfig.h (process_file): Add real_file_name argument. (chroot_canon): Add prototype. * elf/ldconfig.c (cache_file): Remove const. (chroot_stat): New. (create_links): Add real_path argument. If opt_chroot, maintain both real and given filenames. (manual_link): Likewise. (search_dir): Likewise. (parse_conf): If opt_chroot, use chroot_canon to find the real config file. (main): For -r, try to use chroot, if it fails, leave opt_chroot set and use chroot_canon where appropriate to do the same as if chroot succeeded. * elf/readlib.c (process_file): Add real_file_name argument, pass it to fopen. 2000-09-29 Ulrich Drepper <drepper@redhat.com> * math/complex.h (_Complex): We can be more specific when _Complex is defined by the compiler.
Diffstat (limited to 'elf/chroot_canon.c')
-rw-r--r--elf/chroot_canon.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c
new file mode 100644
index 0000000000..82cb8c4bf0
--- /dev/null
+++ b/elf/chroot_canon.c
@@ -0,0 +1,172 @@
+/* Return the canonical absolute name of a given file inside chroot.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+#include "ldconfig.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was
+ done first. A canonical name does not contain any `.', `..' components
+ nor any repeated path separators ('/') or symlinks. All path components
+ must exist and NAME must be absolute filename. The result is malloc'd.
+ The returned name includes the CHROOT prefix. */
+
+char *
+chroot_canon (const char *chroot, const char *name)
+{
+ char *rpath, *dest, *extra_buf = NULL, *rpath_root;
+ const char *start, *end, *rpath_limit;
+ int num_links = 0;
+ size_t chroot_len = strlen (chroot);
+
+ if (chroot_len < 1)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ rpath = malloc (chroot_len + PATH_MAX);
+ rpath_limit = rpath + chroot_len + PATH_MAX;
+
+ rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1;
+ if (*rpath_root != '/')
+ *++rpath_root = '/';
+ dest = rpath_root + 1;
+
+ for (start = end = name; *start; start = end)
+ {
+ struct stat64 st;
+ int n;
+
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath_root + 1)
+ while ((--dest)[-1] != '/');
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > PATH_MAX)
+ new_size += end - start + 1;
+ else
+ new_size += PATH_MAX;
+ rpath = realloc (rpath, new_size);
+ rpath_limit = rpath + new_size;
+ if (rpath == NULL)
+ return NULL;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = mempcpy (dest, start, end - start);
+ *dest = '\0';
+
+ if (lstat64 (rpath, &st) < 0)
+ {
+ if (*end == '\0')
+ goto done;
+ goto error;
+ }
+
+ if (S_ISLNK (st.st_mode))
+ {
+ char *buf = alloca (PATH_MAX);
+ size_t len;
+
+ if (++num_links > MAXSYMLINKS)
+ {
+ __set_errno (ELOOP);
+ goto error;
+ }
+
+ n = readlink (rpath, buf, PATH_MAX);
+ if (n < 0)
+ {
+ if (*end == '\0')
+ goto done;
+ goto error;
+ }
+ buf[n] = '\0';
+
+ if (!extra_buf)
+ extra_buf = alloca (PATH_MAX);
+
+ len = strlen (end);
+ if ((long int) (n + len) >= PATH_MAX)
+ {
+ __set_errno (ENAMETOOLONG);
+ goto error;
+ }
+
+ /* Careful here, end may be a pointer into extra_buf... */
+ memmove (&extra_buf[n], end, len + 1);
+ name = end = memcpy (extra_buf, buf, n);
+
+ if (buf[0] == '/')
+ dest = rpath_root + 1; /* It's an absolute symlink */
+ else
+ /* Back up to previous component, ignore if at root already: */
+ if (dest > rpath_root + 1)
+ while ((--dest)[-1] != '/');
+ }
+ }
+ }
+ done:
+ if (dest > rpath_root + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ return rpath;
+
+ error:
+ free (rpath);
+ return NULL;
+}