aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-core/swupd-client/swupd-client-2.87/0005-swupd-client-Add-existence-check-to-staging-target.patch
blob: 512105ebeff73b4f12925eaf8ba95cf7895f0230 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
From 1f37511e52754f7231c52489ba4f7d8f7de1e2af Mon Sep 17 00:00:00 2001
From: "Brad T. Peters" <brad.t.peters@intel.com>
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 <brad.t.peters@intel.com>
---
 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