GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/compress/gzopen.c Lines: 222 254 87.4 %
Date: 2017-11-07 Branches: 95 136 69.9 %

Line Branch Exec Source
1
/*	$OpenBSD: gzopen.c,v 1.34 2016/09/03 12:29:30 tedu Exp $	*/
2
3
/*
4
 * Copyright (c) 1997 Michael Shalayeff
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 *
28
 */
29
/* this is partially derived from the zlib's gzio.c file, so the notice: */
30
/*
31
  zlib.h -- interface of the 'zlib' general purpose compression library
32
  version 1.0.4, Jul 24th, 1996.
33
34
  Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
35
36
  This software is provided 'as-is', without any express or implied
37
  warranty.  In no event will the authors be held liable for any damages
38
  arising from the use of this software.
39
40
  Permission is granted to anyone to use this software for any purpose,
41
  including commercial applications, and to alter it and redistribute it
42
  freely, subject to the following restrictions:
43
44
  1. The origin of this software must not be misrepresented; you must not
45
     claim that you wrote the original software. If you use this software
46
     in a product, an acknowledgment in the product documentation would be
47
     appreciated but is not required.
48
  2. Altered source versions must be plainly marked as such, and must not be
49
     misrepresented as being the original software.
50
  3. This notice may not be removed or altered from any source distribution.
51
52
  Jean-loup Gailly        Mark Adler
53
  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
54
55
56
  The data format used by the zlib library is described by RFCs (Request for
57
  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
58
  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
59
*/
60
61
#include <sys/stat.h>
62
#include <sys/uio.h>
63
#include <stdio.h>
64
#include <stdlib.h>
65
#include <string.h>
66
#include <errno.h>
67
#include <unistd.h>
68
#include <limits.h>
69
#include <zlib.h>
70
#include "compress.h"
71
72
/* gzip flag byte */
73
#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
74
#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
75
#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
76
#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
77
#define COMMENT      0x10 /* bit 4 set: file comment present */
78
#define RESERVED     0xE0 /* bits 5..7: reserved */
79
80
#define DEF_MEM_LEVEL 8
81
#define OS_CODE 0x03 /* unix */
82
83
typedef
84
struct gz_stream {
85
	int	z_fd;		/* .gz file */
86
	int	z_eof;		/* set if end of input file */
87
	z_stream z_stream;	/* libz stream */
88
	u_char	z_buf[Z_BUFSIZE]; /* i/o buffer */
89
	char	z_mode;		/* 'w' or 'r' */
90
	u_int32_t z_time;	/* timestamp (mtime) */
91
	u_int32_t z_crc;	/* crc32 of uncompressed data */
92
	u_int32_t z_hlen;	/* length of the gz header */
93
	u_int64_t z_total_in;	/* # bytes in */
94
	u_int64_t z_total_out;	/* # bytes out */
95
} gz_stream;
96
97
static const u_char gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
98
99
static u_int32_t get_int32(gz_stream *);
100
static int get_header(gz_stream *, char *, int);
101
static int get_byte(gz_stream *);
102
103
void *
104
gz_ropen(int fd, char *name, int gotmagic)
105
{
106
	gz_stream *s;
107
108
2552
	if (fd < 0)
109
		return NULL;
110
111
1276
	if ((s = calloc(1, sizeof(gz_stream))) == NULL)
112
		return NULL;
113
114
1276
	s->z_stream.zalloc = (alloc_func)0;
115
1276
	s->z_stream.zfree = (free_func)0;
116
1276
	s->z_stream.opaque = (voidpf)0;
117
1276
	s->z_stream.next_in = Z_NULL;
118
1276
	s->z_stream.next_out = Z_NULL;
119
1276
	s->z_stream.avail_in = s->z_stream.avail_out = 0;
120
1276
	s->z_fd = 0;
121
1276
	s->z_eof = 0;
122
1276
	s->z_time = 0;
123
1276
	s->z_hlen = 0;
124
1276
	s->z_total_in = 0;
125
1276
	s->z_total_out = 0;
126
1276
	s->z_crc = crc32(0L, Z_NULL, 0);
127
1276
	s->z_mode = 'r';
128
129
1276
	if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
130
		free (s);
131
		return NULL;
132
	}
133
1276
	s->z_stream.next_in = s->z_buf;
134
1276
	s->z_stream.avail_out = Z_BUFSIZE;
135
136
1276
	errno = 0;
137
1276
	s->z_fd = fd;
138
139
	/* read the .gz header */
140
1276
	if (get_header(s, name, gotmagic) != 0) {
141
		gz_close(s, NULL, NULL, NULL);
142
		s = NULL;
143
	}
144
145
1276
	return s;
