[RFC PATCH 1/2] dpkg: Add option --cross-bootstrap
If --cross-bootstrap is set, don't chroot into the target root directory, but just export DPKG_INSTDIR for the execution of maintscripts. This is useful for Yocto/OpenEmbedded, where programs like update-alternatives, update-rc.d or systemctl run natively or emulated on the build system when creating the cross-compiled root filesystem with apt-get. Signed-off-by: Andreas Oberritter --- src/main.c | 3 +++ src/main.h | 1 + src/script.c | 6 -- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 65c3626..cd0f395 100644 --- a/src/main.c +++ b/src/main.c @@ -134,6 +134,7 @@ usage(const struct cmdinfo *ci, const char *value) " --admindir= Use instead of %s.\n" " --root= Install on a different root directory.\n" " --instdir= Change installation dir without changing admin dir.\n" +" --cross-bootstrap Don't chroot into root directory for scripts.\n" " --path-exclude= Do not install paths which match a shell pattern.\n" " --path-include= Re-include a pattern after a previous exclusion.\n" " -O|--selected-only Skip packages not selected for install/upgrade.\n" @@ -184,6 +185,7 @@ static const char printforhelp[] = N_( int f_pending=0, f_recursive=0, f_alsoselect=1, f_skipsame=0, f_noact=0; int f_autodeconf=0, f_nodebsig=0; int f_triggers = 0; +int f_cross = 0; int fc_downgrade=1, fc_configureany=0, fc_hold=0, fc_removereinstreq=0, fc_overwrite=0; int fc_removeessential=0, fc_conflicts=0, fc_depends=0, fc_dependsversion=0; int fc_breaks=0, fc_badpath=0, fc_overwritediverted=0, fc_architecture=0; @@ -711,6 +713,7 @@ static const struct cmdinfo cmdinfos[]= { { "abort-after", 0, 1, &errabort, NULL, set_integer, 0 }, { "admindir", 0, 1, NULL, &admindir, NULL, 0 }, { "instdir", 0, 1, NULL, &instdir, NULL, 0 }, + { "cross-bootstrap", 0, 0, &f_cross, NULL, NULL, 1 }, { "ignore-depends",0, 1, NULL, NULL, set_ignore_depends, 0 }, { "force", 0, 2, NULL, NULL, set_force, 1 }, { "refuse",0, 2, NULL, NULL, set_force, 0 }, diff --git a/src/main.h b/src/main.h index 5a35808..1b6d78a 100644 --- a/src/main.h +++ b/src/main.h @@ -124,6 +124,7 @@ extern const char *const statusstrings[]; extern int f_pending, f_recursive, f_alsoselect, f_skipsame, f_noact; extern int f_autodeconf, f_nodebsig; extern int f_triggers; +extern int f_cross; extern int fc_downgrade, fc_configureany, fc_hold, fc_removereinstreq, fc_overwrite; extern int fc_removeessential, fc_conflicts, fc_depends, fc_dependsversion; extern int fc_breaks, fc_badpath, fc_overwritediverted, fc_architecture; diff --git a/src/script.c b/src/script.c index d552f3f..4a56cdc 100644 --- a/src/script.c +++ b/src/script.c @@ -105,8 +105,10 @@ maintscript_pre_exec(struct command *cmd) if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0) ohshite(_("unable to setenv for subprocesses")); - if (chroot(instdir)) + if (!f_cross && chroot(instdir)) ohshite(_("failed to chroot to `%.250s'"), instdir); + if (setenv("DPKG_INSTDIR", f_cross ? instdir : "", 1) < 0) + ohshite(_("unable to setenv for subprocesses")); } /* Switch to a known good directory to give the maintainer script * a saner environment, also needed after the chroot(). */ @@ -125,7 +127,7 @@ maintscript_pre_exec(struct command *cmd) args.buf); varbuf_destroy(&args); } - if (!instdirl) + if (f_cross || !instdirl) return cmd->filename; assert(strlen(cmd->filename) >= instdirl); -- 1.9.1 -- To UNSUBSCRIBE, email to debian-dpkg-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: https://lists.debian.org/1409230398-18083-2-git-send-email-...@opendreambox.org
[RFC PATCH 0/2] Running maintscripts for a different architecture
Dear dpkg developers, in OE-Core (Yocto / OpenEmbedded Core), we cross-compile complete distributions and create root filesystem images. You can choose between several package formats (deb, ipk, rpm) and related managers. Because these root filesystems usually are built for an architecture (instruction set) that's incompatible with the build system's CPU, dpkg's habit of chrooting into the 'instdir' before running maintscripts (if the --root option was given) doesn't work. To compensate, we can add a new option --cross-bootstrap, which stops dpkg from chrooting and instead exports DPKG_INSTDIR for maintscripts. Then we can adjust update-alternatives to use this variable, in order to be able to use it in a cross-compile environment. Previously, we had to use a different implementation of update-alternatives, that comes with opkg. So far, I've successfully tested these patches to create root filesystems, i.e. "update-alternatives --install". The other options still need testing, but at least with an empty or unset DPKG_INSTDIR, nothing should have changed. The second patch has room for improvements, e.g. you seem to avoid using predeclarations, and I believe calling alternative_path_classify() from fileset_*() may violate your coding style. But I'd like to get some feedback first, in order to be able fix it properly. I could also split the patch into smaller components: 1.) Predeclare/move/rename alternative_path_classify and enum alternative_path_status. 2.) Replace direct use of stat with calls to alternative_path_classify where possible. 3.) Predeclare/move xasprintf. 4.) Introduce instdir. Best regards, Andreas Andreas Oberritter (2): dpkg: Add option --cross-bootstrap update-alternatives: Implement offline mode src/main.c | 3 + src/main.h | 1 + src/script.c| 6 +- utils/update-alternatives.c | 162 4 files changed, 110 insertions(+), 62 deletions(-) -- 1.9.1 -- To UNSUBSCRIBE, email to debian-dpkg-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: https://lists.debian.org/1409230398-18083-1-git-send-email-...@opendreambox.org
[RFC PATCH 2/2] update-alternatives: Implement offline mode
Lets update-alternatives manage symlinks inside a cross-arch root filesystem in a directory specified by DPKG_INSTDIR. Signed-off-by: Andreas Oberritter --- utils/update-alternatives.c | 162 1 file changed, 102 insertions(+), 60 deletions(-) diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 62675e8..83d5d9e 100644 --- a/utils/update-alternatives.c +++ b/utils/update-alternatives.c @@ -51,6 +51,7 @@ #define PROGNAME "update-alternatives" static const char *altdir = SYSCONFDIR "/alternatives"; +static const char *instdir; static const char *admdir; static const char *prog_path = "update-alternatives"; @@ -71,6 +72,27 @@ static int nb_opts = 0; #define ALT_TMP_EXT ".dpkg-tmp" /* + * Types. + */ + +enum alternative_path_status { + ALT_PATH_SYMLINK, + ALT_PATH_MISSING, + ALT_PATH_OTHER, +}; + + +/* + * Predeclarations. + */ + +static int DPKG_ATTR_PRINTF(2) +xasprintf(char **strp, const char *fmt, ...); + +static enum alternative_path_status +alternative_path_classify(const char *linkname); + +/* * Functions. */ @@ -277,7 +299,7 @@ xstrdup(const char *str) } static char * -areadlink(const char *linkname) +_areadlink(const char *linkname) { struct stat st; char *buf; @@ -310,6 +332,22 @@ areadlink(const char *linkname) } static char * +areadlink(const char *linkname) +{ + char *instdir_linkname; + int saved_errno; + char *ret; + + xasprintf(&instdir_linkname, "%s%s", instdir, linkname); + ret = _areadlink(instdir_linkname); + saved_errno = errno; + free(instdir_linkname); + errno = saved_errno; + + return ret; +} + +static char * xreadlink(const char *linkname) { char *buf; @@ -356,6 +394,18 @@ set_action(const char *new_action) } static const char * +instdir_init(void) +{ + const char *dpkg_instdir; + + dpkg_instdir = getenv("DPKG_INSTDIR"); + if (dpkg_instdir) + return dpkg_instdir; + + return ""; +} + +static const char * admindir_init(void) { const char *basedir, *dpkg_basedir; @@ -477,25 +527,43 @@ rename_mv(const char *src, const char *dst) static void checked_symlink(const char *filename, const char *linkname) { - if (symlink(filename, linkname)) + char *instdir_linkname; + + xasprintf(&instdir_linkname, "%s%s", instdir, linkname); + + if (symlink(filename, instdir_linkname)) syserr(_("error creating symbolic link `%.255s'"), linkname); + + free(instdir_linkname); } static void checked_mv(const char *src, const char *dst) { - if (!rename_mv(src, dst)) + char *instdir_src; + char *instdir_dst; + + xasprintf(&instdir_src, "%s%s", instdir, src); + xasprintf(&instdir_dst, "%s%s", instdir, dst); + + if (!rename_mv(instdir_src, instdir_dst)) syserr(_("unable to install `%.250s' as `%.250s'"), src, dst); + + free(instdir_src); + free(instdir_dst); } static void checked_rm(const char *f) { - if (!unlink(f)) - return; + char *instdir_f; - if (errno != ENOENT) + xasprintf(&instdir_f, "%s%s", instdir, f); + + if (unlink(instdir_f) && errno != ENOENT) syserr(_("unable to remove '%s'"), f); + + free(instdir_f); } static void DPKG_ATTR_PRINTF(1) @@ -612,16 +680,11 @@ fileset_has_slave(struct fileset *fs, const char *name) static bool fileset_can_install_slave(struct fileset *fs, const char *slave_name) { - struct stat st; - /* Decide whether the slave alternative must be setup */ if (fileset_has_slave(fs, slave_name)) { const char *slave = fileset_get_slave(fs, slave_name); - errno = 0; - if (stat(slave, &st) == -1 && errno != ENOENT) - syserr(_("cannot stat file '%s'"), slave); - if (errno == 0) + if (alternative_path_classify(slave) != ALT_PATH_MISSING) return true; } @@ -1212,7 +1275,6 @@ alternative_parse_fileset(struct alternative *a, struct altdb_context *ctx) { struct fileset *fs; struct slave_link *sl; - struct stat st; char *master_file; master_file = altdb_get_line(ctx, _("master file")); @@ -1225,12 +1287,9 @@ alternative_parse_fileset(struct alternative *a, struct altdb_context *ctx) if (fs) ctx->bad_format(ctx, _("duplicate path %s"), master_file); - if (stat(master_file, &st)) { + if (alternative_path_classify(master_file) == ALT_PATH_MISSING) { char *junk; - if (errno != ENOENT) - syserr(_("cannot stat file '%s'"), master_file); - /* File not found - remove. */ if (ctx->flags & ALTDB_WARN_PARSER) warning(_("alternative %s