This repository has been archived by the owner on Apr 19, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
swupd-client: Update the client and server to use bsdtar
This patch adds bsdtar support to swupd-client and swupd-server and enables it. The reason why it's done this way is that: - bsdtar works better with IMA (opens files only once and then updates content and xattrs together); - swupd remains fully functional, including xattrs support, even when a distro disables GPLv3 licensed code. Signed-off-by: Dmitry Rozhkov <[email protected]>
- Loading branch information
Dmitry Rozhkov
committed
Mar 30, 2016
1 parent
215ff54
commit d0326c5
Showing
8 changed files
with
692 additions
and
5 deletions.
There are no files selected for viewing
96 changes: 96 additions & 0 deletions
96
...e/swupd-client/swupd-client/0005-swupd-client-Add-existence-check-to-staging-target.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
From 1f37511e52754f7231c52489ba4f7d8f7de1e2af Mon Sep 17 00:00:00 2001 | ||
From: "Brad T. Peters" <[email protected]> | ||
Date: Thu, 7 Jan 2016 14:37:17 -0800 | ||
Subject: [PATCH] swupd-client: Add existence check to staging target | ||
|
||
Patch adds an stat() check to ensure that: | ||
1. target path for a staged file exists, and | ||
2. target path is indeed a directory | ||
|
||
Follow-on patch will add correct corrective behavior once | ||
verify_fix_path() is implemented | ||
|
||
Upstream-Status: Accepted | ||
|
||
Signed-off-by: Brad T. Peters <[email protected]> | ||
--- | ||
src/staging.c | 39 ++++++++++++++++++++++++++++++++------- | ||
1 file changed, 32 insertions(+), 7 deletions(-) | ||
|
||
diff --git a/src/staging.c b/src/staging.c | ||
index 3a847e2..b8545c1 100644 | ||
--- a/src/staging.c | ||
+++ b/src/staging.c | ||
@@ -277,9 +277,11 @@ int do_staging(struct file *file) | ||
#if SWUPD_LINUX_ROOTFS | ||
char *original = NULL; | ||
char *target = NULL; | ||
+ char *targetpath = NULL; | ||
+ char *symbase = NULL; | ||
#endif | ||
int ret; | ||
- struct stat stat; | ||
+ struct stat s; | ||
|
||
tmp = strdup(file->filename); | ||
tmp2 = strdup(file->filename); | ||
@@ -294,6 +296,29 @@ int do_staging(struct file *file) | ||
string_or_die(&original, "%s/staged/%s", STATE_DIR, file->hash); | ||
|
||
#if SWUPD_LINUX_ROOTFS | ||
+ string_or_die(&targetpath, "%s%s", path_prefix, rel_dir); | ||
+ ret = stat(targetpath, &s); | ||
+ | ||
+ if (S_ISLNK(s.st_mode)) { | ||
+ /* Follow symlink to ultimate target and redo stat */ | ||
+ symbase = realpath(targetpath, NULL); | ||
+ if (symbase != NULL) { | ||
+ free(targetpath); | ||
+ targetpath = strdup(symbase); | ||
+ ret = stat(targetpath, &s); | ||
+ free(symbase); | ||
+ } | ||
+ } | ||
+ | ||
+ /* For now, just report on error conditions. Once we implement | ||
+ * verify_fix_path(char *path, int targetversion), we'll want to call it here */ | ||
+ if ((ret == -1) && (errno == ENOENT)) { | ||
+ printf("Error: Update target directory does not exist: %s\n", targetpath); | ||
+ } else if (!S_ISDIR(s.st_mode)) { | ||
+ printf("Error: Update target exists but is NOT a directory: %s\n", targetpath); | ||
+ } | ||
+ | ||
+ free(targetpath); | ||
string_or_die(&target, "%s%s/.update.%s", path_prefix, rel_dir, base); | ||
ret = swupd_rm(target); | ||
if (ret == 0) | ||
@@ -306,12 +331,12 @@ int do_staging(struct file *file) | ||
string_or_die(&statfile, "%s/%s/%s", STAGING_SUBVOL, rel_dir, base); | ||
#endif | ||
|
||
- memset(&stat, 0, sizeof(struct stat)); | ||
- ret = lstat(statfile, &stat); | ||
+ memset(&s, 0, sizeof(struct stat)); | ||
+ ret = lstat(statfile, &s); | ||
if (ret == 0) { | ||
- if ((file->is_dir && !S_ISDIR(stat.st_mode)) || | ||
- (file->is_link && !S_ISLNK(stat.st_mode)) || | ||
- (file->is_file && !S_ISREG(stat.st_mode))) { | ||
+ if ((file->is_dir && !S_ISDIR(s.st_mode)) || | ||
+ (file->is_link && !S_ISLNK(s.st_mode)) || | ||
+ (file->is_file && !S_ISREG(s.st_mode))) { | ||
LOG_INFO(file, "Type changed!", class_osvol_staging, "%s", statfile); | ||
//file type changed, move old out of the way for new | ||
ret = swupd_rm(statfile); | ||
@@ -325,7 +350,7 @@ int do_staging(struct file *file) | ||
free(statfile); | ||
|
||
#if SWUPD_LINUX_ROOTFS | ||
- if (file->is_dir || S_ISDIR(stat.st_mode)) { | ||
+ if (file->is_dir || S_ISDIR(s.st_mode)) { | ||
/* In the btrfs only scenario there is an implicit | ||
* "create_or_update_dir()" via un-tar-ing a directory.tar after | ||
* download and the untar happens in the staging subvolume which | ||
-- | ||
2.5.0 | ||
|
157 changes: 157 additions & 0 deletions
157
...es-core/swupd-client/swupd-client/0006-Backport-Use-rename-instead-of-tar-transform.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
From e9ad32a273efe2d177c1bbd394ae944ae598fd50 Mon Sep 17 00:00:00 2001 | ||
From: Dmitry Rozhkov <[email protected]> | ||
Date: Mon, 8 Feb 2016 18:12:48 +0200 | ||
Subject: [PATCH] Backport: Use rename instead of tar transform | ||
|
||
This patch is a backport from swupd-client v2.88 | ||
Author: William Douglas <[email protected]> | ||
Subject: Use rename instead of tar transform | ||
|
||
In order to prevent issues with transform name escaping, update logic | ||
for moving an object from staging. First rename the object in the | ||
staging path to its final name (in case of a directory the rename places | ||
it in a seperate directory first to avoid hash colisions), then use tar | ||
to update or create the object in the filesystem. Once finished rename | ||
the object back to the hash name so it can be reused as needed. | ||
|
||
This also fixes up some issues with the SWUPD_LINUX_ROOTFS checks not | ||
always encapsulating variable use within the do_staging function. | ||
|
||
Note: the SWUPD_LINUX_ROOTFS checks have been removed entirely, since | ||
they are not used anywhere in the code at present. | ||
|
||
Upstream-Status: Backported [v2.88] | ||
|
||
Signed-off-by: Dmitry Rozhkov <[email protected]> | ||
--- | ||
src/staging.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- | ||
1 file changed, 67 insertions(+), 6 deletions(-) | ||
|
||
diff --git a/src/staging.c b/src/staging.c | ||
index b8545c1..16dafbb 100644 | ||
--- a/src/staging.c | ||
+++ b/src/staging.c | ||
@@ -36,6 +36,31 @@ | ||
#include "swupd-build-variant.h" | ||
#include <swupd.h> | ||
|
||
+/* clean then recreate temporary folder for tar renames */ | ||
+static int create_staging_renamedir(char *rename_tmpdir) | ||
+{ | ||
+ int ret; | ||
+ char *rmcommand = NULL; | ||
+ | ||
+ string_or_die(&rmcommand, "rm -fr %s", rename_tmpdir); | ||
+ if (!system(rmcommand)) { | ||
+ /* Not fatal but pretty scary, likely to really fail at the | ||
+ * next command too. Pass for now as printing may just cause | ||
+ * confusion */ | ||
+ ; | ||
+ } | ||
+ free(rmcommand); | ||
+ | ||
+ ret = mkdir(rename_tmpdir, S_IRWXU); | ||
+ if (ret == -1 && errno != EEXIST) { | ||
+ ret = -errno; | ||
+ } else { | ||
+ ret = 0; | ||
+ } | ||
+ | ||
+ return ret; | ||
+} | ||
+ | ||
#ifdef SWUPD_WITH_BTRFS | ||
static int create_staging_subvol_from(const char *version) | ||
{ | ||
@@ -269,6 +294,9 @@ int prepare(bool UNUSED_PARAM *is_corrupted, int UNUSED_PARAM current_version, i | ||
#endif | ||
|
||
/* Do the staging of new files into the filesystem */ | ||
+#warning do_staging is currently not able to be run in parallel | ||
+/* Consider adding a remove_leftovers() that runs in verify/fix in order to | ||
+ * allow this function to mkdtemp create folders for parallel build */ | ||
int do_staging(struct file *file) | ||
{ | ||
char *statfile = NULL, *tmp = NULL, *tmp2 = NULL; | ||
@@ -280,6 +308,8 @@ int do_staging(struct file *file) | ||
char *targetpath = NULL; | ||
char *symbase = NULL; | ||
#endif | ||
+ char *rename_target = NULL; | ||
+ char *rename_tmpdir = NULL; | ||
int ret; | ||
struct stat s; | ||
|
||
@@ -360,12 +390,28 @@ int do_staging(struct file *file) | ||
* attributes and it includes internal logic that does the | ||
* right thing to overlay a directory onto something | ||
* pre-existing: */ | ||
- string_or_die(&tarcommand, "tar -C %s/staged " TAR_PERM_ATTR_ARGS " -cf - %s 2> /dev/null | " | ||
- "tar -C %s%s " TAR_PERM_ATTR_ARGS " -xf - --transform=\"s/%s/%s/\" 2> /dev/null", | ||
- STATE_DIR, file->hash, path_prefix, rel_dir, file->hash, base); | ||
+ /* In order to avoid tar transforms with directories, rename | ||
+ * the directory before and after the tar command */ | ||
+ string_or_die(&rename_tmpdir, "%s/tmprenamedir", STATE_DIR); | ||
+ ret = create_staging_renamedir(rename_tmpdir); | ||
+ if (ret) { | ||
+ goto out; | ||
+ } | ||
+ string_or_die(&rename_target, "%s/%s", rename_tmpdir, base); | ||
+ if (rename(original, rename_target)) { | ||
+ ret = -errno; | ||
+ goto out; | ||
+ } | ||
+ string_or_die(&tarcommand, "tar -C %s " TAR_PERM_ATTR_ARGS " -cf - %s 2> /dev/null | " | ||
+ "tar -C %s%s " TAR_PERM_ATTR_ARGS " -xf - 2> /dev/null", | ||
+ rename_tmpdir, base, path_prefix, rel_dir); | ||
LOG_DEBUG(file, "directory overwrite", class_osvol_staging, "%s", tarcommand); | ||
ret = system(tarcommand); | ||
free(tarcommand); | ||
+ if (rename(rename_target, original)) { | ||
+ ret = -errno; | ||
+ goto out; | ||
+ } | ||
if (ret < 0) { | ||
LOG_ERROR(file, "Failed directory overwrite", class_osvol_staging, "%s", strerror(errno)); | ||
ret = -EDIR_OVERWRITE; | ||
@@ -386,12 +432,25 @@ int do_staging(struct file *file) | ||
} | ||
if (ret < 0) { | ||
/* either the hardlink failed, or it was undesirable (config), do a tar-tar dance */ | ||
- string_or_die(&tarcommand, "tar -C %s/staged " TAR_PERM_ATTR_ARGS " -cf - %s 2> /dev/null | " | ||
- "tar -C %s%s " TAR_PERM_ATTR_ARGS " -xf - --transform=\"s/%s/.update.%s/\" 2> /dev/null", | ||
- STATE_DIR, file->hash, path_prefix, rel_dir, file->hash, base); | ||
+ /* In order to avoid tar transforms, rename the file | ||
+ * before and after the tar command */ | ||
+ string_or_die(&rename_target, "%s/staged/.update.%s", STATE_DIR, base); | ||
+ ret = rename(original, rename_target); | ||
+ if (ret) { | ||
+ ret = -errno; | ||
+ goto out; | ||
+ } | ||
+ string_or_die(&tarcommand, "tar -C %s/staged " TAR_PERM_ATTR_ARGS " -cf - .update.%s 2> /dev/null | " | ||
+ "tar -C %s%s " TAR_PERM_ATTR_ARGS " -xf - 2> /dev/null", | ||
+ STATE_DIR, base, path_prefix, rel_dir); | ||
LOG_DEBUG(file, "dotfile install", class_osvol_staging, "%s", tarcommand); | ||
ret = system(tarcommand); | ||
free(tarcommand); | ||
+ ret = rename(rename_target, original); | ||
+ if (ret) { | ||
+ ret = -errno; | ||
+ goto out; | ||
+ } | ||
} | ||
if (ret < 0) { | ||
LOG_ERROR(file, "Failed tar dotfile install", class_osvol_staging, | ||
@@ -436,6 +495,8 @@ int do_staging(struct file *file) | ||
out: | ||
free(target); | ||
free(original); | ||
+ free(rename_target); | ||
+ free(rename_tmpdir); | ||
free(tmp); | ||
free(tmp2); | ||
|
||
-- | ||
2.5.0 | ||
|
Oops, something went wrong.