146
1276
}
147
148
static int
149
get_byte(gz_stream *s)
150
{
151
32074
	if (s->z_eof)
152
		return EOF;
153
154
16037
	if (s->z_stream.avail_in == 0) {
155
1419
		errno = 0;
156
1419
		s->z_stream.avail_in = read(s->z_fd, s->z_buf, Z_BUFSIZE);
157
1419
		if ((int)s->z_stream.avail_in <= 0) {
158
143
			s->z_eof = 1;
159
143
			return EOF;
160
		}
161
1276
		s->z_stream.next_in = s->z_buf;
162
1276
	}
163
15894
	s->z_stream.avail_in--;
164
15894
	return *s->z_stream.next_in++;
165
16037
}
166
167
static u_int32_t
168
get_int32(gz_stream *s)
169
{
170
	u_int32_t x;
171
172
4378
	x  = ((u_int32_t)(get_byte(s) & 0xff));
173
2189
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<8;
174
2189
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<16;
175
2189
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<24;
176
2189
	return x;
177
}
178
179
static int
180
get_header(gz_stream *s, char *name, int gotmagic)
181
{
182
	int method; /* method byte */
183
	int flags;  /* flags byte */
184
	char *ep;
185
	uInt len;
186
	int c;
187
188
	/* Check the gzip magic header */
189
2882
	if (!gotmagic) {
190
418
		for (len = 0; len < 2; len++) {
191
187
			c = get_byte(s);
192
187
			if (c != gz_magic[len]) {
193
143
				errno = EFTYPE;
194
143
				return -1;
195
			}
196
		}
197
	}
198
199
1298
	method = get_byte(s);
200
1298
	flags = get_byte(s);
201

2596
	if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
202
		errno = EFTYPE;
203
		return -1;
204
	}
205
206
	/* Stash timestamp (mtime) */
207
1298
	s->z_time = get_int32(s);
208
209
	/* Discard xflags and OS code */
210
1298
	(void)get_byte(s);
211
1298
	(void)get_byte(s);
212
213
1298
	s->z_hlen += 10; /* magic, method, flags, time, xflags, OS code */
214
1298
	if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
215
		len  =  (uInt)get_byte(s);
216
		len += ((uInt)get_byte(s))<<8;
217
		s->z_hlen += 2;
218
		/* len is garbage if EOF but the loop below will quit anyway */
219
		while (len-- != 0 && get_byte(s) != EOF)
220
			s->z_hlen++;
221
	}
222
223
1298
	if ((flags & ORIG_NAME) != 0) { /* read/save the original file name */
224
90
		if ((ep = name) != NULL)
225
68
			ep += PATH_MAX - 1;
226
567
		while ((c = get_byte(s)) != EOF) {
227
567
			s->z_hlen++;
228
567
			if (c == '\0')
229
				break;
230
477
			if (name < ep)
231
389
				*name++ = c;
232
		}
233
90
		if (name != NULL)
234
68
			*name = '\0';
235
	}
236
237
1298
	if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
238
1335
		while ((c = get_byte(s)) != EOF) {
239
1335
			s->z_hlen++;
240
1335
			if (c == '\0')
241
				break;
242
		}
243
	}
244
245
1298
	if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
246
		(void)get_byte(s);
247
		(void)get_byte(s);
248
		s->z_hlen += 2;
249
	}
250
251
1298
	if (s->z_eof) {
252
		errno = EFTYPE;
253
		return -1;
254
	}
255
256
1298
	return 0;
