From 68f63f58f0999b126c14d127e6ece499bffa51db Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 30 Mar 2009 19:04:34 +0100 Subject: [PATCH] Version 1.4. Now uses FAKECHROOT_CMD_SUBST to remove most %post warnings. --- configure.ac | 2 +- fakechroot-2.9-cmdsubst.patch | 262 ++++++++++++++++++++++++++++++++++++++++++ febootstrap.pod | 20 +--- febootstrap.sh | 5 + febootstrap.spec.in | 2 +- 5 files changed, 273 insertions(+), 18 deletions(-) create mode 100644 fakechroot-2.9-cmdsubst.patch diff --git a/configure.ac b/configure.ac index d7d3d3e..f7aa1fd 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. dnl dnl Written by Richard W.M. Jones -AC_INIT(febootstrap,1.3) +AC_INIT(febootstrap,1.4) AM_INIT_AUTOMAKE AC_CHECK_PROG(PERLDOC,[perldoc],[perldoc],[no]) diff --git a/fakechroot-2.9-cmdsubst.patch b/fakechroot-2.9-cmdsubst.patch new file mode 100644 index 0000000..0d40cd7 --- /dev/null +++ b/fakechroot-2.9-cmdsubst.patch @@ -0,0 +1,262 @@ +Index: test/cmd-subst-pwd.sh +=================================================================== +--- test/cmd-subst-pwd.sh (revision 0) ++++ test/cmd-subst-pwd.sh (revision 0) +@@ -0,0 +1,3 @@ ++#!/bin/sh ++ ++echo substituted + +Property changes on: test/cmd-subst-pwd.sh +___________________________________________________________________ +Added: svn:executable + + * + +Index: test/cmd-subst.t +=================================================================== +--- test/cmd-subst.t (revision 0) ++++ test/cmd-subst.t (revision 0) +@@ -0,0 +1,37 @@ ++#!/bin/sh ++ ++. ./tap.sh ++ ++plan 5 ++ ++rm -rf testtree ++ ++./testtree.sh testtree ++test "`cat testtree/CHROOT`" = "testtree" || not ++ok "testtree" ++ ++t=`./fakechroot.sh testtree /bin/pwd` ++test "$t" = "/" || not ++ok "fakechroot pwd is /" ++ ++export FAKECHROOT_CMD_SUBST="/bin/pwd=$(pwd)/cmd-subst-pwd.sh" ++ ++t=`./fakechroot.sh testtree /bin/pwd` ++test "$t" = "substituted" || not ++ok "fakechroot substituted pwd (1)" ++ ++export FAKECHROOT_CMD_SUBST="/no/file=foo:/bin/pwd=$(pwd)/cmd-subst-pwd.sh" ++ ++t=`./fakechroot.sh testtree /bin/pwd` ++test "$t" = "substituted" || not ++ok "fakechroot substituted pwd (2)" ++ ++export FAKECHROOT_CMD_SUBST="/no/file=foo:/other/file=bar" ++ ++t=`./fakechroot.sh testtree /bin/pwd` ++test "$t" = "/" || not ++ok "fakechroot not substituted pwd is /" ++ ++rm -rf testtree ++ ++end + +Property changes on: test/cmd-subst.t +___________________________________________________________________ +Added: svn:executable + + * + +Index: test/Makefile.am +=================================================================== +--- test/Makefile.am (revision 323) ++++ test/Makefile.am (working copy) +@@ -1,6 +1,6 @@ + SUBDIRS = src + +-TESTS = chroot.t escape-nested-chroot.t pwd.t touch.t ++TESTS = chroot.t cmd-subst.t escape-nested-chroot.t pwd.t touch.t + + suffix = + +Index: src/libfakechroot.c +=================================================================== +--- src/libfakechroot.c (revision 323) ++++ src/libfakechroot.c (working copy) +@@ -1467,7 +1467,38 @@ + return execve (path, argv, environ); + } + ++/* Parse the FAKECHROOT_CMD_SUBST environment variable (the first ++ * parameter) and if there is a match with filename, return the ++ * substitution in cmd_subst. Returns non-zero if there was a match. ++ * ++ * FAKECHROOT_CMD_SUBST=cmd=subst:cmd=subst:... ++ */ ++static int ++try_cmd_subst (char *env, const char *filename, char *cmd_subst) ++{ ++ int len = strlen (filename), len2; ++ char *p; + ++ if (env == NULL) return 0; ++ ++ do { ++ p = strchrnul (env, ':'); ++ ++ if (strncmp (env, filename, len) == 0 && env[len] == '=') { ++ len2 = p - &env[len+1]; ++ if (len2 >= FAKECHROOT_MAXPATH) ++ len2 = FAKECHROOT_MAXPATH - 1; ++ strncpy (cmd_subst, &env[len+1], len2); ++ cmd_subst[len2] = '\0'; ++ return 1; ++ } ++ ++ env = p; ++ } while (*env++ != '\0'); ++ ++ return 0; ++} ++ + /* #include */ + int execve (const char *filename, char *const argv [], char *const envp[]) + { +@@ -1479,32 +1510,16 @@ + char *env; + char tmp[FAKECHROOT_MAXPATH], newfilename[FAKECHROOT_MAXPATH], argv0[FAKECHROOT_MAXPATH]; + char *ptr; +- unsigned int i, j, n, len; ++ unsigned int i, j, n, len, r, newenvppos; + size_t sizeenvp; + char c; + char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH]; + char *envkey[] = { "FAKECHROOT", "FAKECHROOT_BASE", + "FAKECHROOT_VERSION", "FAKECHROOT_EXCLUDE_PATH", ++ "FAKECHROOT_CMD_SUBST", + "LD_LIBRARY_PATH", "LD_PRELOAD" }; ++ const int nr_envkey = sizeof envkey / sizeof envkey[0]; + +- strncpy(argv0, filename, FAKECHROOT_MAXPATH); +- +- expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf); +- strcpy(tmp, filename); +- filename = tmp; +- +- if ((file = open(filename, O_RDONLY)) == -1) { +- errno = ENOENT; +- return -1; +- } +- +- i = read(file, hashbang, FAKECHROOT_MAXPATH-2); +- close(file); +- if (i == -1) { +- errno = ENOENT; +- return -1; +- } +- + if (next_execve == NULL) fakechroot_init(); + + /* Scan envp and check its size */ +@@ -1514,39 +1529,69 @@ + } + + /* Copy envp to newenvp */ +- newenvp = malloc( sizeenvp * sizeof (char *) + sizeof(envkey) ); ++ newenvp = malloc( (sizeenvp + 1) * sizeof (char *) ); + if (newenvp == NULL) { + errno = ENOMEM; + return -1; + } +- for (ep = envp, i = 0; *ep != NULL; ++ep) { +- for (j = 0; j < sizeof (envkey) / sizeof (char *); j++) { ++ for (ep = envp, newenvppos = 0; *ep != NULL; ++ep) { ++ for (j = 0; j < nr_envkey; j++) { + len = strlen (envkey[j]); + if (strncmp (*ep, envkey[j], len) == 0 && (*ep)[len] == '=') + goto skip; + } +- newenvp[i] = *ep; +- i++; ++ newenvp[newenvppos] = *ep; ++ newenvppos++; + skip: ; + } ++ newenvp[newenvppos] = NULL; + ++ strncpy(argv0, filename, FAKECHROOT_MAXPATH); ++ ++ r = try_cmd_subst (getenv ("FAKECHROOT_CMD_SUBST"), filename, tmp); ++ if (r) { ++ filename = tmp; ++ ++ /* FAKECHROOT_CMD_SUBST escapes the chroot. newenvp here does ++ * not contain LD_PRELOAD and the other special environment ++ * variables. ++ */ ++ return next_execve(filename, argv, newenvp); ++ } ++ ++ expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf); ++ strcpy(tmp, filename); ++ filename = tmp; ++ ++ if ((file = open(filename, O_RDONLY)) == -1) { ++ errno = ENOENT; ++ return -1; ++ } ++ ++ i = read(file, hashbang, FAKECHROOT_MAXPATH-2); ++ close(file); ++ if (i == -1) { ++ errno = ENOENT; ++ return -1; ++ } ++ + /* Add our variables to newenvp */ +- newenvp = realloc( newenvp, i * sizeof(char *) + sizeof(envkey) ); ++ newenvp = realloc( newenvp, (newenvppos + nr_envkey + 1) * sizeof(char *) ); + if (newenvp == NULL) { + errno = ENOMEM; + return -1; + } +- for (j = 0; j < sizeof(envkey) / sizeof(char *); j++) { ++ for (j = 0; j < nr_envkey; j++) { + env = getenv(envkey[j]); + if (env != NULL) { +- newenvp[i] = malloc(strlen(envkey[j]) + strlen(env) + 3); +- strcpy(newenvp[i], envkey[j]); +- strcat(newenvp[i], "="); +- strcat(newenvp[i], env); +- i++; ++ newenvp[newenvppos] = malloc(strlen(envkey[j]) + strlen(env) + 3); ++ strcpy(newenvp[newenvppos], envkey[j]); ++ strcat(newenvp[newenvppos], "="); ++ strcat(newenvp[newenvppos], env); ++ newenvppos++; + } + } +- newenvp[i] = NULL; ++ newenvp[newenvppos] = NULL; + + /* No hashbang in argv */ + if (hashbang[0] != '#' || hashbang[1] != '!') +Index: man/fakechroot.pod +=================================================================== +--- man/fakechroot.pod (revision 323) ++++ man/fakechroot.pod (working copy) +@@ -139,6 +139,21 @@ + The list of directories which are excluded from being chrooted. The elements + of list are separated with colon. + ++=item B ++ ++A list of command substitutions. If a program tries to execute one of ++the commands given (path relative to the chroot) then the substitute ++command runs instead (path to substitute command is not chrooted). ++ ++For example: ++ ++ FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/tmp/ldconfig-wrapper ++ ++will substitute C for C. ++ ++Give as many substitute commands as you want, separated by C<:> ++(colon) characters. ++ + =item B, B + + Fakechroot is implemented by wrapping system calls. This is accomplished by diff --git a/febootstrap.pod b/febootstrap.pod index b2d7470..de10a58 100644 --- a/febootstrap.pod +++ b/febootstrap.pod @@ -148,22 +148,10 @@ C<--foreign> installs - see previous point). =head1 OTHER RESTRICTIONS AND BUGS -Some C<%post> scripts do not run correctly. The most common case is -C. Since this binary is statically linked, fakeroot -and fakechroot's LD_PRELOAD hack does not work, so effectively -ldconfig tries to update the system cache. You will see the following -error: - - /sbin/ldconfig: Can't create temporary cache file /etc/ld.so.cache~: Permission denied - -This error is mostly harmless. Just run C the first -time you boot into the newly created Fedora system. - -Another error you will see is with C -which is caused for the same reason - this binary is statically -linked. We have examined what this binary does, and it is not really -necessary for installs. If it makes you happier, you can run it the -first time you boot the new system. +C and C are not run +during C<%post> scriptlets (because they are statically linked, and +fakechroot cannot run statically linked programs). If you wish, you +can run them the first time you boot into the new machine. febootstrap recreates the repository anew each time, and this causes yum to download all the RPMs every time. This is very wasteful, and diff --git a/febootstrap.sh b/febootstrap.sh index 5900499..b08e3c0 100755 --- a/febootstrap.sh +++ b/febootstrap.sh @@ -124,6 +124,11 @@ mkdir -p "$target"/var/cache/yum/febootstrap/packages # error: unpacking of archive failed on file /proc: cpio: utime export FAKECHROOT_EXCLUDE_PATH=/proc +# Substitute some statically-linked commands. This is only supported +# in fakechroot > 2.9. For previous versions of fakechroot it is +# ignored. +export FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/bin/true:/usr/sbin/glibc_post_upgrade.i686=/bin/true:/usr/sbin/glibc_post_upgrade.x86_64=/bin/true + # Make the device nodes inside the fake chroot. # (Copied from mock/backend.py) Why isn't there a base package which # creates these? diff --git a/febootstrap.spec.in b/febootstrap.spec.in index a13f148..05292f6 100644 --- a/febootstrap.spec.in +++ b/febootstrap.spec.in @@ -14,7 +14,7 @@ BuildArch: noarch BuildRequires: /usr/bin/pod2man Requires: fakeroot >= 1.11 -Requires: fakechroot >= 2.8-15.fc10.rwmj4 +Requires: fakechroot >= 2.9-1.fc11.rwmj3 Requires: yum >= 3.2 Requires: MAKEDEV Requires: util-linux-ng -- 1.8.3.1