1228753Smm/*-
2228753Smm * Copyright (c) 2009 Michihiro NAKAJIMA
3228753Smm * Copyright (c) 2003-2007 Tim Kientzle
4228753Smm * All rights reserved.
5228753Smm *
6228753Smm * Redistribution and use in source and binary forms, with or without
7228753Smm * modification, are permitted provided that the following conditions
8228753Smm * are met:
9228753Smm * 1. Redistributions of source code must retain the above copyright
10228753Smm *    notice, this list of conditions and the following disclaimer.
11228753Smm * 2. Redistributions in binary form must reproduce the above copyright
12228753Smm *    notice, this list of conditions and the following disclaimer in the
13228753Smm *    documentation and/or other materials provided with the distribution.
14228753Smm *
15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25228753Smm */
26228753Smm#include "test.h"
27228763Smm__FBSDID("$FreeBSD: releng/11.0/contrib/libarchive/tar/test/test_patterns.c 232153 2012-02-25 10:58:02Z mm $");
28228753Smm
29228753SmmDEFINE_TEST(test_patterns)
30228753Smm{
31228753Smm	FILE *f;
32228753Smm	int r;
33228753Smm	const char *reffile2 = "test_patterns_2.tar";
34228753Smm	const char *reffile3 = "test_patterns_3.tar";
35228753Smm	const char *reffile4 = "test_patterns_4.tar";
36228753Smm
37228753Smm	const char *tar2aExpected[] = {
38228753Smm		"/tmp/foo/bar/",
39228753Smm		"/tmp/foo/bar/baz",
40228753Smm		NULL
41228753Smm	};
42228753Smm
43228753Smm	/*
44228753Smm	 * Test basic command-line pattern handling.
45228753Smm	 */
46228753Smm
47228753Smm	/*
48228753Smm	 * Test 1: Files on the command line that don't get matched
49228753Smm	 * didn't produce an error.
50228753Smm	 *
51228753Smm	 * John Baldwin reported this problem in PR bin/121598
52228753Smm	 */
53228753Smm	f = fopen("foo", "w");
54228753Smm	assert(f != NULL);
55228753Smm	fclose(f);
56228753Smm	r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog);
57228753Smm	assertEqualInt(r, 0);
58228753Smm	r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog);
59228753Smm	failure("tar should return non-zero because a file was given on the command line that's not in the archive");
60228753Smm	assert(r != 0);
61228753Smm
62228753Smm	/*
63228753Smm	 * Test 2: Check basic matching of full paths that start with /
64228753Smm	 */
65228753Smm	extract_reference_file(reffile2);
66228753Smm
67228753Smm	r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err",
68228753Smm	    testprog, reffile2);
69228753Smm	assertEqualInt(r, 0);
70228753Smm	assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected);
71228753Smm	assertEmptyFile("tar2a.err");
72228753Smm
73228753Smm	/*
74228753Smm	 * Test 3 archive has some entries starting with '/' and some not.
75228753Smm	 */
76228753Smm	extract_reference_file(reffile3);
77228753Smm
78228753Smm	/* Test 3a:  Pattern tmp/foo/bar should not match /tmp/foo/bar */
79228753Smm	r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err",
80228753Smm	    testprog, reffile3);
81228753Smm	assert(r != 0);
82228753Smm	assertEmptyFile("tar3a.out");
83228753Smm
84228753Smm	/* Test 3b:  Pattern /tmp/foo/baz should not match tmp/foo/baz */
85228753Smm	assertNonEmptyFile("tar3a.err");
86228753Smm	/* Again, with the '/' */
87228753Smm	r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err",
88228753Smm	    testprog, reffile3);
89228753Smm	assert(r != 0);
90228753Smm	assertEmptyFile("tar3b.out");
91228753Smm	assertNonEmptyFile("tar3b.err");
92228753Smm
93228753Smm	/* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */
94228753Smm	r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err",
95228753Smm	    testprog, reffile3);
96228753Smm	assert(r != 0);
97228753Smm	assertEmptyFile("tar3c.out");
98228753Smm	assertNonEmptyFile("tar3c.err");
99228753Smm
100228753Smm	/* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */
101228753Smm	r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err",
102228753Smm	    testprog, reffile3);
103228753Smm	assertEqualInt(r, 0);
104228753Smm	assertEmptyFile("tar3d.out");
105228753Smm	assertEmptyFile("tar3d.err");
106228753Smm	assertFileExists("tmp/foo/baz/bar");
107228753Smm
108228753Smm	/*
109228753Smm	 * Test 4 archive has some entries starting with windows drive letters
110228753Smm	 * such as 'c:\', '//./c:/' or '//?/c:/'.
111228753Smm	 */
112228753Smm	extract_reference_file(reffile4);
113228753Smm
114228753Smm	r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err",
115228753Smm	    testprog, reffile4);
116228753Smm	assert(r != 0);
117228753Smm	assertEmptyFile("tar4.out");
118228753Smm	assertNonEmptyFile("tar4.err");
119228753Smm
120228753Smm	for (r = 1; r <= 54; r++) {
121228753Smm		char file_a[] = "tmp/fileXX";
122228753Smm		char file_b1[] = "tmp/server/share/fileXX";
123228753Smm		char file_b2[] = "tmp/server\\share\\fileXX";
124228753Smm		char file_c[] = "tmp/../fileXX";
125232153Smm		char file_d[] = "tmp/../../fileXX";
126228753Smm		char *filex;
127228753Smm		int xsize;
128228753Smm
129228753Smm		switch (r) {
130228753Smm		case 15: case 18:
131228753Smm			/*
132228753Smm			 * Including server and share names.
133228753Smm			 * //?/UNC/server/share/file15
134228753Smm			 * //?/unc/server/share/file18
135228753Smm			 */
136228753Smm			filex = file_b1;
137228753Smm			xsize = sizeof(file_b1);
138228753Smm			break;
139228753Smm		case 35: case 38: case 52:
140228753Smm			/*
141228753Smm			 * Including server and share names.
142228753Smm			 * \\?\UNC\server\share\file35
143228753Smm			 * \\?\unc\server\share\file38
144228753Smm			 * \/?/uNc/server\share\file52
145228753Smm			 */
146228753Smm			filex = file_b2;
147228753Smm			xsize = sizeof(file_b2);
148228753Smm			break;
149228753Smm		default:
150228753Smm			filex = file_a;
151228753Smm			xsize = sizeof(file_a);
152228753Smm			break;
153228753Smm		}
154228753Smm		filex[xsize-3] = '0' + r / 10;
155228753Smm		filex[xsize-2] = '0' + r % 10;
156228753Smm		switch (r) {
157228753Smm		case 5: case 6: case 17: case 20: case 25:
158228753Smm		case 26: case 37: case 40: case 43: case 54:
159228753Smm			/*
160228753Smm			 * Not extracted patterns.
161228753Smm			 * D:../file05
162228753Smm			 * c:../../file06
163228753Smm			 * //?/UNC/../file17
164228753Smm			 * //?/unc/../file20
165228753Smm			 * z:..\file25
166228753Smm			 * c:..\..\file26
167228753Smm			 * \\?\UNC\..\file37
168228753Smm			 * \\?\unc\..\file40
169228753Smm			 * c:../..\file43
170228753Smm			 * \/?\UnC\../file54
171228753Smm			 */
172228753Smm			assertFileNotExists(filex);
173232153Smm			if (r == 6 || r == 26 || r == 43) {
174232153Smm				filex = file_d;
175232153Smm				xsize = sizeof(file_d);
176232153Smm			} else {
177232153Smm				filex = file_c;
178232153Smm				xsize = sizeof(file_c);
179232153Smm			}
180228753Smm			filex[xsize-3] = '0' + r / 10;
181228753Smm			filex[xsize-2] = '0' + r % 10;
182228753Smm			assertFileNotExists(filex);
183228753Smm			break;
184228753Smm		default:
185228753Smm			/* Extracted patterns. */
186228753Smm			assertFileExists(filex);
187228753Smm			break;
188228753Smm		}
189228753Smm	}
190228753Smm}
191