1 /*-
2  * Copyright (c) 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  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "test.h"
28 
29 /*
30  * A basic exercise of bzip2 reading and writing.
31  *
32  * TODO: Add a reference file and make sure we can decompress that.
33  */
34 
DEFINE_TEST(test_write_filter_bzip2)35 DEFINE_TEST(test_write_filter_bzip2)
36 {
37 	struct archive_entry *ae;
38 	struct archive* a;
39 	char *buff, *data;
40 	size_t buffsize, datasize;
41 	char path[16];
42 	size_t used1, used2;
43 	int i, r, use_prog;
44 
45 	buffsize = 2000000;
46 	assert(NULL != (buff = (char *)malloc(buffsize)));
47 	if (buff == NULL)
48 		return;
49 
50 	datasize = 10000;
51 	assert(NULL != (data = (char *)malloc(datasize)));
52 	if (data == NULL) {
53 		free(buff);
54 		return;
55 	}
56 	memset(data, 0, datasize);
57 
58 	/*
59 	 * Write a 100 files and read them all back.
60 	 */
61 	assert((a = archive_write_new()) != NULL);
62 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
63 	r = archive_write_add_filter_bzip2(a);
64 	use_prog = (r == ARCHIVE_WARN && canBzip2());
65 	if (r != ARCHIVE_OK && !use_prog) {
66 		skipping("bzip2 writing not supported on this platform");
67 		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
68 		free(buff);
69 		free(data);
70 		return;
71 	}
72 
73 	assertEqualIntA(a, ARCHIVE_OK,
74 	    archive_write_set_bytes_per_block(a, 10));
75 	assertEqualInt(ARCHIVE_FILTER_BZIP2, archive_filter_code(a, 0));
76 	assertEqualString("bzip2", archive_filter_name(a, 0));
77 	assertEqualIntA(a, ARCHIVE_OK,
78 	    archive_write_open_memory(a, buff, buffsize, &used1));
79 	assertEqualInt(ARCHIVE_FILTER_BZIP2, archive_filter_code(a, 0));
80 	assertEqualString("bzip2", archive_filter_name(a, 0));
81 	assert((ae = archive_entry_new()) != NULL);
82 	archive_entry_set_filetype(ae, AE_IFREG);
83 	archive_entry_set_size(ae, datasize);
84 	for (i = 0; i < 999; i++) {
85 		snprintf(path, sizeof(path), "file%03d", i);
86 		archive_entry_copy_pathname(ae, path);
87 		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
88 		assertA(datasize
89 		    == (size_t)archive_write_data(a, data, datasize));
90 	}
91 	archive_entry_free(ae);
92 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
93 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
94 
95 	assert((a = archive_read_new()) != NULL);
96 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
97 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
98 	assertEqualIntA(a, ARCHIVE_OK,
99 	    archive_read_open_memory(a, buff, used1));
100 	for (i = 0; i < 999; i++) {
101 		snprintf(path, sizeof(path), "file%03d", i);
102 		if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
103 			break;
104 		assertEqualString(path, archive_entry_pathname(ae));
105 		assertEqualInt((int)datasize, archive_entry_size(ae));
106 	}
107 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
108 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
109 
110 	/*
111 	 * Repeat the cycle again, this time setting some compression
112 	 * options.
113 	 */
114 	assert((a = archive_write_new()) != NULL);
115 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
116 	assertEqualIntA(a, ARCHIVE_OK,
117 	    archive_write_set_bytes_per_block(a, 10));
118 	if (use_prog)
119 		assertEqualIntA(a, ARCHIVE_WARN,
120 		    archive_write_add_filter_bzip2(a));
121 	else
122 		assertEqualIntA(a, ARCHIVE_OK,
123 		    archive_write_add_filter_bzip2(a));
124 	assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
125 	    NULL, "nonexistent-option", "0"));
126 	assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
127 	    NULL, "compression-level", "abc"));
128 	assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
129 	    NULL, "compression-level", "99"));
130 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a,
131 	    NULL, "compression-level", "9"));
132 	assertEqualIntA(a, ARCHIVE_OK,
133 	    archive_write_open_memory(a, buff, buffsize, &used2));
134 	for (i = 0; i < 999; i++) {
135 		snprintf(path, sizeof(path), "file%03d", i);
136 		assert((ae = archive_entry_new()) != NULL);
137 		archive_entry_copy_pathname(ae, path);
138 		archive_entry_set_size(ae, datasize);
139 		archive_entry_set_filetype(ae, AE_IFREG);
140 		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
141 		assertA(datasize == (size_t)archive_write_data(a, data,
142 		    datasize));
143 		archive_entry_free(ae);
144 	}
145 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
146 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
147 
148 	/* Curiously, this test fails; the test data above compresses
149 	 * better at default compression than at level 9. */
150 	/*
151 	failure("compression-level=9 wrote %d bytes, default wrote %d bytes",
152 	    (int)used2, (int)used1);
153 	assert(used2 < used1);
154 	*/
155 
156 	assert((a = archive_read_new()) != NULL);
157 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
158 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
159 	assertEqualIntA(a, ARCHIVE_OK,
160 	    archive_read_open_memory(a, buff, used2));
161 	for (i = 0; i < 999; i++) {
162 		snprintf(path, sizeof(path), "file%03d", i);
163 		if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
164 			break;
165 		assertEqualString(path, archive_entry_pathname(ae));
166 		assertEqualInt((int)datasize, archive_entry_size(ae));
167 	}
168 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
169 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
170 
171 	/*
172 	 * Repeat again, with much lower compression.
173 	 */
174 	assert((a = archive_write_new()) != NULL);
175 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
176 	assertEqualIntA(a, ARCHIVE_OK,
177 	    archive_write_set_bytes_per_block(a, 10));
178 	if (use_prog)
179 		assertEqualIntA(a, ARCHIVE_WARN,
180 		    archive_write_add_filter_bzip2(a));
181 	else
182 		assertEqualIntA(a, ARCHIVE_OK,
183 		    archive_write_add_filter_bzip2(a));
184 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a,
185 	    NULL, "compression-level", "1"));
186 	assertEqualIntA(a, ARCHIVE_OK,
187 	    archive_write_open_memory(a, buff, buffsize, &used2));
188 	for (i = 0; i < 999; i++) {
189 		snprintf(path, sizeof(path), "file%03d", i);
190 		assert((ae = archive_entry_new()) != NULL);
191 		archive_entry_copy_pathname(ae, path);
192 		archive_entry_set_size(ae, datasize);
193 		archive_entry_set_filetype(ae, AE_IFREG);
194 		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
195 		failure("Writing file %s", path);
196 		assertEqualIntA(a, datasize,
197 		    (size_t)archive_write_data(a, data, datasize));
198 		archive_entry_free(ae);
199 	}
200 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
201 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
202 
203 	/* Level 0 really does result in larger data. */
204 	failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
205 	    (int)used2, (int)used1);
206 	assert(used2 > used1);
207 
208 	assert((a = archive_read_new()) != NULL);
209 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
210 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
211 	assertEqualIntA(a, ARCHIVE_OK,
212 	    archive_read_open_memory(a, buff, used2));
213 	for (i = 0; i < 999; i++) {
214 		snprintf(path, sizeof(path), "file%03d", i);
215 		if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
216 			break;
217 		assertEqualString(path, archive_entry_pathname(ae));
218 		assertEqualInt((int)datasize, archive_entry_size(ae));
219 	}
220 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
221 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
222 
223 	/*
224 	 * Test various premature shutdown scenarios to make sure we
225 	 * don't crash or leak memory.
226 	 */
227 	assert((a = archive_write_new()) != NULL);
228 	if (use_prog)
229 		assertEqualIntA(a, ARCHIVE_WARN,
230 		    archive_write_add_filter_bzip2(a));
231 	else
232 		assertEqualIntA(a, ARCHIVE_OK,
233 		    archive_write_add_filter_bzip2(a));
234 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
235 
236 	assert((a = archive_write_new()) != NULL);
237 	if (use_prog)
238 		assertEqualIntA(a, ARCHIVE_WARN,
239 		    archive_write_add_filter_bzip2(a));
240 	else
241 		assertEqualIntA(a, ARCHIVE_OK,
242 		    archive_write_add_filter_bzip2(a));
243 	assertEqualInt(ARCHIVE_OK, archive_write_close(a));
244 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
245 
246 	assert((a = archive_write_new()) != NULL);
247 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
248 	if (use_prog)
249 		assertEqualIntA(a, ARCHIVE_WARN,
250 		    archive_write_add_filter_bzip2(a));
251 	else
252 		assertEqualIntA(a, ARCHIVE_OK,
253 		    archive_write_add_filter_bzip2(a));
254 	assertEqualInt(ARCHIVE_OK, archive_write_close(a));
255 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
256 
257 	assert((a = archive_write_new()) != NULL);
258 	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
259 	if (use_prog)
260 		assertEqualIntA(a, ARCHIVE_WARN,
261 		    archive_write_add_filter_bzip2(a));
262 	else
263 		assertEqualIntA(a, ARCHIVE_OK,
264 		    archive_write_add_filter_bzip2(a));
265 	assertEqualIntA(a, ARCHIVE_OK,
266 	    archive_write_open_memory(a, buff, buffsize, &used2));
267 	assertEqualInt(ARCHIVE_OK, archive_write_close(a));
268 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
269 
270 	/*
271 	 * Clean up.
272 	 */
273 	free(data);
274 	free(buff);
275 }
276