134 lines
5.3 KiB
Racket
134 lines
5.3 KiB
Racket
#lang scribble/doc
|
|
@(require "common.rkt" (for-label file/unzip))
|
|
|
|
@title[#:tag "unzip"]{@exec{zip} File Extraction}
|
|
@author{David Herman}
|
|
|
|
@defmodule[file/unzip]{The @racketmodname[file/unzip] library provides
|
|
a function to extract items from a @exec{zip} archive.}
|
|
|
|
@defproc[(unzip [in (or/c path-string? input-port)]
|
|
[entry-reader (bytes? boolean? input-port? . -> . any)
|
|
(make-filesystem-entry-reader)])
|
|
void?]{
|
|
|
|
Unzips an entire @exec{zip} archive from @racket[in].
|
|
|
|
For each entry in the archive, the @racket[entry-reader] procedure is
|
|
called with three arguments: the byte string representing the entry
|
|
name, a boolean flag indicating whether the entry represents a
|
|
directory, and an input port containing the inflated contents of the
|
|
entry. The default @racket[entry-reader] unpacks entries to the
|
|
filesystem; call @racket[make-filesystem-entry-reader] to configure
|
|
aspects of the unpacking, such as the destination directory.}
|
|
|
|
@defproc[(make-filesystem-entry-reader
|
|
[#:dest dest-path (or/c path-string? #f) #f]
|
|
[#:strip-count strip-count exact-nonnegative-integer? 0]
|
|
[#:exists exists (or/c 'skip 'error 'replace 'truncate
|
|
'truncate/replace 'append 'update
|
|
'can-update 'must-truncate)
|
|
'error])
|
|
(bytes? boolean? input-port? . -> . any)]{
|
|
|
|
Creates a @exec{zip} entry reader that can be used with either
|
|
@racket[unzip] or @racket[unzip-entry] and whose behavior is to save
|
|
entries to the local filesystem. Intermediate directories are always
|
|
created if necessary before creating files. Directory entries are
|
|
created as directories in the filesystem, and their entry contents are
|
|
ignored.
|
|
|
|
If @racket[dest-path] is not @racket[#f], every path in the archive is
|
|
prefixed to determine the destination path of the extracted entry.
|
|
|
|
If @racket[strip-count] is positive, then @racket[strip-count] path
|
|
elements are removed from the entry path from the archive (before
|
|
prefixing the path with @racket[dest-path]); if the item's path
|
|
contains @racket[strip-count] elements, then it is not extracted.
|
|
|
|
If @racket[exists] is @racket['skip] and the file for an entry already
|
|
exists, then the entry is skipped. Otherwise, @racket[exists] is
|
|
passed on to @racket[open-output-file] for writing the entry's
|
|
inflated content.}
|
|
|
|
|
|
@defproc[(read-zip-directory [in (or/c path-string? input-port?)]) zip-directory?]{
|
|
|
|
Reads the central directory of a @exec{zip} file and generates a
|
|
@deftech{zip directory} representing the zip file's contents. If
|
|
@racket[in] is an input port, it must support position setting via
|
|
@racket[file-position].
|
|
|
|
This procedure performs limited I/O: it reads the list of entries from
|
|
the @exec{zip} file, but it does not inflate any of their
|
|
contents.}
|
|
|
|
@defproc[(zip-directory? [v any/c]) boolean?]{
|
|
|
|
Returns @racket[#t] if @racket[v] is a @tech{zip directory},
|
|
@racket[#f] otherwise.}
|
|
|
|
|
|
@defproc[(zip-directory-entries [zipdir zip-directory?]) (listof bytes?)]{
|
|
|
|
Extracts the list of entries for a @exec{zip} archive.}
|
|
|
|
|
|
@defproc[(zip-directory-contains? [zipdir zip-directory?]
|
|
[name (or/c bytes? path-string?)])
|
|
boolean?]{
|
|
|
|
Determines whether the given entry name occurs in the given @tech{zip
|
|
directory}. If @racket[name] is not a byte string, it is converted
|
|
using @racket[path->zip-path].
|
|
|
|
Directory entries match with or without trailing slashes.}
|
|
|
|
|
|
@defproc[(zip-directory-includes-directory? [zipdir zip-directory?]
|
|
[name (or/c bytes? path-string?)])
|
|
boolean?]{
|
|
|
|
Determines whether the given name is included anywhere in the given
|
|
@tech{zip directory} as a filesystem directory, either as an entry
|
|
itself or as the containing directory of other entries. If
|
|
@racket[name] is not a byte string, it is converted using
|
|
@racket[path->zip-path].}
|
|
|
|
|
|
@defproc[(unzip-entry [path (or/c path-string? input-port?)]
|
|
[zipdir zip-directory?]
|
|
[entry (or/c bytes? path-string?)]
|
|
[entry-reader (bytes? boolean? input-port? . -> . any)
|
|
(make-filesystem-entry-reader)])
|
|
void?]{
|
|
|
|
Unzips a single entry from a @exec{zip} archive based on a previously
|
|
read @tech{zip directory}, @racket[zipdir], from
|
|
@racket[read-zip-directory]. If @racket[in] is an input port, it must
|
|
support position setting via @racket[file-position].
|
|
|
|
The @racket[entry] parameter is a byte string whose name must be found
|
|
in the zip file's central directory. If @racket[entry] is not a byte
|
|
string, it is converted using @racket[path->zip-path].
|
|
|
|
The @racket[read-entry] argument is used to read the contents of the zip entry
|
|
in the same way as for @racket[unzip].
|
|
|
|
If @racket[entry] is not in @racket[zipdir], an
|
|
@racket[exn:fail:unzip:no-such-entry] exception is raised.}
|
|
|
|
|
|
@defproc[(path->zip-path [path path-string?]) bytes?]{
|
|
|
|
Converts a file name potentially containing path separators in the current
|
|
platform's format to use path separators recognized by the zip file
|
|
format: @litchar{/}.}
|
|
|
|
|
|
@defstruct[(exn:fail:unzip:no-such-entry exn:fail) ([entry bytes?])]{
|
|
|
|
Raised when a requested entry cannot be found in a @exec{zip}
|
|
archive. The @racket[entry] field is a byte string representing the
|
|
requested entry name.}
|