racket/racket/collects/file/untgz.rkt
Matthew Flatt 027dd9a43c untgz and gunzip: report unexpected end-of-file
Report an explicit "unexpected end-of-file" error instead of
a later contract failure on #<eof> insteda of a byte

Closes #1204
2016-04-18 08:25:41 -06:00

57 lines
1.8 KiB
Racket

#lang racket/base
(require racket/file
"untar.rkt"
"gunzip.rkt"
racket/contract/base
racket/port)
(provide
(contract-out
[untgz (->* ((or/c path-string? input-port?))
(#:dest
(or/c #f path-string?)
#:strip-count exact-nonnegative-integer?
#:permissive? any/c
#:filter (path? (or/c path? #f)
symbol? exact-integer? (or/c path? #f)
exact-nonnegative-integer? exact-nonnegative-integer?
. -> . any/c))
void?)]))
(define (untgz in
#:dest [dest #f]
#:strip-count [strip-count 0]
#:permissive? [permissive? #f]
#:filter [filter void])
((if (input-port? in)
(lambda (in f) (f in))
call-with-input-file*)
in
(lambda (in)
(define-values (in2 wait)
(cond
[(and (= (peek-byte/not-eof in 0) #o037)
(= (peek-byte/not-eof in 1) #o213))
(define-values (in2 out) (make-pipe 4096))
(define t
(thread
(lambda ()
(dynamic-wind
(lambda () (void))
(lambda () (gunzip-through-ports in out))
(lambda () (close-output-port out))))))
(values in2 (lambda ()
;; drain any remaining bytes:
(copy-port in2 (open-output-nowhere))
(thread-wait t)))]
[else (values in void)]))
(begin0
(untar in2 #:dest dest #:strip-count strip-count #:permissive? permissive? #:filter filter)
(wait)))))
(define (peek-byte/not-eof in at)
(define b (peek-byte in at))
(when (eof-object? b)
(error 'untgz "unexpected end-of-file\n stream: ~e" in))
b)