257
1441
}
258
259
int
260
gz_read(void *cookie, char *buf, int len)
261
{
262
105450
	gz_stream *s = (gz_stream*)cookie;
263
	u_char *start = buf; /* starting point for crc computation */
264
	int error = Z_OK;
265
266
52725
	s->z_stream.next_out = buf;
267
52725
	s->z_stream.avail_out = len;
268
269

396994
	while (error == Z_OK && !s->z_eof && s->z_stream.avail_out != 0) {
270
271
63355
		if (s->z_stream.avail_in == 0) {
272
273
10754
			errno = 0;
274
10754
			s->z_stream.avail_in = read(s->z_fd, s->z_buf,
275
			    Z_BUFSIZE);
276
10754
			if ((int)s->z_stream.avail_in <= 0)
277
22
				s->z_eof = 1;
278
10754
			s->z_stream.next_in = s->z_buf;
279
10754
		}
280
281
63355
		error = inflate(&(s->z_stream), Z_NO_FLUSH);
282
283
63355
		if (error == Z_DATA_ERROR) {
284
			errno = EINVAL;
285
			goto bad;
286
		}
287
62805
		if (error == Z_BUF_ERROR) {
288
			errno = EIO;
289
			goto bad;
290
		}
291
62783
		if (error == Z_STREAM_END) {
292
			/* Check CRC and original size */
293
1452
			s->z_crc = crc32(s->z_crc, start,
294
726
			    (uInt)(s->z_stream.next_out - start));
295
726
			start = s->z_stream.next_out;
296
297
726
			if (get_int32(s) != s->z_crc) {
298
1133
				errno = EINVAL;
299
				goto bad;
300
			}
301
165
			if (get_int32(s) != (u_int32_t)s->z_stream.total_out) {
302
				errno = EIO;
303
				return -1;
304
			}
305
165
			s->z_hlen += 2 * sizeof(int32_t);
306
307
			/* Add byte counts from the finished stream. */
308
165
			s->z_total_in += s->z_stream.total_in;
309
165
			s->z_total_out += s->z_stream.total_out;
310
311
			/* Check for the existence of an appended file. */
312
165
			if (get_header(s, NULL, 0) != 0) {
313
143
				s->z_eof = 1;
314
143
				break;
315
			}
316
22
			inflateReset(&(s->z_stream));
317
22
			s->z_crc = crc32(0L, Z_NULL, 0);
318
			error = Z_OK;
319
22
		}
320
	}
321
103184
	s->z_crc = crc32(s->z_crc, start,
322
51592
	    (uInt)(s->z_stream.next_out - start));
323
51592
	len -= s->z_stream.avail_out;
324
325
51592
	return (len);
326
bad:
327
	/* Add byte counts from the finished stream. */
328
1133
	s->z_total_in += s->z_stream.total_in;
329
1133
	s->z_total_out += s->z_stream.total_out;
330
1133
	return (-1);
331
52725
}
332
333
#ifndef SMALL
334
static int
335
put_int32(gz_stream *s, u_int32_t x)
336
{
337
560
	u_int32_t y = htole32(x);
338
339
280
	if (write(s->z_fd, &y, sizeof(y)) != sizeof(y))
340
		return Z_ERRNO;
341
280
	return 0;
342
280
}
343
344
static int
345
put_header(gz_stream *s, char *name, u_int32_t mtime, int bits)
346
{
347
280
	struct iovec iov[2];
348
140
	u_char buf[10];
349
350
140
	buf[0] = gz_magic[0];
351
140
	buf[1] = gz_magic[1];
352
140
	buf[2] = Z_DEFLATED;
353
140
	buf[3] = name ? ORIG_NAME : 0;
354
140
	buf[4] = mtime & 0xff;
355
140
	buf[5] = (mtime >> 8) & 0xff;
356
140
	buf[6] = (mtime >> 16) & 0xff;
357
140
	buf[7] = (mtime >> 24) & 0xff;
358
420
	buf[8] = bits == 1 ? 4 : bits == 9 ? 2 : 0;	/* xflags */
359
140
	buf[9] = OS_CODE;
360
140
	iov[0].iov_base = buf;
361
140
	iov[0].iov_len = sizeof(buf);
362
140
	s->z_hlen = sizeof(buf);
363
364
140
	if (name != NULL) {
365
45
		iov[1].iov_base = name;
366
45
		iov[1].iov_len = strlen(name) + 1;
367
45
		s->z_hlen += iov[1].iov_len;
368
45
	}
369
140
	if (writev(s->z_fd, iov, name ? 2 : 1) == -1)
370
		return (-1);
371
140
	return (0);
372
140
}
373
374
void *
375
gz_wopen(int fd, char *name, int bits, u_int32_t mtime)
376
{
377
	gz_stream *s;
378
379
280
	if (fd < 0)
380
		return NULL;
381
382
140
	if (bits < 0 || bits > Z_BEST_COMPRESSION) {
383
		errno = EINVAL;
384
		return NULL;
385
	}
386
140
	if ((s = calloc(1, sizeof(gz_stream))) == NULL)
387
		return NULL;
388
389
140
	s->z_stream.zalloc = (alloc_func)0;
390
140
	s->z_stream.zfree = (free_func)0;
391
140
	s->z_stream.opaque = (voidpf)0;
392
140
	s->z_stream.next_in = Z_NULL;
393
140
	s->z_stream.next_out = Z_NULL;
394
140
	s->z_stream.avail_in = s->z_stream.avail_out = 0;
395
140
	s->z_fd = 0;
396
140
	s->z_eof = 0;
397
140
	s->z_time = 0;
398
140
	s->z_hlen = 0;
399
140
	s->z_total_in = 0;
400
140
	s->z_total_out = 0;
401
140
	s->z_crc = crc32(0L, Z_NULL, 0);
402
140
	s->z_mode = 'w';
403
404
	/* windowBits is passed < 0 to suppress zlib header */
405
280
	if (deflateInit2(&(s->z_stream), bits, Z_DEFLATED,
406
140
			 -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) {
407
		free (s);
408
		return NULL;
409
	}
410
140
	s->z_stream.next_out = s->z_buf;
411
140
	s->z_stream.avail_out = Z_BUFSIZE;
412
413
140
	errno = 0;
414
140
	s->z_fd = fd;
415
416
	/* write the .gz header */
417
140
	if (put_header(s, name, mtime, bits) != 0) {
418
		gz_close(s, NULL, NULL, NULL);
419
		s = NULL;
420
	}
421
422
140
	return s;
423
140
}
424
int
425
gz_write(void *cookie, const char *buf, int len)
426
{
427
12522
	gz_stream *s = (gz_stream*)cookie;
428
429
6261
	s->z_stream.next_in = (char *)buf;
430
6261
	s->z_stream.avail_in = len;
431
432
18783
	while (s->z_stream.avail_in != 0) {
433
6261
		if (s->z_stream.avail_out == 0) {
434
4
			if (write(s->z_fd, s->z_buf, Z_BUFSIZE) != Z_BUFSIZE)
435
				break;
436
4
			s->z_stream.next_out = s->z_buf;
437
4
			s->z_stream.avail_out = Z_BUFSIZE;
438
4
		}
439
6261
		if (deflate(&(s->z_stream), Z_NO_FLUSH) != Z_OK)
440
			break;
441
	}
442
6261
	s->z_crc = crc32(s->z_crc, buf, len);
443
444
6261
	return (int)(len - s->z_stream.avail_in);
445
}
446
447
int
448
gz_flush(void *cookie, int flush)
449
{
450
280
	gz_stream *s = (gz_stream*)cookie;
451
	size_t len;
452
	int done = 0;
453
	int err;
454
455

280
	if (s == NULL || s->z_mode != 'w') {
456
		errno = EBADF;
457
		return Z_ERRNO;
458
	}
459
460
140
	s->z_stream.avail_in = 0; /* should be zero already anyway */
461
462
280
	for (;;) {
463
280
		len = Z_BUFSIZE - s->z_stream.avail_out;
464
465
280
		if (len != 0) {
466
142
			if (write(s->z_fd, s->z_buf, len) != len)
467
				return Z_ERRNO;
468
142
			s->z_stream.next_out = s->z_buf;
469
142
			s->z_stream.avail_out = Z_BUFSIZE;
470
142
		}
471
280
		if (done)
472
			break;
473
280
		if ((err = deflate(&(s->z_stream), flush)) != Z_OK &&
474
140
		    err != Z_STREAM_END)
475
			return err;
476
477
		/* deflate has finished flushing only when it hasn't
478
		 * used up all the available space in the output buffer
479
		 */
480
140
		done = (s->z_stream.avail_out != 0 || err == Z_STREAM_END);
481
	}
482
140
	return 0;
483
140
}
484
#endif
485
486
int
487
gz_close(void *cookie, struct z_info *info, const char *name, struct stat *sb)
488
{
489
2832
	gz_stream *s = (gz_stream*)cookie;
490
	int err = 0;
491
492
1416
	if (s == NULL)
493
		return -1;
494
495
#ifndef SMALL
496

1556
	if (s->z_mode == 'w' && (err = gz_flush (s, Z_FINISH)) == Z_OK) {
497
140
		if ((err = put_int32 (s, s->z_crc)) == Z_OK) {
498
140
			s->z_hlen += sizeof(int32_t);
499
140
			if ((err = put_int32 (s, s->z_stream.total_in)) == Z_OK)
500
140
				s->z_hlen += sizeof(int32_t);
501
		}
502
	}
503
#endif
504

2832
	if (!err && s->z_stream.state != NULL) {
505
1416
		if (s->z_mode == 'w')
506
#ifndef SMALL
507
140
			err = deflateEnd(&s->z_stream);
508
#else
509
			err = -1;
510
#endif
511
1276
		else if (s->z_mode == 'r')
512
1276
			err = inflateEnd(&s->z_stream);
513
	}
514
515
1416
	if (info != NULL) {
516
1416
		info->mtime = s->z_time;
517
1416
		info->crc = s->z_crc;
518
1416
		info->hlen = s->z_hlen;
519
1416
		if (s->z_mode == 'r') {
520
1276
			info->total_in = s->z_total_in;
521
1276
			info->total_out = s->z_total_out;
522
1276
		} else {
523
140
			info->total_in = s->z_stream.total_in;
524
140
			info->total_out = s->z_stream.total_out;
525
		}
526
527
1416
	}
528
529
1416
	setfile(name, s->z_fd, sb);
530
2832
	if (!err)
531
1416
		err = close(s->z_fd);
532
	else
533
1416
		(void)close(s->z_fd);
534
535
1416
	free(s);
536
537
1416
	return err;
538
1416
}
539