[PATCH v2 0/2] Running maintscripts for a different architecture

2014-09-29 Thread Andreas Oberritter
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

2014-09-29 Thread Andreas Oberritter
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

2014-09-29 Thread Andreas Oberritter
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