compress.c revision 68349
1/*
2 * compress routines:
3 *	zmagic() - returns 0 if not recognized, uncompresses and prints
4 *		   information if recognized
5 *	uncompress(method, old, n, newch) - uncompress old into new,
6 *					    using method, return sizeof new
7 */
8#include "file.h"
9#include <stdio.h>
10#include <stdlib.h>
11#ifdef HAVE_UNISTD_H
12#include <unistd.h>
13#endif
14#include <string.h>
15#ifdef HAVE_SYS_WAIT_H
16#include <sys/wait.h>
17#endif
18#ifndef lint
19FILE_RCSID("@(#)$Id: compress.c,v 1.17 2000/08/05 17:36:47 christos Exp $")
20#endif
21
22
23static struct {
24	const char *magic;
25	int   maglen;
26	const char *const argv[3];
27	int	 silent;
28} compr[] = {
29	{ "\037\235", 2, { "uncompress", "-c", NULL }, 0 },	/* compressed */
30	{ "\037\235", 2, { "gzip", "-cdq", NULL }, 1 },		/* compressed */
31	{ "\037\213", 2, { "gzip", "-cdq", NULL }, 1 },		/* gzipped */
32	{ "\037\236", 2, { "gzip", "-cdq", NULL }, 1 },		/* frozen */
33	{ "\037\240", 2, { "gzip", "-cdq", NULL }, 1 },		/* SCO LZH */
34	/* the standard pack utilities do not accept standard input */
35	{ "\037\036", 2, { "gzip", "-cdq", NULL }, 0 },		/* packed */
36	{ "BZh",      3, { "bzip2", "-d", NULL }, 1 },		/* bzip2-ed */
37};
38
39static int ncompr = sizeof(compr) / sizeof(compr[0]);
40
41
42static int uncompress __P((int, const unsigned char *, unsigned char **, int));
43
44int
45zmagic(buf, nbytes)
46	unsigned char *buf;
47	int nbytes;
48{
49	unsigned char *newbuf;
50	int newsize;
51	int i;
52
53	for (i = 0; i < ncompr; i++) {
54		if (nbytes < compr[i].maglen)
55			continue;
56		if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 &&
57		    (newsize = uncompress(i, buf, &newbuf, nbytes)) != 0) {
58			tryit(newbuf, newsize, 1);
59			free(newbuf);
60			printf(" (");
61			tryit(buf, nbytes, 0);
62			printf(")");
63			return 1;
64		}
65	}
66
67	if (i == ncompr)
68		return 0;
69
70	return 1;
71}
72
73
74static int
75uncompress(method, old, newch, n)
76	int method;
77	const unsigned char *old;
78	unsigned char **newch;
79	int n;
80{
81	int fdin[2], fdout[2];
82
83	if (pipe(fdin) == -1 || pipe(fdout) == -1) {
84		error("cannot create pipe (%s).\n", strerror(errno));
85		/*NOTREACHED*/
86	}
87	switch (fork()) {
88	case 0:	/* child */
89		(void) close(0);
90		(void) dup(fdin[0]);
91		(void) close(fdin[0]);
92		(void) close(fdin[1]);
93
94		(void) close(1);
95		(void) dup(fdout[1]);
96		(void) close(fdout[0]);
97		(void) close(fdout[1]);
98		if (compr[method].silent)
99			(void) close(2);
100
101		execvp(compr[method].argv[0],
102		       (char *const *)compr[method].argv);
103		exit(1);
104		/*NOTREACHED*/
105	case -1:
106		error("could not fork (%s).\n", strerror(errno));
107		/*NOTREACHED*/
108
109	default: /* parent */
110		(void) close(fdin[0]);
111		(void) close(fdout[1]);
112		if (write(fdin[1], old, n) != n)
113			return 0;
114		(void) close(fdin[1]);
115		if ((*newch = (unsigned char *) malloc(n)) == NULL)
116			return 0;
117		if ((n = read(fdout[0], *newch, n)) <= 0) {
118			free(*newch);
119			return 0;
120		}
121		(void) close(fdout[0]);
122		(void) wait(NULL);
123		return n;
124	}
125}
126