lzlib: 'lzread!' never returns more than it was asked for.

Fixes a bug whereby 'lzread!' could return more than COUNT.

* guix/lzlib.scm (lzread!): Rewrite in a semi-functional style.
This commit is contained in:
Ludovic Courtès 2019-05-24 15:20:46 +02:00
parent 2e5c71b2a2
commit c131bea276
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
1 changed files with 19 additions and 20 deletions

View File

@ -494,29 +494,28 @@ perhaps not yet read."
;; High level functions. ;; High level functions.
(define* (lzread! decoder file-port bv
(define* (lzread! decoder port bv
#:optional (start 0) (count (bytevector-length bv))) #:optional (start 0) (count (bytevector-length bv)))
"Read up to COUNT bytes from FILE-PORT into BV at offset START. Return the "Read up to COUNT bytes from PORT into BV at offset START. Return the
number of uncompressed bytes actually read; it is zero if COUNT is zero or if number of uncompressed bytes actually read; it is zero if COUNT is zero or if
the end-of-stream has been reached." the end-of-stream has been reached."
;; WARNING: Because we don't alternate between lz-reads and lz-writes, we can't (define (feed-decoder! decoder)
;; process more than lz-decompress-write-size from the file-port. ;; Feed DECODER with data read from PORT.
(when (> count (lz-decompress-write-size decoder)) (match (get-bytevector-n port (lz-decompress-write-size decoder))
(set! count (lz-decompress-write-size decoder))) ((? eof-object? eof) eof)
(let ((file-bv (get-bytevector-n file-port count))) (bv (lz-decompress-write decoder bv))))
(unless (eof-object? file-bv)
(lz-decompress-write decoder file-bv 0 (bytevector-length file-bv)))) (let loop ((read 0)
(let ((read 0)) (start start))
(let loop ((rd 0)) (cond ((< read count)
(if (< start (bytevector-length bv)) (match (lz-decompress-read decoder bv start (- count read))
(begin (0 (if (eof-object? (feed-decoder! decoder))
(set! rd (lz-decompress-read decoder bv start (- (bytevector-length bv) start))) read
(set! start (+ start rd)) (loop read start)))
(set! read (+ read rd))) (n (loop (+ read n) (+ start n)))))
(set! rd 0)) (else
(unless (= rd 0) read))))
(loop rd)))
read))
(define (lzwrite! encoder source source-offset source-count (define (lzwrite! encoder source source-offset source-count
target target-offset target-count) target target-offset target-count)