- NAME
- zipfs — Mount and work with ZIP files within Tcl
- SYNOPSIS
- DESCRIPTION
- zipfs
canonical ?mountpoint? filename
?inZipfs?
- zipfs
exists filename
- zipfs
find directoryName
- zipfs
info file
- zipfs
list ?(-glob|-regexp)? ?pattern?
- zipfs
mount
- zipfs
mount mountpoint
- zipfs
mount zipfile mountpoint ?password?
- zipfs
mountdata data mountpoint
- zipfs
root
- zipfs
unmount mountpoint
- ZIP CREATION
COMMANDS
- zipfs
mkzip outfile indir ?strip?
?password?
- zipfs
mkimg outfile indir ?strip? ?password?
?infile?
- zipfs
mkkey password
- zipfs
lmkimg outfile inlist ?password?
?infile?
- zipfs
lmkzip outfile inlist ?password?
- NOTE
- EXAMPLES
- SEE
ALSO
- KEYWORDS
zipfs — Mount and work with ZIP files within Tcl
zipfs canonical ?mountpoint? filename
?ZIPFS?
zipfs exists filename
zipfs find directoryName
zipfs info filename
zipfs list ?(-glob|-regexp)?
?pattern?
zipfs lmkimg outfile inlist ?password?
?infile?
zipfs lmkzip outfile inlist ?password?
zipfs mkimg outfile indir ?strip?
?password? ?infile?
zipfs mkkey password
zipfs mkzip outfile indir ?strip?
?password?
zipfs mount ?zipfile? ?mountpoint?
?password?
zipfs mountdata data mountpoint
zipfs root
zipfs unmount mountpoint
The zipfs command provides Tcl with the ability to mount the
contents of a ZIP archive file as a virtual file system. Tcl's ZIP
archive support is limited to basic features and options. Supported
storage methods include only STORE and DEFLATE with optional simple
encryption, sufficient to prevent casual inspection of their
contents but not able to prevent access by even a moderately
determined attacker. Strong encryption, multi-part archives,
platform metadata, zip64 formats and other compression methods like
bzip2 are not supported.
Files within mounted archives can be written to but new files or
directories cannot be created. Further, modifications to files are
limited to the mounted archive in memory and are not persisted to
disk.
Paths in mounted archives are case-sensitive on all
platforms.
- zipfs canonical ?mountpoint?
filename ?inZipfs?
- This takes the name of a file, filename, and produces
where it would be mapped into a zipfs mount as its result. If
specified, mountpoint says within which mount the mapping
will be done; if omitted, the main root of the zipfs system is
used. The inZipfs argument is a an optional boolean which
controls whether to fully canonicalize the name; it defaults to
true.
- zipfs exists
filename
- Return 1 if the given filename exists in the mounted zipfs and
0 if it does not.
- zipfs find
directoryName
- Returns the list of paths under directory directoryName
which need not be within a zipfs mounted archive. The paths are
prefixed with directoryName. This command is also used by
the zipfs mkzip and zipfs mkimg commands.
- zipfs info file
- Return information about the given file in the mounted
zipfs. The information consists of:
- the name of the ZIP archive file that contains the
file,
- the size of the file after decompressions,
- the compressed size of the file, and
- the offset of the compressed data in the ZIP archive
file.
As a special case, querying the mount point gives the start of
the zip data as the offset in (4), which can be used to truncate
the zip information from an executable. Querying an ancestor of a
mount point will raise an error.
- zipfs list
?(-glob|-regexp)? ?pattern?
- If pattern is not specified, the command returns a list
of files across all zipfs mounted archives. If pattern is
specified, only those paths matching the pattern are returned. By
default, or with the -glob option, the pattern is treated as
a glob pattern and matching is done as described for the
string match command.
Alternatively, the -regexp option may be used to specify
matching pattern as a regular expression. The file names are
returned in arbitrary order. Note that path separators are treated
as ordinary characters in the matching. Thus forward slashes should
be used as path separators in the pattern. The returned paths only
include those actually in the archive and does not include
intermediate directories in mount paths.
- zipfs mount
- zipfs mount
mountpoint
- zipfs mount zipfile
mountpoint ?password?
-
The zipfs mount command mounts ZIP archives as Tcl
virtual file systems and returns information about current
mounts.
With no arguments, the command returns a dictionary mapping
mount points to the path of the corresponding ZIP archive.
In the single argument form, the command returns the file path
of the ZIP archive mounted at the specified mount point.
In the third form, the command mounts the ZIP archive
zipfile as a Tcl virtual filesystem at mountpoint.
After this command executes, files contained in zipfile will
appear to Tcl to be regular files at the mount point. If
mountpoint is specified as an empty string, it is defaulted
to the [zipfs root]. The command returns the normalized
mount point path.
If not under the zipfs file system root, mountpoint is
normalized with respect to it. For example, a mount point passed as
either mt or /mt would be normalized to
//zipfs:/mt (given that zipfs root returns
“//zipfs:/”). An error is raised if the mount point includes a
drive or UNC volume.
NB: because the current working directory is a concept
maintained by the operating system, using cd into a mounted archive will only
work in the current process, and then not entirely consistently
(e.g., if a shared library uses direct access to the OS rather than
through Tcl's filesystem API, it will not see the current directory
as being inside the mount and will not be able to access the files
inside the mount).
- zipfs mountdata data
mountpoint
- Mounts the ZIP archive content data as a Tcl virtual
filesystem at mountpoint.
- zipfs root
- Returns a constant string which indicates the mount point for
zipfs volumes for the current platform. User should not rely on the
mount point being the same constant string for all platforms.
- zipfs unmount
mountpoint
- Unmounts a previously mounted ZIP archive mounted to
mountpoint. The command will fail with an error exception if
there are any files within the mounted archive are open.
This package also provides several commands to aid the creation of
ZIP archives as Tcl applications.
- zipfs mkzip outfile indir
?strip? ?password?
- Creates a ZIP archive file named outfile from the
contents of the input directory indir (contained regular
files only) with optional ZIP password password. While
processing the files below indir the optional file name
prefix given in strip is stripped off the beginning of the
respective file name if non-empty. When stripping, it is common to
remove either the whole source directory name or the name of its
parent directory.
Caution: the choice of the indir parameter (less
the optional stripped prefix) determines the later root name of the
archive's content.
- zipfs mkimg outfile indir
?strip? ?password? ?infile?
- Creates an image (potentially a new executable file) similar to
zipfs mkzip; see that command for a description of most
parameters to this command, as they behave identically here. If
outfile exists, it will be silently overwritten.
If the infile parameter is specified, this file is
prepended in front of the ZIP archive, otherwise the file returned
by info nameofexecutable
(i.e., the executable file of the running process, typically
wish or tclsh) is
used. If the password parameter is not the empty string, an
obfuscated version of that password (see zipfs mkkey) is
placed between the image and ZIP chunks of the output file and the
contents of the ZIP chunk are protected with that password. If the
starting image has a ZIP archive already attached to it, it is
removed from the copy in outfile before the new ZIP archive
is added.
If there is a file, main.tcl, in the root directory of
the resulting archive and the image file that the archive is
attached to is a tclsh
(or wish) instance (true by default, but depends on your
configuration), then the resulting image is an executable that will
source the script in
that main.tcl after mounting the ZIP archive, and will
exit once that script has
been executed.
Note: tclsh
and wish can be built using either dynamic binding or static
binding of the core implementation libraries. With a dynamic
binding, the base application Tcl_Library contents are attached to
the libtcl and libtk shared library, respectively.
With a static binding, the Tcl_Library contents, etc., are attached
to the application, tclsh or wish. When using
mkimg with a statically built tclsh, it is the user's
responsibility to preserve the attached archive by first extracting
it to a temporary location, and then add whatever additional files
desired, before creating and attaching the new archive to the new
application.
- zipfs mkkey
password
- Given the clear text password argument, an obfuscated
string version is returned with the same format used in the
zipfs mkimg command.
- zipfs lmkimg outfile
inlist ?password? ?infile?
- This command is like zipfs mkimg, but instead of an
input directory, inlist must be a Tcl list where the odd
elements are the names of files to be copied into the archive in
the image, and the even elements are their respective names within
that archive.
- zipfs lmkzip outfile
inlist ?password?
- This command is like zipfs mkzip, but instead of an
input directory, inlist must be a Tcl list where the odd
elements are the names of files to be copied into the archive, and
the even elements are their respective names within that
archive.
The current syntax for certain subcommands using multiple optional
parameters might change in the future to support an ?-option
value? pattern instead. Therfore, the current syntax should not
be considered stable.
Mounting an ZIP archive as an application directory and running
code out of it before unmounting it again:
set zip myApp.zip
set base [file join [zipfs root] myApp]
zipfs mount $zip $base
# $base now has the contents of myApp.zip
source [file join $base app.tcl]
# use the contents, load libraries from it, etc...
zipfs unmount $base
Creating a ZIP archive, given that a directory exists containing
the content to put in the archive. Note that the source directory
is given twice, in order to strip the exterior directory name from
each filename in the archive.
set sourceDirectory [file normalize myApp]
set targetZip myApp.zip
zipfs mkzip $targetZip $sourceDirectory $sourceDirectory
Encryption can be applied to ZIP archives by providing a
password when building the ZIP and when mounting it.
set zip myApp.zip
set sourceDir [file normalize myApp]
set password "hunter2"
set base [file join [zipfs root] myApp]
# Create with password
zipfs mkzip $targetZip $sourceDir $sourceDir $password
# Mount with password
zipfs mount $zip $base $password
The following example creates an executable application by
appending a ZIP archive to the tclsh file it was called from and
storing the resulting executable in the file “myApp.bin”. When
creating an executable image with a password, the password is
placed within the executable in a shrouded form so that the
application can read files inside the embedded ZIP archive yet
casual inspection cannot read it.
set appDir [file normalize myApp]
set img "myApp.bin"
set password "hunter2"
# Create some simple content to define a basic application
file mkdir $appDir
set f [open $appDir/main.tcl w]
puts $f {
puts "Hi. This is [info script]"
}
close $f
# Create the executable application
zipfs mkimg $img $appDir $appDir $password
# remove the now obsolete temporary appDir folder
file delete -force $appDir
# Launch the executable, printing its output to stdout
exec $img >@stdout
# prints the following line assuming [zipfs root] returns "//zipfs:/":
# Hi. This is //zipfs:/app/main.tcl
tclsh, file, zipfs, zlib
compress, filesystem, zip
Copyright © 2015 Jan Nijtmans
<jan.nijtmans(at)gmail.com>
Copyright © 2015 Christian Werner <chw(at)ch-werner.de>
Copyright © 2015 Sean Woods <yoda(at)etoyoc.com>