RSS Feed

Lisp Project of the Day

archive & gzip-stream

You can support this project by donating at:

Donate using PatreonDonate using Liberapay

Or see the list of project sponsors.

archive & gzip-streamsystem

This is a pure Common Lisp implementation of TAR and CPIO.

It does not support gzipped or bzipped archive.

I have a tar gzipped archive of the lisp system here.

Attempt to read gzipped archive leads to a nasty error:

POFTHEDAY> (archive:with-open-archive
               (archive
                "/tmp/archive-20160318-git.tgz"
                :direction :input)
             (archive:do-archive-entries (entry archive)
               (format t "~A~%"
                       entry)))
; Debugger entered on #<SIMPLE-ERROR "Invalid byte: ~A in ~A" {1004E9FE73}>
[1] POFTHEDAY>

We can try to use another system for working with compressed streams - "gzip-stream".

Consider this snippet as a bonus. Only today we are presenting two projects of the day simultaneously! :)

POFTHEDAY> (gzip-stream:with-open-gzip-file (stream "/tmp/archive-20160318-git.tgz")
               (archive:with-open-archive
                   (archive stream :direction :input)
                 (archive:do-archive-entries (entry archive)
                   (format t "~A~%"
                           entry))))
#<Tar-Entry archive-20160318-git/>
#<Tar-Entry archive-20160318-git/.gitignore>
#<Tar-Entry archive-20160318-git/LICENSE>
#<Tar-Entry archive-20160318-git/NEWS>
#<Tar-Entry archive-20160318-git/README>
#<Tar-Entry archive-20160318-git/TODO>
#<Tar-Entry archive-20160318-git/archive.asd>
#<Tar-Entry archive-20160318-git/archive.lisp>
#<Tar-Entry archive-20160318-git/compat.lisp>
#<Tar-Entry archive-20160318-git/conditions.lisp>
#<Tar-Entry archive-20160318-git/cpio.lisp>
#<Tar-Entry archive-20160318-git/example.lisp>
#<Tar-Entry archive-20160318-git/formats.lisp>
#<Tar-Entry archive-20160318-git/generics.lisp>
#<Tar-Entry archive-20160318-git/macros.lisp>
#<Tar-Entry archive-20160318-git/package.lisp>
#<Tar-Entry archive-20160318-git/stream.lisp>
#<Tar-Entry archive-20160318-git/tar.lisp>

Now, how to read some file's content?

Easy! Let's pretend, we need to extract asd file from the archive. We will find it and read it from the stream, provided by "archive".

POFTHEDAY> (gzip-stream:with-open-gzip-file (stream "/tmp/archive-20160318-git.tgz")
             (archive:with-open-archive (archive stream :direction :input)
               (archive:do-archive-entries (entry archive)
                 (when (cl-strings:ends-with (archive:name entry)
                                             "/archive.asd")
                   (format t "~A~%"
                           (alexandria:read-stream-content-into-string
                            (flexi-streams:make-flexi-stream
                             (archive:entry-stream entry))))))))
;;; -*- mode: lisp -*-

(asdf:defsystem :archive
  :version "0.9"
  :author "Nathan Froyd <froydnj@gmail.com>"
  :maintainer "Nathan Froyd <froydnj@gmail.com>"
  :description "A package for reading and writing archive (tar, cpio, etc.) files."
  :license "BSD-style (http://opensource.org/licenses/BSD-3-Clause)"
  :depends-on (#+sbcl sb-posix trivial-gray-streams cl-fad)
  :components ((:file "package")
               (:file "conditions" :depends-on ("package"))
               (:file "generics" :depends-on ("package"))
...

Here I used tree utility systems:

  • cl-strings - to match text at the end of the filename
  • alexandria - to read all stream's content into the string
  • flexi-streams - to convert the binary stream into the text

Brought to you by 40Ants under Creative Commons License