1caf54c4fSMartin Matuska /*-
2caf54c4fSMartin Matuska  * Copyright (c) 2003-2007 Tim Kientzle
3caf54c4fSMartin Matuska  * All rights reserved.
4caf54c4fSMartin Matuska  *
5caf54c4fSMartin Matuska  * Redistribution and use in source and binary forms, with or without
6caf54c4fSMartin Matuska  * modification, are permitted provided that the following conditions
7caf54c4fSMartin Matuska  * are met:
8caf54c4fSMartin Matuska  * 1. Redistributions of source code must retain the above copyright
9caf54c4fSMartin Matuska  *    notice, this list of conditions and the following disclaimer.
10caf54c4fSMartin Matuska  * 2. Redistributions in binary form must reproduce the above copyright
11caf54c4fSMartin Matuska  *    notice, this list of conditions and the following disclaimer in the
12caf54c4fSMartin Matuska  *    documentation and/or other materials provided with the distribution.
13caf54c4fSMartin Matuska  *
14caf54c4fSMartin Matuska  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15caf54c4fSMartin Matuska  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16caf54c4fSMartin Matuska  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17caf54c4fSMartin Matuska  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18caf54c4fSMartin Matuska  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19caf54c4fSMartin Matuska  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20caf54c4fSMartin Matuska  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21caf54c4fSMartin Matuska  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22caf54c4fSMartin Matuska  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23caf54c4fSMartin Matuska  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24caf54c4fSMartin Matuska  */
25caf54c4fSMartin Matuska #include "test.h"
26caf54c4fSMartin Matuska 
27caf54c4fSMartin Matuska #if defined(__CYGWIN__)
28caf54c4fSMartin Matuska # include <limits.h>
29caf54c4fSMartin Matuska # include <sys/cygwin.h>
30caf54c4fSMartin Matuska #endif
31acc60b03SMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
32acc60b03SMartin Matuska # include <direct.h>
33acc60b03SMartin Matuska #endif
34caf54c4fSMartin Matuska 
35caf54c4fSMartin Matuska /*
36caf54c4fSMartin Matuska  * Try to figure out how deep we can go in our tests.  Assumes that
37caf54c4fSMartin Matuska  * the first call to this function has the longest starting cwd (which
38caf54c4fSMartin Matuska  * is currently "<testdir>/original").  This is mostly to work around
39caf54c4fSMartin Matuska  * limits in our Win32 support.
40caf54c4fSMartin Matuska  *
41caf54c4fSMartin Matuska  * Background: On Posix systems, PATH_MAX is merely a limit on the
42caf54c4fSMartin Matuska  * length of the string passed into a system call.  By repeatedly
43caf54c4fSMartin Matuska  * calling chdir(), you can work with arbitrarily long paths on such
44caf54c4fSMartin Matuska  * systems.  In contrast, Win32 APIs apply PATH_MAX limits to the full
45caf54c4fSMartin Matuska  * absolute path, so the permissible length of a system call argument
46caf54c4fSMartin Matuska  * varies with the cwd. Some APIs actually enforce limits
47caf54c4fSMartin Matuska  * significantly less than PATH_MAX to ensure that you can create
48caf54c4fSMartin Matuska  * files within the current working directory.  The Win32 limits also
49caf54c4fSMartin Matuska  * apply to Cygwin before 1.7.
50caf54c4fSMartin Matuska  *
51caf54c4fSMartin Matuska  * Someday, I want to convert the Win32 support to use newer
52caf54c4fSMartin Matuska  * wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX
53caf54c4fSMartin Matuska  * instead of the rather anemic 260 character limit of the older
54caf54c4fSMartin Matuska  * system calls.  Then we can drop this mess (unless we want to
55caf54c4fSMartin Matuska  * continue to special-case Cygwin 1.5 and earlier).
56caf54c4fSMartin Matuska  */
57caf54c4fSMartin Matuska static int
compute_loop_max(void)58caf54c4fSMartin Matuska compute_loop_max(void)
59caf54c4fSMartin Matuska {
60caf54c4fSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
61caf54c4fSMartin Matuska 	static int LOOP_MAX = 0;
62caf54c4fSMartin Matuska 	char buf[MAX_PATH];
63caf54c4fSMartin Matuska 	size_t cwdlen;
64caf54c4fSMartin Matuska 
65caf54c4fSMartin Matuska 	if (LOOP_MAX == 0) {
66caf54c4fSMartin Matuska 		assert(_getcwd(buf, MAX_PATH) != NULL);
67caf54c4fSMartin Matuska 		cwdlen = strlen(buf);
68caf54c4fSMartin Matuska 		/* 12 characters = length of 8.3 filename */
69caf54c4fSMartin Matuska 		/* 4 characters = length of "/../" used in symlink tests */
70caf54c4fSMartin Matuska 		/* 1 character = length of extra "/" separator */
71caf54c4fSMartin Matuska 		LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1;
72caf54c4fSMartin Matuska 	}
73caf54c4fSMartin Matuska 	return LOOP_MAX;
74caf54c4fSMartin Matuska #elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH)
75caf54c4fSMartin Matuska 	static int LOOP_MAX = 0;
76caf54c4fSMartin Matuska 	if (LOOP_MAX == 0) {
77caf54c4fSMartin Matuska 		char wbuf[PATH_MAX];
78caf54c4fSMartin Matuska 		char pbuf[PATH_MAX];
79caf54c4fSMartin Matuska 		size_t wcwdlen;
80caf54c4fSMartin Matuska 		size_t pcwdlen;
81caf54c4fSMartin Matuska 	        size_t cwdlen;
82caf54c4fSMartin Matuska 		assert(getcwd(pbuf, PATH_MAX) != NULL);
83caf54c4fSMartin Matuska 		pcwdlen = strlen(pbuf);
84caf54c4fSMartin Matuska 		cygwin_conv_to_full_win32_path(pbuf, wbuf);
85caf54c4fSMartin Matuska 		wcwdlen = strlen(wbuf);
86caf54c4fSMartin Matuska 		cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen);
87caf54c4fSMartin Matuska 		/* Cygwin helper needs an extra few characters. */
88caf54c4fSMartin Matuska 		LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4;
89caf54c4fSMartin Matuska 	}
90caf54c4fSMartin Matuska 	return LOOP_MAX;
91caf54c4fSMartin Matuska #else
92caf54c4fSMartin Matuska 	/* cygwin-1.7 ends up here, along with "normal" unix */
93caf54c4fSMartin Matuska 	return 200; /* restore pre-r278 depth */
94caf54c4fSMartin Matuska #endif
95caf54c4fSMartin Matuska }
96caf54c4fSMartin Matuska 
97caf54c4fSMartin Matuska /* filenames[i] is a distinctive filename of length i. */
98caf54c4fSMartin Matuska /* To simplify interpreting failures, each filename ends with a
99caf54c4fSMartin Matuska  * decimal integer which is the length of the filename.  E.g., A
100caf54c4fSMartin Matuska  * filename ending in "_92" is 92 characters long.  To detect errors
101caf54c4fSMartin Matuska  * which drop or misplace characters, the filenames use a repeating
102caf54c4fSMartin Matuska  * "abcdefghijklmnopqrstuvwxyz..." pattern. */
103caf54c4fSMartin Matuska static char *filenames[201];
104caf54c4fSMartin Matuska 
105caf54c4fSMartin Matuska static void
compute_filenames(void)106caf54c4fSMartin Matuska compute_filenames(void)
107caf54c4fSMartin Matuska {
108caf54c4fSMartin Matuska 	char buff[250];
109caf54c4fSMartin Matuska 	size_t i,j;
110caf54c4fSMartin Matuska 
111caf54c4fSMartin Matuska 	filenames[0] = strdup("");
112caf54c4fSMartin Matuska 	filenames[1] = strdup("1");
113caf54c4fSMartin Matuska 	filenames[2] = strdup("a2");
114caf54c4fSMartin Matuska 	for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) {
115caf54c4fSMartin Matuska 		/* Fill with "abcdefghij..." */
116caf54c4fSMartin Matuska 		for (j = 0; j < i; ++j)
117caf54c4fSMartin Matuska 			buff[j] = 'a' + (j % 26);
118caf54c4fSMartin Matuska 		buff[j--] = '\0';
119caf54c4fSMartin Matuska 		/* Work from the end to fill in the number portion. */
120caf54c4fSMartin Matuska 		buff[j--] = '0' + (i % 10);
121caf54c4fSMartin Matuska 		if (i > 9) {
122caf54c4fSMartin Matuska 			buff[j--] = '0' + ((i / 10) % 10);
123caf54c4fSMartin Matuska 			if (i > 99)
124acc60b03SMartin Matuska 				buff[j--] = '0' + (char)(i / 100);
125caf54c4fSMartin Matuska 		}
126caf54c4fSMartin Matuska 		buff[j] = '_';
127caf54c4fSMartin Matuska 		/* Guard against obvious screwups in the above code. */
128caf54c4fSMartin Matuska 		assertEqualInt(strlen(buff), i);
129caf54c4fSMartin Matuska 		filenames[i] = strdup(buff);
130caf54c4fSMartin Matuska 	}
131caf54c4fSMartin Matuska }
132caf54c4fSMartin Matuska 
133caf54c4fSMartin Matuska static void
create_tree(void)134caf54c4fSMartin Matuska create_tree(void)
135caf54c4fSMartin Matuska {
136caf54c4fSMartin Matuska 	char buff[260];
137caf54c4fSMartin Matuska 	char buff2[260];
138caf54c4fSMartin Matuska 	int i;
139caf54c4fSMartin Matuska 	int LOOP_MAX;
140caf54c4fSMartin Matuska 
141caf54c4fSMartin Matuska 	compute_filenames();
142caf54c4fSMartin Matuska 
143caf54c4fSMartin Matuska 	/* Log that we'll be omitting some checks. */
144caf54c4fSMartin Matuska 	if (!canSymlink()) {
145caf54c4fSMartin Matuska 		skipping("Symlink checks");
146caf54c4fSMartin Matuska 	}
147caf54c4fSMartin Matuska 
148caf54c4fSMartin Matuska 	assertMakeDir("original", 0775);
149caf54c4fSMartin Matuska 	assertEqualInt(0, chdir("original"));
150caf54c4fSMartin Matuska 	LOOP_MAX = compute_loop_max();
151caf54c4fSMartin Matuska 
152caf54c4fSMartin Matuska 	assertMakeDir("f", 0775);
153caf54c4fSMartin Matuska 	assertMakeDir("l", 0775);
154caf54c4fSMartin Matuska 	assertMakeDir("m", 0775);
155caf54c4fSMartin Matuska 	assertMakeDir("s", 0775);
156caf54c4fSMartin Matuska 	assertMakeDir("d", 0775);
157caf54c4fSMartin Matuska 
158caf54c4fSMartin Matuska 	for (i = 1; i < LOOP_MAX; i++) {
159caf54c4fSMartin Matuska 		failure("Internal sanity check failed: i = %d", i);
160caf54c4fSMartin Matuska 		assert(filenames[i] != NULL);
161caf54c4fSMartin Matuska 
162bd5e624aSMartin Matuska 		snprintf(buff, sizeof(buff), "f/%s", filenames[i]);
163caf54c4fSMartin Matuska 		assertMakeFile(buff, 0777, buff);
164caf54c4fSMartin Matuska 
165caf54c4fSMartin Matuska 		/* Create a link named "l/abcdef..." to the above. */
166bd5e624aSMartin Matuska 		snprintf(buff2, sizeof(buff2), "l/%s", filenames[i]);
167caf54c4fSMartin Matuska 		assertMakeHardlink(buff2, buff);
168caf54c4fSMartin Matuska 
169caf54c4fSMartin Matuska 		/* Create a link named "m/abcdef..." to the above. */
170bd5e624aSMartin Matuska 		snprintf(buff2, sizeof(buff2), "m/%s", filenames[i]);
171caf54c4fSMartin Matuska 		assertMakeHardlink(buff2, buff);
172caf54c4fSMartin Matuska 
173caf54c4fSMartin Matuska 		if (canSymlink()) {
174caf54c4fSMartin Matuska 			/* Create a symlink named "s/abcdef..." to the above. */
175bd5e624aSMartin Matuska 			snprintf(buff, sizeof(buff), "s/%s", filenames[i]);
176bd5e624aSMartin Matuska 			snprintf(buff2, sizeof(buff2), "../f/%s", filenames[i]);
177caf54c4fSMartin Matuska 			failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
17852c2bb75SMartin Matuska 			assertMakeSymlink(buff, buff2, 0);
179caf54c4fSMartin Matuska 		}
180caf54c4fSMartin Matuska 		/* Create a dir named "d/abcdef...". */
181caf54c4fSMartin Matuska 		buff[0] = 'd';
182caf54c4fSMartin Matuska 		failure("buff=\"%s\"", buff);
183caf54c4fSMartin Matuska 		assertMakeDir(buff, 0775);
184caf54c4fSMartin Matuska 	}
185caf54c4fSMartin Matuska 
186caf54c4fSMartin Matuska 	assertEqualInt(0, chdir(".."));
187caf54c4fSMartin Matuska }
188caf54c4fSMartin Matuska 
189caf54c4fSMartin Matuska #define LIMIT_NONE 200
190caf54c4fSMartin Matuska #define LIMIT_USTAR 100
191caf54c4fSMartin Matuska 
192caf54c4fSMartin Matuska static void
verify_tree(size_t limit)193caf54c4fSMartin Matuska verify_tree(size_t limit)
194caf54c4fSMartin Matuska {
195caf54c4fSMartin Matuska 	char name1[260];
196caf54c4fSMartin Matuska 	char name2[260];
197caf54c4fSMartin Matuska 	size_t i, LOOP_MAX;
198caf54c4fSMartin Matuska 
199caf54c4fSMartin Matuska 	LOOP_MAX = compute_loop_max();
200caf54c4fSMartin Matuska 
201caf54c4fSMartin Matuska 	/* Generate the names we know should be there and verify them. */
202caf54c4fSMartin Matuska 	for (i = 1; i < LOOP_MAX; i++) {
203caf54c4fSMartin Matuska 		/* Verify a file named "f/abcdef..." */
204bd5e624aSMartin Matuska 		snprintf(name1, sizeof(name1), "f/%s", filenames[i]);
205caf54c4fSMartin Matuska 		if (i <= limit) {
206caf54c4fSMartin Matuska 			assertFileExists(name1);
207acc60b03SMartin Matuska 			assertFileContents(name1, (int)strlen(name1), name1);
208caf54c4fSMartin Matuska 		}
209caf54c4fSMartin Matuska 
210bd5e624aSMartin Matuska 		snprintf(name2, sizeof(name2), "l/%s", filenames[i]);
211caf54c4fSMartin Matuska 		if (i + 2 <= limit) {
212caf54c4fSMartin Matuska 			/* Verify hardlink "l/abcdef..." */
213caf54c4fSMartin Matuska 			assertIsHardlink(name1, name2);
214caf54c4fSMartin Matuska 			/* Verify hardlink "m/abcdef..." */
215caf54c4fSMartin Matuska 			name2[0] = 'm';
216caf54c4fSMartin Matuska 			assertIsHardlink(name1, name2);
217caf54c4fSMartin Matuska 		}
218caf54c4fSMartin Matuska 
219caf54c4fSMartin Matuska 		if (canSymlink()) {
220caf54c4fSMartin Matuska 			/* Verify symlink "s/abcdef..." */
221bd5e624aSMartin Matuska 			snprintf(name1, sizeof(name1), "s/%s", filenames[i]);
222bd5e624aSMartin Matuska 			snprintf(name2, sizeof(name2), "../f/%s", filenames[i]);
223caf54c4fSMartin Matuska 			if (strlen(name2) <= limit)
22452c2bb75SMartin Matuska 				assertIsSymlink(name1, name2, 0);
225caf54c4fSMartin Matuska 		}
226caf54c4fSMartin Matuska 
227caf54c4fSMartin Matuska 		/* Verify dir "d/abcdef...". */
228bd5e624aSMartin Matuska 		snprintf(name1, sizeof(name1), "d/%s", filenames[i]);
229caf54c4fSMartin Matuska 		if (i + 1 <= limit) { /* +1 for trailing slash */
230caf54c4fSMartin Matuska 			if (assertIsDir(name1, -1)) {
231caf54c4fSMartin Matuska 				/* TODO: opendir/readdir this
232caf54c4fSMartin Matuska 				 * directory and make sure
233caf54c4fSMartin Matuska 				 * it's empty.
234caf54c4fSMartin Matuska 				 */
235caf54c4fSMartin Matuska 			}
236caf54c4fSMartin Matuska 		}
237caf54c4fSMartin Matuska 	}
238caf54c4fSMartin Matuska 
239caf54c4fSMartin Matuska #if !defined(_WIN32) || defined(__CYGWIN__)
240caf54c4fSMartin Matuska 	{
241caf54c4fSMartin Matuska 		const char *dp;
242caf54c4fSMartin Matuska 		/* Now make sure nothing is there that shouldn't be. */
243caf54c4fSMartin Matuska 		for (dp = "dflms"; *dp != '\0'; ++dp) {
244caf54c4fSMartin Matuska 			DIR *d;
245caf54c4fSMartin Matuska 			struct dirent *de;
246caf54c4fSMartin Matuska 			char dir[2];
247caf54c4fSMartin Matuska 			dir[0] = *dp; dir[1] = '\0';
248caf54c4fSMartin Matuska 			d = opendir(dir);
249caf54c4fSMartin Matuska 			failure("Unable to open dir '%s'", dir);
250caf54c4fSMartin Matuska 			if (!assert(d != NULL))
251caf54c4fSMartin Matuska 				continue;
252caf54c4fSMartin Matuska 			while ((de = readdir(d)) != NULL) {
253caf54c4fSMartin Matuska 				char *p = de->d_name;
254caf54c4fSMartin Matuska 				if (p[0] == '.')
255caf54c4fSMartin Matuska 					continue;
256caf54c4fSMartin Matuska 				switch(dp[0]) {
257caf54c4fSMartin Matuska 				case 'l': case 'm': case 'd':
258f9762417SMartin Matuska 					failure("strlen(p)=%zu", strlen(p));
259caf54c4fSMartin Matuska 					assert(strlen(p) < limit);
260caf54c4fSMartin Matuska 					assertEqualString(p,
261caf54c4fSMartin Matuska 					    filenames[strlen(p)]);
262caf54c4fSMartin Matuska 					break;
263caf54c4fSMartin Matuska 				case 'f': case 's':
264f9762417SMartin Matuska 					failure("strlen(p)=%zu", strlen(p));
265caf54c4fSMartin Matuska 					assert(strlen(p) < limit + 1);
266caf54c4fSMartin Matuska 					assertEqualString(p,
267caf54c4fSMartin Matuska 					    filenames[strlen(p)]);
268caf54c4fSMartin Matuska 					break;
269caf54c4fSMartin Matuska 				default:
270caf54c4fSMartin Matuska 					failure("File %s shouldn't be here", p);
271caf54c4fSMartin Matuska 					assert(0);
272caf54c4fSMartin Matuska 				}
273caf54c4fSMartin Matuska 			}
274caf54c4fSMartin Matuska 			closedir(d);
275caf54c4fSMartin Matuska 		}
276caf54c4fSMartin Matuska 	}
277caf54c4fSMartin Matuska #endif
278caf54c4fSMartin Matuska }
279caf54c4fSMartin Matuska 
280caf54c4fSMartin Matuska static void
copy_basic(void)281caf54c4fSMartin Matuska copy_basic(void)
282caf54c4fSMartin Matuska {
283caf54c4fSMartin Matuska 	int r;
284caf54c4fSMartin Matuska 
285caf54c4fSMartin Matuska 	/* NOTE: for proper operation on cygwin-1.5 and windows, the
286caf54c4fSMartin Matuska 	 * length of the name of the directory below, "plain", must be
287007dbc1fSMartin Matuska 	 * less than or equal to the length of the name of the original
288caf54c4fSMartin Matuska 	 * directory, "original"  This restriction derives from the
289caf54c4fSMartin Matuska 	 * extremely limited pathname lengths on those platforms.
290caf54c4fSMartin Matuska 	 */
291caf54c4fSMartin Matuska 	assertMakeDir("plain", 0775);
292caf54c4fSMartin Matuska 	assertEqualInt(0, chdir("plain"));
293caf54c4fSMartin Matuska 
294caf54c4fSMartin Matuska 	/*
295caf54c4fSMartin Matuska 	 * Use the tar program to create an archive.
296caf54c4fSMartin Matuska 	 */
297caf54c4fSMartin Matuska 	r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err",
298caf54c4fSMartin Matuska 	    testprog);
299caf54c4fSMartin Matuska 	failure("Error invoking \"%s cf\"", testprog);
300caf54c4fSMartin Matuska 	assertEqualInt(r, 0);
301caf54c4fSMartin Matuska 
302caf54c4fSMartin Matuska 	/* Verify that nothing went to stdout or stderr. */
303caf54c4fSMartin Matuska 	assertEmptyFile("pack.err");
304caf54c4fSMartin Matuska 	assertEmptyFile("pack.out");
305caf54c4fSMartin Matuska 
306caf54c4fSMartin Matuska 	/*
307caf54c4fSMartin Matuska 	 * Use tar to unpack the archive into another directory.
308caf54c4fSMartin Matuska 	 */
309caf54c4fSMartin Matuska 	r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog);
310caf54c4fSMartin Matuska 	failure("Error invoking %s xf archive", testprog);
311caf54c4fSMartin Matuska 	assertEqualInt(r, 0);
312caf54c4fSMartin Matuska 
313caf54c4fSMartin Matuska 	/* Verify that nothing went to stdout or stderr. */
314caf54c4fSMartin Matuska 	assertEmptyFile("unpack.err");
315caf54c4fSMartin Matuska 	assertEmptyFile("unpack.out");
316caf54c4fSMartin Matuska 
317caf54c4fSMartin Matuska 	verify_tree(LIMIT_NONE);
318caf54c4fSMartin Matuska 	assertEqualInt(0, chdir(".."));
319caf54c4fSMartin Matuska }
320caf54c4fSMartin Matuska 
321caf54c4fSMartin Matuska static void
copy_ustar(void)322caf54c4fSMartin Matuska copy_ustar(void)
323caf54c4fSMartin Matuska {
324caf54c4fSMartin Matuska 	const char *target = "ustar";
325caf54c4fSMartin Matuska 	int r;
326caf54c4fSMartin Matuska 
327caf54c4fSMartin Matuska 	/* NOTE: for proper operation on cygwin-1.5 and windows, the
328caf54c4fSMartin Matuska 	 * length of the name of the directory below, "ustar", must be
329007dbc1fSMartin Matuska 	 * less than or equal to the length of the name of the original
330caf54c4fSMartin Matuska 	 * directory, "original"  This restriction derives from the
331caf54c4fSMartin Matuska 	 * extremely limited pathname lengths on those platforms.
332caf54c4fSMartin Matuska 	 */
333caf54c4fSMartin Matuska 	assertMakeDir(target, 0775);
334caf54c4fSMartin Matuska 	assertEqualInt(0, chdir(target));
335caf54c4fSMartin Matuska 
336caf54c4fSMartin Matuska 	/*
337caf54c4fSMartin Matuska 	 * Use the tar program to create an archive.
338caf54c4fSMartin Matuska 	 */
339caf54c4fSMartin Matuska 	r = systemf("%s cf archive --format=ustar -C ../original f d l m s >pack.out 2>pack.err",
340caf54c4fSMartin Matuska 	    testprog);
341caf54c4fSMartin Matuska 	failure("Error invoking \"%s cf archive --format=ustar\"", testprog);
342caf54c4fSMartin Matuska 	assertEqualInt(r, 0);
343caf54c4fSMartin Matuska 
344caf54c4fSMartin Matuska 	/* Verify that nothing went to stdout. */
345caf54c4fSMartin Matuska 	assertEmptyFile("pack.out");
346caf54c4fSMartin Matuska 	/* Stderr is non-empty, since there are a bunch of files
347caf54c4fSMartin Matuska 	 * with filenames too long to archive. */
348caf54c4fSMartin Matuska 
349caf54c4fSMartin Matuska 	/*
350caf54c4fSMartin Matuska 	 * Use tar to unpack the archive into another directory.
351caf54c4fSMartin Matuska 	 */
352caf54c4fSMartin Matuska 	r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog);
353caf54c4fSMartin Matuska 	failure("Error invoking %s xf archive", testprog);
354caf54c4fSMartin Matuska 	assertEqualInt(r, 0);
355caf54c4fSMartin Matuska 
356caf54c4fSMartin Matuska 	/* Verify that nothing went to stdout or stderr. */
357caf54c4fSMartin Matuska 	assertEmptyFile("unpack.err");
358caf54c4fSMartin Matuska 	assertEmptyFile("unpack.out");
359caf54c4fSMartin Matuska 
360caf54c4fSMartin Matuska 	verify_tree(LIMIT_USTAR);
361caf54c4fSMartin Matuska 	assertEqualInt(0, chdir("../.."));
362caf54c4fSMartin Matuska }
363caf54c4fSMartin Matuska 
DEFINE_TEST(test_copy)364caf54c4fSMartin Matuska DEFINE_TEST(test_copy)
365caf54c4fSMartin Matuska {
366caf54c4fSMartin Matuska 	assertUmask(0);
367caf54c4fSMartin Matuska 	create_tree(); /* Create sample files in "original" dir. */
368caf54c4fSMartin Matuska 
369caf54c4fSMartin Matuska 	/* Test simple "tar -c | tar -x" pipeline copy. */
370caf54c4fSMartin Matuska 	copy_basic();
371caf54c4fSMartin Matuska 
372caf54c4fSMartin Matuska 	/* Same, but constrain to ustar format. */
373caf54c4fSMartin Matuska 	copy_ustar();
374caf54c4fSMartin Matuska }
375