1 /* $OpenBSD: gzip.c,v 1.3 1999/10/04 21:46:28 espie Exp $ */
3 * Copyright (c) 1999 Marc Espie.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Marc Espie for the OpenBSD
18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * $FreeBSD: src/usr.sbin/pkg_install/sign/gzip.c,v 1.1.2.3 2002/08/20 06:35:08 obrien Exp $
31 * $DragonFly: src/usr.sbin/pkg_install/sign/Attic/gzip.c,v 1.2 2003/06/17 04:29:59 dillon Exp $
34 #include <sys/types.h>
45 * Signatures follow a simple format
46 * (endianess was chosen to conform to gzip header format)
49 SIGNTAG known_tags[KNOWN_TAGS] = {
50 {'S', 'I', 'G', 'P', 'G', 'P', 0, 0 },
51 {'C', 'K', 'S', 'H', 'A', '1', 0, 0 },
52 {'C', 'R', 'X', '5', '0', '9', 0, 0 },
53 {'S', 'i', 'g', 'P', 'G', 'P', 0, 0 } /* old format */
58 struct signature *sign;
60 sign->tag[6] = sign->length % 256;
61 sign->tag[7] = sign->length / 256;
65 sign_fill_length(sign)
66 struct signature *sign;
68 sign->length = sign->tag[6] + 256 * sign->tag[7];
72 stack_sign(match, t, f, sign)
76 struct signature **sign;
78 struct signature *new_sign;
81 new_sign = malloc(sizeof *new_sign);
85 new_sign->next = NULL;
86 memcpy(new_sign->tag, match, sizeof(SIGNTAG));
87 sign_fill_length(new_sign);
88 new_sign->data = malloc(new_sign->length);
89 if (new_sign->data == NULL ||
90 fread(new_sign->data, 1, new_sign->length, f) != new_sign->length) {
91 free_signature(new_sign);
94 length = new_sign->length;
99 while ((*sign)->next != NULL)
100 sign = &((*sign)->next);
101 (*sign)->next = new_sign;
104 free_signature(new_sign);
112 struct signature **sign;
117 if (fread(match, 1, sizeof(SIGNTAG), f) != sizeof(SIGNTAG))
119 for (i = 0; i < KNOWN_TAGS; i++) {
120 if (memcmp(match, known_tags[i], TAGCHECK) == 0) {
121 unsigned int sign_length = stack_sign(match, i, f, sign);
123 return sign_length + sizeof(SIGNTAG);
139 if ((unsigned char)c != (unsigned char)GZIP_MAGIC0
140 || (unsigned char)d != (unsigned char)GZIP_MAGIC1)
147 fill_gzip_fields(f, h)
149 struct mygzip_header *h;
156 if (method == EOF || flags == EOF || fread(h->stamp, 1, 6, f) != 6)
158 h->method = (char)method;
159 h->flags = (char)flags;
160 if ((h->flags & CONTINUATION) != 0)
161 if (fread(h->part, 1, 2, f) != 2)
166 /* retrieve a gzip header, including signatures */
168 gzip_read_header(f, h, sign)
170 struct mygzip_header *h;
171 struct signature **sign;
175 if (!gzip_magic(f) || !fill_gzip_fields(f, h))
176 return GZIP_NOT_GZIP;
178 if ((h->flags & EXTRA_FIELD) == 0) {
180 return GZIP_UNSIGNED;
187 return GZIP_NOT_GZIP;
188 h->remaining = (unsigned)c;
191 return GZIP_NOT_PGPSIGNED;
192 h->remaining += ((unsigned) c) << 8;
193 while (h->remaining >= sizeof(SIGNTAG)) {
194 int sign_length = add_sign(f, sign);
196 h->remaining -= sign_length;
198 return GZIP_NOT_GZIP;
199 if (sign_length == 0)
208 struct signature *sign;
212 while (sign != NULL) {
213 total += sizeof(SIGNTAG) + sign->length;
224 static void myadd(arg, buffer, size)
229 struct mydata *d = arg;
231 if (fwrite(buffer, 1, size, d->file) == size)
237 /* write a gzip header, including signatures */
239 gzip_write_header(f, h, sign)
241 const struct mygzip_header *h;
242 struct signature *sign;
246 if (gzip_copy_header(h, sign, myadd, &d) == 0)
252 gzip_copy_header(h, sign, add, data)
253 const struct mygzip_header *h;
254 struct signature *sign;
255 void (*add)(void *, const char *, size_t);
264 length = h->remaining + sign_length(sign);
266 buflength = length + 2;
267 flags = h->flags | EXTRA_FIELD;
269 flags = h->flags & ~EXTRA_FIELD;
273 if ((h->flags & CONTINUATION) != 0)
276 buffer = malloc(buflength);
281 buffer[i++] = GZIP_MAGIC0;
282 buffer[i++] = GZIP_MAGIC1;
283 buffer[i++] = h->method;
285 memcpy(buffer+i, h->stamp, 6);
287 if ((flags & CONTINUATION) != 0) {
288 memcpy(buffer+i, h->part, 2);
292 buffer[i++] = (char)(length % 256);
293 buffer[i++] = (char)(length / 256);
294 while (sign != NULL) {
295 memcpy(buffer+i, sign->tag, sizeof(SIGNTAG));
296 i += sizeof(SIGNTAG);
297 memcpy(buffer+i, sign->data, sign->length);
302 (*add)(data, buffer, buflength);
309 struct signature *sign;
311 struct signature *next;
313 while (sign != NULL) {