diff options
Diffstat (limited to 'src/wrap-file.c')
-rw-r--r-- | src/wrap-file.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/src/wrap-file.c b/src/wrap-file.c new file mode 100644 index 0000000..f2cf305 --- /dev/null +++ b/src/wrap-file.c @@ -0,0 +1,399 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003. + + 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 <glob.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/xattr.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 + +extern char *canon_filename (const char *name, int nested, struct stat64 *stp, + const char *chroot, int allow_last_link, + int allow_missing); + +const char *sysroot; + +char * +sysroot_file_name (const char *name, int allow_last_link) +{ + struct stat64 st; + char *ret; + + if (sysroot == NULL) + return (char *) name; + + ret = canon_filename (name, 0, &st, sysroot, allow_last_link, 1); + + if (ret == NULL) + /* That will have set errno. */ + return NULL; + + return ret; +} + +char * +unsysroot_file_name (const 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; +} + +static int +wrap_stat_body (const char *file, struct stat64 *buf, int lstat) +{ + char* file_copy; + char *tmpname; + int ret; + int len; + + tmpname = sysroot_file_name (file, lstat); + + 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 (len && (file_copy[len - 1] == '/' || file_copy[len - 1] == '\\')) + file_copy[len - 1] = '\0'; + + ret = lstat ? lstat64 (file_copy, buf) : stat64 (file_copy, buf); + + free (file_copy); + + return ret; +} + +int +wrap_lstat64 (const char *file, struct stat64 *buf) +{ + return wrap_stat_body (file, buf, 1); +} + +int +wrap_stat64 (const char *file, struct stat64 *buf) +{ + return wrap_stat_body (file, buf, 0); +} + +int +wrap_rename (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1); + 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); + 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); + 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); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1); + 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); + 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); + 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); + 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); + int ret; + + if (tmpname == NULL) + return -1; + + ret = unlink (tmpname); + + if (tmpname != filename) + free (tmpname); + return ret; +} + +int +wrap_readlink (const char *path, char *buf, int len) +{ + char *tmpname = sysroot_file_name (path, 1); + int ret; + + if (tmpname == NULL) + return -1; + + ret = readlink (tmpname, buf, len); + + if (tmpname != path) + free (tmpname); + return ret; +} + +int +wrap_setxattr (const char *path, const char *name, const void *value, + size_t size, int flags) +{ + char *tmpname = sysroot_file_name (path, 0); + int ret; + + if (tmpname == NULL) + return -1; + + ret = setxattr (tmpname, name, value, size, flags); + + if (tmpname != path) + free (tmpname); + return ret; +} + +ssize_t +wrap_getxattr (const char *path, const char *name, void *value, + size_t size) +{ + char *tmpname = sysroot_file_name (path, 0); + ssize_t ret; + + if (tmpname == NULL) + return -1; + + ret = getxattr (tmpname, name, value, size); + + if (tmpname != path) + free (tmpname); + return ret; +} + +ssize_t +wrap_listxattr (const char *path, char *list, size_t size) +{ + char *tmpname = sysroot_file_name (path, 0); + ssize_t ret; + + if (tmpname == NULL) + return -1; + + ret = listxattr (tmpname, list, size); + + if (tmpname != path) + free (tmpname); + return ret; +} + +int +wrap_glob (const char *pattern, int flags, + int (*errfunc) (const char *epath, int eerrno), + glob_t *pglob) +{ + char *tmp; + int ret; + + if (!sysroot) + return glob (pattern, flags, errfunc, pglob); + + asprintf (&tmp, "%s%s", sysroot, pattern); + + ret = glob(tmp, flags, errfunc, pglob); + if (!ret) + { + size_t n; + + for (n = 0; n < pglob->gl_pathc; ++n) + { + char *usname = unsysroot_file_name(pglob->gl_pathv[n]); + if (usname != pglob->gl_pathv[n]) + free(pglob->gl_pathv[n]); + pglob->gl_pathv[n] = usname; + } + } + + free(tmp); + return ret; +} |