test_write_disk_hfs_compression.c revision 302001
1/*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * Copyright (c) 2012 Michihiro NAKAJIMA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
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#include "test.h"
27__FBSDID("$FreeBSD$");
28
29#ifdef HAVE_SYS_XATTR_H
30#include <sys/xattr.h>
31#endif
32
33#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
34	&& defined(HAVE_ZLIB_H)
35static int
36has_xattr(const char *filename, const char *xattrname)
37{
38	char *nl, *nlp;
39	ssize_t r;
40	int exisiting;
41
42	r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
43	if (r < 0)
44		return (0);
45	if (r == 0)
46		return (0);
47
48	assert((nl = malloc(r)) != NULL);
49	if (nl == NULL)
50		return (0);
51
52	r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION);
53	if (r < 0) {
54		free(nl);
55		return (0);
56	}
57
58	exisiting = 0;
59	for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
60		if (strcmp(nlp, xattrname) == 0) {
61			exisiting = 1;
62			break;
63		}
64	}
65	free(nl);
66	return (exisiting);
67}
68static int
69get_rsrc_footer(const char *filename, char *buff, size_t s)
70{
71	ssize_t r;
72
73	r = getxattr(filename, "com.apple.ResourceFork", NULL, 0, 0,
74	    XATTR_SHOWCOMPRESSION);
75	if (r < (ssize_t)s)
76		return (-1);
77	r = getxattr(filename, "com.apple.ResourceFork", buff, s,
78	    r - s, XATTR_SHOWCOMPRESSION);
79	if (r < (ssize_t)s)
80		return (-1);
81	return (0);
82}
83
84#endif
85
86/*
87 * Exercise HFS+ Compression.
88 */
89DEFINE_TEST(test_write_disk_hfs_compression)
90{
91#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\
92	|| !defined(HAVE_ZLIB_H)
93	skipping("MacOS-specific HFS+ Compression test");
94#else
95	const char *refname = "test_write_disk_hfs_compression.tgz";
96	struct archive *ad, *a;
97	struct archive_entry *ae;
98	struct stat st;
99	char rsrc[50];
100	static const char rsrc_footer[50] = {
101		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104		0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c',  'm',
105		'p', 'f',   0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
106		0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107		0x00, 0x00
108	};
109
110	extract_reference_file(refname);
111
112	/*
113	 * Extract an archive to disk with HFS+ Compression.
114	 */
115	assert((ad = archive_write_disk_new()) != NULL);
116	assertEqualIntA(ad, ARCHIVE_OK,
117	    archive_write_disk_set_standard_lookup(ad));
118	assertEqualIntA(ad, ARCHIVE_OK,
119	    archive_write_disk_set_options(ad,
120		ARCHIVE_EXTRACT_TIME |
121		ARCHIVE_EXTRACT_SECURE_SYMLINKS |
122		ARCHIVE_EXTRACT_SECURE_NODOTDOT |
123		ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED));
124
125	assert((a = archive_read_new()) != NULL);
126	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
127	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
128	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a,
129	    refname, 512 * 20));
130
131	assertMakeDir("hfscmp", 0755);
132	assertChdir("hfscmp");
133
134	/* Extract file1. */
135	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
136	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
137	/* Extract README. */
138	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
139	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
140	/* Extract NEWS. */
141	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
142	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
143	/* Extract Makefile. */
144	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
145	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
146
147	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
148	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
149	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
150	assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad));
151
152	/* Test file1. */
153	assertEqualInt(0, stat("file1", &st));
154	assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED);
155	assertFileSize("file1", 8);
156	failure("'%s' should not have Resource Fork", "file1");
157	assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork"));
158	failure("'%s' should have decompfs xattr", "file1");
159	assertEqualInt(1, has_xattr("file1", "com.apple.decmpfs"));
160
161	/* Test README. */
162	assertEqualInt(0, stat("README", &st));
163	assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED);
164	assertFileSize("README", 6586);
165	failure("'%s' should not have Resource Fork", "README");
166	assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork"));
167	failure("'%s' should have decompfs xattr", "README");
168	assertEqualInt(1, has_xattr("README", "com.apple.decmpfs"));
169
170	/* Test NEWS. */
171	assertEqualInt(0, stat("NEWS", &st));
172	assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED);
173	assertFileSize("NEWS", 28438);
174	failure("'%s' should have Resource Fork", "NEWS");
175	assertEqualInt(1, has_xattr("NEWS", "com.apple.ResourceFork"));
176	failure("'%s' should have decompfs xattr", "NEWS");
177	assertEqualInt(1, has_xattr("NEWS", "com.apple.decmpfs"));
178	assertEqualInt(0, get_rsrc_footer("NEWS", rsrc, sizeof(rsrc)));
179	failure("Resource Fork should have consistent 50 bytes data");
180	assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc));
181
182	/* Test Makefile. */
183	assertEqualInt(0, stat("Makefile", &st));
184	assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED);
185	assertFileSize("Makefile", 1264000);
186	failure("'%s' should have Resource Fork", "Makefile");
187	assertEqualInt(1, has_xattr("Makefile", "com.apple.ResourceFork"));
188	failure("'%s' should have decompfs xattr", "Makefile");
189	assertEqualInt(1, has_xattr("Makefile", "com.apple.decmpfs"));
190	assertEqualInt(0, get_rsrc_footer("Makefile", rsrc, sizeof(rsrc)));
191	failure("Resource Fork should have consistent 50 bytes data");
192	assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc));
193
194	assertChdir("..");
195
196	/*
197	 * Extract an archive to disk without HFS+ Compression.
198	 */
199	assert((ad = archive_write_disk_new()) != NULL);
200	assertEqualIntA(ad, ARCHIVE_OK,
201	    archive_write_disk_set_standard_lookup(ad));
202	assertEqualIntA(ad, ARCHIVE_OK,
203	    archive_write_disk_set_options(ad,
204		ARCHIVE_EXTRACT_TIME |
205		ARCHIVE_EXTRACT_SECURE_SYMLINKS |
206		ARCHIVE_EXTRACT_SECURE_NODOTDOT));
207
208	assert((a = archive_read_new()) != NULL);
209	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
210	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
211	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a,
212	    refname, 512 * 20));
213
214	assertMakeDir("nocmp", 0755);
215	assertChdir("nocmp");
216
217	/* Extract file1. */
218	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
219	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
220	/* Extract README. */
221	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
222	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
223	/* Extract NEWS. */
224	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
225	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
226	/* Extract Makefile. */
227	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
228	assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
229
230	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
231	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
232	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
233	assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad));
234
235	/* Test file1. */
236	assertEqualInt(0, stat("file1", &st));
237	assertEqualInt(0, st.st_flags & UF_COMPRESSED);
238	assertFileSize("file1", 8);
239	failure("'%s' should not have Resource Fork", "file1");
240	assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork"));
241	failure("'%s' should not have decmpfs", "file1");
242	assertEqualInt(0, has_xattr("file1", "com.apple.decmpfs"));
243
244	/* Test README. */
245	assertEqualInt(0, stat("README", &st));
246	assertEqualInt(0, st.st_flags & UF_COMPRESSED);
247	assertFileSize("README", 6586);
248	failure("'%s' should not have Resource Fork", "README");
249	assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork"));
250	failure("'%s' should not have decmpfs", "README");
251	assertEqualInt(0, has_xattr("README", "com.apple.decmpfs"));
252
253	/* Test NEWS. */
254	assertEqualInt(0, stat("NEWS", &st));
255	assertEqualInt(0, st.st_flags & UF_COMPRESSED);
256	assertFileSize("NEWS", 28438);
257	failure("'%s' should not have Resource Fork", "NEWS");
258	assertEqualInt(0, has_xattr("NEWS", "com.apple.ResourceFork"));
259	failure("'%s' should not have decmpfs", "NEWS");
260	assertEqualInt(0, has_xattr("NEWS", "com.apple.decmpfs"));
261
262	/* Test Makefile. */
263	assertEqualInt(0, stat("Makefile", &st));
264	assertEqualInt(0, st.st_flags & UF_COMPRESSED);
265	assertFileSize("Makefile", 1264000);
266	failure("'%s' should not have Resource Fork", "Makefile");
267	assertEqualInt(0, has_xattr("Makefile", "com.apple.ResourceFork"));
268	failure("'%s' should not have decmpfs", "Makefile");
269	assertEqualInt(0, has_xattr("Makefile", "com.apple.decmpfs"));
270
271	assertChdir("..");
272
273	assertEqualFile("hfscmp/file1", "nocmp/file1");
274	assertEqualFile("hfscmp/README", "nocmp/README");
275	assertEqualFile("hfscmp/NEWS", "nocmp/NEWS");
276	assertEqualFile("hfscmp/Makefile", "nocmp/Makefile");
277#endif
278}
279