1299425Smm/*- 2299425Smm * Copyright (c) 2008 Anselm Strauss 3299425Smm * All rights reserved. 4299425Smm * 5299425Smm * Redistribution and use in source and binary forms, with or without 6299425Smm * modification, are permitted provided that the following conditions 7299425Smm * are met: 8299425Smm * 1. Redistributions of source code must retain the above copyright 9299425Smm * notice, this list of conditions and the following disclaimer. 10299425Smm * 2. Redistributions in binary form must reproduce the above copyright 11299425Smm * notice, this list of conditions and the following disclaimer in the 12299425Smm * documentation and/or other materials provided with the distribution. 13299425Smm * 14299425Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15299425Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16299425Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17299425Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18299425Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19299425Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20299425Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21299425Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22299425Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23299425Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24299425Smm */ 25299425Smm 26299425Smm/* 27299425Smm * Development supported by Google Summer of Code 2008. 28299425Smm */ 29299425Smm 30299425Smm#include "test.h" 31370535Sgit2svn__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c 370535 2021-09-10 08:34:36Z git2svn $"); 32299425Smm 33299425Smm/* File data */ 34299425Smmstatic const char file_name[] = "file"; 35299425Smmstatic const char file_data1[] = {'1', '2', '3', '4', '5'}; 36299425Smmstatic const char file_data2[] = {'6', '7', '8', '9', '0'}; 37299425Smmstatic const int file_perm = 00644; 38299425Smmstatic const short file_uid = 10; 39299425Smmstatic const short file_gid = 20; 40299425Smm 41299425Smm/* Folder data */ 42299425Smmstatic const char folder_name[] = "folder/"; 43299425Smmstatic const int folder_perm = 00755; 44299425Smmstatic const short folder_uid = 30; 45299425Smmstatic const short folder_gid = 40; 46299425Smm 47299425Smmstatic time_t now; 48299425Smm 49299425Smmstatic unsigned long 50299425Smmbitcrc32(unsigned long c, const void *_p, size_t s) 51299425Smm{ 52299425Smm /* This is a drop-in replacement for crc32() from zlib. 53299425Smm * Libarchive should be able to correctly generate 54299425Smm * uncompressed zip archives (including correct CRCs) even 55299425Smm * when zlib is unavailable, and this function helps us verify 56299425Smm * that. Yes, this is very, very slow and unsuitable for 57299425Smm * production use, but it's correct, compact, and works well 58299425Smm * enough for this particular usage. Libarchive internally 59299425Smm * uses a much more efficient implementation. */ 60299425Smm const unsigned char *p = _p; 61299425Smm int bitctr; 62299425Smm 63299425Smm if (p == NULL) 64299425Smm return (0); 65299425Smm 66299425Smm for (; s > 0; --s) { 67299425Smm c ^= *p++; 68299425Smm for (bitctr = 8; bitctr > 0; --bitctr) { 69299425Smm if (c & 1) c = (c >> 1); 70299425Smm else c = (c >> 1) ^ 0xedb88320; 71299425Smm c ^= 0x80000000; 72299425Smm } 73299425Smm } 74299425Smm return (c); 75299425Smm} 76299425Smm 77299425Smmstatic void verify_write_uncompressed(struct archive *a) 78299425Smm{ 79299425Smm struct archive_entry *entry; 80299425Smm 81299425Smm /* Write entries. */ 82299425Smm 83299425Smm /* Regular file */ 84299425Smm assert((entry = archive_entry_new()) != NULL); 85299425Smm archive_entry_set_pathname(entry, file_name); 86299425Smm archive_entry_set_mode(entry, S_IFREG | 0644); 87299425Smm archive_entry_set_size(entry, sizeof(file_data1) + sizeof(file_data2)); 88299425Smm archive_entry_set_uid(entry, file_uid); 89299425Smm archive_entry_set_gid(entry, file_gid); 90299425Smm archive_entry_set_mtime(entry, now, 0); 91299425Smm archive_entry_set_atime(entry, now + 3, 0); 92299425Smm assertEqualIntA(a, 0, archive_write_header(a, entry)); 93299425Smm assertEqualIntA(a, sizeof(file_data1), archive_write_data(a, file_data1, sizeof(file_data1))); 94299425Smm assertEqualIntA(a, sizeof(file_data2), archive_write_data(a, file_data2, sizeof(file_data2))); 95299425Smm archive_entry_free(entry); 96299425Smm 97299425Smm /* Folder */ 98299425Smm assert((entry = archive_entry_new()) != NULL); 99299425Smm archive_entry_set_pathname(entry, folder_name); 100299425Smm archive_entry_set_mode(entry, S_IFDIR | folder_perm); 101299425Smm archive_entry_set_size(entry, 0); 102299425Smm archive_entry_set_uid(entry, folder_uid); 103299425Smm archive_entry_set_gid(entry, folder_gid); 104299425Smm archive_entry_set_mtime(entry, now, 0); 105299425Smm archive_entry_set_ctime(entry, now + 5, 0); 106299425Smm assertEqualIntA(a, 0, archive_write_header(a, entry)); 107299425Smm archive_entry_free(entry); 108299425Smm} 109299425Smm 110299425Smm/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */ 111318482Smmstatic unsigned int 112318482Smmi2(const void *p_) 113318482Smm{ 114318482Smm const unsigned char *p = p_; 115318482Smm return (p[0] | (p[1] << 8)); 116318482Smm} 117299425Smm 118318482Smmstatic unsigned int 119318482Smmi4(const void *p_) 120318482Smm{ 121318482Smm const unsigned char *p = p_; 122318482Smm return (i2(p) | (i2(p + 2) << 16)); 123318482Smm} 124318482Smm 125299425Smmstatic void verify_uncompressed_contents(const char *buff, size_t used) 126299425Smm{ 127299425Smm const char *buffend; 128299425Smm 129299425Smm /* Misc variables */ 130299425Smm unsigned long crc; 131299425Smm struct tm *tm = localtime(&now); 132299425Smm 133299425Smm /* p is the pointer to walk over the central directory, 134299425Smm * q walks over the local headers, the data and the data descriptors. */ 135299425Smm const char *p, *q, *local_header, *extra_start; 136299425Smm 137299425Smm /* Remember the end of the archive in memory. */ 138299425Smm buffend = buff + used; 139299425Smm 140299425Smm /* Verify "End of Central Directory" record. */ 141299425Smm /* Get address of end-of-central-directory record. */ 142299425Smm p = buffend - 22; /* Assumes there is no zip comment field. */ 143299425Smm failure("End-of-central-directory begins with PK\\005\\006 signature"); 144299425Smm assertEqualMem(p, "PK\005\006", 4); 145299425Smm failure("This must be disk 0"); 146299425Smm assertEqualInt(i2(p + 4), 0); 147299425Smm failure("Central dir must start on disk 0"); 148299425Smm assertEqualInt(i2(p + 6), 0); 149299425Smm failure("All central dir entries are on this disk"); 150299425Smm assertEqualInt(i2(p + 8), i2(p + 10)); 151299425Smm failure("CD start (%d) + CD length (%d) should == archive size - 22", 152299425Smm i4(p + 12), i4(p + 16)); 153299425Smm assertEqualInt(i4(p + 12) + i4(p + 16), used - 22); 154299425Smm failure("no zip comment"); 155299425Smm assertEqualInt(i2(p + 20), 0); 156299425Smm 157299425Smm /* Get address of first entry in central directory. */ 158299425Smm p = buff + i4(buffend - 6); 159299425Smm failure("Central file record at offset %d should begin with" 160299425Smm " PK\\001\\002 signature", 161299425Smm i4(buffend - 10)); 162299425Smm 163299425Smm /* Verify file entry in central directory. */ 164299425Smm assertEqualMem(p, "PK\001\002", 4); /* Signature */ 165299425Smm assertEqualInt(i2(p + 4), 3 * 256 + 10); /* Version made by */ 166299425Smm assertEqualInt(i2(p + 6), 10); /* Version needed to extract */ 167299425Smm assertEqualInt(i2(p + 8), 8); /* Flags */ 168299425Smm assertEqualInt(i2(p + 10), 0); /* Compression method */ 169299425Smm assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ 170299425Smm assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ 171299425Smm crc = bitcrc32(0, file_data1, sizeof(file_data1)); 172299425Smm crc = bitcrc32(crc, file_data2, sizeof(file_data2)); 173299425Smm assertEqualInt(i4(p + 16), crc); /* CRC-32 */ 174299425Smm assertEqualInt(i4(p + 20), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ 175299425Smm assertEqualInt(i4(p + 24), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ 176299425Smm assertEqualInt(i2(p + 28), strlen(file_name)); /* Pathname length */ 177299425Smm assertEqualInt(i2(p + 30), 28); /* Extra field length */ 178299425Smm assertEqualInt(i2(p + 32), 0); /* File comment length */ 179299425Smm assertEqualInt(i2(p + 34), 0); /* Disk number start */ 180299425Smm assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ 181299425Smm assertEqualInt(i4(p + 38) >> 16 & 01777, file_perm); /* External file attrs */ 182299425Smm assertEqualInt(i4(p + 42), 0); /* Offset of local header */ 183299425Smm assertEqualMem(p + 46, file_name, strlen(file_name)); /* Pathname */ 184299425Smm p = p + 46 + strlen(file_name); 185299425Smm assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ 186299425Smm assertEqualInt(i2(p + 2), 9); /* 'UT' size */ 187299425Smm assertEqualInt(p[4], 3); /* 'UT' flags */ 188299425Smm assertEqualInt(i4(p + 5), now); /* 'UT' mtime */ 189299425Smm assertEqualInt(i4(p + 9), now + 3); /* 'UT' atime */ 190299425Smm p = p + 4 + i2(p + 2); 191299425Smm assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ 192299425Smm assertEqualInt(i2(p + 2), 11); /* 'ux' size */ 193299425Smm/* TODO */ 194299425Smm p = p + 4 + i2(p + 2); 195299425Smm 196299425Smm /* Verify local header of file entry. */ 197299425Smm local_header = q = buff; 198299425Smm assertEqualMem(q, "PK\003\004", 4); /* Signature */ 199299425Smm assertEqualInt(i2(q + 4), 10); /* Version needed to extract */ 200299425Smm assertEqualInt(i2(q + 6), 8); /* Flags */ 201299425Smm assertEqualInt(i2(q + 8), 0); /* Compression method */ 202299425Smm assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ 203299425Smm assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ 204299425Smm assertEqualInt(i4(q + 14), 0); /* CRC-32 */ 205299425Smm assertEqualInt(i4(q + 18), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ 206299425Smm assertEqualInt(i4(q + 22), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ 207299425Smm assertEqualInt(i2(q + 26), strlen(file_name)); /* Pathname length */ 208299425Smm assertEqualInt(i2(q + 28), 41); /* Extra field length */ 209299425Smm assertEqualMem(q + 30, file_name, strlen(file_name)); /* Pathname */ 210299425Smm extra_start = q = q + 30 + strlen(file_name); 211299425Smm assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ 212299425Smm assertEqualInt(i2(q + 2), 9); /* 'UT' size */ 213299425Smm assertEqualInt(q[4], 3); /* 'UT' flags */ 214299425Smm assertEqualInt(i4(q + 5), now); /* 'UT' mtime */ 215299425Smm assertEqualInt(i4(q + 9), now + 3); /* 'UT' atime */ 216299425Smm q = q + 4 + i2(q + 2); 217299425Smm 218299425Smm assertEqualInt(i2(q), 0x7875); /* 'ux' extension header */ 219299425Smm assertEqualInt(i2(q + 2), 11); /* 'ux' size */ 220299425Smm assertEqualInt(q[4], 1); /* 'ux' version */ 221299425Smm assertEqualInt(q[5], 4); /* 'ux' uid size */ 222299425Smm assertEqualInt(i4(q + 6), file_uid); /* 'Ux' UID */ 223299425Smm assertEqualInt(q[10], 4); /* 'ux' gid size */ 224299425Smm assertEqualInt(i4(q + 11), file_gid); /* 'Ux' GID */ 225299425Smm q = q + 4 + i2(q + 2); 226299425Smm 227299425Smm assertEqualInt(i2(q), 0x6c78); /* 'xl' experimental extension header */ 228299425Smm assertEqualInt(i2(q + 2), 9); /* size */ 229299425Smm assertEqualInt(q[4], 7); /* Bitmap of fields included. */ 230299425Smm assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */ 231299425Smm assertEqualInt(i2(q + 7), 0); /* internal file attributes */ 232299425Smm assertEqualInt(i4(q + 9) >> 16 & 01777, file_perm); /* external file attributes */ 233299425Smm q = q + 4 + i2(q + 2); 234299425Smm 235299425Smm assert(q == extra_start + i2(local_header + 28)); 236299425Smm q = extra_start + i2(local_header + 28); 237299425Smm 238299425Smm /* Verify data of file entry. */ 239299425Smm assertEqualMem(q, file_data1, sizeof(file_data1)); 240299425Smm assertEqualMem(q + sizeof(file_data1), file_data2, sizeof(file_data2)); 241299425Smm q = q + sizeof(file_data1) + sizeof(file_data2); 242299425Smm 243299425Smm /* Verify data descriptor of file entry. */ 244299425Smm assertEqualMem(q, "PK\007\010", 4); /* Signature */ 245299425Smm assertEqualInt(i4(q + 4), crc); /* CRC-32 */ 246299425Smm assertEqualInt(i4(q + 8), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ 247299425Smm assertEqualInt(i4(q + 12), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ 248299425Smm q = q + 16; 249299425Smm 250299425Smm /* Verify folder entry in central directory. */ 251299425Smm assertEqualMem(p, "PK\001\002", 4); /* Signature */ 252299425Smm assertEqualInt(i2(p + 4), 3 * 256 + 20); /* Version made by */ 253299425Smm assertEqualInt(i2(p + 6), 20); /* Version needed to extract */ 254299425Smm assertEqualInt(i2(p + 8), 0); /* Flags */ 255299425Smm assertEqualInt(i2(p + 10), 0); /* Compression method */ 256299425Smm assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ 257299425Smm assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ 258299425Smm crc = 0; 259299425Smm assertEqualInt(i4(p + 16), crc); /* CRC-32 */ 260299425Smm assertEqualInt(i4(p + 20), 0); /* Compressed size */ 261299425Smm assertEqualInt(i4(p + 24), 0); /* Uncompressed size */ 262299425Smm assertEqualInt(i2(p + 28), strlen(folder_name)); /* Pathname length */ 263299425Smm assertEqualInt(i2(p + 30), 28); /* Extra field length */ 264299425Smm assertEqualInt(i2(p + 32), 0); /* File comment length */ 265299425Smm assertEqualInt(i2(p + 34), 0); /* Disk number start */ 266299425Smm assertEqualInt(i2(p + 36), 0); /* Internal file attrs */ 267299425Smm assertEqualInt(i4(p + 38) >> 16 & 01777, folder_perm); /* External file attrs */ 268299425Smm assertEqualInt(i4(p + 42), q - buff); /* Offset of local header */ 269299425Smm assertEqualMem(p + 46, folder_name, strlen(folder_name)); /* Pathname */ 270299425Smm p = p + 46 + strlen(folder_name); 271299425Smm assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ 272299425Smm assertEqualInt(i2(p + 2), 9); /* 'UT' size */ 273299425Smm assertEqualInt(p[4], 5); /* 'UT' flags */ 274299425Smm assertEqualInt(i4(p + 5), now); /* 'UT' mtime */ 275299425Smm assertEqualInt(i4(p + 9), now + 5); /* 'UT' atime */ 276299425Smm p = p + 4 + i2(p + 2); 277299425Smm assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ 278299425Smm assertEqualInt(i2(p + 2), 11); /* 'ux' size */ 279299425Smm assertEqualInt(p[4], 1); /* 'ux' version */ 280299425Smm assertEqualInt(p[5], 4); /* 'ux' uid size */ 281299425Smm assertEqualInt(i4(p + 6), folder_uid); /* 'ux' UID */ 282299425Smm assertEqualInt(p[10], 4); /* 'ux' gid size */ 283299425Smm assertEqualInt(i4(p + 11), folder_gid); /* 'ux' GID */ 284299425Smm /*p = p + 4 + i2(p + 2);*/ 285299425Smm 286299425Smm /* Verify local header of folder entry. */ 287299425Smm local_header = q; 288299425Smm assertEqualMem(q, "PK\003\004", 4); /* Signature */ 289299425Smm assertEqualInt(i2(q + 4), 20); /* Version needed to extract */ 290299425Smm assertEqualInt(i2(q + 6), 0); /* Flags */ 291299425Smm assertEqualInt(i2(q + 8), 0); /* Compression method */ 292299425Smm assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */ 293299425Smm assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */ 294299425Smm assertEqualInt(i4(q + 14), 0); /* CRC-32 */ 295299425Smm assertEqualInt(i4(q + 18), 0); /* Compressed size */ 296299425Smm assertEqualInt(i4(q + 22), 0); /* Uncompressed size */ 297299425Smm assertEqualInt(i2(q + 26), strlen(folder_name)); /* Pathname length */ 298299425Smm assertEqualInt(i2(q + 28), 41); /* Extra field length */ 299299425Smm assertEqualMem(q + 30, folder_name, strlen(folder_name)); /* Pathname */ 300299425Smm extra_start = q = q + 30 + strlen(folder_name); 301299425Smm assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ 302299425Smm assertEqualInt(i2(q + 2), 9); /* 'UT' size */ 303299425Smm assertEqualInt(q[4], 5); /* 'UT' flags */ 304299425Smm assertEqualInt(i4(q + 5), now); /* 'UT' mtime */ 305299425Smm assertEqualInt(i4(q + 9), now + 5); /* 'UT' atime */ 306299425Smm q = q + 4 + i2(q + 2); 307299425Smm assertEqualInt(i2(q), 0x7875); /* 'ux' extension header */ 308299425Smm assertEqualInt(i2(q + 2), 11); /* 'ux' size */ 309299425Smm assertEqualInt(q[4], 1); /* 'ux' version */ 310299425Smm assertEqualInt(q[5], 4); /* 'ux' uid size */ 311299425Smm assertEqualInt(i4(q + 6), folder_uid); /* 'ux' UID */ 312299425Smm assertEqualInt(q[10], 4); /* 'ux' gid size */ 313299425Smm assertEqualInt(i4(q + 11), folder_gid); /* 'ux' GID */ 314299425Smm q = q + 4 + i2(q + 2); 315299425Smm 316299425Smm assertEqualInt(i2(q), 0x6c78); /* 'xl' experimental extension header */ 317299425Smm assertEqualInt(i2(q + 2), 9); /* size */ 318299425Smm assertEqualInt(q[4], 7); /* bitmap of fields */ 319299425Smm assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */ 320299425Smm assertEqualInt(i2(q + 7), 0); /* internal file attributes */ 321299425Smm assertEqualInt(i4(q + 9) >> 16 & 01777, folder_perm); /* external file attributes */ 322299425Smm q = q + 4 + i2(q + 2); 323299425Smm 324299425Smm assert(q == extra_start + i2(local_header + 28)); 325299425Smm q = extra_start + i2(local_header + 28); 326299425Smm 327299425Smm /* There should not be any data in the folder entry, 328299425Smm * so the first central directory entry should be next: */ 329299425Smm assertEqualMem(q, "PK\001\002", 4); /* Signature */ 330299425Smm} 331299425Smm 332299425SmmDEFINE_TEST(test_write_format_zip_compression_store) 333299425Smm{ 334299425Smm /* Buffer data */ 335299425Smm struct archive *a; 336299425Smm char buff[100000]; 337299425Smm size_t used; 338299425Smm 339299425Smm /* Time data */ 340299425Smm now = time(NULL); 341299425Smm 342299425Smm /* Create new ZIP archive in memory without padding. */ 343299425Smm /* Use compression=store to disable compression. */ 344299425Smm assert((a = archive_write_new()) != NULL); 345299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); 346299425Smm assertEqualIntA(a, ARCHIVE_OK, 347299425Smm archive_write_set_options(a, "zip:compression=store")); 348299425Smm assertEqualIntA(a, ARCHIVE_OK, 349299425Smm archive_write_set_options(a, "zip:experimental")); 350299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); 351299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); 352299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); 353299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); 354299425Smm 355299425Smm verify_write_uncompressed(a); 356299425Smm 357299425Smm /* Close the archive . */ 358299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 359299425Smm assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 360299425Smm dumpfile("constructed.zip", buff, used); 361299425Smm 362299425Smm verify_uncompressed_contents(buff, used); 363299425Smm 364299425Smm /* Create new ZIP archive in memory without padding. */ 365299425Smm /* Use compression-level=0 to disable compression. */ 366299425Smm assert((a = archive_write_new()) != NULL); 367299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); 368299425Smm assertEqualIntA(a, ARCHIVE_OK, 369299425Smm archive_write_set_options(a, "zip:compression-level=0")); 370299425Smm assertEqualIntA(a, ARCHIVE_OK, 371299425Smm archive_write_set_options(a, "zip:experimental")); 372299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); 373299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); 374299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); 375299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); 376299425Smm 377299425Smm verify_write_uncompressed(a); 378299425Smm 379299425Smm /* Close the archive . */ 380299425Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 381299425Smm assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 382299425Smm dumpfile("constructed.zip", buff, used); 383299425Smm 384299425Smm verify_uncompressed_contents(buff, used); 385299425Smm 386299425Smm} 387