[PATCH v2 0/2] Running maintscripts for a different architecture
Dear dpkg developers, this is v2 of the patch set I sent last month, which includes a fix to let update-alternatives succeed in offline-mode on distributions not based on Debian, e.g. ArchLinux. altdb_get_namelist() ignored the root directory, so it mistakenly used the host's altdb. I dropped the RFC status, since there was no negative feedback. 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/1411996080-20949-1-git-send-email-...@opendreambox.org
[PATCH v2 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 --- Changes since v1: altdb_get_namelist() didn't respect DPKG_INSTDIR. utils/update-alternatives.c | 171 1 file changed, 109 insertions(+), 62 deletions(-) diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 62675e8..5d15add 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; + + xasprintf(&instdir_f, "%s%s", instdir, f); - if (errno != ENOENT) + 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; } @@ -1084,10 +1147,15 @@ static int altdb_get_namelist(struct dirent ***table) { int count; + char *instdir_admdir; + + xasprintf(&instdir_admdir, "%s%s", instdir, admdir); - count = scandir(admdir, table, altdb_filter_namelist, alphasort); + count = scandir(instdir_admdir, table, altdb_filter_namelist, alphasort); if (count < 0) - syserr(_("cannot scan directory `%.255s'"), admdir); + syserr(_("cannot scan directory `%.255s'"), instdir_admdir); + + free(instdir_admdir); return count; } @@ -1212,7 +1280,6 @@ alternative_parse_fileset(struct alternative *a, struct altdb_context *ctx) { struct fileset *fs; struct slave_link *sl; - struct stat st; char *master_file;
[PATCH v2 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 --- Changes since v1: none 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/1411996080-20949-2-git-send-email-...@opendreambox.org