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