1*986fd29aSsetje /* 2*986fd29aSsetje * CDDL HEADER START 3*986fd29aSsetje * 4*986fd29aSsetje * The contents of this file are subject to the terms of the 5*986fd29aSsetje * Common Development and Distribution License (the "License"). 6*986fd29aSsetje * You may not use this file except in compliance with the License. 7*986fd29aSsetje * 8*986fd29aSsetje * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*986fd29aSsetje * or http://www.opensolaris.org/os/licensing. 10*986fd29aSsetje * See the License for the specific language governing permissions 11*986fd29aSsetje * and limitations under the License. 12*986fd29aSsetje * 13*986fd29aSsetje * When distributing Covered Code, include this CDDL HEADER in each 14*986fd29aSsetje * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*986fd29aSsetje * If applicable, add the following below this CDDL HEADER, with the 16*986fd29aSsetje * fields enclosed by brackets "[]" replaced with your own identifying 17*986fd29aSsetje * information: Portions Copyright [yyyy] [name of copyright owner] 18*986fd29aSsetje * 19*986fd29aSsetje * CDDL HEADER END 20*986fd29aSsetje */ 21*986fd29aSsetje /* 22*986fd29aSsetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*986fd29aSsetje * Use is subject to license terms. 24*986fd29aSsetje */ 25*986fd29aSsetje 26*986fd29aSsetje #pragma ident "%Z%%M% %I% %E% SMI" 27*986fd29aSsetje 28*986fd29aSsetje /* 29*986fd29aSsetje * fiocompress - a utility to compress files with a filesystem. 30*986fd29aSsetje * Used to build compressed boot archives to reduce memory 31*986fd29aSsetje * requirements for booting. 32*986fd29aSsetje */ 33*986fd29aSsetje 34*986fd29aSsetje #include <stdio.h> 35*986fd29aSsetje #include <errno.h> 36*986fd29aSsetje #include <stdlib.h> 37*986fd29aSsetje #include <fcntl.h> 38*986fd29aSsetje #include <sys/types.h> 39*986fd29aSsetje #include <sys/stat.h> 40*986fd29aSsetje #include <sys/mman.h> 41*986fd29aSsetje #include <unistd.h> 42*986fd29aSsetje #include <utility.h> 43*986fd29aSsetje #include <zlib.h> 44*986fd29aSsetje 45*986fd29aSsetje #include <sys/filio.h> 46*986fd29aSsetje #include <sys/fs/decomp.h> 47*986fd29aSsetje 48*986fd29aSsetje #include "message.h" 49*986fd29aSsetje 50*986fd29aSsetje static void setup_infile(char *); 51*986fd29aSsetje static void setup_outfile(char *); 52*986fd29aSsetje static void do_comp(size_t); 53*986fd29aSsetje static void do_decomp(void); 54*986fd29aSsetje 55*986fd29aSsetje static caddr_t srcaddr; 56*986fd29aSsetje static size_t srclen; 57*986fd29aSsetje 58*986fd29aSsetje static int dstfd; 59*986fd29aSsetje 60*986fd29aSsetje static char *srcfile; 61*986fd29aSsetje static char *dstfile; 62*986fd29aSsetje 63*986fd29aSsetje 64*986fd29aSsetje int 65*986fd29aSsetje main(int argc, char **argv) 66*986fd29aSsetje { 67*986fd29aSsetje int compress = 0; 68*986fd29aSsetje int decompress = 0; 69*986fd29aSsetje int doioc = 0; 70*986fd29aSsetje size_t blksize = 8192; 71*986fd29aSsetje char c; 72*986fd29aSsetje 73*986fd29aSsetje while ((c = getopt(argc, argv, "mcdb:")) != -1) { 74*986fd29aSsetje switch (c) { 75*986fd29aSsetje case 'm': 76*986fd29aSsetje doioc++; 77*986fd29aSsetje break; 78*986fd29aSsetje case 'c': 79*986fd29aSsetje if (decompress) { 80*986fd29aSsetje (void) fprintf(stderr, OPT_DC_EXCL); 81*986fd29aSsetje exit(-1); 82*986fd29aSsetje } 83*986fd29aSsetje compress = 1; 84*986fd29aSsetje break; 85*986fd29aSsetje case 'd': 86*986fd29aSsetje if (compress) { 87*986fd29aSsetje (void) fprintf(stderr, OPT_DC_EXCL); 88*986fd29aSsetje exit(-1); 89*986fd29aSsetje } 90*986fd29aSsetje decompress = 1; 91*986fd29aSsetje break; 92*986fd29aSsetje case 'b': 93*986fd29aSsetje blksize = atoi(optarg); 94*986fd29aSsetje if (blksize == 0 || (blksize & (blksize-1))) { 95*986fd29aSsetje (void) fprintf(stderr, INVALID_BLKSZ); 96*986fd29aSsetje exit(-1); 97*986fd29aSsetje } 98*986fd29aSsetje break; 99*986fd29aSsetje case '?': 100*986fd29aSsetje (void) fprintf(stderr, UNKNOWN_OPTION, optopt); 101*986fd29aSsetje exit(-1); 102*986fd29aSsetje } 103*986fd29aSsetje } 104*986fd29aSsetje if (argc - optind != 2) { 105*986fd29aSsetje (void) fprintf(stderr, MISS_FILES); 106*986fd29aSsetje exit(-1); 107*986fd29aSsetje } 108*986fd29aSsetje 109*986fd29aSsetje setup_infile(argv[optind]); 110*986fd29aSsetje setup_outfile(argv[optind + 1]); 111*986fd29aSsetje 112*986fd29aSsetje if (decompress) 113*986fd29aSsetje do_decomp(); 114*986fd29aSsetje else { 115*986fd29aSsetje do_comp(blksize); 116*986fd29aSsetje if (doioc) { 117*986fd29aSsetje if (ioctl(dstfd, _FIO_COMPRESSED, 0) == -1) { 118*986fd29aSsetje (void) fprintf(stderr, FIO_COMP_FAIL, 119*986fd29aSsetje dstfile, strerror(errno)); 120*986fd29aSsetje exit(-1); 121*986fd29aSsetje } 122*986fd29aSsetje } 123*986fd29aSsetje } 124*986fd29aSsetje return (0); 125*986fd29aSsetje } 126*986fd29aSsetje 127*986fd29aSsetje static void 128*986fd29aSsetje setup_infile(char *file) 129*986fd29aSsetje { 130*986fd29aSsetje int fd; 131*986fd29aSsetje void *addr; 132*986fd29aSsetje struct stat stbuf; 133*986fd29aSsetje 134*986fd29aSsetje srcfile = file; 135*986fd29aSsetje 136*986fd29aSsetje fd = open(srcfile, O_RDONLY, 0); 137*986fd29aSsetje if (fd == -1) { 138*986fd29aSsetje (void) fprintf(stderr, CANT_OPEN, 139*986fd29aSsetje srcfile, strerror(errno)); 140*986fd29aSsetje exit(-1); 141*986fd29aSsetje } 142*986fd29aSsetje 143*986fd29aSsetje if (fstat(fd, &stbuf) == -1) { 144*986fd29aSsetje (void) fprintf(stderr, STAT_FAIL, 145*986fd29aSsetje srcfile, strerror(errno)); 146*986fd29aSsetje exit(-1); 147*986fd29aSsetje } 148*986fd29aSsetje srclen = stbuf.st_size; 149*986fd29aSsetje 150*986fd29aSsetje addr = mmap(0, srclen, PROT_READ, MAP_SHARED, fd, 0); 151*986fd29aSsetje if (addr == MAP_FAILED) { 152*986fd29aSsetje (void) fprintf(stderr, MMAP_FAIL, srcfile, strerror(errno)); 153*986fd29aSsetje exit(-1); 154*986fd29aSsetje } 155*986fd29aSsetje srcaddr = addr; 156*986fd29aSsetje } 157*986fd29aSsetje 158*986fd29aSsetje static void 159*986fd29aSsetje setup_outfile(char *file) 160*986fd29aSsetje { 161*986fd29aSsetje int fd; 162*986fd29aSsetje 163*986fd29aSsetje dstfile = file; 164*986fd29aSsetje 165*986fd29aSsetje fd = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, 166*986fd29aSsetje S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 167*986fd29aSsetje if (fd == -1) { 168*986fd29aSsetje (void) fprintf(stderr, OPEN_FAIL, dstfile, strerror(errno)); 169*986fd29aSsetje exit(-1); 170*986fd29aSsetje } 171*986fd29aSsetje dstfd = fd; 172*986fd29aSsetje } 173*986fd29aSsetje 174*986fd29aSsetje static void 175*986fd29aSsetje do_comp(size_t blksize) 176*986fd29aSsetje { 177*986fd29aSsetje struct comphdr *hdr; 178*986fd29aSsetje off_t offset; 179*986fd29aSsetje size_t blks, dstlen, hlen; 180*986fd29aSsetje void *dstbuf; 181*986fd29aSsetje int i; 182*986fd29aSsetje 183*986fd29aSsetje blks = ((srclen - 1) / blksize) + 1; 184*986fd29aSsetje hlen = offset = sizeof (struct comphdr) + blks * sizeof (uint64_t); 185*986fd29aSsetje hdr = malloc(hlen); 186*986fd29aSsetje if (hdr == NULL) { 187*986fd29aSsetje (void) fprintf(stderr, HDR_ALLOC, hlen); 188*986fd29aSsetje exit(-1); 189*986fd29aSsetje } 190*986fd29aSsetje 191*986fd29aSsetje hdr->ch_magic = CH_MAGIC; 192*986fd29aSsetje hdr->ch_version = CH_VERSION; 193*986fd29aSsetje hdr->ch_algorithm = CH_ALG_ZLIB; 194*986fd29aSsetje hdr->ch_fsize = srclen; 195*986fd29aSsetje hdr->ch_blksize = blksize; 196*986fd29aSsetje 197*986fd29aSsetje dstlen = ZMAXBUF(blksize); 198*986fd29aSsetje dstbuf = malloc(dstlen); 199*986fd29aSsetje if (dstbuf == NULL) { 200*986fd29aSsetje (void) fprintf(stderr, BUF_ALLOC, dstlen); 201*986fd29aSsetje exit(-1); 202*986fd29aSsetje } 203*986fd29aSsetje 204*986fd29aSsetje if (lseek(dstfd, offset, SEEK_SET) == (off_t)-1) { 205*986fd29aSsetje (void) fprintf(stderr, SEEK_ERR, 206*986fd29aSsetje offset, dstfile, strerror(errno)); 207*986fd29aSsetje exit(-1); 208*986fd29aSsetje } 209*986fd29aSsetje 210*986fd29aSsetje for (i = 0; i < blks; i++) { 211*986fd29aSsetje ulong_t slen, dlen; 212*986fd29aSsetje int ret; 213*986fd29aSsetje 214*986fd29aSsetje hdr->ch_blkmap[i] = offset; 215*986fd29aSsetje slen = MIN(srclen, blksize); 216*986fd29aSsetje dlen = dstlen; 217*986fd29aSsetje ret = compress2(dstbuf, &dlen, (Bytef *)srcaddr, slen, 9); 218*986fd29aSsetje if (ret != Z_OK) { 219*986fd29aSsetje (void) fprintf(stderr, COMP_ERR, srcfile, ret); 220*986fd29aSsetje exit(-1); 221*986fd29aSsetje } 222*986fd29aSsetje 223*986fd29aSsetje if (write(dstfd, dstbuf, dlen) != dlen) { 224*986fd29aSsetje (void) fprintf(stderr, WRITE_ERR, 225*986fd29aSsetje dlen, dstfile, strerror(errno)); 226*986fd29aSsetje exit(-1); 227*986fd29aSsetje } 228*986fd29aSsetje 229*986fd29aSsetje offset += dlen; 230*986fd29aSsetje srclen -= slen; 231*986fd29aSsetje srcaddr += slen; 232*986fd29aSsetje } 233*986fd29aSsetje 234*986fd29aSsetje if (lseek(dstfd, 0, SEEK_SET) == (off_t)-1) { 235*986fd29aSsetje (void) fprintf(stderr, SEEK_ERR, 236*986fd29aSsetje 0, dstfile, strerror(errno)); 237*986fd29aSsetje exit(-1); 238*986fd29aSsetje } 239*986fd29aSsetje 240*986fd29aSsetje if (write(dstfd, hdr, hlen) != hlen) { 241*986fd29aSsetje (void) fprintf(stderr, WRITE_ERR, 242*986fd29aSsetje hlen, dstfile, strerror(errno)); 243*986fd29aSsetje exit(-1); 244*986fd29aSsetje } 245*986fd29aSsetje } 246*986fd29aSsetje 247*986fd29aSsetje static void 248*986fd29aSsetje do_decomp() 249*986fd29aSsetje { 250*986fd29aSsetje struct comphdr *hdr; 251*986fd29aSsetje size_t blks, blksize; 252*986fd29aSsetje void *dstbuf; 253*986fd29aSsetje int i; 254*986fd29aSsetje ulong_t slen, dlen; 255*986fd29aSsetje int ret; 256*986fd29aSsetje 257*986fd29aSsetje hdr = (struct comphdr *)(void *)srcaddr; 258*986fd29aSsetje if (hdr->ch_magic != CH_MAGIC) { 259*986fd29aSsetje (void) fprintf(stderr, BAD_MAGIC, 260*986fd29aSsetje srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC); 261*986fd29aSsetje exit(-1); 262*986fd29aSsetje } 263*986fd29aSsetje if (hdr->ch_version != CH_VERSION) { 264*986fd29aSsetje (void) fprintf(stderr, BAD_VERS, 265*986fd29aSsetje srcfile, (uint64_t)hdr->ch_version, CH_VERSION); 266*986fd29aSsetje exit(-1); 267*986fd29aSsetje } 268*986fd29aSsetje if (hdr->ch_algorithm != CH_ALG_ZLIB) { 269*986fd29aSsetje (void) fprintf(stderr, BAD_ALG, 270*986fd29aSsetje srcfile, (uint64_t)hdr->ch_algorithm, CH_ALG_ZLIB); 271*986fd29aSsetje exit(-1); 272*986fd29aSsetje } 273*986fd29aSsetje 274*986fd29aSsetje blksize = hdr->ch_blksize; 275*986fd29aSsetje dstbuf = malloc(blksize); 276*986fd29aSsetje if (dstbuf == NULL) { 277*986fd29aSsetje (void) fprintf(stderr, HDR_ALLOC, blksize); 278*986fd29aSsetje exit(-1); 279*986fd29aSsetje } 280*986fd29aSsetje 281*986fd29aSsetje blks = (hdr->ch_fsize - 1) / blksize; 282*986fd29aSsetje srcaddr += hdr->ch_blkmap[0]; 283*986fd29aSsetje for (i = 0; i < blks; i++) { 284*986fd29aSsetje dlen = blksize; 285*986fd29aSsetje slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i]; 286*986fd29aSsetje ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen); 287*986fd29aSsetje if (ret != Z_OK) { 288*986fd29aSsetje (void) fprintf(stderr, DECOMP_ERR, srcfile, ret); 289*986fd29aSsetje exit(-1); 290*986fd29aSsetje } 291*986fd29aSsetje 292*986fd29aSsetje if (dlen != blksize) { 293*986fd29aSsetje (void) fprintf(stderr, CORRUPT, srcfile); 294*986fd29aSsetje exit(-1); 295*986fd29aSsetje } 296*986fd29aSsetje if (write(dstfd, dstbuf, dlen) != dlen) { 297*986fd29aSsetje (void) fprintf(stderr, WRITE_ERR, 298*986fd29aSsetje dlen, dstfile, strerror(errno)); 299*986fd29aSsetje exit(-1); 300*986fd29aSsetje } 301*986fd29aSsetje srcaddr += slen; 302*986fd29aSsetje } 303*986fd29aSsetje 304*986fd29aSsetje dlen = blksize; 305*986fd29aSsetje slen = hdr->ch_fsize - hdr->ch_blkmap[i]; 306*986fd29aSsetje if ((ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen)) != Z_OK) { 307*986fd29aSsetje (void) fprintf(stderr, DECOMP_ERR, dstfile, ret); 308*986fd29aSsetje exit(-1); 309*986fd29aSsetje } 310*986fd29aSsetje 311*986fd29aSsetje if (write(dstfd, dstbuf, dlen) != dlen) { 312*986fd29aSsetje (void) fprintf(stderr, WRITE_ERR, 313*986fd29aSsetje dlen, dstfile, strerror(errno)); 314*986fd29aSsetje exit(-1); 315*986fd29aSsetje } 316*986fd29aSsetje } 317