From e72a040628d7b8b5fd193653c13304f47cba611b Mon Sep 17 00:00:00 2001 From: Dmitry Rozhkov Date: Tue, 23 Feb 2016 15:11:58 +0200 Subject: [PATCH] Add compatibility with libarchive's bsdtar command Since GNU tar fails to extract files with xattrs preserved when Integrity Measurement Architecture (IMA) is enabled some vendors may choose to install libarchive-based tar (bsdtar) on their embedded devices, so the swupd server needs to be able to create archives in its format. This patch adds one compile-time options --enable-bsdtar that is used to enable/disable GNU tar specific options. Also it harmonizes the command strings to be compatible with both GNU tar and bsdtar. Particularly it - changes --exclude pattern from '%s'/* to more explicit '%s/?*' because bsdtar's pattern matching is greedier than in tar: it uses tcsh's globbing where '*' can be anything including the null string and the original pattern would include the directory itself; - OS file names are escaped with leading ./ to avoid collisions with file names starting with @ which has special meaning in bsdtar. Upstream-Status: Accepted Signed-off-by: Dmitry Rozhkov --- configure.ac | 8 ++++++++ include/swupd.h | 14 ++++++++++++-- src/fullfiles.c | 12 ++++++------ src/manifest.c | 2 +- src/pack.c | 4 ++-- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 47256b6..32d1412 100644 --- a/configure.ac +++ b/configure.ac @@ -15,6 +15,14 @@ PKG_CHECK_MODULES([openssl], [libcrypto >= 0.9.8]) AC_CHECK_LIB([magic], [magic_open], [], [AC_MSG_ERROR([the magic library is missing])]) AC_CHECK_PROGS(TAR, tar) AC_ARG_ENABLE( + bsdtar, + AS_HELP_STRING([--enable-bsdtar],[Use alternative bsdtar command (uses tar by default)]), + AS_IF([test "x$enable_bsdtar" = "xyes"], + AC_DEFINE([SWUPD_WITH_BSDTAR], 1, [Use alternative bsdtar]), + AC_DEFINE([SWUPD_WITH_BSDTAR], 0, [Use default tar command])), + AC_DEFINE([SWUPD_WITH_BSDTAR], 0, [Use default tar command]) +) +AC_ARG_ENABLE( bzip2, AS_HELP_STRING([--disable-bzip2],[Do not use bzip2 compression (uses bzip2 by default)]), AC_DEFINE(SWUPD_WITHOUT_BZIP2,1,[Do not use bzip2 compression]) , diff --git a/include/swupd.h b/include/swupd.h index d45ca9c..b049135 100644 --- a/include/swupd.h +++ b/include/swupd.h @@ -17,10 +17,20 @@ #define SWUPD_SERVER_STATE_DIR "/var/lib/update" +#if SWUPD_WITH_BSDTAR +#define TAR_COMMAND "bsdtar" +#define TAR_XATTR_ARGS "" +#define TAR_WARN_ARGS "" +#else +#define TAR_COMMAND "tar" +#define TAR_XATTR_ARGS "--xattrs --xattrs-include='*'" +#define TAR_WARN_ARGS "--warning=no-timestamp" +#endif + #if SWUPD_WITH_SELINUX -#define TAR_PERM_ATTR_ARGS "--preserve-permissions --xattrs --xattrs-include='*' --selinux" +#define TAR_PERM_ATTR_ARGS "--preserve-permissions --selinux " TAR_XATTR_ARGS #else -#define TAR_PERM_ATTR_ARGS "--preserve-permissions --xattrs --xattrs-include='*'" +#define TAR_PERM_ATTR_ARGS "--preserve-permissions " TAR_XATTR_ARGS #endif #if SWUPD_WITH_STATELESS diff --git a/src/fullfiles.c b/src/fullfiles.c index 23e95db..cf77e74 100644 --- a/src/fullfiles.c +++ b/src/fullfiles.c @@ -93,8 +93,8 @@ static void create_fullfile(struct file *file) assert(0); } - string_or_die(&tarcommand, "tar -C %s " TAR_PERM_ATTR_ARGS " -cf - --exclude='%s'/* '%s' 2> /dev/null | " - "tar -C %s " TAR_PERM_ATTR_ARGS " -xf - 2> /dev/null", + string_or_die(&tarcommand, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -cf - --exclude='%s/?*' './%s' 2> /dev/null | " + TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -xf - 2> /dev/null", dir, base, base, rename_tmpdir); if (system(tarcommand) != 0) { LOG(NULL, "Failed to run command:", "%s", tarcommand); @@ -111,7 +111,7 @@ static void create_fullfile(struct file *file) free(rename_source); /* for a directory file, tar up simply with gzip */ - string_or_die(&tarcommand, "tar -C %s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar %s", + string_or_die(&tarcommand, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar %s", rename_tmpdir, outdir, file->last_change, file->hash, file->hash); if (system(tarcommand) != 0) { LOG(NULL, "Failed to run command:", "%s", tarcommand); @@ -146,7 +146,7 @@ static void create_fullfile(struct file *file) /* step 2a: tar it with each compression type */ // lzma - string_or_die(&tarcommand, "tar --directory=%s " TAR_PERM_ATTR_ARGS " -Jcf %s/%i/files/%s.tar.xz %s", + string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -Jcf %s/%i/files/%s.tar.xz %s", empty, outdir, file->last_change, file->hash, file->hash); if (system(tarcommand) != 0) { LOG(NULL, "Failed to run command:", "%s", tarcommand); @@ -154,7 +154,7 @@ static void create_fullfile(struct file *file) } free(tarcommand); // gzip - string_or_die(&tarcommand, "tar --directory=%s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar.gz %s", + string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -zcf %s/%i/files/%s.tar.gz %s", empty, outdir, file->last_change, file->hash, file->hash); if (system(tarcommand) != 0) { LOG(NULL, "Failed to run command:", "%s", tarcommand); @@ -162,7 +162,7 @@ static void create_fullfile(struct file *file) } free(tarcommand); #ifdef SWUPD_WITH_BZIP2 - string_or_die(&tarcommand, "tar --directory=%s " TAR_PERM_ATTR_ARGS " -jcf %s/%i/files/%s.tar.bz2 %s", + string_or_die(&tarcommand, TAR_COMMAND " --directory=%s " TAR_PERM_ATTR_ARGS " -jcf %s/%i/files/%s.tar.bz2 %s", empty, outdir, file->last_change, file->hash, file->hash); if (system(tarcommand) != 0) { LOG(NULL, "Failed to run command:", "%s", tarcommand); diff --git a/src/manifest.c b/src/manifest.c index e878288..cf0cabf 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -750,7 +750,7 @@ static int write_manifest_tar(struct manifest *manifest) /* now, tar the thing up for efficient full file download */ /* and put the signature of the plain manifest into the archive, too */ - string_or_die(&tarcmd, "tar --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf " + string_or_die(&tarcmd, TAR_COMMAND " --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf " "%s/%i/Manifest.%s.tar Manifest.%s Manifest.%s.signed", conf, manifest->version, conf, manifest->version, manifest->component, manifest->component, manifest->component); diff --git a/src/pack.c b/src/pack.c index e5203d0..1a11a03 100644 --- a/src/pack.c +++ b/src/pack.c @@ -113,7 +113,7 @@ static void explode_pack_stage(int version, char *module) * the resulting pack is slightly smaller, and in addition, we're saving CPU * time on the client... */ - string_or_die(&tar, "tar --directory=%s/%s/%i/staged --warning=no-timestamp " + string_or_die(&tar, TAR_COMMAND " --directory=%s/%s/%i/staged " TAR_WARN_ARGS " " TAR_PERM_ATTR_ARGS " -xf %s", packstage_dir, module, version, path); ret = system(tar); if (!ret) { @@ -442,7 +442,7 @@ static int make_final_pack(struct packdata *pack) /* tar the staging directory up */ LOG(NULL, "starting tar for pack", "%s: %i to %i", pack->module, pack->from, pack->to); - string_or_die(&tar, "tar " TAR_PERM_ATTR_ARGS " --directory=%s/%s/%i/ " + string_or_die(&tar, TAR_COMMAND " " TAR_PERM_ATTR_ARGS " --directory=%s/%s/%i/ " "--numeric-owner -Jcf %s/%i/pack-%s-from-%i.tar delta staged", packstage_dir, pack->module, pack->from, staging_dir, pack->to, pack->module, pack->from); ret = system(tar); -- 2.5.0