xref: /freebsd/contrib/libarchive/tar/test/test_patterns.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2009 Michihiro NAKAJIMA
5  * Copyright (c) 2003-2007 Tim Kientzle
6  * All rights reserved.
7  */
8 #include "test.h"
9 
DEFINE_TEST(test_patterns)10 DEFINE_TEST(test_patterns)
11 {
12 	FILE *f;
13 	int r;
14 	const char *reffile2 = "test_patterns_2.tar";
15 	const char *reffile3 = "test_patterns_3.tar";
16 	const char *reffile4 = "test_patterns_4.tar";
17 
18 	const char *tar2aExpected[] = {
19 		"/tmp/foo/bar/",
20 		"/tmp/foo/bar/baz",
21 		NULL
22 	};
23 
24 	/*
25 	 * Test basic command-line pattern handling.
26 	 */
27 
28 	/*
29 	 * Test 1: Files on the command line that don't get matched
30 	 * didn't produce an error.
31 	 *
32 	 * John Baldwin reported this problem in PR bin/121598
33 	 */
34 	f = fopen("foo", "w");
35 	assert(f != NULL);
36 	fclose(f);
37 	r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog);
38 	assertEqualInt(r, 0);
39 	r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog);
40 	failure("tar should return non-zero because a file was given on the command line that's not in the archive");
41 	assert(r != 0);
42 
43 	/*
44 	 * Test 2: Check basic matching of full paths that start with /
45 	 */
46 	extract_reference_file(reffile2);
47 
48 	r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err",
49 	    testprog, reffile2);
50 	assertEqualInt(r, 0);
51 	assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected);
52 	assertEmptyFile("tar2a.err");
53 
54 	/*
55 	 * Test 3 archive has some entries starting with '/' and some not.
56 	 */
57 	extract_reference_file(reffile3);
58 
59 	/* Test 3a:  Pattern tmp/foo/bar should not match /tmp/foo/bar */
60 	r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err",
61 	    testprog, reffile3);
62 	assert(r != 0);
63 	assertEmptyFile("tar3a.out");
64 
65 	/* Test 3b:  Pattern /tmp/foo/baz should not match tmp/foo/baz */
66 	assertNonEmptyFile("tar3a.err");
67 	/* Again, with the '/' */
68 	r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err",
69 	    testprog, reffile3);
70 	assert(r != 0);
71 	assertEmptyFile("tar3b.out");
72 	assertNonEmptyFile("tar3b.err");
73 
74 	/* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */
75 	r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err",
76 	    testprog, reffile3);
77 	assert(r != 0);
78 	assertEmptyFile("tar3c.out");
79 	assertNonEmptyFile("tar3c.err");
80 
81 	/* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */
82 	r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err",
83 	    testprog, reffile3);
84 	assertEqualInt(r, 0);
85 	assertEmptyFile("tar3d.out");
86 	assertEmptyFile("tar3d.err");
87 	assertFileExists("tmp/foo/baz/bar");
88 
89 	/*
90 	 * Test 4 archive has some entries starting with windows drive letters
91 	 * such as 'c:\', '//./c:/' or '//?/c:/'.
92 	 */
93 	extract_reference_file(reffile4);
94 
95 	r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err",
96 	    testprog, reffile4);
97 	assert(r != 0);
98 	assertEmptyFile("tar4.out");
99 	assertNonEmptyFile("tar4.err");
100 
101 	for (r = 1; r <= 54; r++) {
102 		char file_a[] = "tmp/fileXX";
103 		char file_b1[] = "tmp/server/share/fileXX";
104 		char file_b2[] = "tmp/server\\share\\fileXX";
105 		char file_c[] = "tmp/../fileXX";
106 		char file_d[] = "tmp/../../fileXX";
107 		char *filex;
108 		int xsize;
109 
110 		switch (r) {
111 		case 15: case 18:
112 			/*
113 			 * Including server and share names.
114 			 * //?/UNC/server/share/file15
115 			 * //?/unc/server/share/file18
116 			 */
117 			filex = file_b1;
118 			xsize = sizeof(file_b1);
119 			break;
120 		case 35: case 38: case 52:
121 			/*
122 			 * Including server and share names.
123 			 * \\?\UNC\server\share\file35
124 			 * \\?\unc\server\share\file38
125 			 * \/?/uNc/server\share\file52
126 			 */
127 			filex = file_b2;
128 			xsize = sizeof(file_b2);
129 			break;
130 		default:
131 			filex = file_a;
132 			xsize = sizeof(file_a);
133 			break;
134 		}
135 		filex[xsize-3] = '0' + r / 10;
136 		filex[xsize-2] = '0' + r % 10;
137 		switch (r) {
138 		case 5: case 6: case 17: case 20: case 25:
139 		case 26: case 37: case 40: case 43: case 54:
140 			/*
141 			 * Not extracted patterns.
142 			 * D:../file05
143 			 * c:../../file06
144 			 * //?/UNC/../file17
145 			 * //?/unc/../file20
146 			 * z:..\file25
147 			 * c:..\..\file26
148 			 * \\?\UNC\..\file37
149 			 * \\?\unc\..\file40
150 			 * c:../..\file43
151 			 * \/?\UnC\../file54
152 			 */
153 			assertFileNotExists(filex);
154 			if (r == 6 || r == 26 || r == 43) {
155 				filex = file_d;
156 				xsize = sizeof(file_d);
157 			} else {
158 				filex = file_c;
159 				xsize = sizeof(file_c);
160 			}
161 			filex[xsize-3] = '0' + r / 10;
162 			filex[xsize-2] = '0' + r % 10;
163 			assertFileNotExists(filex);
164 			break;
165 		default:
166 			/* Extracted patterns. */
167 			assertFileExists(filex);
168 			break;
169 		}
170 	}
171 }
172