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 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 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 */ 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