summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/libarchive/files/0002-Fix-extracting-hardlinks-over-symlinks.patch
blob: 37418632f358ee56804669408348630d879962d3 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
From ece28103885a079a129a23c5001252a1648517af Mon Sep 17 00:00:00 2001
From: Martin Matuska <martin@matuska.org>
Date: Tue, 29 Nov 2016 16:55:41 +0100
Subject: [PATCH 2/2] Fix extracting hardlinks over symlinks

Closes #821

Upstream-Status: Backported

Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
 libarchive/archive_write_disk_posix.c | 43 +++++++++++++++++++++++++++++++++++
 tar/test/test_symlink_dir.c           | 18 ++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index d786bc2..80b03cd 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -2563,6 +2563,49 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, int
 					break;
 				}
 				tail[0] = c;
+			} else if ((flags &
+			    ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+				/*
+				 * We are not the last element and we want to
+				 * follow symlinks if they are a directory.
+				 * 
+				 * This is needed to extract hardlinks over
+				 * symlinks.
+				 */
+				r = stat(head, &st);
+				if (r != 0) {
+					tail[0] = c;
+					if (errno == ENOENT) {
+						break;
+					} else {
+						fsobj_error(a_eno, a_estr,
+						    errno,
+						    "Could not stat %s", path);
+						res = (ARCHIVE_FAILED);
+						break;
+					}
+				} else if (S_ISDIR(st.st_mode)) {
+					if (chdir(head) != 0) {
+						tail[0] = c;
+						fsobj_error(a_eno, a_estr,
+						    errno,
+						    "Could not chdir %s", path);
+						res = (ARCHIVE_FATAL);
+						break;
+					}
+					/*
+					 * Our view is now from inside
+					 * this dir:
+					 */
+					head = tail + 1;
+				} else {
+					tail[0] = c;
+					fsobj_error(a_eno, a_estr, 0,
+					    "Cannot extract through "
+					    "symlink %s", path);
+					res = ARCHIVE_FAILED;
+					break;
+				}
 			} else {
 				tail[0] = c;
 				fsobj_error(a_eno, a_estr, 0,
diff --git a/tar/test/test_symlink_dir.c b/tar/test/test_symlink_dir.c
index 25bd8b1..852e00b 100644
--- a/tar/test/test_symlink_dir.c
+++ b/tar/test/test_symlink_dir.c
@@ -47,11 +47,18 @@ DEFINE_TEST(test_symlink_dir)
 	assertMakeDir("source/dir3", 0755);
 	assertMakeDir("source/dir3/d3", 0755);
 	assertMakeFile("source/dir3/f3", 0755, "abcde");
+	assertMakeDir("source/dir4", 0755);
+	assertMakeFile("source/dir4/file3", 0755, "abcdef");
+	assertMakeHardlink("source/dir4/file4", "source/dir4/file3");
 
 	assertEqualInt(0,
 	    systemf("%s -cf test.tar -C source dir dir2 dir3 file file2",
 		testprog));
 
+	/* Second archive with hardlinks */
+	assertEqualInt(0,
+	    systemf("%s -cf test2.tar -C source dir4", testprog));
+
 	/*
 	 * Extract with -x and without -P.
 	 */
@@ -118,9 +125,15 @@ DEFINE_TEST(test_symlink_dir)
 		assertMakeSymlink("dest2/file2", "real_file2");
 	assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
 
-	/* dest2/dir symlink should be followed */
+	/* "dir4" is a symlink to existing "real_dir" */
+	if (canSymlink())
+		assertMakeSymlink("dest2/dir4", "real_dir");
+	assertEqualInt(0, systemf("%s -xPf test2.tar -C dest2", testprog));
+
+	/* dest2/dir and dest2/dir4 symlinks should be followed */
 	if (canSymlink()) {
 		assertIsSymlink("dest2/dir", "real_dir");
+		assertIsSymlink("dest2/dir4", "real_dir");
 		assertIsDir("dest2/real_dir", -1);
 	}
 
@@ -141,4 +154,7 @@ DEFINE_TEST(test_symlink_dir)
 	/* dest2/file2 symlink should be removed */
 	failure("Symlink to non-existing file should be removed");
 	assertIsReg("dest2/file2", -1);
+
+	/* dest2/dir4/file3 and dest2/dir4/file4 should be hard links */
+	assertIsHardlink("dest2/dir4/file3", "dest2/dir4/file4");
 }
-- 
2.7.4