GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/compress/gzopen.c Lines: 218 253 86.2 %
Date: 2017-11-13 Branches: 92 136 67.6 %

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
1142
	if (fd < 0)
109
		return NULL;
110
111
571
	if ((s = calloc(1, sizeof(gz_stream))) == NULL)
112
		return NULL;
113
114
571
	s->z_stream.zalloc = (alloc_func)0;
115
571
	s->z_stream.zfree = (free_func)0;
116
571
	s->z_stream.opaque = (voidpf)0;
117
571
	s->z_stream.next_in = Z_NULL;
118
571
	s->z_stream.next_out = Z_NULL;
119
571
	s->z_stream.avail_in = s->z_stream.avail_out = 0;
120
571
	s->z_fd = 0;
121
571
	s->z_eof = 0;
122
571
	s->z_time = 0;
123
571
	s->z_hlen = 0;
124
571
	s->z_total_in = 0;
125
571
	s->z_total_out = 0;
126
571
	s->z_crc = crc32(0L, Z_NULL, 0);
127
571
	s->z_mode = 'r';
128
129
571
	if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
130
		free (s);
131
		return NULL;
132
	}
133
571
	s->z_stream.next_in = s->z_buf;
134
571
	s->z_stream.avail_out = Z_BUFSIZE;
135
136
571
	errno = 0;
137
571
	s->z_fd = fd;
138
139
	/* read the .gz header */
140
571
	if (get_header(s, name, gotmagic) != 0) {
141
		gz_close(s, NULL, NULL, NULL);
142
		s = NULL;
143
	}
144
145
571
	return s;
146
571
}
147
148
static int
149
get_byte(gz_stream *s)
150
{
151
16388
	if (s->z_eof)
152
		return EOF;
153
154
8194
	if (s->z_stream.avail_in == 0) {
155
627
		errno = 0;
156
627
		s->z_stream.avail_in = read(s->z_fd, s->z_buf, Z_BUFSIZE);
157
627
		if ((int)s->z_stream.avail_in <= 0) {
158
56
			s->z_eof = 1;
159
56
			return EOF;
160
		}
161
571
		s->z_stream.next_in = s->z_buf;
162
571
	}
163
8138
	s->z_stream.avail_in--;
164
8138
	return *s->z_stream.next_in++;
165
8194
}
166
167
static u_int32_t
168
get_int32(gz_stream *s)
169
{
170
	u_int32_t x;
171
172
1916
	x  = ((u_int32_t)(get_byte(s) & 0xff));
173
958
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<8;
174
958
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<16;
175
958
	x |= ((u_int32_t)(get_byte(s) & 0xff))<<24;
176
958
	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
1274
	if (!gotmagic) {
190
172
		for (len = 0; len < 2; len++) {
191
76
			c = get_byte(s);
192
76
			if (c != gz_magic[len]) {
193
56
				errno = EFTYPE;
194
56
				return -1;
195
			}
196
		}
197
	}
198
199
581
	method = get_byte(s);
200
581
	flags = get_byte(s);
201

1162
	if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
202
		errno = EFTYPE;
203
		return -1;
204
	}
205
206
	/* Stash timestamp (mtime) */
207
581
	s->z_time = get_int32(s);
208
209
	/* Discard xflags and OS code */
210
581
	(void)get_byte(s);
211
581
	(void)get_byte(s);
212
213
581
	s->z_hlen += 10; /* magic, method, flags, time, xflags, OS code */
214
581
	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
581
	if ((flags & ORIG_NAME) != 0) { /* read/save the original file name */
224
32
		if ((ep = name) != NULL)
225
22
			ep += PATH_MAX - 1;
226
364
		while ((c = get_byte(s)) != EOF) {
227
182
			s->z_hlen++;
228
182
			if (c == '\0')
229
				break;
230
150
			if (name < ep)
231
110
				*name++ = c;
232
		}
233
32
		if (name != NULL)
234
22
			*name = '\0';
235
	}
236
237
581
	if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
238
3560
		while ((c = get_byte(s)) != EOF) {
239
1780
			s->z_hlen++;
240
1780
			if (c == '\0')
241
				break;
242
		}
243
	}
244
245
581
	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
581
	if (s->z_eof) {
252
		errno = EFTYPE;
253
		return -1;
254
	}
255
256
581
	return 0;
257
637
}
258
259
int
260
gz_read(void *cookie, char *buf, int len)
261
{
262
1282
	gz_stream *s = (gz_stream*)cookie;
263
	u_char *start = buf; /* starting point for crc computation */
264
	int error = Z_OK;
265
266
641
	s->z_stream.next_out = buf;
267
641
	s->z_stream.avail_out = len;
268
269

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

128
	if (s == NULL || s->z_mode != 'w') {
456
		errno = EBADF;
457
		return Z_ERRNO;
458
	}
459
460
64
	s->z_stream.avail_in = 0; /* should be zero already anyway */
461
462
128
	for (;;) {
463
128
		len = Z_BUFSIZE - s->z_stream.avail_out;
464
465
128
		if (len != 0) {
466
64
			if (write(s->z_fd, s->z_buf, len) != len)
467
				return Z_ERRNO;
468
64
			s->z_stream.next_out = s->z_buf;
469
64
			s->z_stream.avail_out = Z_BUFSIZE;
470
64
		}
471
128
		if (done)
472
			break;
473
128
		if ((err = deflate(&(s->z_stream), flush)) != Z_OK &&
474
64
		    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
64
		done = (s->z_stream.avail_out != 0 || err == Z_STREAM_END);
481
	}
482
64
	return 0;
483
64
}
484
#endif
485
486
int
487
gz_close(void *cookie, struct z_info *info, const char *name, struct stat *sb)
488
{
489
1270
	gz_stream *s = (gz_stream*)cookie;
490
	int err = 0;
491
492
635
	if (s == NULL)
493
		return -1;
494
495
#ifndef SMALL
496

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

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