]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.bin/tar/test/test_strip_components.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / usr.bin / tar / test / test_strip_components.c
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$");
27
28 static int
29 touch(const char *fn)
30 {
31         int fd = open(fn, O_RDWR | O_CREAT, 0644);
32         failure("Couldn't create file '%s', fd=%d, errno=%d (%s)\n",
33             fn, fd, errno, strerror(errno));
34         if (!assert(fd > 0))
35                 return (0); /* Failure. */
36         close(fd);
37         return (1); /* Success */
38 }
39
40 DEFINE_TEST(test_strip_components)
41 {
42         struct stat st;
43
44         assertEqualInt(0, mkdir("d0", 0755));
45         assertEqualInt(0, chdir("d0"));
46         assertEqualInt(0, mkdir("d1", 0755));
47         assertEqualInt(0, mkdir("d1/d2", 0755));
48         assertEqualInt(0, mkdir("d1/d2/d3", 0755));
49         assertEqualInt(1, touch("d1/d2/f1"));
50         assertEqualInt(0, link("d1/d2/f1", "l1"));
51         assertEqualInt(0, link("d1/d2/f1", "d1/l2"));
52         assertEqualInt(0, symlink("d1/d2/f1", "s1"));
53         assertEqualInt(0, symlink("d2/f1", "d1/s2"));
54         assertEqualInt(0, chdir(".."));
55
56         assertEqualInt(0, systemf("%s -cf test.tar d0", testprog));
57
58         assertEqualInt(0, mkdir("target", 0755));
59         assertEqualInt(0, systemf("%s -x -C target --strip-components 2 "
60             "-f test.tar", testprog));
61
62         failure("d0/ is too short and should not get restored");
63         assertEqualInt(-1, lstat("target/d0", &st));
64         failure("d0/d1/ is too short and should not get restored");
65         assertEqualInt(-1, lstat("target/d1", &st));
66         failure("d0/d1/s2 is a symlink to something that won't be extracted");
67 #if !defined(_WIN32) || defined(__CYGWIN__)
68         assertEqualInt(-1, stat("target/s2", &st));
69 #else
70         skipping("symlink with stat()");
71 #endif
72         assertEqualInt(0, lstat("target/s2", &st));
73         failure("d0/d1/d2 should be extracted");
74         assertEqualInt(0, lstat("target/d2", &st));
75
76         /*
77          * This next is a complicated case.  d0/l1, d0/d1/l2, and
78          * d0/d1/d2/f1 are all hardlinks to the same file; d0/l1 can't
79          * be extracted with --strip-components=2 and the other two
80          * can.  Remember that tar normally stores the first file with
81          * a body and the other as hardlink entries to the first
82          * appearance.  So the final result depends on the order in
83          * which these three names get archived.  If d0/l1 is first,
84          * none of the three can be restored.  If either of the longer
85          * names are first, then the two longer ones can both be
86          * restored.
87          *
88          * The tree-walking code used by bsdtar always visits files
89          * before subdirectories, so bsdtar's behavior is fortunately
90          * deterministic:  d0/l1 will always get stored first and the
91          * other two will be stored as hardlinks to d0/l1.  Since
92          * d0/l1 can't be extracted, none of these three will be
93          * extracted.
94          *
95          * It may be worth extending this test to force a particular
96          * archiving order so as to exercise both of the cases described
97          * above.
98          *
99          * Of course, this is all totally different for cpio and newc
100          * formats because the hardlink management is different.
101          * TODO: Rename this to test_strip_components_tar and create
102          * parallel tests for cpio and newc formats.
103          */
104         failure("d0/l1 is too short and should not get restored");
105         assertEqualInt(-1, lstat("target/l1", &st));
106         failure("d0/d1/l2 is a hardlink to file whose name was too short");
107         assertEqualInt(-1, lstat("target/l2", &st));
108         failure("d0/d1/d2/f1 is a hardlink to file whose name was too short");
109         assertEqualInt(-1, lstat("target/d2/f1", &st));
110 }