diff options
author | Andreas Oberritter <obi@opendreambox.org> | 2014-08-27 17:37:20 +0200 |
---|---|---|
committer | Andreas Oberritter <obi@opendreambox.org> | 2017-06-26 22:57:08 +0200 |
commit | ba1ce388bd34a5206b3e113cd7e8ff473e5fef0a (patch) | |
tree | 5180a88dafcd2315e81c3b37c2d5ec08aa863d34 /meta/recipes-devtools/dpkg | |
parent | 1a4f0ffef55a37df5b181eea9655296c531217be (diff) | |
download | openembedded-core-contrib-ba1ce388bd34a5206b3e113cd7e8ff473e5fef0a.tar.gz |
dpkg: implement offline mode for update-alternatives
Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Diffstat (limited to 'meta/recipes-devtools/dpkg')
5 files changed, 460 insertions, 72 deletions
diff --git a/meta/recipes-devtools/dpkg/dpkg.inc b/meta/recipes-devtools/dpkg/dpkg.inc index 1f2911308e..5c42a37905 100644 --- a/meta/recipes-devtools/dpkg/dpkg.inc +++ b/meta/recipes-devtools/dpkg/dpkg.inc @@ -1,11 +1,12 @@ SUMMARY = "Package maintenance system from Debian" LICENSE = "GPLv2.0+" SECTION = "base" +PROVIDES = "virtual/update-alternatives" SRC_URI_append_class-native = " file://0001-When-running-do_package_write_deb-we-have-trees-of-h.patch" DEPENDS = "zlib bzip2 perl ncurses" -DEPENDS_class-native = "bzip2-replacement-native zlib-native virtual/update-alternatives-native gettext-native perl-native" +DEPENDS_class-native = "bzip2-replacement-native zlib-native gettext-native perl-native" RDEPENDS_${PN} = "${VIRTUAL-RUNTIME_update-alternatives} xz run-postinsts perl" RDEPENDS_${PN}_class-native = "xz-native" @@ -45,8 +46,6 @@ do_configure () { do_install_append () { if [ "${PN}" = "dpkg-native" ]; then - # update-alternatives doesn't have an offline mode - rm ${D}${bindir}/update-alternatives sed -i -e 's|^#!.*${bindir}/perl-native.*/perl|#!/usr/bin/env nativeperl|' ${D}${bindir}/dpkg-* else sed -i -e 's|^#!.*${bindir}/perl-native.*/perl|#!/usr/bin/env perl|' ${D}${bindir}/dpkg-* @@ -63,18 +62,11 @@ do_install_append () { fi } -PROV = "virtual/update-alternatives" -PROV_class-native = "" - -PROVIDES += "${PROV}" - PACKAGES =+ "update-alternatives-dpkg" FILES_update-alternatives-dpkg = "${bindir}/update-alternatives ${localstatedir}/lib/dpkg/alternatives ${sysconfdir}/alternatives" -RPROVIDES_update-alternatives-dpkg += "update-alternatives" +RPROVIDES_update-alternatives-dpkg = "update-alternatives" PACKAGES += "${PN}-perl" FILES_${PN}-perl = "${libdir}/perl" BBCLASSEXTEND = "native" - - diff --git a/meta/recipes-devtools/dpkg/dpkg/0003-Our-pre-postinsts-expect-D-to-be-set-when-running-in.patch b/meta/recipes-devtools/dpkg/dpkg/0003-Our-pre-postinsts-expect-D-to-be-set-when-running-in.patch deleted file mode 100644 index 9f77c6c991..0000000000 --- a/meta/recipes-devtools/dpkg/dpkg/0003-Our-pre-postinsts-expect-D-to-be-set-when-running-in.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 24229971492515b64c81e8c6392e5dfbdc22b44c Mon Sep 17 00:00:00 2001 -From: Alexander Kanavin <alex.kanavin@gmail.com> -Date: Wed, 26 Aug 2015 16:25:45 +0300 -Subject: [PATCH 3/5] Our pre/postinsts expect $D to be set when running in a - sysroot and don't expect a chroot. This matches up our system expectations - with what dpkg does. - -Upstream-Status: Inappropriate [OE Specific] - -RP 2011/12/07 ---- - src/script.c | 31 ++----------------------------- - 1 file changed, 2 insertions(+), 29 deletions(-) - -diff --git a/src/script.c b/src/script.c -index a958145..24c49f9 100644 ---- a/src/script.c -+++ b/src/script.c -@@ -100,36 +100,9 @@ maintscript_pre_exec(struct command *cmd) - size_t instdirl = strlen(instdir); - - if (*instdir) { -- if (strncmp(admindir, instdir, instdirl) != 0) -- ohshit(_("admindir must be inside instdir for dpkg to work properly")); -- if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0) -- ohshite(_("unable to setenv for subprocesses")); -- -- if (chroot(instdir)) -- ohshite(_("failed to chroot to '%.250s'"), instdir); -- } -- /* Switch to a known good directory to give the maintainer script -- * a saner environment, also needed after the chroot(). */ -- if (chdir("/")) -- ohshite(_("failed to chdir to '%.255s'"), "/"); -- if (debug_has_flag(dbg_scripts)) { -- struct varbuf args = VARBUF_INIT; -- const char **argv = cmd->argv; -- -- while (*++argv) { -- varbuf_add_char(&args, ' '); -- varbuf_add_str(&args, *argv); -- } -- varbuf_end_str(&args); -- debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename, -- args.buf); -- varbuf_destroy(&args); -+ setenv("D", instdir, 1); - } -- if (!instdirl) -- return cmd->filename; -- -- assert(strlen(cmd->filename) >= instdirl); -- return cmd->filename + instdirl; -+ return cmd->filename; - } - - /** --- -2.1.4 - diff --git a/meta/recipes-devtools/dpkg/dpkg/0007-dpkg-Add-option-cross-bootstrap.patch b/meta/recipes-devtools/dpkg/dpkg/0007-dpkg-Add-option-cross-bootstrap.patch new file mode 100644 index 0000000000..ce0677a88d --- /dev/null +++ b/meta/recipes-devtools/dpkg/dpkg/0007-dpkg-Add-option-cross-bootstrap.patch @@ -0,0 +1,86 @@ +From bc12439e443dc4d2e7a9ddadf60f31db462aa824 Mon Sep 17 00:00:00 2001 +From: Andreas Oberritter <obi@opendreambox.org> +Date: Thu, 28 Aug 2014 04:51:16 +0200 +Subject: [PATCH] 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 <obi@opendreambox.org> +--- + 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 0ff04f1..4decf21 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -137,6 +137,7 @@ usage(const struct cmdinfo *ci, const char *value) + " --admindir=<directory> Use <directory> instead of %s.\n" + " --root=<directory> Install on a different root directory.\n" + " --instdir=<directory> Change installation dir without changing admin dir.\n" ++" --cross-bootstrap Don't chroot into root directory for scripts.\n" + " --path-exclude=<pattern> Do not install paths which match a shell pattern.\n" + " --path-include=<pattern> Re-include a pattern after a previous exclusion.\n" + " -O|--selected-only Skip packages not selected for install/upgrade.\n" +@@ -187,6 +188,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; +@@ -725,6 +727,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, NULL, set_instdir, 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 021d611..5b91f05 100644 +--- a/src/main.h ++++ b/src/main.h +@@ -133,6 +133,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 d9514da..747c27f 100644 +--- a/src/script.c ++++ b/src/script.c +@@ -106,8 +106,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(). */ +@@ -126,7 +128,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); diff --git a/meta/recipes-devtools/dpkg/dpkg/0008-update-alternatives-Implement-offline-mode.patch b/meta/recipes-devtools/dpkg/dpkg/0008-update-alternatives-Implement-offline-mode.patch new file mode 100644 index 0000000000..9377066b7d --- /dev/null +++ b/meta/recipes-devtools/dpkg/dpkg/0008-update-alternatives-Implement-offline-mode.patch @@ -0,0 +1,369 @@ +From 93266aa74d87bd28dbf3c3fd4056bd2f96a40bfc Mon Sep 17 00:00:00 2001 +From: Andreas Oberritter <obi@opendreambox.org> +Date: Thu, 28 Aug 2014 05:20:21 +0200 +Subject: [PATCH] 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 <obi@opendreambox.org> +--- + utils/update-alternatives.c | 168 ++++++++++++++++++++++++++++---------------- + 1 file changed, 106 insertions(+), 62 deletions(-) + +diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c +index 0ea5c81..cbf583f 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"; +@@ -66,6 +67,27 @@ static int opt_force = 0; + #define ALT_TMP_EXT ".dpkg-tmp" + + /* ++ * Types. ++ */ ++ ++enum alternative_path_status { ++ ALT_PATH_SYMLINK, ++ ALT_PATH_MISSING, ++ ALT_PATH_OTHER, ++}; ++ ++ ++/* ++ * Predeclarations. ++ */ ++ ++static char * DPKG_ATTR_PRINTF(1) ++xasprintf(const char *fmt, ...); ++ ++static enum alternative_path_status ++alternative_path_classify(const char *linkname); ++ ++/* + * Functions. + */ + +@@ -272,7 +294,7 @@ xstrdup(const char *str) + } + + static char * +-areadlink(const char *linkname) ++_areadlink(const char *linkname) + { + struct stat st; + char *buf; +@@ -305,6 +327,19 @@ areadlink(const char *linkname) + } + + static char * ++areadlink(const char *linkname) ++{ ++ char *instdir_linkname; ++ char *ret; ++ ++ instdir_linkname = xasprintf("%s%s", instdir, linkname); ++ ret = _areadlink(instdir_linkname); ++ free(instdir_linkname); ++ ++ return ret; ++} ++ ++static char * + xreadlink(const char *linkname) + { + char *buf; +@@ -350,6 +385,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; +@@ -432,25 +479,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; ++ ++ instdir_linkname = xasprintf("%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; ++ ++ instdir_src = xasprintf("%s%s", instdir, src); ++ instdir_dst = xasprintf("%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; ++ ++ instdir_f = xasprintf("%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) +@@ -567,16 +632,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; + } + +@@ -1039,10 +1099,15 @@ static int + altdb_get_namelist(struct dirent ***table) + { + int count; ++ char *instdir_admdir; ++ ++ instdir_admdir = xasprintf("%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; + } +@@ -1167,7 +1232,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")); +@@ -1180,12 +1244,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 (part of link group %s) " +@@ -1248,7 +1309,7 @@ alternative_load(struct alternative *a, enum altdb_flags flags) + ctx.bad_format = altdb_parse_stop; + else + ctx.bad_format = altdb_parse_error; +- ctx.filename = xasprintf("%s/%s", admdir, a->master_name); ++ ctx.filename = xasprintf("%s%s/%s", instdir, admdir, a->master_name); + + /* Open the alternative file. */ + ctx.fh = fopen(ctx.filename, "r"); +@@ -1340,7 +1401,7 @@ alternative_save(struct alternative *a) + file = xasprintf("%s/%s", admdir, a->master_name); + filenew = xasprintf("%s" ALT_TMP_EXT, file); + +- ctx.filename = filenew; ++ ctx.filename = xasprintf("%s%s", instdir, filenew); + ctx.fh = fopen(ctx.filename, "w"); + if (ctx.fh == NULL) + syserr(_("unable to create file '%s'"), ctx.filename); +@@ -1379,6 +1440,7 @@ alternative_save(struct alternative *a) + syserr(_("unable to sync file '%s'"), ctx.filename); + if (fclose(ctx.fh)) + syserr(_("unable to close file '%s'"), ctx.filename); ++ free(ctx.filename); + + /* Put in place atomically. */ + checked_mv(filenew, file); +@@ -1399,7 +1461,6 @@ alternative_set_current(struct alternative *a, char *new_choice) + static const char * + alternative_get_current(struct alternative *a) + { +- struct stat st; + char *curlink; + char *file; + +@@ -1407,12 +1468,9 @@ alternative_get_current(struct alternative *a) + return a->current; + + curlink = xasprintf("%s/%s", altdir, a->master_name); +- if (lstat(curlink, &st)) { +- if (errno == ENOENT) { +- free(curlink); +- return alternative_set_current(a, NULL); +- } +- syserr(_("cannot stat file '%s'"), curlink); ++ if (alternative_path_classify(curlink) == ALT_PATH_MISSING) { ++ free(curlink); ++ return alternative_set_current(a, NULL); + } + + file = xreadlink(curlink); +@@ -1674,14 +1732,8 @@ alternative_commit(struct alternative *a) + alternative_commit_operations_free(a); + } + +-enum alternative_path_status { +- ALT_PATH_SYMLINK, +- ALT_PATH_MISSING, +- ALT_PATH_OTHER, +-}; +- + static enum alternative_path_status +-alternative_path_classify(const char *linkname) ++_alternative_path_classify(const char *linkname) + { + struct stat st; + +@@ -1697,6 +1749,19 @@ alternative_path_classify(const char *linkname) + } + } + ++static enum alternative_path_status ++alternative_path_classify(const char *linkname) ++{ ++ enum alternative_path_status ret; ++ char *instdir_linkname; ++ ++ instdir_linkname = xasprintf("%s%s", instdir, linkname); ++ ret = _alternative_path_classify(instdir_linkname); ++ free(instdir_linkname); ++ ++ return ret; ++} ++ + static bool + alternative_path_can_remove(const char *linkname) + { +@@ -2120,13 +2185,7 @@ alternative_select_mode(struct alternative *a, const char *current_choice) + if (current_choice) { + /* Detect manually modified alternative, switch to manual. */ + if (!alternative_has_choice(a, current_choice)) { +- struct stat st; +- +- errno = 0; +- if (stat(current_choice, &st) == -1 && errno != ENOENT) +- syserr(_("cannot stat file '%s'"), current_choice); +- +- if (errno == ENOENT) { ++ if (alternative_path_classify(current_choice) == ALT_PATH_MISSING) { + warning(_("%s/%s is dangling; it will be updated " + "with best choice"), altdir, a->master_name); + alternative_set_status(a, ALT_ST_AUTO); +@@ -2149,7 +2208,6 @@ static void + alternative_evolve_slave(struct alternative *a, const char *cur_choice, + struct slave_link *sl, struct fileset *fs) + { +- struct stat st; + char *new_file = NULL; + const char *old, *new; + +@@ -2167,17 +2225,7 @@ alternative_evolve_slave(struct alternative *a, const char *cur_choice, + } + if (strcmp(old, new) != 0 && + alternative_path_classify(old) == ALT_PATH_SYMLINK) { +- bool rename_link = false; +- +- if (new_file) { +- errno = 0; +- if (stat(new_file, &st) == -1 && errno != ENOENT) +- syserr(_("cannot stat file '%s'"), +- new_file); +- rename_link = (errno == 0); +- } +- +- if (rename_link) { ++ if (new_file && alternative_path_classify(new_file) != ALT_PATH_MISSING) { + info(_("renaming %s slave link from %s to %s"), + sl->name, old, new); + checked_mv(old, new); +@@ -2471,7 +2519,6 @@ alternative_check_install_args(struct alternative *inst_alt, + struct alternative_map *alt_map_links, *alt_map_parent; + struct alternative *found; + struct slave_link *sl; +- struct stat st; + + alternative_check_name(inst_alt->master_name); + alternative_check_link(inst_alt->master_link); +@@ -2496,13 +2543,9 @@ alternative_check_install_args(struct alternative *inst_alt, + inst_alt->master_link, found->master_name); + } + +- if (stat(fileset->master_file, &st) == -1) { +- if (errno == ENOENT) +- error(_("alternative path %s doesn't exist"), +- fileset->master_file); +- else +- syserr(_("cannot stat file '%s'"), fileset->master_file); +- } ++ if (alternative_path_classify(fileset->master_file) == ALT_PATH_MISSING) ++ error(_("alternative path %s doesn't exist"), ++ fileset->master_file); + + for (sl = inst_alt->slaves; sl; sl = sl->next) { + const char *file = fileset_get_slave(fileset, sl->name); +@@ -2577,6 +2620,7 @@ main(int argc, char **argv) + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + ++ instdir = instdir_init(); + admdir = admindir_init(); + + if (setvbuf(stdout, NULL, _IONBF, 0)) diff --git a/meta/recipes-devtools/dpkg/dpkg_1.18.4.bb b/meta/recipes-devtools/dpkg/dpkg_1.18.4.bb index 5eb42de6a0..96728c188f 100644 --- a/meta/recipes-devtools/dpkg/dpkg_1.18.4.bb +++ b/meta/recipes-devtools/dpkg/dpkg_1.18.4.bb @@ -9,10 +9,11 @@ SRC_URI += "http://snapshot.debian.org/archive/debian/20160509T100042Z/pool/main file://dpkg-configure.service \ file://add_armeb_triplet_entry.patch \ file://0002-Adapt-to-linux-wrs-kernel-version-which-has-characte.patch \ - file://0003-Our-pre-postinsts-expect-D-to-be-set-when-running-in.patch \ file://0004-The-lutimes-function-doesn-t-work-properly-for-all-s.patch \ file://0005-dpkg-compiler.m4-remove-Wvla.patch \ file://0006-add-musleabi-to-known-target-tripets.patch \ + file://0007-dpkg-Add-option-cross-bootstrap.patch \ + file://0008-update-alternatives-Implement-offline-mode.patch \ " SRC_URI_append_class-native =" file://glibc2.5-sync_file_range.patch " |