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