]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/test/test_write_format_cpio.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / test / test_write_format_cpio.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 void
29 test_format(int (*set_format)(struct archive *))
30 {
31         char filedata[64];
32         struct archive_entry *ae;
33         struct archive *a;
34         char *p;
35         size_t used;
36         size_t buffsize = 1000000;
37         char *buff;
38         int damaged = 0;
39
40         buff = malloc(buffsize);
41
42         /* Create a new archive in memory. */
43         assert((a = archive_write_new()) != NULL);
44         assertA(0 == (*set_format)(a));
45         assertA(0 == archive_write_add_filter_none(a));
46         assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
47
48         /*
49          * Write a file to it.
50          */
51         assert((ae = archive_entry_new()) != NULL);
52         archive_entry_set_mtime(ae, 1, 10);
53         assert(1 == archive_entry_mtime(ae));
54         assert(10 == archive_entry_mtime_nsec(ae));
55         p = strdup("file");
56         archive_entry_copy_pathname(ae, p);
57         strcpy(p, "XXXX");
58         free(p);
59         assertEqualString("file", archive_entry_pathname(ae));
60         archive_entry_set_mode(ae, S_IFREG | 0755);
61         assert((S_IFREG | 0755) == archive_entry_mode(ae));
62         archive_entry_set_size(ae, 8);
63
64         assertA(0 == archive_write_header(a, ae));
65         archive_entry_free(ae);
66         assertA(8 == archive_write_data(a, "12345678", 9));
67
68         /*
69          * Write another file to it.
70          */
71         assert((ae = archive_entry_new()) != NULL);
72         archive_entry_set_mtime(ae, 1, 10);
73         assert(1 == archive_entry_mtime(ae));
74         assert(10 == archive_entry_mtime_nsec(ae));
75         p = strdup("file2");
76         archive_entry_copy_pathname(ae, p);
77         strcpy(p, "XXXX");
78         free(p);
79         assertEqualString("file2", archive_entry_pathname(ae));
80         archive_entry_set_mode(ae, S_IFREG | 0755);
81         assert((S_IFREG | 0755) == archive_entry_mode(ae));
82         archive_entry_set_size(ae, 4);
83
84         assertA(0 == archive_write_header(a, ae));
85         archive_entry_free(ae);
86         assertA(4 == archive_write_data(a, "1234", 5));
87
88         /*
89          * Write a file with a name, filetype, and size.
90          */
91         assert((ae = archive_entry_new()) != NULL);
92         archive_entry_copy_pathname(ae, "name");
93         archive_entry_set_size(ae, 0);
94         archive_entry_set_filetype(ae, AE_IFREG);
95         assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
96         assert(archive_error_string(a) == NULL);
97         archive_entry_free(ae);
98
99         /*
100          * Write a file with a name and filetype but no size.
101          */
102         assert((ae = archive_entry_new()) != NULL);
103         archive_entry_copy_pathname(ae, "name");
104         archive_entry_unset_size(ae);
105         archive_entry_set_filetype(ae, AE_IFREG);
106         assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
107         assert(archive_error_string(a) != NULL);
108         archive_entry_free(ae);
109
110         /*
111          * Write a file with a name and size but no filetype.
112          */
113         assert((ae = archive_entry_new()) != NULL);
114         archive_entry_copy_pathname(ae, "name");
115         archive_entry_set_size(ae, 0);
116         assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
117         assert(archive_error_string(a) != NULL);
118         archive_entry_free(ae);
119
120         /*
121          * Write a file with a size and filetype but no name.
122          */
123         assert((ae = archive_entry_new()) != NULL);
124         archive_entry_set_size(ae, 0);
125         archive_entry_set_filetype(ae, AE_IFREG);
126         assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
127         assert(archive_error_string(a) != NULL);
128         archive_entry_free(ae);
129
130         /*
131          * Write a directory to it.
132          */
133         assert((ae = archive_entry_new()) != NULL);
134         archive_entry_set_mtime(ae, 11, 110);
135         archive_entry_copy_pathname(ae, "dir");
136         archive_entry_set_mode(ae, S_IFDIR | 0755);
137         archive_entry_set_size(ae, 512);
138
139         assertA(0 == archive_write_header(a, ae));
140         assertEqualInt(0, archive_entry_size(ae));
141         archive_entry_free(ae);
142         assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));
143
144         /*
145          * Write a character device to it.
146          */
147         assert((ae = archive_entry_new()) != NULL);
148         archive_entry_copy_pathname(ae, "tty0");
149         archive_entry_set_mode(ae, S_IFCHR | 0600);
150         archive_entry_set_size(ae, 0);
151         archive_entry_set_rdev(ae, 1024);
152         assertA(0 == archive_write_header(a, ae));
153         archive_entry_free(ae);
154
155
156         /* Close out the archive. */
157         assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
158         assertEqualInt(ARCHIVE_OK, archive_write_free(a));
159
160         /*
161          * Damage the second entry to test the search-ahead recovery.
162          * TODO: Move the damage-recovery checking to a separate test;
163          * it doesn't really belong in this write test.
164          */
165         {
166                 int i;
167                 for (i = 80; i < 150; i++) {
168                         if (memcmp(buff + i, "07070", 5) == 0) {
169                                 damaged = 1;
170                                 buff[i] = 'X';
171                                 break;
172                         }
173                 }
174         }
175         failure("Unable to locate the second header for damage-recovery test.");
176         assert(damaged == 1);
177
178         /*
179          * Now, read the data back.
180          */
181         assert((a = archive_read_new()) != NULL);
182         assertA(0 == archive_read_support_format_all(a));
183         assertA(0 == archive_read_support_filter_all(a));
184         assertA(0 == archive_read_open_memory(a, buff, used));
185
186         if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
187                 archive_read_free(a);
188                 return;
189         }
190
191         assertEqualInt(1, archive_entry_mtime(ae));
192         /* Not the same as above: cpio doesn't store hi-res times. */
193         assert(0 == archive_entry_mtime_nsec(ae));
194         assert(0 == archive_entry_atime(ae));
195         assert(0 == archive_entry_ctime(ae));
196         assertEqualString("file", archive_entry_pathname(ae));
197         assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
198         assertEqualInt(8, archive_entry_size(ae));
199         assertA(8 == archive_read_data(a, filedata, 10));
200         assertEqualMem(filedata, "12345678", 8);
201
202         /*
203          * The second file can't be read because we damaged its header.
204          */
205
206         /*
207          * Read the third file back.
208          * ARCHIVE_WARN here because the damaged entry was skipped.
209          */
210         assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
211         assertEqualString("name", archive_entry_pathname(ae));
212
213         /*
214          * Read the dir entry back.
215          */
216         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
217         assertEqualInt(11, archive_entry_mtime(ae));
218         assert(0 == archive_entry_mtime_nsec(ae));
219         assert(0 == archive_entry_atime(ae));
220         assert(0 == archive_entry_ctime(ae));
221         assertEqualString("dir", archive_entry_pathname(ae));
222         assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae));
223         assertEqualInt(0, archive_entry_size(ae));
224         assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));
225
226         /*
227          * Read the character device entry back.
228          */
229         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
230         assertEqualString("tty0", archive_entry_pathname(ae));
231         assertEqualInt((S_IFCHR | 0600), archive_entry_mode(ae));
232         assertEqualInt(0, archive_entry_size(ae));
233         assertEqualInt(1024, archive_entry_rdev(ae));
234
235         /* Verify the end of the archive. */
236         assertEqualIntA(a, 1, archive_read_next_header(a, &ae));
237         assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
238         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
239
240         free(buff);
241 }
242
243 static void
244 test_big_entries(int (*set_format)(struct archive *), int64_t size, int expected)
245 {
246         struct archive_entry *ae;
247         struct archive *a;
248         size_t buffsize = 1000000;
249         size_t used;
250         char *buff;
251
252         buff = malloc(buffsize);
253
254         /* Create a new archive in memory. */
255         assert((a = archive_write_new()) != NULL);
256         assertA(0 == (*set_format)(a));
257         assertA(0 == archive_write_add_filter_none(a));
258         assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
259
260         assert((ae = archive_entry_new()) != NULL);
261         archive_entry_copy_pathname(ae, "file");
262         archive_entry_set_size(ae, size);
263         archive_entry_set_filetype(ae, AE_IFREG);
264         assertEqualInt(expected, archive_write_header(a, ae));
265         if (expected != ARCHIVE_OK)
266                 assert(archive_error_string(a) != NULL);
267
268         archive_entry_free(ae);
269         archive_write_free(a);
270         free(buff);
271 }
272
273
274 DEFINE_TEST(test_write_format_cpio)
275 {
276         int64_t size_4g = ((int64_t)1) << 32;
277         int64_t size_8g = ((int64_t)1) << 33;
278
279         test_format(archive_write_set_format_cpio);
280         test_format(archive_write_set_format_cpio_newc);
281
282         test_big_entries(archive_write_set_format_cpio,
283             size_8g - 1, ARCHIVE_OK);
284         test_big_entries(archive_write_set_format_cpio,
285             size_8g, ARCHIVE_FAILED);
286         test_big_entries(archive_write_set_format_cpio_newc,
287             size_4g - 1, ARCHIVE_OK);
288         test_big_entries(archive_write_set_format_cpio_newc,
289             size_4g, ARCHIVE_FAILED);
290 }