On Wed, 2010-09-01 at 21:50 +0300, Panu Matilainen wrote: > On Wed, 1 Sep 2010, Ralf Corsepius wrote: > > > > b) To equippe the rpm/yum/mock etc. infrastructure with a mechanism to > > pull-in "foreign binaries" into a sys-root (E.g. to install Fedora > > *.ppc.rpm rpms into /usr/ppc-redhat/sys-root). So far, such mechanism > > doesn't exist. > > You should be able to force rpm to lay down the files, given enough > override-switches. Something like > # rpm -Uvh --root /usr/ppc-redhat/sys-root --ignorearch --noscripts *.rpm > > (or alternatively --relocate with --badrelocate instead of --root, if you > want the packages showing in system rpmdb instead of alternate root, and > then you'd /really/ need arch-specific buildrequires which in turn is > another can of worms etc) > > ...but the resulting pile of files is likely to be fairly useless since > no scripts are executed. Having some way of executing scriptlets in an > emulator (eg qemu) might be an interesting experiment actually ;) > > - Panu - Speaking of crazy experiments, I came up with the attached rpm patch last year when I was bootstrapping another arch. In short, to run scripts without having to write a simulator, it bind mounts native binary (/bin, /lib, etc) directories into the target sysroot before running a script and unmounts them afterward. As crazy as that is, it worked surprisingly well for a core set of F-10 rpms. Of course, it doesn't work for scripts that try writing to the binary directories, but it did help me compose a cross rootfs based on a kickstart file. Something simulator based would definitely have been better. --Mark
diff -rup a/lib/poptALL.c b/lib/poptALL.c --- a/lib/poptALL.c 2009-03-03 01:51:52.000000000 -0500 +++ b/lib/poptALL.c 2009-08-03 16:01:23.295685376 -0400 @@ -68,6 +68,8 @@ const char * rpmcliRcfile = NULL; const char * rpmcliRootDir = "/"; +const char * rpmcliNativeRootDir = NULL; + rpmQueryFlags rpmcliQueryFlags; extern int _rpmio_debug; @@ -238,6 +240,10 @@ struct poptOption rpmcliAllPoptTable[] = N_("use ROOT as top level directory"), N_("ROOT") }, + { "nativeroot", '\0', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &rpmcliNativeRootDir, 0, + N_("use ROOT as top level directory of native binaries"), + N_("ROOT") }, + { "querytags", '\0', 0, 0, POPT_QUERYTAGS, N_("display known query tags"), NULL }, { "showrc", '\0', 0, NULL, POPT_SHOWRC, diff -rup a/lib/psm.c b/lib/psm.c --- a/lib/psm.c 2009-04-03 07:04:46.000000000 -0400 +++ b/lib/psm.c 2009-08-04 16:39:57.944559570 -0400 @@ -4,6 +4,7 @@ */ #include "system.h" +#include <sys/mount.h> #include <rpm/rpmlib.h> /* rpmvercmp and others */ #include <rpm/rpmmacro.h> @@ -63,6 +64,69 @@ struct rpmpsm_s { int nrefs; /*!< Reference count. */ }; +static const char *nativeDirs[] = { + "bin", + "sbin", + "usr/bin", + "usr/sbin", + "lib", + "usr/lib", + "usr/libexec", + NULL +}; + +static int rpmMountNatives(rpmts ts) +{ + const char * rootDir = rpmtsRootDir(ts); + const char *nativeDir = rpmtsNativeDir(ts); + + if (rootDir != NULL && nativeDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { + char **dirs; + if (rpmtsChrootDone(ts)) + rootDir = "/"; + + for (dirs = nativeDirs; *dirs != NULL; ++dirs) { + struct stat st; + char *srcDir = rpmGetPath(rootDir, "native/", *dirs, NULL); + char *targetDir = rpmGetPath(rootDir, *dirs, NULL); + + if (stat(srcDir, &st) == 0) { + rpmioMkpath(targetDir, 0755, -1, -1); + mount(srcDir, targetDir, NULL, MS_BIND, NULL); + } + + _free(srcDir); + _free(targetDir); + } + } + return 0; +} + +static int rpmUmountNatives(rpmts ts) +{ + const char * rootDir = rpmtsRootDir(ts); + char *nativeDir = rpmtsNativeDir(ts); + + if (rootDir != NULL && nativeDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { + char **dirs; + if (rpmtsChrootDone(ts)) + rootDir = "/"; + + for (dirs = nativeDirs; *dirs != NULL; ++dirs) { + struct stat st; + char *targetDir = rpmGetPath(rootDir, *dirs, NULL); + + if (stat(targetDir, &st) == 0) { + umount(targetDir); + unlink(targetDir); + } + + _free(targetDir); + } + } + return 0; +} + int rpmVersionCompare(Header first, Header second) { struct rpmtd_s one, two; @@ -482,11 +546,13 @@ static rpmRC runLuaScript(rpmpsm psm, He var = rpmluavFree(var); rpmluaPop(lua); + rpmMountNatives(ts); if (rpmluaRunScript(lua, script, sname) == 0) { rc = RPMRC_OK; } else if ((stag != RPMTAG_PREIN && stag != RPMTAG_PREUN)) { warn_only = 1; } + rpmUmountNatives(ts); rpmluaDelVar(lua, "arg"); @@ -744,6 +810,7 @@ static rpmRC runScript(rpmpsm psm, Heade goto exit; } + rpmMountNatives(ts); xx = rpmsqFork(&psm->sq); if (psm->sq.child == 0) { rpmlog(RPMLOG_DEBUG, "%s: %s\texecv(%s) pid %d\n", @@ -778,6 +845,7 @@ static rpmRC runScript(rpmpsm psm, Heade /* if we get this far we're clear */ rc = RPMRC_OK; } + rpmUmountNatives(ts); exit: rpmtdFreeData(&prefixes); @@ -1556,17 +1624,41 @@ rpmRC rpmpsmStage(rpmpsm psm, pkgStage s case PSM_CHROOT_IN: { const char * rootDir = rpmtsRootDir(ts); /* Change root directory if requested and not already done. */ + rpmlog(RPMLOG_DEBUG, "PSM_CHROOT_IN: rootDir: %s\n", rootDir ? rootDir : "NULL"); if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0') && !rpmtsChrootDone(ts) && !psm->chrootDone) { + const char * nativeDir = rpmtsNativeDir(ts); + char *chrootNative = NULL; + rpmlog(RPMLOG_DEBUG, "PSM_CHROOT_IN: nativeDir: %s\n", nativeDir ? nativeDir : "NULL"); + if (nativeDir != NULL) { + chrootNative = rpmGetPath(rootDir, "native", NULL); + /* mount nativeDir somewhere we can get to from chroot */ + if (mkdir(chrootNative, 0755)) { + rpmlog(RPMLOG_ERR, _("Unable to make chroot native directory: %m\n")); + return -1; + } + if (mount(nativeDir, chrootNative, NULL, MS_BIND, NULL)) { + rpmlog(RPMLOG_ERR, _("Unable to mount chroot native directory: %m\n")); + rmdir(chrootNative); + _free(chrootNative); + return -1; + } + } xx = chdir("/"); if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') if (chroot(rootDir) == -1) { rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n")); + if (chrootNative) { + umount(chrootNative); + rmdir(chrootNative); + _free(chrootNative); + } return -1; } psm->chrootDone = 1; (void) rpmtsSetChrootDone(ts, 1); + _free(chrootNative); } } break; case PSM_CHROOT_OUT: @@ -1574,8 +1666,16 @@ rpmRC rpmpsmStage(rpmpsm psm, pkgStage s if (psm->chrootDone) { const char * rootDir = rpmtsRootDir(ts); const char * currDir = rpmtsCurrDir(ts); - if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') + if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { + const char * nativeDir = rpmtsNativeDir(ts); rc = chroot("."); + if (nativeDir != NULL) { + char *tmpDir = rpmGetPath(rootDir, "native", NULL); + umount(tmpDir); + rmdir(tmpDir); + _free(tmpDir); + } + } psm->chrootDone = 0; (void) rpmtsSetChrootDone(ts, 0); if (currDir != NULL) /* XXX can't happen */ diff -rup a/lib/rpmcli.h b/lib/rpmcli.h --- a/lib/rpmcli.h 2009-04-03 06:59:20.000000000 -0400 +++ b/lib/rpmcli.h 2009-08-04 15:43:51.432639428 -0400 @@ -40,6 +40,8 @@ extern const char * rpmcliRcfile; extern const char * rpmcliRootDir; +extern const char * rpmcliNativeRootDir; + /** \ingroup rpmcli * Initialize most everything needed by an rpm CLI executable context. * @param argc no. of args diff -rup a/lib/rpmts.c b/lib/rpmts.c --- a/lib/rpmts.c 2009-04-03 07:36:48.000000000 -0400 +++ b/lib/rpmts.c 2009-08-04 11:40:51.269560123 -0400 @@ -594,6 +594,7 @@ rpmts rpmtsFree(rpmts ts) ts->scriptFd = NULL; } ts->rootDir = _free(ts->rootDir); + ts->nativeDir = _free(ts->nativeDir); ts->currDir = _free(ts->currDir); ts->order = _free(ts->order); @@ -681,6 +682,50 @@ int rpmtsSetRootDir(rpmts ts, const char return 0; } +const char * rpmtsNativeDir(rpmts ts) +{ + const char * nativeDir = NULL; + + if (ts == NULL) + return NULL; + + if (ts->nativeDir == NULL) { + char *x = getenv("RPM_NATIVEDIR"); + if (x) + ts->nativeDir = rpmGetPath(x, NULL); + } + + if (ts->nativeDir != NULL) { + urltype ut = urlPath(ts->nativeDir, &nativeDir); + switch (ut) { + case URL_IS_UNKNOWN: + case URL_IS_PATH: + break; + /* XXX these shouldn't be allowed as nativedir! */ + case URL_IS_HTTPS: + case URL_IS_HTTP: + case URL_IS_HKP: + case URL_IS_FTP: + case URL_IS_DASH: + default: + nativeDir = NULL; + break; + } + } + return nativeDir; +} + +int rpmtsSetNativeDir(rpmts ts, const char * nativeDir) +{ + if (ts == NULL || (nativeDir && nativeDir[0] != '/')) { + return -1; + } + + ts->nativeDir = _free(ts->nativeDir); + ts->nativeDir = nativeDir ? rpmGetPath(nativeDir, NULL) : NULL ; + return 0; +} + const char * rpmtsCurrDir(rpmts ts) { const char * currDir = NULL; @@ -1129,6 +1174,7 @@ rpmts rpmtsCreate(void) sizeof(*ts->removedPackages)); ts->rootDir = NULL; + ts->nativeDir = NULL; ts->currDir = NULL; ts->chrootDone = 0; diff -rup a/lib/rpmts.h b/lib/rpmts.h --- a/lib/rpmts.h 2009-04-03 06:59:20.000000000 -0400 +++ b/lib/rpmts.h 2009-08-04 13:11:36.436559980 -0400 @@ -394,6 +394,21 @@ const char * rpmtsRootDir(rpmts ts); int rpmtsSetRootDir(rpmts ts, const char * rootDir); /** \ingroup rpmts + * Get transaction nativeDir, i.e. path to native binaries. + * @param ts transaction set + * @return transaction nativeDir + */ +const char * rpmtsNativeDir(rpmts ts); + +/** \ingroup rpmts + * Set transaction nativeDir, i.e. path to native binaries. + * @param ts transaction set + * @param nativeDir new transaction nativeDir (or NULL) + * @return 0 on success, -1 on error (invalid rootDir) + */ +int rpmtsSetNativeDir(rpmts ts, const char * nativeDir); + +/** \ingroup rpmts * Get transaction currDir, i.e. current directory before chroot(2). * @param ts transaction set * @return transaction currDir diff -rup a/lib/rpmts_internal.h b/lib/rpmts_internal.h --- a/lib/rpmts_internal.h 2009-04-03 07:36:48.000000000 -0400 +++ b/lib/rpmts_internal.h 2009-08-03 21:20:18.112685343 -0400 @@ -73,6 +73,7 @@ struct rpmts_s { int selinuxEnabled; /*!< Is SE linux enabled? */ int chrootDone; /*!< Has chroot(2) been been done? */ char * rootDir; /*!< Path to top of install tree. */ + char * nativeDir; /*!< Path to top of native install tree. */ char * currDir; /*!< Current working directory. */ FD_t scriptFd; /*!< Scriptlet stdout/stderr. */ int delta; /*!< Delta for reallocation. */ diff -rup a/python/rpmts-py.c b/python/rpmts-py.c --- a/python/rpmts-py.c 2009-08-03 15:52:47.104684373 -0400 +++ b/python/rpmts-py.c 2009-09-14 15:28:49.281737146 -0400 @@ -790,6 +790,22 @@ fprintf(stderr, "*** rpmts_GetKeys(%p) t return tuple; } +static PyObject * +rpmts_SetNativeRoot(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + const char *nativeRoot; + char * kwlist[] = {"nativeRoot", NULL}; + +if (_rpmts_debug) +fprintf(stderr, "*** rpmts_SetNativeRoot(%p) ts %p\n", s, s->ts); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:SetNativeRoot", kwlist, + &nativeRoot)) + return NULL; + + return Py_BuildValue("i", rpmtsSetNativeDir(s->ts, nativeRoot)); +} + /** \ingroup py_c */ static void * @@ -1217,6 +1233,8 @@ static struct PyMethodDef rpmts_methods[ {"next", (PyCFunction)rpmts_Next, METH_NOARGS, "ts.next() -> te\n\ - Retrieve next transaction set element.\n" }, + {"setNativeRoot",(PyCFunction) rpmts_SetNativeRoot, METH_VARARGS|METH_KEYWORDS, + NULL }, {NULL, NULL} /* sentinel */ }; @@ -1310,19 +1328,21 @@ static PyObject * rpmts_new(PyTypeObject rpmtsObject * s = (void *) PyObject_New(rpmtsObject, subtype); char * rootDir = "/"; + char * nativeDir = NULL; rpmVSFlags vsflags = rpmExpandNumeric("%{?__vsflags}"); - char * kwlist[] = {"rootdir", "vsflags", 0}; + char * kwlist[] = {"rootdir", "vsflags", "nativeRoot", 0}; if (_rpmts_debug < 0) fprintf(stderr, "*** rpmts_new(%p,%p,%p)\n", s, args, kwds); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_init", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sis:rpmts_init", kwlist, &rootDir, &vsflags)) return NULL; s->ts = rpmtsCreate(); /* XXX: Why is there no rpmts_SetRootDir() ? */ (void) rpmtsSetRootDir(s->ts, rootDir); + (void) rpmtsSetNativeDir(s->ts, nativeDir); /* XXX: make this use common code with rpmts_SetVSFlags() to check the * python objects */ (void) rpmtsSetVSFlags(s->ts, vsflags); diff -rup a/rpmqv.c b/rpmqv.c --- a/rpmqv.c 2009-04-03 07:05:52.000000000 -0400 +++ b/rpmqv.c 2009-08-04 15:44:01.539559986 -0400 @@ -597,6 +597,7 @@ int main(int argc, char *argv[]) ts = rpmtsCreate(); (void) rpmtsSetRootDir(ts, rpmcliRootDir); + (void) rpmtsSetNativeDir(ts, rpmcliNativeRootDir); switch (bigMode) { #ifdef IAM_RPMDB case MODE_INITDB: diff --git a/tools/debugedit.c b/tools/debugedit.c index f42b34a..5d150e8 100644 --- a/tools/debugedit.c +++ b/tools/debugedit.c @@ -1247,6 +1247,56 @@ edit_dwarf2 (DSO *dso) return 0; } +/* The .GCC-command-line section will likely have the RPM_BUILD_ROOT string + in it. This causes check-buildroot to abort the build. Since this section + is informational, just change the string slightly to avoid problems with + check-buildroot. */ +static int +edit_commandline (DSO *dso) +{ + Elf_Data *data; + Elf_Scn *scn; + char *p, *end; + int i, changed; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) + && dso->shdr[i].sh_size) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name); + if (strcmp (name, ".GCC-command-line") == 0) + { + scn = dso->scn[i]; + data = elf_rawdata (scn, NULL); + assert (data != NULL && data->d_buf != NULL); + assert (elf_rawdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[i].sh_size); + + changed = 0; + p = data->d_buf; + end = p + data->d_size - strlen("BUILDR00T"); + while (p < end) + { + /* just change "BUILDROOT" to "BUILDR00T" */ + if (*p == 'B' && strncmp(p, "BUILDROOT", 9) == 0) + { + p[6] = p[7] = '0'; + changed = 1; + p += 9; + } + else + ++p; + } + if (changed) + elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); + } + } + return 0; +} + + static struct poptOption optionsTable[] = { { "base-dir", 'b', POPT_ARG_STRING, &base_dir, 0, "base build directory of objects", NULL }, @@ -1530,7 +1580,7 @@ main (int argc, char *argv[]) if (stat(file, &stat_buf) < 0) { - fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno)); + fprintf (stderr, "Failed to stat input file '%s': %s\n", file, strerror(errno)); exit (1); } @@ -1564,6 +1614,10 @@ main (int argc, char *argv[]) if (strcmp (name, ".debug_info") == 0) edit_dwarf2 (dso); + /* Handle gcc command-line section */ + if (strcmp (name, ".GCC-command-line") == 0) + edit_commandline (dso); + break; case SHT_NOTE: if (do_build_id
-- devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/devel