1248590Smm/*- 2248590Smm * Copyright (c) 2003-2007 Tim Kientzle 3248590Smm * Copyright (c) 2012 Michihiro NAKAJIMA 4248590Smm * All rights reserved. 5248590Smm * 6248590Smm * Redistribution and use in source and binary forms, with or without 7248590Smm * modification, are permitted provided that the following conditions 8248590Smm * are met: 9248590Smm * 1. Redistributions of source code must retain the above copyright 10248590Smm * notice, this list of conditions and the following disclaimer. 11248590Smm * 2. Redistributions in binary form must reproduce the above copyright 12248590Smm * notice, this list of conditions and the following disclaimer in the 13248590Smm * documentation and/or other materials provided with the distribution. 14248590Smm * 15248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16248590Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17248590Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18248590Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19248590Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20248590Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21248590Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22248590Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23248590Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24248590Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25248590Smm */ 26248590Smm#include "test.h" 27248590Smm__FBSDID("$FreeBSD$"); 28248590Smm 29248590Smm#ifdef HAVE_SYS_XATTR_H 30248590Smm#include <sys/xattr.h> 31248590Smm#endif 32248590Smm 33248590Smm#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ 34248590Smm && defined(HAVE_ZLIB_H) 35248590Smmstatic int 36248590Smmhas_xattr(const char *filename, const char *xattrname) 37248590Smm{ 38248590Smm char *nl, *nlp; 39248590Smm ssize_t r; 40248590Smm int exisiting; 41248590Smm 42248590Smm r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION); 43248590Smm if (r < 0) 44248590Smm return (0); 45248590Smm if (r == 0) 46248590Smm return (0); 47248590Smm 48248590Smm nl = malloc(r); 49248590Smm if (!assert(nl != NULL)) 50248590Smm return (0); 51248590Smm 52248590Smm r = listxattr(filename, nl, r, XATTR_SHOWCOMPRESSION); 53248590Smm if (r < 0) { 54248590Smm free(nl); 55248590Smm return (0); 56248590Smm } 57248590Smm 58248590Smm exisiting = 0; 59248590Smm for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) { 60248590Smm if (strcmp(nlp, xattrname) == 0) { 61248590Smm exisiting = 1; 62248590Smm break; 63248590Smm } 64248590Smm } 65248590Smm free(nl); 66248590Smm return (exisiting); 67248590Smm} 68248590Smmstatic int 69248590Smmget_rsrc_footer(const char *filename, char *buff, size_t s) 70248590Smm{ 71248590Smm ssize_t r; 72248590Smm 73248590Smm r = getxattr(filename, "com.apple.ResourceFork", NULL, 0, 0, 74248590Smm XATTR_SHOWCOMPRESSION); 75248590Smm if (r < (ssize_t)s) 76248590Smm return (-1); 77248590Smm r = getxattr(filename, "com.apple.ResourceFork", buff, s, 78248590Smm r - s, XATTR_SHOWCOMPRESSION); 79248590Smm if (r < (ssize_t)s) 80248590Smm return (-1); 81248590Smm return (0); 82248590Smm} 83248590Smm 84248590Smm#endif 85248590Smm 86248590Smm/* 87248590Smm * Exercise HFS+ Compression. 88248590Smm */ 89248590SmmDEFINE_TEST(test_write_disk_hfs_compression) 90248590Smm{ 91248590Smm#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ 92248590Smm || !defined(HAVE_ZLIB_H) 93248590Smm skipping("MacOS-specific HFS+ Compression test"); 94248590Smm#else 95248590Smm const char *refname = "test_write_disk_hfs_compression.tgz"; 96248590Smm struct archive *ad, *a; 97248590Smm struct archive_entry *ae; 98248590Smm struct stat st; 99248590Smm char rsrc[50]; 100248590Smm static const char rsrc_footer[50] = { 101248590Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102248590Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 103248590Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 104248590Smm 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', 105248590Smm 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 106248590Smm 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107248590Smm 0x00, 0x00 108248590Smm }; 109248590Smm 110248590Smm extract_reference_file(refname); 111248590Smm 112248590Smm /* 113248590Smm * Extract an archive to disk with HFS+ Compression. 114248590Smm */ 115248590Smm assert((ad = archive_write_disk_new()) != NULL); 116248590Smm assertEqualIntA(ad, ARCHIVE_OK, 117248590Smm archive_write_disk_set_standard_lookup(ad)); 118248590Smm assertEqualIntA(ad, ARCHIVE_OK, 119248590Smm archive_write_disk_set_options(ad, 120248590Smm ARCHIVE_EXTRACT_TIME | 121248590Smm ARCHIVE_EXTRACT_SECURE_SYMLINKS | 122248590Smm ARCHIVE_EXTRACT_SECURE_NODOTDOT | 123248590Smm ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED)); 124248590Smm 125248590Smm assert((a = archive_read_new()) != NULL); 126248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 127248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 128248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, 129248590Smm refname, 512 * 20)); 130248590Smm 131248590Smm assertMakeDir("hfscmp", 0755); 132248590Smm assertChdir("hfscmp"); 133248590Smm 134248590Smm /* Extract file1. */ 135248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 136248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 137248590Smm /* Extract README. */ 138248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 139248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 140248590Smm /* Extract NEWS. */ 141248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 142248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 143248590Smm /* Extract Makefile. */ 144248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 145248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 146248590Smm 147248590Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 148248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 149248590Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 150248590Smm assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); 151248590Smm 152248590Smm /* Test file1. */ 153248590Smm assertEqualInt(0, stat("file1", &st)); 154248590Smm assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); 155248590Smm assertFileSize("file1", 8); 156248590Smm failure("'%s' should not have Resource Fork", "file1"); 157248590Smm assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); 158248590Smm failure("'%s' should have decompfs xattr", "file1"); 159248590Smm assertEqualInt(1, has_xattr("file1", "com.apple.decmpfs")); 160248590Smm 161248590Smm /* Test README. */ 162248590Smm assertEqualInt(0, stat("README", &st)); 163248590Smm assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); 164248590Smm assertFileSize("README", 6586); 165248590Smm failure("'%s' should not have Resource Fork", "README"); 166248590Smm assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); 167248590Smm failure("'%s' should have decompfs xattr", "README"); 168248590Smm assertEqualInt(1, has_xattr("README", "com.apple.decmpfs")); 169248590Smm 170248590Smm /* Test NEWS. */ 171248590Smm assertEqualInt(0, stat("NEWS", &st)); 172248590Smm assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); 173248590Smm assertFileSize("NEWS", 28438); 174248590Smm failure("'%s' should have Resource Fork", "NEWS"); 175248590Smm assertEqualInt(1, has_xattr("NEWS", "com.apple.ResourceFork")); 176248590Smm failure("'%s' should have decompfs xattr", "NEWS"); 177248590Smm assertEqualInt(1, has_xattr("NEWS", "com.apple.decmpfs")); 178248590Smm assertEqualInt(0, get_rsrc_footer("NEWS", rsrc, sizeof(rsrc))); 179248590Smm failure("Resource Fork should have consistent 50 bytes data"); 180248590Smm assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc)); 181248590Smm 182248590Smm /* Test Makefile. */ 183248590Smm assertEqualInt(0, stat("Makefile", &st)); 184248590Smm assertEqualInt(UF_COMPRESSED, st.st_flags & UF_COMPRESSED); 185248590Smm assertFileSize("Makefile", 1264000); 186248590Smm failure("'%s' should have Resource Fork", "Makefile"); 187248590Smm assertEqualInt(1, has_xattr("Makefile", "com.apple.ResourceFork")); 188248590Smm failure("'%s' should have decompfs xattr", "Makefile"); 189248590Smm assertEqualInt(1, has_xattr("Makefile", "com.apple.decmpfs")); 190248590Smm assertEqualInt(0, get_rsrc_footer("Makefile", rsrc, sizeof(rsrc))); 191248590Smm failure("Resource Fork should have consistent 50 bytes data"); 192248590Smm assertEqualMem(rsrc_footer, rsrc, sizeof(rsrc)); 193248590Smm 194248590Smm assertChdir(".."); 195248590Smm 196248590Smm /* 197248590Smm * Extract an archive to disk without HFS+ Compression. 198248590Smm */ 199248590Smm assert((ad = archive_write_disk_new()) != NULL); 200248590Smm assertEqualIntA(ad, ARCHIVE_OK, 201248590Smm archive_write_disk_set_standard_lookup(ad)); 202248590Smm assertEqualIntA(ad, ARCHIVE_OK, 203248590Smm archive_write_disk_set_options(ad, 204248590Smm ARCHIVE_EXTRACT_TIME | 205248590Smm ARCHIVE_EXTRACT_SECURE_SYMLINKS | 206248590Smm ARCHIVE_EXTRACT_SECURE_NODOTDOT)); 207248590Smm 208248590Smm assert((a = archive_read_new()) != NULL); 209248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 210248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 211248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, 212248590Smm refname, 512 * 20)); 213248590Smm 214248590Smm assertMakeDir("nocmp", 0755); 215248590Smm assertChdir("nocmp"); 216248590Smm 217248590Smm /* Extract file1. */ 218248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 219248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 220248590Smm /* Extract README. */ 221248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 222248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 223248590Smm /* Extract NEWS. */ 224248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 225248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 226248590Smm /* Extract Makefile. */ 227248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 228248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); 229248590Smm 230248590Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 231248590Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 232248590Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 233248590Smm assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); 234248590Smm 235248590Smm /* Test file1. */ 236248590Smm assertEqualInt(0, stat("file1", &st)); 237248590Smm assertEqualInt(0, st.st_flags & UF_COMPRESSED); 238248590Smm assertFileSize("file1", 8); 239248590Smm failure("'%s' should not have Resource Fork", "file1"); 240248590Smm assertEqualInt(0, has_xattr("file1", "com.apple.ResourceFork")); 241248590Smm failure("'%s' should not have decmpfs", "file1"); 242248590Smm assertEqualInt(0, has_xattr("file1", "com.apple.decmpfs")); 243248590Smm 244248590Smm /* Test README. */ 245248590Smm assertEqualInt(0, stat("README", &st)); 246248590Smm assertEqualInt(0, st.st_flags & UF_COMPRESSED); 247248590Smm assertFileSize("README", 6586); 248248590Smm failure("'%s' should not have Resource Fork", "README"); 249248590Smm assertEqualInt(0, has_xattr("README", "com.apple.ResourceFork")); 250248590Smm failure("'%s' should not have decmpfs", "README"); 251248590Smm assertEqualInt(0, has_xattr("README", "com.apple.decmpfs")); 252248590Smm 253248590Smm /* Test NEWS. */ 254248590Smm assertEqualInt(0, stat("NEWS", &st)); 255248590Smm assertEqualInt(0, st.st_flags & UF_COMPRESSED); 256248590Smm assertFileSize("NEWS", 28438); 257248590Smm failure("'%s' should not have Resource Fork", "NEWS"); 258248590Smm assertEqualInt(0, has_xattr("NEWS", "com.apple.ResourceFork")); 259248590Smm failure("'%s' should not have decmpfs", "NEWS"); 260248590Smm assertEqualInt(0, has_xattr("NEWS", "com.apple.decmpfs")); 261248590Smm 262248590Smm /* Test Makefile. */ 263248590Smm assertEqualInt(0, stat("Makefile", &st)); 264248590Smm assertEqualInt(0, st.st_flags & UF_COMPRESSED); 265248590Smm assertFileSize("Makefile", 1264000); 266248590Smm failure("'%s' should not have Resource Fork", "Makefile"); 267248590Smm assertEqualInt(0, has_xattr("Makefile", "com.apple.ResourceFork")); 268248590Smm failure("'%s' should not have decmpfs", "Makefile"); 269248590Smm assertEqualInt(0, has_xattr("Makefile", "com.apple.decmpfs")); 270248590Smm 271248590Smm assertChdir(".."); 272248590Smm 273248590Smm assertEqualFile("hfscmp/file1", "nocmp/file1"); 274248590Smm assertEqualFile("hfscmp/README", "nocmp/README"); 275248590Smm assertEqualFile("hfscmp/NEWS", "nocmp/NEWS"); 276248590Smm assertEqualFile("hfscmp/Makefile", "nocmp/Makefile"); 277248590Smm#endif 278248590Smm} 279