test_write_format_cpio.c revision 368707
1289284Srpaulo/*-
2289284Srpaulo * Copyright (c) 2003-2007 Tim Kientzle
3289284Srpaulo * All rights reserved.
4289284Srpaulo *
5289284Srpaulo * Redistribution and use in source and binary forms, with or without
6289284Srpaulo * modification, are permitted provided that the following conditions
7289284Srpaulo * are met:
8289284Srpaulo * 1. Redistributions of source code must retain the above copyright
9289284Srpaulo *    notice, this list of conditions and the following disclaimer.
10289284Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
11289284Srpaulo *    notice, this list of conditions and the following disclaimer in the
12289284Srpaulo *    documentation and/or other materials provided with the distribution.
13289284Srpaulo *
14289284Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15289284Srpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16289284Srpaulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17289284Srpaulo * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18289284Srpaulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19289284Srpaulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20289284Srpaulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21289284Srpaulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22289284Srpaulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23289284Srpaulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24289284Srpaulo */
25289284Srpaulo#include "test.h"
26289284Srpaulo__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/test/test_write_format_cpio.c 368707 2020-12-16 22:25:20Z mm $");
27289284Srpaulo
28289284Srpaulostatic void
29289284Srpaulotest_format(int	(*set_format)(struct archive *))
30289284Srpaulo{
31289284Srpaulo	char filedata[64];
32289284Srpaulo	struct archive_entry *ae;
33289284Srpaulo	struct archive *a;
34289284Srpaulo	char *p;
35289284Srpaulo	size_t used;
36289284Srpaulo	size_t buffsize = 1000000;
37289284Srpaulo	char *buff;
38289284Srpaulo	int damaged = 0;
39289284Srpaulo
40289284Srpaulo	buff = malloc(buffsize);
41289284Srpaulo
42289284Srpaulo	/* Create a new archive in memory. */
43289284Srpaulo	assert((a = archive_write_new()) != NULL);
44289284Srpaulo	assertA(0 == (*set_format)(a));
45289284Srpaulo	assertA(0 == archive_write_add_filter_none(a));
46289284Srpaulo	assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
47337817Scy
48289284Srpaulo	/*
49289284Srpaulo	 * Write a file to it.
50289284Srpaulo	 */
51289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
52289284Srpaulo	archive_entry_set_mtime(ae, 1, 10);
53289284Srpaulo	assert(1 == archive_entry_mtime(ae));
54289284Srpaulo	assert(10 == archive_entry_mtime_nsec(ae));
55289284Srpaulo	p = strdup("file");
56289284Srpaulo	archive_entry_copy_pathname(ae, p);
57289284Srpaulo	strcpy(p, "XXXX");
58289284Srpaulo	free(p);
59289284Srpaulo	assertEqualString("file", archive_entry_pathname(ae));
60289284Srpaulo	archive_entry_set_mode(ae, S_IFREG | 0755);
61289284Srpaulo	assert((S_IFREG | 0755) == archive_entry_mode(ae));
62289284Srpaulo	archive_entry_set_size(ae, 8);
63289284Srpaulo
64289284Srpaulo	assertA(0 == archive_write_header(a, ae));
65289284Srpaulo	archive_entry_free(ae);
66289284Srpaulo	assertA(8 == archive_write_data(a, "12345678", 9));
67289284Srpaulo
68289284Srpaulo	/*
69289284Srpaulo	 * Write another file to it.
70289284Srpaulo	 */
71289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
72289284Srpaulo	archive_entry_set_mtime(ae, 1, 10);
73289284Srpaulo	assert(1 == archive_entry_mtime(ae));
74289284Srpaulo	assert(10 == archive_entry_mtime_nsec(ae));
75289284Srpaulo	p = strdup("file2");
76289284Srpaulo	archive_entry_copy_pathname(ae, p);
77289284Srpaulo	strcpy(p, "XXXX");
78289284Srpaulo	free(p);
79289284Srpaulo	assertEqualString("file2", archive_entry_pathname(ae));
80289284Srpaulo	archive_entry_set_mode(ae, S_IFREG | 0755);
81289284Srpaulo	assert((S_IFREG | 0755) == archive_entry_mode(ae));
82289284Srpaulo	archive_entry_set_size(ae, 4);
83289284Srpaulo
84289284Srpaulo	assertA(0 == archive_write_header(a, ae));
85289284Srpaulo	archive_entry_free(ae);
86289284Srpaulo	assertA(4 == archive_write_data(a, "1234", 5));
87289284Srpaulo
88289284Srpaulo	/*
89289284Srpaulo	 * Write a file with a name, filetype, and size.
90289284Srpaulo	 */
91289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
92289284Srpaulo	archive_entry_copy_pathname(ae, "name");
93289284Srpaulo	archive_entry_set_size(ae, 0);
94289284Srpaulo	archive_entry_set_filetype(ae, AE_IFREG);
95289284Srpaulo	assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
96289284Srpaulo	assert(archive_error_string(a) == NULL);
97289284Srpaulo	archive_entry_free(ae);
98289284Srpaulo
99289284Srpaulo	/*
100289284Srpaulo	 * Write a file with a name and filetype but no size.
101289284Srpaulo	 */
102289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
103289284Srpaulo	archive_entry_copy_pathname(ae, "name");
104289284Srpaulo	archive_entry_unset_size(ae);
105289284Srpaulo	archive_entry_set_filetype(ae, AE_IFREG);
106289284Srpaulo	assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
107289284Srpaulo	assert(archive_error_string(a) != NULL);
108289284Srpaulo	archive_entry_free(ae);
109289284Srpaulo
110289284Srpaulo	/*
111289284Srpaulo	 * Write a file with a name and size but no filetype.
112289284Srpaulo	 */
113289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
114289284Srpaulo	archive_entry_copy_pathname(ae, "name");
115289284Srpaulo	archive_entry_set_size(ae, 0);
116289284Srpaulo	assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
117289284Srpaulo	assert(archive_error_string(a) != NULL);
118289284Srpaulo	archive_entry_free(ae);
119289284Srpaulo
120289284Srpaulo	/*
121289284Srpaulo	 * Write a file with a size and filetype but no name.
122289284Srpaulo	 */
123289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
124289284Srpaulo	archive_entry_set_size(ae, 0);
125289284Srpaulo	archive_entry_set_filetype(ae, AE_IFREG);
126289284Srpaulo	assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
127289284Srpaulo	assert(archive_error_string(a) != NULL);
128289284Srpaulo	archive_entry_free(ae);
129289284Srpaulo
130289284Srpaulo	/*
131289284Srpaulo	 * Write a directory to it.
132289284Srpaulo	 */
133289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
134289284Srpaulo	archive_entry_set_mtime(ae, 11, 110);
135289284Srpaulo	archive_entry_copy_pathname(ae, "dir");
136289284Srpaulo	archive_entry_set_mode(ae, S_IFDIR | 0755);
137289284Srpaulo	archive_entry_set_size(ae, 512);
138289284Srpaulo
139289284Srpaulo	assertA(0 == archive_write_header(a, ae));
140289284Srpaulo	assertEqualInt(0, archive_entry_size(ae));
141289284Srpaulo	archive_entry_free(ae);
142289284Srpaulo	assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));
143289284Srpaulo
144289284Srpaulo	/*
145289284Srpaulo	 * Write a character device to it.
146289284Srpaulo	 */
147289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
148289284Srpaulo	archive_entry_copy_pathname(ae, "tty0");
149289284Srpaulo	archive_entry_set_mode(ae, S_IFCHR | 0600);
150289284Srpaulo	archive_entry_set_size(ae, 0);
151289284Srpaulo	archive_entry_set_rdev(ae, 1024);
152289284Srpaulo	assertA(0 == archive_write_header(a, ae));
153289284Srpaulo	archive_entry_free(ae);
154289284Srpaulo
155289284Srpaulo
156289284Srpaulo	/* Close out the archive. */
157289284Srpaulo	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
158289284Srpaulo	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
159289284Srpaulo
160289284Srpaulo	/*
161289284Srpaulo	 * Damage the second entry to test the search-ahead recovery.
162289284Srpaulo	 * TODO: Move the damage-recovery checking to a separate test;
163289284Srpaulo	 * it doesn't really belong in this write test.
164289284Srpaulo	 */
165289284Srpaulo	{
166289284Srpaulo		int i;
167289284Srpaulo		for (i = 80; i < 150; i++) {
168289284Srpaulo			if (memcmp(buff + i, "07070", 5) == 0) {
169289284Srpaulo				damaged = 1;
170289284Srpaulo				buff[i] = 'X';
171289284Srpaulo				break;
172289284Srpaulo			}
173289284Srpaulo		}
174289284Srpaulo	}
175289284Srpaulo	failure("Unable to locate the second header for damage-recovery test.");
176289284Srpaulo	assert(damaged == 1);
177289284Srpaulo
178289284Srpaulo	/*
179289284Srpaulo	 * Now, read the data back.
180289284Srpaulo	 */
181289284Srpaulo	assert((a = archive_read_new()) != NULL);
182289284Srpaulo	assertA(0 == archive_read_support_format_all(a));
183289284Srpaulo	assertA(0 == archive_read_support_filter_all(a));
184337817Scy	assertA(0 == archive_read_open_memory(a, buff, used));
185337817Scy
186289284Srpaulo	if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
187289284Srpaulo		archive_read_free(a);
188289284Srpaulo		return;
189289284Srpaulo	}
190289284Srpaulo
191289284Srpaulo	assertEqualInt(1, archive_entry_mtime(ae));
192289284Srpaulo	/* Not the same as above: cpio doesn't store hi-res times. */
193289284Srpaulo	assert(0 == archive_entry_mtime_nsec(ae));
194289284Srpaulo	assert(0 == archive_entry_atime(ae));
195289284Srpaulo	assert(0 == archive_entry_ctime(ae));
196289284Srpaulo	assertEqualString("file", archive_entry_pathname(ae));
197289284Srpaulo	assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
198289284Srpaulo	assertEqualInt(8, archive_entry_size(ae));
199289284Srpaulo	assertA(8 == archive_read_data(a, filedata, 10));
200289284Srpaulo	assertEqualMem(filedata, "12345678", 8);
201289284Srpaulo
202289284Srpaulo	/*
203289284Srpaulo	 * The second file can't be read because we damaged its header.
204289284Srpaulo	 */
205289284Srpaulo
206289284Srpaulo	/*
207289284Srpaulo	 * Read the third file back.
208289284Srpaulo	 * ARCHIVE_WARN here because the damaged entry was skipped.
209289284Srpaulo	 */
210289284Srpaulo	assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
211289284Srpaulo	assertEqualString("name", archive_entry_pathname(ae));
212289284Srpaulo
213289284Srpaulo	/*
214289284Srpaulo	 * Read the dir entry back.
215289284Srpaulo	 */
216289284Srpaulo	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
217289284Srpaulo	assertEqualInt(11, archive_entry_mtime(ae));
218289284Srpaulo	assert(0 == archive_entry_mtime_nsec(ae));
219289284Srpaulo	assert(0 == archive_entry_atime(ae));
220289284Srpaulo	assert(0 == archive_entry_ctime(ae));
221289284Srpaulo	assertEqualString("dir", archive_entry_pathname(ae));
222289284Srpaulo	assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae));
223289284Srpaulo	assertEqualInt(0, archive_entry_size(ae));
224289284Srpaulo	assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));
225289284Srpaulo
226289284Srpaulo	/*
227289284Srpaulo	 * Read the character device entry back.
228289284Srpaulo	 */
229289284Srpaulo	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
230289284Srpaulo	assertEqualString("tty0", archive_entry_pathname(ae));
231289284Srpaulo	assertEqualInt((S_IFCHR | 0600), archive_entry_mode(ae));
232289284Srpaulo	assertEqualInt(0, archive_entry_size(ae));
233289284Srpaulo	assertEqualInt(1024, archive_entry_rdev(ae));
234289284Srpaulo
235289284Srpaulo	/* Verify the end of the archive. */
236289284Srpaulo	assertEqualIntA(a, 1, archive_read_next_header(a, &ae));
237289284Srpaulo	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
238289284Srpaulo	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
239289284Srpaulo
240289284Srpaulo	free(buff);
241289284Srpaulo}
242289284Srpaulo
243289284Srpaulostatic void
244289284Srpaulotest_big_entries(int (*set_format)(struct archive *), int64_t size, int expected)
245289284Srpaulo{
246289284Srpaulo	struct archive_entry *ae;
247289284Srpaulo	struct archive *a;
248289284Srpaulo	size_t buffsize = 1000000;
249289284Srpaulo	size_t used;
250289284Srpaulo	char *buff;
251289284Srpaulo
252289284Srpaulo	buff = malloc(buffsize);
253289284Srpaulo
254289284Srpaulo	/* Create a new archive in memory. */
255289284Srpaulo	assert((a = archive_write_new()) != NULL);
256289284Srpaulo	assertA(0 == (*set_format)(a));
257289284Srpaulo	assertA(0 == archive_write_add_filter_none(a));
258289284Srpaulo	assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
259289284Srpaulo
260289284Srpaulo	assert((ae = archive_entry_new()) != NULL);
261289284Srpaulo	archive_entry_copy_pathname(ae, "file");
262289284Srpaulo	archive_entry_set_size(ae, size);
263289284Srpaulo	archive_entry_set_filetype(ae, AE_IFREG);
264289284Srpaulo	assertEqualInt(expected, archive_write_header(a, ae));
265289284Srpaulo	if (expected != ARCHIVE_OK)
266289284Srpaulo		assert(archive_error_string(a) != NULL);
267289284Srpaulo
268289284Srpaulo	archive_entry_free(ae);
269289284Srpaulo	archive_write_free(a);
270289284Srpaulo	free(buff);
271289284Srpaulo}
272289284Srpaulo
273289284Srpaulo
274289284SrpauloDEFINE_TEST(test_write_format_cpio)
275289284Srpaulo{
276289284Srpaulo	int64_t size_4g = ((int64_t)1) << 32;
277289284Srpaulo	int64_t size_8g = ((int64_t)1) << 33;
278289284Srpaulo
279289284Srpaulo	test_format(archive_write_set_format_cpio);
280289284Srpaulo	test_format(archive_write_set_format_cpio_newc);
281289284Srpaulo
282289284Srpaulo	test_big_entries(archive_write_set_format_cpio,
283289284Srpaulo	    size_8g - 1, ARCHIVE_OK);
284289284Srpaulo	test_big_entries(archive_write_set_format_cpio,
285289284Srpaulo	    size_8g, ARCHIVE_FAILED);
286289284Srpaulo	test_big_entries(archive_write_set_format_cpio_newc,
287289284Srpaulo	    size_4g - 1, ARCHIVE_OK);
288289284Srpaulo	test_big_entries(archive_write_set_format_cpio_newc,
289289284Srpaulo	    size_4g, ARCHIVE_FAILED);
290289284Srpaulo}
291289284Srpaulo