# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. PROG= fiocompress SBINLINKS= $(PROG) OBJS= fiocompress.o SRCS = $(OBJS:.o=.c) include ../Makefile.com .KEEP_STATE: LDLIBS += -lz CFLAGS += -I../../../uts/common SMOFF += leaks all: $(PROG) $(PROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) install: all $(ROOTSBINPROG) .WAIT $(ROOTUSRSBINLINKS) clean: -$(RM) $(OBJS) _msg: include ../Makefile.targ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * fiocompress - a utility to compress files with a filesystem. * Used to build compressed boot archives to reduce memory * requirements for booting. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "message.h" static void setup_infile(char *); static void setup_outfile(char *); static void do_comp(size_t); static void do_decomp(void); static caddr_t srcaddr; static size_t srclen; static int dstfd; static char *srcfile; static char *dstfile; int main(int argc, char **argv) { int compress = 0; int decompress = 0; int doioc = 0; size_t blksize = 8192; int c; while ((c = getopt(argc, argv, "mcdb:")) != -1) { switch (c) { case 'm': doioc++; break; case 'c': if (decompress) { (void) fprintf(stderr, OPT_DC_EXCL); exit(-1); } compress = 1; break; case 'd': if (compress) { (void) fprintf(stderr, OPT_DC_EXCL); exit(-1); } decompress = 1; break; case 'b': blksize = atoi(optarg); if (blksize == 0 || (blksize & (blksize-1))) { (void) fprintf(stderr, INVALID_BLKSZ); exit(-1); } break; case '?': (void) fprintf(stderr, UNKNOWN_OPTION, optopt); exit(-1); } } if (argc - optind != 2) { (void) fprintf(stderr, MISS_FILES); exit(-1); } setup_infile(argv[optind]); setup_outfile(argv[optind + 1]); if (decompress) do_decomp(); else { do_comp(blksize); if (doioc) { if (ioctl(dstfd, _FIO_COMPRESSED, 0) == -1) { (void) fprintf(stderr, FIO_COMP_FAIL, dstfile, strerror(errno)); exit(-1); } } } return (0); } static void setup_infile(char *file) { int fd; void *addr; struct stat stbuf; srcfile = file; fd = open(srcfile, O_RDONLY, 0); if (fd == -1) { (void) fprintf(stderr, CANT_OPEN, srcfile, strerror(errno)); exit(-1); } if (fstat(fd, &stbuf) == -1) { (void) fprintf(stderr, STAT_FAIL, srcfile, strerror(errno)); exit(-1); } srclen = stbuf.st_size; addr = mmap(0, srclen, PROT_READ, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { (void) fprintf(stderr, MMAP_FAIL, srcfile, strerror(errno)); exit(-1); } srcaddr = addr; } static void setup_outfile(char *file) { int fd; dstfile = file; fd = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd == -1) { (void) fprintf(stderr, OPEN_FAIL, dstfile, strerror(errno)); exit(-1); } dstfd = fd; } static void do_comp(size_t blksize) { struct comphdr *hdr; off_t offset; size_t blks, dstlen, hlen; void *dstbuf; int i; blks = ((srclen - 1) / blksize) + 1; hlen = offset = sizeof (struct comphdr) + blks * sizeof (uint64_t); hdr = malloc(hlen); if (hdr == NULL) { (void) fprintf(stderr, HDR_ALLOC, hlen); exit(-1); } hdr->ch_magic = CH_MAGIC_ZLIB; hdr->ch_version = CH_VERSION; hdr->ch_algorithm = CH_ALG_ZLIB; hdr->ch_fsize = srclen; hdr->ch_blksize = blksize; dstlen = ZMAXBUF(blksize); dstbuf = malloc(dstlen); if (dstbuf == NULL) { (void) fprintf(stderr, BUF_ALLOC, dstlen); exit(-1); } if (lseek(dstfd, offset, SEEK_SET) == (off_t)-1) { (void) fprintf(stderr, SEEK_ERR, offset, dstfile, strerror(errno)); exit(-1); } for (i = 0; i < blks; i++) { ulong_t slen, dlen; int ret; hdr->ch_blkmap[i] = offset; slen = MIN(srclen, blksize); dlen = dstlen; ret = compress2(dstbuf, &dlen, (Bytef *)srcaddr, slen, 9); if (ret != Z_OK) { (void) fprintf(stderr, COMP_ERR, srcfile, ret); exit(-1); } if (write(dstfd, dstbuf, dlen) != dlen) { (void) fprintf(stderr, WRITE_ERR, dlen, dstfile, strerror(errno)); exit(-1); } offset += dlen; srclen -= slen; srcaddr += slen; } if (lseek(dstfd, 0, SEEK_SET) == (off_t)-1) { (void) fprintf(stderr, SEEK_ERR, 0, dstfile, strerror(errno)); exit(-1); } if (write(dstfd, hdr, hlen) != hlen) { (void) fprintf(stderr, WRITE_ERR, hlen, dstfile, strerror(errno)); exit(-1); } } static void do_decomp() { struct comphdr *hdr; size_t blks, blksize; void *dstbuf; int i; ulong_t slen, dlen; int ret; hdr = (struct comphdr *)(void *)srcaddr; if (hdr->ch_magic != CH_MAGIC_ZLIB) { (void) fprintf(stderr, BAD_MAGIC, srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC_ZLIB); exit(-1); } if (hdr->ch_version != CH_VERSION) { (void) fprintf(stderr, BAD_VERS, srcfile, (uint64_t)hdr->ch_version, CH_VERSION); exit(-1); } if (hdr->ch_algorithm != CH_ALG_ZLIB) { (void) fprintf(stderr, BAD_ALG, srcfile, (uint64_t)hdr->ch_algorithm, CH_ALG_ZLIB); exit(-1); } blksize = hdr->ch_blksize; dstbuf = malloc(blksize); if (dstbuf == NULL) { (void) fprintf(stderr, HDR_ALLOC, blksize); exit(-1); } blks = (hdr->ch_fsize - 1) / blksize; srcaddr += hdr->ch_blkmap[0]; for (i = 0; i < blks; i++) { dlen = blksize; slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i]; ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen); if (ret != Z_OK) { (void) fprintf(stderr, DECOMP_ERR, srcfile, ret); exit(-1); } if (dlen != blksize) { (void) fprintf(stderr, CORRUPT, srcfile); exit(-1); } if (write(dstfd, dstbuf, dlen) != dlen) { (void) fprintf(stderr, WRITE_ERR, dlen, dstfile, strerror(errno)); exit(-1); } srcaddr += slen; } dlen = blksize; slen = hdr->ch_fsize - hdr->ch_blkmap[i]; if ((ret = uncompress(dstbuf, &dlen, (Bytef *)srcaddr, slen)) != Z_OK) { (void) fprintf(stderr, DECOMP_ERR, dstfile, ret); exit(-1); } if (write(dstfd, dstbuf, dlen) != dlen) { (void) fprintf(stderr, WRITE_ERR, dlen, dstfile, strerror(errno)); exit(-1); } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MESSAGE_H #define _MESSAGE_H #ifdef __cplusplus extern "C" { #endif #include #define OPT_DC_EXCL gettext("fiocompress: -c and -d are exclusive\n") #define INVALID_BLKSZ gettext("fiocompress: invalid block size\n") #define UNKNOWN_OPTION gettext("fiocompress: unknown option -%c\n") #define MISS_FILES gettext("fiocompress: input and output files\ must be specified\n") #define FIO_COMP_FAIL gettext("fiocompress: FIO_COMPRESSED on %s failed\ - %s\n") #define CANT_OPEN gettext("fiocompress: cannot open %s - %s\n") #define STAT_FAIL gettext("fiocompress: stat of %s failed - %s\n") #define MMAP_FAIL gettext("fiocompress: mmapping on %s failed - %s\n") #define OPEN_FAIL gettext("fiocompress: open of %s failed - %s\n") #define HDR_ALLOC gettext("fiocompress: failed to allocate %d bytes\ for header\n") #define BUF_ALLOC gettext("fiocompress: failed to allocate %d bytes\ for buffer\n") #define SEEK_ERR gettext("fiocompress: seek to %ld on %s failed - %s\n") #define COMP_ERR gettext("fiocompress: %s - compression error %d\n") #define WRITE_ERR gettext("fiocompress: write of %ld bytes on %s failed\ - %s\n") #define BAD_MAGIC gettext("fiocompress: %s - bad magic (0x%llx/0x%x)\n") #define BAD_VERS gettext("fiocompress: %s - bad version (0x%llx/0x%x)\n") #define BAD_ALG gettext("fiocompress: %s - bad algorithm\ (0x%llx/0x%x)\n") #define DECOMP_ERR gettext("fiocompress: %s - decompression error %d\n") #define CORRUPT gettext("fiocompress: %s - corrupt file\n") #ifdef __cplusplus } #endif #endif /* _MESSAGE_H */