xref: /netbsd-src/external/bsd/libarchive/dist/cpio/test/test_basic.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
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 void
29 verify_files(const char *target)
30 {
31 	struct stat st, st2;
32 	char buff[128];
33 	int r;
34 
35 	/*
36 	 * Verify unpacked files.
37 	 */
38 
39 	/* Regular file with 2 links. */
40 	r = lstat("file", &st);
41 	failure("Failed to stat file %s/file, errno=%d", target, errno);
42 	assertEqualInt(r, 0);
43 	if (r == 0) {
44 		assert(S_ISREG(st.st_mode));
45 		assertEqualInt(0644, st.st_mode & 0777);
46 		assertEqualInt(10, st.st_size);
47 		failure("file %s/file should have 2 links", target);
48 		assertEqualInt(2, st.st_nlink);
49 	}
50 
51 	/* Another name for the same file. */
52 	r = lstat("linkfile", &st2);
53 	failure("Failed to stat file %s/linkfile, errno=%d", target, errno);
54 	assertEqualInt(r, 0);
55 	if (r == 0) {
56 		assert(S_ISREG(st2.st_mode));
57 		assertEqualInt(0644, st2.st_mode & 0777);
58 		assertEqualInt(10, st2.st_size);
59 		failure("file %s/linkfile should have 2 links", target);
60 		assertEqualInt(2, st2.st_nlink);
61 		/* Verify that the two are really hardlinked. */
62 		assertEqualInt(st.st_dev, st2.st_dev);
63 		failure("%s/linkfile and %s/file should be hardlinked",
64 		    target, target);
65 		assertEqualInt(st.st_ino, st2.st_ino);
66 	}
67 
68 	/* Symlink */
69 	r = lstat("symlink", &st);
70 	failure("Failed to stat file %s/symlink, errno=%d", target, errno);
71 	assertEqualInt(r, 0);
72 	if (r == 0) {
73 		failure("symlink should be a symlink; actual mode is %o",
74 		    st.st_mode);
75 		assert(S_ISLNK(st.st_mode));
76 		if (S_ISLNK(st.st_mode)) {
77 			r = readlink("symlink", buff, sizeof(buff));
78 			assertEqualInt(r, 4);
79 			buff[r] = '\0';
80 			assertEqualString(buff, "file");
81 		}
82 	}
83 
84 	/* dir */
85 	r = lstat("dir", &st);
86 	if (r == 0) {
87 		assertEqualInt(r, 0);
88 		assert(S_ISDIR(st.st_mode));
89 		assertEqualInt(0775, st.st_mode & 0777);
90 	}
91 }
92 
93 static void
94 basic_cpio(const char *target,
95     const char *pack_options,
96     const char *unpack_options,
97     const char *se)
98 {
99 	int r;
100 
101 	if (!assertEqualInt(0, mkdir(target, 0775)))
102 	    return;
103 
104 	/* Use the cpio program to create an archive. */
105 	r = systemf("%s -o %s < filelist >%s/archive 2>%s/pack.err",
106 	    testprog, pack_options, target, target);
107 	failure("Error invoking %s -o %s", testprog, pack_options);
108 	assertEqualInt(r, 0);
109 
110 	chdir(target);
111 
112 	/* Verify stderr. */
113 	failure("Expected: %s, options=%s", se, pack_options);
114 	assertFileContents(se, strlen(se), "pack.err");
115 
116 	/*
117 	 * Use cpio to unpack the archive into another directory.
118 	 */
119 	r = systemf("%s -i %s< archive >unpack.out 2>unpack.err",
120 	    testprog, unpack_options);
121 	failure("Error invoking %s -i %s", testprog, unpack_options);
122 	assertEqualInt(r, 0);
123 
124 	/* Verify stderr. */
125 	failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
126 	assertFileContents(se, strlen(se), "unpack.err");
127 
128 	verify_files(target);
129 
130 	chdir("..");
131 }
132 
133 static void
134 passthrough(const char *target)
135 {
136 	int r;
137 
138 	if (!assertEqualInt(0, mkdir(target, 0775)))
139 		return;
140 
141 	/*
142 	 * Use cpio passthrough mode to copy files to another directory.
143 	 */
144 	r = systemf("%s -p -W quiet %s <filelist >%s/stdout 2>%s/stderr",
145 	    testprog, target, target, target);
146 	failure("Error invoking %s -p", testprog);
147 	assertEqualInt(r, 0);
148 
149 	chdir(target);
150 
151 	/* Verify stderr. */
152 	failure("Error invoking %s -p in dir %s",
153 	    testprog, target);
154 	assertEmptyFile("stderr");
155 
156 	verify_files(target);
157 	chdir("..");
158 }
159 
160 DEFINE_TEST(test_basic)
161 {
162 	int fd;
163 	int filelist;
164 	int oldumask;
165 
166 	oldumask = umask(0);
167 
168 	/*
169 	 * Create an assortment of files on disk.
170 	 */
171 	filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
172 
173 	/* File with 10 bytes content. */
174 	fd = open("file", O_CREAT | O_WRONLY, 0644);
175 	assert(fd >= 0);
176 	assertEqualInt(10, write(fd, "123456789", 10));
177 	close(fd);
178 	write(filelist, "file\n", 5);
179 
180 	/* hardlink to above file. */
181 	assertEqualInt(0, link("file", "linkfile"));
182 	write(filelist, "linkfile\n", 9);
183 
184 	/* Symlink to above file. */
185 	assertEqualInt(0, symlink("file", "symlink"));
186 	write(filelist, "symlink\n", 8);
187 
188 	/* Directory. */
189 	assertEqualInt(0, mkdir("dir", 0775));
190 	write(filelist, "dir\n", 4);
191 	/* All done. */
192 	close(filelist);
193 
194 	/* Archive/dearchive with a variety of options. */
195 	basic_cpio("copy", "", "", "1 block\n");
196 	basic_cpio("copy_odc", "--format=odc", "", "1 block\n");
197 	basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
198 	basic_cpio("copy_cpio", "-H odc", "", "1 block\n");
199 	basic_cpio("copy_ustar", "-H ustar", "", "7 blocks\n");
200 	/* Copy in one step using -p */
201 	passthrough("passthrough");
202 
203 	umask(oldumask);
204 }
205