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*62ee4b69SMaxim Sobolev struct { 94*62ee4b69SMaxim Sobolev int en; 95*62ee4b69SMaxim Sobolev FILE *f; 96*62ee4b69SMaxim Sobolev } summary; 977f4caa8cSMaxim Sobolev struct iovec iov[2]; 987f4caa8cSMaxim Sobolev struct stat sb; 998f8cb840SMaxim Sobolev uint32_t destlen; 1008f8cb840SMaxim Sobolev uint64_t offset, last_offset; 1018f8cb840SMaxim Sobolev struct cloop_header hdr; 1028f8cb840SMaxim Sobolev struct mkuz_blkcache_hit *chit; 1038f8cb840SMaxim Sobolev const struct mkuz_format *handler; 1047f4caa8cSMaxim Sobolev 1057f4caa8cSMaxim Sobolev memset(&hdr, 0, sizeof(hdr)); 1068f8cb840SMaxim Sobolev hdr.blksz = DEFAULT_CLSTSIZE; 1077f4caa8cSMaxim Sobolev oname = NULL; 1087f4caa8cSMaxim Sobolev verbose = 0; 1098f8cb840SMaxim Sobolev no_zcomp = 0; 1108f8cb840SMaxim Sobolev en_dedup = 0; 111*62ee4b69SMaxim Sobolev summary.en = 0; 112*62ee4b69SMaxim Sobolev summary.f = stderr; 1138f8cb840SMaxim Sobolev handler = &uzip_fmt; 1147f4caa8cSMaxim Sobolev 115d83e0778SMaxim Sobolev while((opt = getopt(argc, argv, "o:s:vZdLS")) != -1) { 1167f4caa8cSMaxim Sobolev switch(opt) { 1177f4caa8cSMaxim Sobolev case 'o': 1187f4caa8cSMaxim Sobolev oname = optarg; 1197f4caa8cSMaxim Sobolev break; 1207f4caa8cSMaxim Sobolev 1217f4caa8cSMaxim Sobolev case 's': 1227f4caa8cSMaxim Sobolev tmp = atoi(optarg); 1237f4caa8cSMaxim Sobolev if (tmp <= 0) { 1247f4caa8cSMaxim Sobolev errx(1, "invalid cluster size specified: %s", 1257f4caa8cSMaxim Sobolev optarg); 1267f4caa8cSMaxim Sobolev /* Not reached */ 1277f4caa8cSMaxim Sobolev } 1287f4caa8cSMaxim Sobolev hdr.blksz = tmp; 1297f4caa8cSMaxim Sobolev break; 1307f4caa8cSMaxim Sobolev 1317f4caa8cSMaxim Sobolev case 'v': 1327f4caa8cSMaxim Sobolev verbose = 1; 1337f4caa8cSMaxim Sobolev break; 1347f4caa8cSMaxim Sobolev 1358f8cb840SMaxim Sobolev case 'Z': 1368f8cb840SMaxim Sobolev no_zcomp = 1; 1378f8cb840SMaxim Sobolev break; 1388f8cb840SMaxim Sobolev 1398f8cb840SMaxim Sobolev case 'd': 1408f8cb840SMaxim Sobolev en_dedup = 1; 1418f8cb840SMaxim Sobolev break; 1428f8cb840SMaxim Sobolev 1438f8cb840SMaxim Sobolev case 'L': 1448f8cb840SMaxim Sobolev handler = &ulzma_fmt; 1458f8cb840SMaxim Sobolev break; 1468f8cb840SMaxim Sobolev 147d83e0778SMaxim Sobolev case 'S': 148*62ee4b69SMaxim Sobolev summary.en = 1; 149*62ee4b69SMaxim Sobolev summary.f = stdout; 150d83e0778SMaxim Sobolev break; 151d83e0778SMaxim Sobolev 1527f4caa8cSMaxim Sobolev default: 1537f4caa8cSMaxim Sobolev usage(); 1547f4caa8cSMaxim Sobolev /* Not reached */ 1557f4caa8cSMaxim Sobolev } 1567f4caa8cSMaxim Sobolev } 1577f4caa8cSMaxim Sobolev argc -= optind; 1587f4caa8cSMaxim Sobolev argv += optind; 1597f4caa8cSMaxim Sobolev 1607f4caa8cSMaxim Sobolev if (argc != 1) { 1617f4caa8cSMaxim Sobolev usage(); 1627f4caa8cSMaxim Sobolev /* Not reached */ 1637f4caa8cSMaxim Sobolev } 1647f4caa8cSMaxim Sobolev 1658f8cb840SMaxim Sobolev strcpy(hdr.magic, handler->magic); 1668f8cb840SMaxim Sobolev 1678f8cb840SMaxim Sobolev if (en_dedup != 0) { 1688f8cb840SMaxim Sobolev hdr.magic[CLOOP_OFS_VERSN] = CLOOP_MAJVER_3; 1698f8cb840SMaxim Sobolev hdr.magic[CLOOP_OFS_COMPR] = 1708f8cb840SMaxim Sobolev tolower(hdr.magic[CLOOP_OFS_COMPR]); 1718f8cb840SMaxim Sobolev } 1728f8cb840SMaxim Sobolev 1738f8cb840SMaxim Sobolev obuf = handler->f_init(hdr.blksz); 1748f8cb840SMaxim Sobolev 1757f4caa8cSMaxim Sobolev iname = argv[0]; 1767f4caa8cSMaxim Sobolev if (oname == NULL) { 1778f8cb840SMaxim Sobolev asprintf(&oname, "%s%s", iname, handler->default_sufx); 1787f4caa8cSMaxim Sobolev if (oname == NULL) { 1797f4caa8cSMaxim Sobolev err(1, "can't allocate memory"); 1807f4caa8cSMaxim Sobolev /* Not reached */ 1817f4caa8cSMaxim Sobolev } 1827f4caa8cSMaxim Sobolev } 1837f4caa8cSMaxim Sobolev 1848f8cb840SMaxim Sobolev ibuf = mkuz_safe_malloc(hdr.blksz); 1857f4caa8cSMaxim Sobolev 1867f4caa8cSMaxim Sobolev signal(SIGHUP, exit); 1877f4caa8cSMaxim Sobolev signal(SIGINT, exit); 1887f4caa8cSMaxim Sobolev signal(SIGTERM, exit); 1897f4caa8cSMaxim Sobolev signal(SIGXCPU, exit); 1907f4caa8cSMaxim Sobolev signal(SIGXFSZ, exit); 1917f4caa8cSMaxim Sobolev atexit(cleanup); 1927f4caa8cSMaxim Sobolev 19327d0a1a4SMax Khon fdr = open(iname, O_RDONLY); 19427d0a1a4SMax Khon if (fdr < 0) { 19527d0a1a4SMax Khon err(1, "open(%s)", iname); 1967f4caa8cSMaxim Sobolev /* Not reached */ 1977f4caa8cSMaxim Sobolev } 19827d0a1a4SMax Khon if (fstat(fdr, &sb) != 0) { 19927d0a1a4SMax Khon err(1, "fstat(%s)", iname); 20027d0a1a4SMax Khon /* Not reached */ 20127d0a1a4SMax Khon } 20227d0a1a4SMax Khon if (S_ISCHR(sb.st_mode)) { 20327d0a1a4SMax Khon off_t ms; 20427d0a1a4SMax Khon 20527d0a1a4SMax Khon if (ioctl(fdr, DIOCGMEDIASIZE, &ms) < 0) { 20627d0a1a4SMax Khon err(1, "ioctl(DIOCGMEDIASIZE)"); 20727d0a1a4SMax Khon /* Not reached */ 20827d0a1a4SMax Khon } 20927d0a1a4SMax Khon sb.st_size = ms; 21027d0a1a4SMax Khon } else if (!S_ISREG(sb.st_mode)) { 21127d0a1a4SMax Khon fprintf(stderr, "%s: not a character device or regular file\n", 21227d0a1a4SMax Khon iname); 21327d0a1a4SMax Khon exit(1); 21427d0a1a4SMax Khon } 2157f4caa8cSMaxim Sobolev hdr.nblocks = sb.st_size / hdr.blksz; 2160b99ac63SMaxim Sobolev if ((sb.st_size % hdr.blksz) != 0) { 2170b99ac63SMaxim Sobolev if (verbose != 0) 2180b99ac63SMaxim Sobolev fprintf(stderr, "file size is not multiple " 2190b99ac63SMaxim Sobolev "of %d, padding data\n", hdr.blksz); 2200b99ac63SMaxim Sobolev hdr.nblocks++; 2210b99ac63SMaxim Sobolev } 2228f8cb840SMaxim Sobolev toc = mkuz_safe_malloc((hdr.nblocks + 1) * sizeof(*toc)); 2237f4caa8cSMaxim Sobolev 2247f4caa8cSMaxim Sobolev fdw = open(oname, O_WRONLY | O_TRUNC | O_CREAT, 2255cf3bf70SMax Khon S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 2267f4caa8cSMaxim Sobolev if (fdw < 0) { 227d72d8f53SPawel Jakub Dawidek err(1, "open(%s)", oname); 2287f4caa8cSMaxim Sobolev /* Not reached */ 2297f4caa8cSMaxim Sobolev } 2307f4caa8cSMaxim Sobolev cleanfile = oname; 2317f4caa8cSMaxim Sobolev 2327f4caa8cSMaxim Sobolev /* Prepare header that we will write later when we have index ready. */ 2337f4caa8cSMaxim Sobolev iov[0].iov_base = (char *)&hdr; 2347f4caa8cSMaxim Sobolev iov[0].iov_len = sizeof(hdr); 2357f4caa8cSMaxim Sobolev iov[1].iov_base = (char *)toc; 2367f4caa8cSMaxim Sobolev iov[1].iov_len = (hdr.nblocks + 1) * sizeof(*toc); 2377f4caa8cSMaxim Sobolev offset = iov[0].iov_len + iov[1].iov_len; 2387f4caa8cSMaxim Sobolev 2397f4caa8cSMaxim Sobolev /* Reserve space for header */ 2407f4caa8cSMaxim Sobolev lseek(fdw, offset, SEEK_SET); 2417f4caa8cSMaxim Sobolev 2427f4caa8cSMaxim Sobolev if (verbose != 0) 243ed9302fdSMaxim Sobolev fprintf(stderr, "data size %ju bytes, number of clusters " 2445cf3bf70SMax Khon "%u, index length %zu bytes\n", sb.st_size, 2450b99ac63SMaxim Sobolev hdr.nblocks, iov[1].iov_len); 2467f4caa8cSMaxim Sobolev 2478f8cb840SMaxim Sobolev last_offset = 0; 2487f4caa8cSMaxim Sobolev for(i = 0; i == 0 || ibuf != NULL; i++) { 2497f4caa8cSMaxim Sobolev ibuf = readblock(fdr, ibuf, hdr.blksz); 2507f4caa8cSMaxim Sobolev if (ibuf != NULL) { 2518f8cb840SMaxim Sobolev if (no_zcomp == 0 && \ 2528f8cb840SMaxim Sobolev memvcmp(ibuf, '\0', hdr.blksz) != 0) { 2538f8cb840SMaxim Sobolev /* All zeroes block */ 2548f8cb840SMaxim Sobolev destlen = 0; 2558f8cb840SMaxim Sobolev } else { 2568f8cb840SMaxim Sobolev handler->f_compress(ibuf, &destlen); 2577f4caa8cSMaxim Sobolev } 2587f4caa8cSMaxim Sobolev } else { 2597f4caa8cSMaxim Sobolev destlen = DEV_BSIZE - (offset % DEV_BSIZE); 2607f4caa8cSMaxim Sobolev memset(obuf, 0, destlen); 2610b99ac63SMaxim Sobolev if (verbose != 0) 2628f8cb840SMaxim Sobolev fprintf(stderr, "padding data with %lu bytes " 2638f8cb840SMaxim Sobolev "so that file size is multiple of %d\n", 2648f8cb840SMaxim Sobolev (u_long)destlen, DEV_BSIZE); 2657f4caa8cSMaxim Sobolev } 2668f8cb840SMaxim Sobolev if (destlen > 0 && en_dedup != 0) { 2678f8cb840SMaxim Sobolev chit = mkuz_blkcache_regblock(fdw, i, offset, destlen, 2688f8cb840SMaxim Sobolev obuf); 2698f8cb840SMaxim Sobolev /* 2708f8cb840SMaxim Sobolev * There should be at least one non-empty block 2718f8cb840SMaxim Sobolev * between us and the backref'ed offset, otherwise 2728f8cb840SMaxim Sobolev * we won't be able to parse that sequence correctly 2738f8cb840SMaxim Sobolev * as it would be indistinguishible from another 2748f8cb840SMaxim Sobolev * empty block. 2758f8cb840SMaxim Sobolev */ 2768f8cb840SMaxim Sobolev if (chit != NULL && chit->offset == last_offset) { 2778f8cb840SMaxim Sobolev chit = NULL; 2788f8cb840SMaxim Sobolev } 2798f8cb840SMaxim Sobolev } else { 2808f8cb840SMaxim Sobolev chit = NULL; 2818f8cb840SMaxim Sobolev } 2828f8cb840SMaxim Sobolev if (chit != NULL) { 2838f8cb840SMaxim Sobolev toc[i] = htobe64(chit->offset); 2848f8cb840SMaxim Sobolev } else { 2858f8cb840SMaxim Sobolev if (destlen > 0 && write(fdw, obuf, destlen) < 0) { 286d72d8f53SPawel Jakub Dawidek err(1, "write(%s)", oname); 2877f4caa8cSMaxim Sobolev /* Not reached */ 2887f4caa8cSMaxim Sobolev } 2897f4caa8cSMaxim Sobolev toc[i] = htobe64(offset); 2908f8cb840SMaxim Sobolev last_offset = offset; 2917f4caa8cSMaxim Sobolev offset += destlen; 2927f4caa8cSMaxim Sobolev } 2938f8cb840SMaxim Sobolev if (ibuf != NULL && verbose != 0) { 2948f8cb840SMaxim Sobolev fprintf(stderr, "cluster #%d, in %u bytes, " 2958f8cb840SMaxim Sobolev "out len=%lu offset=%lu", i, hdr.blksz, 2968f8cb840SMaxim Sobolev chit == NULL ? (u_long)destlen : 0, 2978f8cb840SMaxim Sobolev (u_long)be64toh(toc[i])); 2988f8cb840SMaxim Sobolev if (chit != NULL) { 2998f8cb840SMaxim Sobolev fprintf(stderr, " (backref'ed to #%d)", 3008f8cb840SMaxim Sobolev chit->blkno); 3018f8cb840SMaxim Sobolev } 3028f8cb840SMaxim Sobolev fprintf(stderr, "\n"); 3038f8cb840SMaxim Sobolev 3048f8cb840SMaxim Sobolev } 3058f8cb840SMaxim Sobolev } 3067f4caa8cSMaxim Sobolev close(fdr); 3077f4caa8cSMaxim Sobolev 308*62ee4b69SMaxim Sobolev if (verbose != 0 || summary.en != 0) 309*62ee4b69SMaxim Sobolev fprintf(summary.f, "compressed data to %ju bytes, saved %lld " 3108f8cb840SMaxim Sobolev "bytes, %.2f%% decrease.\n", offset, 3118f8cb840SMaxim Sobolev (long long)(sb.st_size - offset), 3128f8cb840SMaxim Sobolev 100.0 * (long long)(sb.st_size - offset) / 3138f8cb840SMaxim Sobolev (float)sb.st_size); 3147f4caa8cSMaxim Sobolev 3157f4caa8cSMaxim Sobolev /* Convert to big endian */ 3167f4caa8cSMaxim Sobolev hdr.blksz = htonl(hdr.blksz); 3177f4caa8cSMaxim Sobolev hdr.nblocks = htonl(hdr.nblocks); 3187f4caa8cSMaxim Sobolev /* Write headers into pre-allocated space */ 3197f4caa8cSMaxim Sobolev lseek(fdw, 0, SEEK_SET); 3207f4caa8cSMaxim Sobolev if (writev(fdw, iov, 2) < 0) { 321d72d8f53SPawel Jakub Dawidek err(1, "writev(%s)", oname); 3227f4caa8cSMaxim Sobolev /* Not reached */ 3237f4caa8cSMaxim Sobolev } 3247f4caa8cSMaxim Sobolev cleanfile = NULL; 3257f4caa8cSMaxim Sobolev close(fdw); 3267f4caa8cSMaxim Sobolev 3277f4caa8cSMaxim Sobolev exit(0); 3287f4caa8cSMaxim Sobolev } 3297f4caa8cSMaxim Sobolev 3307f4caa8cSMaxim Sobolev static char * 3310b99ac63SMaxim Sobolev readblock(int fd, char *ibuf, u_int32_t clstsize) 3320b99ac63SMaxim Sobolev { 3337f4caa8cSMaxim Sobolev int numread; 3347f4caa8cSMaxim Sobolev 3357f4caa8cSMaxim Sobolev bzero(ibuf, clstsize); 3367f4caa8cSMaxim Sobolev numread = read(fd, ibuf, clstsize); 3377f4caa8cSMaxim Sobolev if (numread < 0) { 3387f4caa8cSMaxim Sobolev err(1, "read() failed"); 3397f4caa8cSMaxim Sobolev /* Not reached */ 3407f4caa8cSMaxim Sobolev } 3417f4caa8cSMaxim Sobolev if (numread == 0) { 3427f4caa8cSMaxim Sobolev return NULL; 3437f4caa8cSMaxim Sobolev } 3447f4caa8cSMaxim Sobolev return ibuf; 3457f4caa8cSMaxim Sobolev } 3467f4caa8cSMaxim Sobolev 3477f4caa8cSMaxim Sobolev static void 3480b99ac63SMaxim Sobolev usage(void) 3490b99ac63SMaxim Sobolev { 3507f4caa8cSMaxim Sobolev 351d83e0778SMaxim Sobolev fprintf(stderr, "usage: mkuzip [-vZdLS] [-o outfile] [-s cluster_size] " 3528f8cb840SMaxim Sobolev "infile\n"); 3537f4caa8cSMaxim Sobolev exit(1); 3547f4caa8cSMaxim Sobolev } 3557f4caa8cSMaxim Sobolev 3568f8cb840SMaxim Sobolev void * 3578f8cb840SMaxim Sobolev mkuz_safe_malloc(size_t size) 3580b99ac63SMaxim Sobolev { 3597f4caa8cSMaxim Sobolev void *retval; 3607f4caa8cSMaxim Sobolev 3617f4caa8cSMaxim Sobolev retval = malloc(size); 3627f4caa8cSMaxim Sobolev if (retval == NULL) { 3637f4caa8cSMaxim Sobolev err(1, "can't allocate memory"); 3647f4caa8cSMaxim Sobolev /* Not reached */ 3657f4caa8cSMaxim Sobolev } 3667f4caa8cSMaxim Sobolev return retval; 3677f4caa8cSMaxim Sobolev } 3687f4caa8cSMaxim Sobolev 3697f4caa8cSMaxim Sobolev static void 3700b99ac63SMaxim Sobolev cleanup(void) 3710b99ac63SMaxim Sobolev { 3727f4caa8cSMaxim Sobolev 3737f4caa8cSMaxim Sobolev if (cleanfile != NULL) 3747f4caa8cSMaxim Sobolev unlink(cleanfile); 3757f4caa8cSMaxim Sobolev } 3768f8cb840SMaxim Sobolev 3778f8cb840SMaxim Sobolev static int 3788f8cb840SMaxim Sobolev memvcmp(const void *memory, unsigned char val, size_t size) 3798f8cb840SMaxim Sobolev { 3808f8cb840SMaxim Sobolev const u_char *mm; 3818f8cb840SMaxim Sobolev 3828f8cb840SMaxim Sobolev mm = (const u_char *)memory; 3838f8cb840SMaxim Sobolev return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0; 3848f8cb840SMaxim Sobolev } 385