15648Ssetje /*
25648Ssetje * CDDL HEADER START
35648Ssetje *
45648Ssetje * The contents of this file are subject to the terms of the
55648Ssetje * Common Development and Distribution License (the "License").
65648Ssetje * You may not use this file except in compliance with the License.
75648Ssetje *
85648Ssetje * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95648Ssetje * or http://www.opensolaris.org/os/licensing.
105648Ssetje * See the License for the specific language governing permissions
115648Ssetje * and limitations under the License.
125648Ssetje *
135648Ssetje * When distributing Covered Code, include this CDDL HEADER in each
145648Ssetje * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155648Ssetje * If applicable, add the following below this CDDL HEADER, with the
165648Ssetje * fields enclosed by brackets "[]" replaced with your own identifying
175648Ssetje * information: Portions Copyright [yyyy] [name of copyright owner]
185648Ssetje *
195648Ssetje * CDDL HEADER END
205648Ssetje */
215648Ssetje /*
22*7858SKrishnendu.Sadhukhan@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
235648Ssetje * Use is subject to license terms.
245648Ssetje */
255648Ssetje
265648Ssetje /*
275648Ssetje * fiocompress - a utility to compress files with a filesystem.
285648Ssetje * Used to build compressed boot archives to reduce memory
295648Ssetje * requirements for booting.
305648Ssetje */
315648Ssetje
325648Ssetje #include <stdio.h>
335648Ssetje #include <errno.h>
345648Ssetje #include <stdlib.h>
355648Ssetje #include <fcntl.h>
365648Ssetje #include <sys/types.h>
375648Ssetje #include <sys/stat.h>
385648Ssetje #include <sys/mman.h>
395648Ssetje #include <unistd.h>
405648Ssetje #include <utility.h>
415648Ssetje #include <zlib.h>
425648Ssetje
435648Ssetje #include <sys/filio.h>
445648Ssetje #include <sys/fs/decomp.h>
455648Ssetje
465648Ssetje #include "message.h"
475648Ssetje
485648Ssetje static void setup_infile(char *);
495648Ssetje static void setup_outfile(char *);
505648Ssetje static void do_comp(size_t);
515648Ssetje static void do_decomp(void);
525648Ssetje
535648Ssetje static caddr_t srcaddr;
545648Ssetje static size_t srclen;
555648Ssetje
565648Ssetje static int dstfd;
575648Ssetje
585648Ssetje static char *srcfile;
595648Ssetje static char *dstfile;
605648Ssetje
615648Ssetje
625648Ssetje int
main(int argc,char ** argv)635648Ssetje main(int argc, char **argv)
645648Ssetje {
655648Ssetje int compress = 0;
665648Ssetje int decompress = 0;
675648Ssetje int doioc = 0;
685648Ssetje size_t blksize = 8192;
695648Ssetje char c;
705648Ssetje
715648Ssetje while ((c = getopt(argc, argv, "mcdb:")) != -1) {
725648Ssetje switch (c) {
735648Ssetje case 'm':
745648Ssetje doioc++;
755648Ssetje break;
765648Ssetje case 'c':
775648Ssetje if (decompress) {
785648Ssetje (void) fprintf(stderr, OPT_DC_EXCL);
795648Ssetje exit(-1);
805648Ssetje }
815648Ssetje compress = 1;
825648Ssetje break;
835648Ssetje case 'd':
845648Ssetje if (compress) {
855648Ssetje (void) fprintf(stderr, OPT_DC_EXCL);
865648Ssetje exit(-1);
875648Ssetje }
885648Ssetje decompress = 1;
895648Ssetje break;
905648Ssetje case 'b':
915648Ssetje blksize = atoi(optarg);
925648Ssetje if (blksize == 0 || (blksize & (blksize-1))) {
935648Ssetje (void) fprintf(stderr, INVALID_BLKSZ);
945648Ssetje exit(-1);
955648Ssetje }
965648Ssetje break;
975648Ssetje case '?':
985648Ssetje (void) fprintf(stderr, UNKNOWN_OPTION, optopt);
995648Ssetje exit(-1);
1005648Ssetje }
1015648Ssetje }
1025648Ssetje if (argc - optind != 2) {
1035648Ssetje (void) fprintf(stderr, MISS_FILES);
1045648Ssetje exit(-1);
1055648Ssetje }
1065648Ssetje
1075648Ssetje setup_infile(argv[optind]);
1085648Ssetje setup_outfile(argv[optind + 1]);
1095648Ssetje
1105648Ssetje if (decompress)
1115648Ssetje do_decomp();
1125648Ssetje else {
1135648Ssetje do_comp(blksize);
1145648Ssetje if (doioc) {
1155648Ssetje if (ioctl(dstfd, _FIO_COMPRESSED, 0) == -1) {
1165648Ssetje (void) fprintf(stderr, FIO_COMP_FAIL,
1175648Ssetje dstfile, strerror(errno));
1185648Ssetje exit(-1);
1195648Ssetje }
1205648Ssetje }
1215648Ssetje }
1225648Ssetje return (0);
1235648Ssetje }
1245648Ssetje
1255648Ssetje static void
setup_infile(char * file)1265648Ssetje setup_infile(char *file)
1275648Ssetje {
1285648Ssetje int fd;
1295648Ssetje void *addr;
1305648Ssetje struct stat stbuf;
1315648Ssetje
1325648Ssetje srcfile = file;
1335648Ssetje
1345648Ssetje fd = open(srcfile, O_RDONLY, 0);
1355648Ssetje if (fd == -1) {
1365648Ssetje (void) fprintf(stderr, CANT_OPEN,
1375648Ssetje srcfile, strerror(errno));
1385648Ssetje exit(-1);
1395648Ssetje }
1405648Ssetje
1415648Ssetje if (fstat(fd, &stbuf) == -1) {
1425648Ssetje (void) fprintf(stderr, STAT_FAIL,
1435648Ssetje srcfile, strerror(errno));
1445648Ssetje exit(-1);
1455648Ssetje }
1465648Ssetje srclen = stbuf.st_size;
1475648Ssetje
1485648Ssetje addr = mmap(0, srclen, PROT_READ, MAP_SHARED, fd, 0);
1495648Ssetje if (addr == MAP_FAILED) {
1505648Ssetje (void) fprintf(stderr, MMAP_FAIL, srcfile, strerror(errno));
1515648Ssetje exit(-1);
1525648Ssetje }
1535648Ssetje srcaddr = addr;
1545648Ssetje }
1555648Ssetje
1565648Ssetje static void
setup_outfile(char * file)1575648Ssetje setup_outfile(char *file)
1585648Ssetje {
1595648Ssetje int fd;
1605648Ssetje
1615648Ssetje dstfile = file;
1625648Ssetje
1635648Ssetje fd = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC,
1645648Ssetje S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1655648Ssetje if (fd == -1) {
1665648Ssetje (void) fprintf(stderr, OPEN_FAIL, dstfile, strerror(errno));
1675648Ssetje exit(-1);
1685648Ssetje }
1695648Ssetje dstfd = fd;
1705648Ssetje }
1715648Ssetje
1725648Ssetje static void
do_comp(size_t blksize)1735648Ssetje do_comp(size_t blksize)
1745648Ssetje {
1755648Ssetje struct comphdr *hdr;
1765648Ssetje off_t offset;
1775648Ssetje size_t blks, dstlen, hlen;
1785648Ssetje void *dstbuf;
1795648Ssetje int i;
1805648Ssetje
1815648Ssetje blks = ((srclen - 1) / blksize) + 1;
1825648Ssetje hlen = offset = sizeof (struct comphdr) + blks * sizeof (uint64_t);
1835648Ssetje hdr = malloc(hlen);
1845648Ssetje if (hdr == NULL) {
1855648Ssetje (void) fprintf(stderr, HDR_ALLOC, hlen);
1865648Ssetje exit(-1);
1875648Ssetje }
1885648Ssetje
189*7858SKrishnendu.Sadhukhan@Sun.COM hdr->ch_magic = CH_MAGIC_ZLIB;
1905648Ssetje hdr->ch_version = CH_VERSION;
1915648Ssetje hdr->ch_algorithm = CH_ALG_ZLIB;
1925648Ssetje hdr->ch_fsize = srclen;
1935648Ssetje hdr->ch_blksize = blksize;
1945648Ssetje
1955648Ssetje dstlen = ZMAXBUF(blksize);
1965648Ssetje dstbuf = malloc(dstlen);
1975648Ssetje if (dstbuf == NULL) {
1985648Ssetje (void) fprintf(stderr, BUF_ALLOC, dstlen);
1995648Ssetje exit(-1);
2005648Ssetje }
2015648Ssetje
2025648Ssetje if (lseek(dstfd, offset, SEEK_SET) == (off_t)-1) {
2035648Ssetje (void) fprintf(stderr, SEEK_ERR,
2045648Ssetje offset, dstfile, strerror(errno));
2055648Ssetje exit(-1);
2065648Ssetje }
2075648Ssetje
2085648Ssetje for (i = 0; i < blks; i++) {
2095648Ssetje ulong_t slen, dlen;
2105648Ssetje int ret;
2115648Ssetje
2125648Ssetje hdr->ch_blkmap[i] = offset;
2135648Ssetje slen = MIN(srclen, blksize);
2145648Ssetje dlen = dstlen;
2155648Ssetje ret = compress2(dstbuf, &dlen, (Bytef *)srcaddr, slen, 9);
2165648Ssetje if (ret != Z_OK) {
2175648Ssetje (void) fprintf(stderr, COMP_ERR, srcfile, ret);
2185648Ssetje exit(-1);
2195648Ssetje }
2205648Ssetje
2215648Ssetje if (write(dstfd, dstbuf, dlen) != dlen) {
2225648Ssetje (void) fprintf(stderr, WRITE_ERR,
2235648Ssetje dlen, dstfile, strerror(errno));
2245648Ssetje exit(-1);
2255648Ssetje }
2265648Ssetje
2275648Ssetje offset += dlen;
2285648Ssetje srclen -= slen;
2295648Ssetje srcaddr += slen;
2305648Ssetje }
2315648Ssetje
2325648Ssetje if (lseek(dstfd, 0, SEEK_SET) == (off_t)-1) {
2335648Ssetje (void) fprintf(stderr, SEEK_ERR,
2345648Ssetje 0, dstfile, strerror(errno));
2355648Ssetje exit(-1);
2365648Ssetje }
2375648Ssetje
2385648Ssetje if (write(dstfd, hdr, hlen) != hlen) {
2395648Ssetje (void) fprintf(stderr, WRITE_ERR,
2405648Ssetje hlen, dstfile, strerror(errno));
2415648Ssetje exit(-1);
2425648Ssetje }
2435648Ssetje }
2445648Ssetje
2455648Ssetje static void
do_decomp()2465648Ssetje do_decomp()
2475648Ssetje {
2485648Ssetje struct comphdr *hdr;
2495648Ssetje size_t blks, blksize;
2505648Ssetje void *dstbuf;
2515648Ssetje int i;
2525648Ssetje ulong_t slen, dlen;
2535648Ssetje int ret;
2545648Ssetje
2555648Ssetje hdr = (struct comphdr *)(void *)srcaddr;
256*7858SKrishnendu.Sadhukhan@Sun.COM if (hdr->ch_magic != CH_MAGIC_ZLIB) {
2575648Ssetje (void) fprintf(stderr, BAD_MAGIC,
258*7858SKrishnendu.Sadhukhan@Sun.COM srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC_ZLIB);
2595648Ssetje exit(-1);
2605648Ssetje }
2615648Ssetje if (hdr->ch_version != CH_VERSION) {
2625648Ssetje (void) fprintf(stderr, BAD_VERS,
2635648Ssetje srcfile, (uint64_t)hdr->ch_version, CH_VERSION);
2645648Ssetje exit(-1);
2655648Ssetje }
2665648Ssetje if (hdr->ch_algorithm != CH_ALG_ZLIB) {
2675648Ssetje (void) fprintf(stderr, BAD_ALG,
2685648Ssetje srcfile, (uint64_t)hdr->ch_algorithm, CH_ALG_ZLIB);
2695648Ssetje exit(-1);
2705648Ssetje }
2715648Ssetje
2725648Ssetje blksize = hdr->ch_blksize;
2735648Ssetje dstbuf = malloc(blksize);
2745648Ssetje if (dstbuf == NULL) {
2755648Ssetje (void) fprintf(stderr, HDR_ALLOC, blksize);
2765648Ssetje exit(-1);
2775648Ssetje }
2785648Ssetje
2795648Ssetje blks = (hdr->ch_fsize - 1) / blksize;
2805648Ssetje srcaddr += hdr->ch_blkmap[0];
2815648Ssetje for (i = 0; i < blks; i++) {
2825648Ssetje dlen = blksize;
2835648Ssetje slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i];
2845648Ssetje ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen);
2855648Ssetje if (ret != Z_OK) {
2865648Ssetje (void) fprintf(stderr, DECOMP_ERR, srcfile, ret);
2875648Ssetje exit(-1);
2885648Ssetje }
2895648Ssetje
2905648Ssetje if (dlen != blksize) {
2915648Ssetje (void) fprintf(stderr, CORRUPT, srcfile);
2925648Ssetje exit(-1);
2935648Ssetje }
2945648Ssetje if (write(dstfd, dstbuf, dlen) != dlen) {
2955648Ssetje (void) fprintf(stderr, WRITE_ERR,
2965648Ssetje dlen, dstfile, strerror(errno));
2975648Ssetje exit(-1);
2985648Ssetje }
2995648Ssetje srcaddr += slen;
3005648Ssetje }
3015648Ssetje
3025648Ssetje dlen = blksize;
3035648Ssetje slen = hdr->ch_fsize - hdr->ch_blkmap[i];
3045648Ssetje if ((ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen)) != Z_OK) {
3055648Ssetje (void) fprintf(stderr, DECOMP_ERR, dstfile, ret);
3065648Ssetje exit(-1);
3075648Ssetje }
3085648Ssetje
3095648Ssetje if (write(dstfd, dstbuf, dlen) != dlen) {
3105648Ssetje (void) fprintf(stderr, WRITE_ERR,
3115648Ssetje dlen, dstfile, strerror(errno));
3125648Ssetje exit(-1);
3135648Ssetje }
3145648Ssetje }
315