forsyth20121205-174063a80cc13 years agoHistory
139 lines · 2.9 KB · Brainfuck
RawDownload
implement Gunzip; include "sys.m";	sys:	Sys;	fprint, sprint: import sys; include "draw.m"; include "string.m";	str: String; include "bufio.m";	bufio:	Bufio;	Iobuf:	import bufio; include "filter.m";	inflate: Filter; Gunzip: module{	init:	fn(ctxt: ref Draw->Context, argv: list of string);}; argv0:	con "gunzip";stderr:	ref Sys->FD; INFLATEPATH: con "/dis/lib/inflate.dis"; init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	bufio = load Bufio Bufio->PATH;	if (bufio == nil)		fatal(sys->sprint("cannot load %s: %r", Bufio->PATH));	str = load String String->PATH;	if (bufio == nil)		fatal(sys->sprint("cannot load %s: %r", String->PATH));	inflate = load Filter INFLATEPATH;	if (inflate == nil)		fatal(sys->sprint("cannot load %s: %r", INFLATEPATH)); 	inflate->init(); 	if(argv != nil)		argv = tl argv; 	ok := 1;	if(len argv == 0){		bin := bufio->fopen(sys->fildes(0), Bufio->OREAD);		bout := bufio->fopen(sys->fildes(1), Bufio->OWRITE);		ok = gunzip(bin, bout, "stdin", "stdout");		bout.close();	} else {		for(; argv != nil; argv = tl argv)			ok &= gunzipf(hd argv);	}	if(ok == 0)		raise "fail:errors";} gunzipf(file: string): int{	bin := bufio->open(file, Bufio->OREAD);	if(bin == nil){		fprint(stderr, "%s: can't open %s: %r\n", argv0, file);		return 0;	} 	(nil, ofile) := str->splitr(file, "/");	n := len ofile;	if(n < 4 || ofile[n-3:] != ".gz"){		fprint(stderr, "%s: .gz extension required: %s\n", argv0, file);		bin.close();		return 0;	} else		ofile = ofile[:n-3];	bout := bufio->create(ofile, Bufio->OWRITE, 8r666);	if(bout == nil){		fprint(stderr, "%s: can't open %s: %r\n", argv0, ofile);		bin.close();		return 0;	} 	ok := gunzip(bin, bout, file, ofile);	bin.close();	bout.close();	if(ok) {		# did possibly rename file and update modification time here.		if (sys->remove(file) == -1)			sys->fprint(stderr, "%s: cannot remove %s: %r\n", argv0, file);	} 	return ok;} gunzip(bin, bout: ref Iobuf, fin, fout: string): int{	rq := inflate->start("h");	for(;;) {		pick m := <-rq {		Fill =>			n := bin.read(m.buf, len m.buf);			m.reply <-= n;			if (n == -1) {				sys->fprint(stderr, "%s: %s: read error: %r\n", argv0, fin);				return 0;			}		Result =>			if (len m.buf > 0) {				n := bout.write(m.buf, len m.buf);				if (n != len m.buf) {					m.reply <-= -1;					sys->fprint(stderr, "%s: %s: write error: %r\n", argv0, fout);					return 0;				}				m.reply <-= 0;			}		#Info =>		#	if m.msg begins with "file", it's the original filename of the compressed file.		#	if m.msg begins with "mtime", it's the original modification time.		Finished =>			if (bout.flush() != 0) {				sys->fprint(stderr, "%s: %s: flush error: %r\n", argv0, fout);				return 0;			}			return 1;		Error =>			sys->fprint(stderr, "%s: %s: inflate error: %s\n", argv0, fin, m.e);			return 0;		}	}} fatal(msg: string){	fprint(stderr, "%s: %s\n", argv0, msg);	raise "fail:error";}