17f4caa8cSMaxim Sobolev /* 28f8cb840SMaxim Sobolev * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org> 38f8cb840SMaxim Sobolev * All rights reserved. 47f4caa8cSMaxim Sobolev * 58f8cb840SMaxim Sobolev * Redistribution and use in source and binary forms, with or without 68f8cb840SMaxim Sobolev * modification, are permitted provided that the following conditions 78f8cb840SMaxim Sobolev * are met: 88f8cb840SMaxim Sobolev * 1. Redistributions of source code must retain the above copyright 98f8cb840SMaxim Sobolev * notice, this list of conditions and the following disclaimer. 108f8cb840SMaxim Sobolev * 2. Redistributions in binary form must reproduce the above copyright 118f8cb840SMaxim Sobolev * notice, this list of conditions and the following disclaimer in the 128f8cb840SMaxim Sobolev * documentation and/or other materials provided with the distribution. 138f8cb840SMaxim Sobolev * 148f8cb840SMaxim Sobolev * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158f8cb840SMaxim Sobolev * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168f8cb840SMaxim Sobolev * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 178f8cb840SMaxim Sobolev * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 188f8cb840SMaxim Sobolev * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 198f8cb840SMaxim Sobolev * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 208f8cb840SMaxim Sobolev * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 218f8cb840SMaxim Sobolev * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228f8cb840SMaxim Sobolev * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 238f8cb840SMaxim Sobolev * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 248f8cb840SMaxim Sobolev * SUCH DAMAGE. 257f4caa8cSMaxim Sobolev * 267f4caa8cSMaxim Sobolev */ 277f4caa8cSMaxim Sobolev 288f8cb840SMaxim Sobolev #include <sys/cdefs.h> 298f8cb840SMaxim Sobolev __FBSDID("$FreeBSD$"); 308f8cb840SMaxim Sobolev 317f4caa8cSMaxim Sobolev #include <sys/types.h> 3227d0a1a4SMax Khon #include <sys/disk.h> 337f4caa8cSMaxim Sobolev #include <sys/endian.h> 347f4caa8cSMaxim Sobolev #include <sys/param.h> 357f4caa8cSMaxim Sobolev #include <sys/stat.h> 367f4caa8cSMaxim Sobolev #include <sys/uio.h> 377f4caa8cSMaxim Sobolev #include <netinet/in.h> 388f8cb840SMaxim Sobolev #include <ctype.h> 397f4caa8cSMaxim Sobolev #include <err.h> 407f4caa8cSMaxim Sobolev #include <fcntl.h> 417f4caa8cSMaxim Sobolev #include <signal.h> 427f4caa8cSMaxim Sobolev #include <stdio.h> 437f4caa8cSMaxim Sobolev #include <stdlib.h> 447f4caa8cSMaxim Sobolev #include <string.h> 457f4caa8cSMaxim Sobolev #include <unistd.h> 467f4caa8cSMaxim Sobolev 478f8cb840SMaxim Sobolev #include "mkuzip.h" 488f8cb840SMaxim Sobolev #include "mkuz_cloop.h" 498f8cb840SMaxim Sobolev #include "mkuz_blockcache.h" 508f8cb840SMaxim Sobolev #include "mkuz_zlib.h" 518f8cb840SMaxim Sobolev #include "mkuz_lzma.h" 527f4caa8cSMaxim Sobolev 538f8cb840SMaxim Sobolev #define DEFINE_RAW_METHOD(func, rval, args...) typedef rval (*func##_t)(args) 548f8cb840SMaxim Sobolev 558f8cb840SMaxim Sobolev #define DEFAULT_CLSTSIZE 16384 568f8cb840SMaxim Sobolev 578f8cb840SMaxim Sobolev DEFINE_RAW_METHOD(f_init, void *, uint32_t); 588f8cb840SMaxim Sobolev DEFINE_RAW_METHOD(f_compress, void, const char *, uint32_t *); 598f8cb840SMaxim Sobolev 608f8cb840SMaxim Sobolev struct mkuz_format { 618f8cb840SMaxim Sobolev const char *magic; 628f8cb840SMaxim Sobolev const char *default_sufx; 638f8cb840SMaxim Sobolev f_init_t f_init; 648f8cb840SMaxim Sobolev f_compress_t f_compress; 658f8cb840SMaxim Sobolev }; 668f8cb840SMaxim Sobolev 678f8cb840SMaxim Sobolev static struct mkuz_format uzip_fmt = { 688f8cb840SMaxim Sobolev .magic = CLOOP_MAGIC_ZLIB, 698f8cb840SMaxim Sobolev .default_sufx = DEFAULT_SUFX_ZLIB, 708f8cb840SMaxim Sobolev .f_init = &mkuz_zlib_init, 718f8cb840SMaxim Sobolev .f_compress = &mkuz_zlib_compress 728f8cb840SMaxim Sobolev }; 738f8cb840SMaxim Sobolev 748f8cb840SMaxim Sobolev static struct mkuz_format ulzma_fmt = { 758f8cb840SMaxim Sobolev .magic = CLOOP_MAGIC_LZMA, 768f8cb840SMaxim Sobolev .default_sufx = DEFAULT_SUFX_LZMA, 778f8cb840SMaxim Sobolev .f_init = &mkuz_lzma_init, 788f8cb840SMaxim Sobolev .f_compress = &mkuz_lzma_compress 798f8cb840SMaxim Sobolev }; 807f4caa8cSMaxim Sobolev 817f4caa8cSMaxim Sobolev static char *readblock(int, char *, u_int32_t); 827f4caa8cSMaxim Sobolev static void usage(void); 837f4caa8cSMaxim Sobolev static void cleanup(void); 848f8cb840SMaxim Sobolev static int memvcmp(const void *, unsigned char, size_t); 857f4caa8cSMaxim Sobolev 867f4caa8cSMaxim Sobolev static char *cleanfile = NULL; 877f4caa8cSMaxim Sobolev 887f4caa8cSMaxim Sobolev int main(int argc, char **argv) 897f4caa8cSMaxim Sobolev { 907f4caa8cSMaxim Sobolev char *iname, *oname, *obuf, *ibuf; 917f4caa8cSMaxim Sobolev uint64_t *toc; 928f8cb840SMaxim Sobolev int fdr, fdw, i, opt, verbose, no_zcomp, tmp, en_dedup; 93*d83e0778SMaxim Sobolev int summary; 947f4caa8cSMaxim Sobolev struct iovec iov[2]; 957f4caa8cSMaxim Sobolev struct stat sb; 968f8cb840SMaxim Sobolev uint32_t destlen; 978f8cb840SMaxim Sobolev uint64_t offset, last_offset; 988f8cb840SMaxim Sobolev struct cloop_header hdr; 998f8cb840SMaxim Sobolev struct mkuz_blkcache_hit *chit; 1008f8cb840SMaxim Sobolev const struct mkuz_format *handler; 1017f4caa8cSMaxim Sobolev 1027f4caa8cSMaxim Sobolev memset(&hdr, 0, sizeof(hdr)); 1038f8cb840SMaxim Sobolev hdr.blksz = DEFAULT_CLSTSIZE; 1047f4caa8cSMaxim Sobolev oname = NULL; 1057f4caa8cSMaxim Sobolev verbose = 0; 1068f8cb840SMaxim Sobolev no_zcomp = 0; 1078f8cb840SMaxim Sobolev en_dedup = 0; 108*d83e0778SMaxim Sobolev summary = 0; 1098f8cb840SMaxim Sobolev handler = &uzip_fmt; 1107f4caa8cSMaxim Sobolev 111*d83e0778SMaxim Sobolev while((opt = getopt(argc, argv, "o:s:vZdLS")) != -1) { 1127f4caa8cSMaxim Sobolev switch(opt) { 1137f4caa8cSMaxim Sobolev case 'o': 1147f4caa8cSMaxim Sobolev oname = optarg; 1157f4caa8cSMaxim Sobolev break; 1167f4caa8cSMaxim Sobolev 1177f4caa8cSMaxim Sobolev case 's': 1187f4caa8cSMaxim Sobolev tmp = atoi(optarg); 1197f4caa8cSMaxim Sobolev if (tmp <= 0) { 1207f4caa8cSMaxim Sobolev errx(1, "invalid cluster size specified: %s", 1217f4caa8cSMaxim Sobolev optarg); 1227f4caa8cSMaxim Sobolev /* Not reached */ 1237f4caa8cSMaxim Sobolev } 1247f4caa8cSMaxim Sobolev hdr.blksz = tmp; 1257f4caa8cSMaxim Sobolev break; 1267f4caa8cSMaxim Sobolev 1277f4caa8cSMaxim Sobolev case 'v': 1287f4caa8cSMaxim Sobolev verbose = 1; 1297f4caa8cSMaxim Sobolev break; 1307f4caa8cSMaxim Sobolev 1318f8cb840SMaxim Sobolev case 'Z': 1328f8cb840SMaxim Sobolev no_zcomp = 1; 1338f8cb840SMaxim Sobolev break; 1348f8cb840SMaxim Sobolev 1358f8cb840SMaxim Sobolev case 'd': 1368f8cb840SMaxim Sobolev en_dedup = 1; 1378f8cb840SMaxim Sobolev break; 1388f8cb840SMaxim Sobolev 1398f8cb840SMaxim Sobolev case 'L': 1408f8cb840SMaxim Sobolev handler = &ulzma_fmt; 1418f8cb840SMaxim Sobolev break; 1428f8cb840SMaxim Sobolev 143*d83e0778SMaxim Sobolev case 'S': 144*d83e0778SMaxim Sobolev summary = 1; 145*d83e0778SMaxim Sobolev break; 146*d83e0778SMaxim Sobolev 1477f4caa8cSMaxim Sobolev default: 1487f4caa8cSMaxim Sobolev usage(); 1497f4caa8cSMaxim Sobolev /* Not reached */ 1507f4caa8cSMaxim Sobolev } 1517f4caa8cSMaxim Sobolev } 1527f4caa8cSMaxim Sobolev argc -= optind; 1537f4caa8cSMaxim Sobolev argv += optind; 1547f4caa8cSMaxim Sobolev 1557f4caa8cSMaxim Sobolev if (argc != 1) { 1567f4caa8cSMaxim Sobolev usage(); 1577f4caa8cSMaxim Sobolev /* Not reached */ 1587f4caa8cSMaxim Sobolev } 1597f4caa8cSMaxim Sobolev 1608f8cb840SMaxim Sobolev strcpy(hdr.magic, handler->magic); 1618f8cb840SMaxim Sobolev 1628f8cb840SMaxim Sobolev if (en_dedup != 0) { 1638f8cb840SMaxim Sobolev hdr.magic[CLOOP_OFS_VERSN] = CLOOP_MAJVER_3; 1648f8cb840SMaxim Sobolev hdr.magic[CLOOP_OFS_COMPR] = 1658f8cb840SMaxim Sobolev tolower(hdr.magic[CLOOP_OFS_COMPR]); 1668f8cb840SMaxim Sobolev } 1678f8cb840SMaxim Sobolev 1688f8cb840SMaxim Sobolev obuf = handler->f_init(hdr.blksz); 1698f8cb840SMaxim Sobolev 1707f4caa8cSMaxim Sobolev iname = argv[0]; 1717f4caa8cSMaxim Sobolev if (oname == NULL) { 1728f8cb840SMaxim Sobolev asprintf(&oname, "%s%s", iname, handler->default_sufx); 1737f4caa8cSMaxim Sobolev if (oname == NULL) { 1747f4caa8cSMaxim Sobolev err(1, "can't allocate memory"); 1757f4caa8cSMaxim Sobolev /* Not reached */ 1767f4caa8cSMaxim Sobolev } 1777f4caa8cSMaxim Sobolev } 1787f4caa8cSMaxim Sobolev 1798f8cb840SMaxim Sobolev ibuf = mkuz_safe_malloc(hdr.blksz); 1807f4caa8cSMaxim Sobolev 1817f4caa8cSMaxim Sobolev signal(SIGHUP, exit); 1827f4caa8cSMaxim Sobolev signal(SIGINT, exit); 1837f4caa8cSMaxim Sobolev signal(SIGTERM, exit); 1847f4caa8cSMaxim Sobolev signal(SIGXCPU, exit); 1857f4caa8cSMaxim Sobolev signal(SIGXFSZ, exit); 1867f4caa8cSMaxim Sobolev atexit(cleanup); 1877f4caa8cSMaxim Sobolev 18827d0a1a4SMax Khon fdr = open(iname, O_RDONLY); 18927d0a1a4SMax Khon if (fdr < 0) { 19027d0a1a4SMax Khon err(1, "open(%s)", iname); 1917f4caa8cSMaxim Sobolev /* Not reached */ 1927f4caa8cSMaxim Sobolev } 19327d0a1a4SMax Khon if (fstat(fdr, &sb) != 0) { 19427d0a1a4SMax Khon err(1, "fstat(%s)", iname); 19527d0a1a4SMax Khon /* Not reached */ 19627d0a1a4SMax Khon } 19727d0a1a4SMax Khon if (S_ISCHR(sb.st_mode)) { 19827d0a1a4SMax Khon off_t ms; 19927d0a1a4SMax Khon 20027d0a1a4SMax Khon if (ioctl(fdr, DIOCGMEDIASIZE, &ms) < 0) { 20127d0a1a4SMax Khon err(1, "ioctl(DIOCGMEDIASIZE)"); 20227d0a1a4SMax Khon /* Not reached */ 20327d0a1a4SMax Khon } 20427d0a1a4SMax Khon sb.st_size = ms; 20527d0a1a4SMax Khon } else if (!S_ISREG(sb.st_mode)) { 20627d0a1a4SMax Khon fprintf(stderr, "%s: not a character device or regular file\n", 20727d0a1a4SMax Khon iname); 20827d0a1a4SMax Khon exit(1); 20927d0a1a4SMax Khon } 2107f4caa8cSMaxim Sobolev hdr.nblocks = sb.st_size / hdr.blksz; 2110b99ac63SMaxim Sobolev if ((sb.st_size % hdr.blksz) != 0) { 2120b99ac63SMaxim Sobolev if (verbose != 0) 2130b99ac63SMaxim Sobolev fprintf(stderr, "file size is not multiple " 2140b99ac63SMaxim Sobolev "of %d, padding data\n", hdr.blksz); 2150b99ac63SMaxim Sobolev hdr.nblocks++; 2160b99ac63SMaxim Sobolev } 2178f8cb840SMaxim Sobolev toc = mkuz_safe_malloc((hdr.nblocks + 1) * sizeof(*toc)); 2187f4caa8cSMaxim Sobolev 2197f4caa8cSMaxim Sobolev fdw = open(oname, O_WRONLY | O_TRUNC | O_CREAT, 2205cf3bf70SMax Khon S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 2217f4caa8cSMaxim Sobolev if (fdw < 0) { 222d72d8f53SPawel Jakub Dawidek err(1, "open(%s)", oname); 2237f4caa8cSMaxim Sobolev /* Not reached */ 2247f4caa8cSMaxim Sobolev } 2257f4caa8cSMaxim Sobolev cleanfile = oname; 2267f4caa8cSMaxim Sobolev 2277f4caa8cSMaxim Sobolev /* Prepare header that we will write later when we have index ready. */ 2287f4caa8cSMaxim Sobolev iov[0].iov_base = (char *)&hdr; 2297f4caa8cSMaxim Sobolev iov[0].iov_len = sizeof(hdr); 2307f4caa8cSMaxim Sobolev iov[1].iov_base = (char *)toc; 2317f4caa8cSMaxim Sobolev iov[1].iov_len = (hdr.nblocks + 1) * sizeof(*toc); 2327f4caa8cSMaxim Sobolev offset = iov[0].iov_len + iov[1].iov_len; 2337f4caa8cSMaxim Sobolev 2347f4caa8cSMaxim Sobolev /* Reserve space for header */ 2357f4caa8cSMaxim Sobolev lseek(fdw, offset, SEEK_SET); 2367f4caa8cSMaxim Sobolev 2377f4caa8cSMaxim Sobolev if (verbose != 0) 238ed9302fdSMaxim Sobolev fprintf(stderr, "data size %ju bytes, number of clusters " 2395cf3bf70SMax Khon "%u, index length %zu bytes\n", sb.st_size, 2400b99ac63SMaxim Sobolev hdr.nblocks, iov[1].iov_len); 2417f4caa8cSMaxim Sobolev 2428f8cb840SMaxim Sobolev last_offset = 0; 2437f4caa8cSMaxim Sobolev for(i = 0; i == 0 || ibuf != NULL; i++) { 2447f4caa8cSMaxim Sobolev ibuf = readblock(fdr, ibuf, hdr.blksz); 2457f4caa8cSMaxim Sobolev if (ibuf != NULL) { 2468f8cb840SMaxim Sobolev if (no_zcomp == 0 && \ 2478f8cb840SMaxim Sobolev memvcmp(ibuf, '\0', hdr.blksz) != 0) { 2488f8cb840SMaxim Sobolev /* All zeroes block */ 2498f8cb840SMaxim Sobolev destlen = 0; 2508f8cb840SMaxim Sobolev } else { 2518f8cb840SMaxim Sobolev handler->f_compress(ibuf, &destlen); 2527f4caa8cSMaxim Sobolev } 2537f4caa8cSMaxim Sobolev } else { 2547f4caa8cSMaxim Sobolev destlen = DEV_BSIZE - (offset % DEV_BSIZE); 2557f4caa8cSMaxim Sobolev memset(obuf, 0, destlen); 2560b99ac63SMaxim Sobolev if (verbose != 0) 2578f8cb840SMaxim Sobolev fprintf(stderr, "padding data with %lu bytes " 2588f8cb840SMaxim Sobolev "so that file size is multiple of %d\n", 2598f8cb840SMaxim Sobolev (u_long)destlen, DEV_BSIZE); 2607f4caa8cSMaxim Sobolev } 2618f8cb840SMaxim Sobolev if (destlen > 0 && en_dedup != 0) { 2628f8cb840SMaxim Sobolev chit = mkuz_blkcache_regblock(fdw, i, offset, destlen, 2638f8cb840SMaxim Sobolev obuf); 2648f8cb840SMaxim Sobolev /* 2658f8cb840SMaxim Sobolev * There should be at least one non-empty block 2668f8cb840SMaxim Sobolev * between us and the backref'ed offset, otherwise 2678f8cb840SMaxim Sobolev * we won't be able to parse that sequence correctly 2688f8cb840SMaxim Sobolev * as it would be indistinguishible from another 2698f8cb840SMaxim Sobolev * empty block. 2708f8cb840SMaxim Sobolev */ 2718f8cb840SMaxim Sobolev if (chit != NULL && chit->offset == last_offset) { 2728f8cb840SMaxim Sobolev chit = NULL; 2738f8cb840SMaxim Sobolev } 2748f8cb840SMaxim Sobolev } else { 2758f8cb840SMaxim Sobolev chit = NULL; 2768f8cb840SMaxim Sobolev } 2778f8cb840SMaxim Sobolev if (chit != NULL) { 2788f8cb840SMaxim Sobolev toc[i] = htobe64(chit->offset); 2798f8cb840SMaxim Sobolev } else { 2808f8cb840SMaxim Sobolev if (destlen > 0 && write(fdw, obuf, destlen) < 0) { 281d72d8f53SPawel Jakub Dawidek err(1, "write(%s)", oname); 2827f4caa8cSMaxim Sobolev /* Not reached */ 2837f4caa8cSMaxim Sobolev } 2847f4caa8cSMaxim Sobolev toc[i] = htobe64(offset); 2858f8cb840SMaxim Sobolev last_offset = offset; 2867f4caa8cSMaxim Sobolev offset += destlen; 2877f4caa8cSMaxim Sobolev } 2888f8cb840SMaxim Sobolev if (ibuf != NULL && verbose != 0) { 2898f8cb840SMaxim Sobolev fprintf(stderr, "cluster #%d, in %u bytes, " 2908f8cb840SMaxim Sobolev "out len=%lu offset=%lu", i, hdr.blksz, 2918f8cb840SMaxim Sobolev chit == NULL ? (u_long)destlen : 0, 2928f8cb840SMaxim Sobolev (u_long)be64toh(toc[i])); 2938f8cb840SMaxim Sobolev if (chit != NULL) { 2948f8cb840SMaxim Sobolev fprintf(stderr, " (backref'ed to #%d)", 2958f8cb840SMaxim Sobolev chit->blkno); 2968f8cb840SMaxim Sobolev } 2978f8cb840SMaxim Sobolev fprintf(stderr, "\n"); 2988f8cb840SMaxim Sobolev 2998f8cb840SMaxim Sobolev } 3008f8cb840SMaxim Sobolev } 3017f4caa8cSMaxim Sobolev close(fdr); 3027f4caa8cSMaxim Sobolev 303*d83e0778SMaxim Sobolev if (verbose != 0 || summary != 0) 304ed9302fdSMaxim Sobolev fprintf(stderr, "compressed data to %ju bytes, saved %lld " 3058f8cb840SMaxim Sobolev "bytes, %.2f%% decrease.\n", offset, 3068f8cb840SMaxim Sobolev (long long)(sb.st_size - offset), 3078f8cb840SMaxim Sobolev 100.0 * (long long)(sb.st_size - offset) / 3088f8cb840SMaxim Sobolev (float)sb.st_size); 3097f4caa8cSMaxim Sobolev 3107f4caa8cSMaxim Sobolev /* Convert to big endian */ 3117f4caa8cSMaxim Sobolev hdr.blksz = htonl(hdr.blksz); 3127f4caa8cSMaxim Sobolev hdr.nblocks = htonl(hdr.nblocks); 3137f4caa8cSMaxim Sobolev /* Write headers into pre-allocated space */ 3147f4caa8cSMaxim Sobolev lseek(fdw, 0, SEEK_SET); 3157f4caa8cSMaxim Sobolev if (writev(fdw, iov, 2) < 0) { 316d72d8f53SPawel Jakub Dawidek err(1, "writev(%s)", oname); 3177f4caa8cSMaxim Sobolev /* Not reached */ 3187f4caa8cSMaxim Sobolev } 3197f4caa8cSMaxim Sobolev cleanfile = NULL; 3207f4caa8cSMaxim Sobolev close(fdw); 3217f4caa8cSMaxim Sobolev 3227f4caa8cSMaxim Sobolev exit(0); 3237f4caa8cSMaxim Sobolev } 3247f4caa8cSMaxim Sobolev 3257f4caa8cSMaxim Sobolev static char * 3260b99ac63SMaxim Sobolev readblock(int fd, char *ibuf, u_int32_t clstsize) 3270b99ac63SMaxim Sobolev { 3287f4caa8cSMaxim Sobolev int numread; 3297f4caa8cSMaxim Sobolev 3307f4caa8cSMaxim Sobolev bzero(ibuf, clstsize); 3317f4caa8cSMaxim Sobolev numread = read(fd, ibuf, clstsize); 3327f4caa8cSMaxim Sobolev if (numread < 0) { 3337f4caa8cSMaxim Sobolev err(1, "read() failed"); 3347f4caa8cSMaxim Sobolev /* Not reached */ 3357f4caa8cSMaxim Sobolev } 3367f4caa8cSMaxim Sobolev if (numread == 0) { 3377f4caa8cSMaxim Sobolev return NULL; 3387f4caa8cSMaxim Sobolev } 3397f4caa8cSMaxim Sobolev return ibuf; 3407f4caa8cSMaxim Sobolev } 3417f4caa8cSMaxim Sobolev 3427f4caa8cSMaxim Sobolev static void 3430b99ac63SMaxim Sobolev usage(void) 3440b99ac63SMaxim Sobolev { 3457f4caa8cSMaxim Sobolev 346*d83e0778SMaxim Sobolev fprintf(stderr, "usage: mkuzip [-vZdLS] [-o outfile] [-s cluster_size] " 3478f8cb840SMaxim Sobolev "infile\n"); 3487f4caa8cSMaxim Sobolev exit(1); 3497f4caa8cSMaxim Sobolev } 3507f4caa8cSMaxim Sobolev 3518f8cb840SMaxim Sobolev void * 3528f8cb840SMaxim Sobolev mkuz_safe_malloc(size_t size) 3530b99ac63SMaxim Sobolev { 3547f4caa8cSMaxim Sobolev void *retval; 3557f4caa8cSMaxim Sobolev 3567f4caa8cSMaxim Sobolev retval = malloc(size); 3577f4caa8cSMaxim Sobolev if (retval == NULL) { 3587f4caa8cSMaxim Sobolev err(1, "can't allocate memory"); 3597f4caa8cSMaxim Sobolev /* Not reached */ 3607f4caa8cSMaxim Sobolev } 3617f4caa8cSMaxim Sobolev return retval; 3627f4caa8cSMaxim Sobolev } 3637f4caa8cSMaxim Sobolev 3647f4caa8cSMaxim Sobolev static void 3650b99ac63SMaxim Sobolev cleanup(void) 3660b99ac63SMaxim Sobolev { 3677f4caa8cSMaxim Sobolev 3687f4caa8cSMaxim Sobolev if (cleanfile != NULL) 3697f4caa8cSMaxim Sobolev unlink(cleanfile); 3707f4caa8cSMaxim Sobolev } 3718f8cb840SMaxim Sobolev 3728f8cb840SMaxim Sobolev static int 3738f8cb840SMaxim Sobolev memvcmp(const void *memory, unsigned char val, size_t size) 3748f8cb840SMaxim Sobolev { 3758f8cb840SMaxim Sobolev const u_char *mm; 3768f8cb840SMaxim Sobolev 3778f8cb840SMaxim Sobolev mm = (const u_char *)memory; 3788f8cb840SMaxim Sobolev return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0; 3798f8cb840SMaxim Sobolev } 380