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 <[email protected]>"
:maintainer "Nathan Froyd <[email protected]>"
: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