diff options
-rw-r--r-- | ChangeLog.cross | 8 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/cache.c | 18 | ||||
-rw-r--r-- | src/doit.c | 12 | ||||
-rw-r--r-- | src/dso.c | 20 | ||||
-rw-r--r-- | src/execstack.c | 6 | ||||
-rw-r--r-- | src/gather.c | 12 | ||||
-rw-r--r-- | src/get.c | 2 | ||||
-rw-r--r-- | src/main.c | 26 | ||||
-rw-r--r-- | src/prelink.h | 17 | ||||
-rw-r--r-- | src/undoall.c | 10 | ||||
-rw-r--r-- | src/verify.c | 6 | ||||
-rw-r--r-- | src/wrap-file.c | 536 |
13 files changed, 630 insertions, 48 deletions
diff --git a/ChangeLog.cross b/ChangeLog.cross index 9cd2dcc..b9b2d51 100644 --- a/ChangeLog.cross +++ b/ChangeLog.cross @@ -1,3 +1,11 @@ +2006-08-08 Montavista Software, Inc. + + * Makefile.am: Add function wrapper support for sysroots + * main.c: add --root option + * cache.c, doit.c, dso.c, execstack.c, gather.c, get.c, + prelink.h, undoall.c, verify.c: Add functional wrappers for sysroot + * wrap-file.c: add function wrapper definitions + 2006-07-28 Alexandre Oliva <aoliva@redhat.com> * src/cache.c: Avoid SEGFAULT when sorting cache entries (#197451) diff --git a/src/Makefile.am b/src/Makefile.am index 6cfe1e1..e5f3b8f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,11 +14,12 @@ arch_SOURCES = arch-i386.c arch-alpha.c arch-ppc.c arch-ppc64.c \ arch-sparc.c arch-sparc64.c arch-x86_64.c \ arch-s390.c arch-s390x.c arch-arm.c arch-sh.c arch-ia64.c common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \ - hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c + hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c \ + wrap-file.c canonicalize.c prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \ gather.c layout.c main.c prelink.c \ prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \ - verify.c canonicalize.c md5.c md5.h sha.c sha.h \ + verify.c md5.c md5.h sha.c sha.h \ $(common_SOURCES) $(arch_SOURCES) prelink_LDADD = @LIBGELF@ prelink_LDFLAGS = -all-static diff --git a/src/cache.c b/src/cache.c index b677e22..2a72267 100644 --- a/src/cache.c +++ b/src/cache.c @@ -112,8 +112,8 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, if (! stp) { - canon_filename = prelink_canonicalize (filename, &st); - if (canon_filename == NULL && stat64 (filename, &st) < 0) + canon_filename = wrap_prelink_canonicalize (filename, &st); + if (canon_filename == NULL && wrap_stat64 (filename, &st) < 0) { error (0, errno, "Could not stat %s", filename); if (insert) @@ -142,7 +142,7 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, { ent = (struct prelink_entry *) *devino_slot; if (canon_filename == NULL) - canon_filename = prelink_canonicalize (filename, NULL); + canon_filename = wrap_prelink_canonicalize (filename, NULL); if (canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); @@ -189,7 +189,7 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, if (canon_filename != NULL) ent->canon_filename = canon_filename; else - ent->canon_filename = prelink_canonicalize (filename, NULL); + ent->canon_filename = wrap_prelink_canonicalize (filename, NULL); if (ent->canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); @@ -248,7 +248,7 @@ prelink_load_entry (const char *filename) if (*filename_slot != NULL) return (struct prelink_entry *) *filename_slot; - canon_filename = prelink_canonicalize (filename, &st); + canon_filename = wrap_prelink_canonicalize (filename, &st); if (canon_filename == NULL) goto error_out2; if (strcmp (canon_filename, filename) != 0) @@ -364,7 +364,7 @@ prelink_load_cache (void) size_t cache_size; uint32_t string_start, *dep; - fd = open (prelink_cache, O_RDONLY); + fd = wrap_open (prelink_cache, O_RDONLY); if (fd < 0) return 0; /* The cache does not exist yet. */ @@ -672,7 +672,7 @@ prelink_save_cache (int do_warn) char prelink_cache_tmp [prelink_cache_len + sizeof (".XXXXXX")]; memcpy (mempcpy (prelink_cache_tmp, prelink_cache, prelink_cache_len), ".XXXXXX", sizeof (".XXXXXX")); - fd = mkstemp (prelink_cache_tmp); + fd = wrap_mkstemp (prelink_cache_tmp); if (fd < 0) { error (0, errno, "Could not write prelink cache"); @@ -683,10 +683,10 @@ prelink_save_cache (int do_warn) || write (fd, data, len) != len || fchmod (fd, 0644) || close (fd) - || rename (prelink_cache_tmp, prelink_cache)) + || wrap_rename (prelink_cache_tmp, prelink_cache)) { error (0, errno, "Could not write prelink cache"); - unlink (prelink_cache_tmp); + wrap_unlink (prelink_cache_tmp); return 1; } return 0; @@ -161,7 +161,7 @@ prelink_ent (struct prelink_entry *ent) { size_t len; - if (lstat64 (hardlink->canon_filename, &st) < 0) + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) { error (0, 0, "Could not stat %s (former hardlink to %s)", hardlink->canon_filename, ent->canon_filename); @@ -204,19 +204,19 @@ prelink_ent (struct prelink_entry *ent) memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", sizeof (".#prelink#")); - if (rename (hardlink->canon_filename, move) < 0) + if (wrap_rename (hardlink->canon_filename, move) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); continue; } - if (link (ent->canon_filename, hardlink->canon_filename) < 0) + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); - if (rename (move, hardlink->canon_filename) < 0) + if (wrap_rename (move, hardlink->canon_filename) < 0) { error (0, errno, "Could not rename %s back to %s", move, hardlink->canon_filename); @@ -224,7 +224,7 @@ prelink_ent (struct prelink_entry *ent) continue; } - if (unlink (move) < 0) + if (wrap_unlink (move) < 0) { error (0, errno, "Could not unlink %s", move); continue; @@ -232,7 +232,7 @@ prelink_ent (struct prelink_entry *ent) } free (move); - if (! dry_run && stat64 (ent->canon_filename, &st) >= 0) + if (! dry_run && wrap_stat64 (ent->canon_filename, &st) >= 0) { ent->dev = st.st_dev; ent->ino = st.st_ino; @@ -220,7 +220,7 @@ open_dso (const char *name) { int fd; - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) { error (0, errno, "cannot open \"%s\"", name); @@ -756,15 +756,15 @@ reopen_dso (DSO *dso, struct section_move *move, const char *temp_base) temp_base = dso->filename; sprintf (filename, "%s.#prelink#.XXXXXX", temp_base); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { strcpy (filename, "/tmp/#prelink#.XXXXXX"); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { strcpy (filename, "/dev/shm/#prelink#.XXXXXX"); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); } if (fd == -1) { @@ -1005,7 +1005,7 @@ error_out: elf_end (elf); if (fd != -1) { - unlink (filename); + wrap_unlink (filename); close (fd); } return 1; @@ -1632,7 +1632,7 @@ close_dso (DSO *dso) int rdwr = dso_is_rdwr (dso); if (rdwr && dso->temp_filename != NULL) - unlink (dso->temp_filename); + wrap_unlink (dso->temp_filename); close_dso_1 (dso); return 0; } @@ -1750,17 +1750,17 @@ update_dso (DSO *dso, const char *orig_name) close_dso_1 (dso); u.actime = time (NULL); u.modtime = st.st_mtime; - utime (name2, &u); + wrap_utime (name2, &u); if (set_security_context (dso, name2, orig_name ? orig_name : name1)) { - unlink (name2); + wrap_unlink (name2); return 1; } - if (rename (name2, name1)) + if (wrap_rename (name2, name1)) { - unlink (name2); + wrap_unlink (name2); error (0, errno, "Could not rename temporary to %s", name1); return 1; } diff --git a/src/execstack.c b/src/execstack.c index 1e50aad..9f1a4f2 100644 --- a/src/execstack.c +++ b/src/execstack.c @@ -107,7 +107,7 @@ execstack_make_rdwr (DSO *dso, int flag) header we've created. */ sprintf (filename, "%s.#execstack#.XXXXXX", dso->filename); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { error (0, 0, "%s: Cannot create temporary file", @@ -183,7 +183,7 @@ execstack_make_rdwr (DSO *dso, int flag) ndso->filename = p; p = NULL; - unlink (filename); + wrap_unlink (filename); close (fd); fd = -1; close_dso (dso); @@ -195,7 +195,7 @@ error_out: close_dso (ndso); if (fd != -1) { - unlink (filename); + wrap_unlink (filename); close (fd); } close_dso (dso); diff --git a/src/gather.c b/src/gather.c index a3d0870..a7ebcfd 100644 --- a/src/gather.c +++ b/src/gather.c @@ -587,7 +587,7 @@ add_dir_to_dirlist (const char *name, dev_t dev, int flags) struct prelink_dir *dir; size_t len; - canon_name = prelink_canonicalize (name, NULL); + canon_name = wrap_prelink_canonicalize (name, NULL); if (canon_name == NULL) { if (! all && implicit) @@ -693,7 +693,7 @@ gather_func (const char *name, const struct stat64 *st, int type, if (st->st_size < sizeof (e_ident)) return FTW_CONTINUE; - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) return FTW_CONTINUE; @@ -891,7 +891,7 @@ gather_binlib (const char *name, const struct stat64 *st) return 0; } - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) { error (0, errno, "Could not open %s", name); @@ -979,7 +979,7 @@ gather_object (const char *name, int deref, int onefs) { struct stat64 st; - if (stat64 (name, &st) < 0) + if (wrap_stat64 (name, &st) < 0) { if (implicit) return 0; @@ -1002,7 +1002,7 @@ gather_object (const char *name, int deref, int onefs) if (!all && implicit && ! deref) return 0; ++implicit; - ret = nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL); + ret = wrap_nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL); --implicit; #ifndef HAVE_FTW_ACTIONRETVAL free (blacklist_dir); @@ -1226,7 +1226,7 @@ add_to_blacklist (const char *name, int deref, int onefs) return 0; } - canon_name = prelink_canonicalize (name, NULL); + canon_name = wrap_prelink_canonicalize (name, NULL); if (canon_name == NULL) { if (implicit) @@ -144,7 +144,7 @@ prelink_record_relocations (struct prelink_info *info, FILE *f, { struct stat64 st; - if (stat64 (filename, &st) < 0) + if (wrap_stat64 (filename, &st) < 0) { error (0, errno, "%s: Could not stat %s", info->ent->filename, filename); @@ -77,6 +77,7 @@ static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared #define OPT_MD5 0x89 #define OPT_SHA 0x8a #define OPT_COMPUTE_CHECKSUM 0x8b +#define OPT_SYSROOT 0x8c static struct argp_option options[] = { {"all", 'a', 0, 0, "Prelink all binaries" }, @@ -94,6 +95,7 @@ static struct argp_option options[] = { {"quick", 'q', 0, 0, "Quick scan" }, {"random", 'R', 0, 0, "Choose random base for libraries" }, {"reloc-only", 'r', "BASE_ADDRESS", 0, "Relocate library to given address, don't prelink" }, + {"root", OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" }, {"undo", 'u', 0, 0, "Undo prelink" }, {"verbose", 'v', 0, 0, "Produce verbose output" }, {"verify", 'y', 0, 0, "Verify file consistency by undoing and redoing prelink and printing original to standard output" }, @@ -222,6 +224,9 @@ parse_opt (int key, char *arg, struct argp_state *state) case OPT_COMPUTE_CHECKSUM: compute_checksum = 1; break; + case OPT_SYSROOT: + sysroot = arg; + break; default: return ARGP_ERR_UNKNOWN; } @@ -237,9 +242,7 @@ main (int argc, char *argv[]) setlocale (LC_ALL, ""); - /* Set the default for exec_shield. */ - if (! access ("/proc/sys/kernel/exec-shield", F_OK)) - exec_shield = 1; + exec_shield = 2; prelink_init_cache (); @@ -261,6 +264,23 @@ main (int argc, char *argv[]) if ((undo || verify) && quick) error (EXIT_FAILURE, 0, "--undo and --quick options are incompatible"); + /* Set the default for exec_shield. */ + if (exec_shield == 2) + { + if (sysroot == NULL && ! access ("/proc/sys/kernel/exec-shield", F_OK)) + exec_shield = 1; + else + exec_shield = 0; + } + + if (sysroot) + { + sysroot = prelink_canonicalize (sysroot, NULL); + if (sysroot == NULL) + error (EXIT_FAILURE, 0, "Could not canonicalize --root argument"); + asprintf ((char **) &prelink_conf, "%s%s", sysroot, prelink_conf); + } + if (print_cache) { prelink_load_cache (); diff --git a/src/prelink.h b/src/prelink.h index 17d34fc..72ebf5d 100644 --- a/src/prelink.h +++ b/src/prelink.h @@ -21,10 +21,12 @@ #include <elf.h> #include <libelf.h> #include <gelfx.h> +#include <ftw.h> #include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> +#include <utime.h> #ifndef DT_GNU_LIBLIST #define DT_GNU_LIBLIST 0x6ffffef9 @@ -437,4 +439,19 @@ extern int quick; extern long long seed; extern GElf_Addr mmap_reg_start, mmap_reg_end; +extern const char *sysroot; + +char *wrap_prelink_canonicalize (const char *name, struct stat64 *stp); +int wrap_lstat64 (const char *file, struct stat64 *buf); +int wrap_stat64 (const char *file, struct stat64 *buf); +int wrap_open (const char *file, int mode, ...); +int wrap_access (const char *file, int mode); +int wrap_rename (const char *old, const char *new); +int wrap_link (const char *old, const char *new); +int wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag); +int wrap_utime (const char *file, struct utimbuf *file_times); +int wrap_mkstemp (char *filename); +int wrap_unlink (const char *filename); + #endif /* PRELINK_H */ diff --git a/src/undoall.c b/src/undoall.c index 4ce4670..90e9240 100644 --- a/src/undoall.c +++ b/src/undoall.c @@ -88,7 +88,7 @@ undo_one (void **p, void *info) { size_t len; - if (lstat64 (hardlink->canon_filename, &st) < 0) + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) { error (0, 0, "Could not stat %s (former hardlink to %s)", hardlink->canon_filename, ent->canon_filename); @@ -128,19 +128,19 @@ undo_one (void **p, void *info) memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", sizeof (".#prelink#")); - if (rename (hardlink->canon_filename, move) < 0) + if (wrap_rename (hardlink->canon_filename, move) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); continue; } - if (link (ent->canon_filename, hardlink->canon_filename) < 0) + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); - if (rename (move, hardlink->canon_filename) < 0) + if (wrap_rename (move, hardlink->canon_filename) < 0) { error (0, errno, "Could not rename %s back to %s", move, hardlink->canon_filename); @@ -148,7 +148,7 @@ undo_one (void **p, void *info) continue; } - if (unlink (move) < 0) + if (wrap_unlink (move) < 0) { error (0, errno, "Could not unlink %s", move); continue; diff --git a/src/verify.c b/src/verify.c index 935cbc2..a40c98f 100644 --- a/src/verify.c +++ b/src/verify.c @@ -193,7 +193,7 @@ prelink_verify (const char *filename) size_t count; char *p, *q; - if (stat64 (filename, &st) < 0) + if (wrap_stat64 (filename, &st) < 0) error (EXIT_FAILURE, errno, "Couldn't stat %s", filename); dso = open_dso (filename); @@ -266,7 +266,7 @@ prelink_verify (const char *filename) break; } - fd = open (dso->temp_filename, O_RDONLY); + fd = wrap_open (dso->temp_filename, O_RDONLY); if (fd < 0) { error (0, errno, "Could not verify %s", filename); @@ -430,7 +430,7 @@ failure: not_prelinked: if (dso) close_dso (dso); - fd = open (filename, O_RDONLY); + fd = wrap_open (filename, O_RDONLY); if (fd < 0) error (EXIT_FAILURE, errno, "Couldn't open %s", filename); if (handle_verify (fd, filename)) diff --git a/src/wrap-file.c b/src/wrap-file.c new file mode 100644 index 0000000..c631458 --- /dev/null +++ b/src/wrap-file.c @@ -0,0 +1,536 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003. + + The chroot_canon function is copied from the GNU C Library, + elf/chroot-canon.c, also licensed under the GPL: + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + [and then further modified.] + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <ftw.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef MAXSYMLINKS +#define MAXSYMLINKS 20 +#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. + + If ALLOW_LAST_LINK, then symlinks in the last component won't be + resolved. */ + +static char * +chroot_canon_filename (const char * chroot, const char *name, int allow_last_link, struct stat64 *stp) +{ + char *rpath, *dest, *extra_buf = NULL; + char *rpath_root; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + int stp_initialized = 0; + size_t chroot_len = 0; + + if (name == NULL) + { + errno = EINVAL; + return NULL; + } + + if (name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + + if (chroot == NULL) + { + errno = EINVAL; + return NULL; + } + + chroot_len = strlen (chroot); + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + rpath = malloc (chroot_len + path_max); + if (rpath == NULL) + return NULL; + 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) + { + 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] != '/'); + stp_initialized = 0; + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + + dest = mempcpy (dest, start, end - start); + *dest = '\0'; + + if (lstat64 (rpath, stp) < 0) + goto error; + + stp_initialized = 1; + + if (allow_last_link && *end == '\0') + goto done; + + if (S_ISLNK (stp->st_mode)) + { + char *buf = alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + errno = ELOOP; + goto error; + } + + n = readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + 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] != '/'); + } + else if (!S_ISDIR (stp->st_mode) && *end != '\0') + { + errno = ENOTDIR; + goto error; + } + } + } +done: + if (dest > rpath_root + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + if (!stp_initialized && lstat64 (rpath, stp) < 0) + goto error; + + if (dest + 1 - rpath <= (rpath_limit - rpath) / 2) + { + char *new_rpath = realloc (rpath, dest + 1 - rpath); + + if (new_rpath != NULL) + return new_rpath; + } + return rpath; + +error: + free (rpath); + return NULL; +} + + +const char *sysroot; + +static char * +sysroot_file_name (const char *name, int allow_last_link, struct stat64 *stp) +{ + char *ret; + struct stat64 st; + + if (sysroot == NULL || name == NULL) + return (char *) name; + + if (name[0] != '/') + { + char *tmpname = malloc (strlen (name) + 2); + strcpy (tmpname, "/"); + strcat (tmpname, name); + ret = chroot_canon_filename (sysroot, tmpname, allow_last_link, stp ? stp : &st); + free (tmpname); + } + else + ret = chroot_canon_filename (sysroot, name, allow_last_link, stp ? stp : &st); + + if (ret == NULL) + { + char *ret_root; + + ret = malloc(strlen(sysroot) + strlen(name) + 1); + ret_root = mempcpy(ret, sysroot, strlen(sysroot)); + ret_root = mempcpy(ret_root, name, strlen(name)); + *ret_root='\0'; + } + return ret; +} + +static char * +unsysroot_file_name (const char *name) +{ + if (name == NULL) + return (char *)name; + + if (sysroot) + { + int sysroot_len = strlen (sysroot); + if (strncmp (name, sysroot, sysroot_len) == 0) + { + if (name[sysroot_len] == '/') + return strdup (name + sysroot_len); + else if (name[sysroot_len] == 0) + return strdup ("/"); + } + } + return (char *)name; +} + +char * +wrap_prelink_canonicalize (const char *name, struct stat64 *stp) +{ + if (sysroot) + { + struct stat64 st; + char *tmpname; + char *ret; + + /* Use chroot_canon_filename because we want a NULL return if it doesn't exist! */ + tmpname = chroot_canon_filename (sysroot, name, 0, stp ? stp : &st); + + if (tmpname == NULL) + return NULL; + + ret = unsysroot_file_name (tmpname); + + if (ret == tmpname) + ret = strdup (ret); + + if (tmpname != name) + free (tmpname); + + return ret; + } + else + return prelink_canonicalize(name, stp); +} + +int +wrap_lstat64 (const char *file, struct stat64 *buf) +{ + char *tmpname = sysroot_file_name (file, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = lstat64 (tmpname, buf); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_stat64 (const char *file, struct stat64 *buf) +{ + char* file_copy; + char *tmpname; + int ret; + int len; + + tmpname = sysroot_file_name (file, 0, NULL); + + if (tmpname == NULL) + return -1; + + file_copy = strdup (tmpname); + + if (tmpname != file) + free (tmpname); + + if (file_copy == NULL) + return -1; + + len = strlen (file_copy); + if (file_copy[len - 1] == '/') + file_copy[len - 1] = '\0'; + + ret = stat64 (file_copy, buf); + + free (file_copy); + + return ret; +} + +int +wrap_rename (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = rename (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +int +wrap_open (const char *name, int mode, ...) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + if (mode & O_CREAT) + { + va_list va; + int flags; + va_start (va, mode); + flags = va_arg (va, int); + va_end (va); + ret = open (tmpname, mode, flags); + } + else + ret = open (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_access (const char *name, int mode) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = access (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_link (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = link (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +/* Note that this isn't recursive safe, since nftw64 doesn't + pass an opaque object around to use. But that fits our needs + for now. */ + +static __nftw64_func_t nftw64_cur_func; + +static int +wrap_nftw64_func (const char *filename, const struct stat64 *status, + int flag, struct FTW *info) +{ + char *tmpname = unsysroot_file_name (filename); + int ret = nftw64_cur_func (tmpname, status, flag, info); + + if (tmpname != filename) + free (tmpname); + return ret; +} + +int +wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag) +{ + char *tmpdir = sysroot_file_name (dir, 1, NULL); + int ret; + + if (tmpdir == NULL) + return -1; + + nftw64_cur_func = func; + ret = nftw64 (tmpdir, wrap_nftw64_func, descriptors, flag); + + if (tmpdir != dir) + free (tmpdir); + return ret; +} + +int +wrap_utime (const char *file, struct utimbuf *file_times) +{ + char *tmpname = sysroot_file_name (file, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = utime (tmpname, file_times); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_mkstemp (char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = mkstemp (tmpname); + + if (tmpname != filename) + { + strcpy (filename, tmpname + strlen (sysroot)); + free (tmpname); + } + return ret; +} + +int +wrap_unlink (const char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = unlink (tmpname); + + if (tmpname != filename) + free (tmpname); + return ret; +} |