1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2003-2007 Tim Kientzle
5 * All rights reserved.
6 */
7 #include "test.h"
8
9 static void
verify_files(const char * msg)10 verify_files(const char *msg)
11 {
12 /*
13 * Verify unpacked files.
14 */
15
16 /* Regular file with 2 links. */
17 failure("%s", msg);
18 assertIsReg("file", 0644);
19 failure("%s", msg);
20 assertFileSize("file", 10);
21 failure("%s", msg);
22 assertFileNLinks("file", 2);
23
24 /* Another name for the same file. */
25 failure("%s", msg);
26 assertIsHardlink("linkfile", "file");
27
28 /* Symlink */
29 if (canSymlink())
30 assertIsSymlink("symlink", "file", 0);
31
32 /* Another file with 1 link and different permissions. */
33 failure("%s", msg);
34 assertIsReg("file2", 0777);
35 failure("%s", msg);
36 assertFileSize("file2", 10);
37 failure("%s", msg);
38 assertFileNLinks("file2", 1);
39
40 /* dir */
41 assertIsDir("dir", 0775);
42 }
43
44 static void
basic_cpio(const char * target,const char * pack_options,const char * unpack_options,const char * se,const char * se2)45 basic_cpio(const char *target,
46 const char *pack_options,
47 const char *unpack_options,
48 const char *se, const char *se2)
49 {
50 int r;
51
52 if (!assertMakeDir(target, 0775))
53 return;
54
55 /* Use the cpio program to create an archive. */
56 r = systemf("%s -R 1000:1000 -o %s < filelist >%s/archive 2>%s/pack.err",
57 testprog, pack_options, target, target);
58 failure("Error invoking %s -o %s", testprog, pack_options);
59 assertEqualInt(r, 0);
60
61 assertChdir(target);
62
63 /* Verify stderr. */
64 failure("Expected: %s, options=%s", se, pack_options);
65 assertTextFileContents(se, "pack.err");
66
67 /*
68 * Use cpio to unpack the archive into another directory.
69 */
70 r = systemf("%s -i %s< archive >unpack.out 2>unpack.err",
71 testprog, unpack_options);
72 failure("Error invoking %s -i %s", testprog, unpack_options);
73 assertEqualInt(r, 0);
74
75 /* Verify stderr. */
76 failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
77 assertTextFileContents(se2, "unpack.err");
78
79 verify_files(pack_options);
80
81 assertChdir("..");
82 }
83
84 static void
passthrough(const char * target)85 passthrough(const char *target)
86 {
87 int r;
88
89 if (!assertMakeDir(target, 0775))
90 return;
91
92 /*
93 * Use cpio passthrough mode to copy files to another directory.
94 */
95 r = systemf("%s -p %s <filelist >%s/stdout 2>%s/stderr",
96 testprog, target, target, target);
97 failure("Error invoking %s -p", testprog);
98 assertEqualInt(r, 0);
99
100 assertChdir(target);
101
102 /* Verify stderr. */
103 failure("Error invoking %s -p in dir %s",
104 testprog, target);
105 assertTextFileContents("1 block\n", "stderr");
106
107 verify_files("passthrough");
108 assertChdir("..");
109 }
110
DEFINE_TEST(test_basic)111 DEFINE_TEST(test_basic)
112 {
113 FILE *filelist;
114 const char *msg;
115 char result[1024];
116
117 assertUmask(0);
118
119 /*
120 * Create an assortment of files on disk.
121 */
122 filelist = fopen("filelist", "w");
123 memset(result, 0, sizeof(result));
124
125 /* File with 10 bytes content. */
126 assertMakeFile("file", 0644, "1234567890");
127 fprintf(filelist, "file\n");
128 if (is_LargeInode("file")) {
129 strncat(result,
130 "bsdcpio: file: large inode number truncated: ",
131 sizeof(result) - strlen(result) -1);
132 strncat(result,
133 strerror(ERANGE),
134 sizeof(result) - strlen(result) -1);
135 strncat(result,
136 "\n",
137 sizeof(result) - strlen(result) -1);
138 }
139
140 /* hardlink to above file. */
141 assertMakeHardlink("linkfile", "file");
142 fprintf(filelist, "linkfile\n");
143 if (is_LargeInode("linkfile")) {
144 strncat(result,
145 "bsdcpio: linkfile: large inode number truncated: ",
146 sizeof(result) - strlen(result) -1);
147 strncat(result,
148 strerror(ERANGE),
149 sizeof(result) - strlen(result) -1);
150 strncat(result,
151 "\n",
152 sizeof(result) - strlen(result) -1);
153 }
154
155 /* Symlink to above file. */
156 if (canSymlink()) {
157 assertMakeSymlink("symlink", "file", 0);
158 fprintf(filelist, "symlink\n");
159 if (is_LargeInode("symlink")) {
160 strncat(result,
161 "bsdcpio: symlink: large inode number truncated: ",
162 sizeof(result) - strlen(result) -1);
163 strncat(result,
164 strerror(ERANGE),
165 sizeof(result) - strlen(result) -1);
166 strncat(result,
167 "\n",
168 sizeof(result) - strlen(result) -1);
169 }
170 }
171
172 /* Another file with different permissions. */
173 assertMakeFile("file2", 0777, "1234567890");
174 fprintf(filelist, "file2\n");
175 if (is_LargeInode("file2")) {
176 strncat(result,
177 "bsdcpio: file2: large inode number truncated: ",
178 sizeof(result) - strlen(result) -1);
179 strncat(result,
180 strerror(ERANGE),
181 sizeof(result) - strlen(result) -1);
182 strncat(result,
183 "\n",
184 sizeof(result) - strlen(result) -1);
185 }
186
187 /* Directory. */
188 assertMakeDir("dir", 0775);
189 fprintf(filelist, "dir\n");
190 if (is_LargeInode("dir")) {
191 strncat(result,
192 "bsdcpio: dir: large inode number truncated: ",
193 sizeof(result) - strlen(result) -1);
194 strncat(result,
195 strerror(ERANGE),
196 sizeof(result) - strlen(result) -1);
197 strncat(result,
198 "\n",
199 sizeof(result) - strlen(result) -1);
200 }
201 strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
202
203 /* All done. */
204 fclose(filelist);
205
206 assertUmask(022);
207
208 /* Archive/dearchive with a variety of options. */
209 msg = canSymlink() ? "2 blocks\n" : "1 block\n";
210 basic_cpio("copy", "", "", msg, msg);
211 basic_cpio("copy_odc", "--format=odc", "", msg, msg);
212 basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
213 basic_cpio("copy_cpio", "-H odc", "", msg, msg);
214 msg = "1 block\n";
215 basic_cpio("copy_bin", "-H bin", "", msg, msg);
216 msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
217 basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
218
219 /* Copy in one step using -p */
220 passthrough("passthrough");
221 }
222