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