diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/gunzip.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/gunzip.b')
| -rw-r--r-- | appl/cmd/gunzip.b | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/appl/cmd/gunzip.b b/appl/cmd/gunzip.b new file mode 100644 index 00000000..6cb9eaf8 --- /dev/null +++ b/appl/cmd/gunzip.b @@ -0,0 +1,139 @@ +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"; +} |
