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)
35 static int
has_xattr(const char * filename,const char * xattrname)36 has_xattr(const char *filename, const char *xattrname)
37 {
38 char *nl, *nlp;
39 ssize_t r;
40 int existing;
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 existing = 0;
59 for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
60 if (strcmp(nlp, xattrname) == 0) {
61 existing = 1;
62 break;
63 }
64 }
65 free(nl);
66 return (existing);
67 }
68 static int
get_rsrc_footer(const char * filename,char * buff,size_t s)69 get_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 */
DEFINE_TEST(test_write_disk_hfs_compression)89 DEFINE_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