diff options
| author | Fumitoshi UKAI <ukai@debian.or.jp> | 2002-01-31 14:03:49 +0000 | 
|---|---|---|
| committer | Fumitoshi UKAI <ukai@debian.or.jp> | 2002-01-31 14:03:49 +0000 | 
| commit | 40e4f285117669169eb674da49b20d1b0e210dd8 (patch) | |
| tree | 249730429705a1ecefbb1babd6a44fce59a2258c | |
| parent | [w3m-dev 02955] compression_decoders error message (diff) | |
| download | w3m-40e4f285117669169eb674da49b20d1b0e210dd8.tar.gz w3m-40e4f285117669169eb674da49b20d1b0e210dd8.zip | |
inflate.c: support raw deflate without zlib header
From: Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | inflate.c | 201 | 
2 files changed, 161 insertions, 46 deletions
| @@ -1,3 +1,7 @@ +2002-01-31  Kiyokazu SUTO <suto@ks-and-ks.ne.jp> + +	* inflate.c: support raw deflate without zlib header +  2002-01-31  Fumitoshi UKAI  <ukai@debian.or.jp>  	* [w3m-dev 02955] compression_decoders error message @@ -2468,4 +2472,4 @@  	* release-0-2-1  	* import w3m-0.2.1 -$Id: ChangeLog,v 1.282 2002/01/31 09:43:14 ukai Exp $ +$Id: ChangeLog,v 1.283 2002/01/31 14:03:49 ukai Exp $ @@ -1,63 +1,174 @@ -/* $Id: inflate.c,v 1.4 2002/01/31 09:43:15 ukai Exp $ */ +#include <errno.h>  #include <stdio.h> +#include <string.h>  #include <stdlib.h>  #include <zlib.h> -#undef BUFSIZE -#define BUFSIZE 4096 +#define MYBUFSIZ (BUFSIZ * 0x10) + +/* cf. rfc1950.txt */ +static char dummy_head[1 + 1] = { +    0x8 + 0x7 * 0x10, +    (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, +};  int -main(int argc, char **argv) +main(int argc, char *argv[])  { -    z_stream s; -    FILE *f; -    char inbuf[BUFSIZE], outbuf[BUFSIZE]; -    int status, flush; +    int err, nfiles, i, nin, inrest, eoin, nout, outrest, eoout, ninflates, +	raw; +    z_stream d_stream; +    char *me = argv[0]; +    char *inbuf, *outbuf, **filev; + +    if (!(inbuf = malloc(MYBUFSIZ))) { +	fprintf(stderr, "%s: inbuf = malloc(%lu): %s\n", me, +		(unsigned long)MYBUFSIZ, strerror(errno)); +	exit(1); +    } + +    if (!(outbuf = malloc(MYBUFSIZ))) { +	fprintf(stderr, "%s: outbuf = malloc(%lu): %s\n", me, +		(unsigned long)MYBUFSIZ, strerror(errno)); +	exit(1); +    } + +    d_stream.zalloc = NULL; +    d_stream.zfree = NULL; +    d_stream.opaque = NULL;      if (argc > 1) { -	f = fopen(argv[1], "rb"); -	if (!f) { -	    fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]); -	    exit(1); -	} +	nfiles = argc - 1; +	filev = &argv[1];      } -    else -	f = stdin; +    else { +	static char *myargv[] = { "-", NULL }; -    s.zalloc = Z_NULL; -    s.zfree = Z_NULL; -    s.opaque = Z_NULL; -    status = inflateInit(&s); -    if (status != Z_OK) { -	fprintf(stderr, "%s: inflateInit() %s\n", argv[0], zError(status)); +	nfiles = 1; +	filev = myargv; +    } + +    if ((err = inflateInit(&d_stream)) != Z_OK) { +	fprintf(stderr, "%s: inflateInit(&d_stream): %d\n", me, err);  	exit(1);      } -    s.avail_in = 0; -    s.next_out = (Bytef *) outbuf; -    s.avail_out = sizeof(outbuf); -    flush = Z_NO_FLUSH; -    while (1) { -	if (s.avail_in == 0) { -	    s.next_in = (Bytef *) inbuf; -	    s.avail_in = fread(inbuf, 1, sizeof(inbuf), f); -	} -	status = inflate(&s, flush); -	if (status == Z_STREAM_END) { -	    if (sizeof(outbuf) - s.avail_out) -		fwrite(outbuf, 1, sizeof(outbuf) - s.avail_out, stdout); -	    break; -	} -	if (status != Z_OK) { -	    fprintf(stderr, "%s: inflate() %s\n", argv[0], zError(status)); -	    exit(1); + +    for (raw = ninflates = i = inrest = outrest = 0, eoout = 1; i < nfiles; +	 ++i) { +	FILE *in; + +	if (strcmp(filev[i], "-")) { +	    if (!(in = fopen(filev[i], "rb"))) { +		fprintf(stderr, "%s: fopen(\"%s\", \"rb\"): %s\n", me, +			filev[i], strerror(errno)); +		exit(1); +	    }  	} -	if (s.avail_out == 0) { -	    fwrite(outbuf, 1, sizeof(outbuf), stdout); -	    s.next_out = (Bytef *) outbuf; -	    s.avail_out = sizeof(outbuf); +	else +	    in = stdin; + +	for (eoin = 0;;) { +	    if ((nin = +		 fread(&inbuf[inrest], 1, MYBUFSIZ - inrest, +		       in)) < MYBUFSIZ - inrest) { +		if (ferror(in)) { +		    fprintf(stderr, "%s: fread(&inbuf[%d], 1, %d, in): %s\n", +			    me, inrest, MYBUFSIZ - inrest, strerror(errno)); +		    exit(1); +		} + +		eoin = 1; +	    } + +	    if (nin > 0) { +	      retry: +		d_stream.next_in = inbuf; +		d_stream.avail_in = inrest + nin; + +		for (eoout = 0;;) { +		    d_stream.next_out = &outbuf[outrest]; +		    d_stream.avail_out = MYBUFSIZ - outrest; + +		    switch (err = inflate(&d_stream, Z_NO_FLUSH)) { +		    case Z_OK: +			if (! +			    ((nout = +			      fwrite(outbuf, 1, MYBUFSIZ - d_stream.avail_out, +				     stdout)) > 0)) { +			    fprintf(stderr, +				    "%s: fwrite(outbuf, 1, %d, stdout): %s\n", +				    me, MYBUFSIZ - d_stream.avail_out, +				    strerror(errno)); +			    exit(1); +			} + +			memmove(outbuf, &outbuf[nout], +				MYBUFSIZ - d_stream.avail_out - nout); +			outrest = MYBUFSIZ - d_stream.avail_out - nout; +			++ninflates; +			break; +		    case Z_STREAM_END: +		    case Z_BUF_ERROR: +			ninflates = 0; +			outrest = MYBUFSIZ - d_stream.avail_out; +			eoout = 1; +			goto next_fread; +		    case Z_DATA_ERROR: +			if (!ninflates) { +			    if ((err = inflateReset(&d_stream)) != Z_OK) { +				fprintf(stderr, +					"%s: inflateReset(&d_stream): %d\n", +					me, err); +				exit(1); +			    } + +			    d_stream.next_in = dummy_head; +			    d_stream.avail_in = sizeof(dummy_head); + +			    if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_OK) { +				raw = ninflates = 1; +				goto retry; +			    } +			} +		    default: +			fprintf(stderr, +				"%s: inflate(&d_stream, Z_NO_FLUSH): %d\n", me, +				err); +			exit(1); +		    } +		} +	    } + +	  next_fread: +	    if (d_stream.avail_in) { +		memmove(inbuf, &inbuf[inrest + nin - d_stream.avail_in], +			d_stream.avail_in); +		inrest = d_stream.avail_in; +	    } +	    else +		inrest = 0; + +	    if (eoin) +		break;  	} + +	if (in != stdin) +	    fclose(in);      } -    inflateEnd(&s); -    fclose(f); + +    if (!eoout && !raw) { +	fprintf(stderr, "%s: short input\n", me); +	exit(1); +    } + +    if (inrest) +	fprintf(stderr, "%s: trailing garbages are ignored\n", me); + +    if (outrest && fwrite(outbuf, 1, outrest, stdout) < outrest) { +	fprintf(stderr, "%s: fwrite(outbuf, 1, %d, stdout): %s\n", me, outrest, +		strerror(errno)); +	exit(1); +    } +      return 0;  } | 
