'\" '\" Copyright (c) 2015 Jan Nijtmans '\" Copyright (c) 2015 Christian Werner '\" Copyright (c) 2015 Sean Woods '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH zipfs n 1.0 Zipfs "zipfs Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME zipfs \- Mount and work with ZIP files within Tcl .SH SYNOPSIS .nf \fBpackage require tcl::zipfs \fR?\fB1.0\fR? .sp \fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR ?\fIZIPFS\fR? \fBzipfs exists\fR \fIfilename\fR \fBzipfs find\fR \fIdirectoryName\fR \fBzipfs info\fR \fIfilename\fR \fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR? \fBzipfs lmkimg\fR \fIoutfile inlist\fR ?\fIpassword infile\fR? \fBzipfs lmkzip\fR \fIoutfile inlist\fR ?\fIpassword\fR? \fBzipfs mkimg\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR? \fBzipfs mkkey\fR \fIpassword\fR \fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? \fBzipfs mount\fR ?\fIzipfile\fR? ?\fImountpoint\fR? ?\fIpassword\fR? \fBzipfs root\fR \fBzipfs unmount\fR \fImountpoint\fR .fi '\" The following subcommand is *UNDOCUMENTED* '\" \fBzipfs mount_data\fR ?\fIdata\fR ?\fImountpoint\fR?? .BE .SH DESCRIPTION .PP The \fBzipfs\fR 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. .PP 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. .PP Paths in mounted archives are case-sensitive on all platforms. .TP \fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR ?\fIinZipfs\fR? . This takes the name of a file, \fIfilename\fR, and produces where it would be mapped into a zipfs mount as its result. If specified, \fImountpoint\fR says within which mount the mapping will be done; if omitted, the main root of the zipfs system is used. The \fIinZipfs\fR argument is a an optional boolean which controls whether to fully canonicalize the name; it defaults to true. .TP \fBzipfs exists\fR \fIfilename\fR . Return 1 if the given filename exists in the mounted zipfs and 0 if it does not. .TP \fBzipfs find\fR \fIdirectoryName\fR . Returns the list of paths under directory \fIdirectoryName\fR which need not be within a zipfs mounted archive. The paths are prefixed with \fIdirectoryName\fR. This command is also used by the \fBzipfs mkzip\fR and \fBzipfs mkimg\fR commands. .TP \fBzipfs info\fR \fIfile\fR . Return information about the given \fIfile\fR in the mounted zipfs. The information consists of: .RS .IP (1) the name of the ZIP archive file that contains the file, .IP (2) the size of the file after decompressions, .IP (3) the compressed size of the file, and .IP (4) the offset of the compressed data in the ZIP archive file. .PP 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. .RE .TP \fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR? . If \fIpattern\fR is not specified, the command returns a list of files across all zipfs mounted archives. If \fIpattern\fR is specified, only those paths matching the pattern are returned. By default, or with the \fB\-glob\fR option, the pattern is treated as a glob pattern and matching is done as described for the \fBstring match\fR command. Alternatively, the \fB\-regexp\fR option may be used to specify matching \fBpattern\fR 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. .TP \fBzipfs mount\fR .TP \fBzipfs mount\fR \fImountpoint\fR .TP \fBzipfs mount\fR \fIzipfile\fR \fImountpoint\fR ?\fIpassword\fR? .RS .PP The \fBzipfs mount\fR command mounts ZIP archives as Tcl virtual file systems and returns information about current mounts. .PP With no arguments, the command returns a dictionary mapping mount points to the path of the corresponding ZIP archive. .PP In the single argument form, the command returns the file path of the ZIP archive mounted at the specified mount point. .PP In the third form, the command mounts the ZIP archive \fIzipfile\fR as a Tcl virtual filesystem at \fImountpoint\fR. After this command executes, files contained in \fIzipfile\fR will appear to Tcl to be regular files at the mount point. If \fImountpoint\fR is specified as an empty string, it is defaulted to the \fB[zipfs root]\fR. The command returns the normalized mount point path. .PP If not under the zipfs file system root, \fImountpoint\fR is normalized with respect to it. For example, a mount point passed as either \fBmt\fR \fB/mt\fR would be normalized to \fB//zipfs:/mt\fR. An error is raised if the mount point includes a drive or UNC volume. .PP \fBNB:\fR because the current working directory is a concept maintained by the operating system, using \fBcd\fR 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). .RE .TP \fBzipfs root\fR . Returns a constant string which indicates the mount point for zipfs volumes for the current platform. This value is .QW \fB//zipfs:/\fR on most platforms. .TP \fBzipfs unmount \fImountpoint\fR . Unmounts a previously mounted ZIP archive mounted to \fImountpoint\fR. The command will fail with an error exception if there are any files within the mounted archive are open. .SS "ZIP CREATION COMMANDS" This package also provides several commands to aid the creation of ZIP archives as Tcl applications. .TP \fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? . Creates a ZIP archive file named \fIoutfile\fR from the contents of the input directory \fIindir\fR (contained regular files only) with optional ZIP password \fIpassword\fR. While processing the files below \fIindir\fR the optional file name prefix given in \fIstrip\fR is stripped off the beginning of the respective file name. When stripping, it is common to remove either the whole source directory name or the name of its parent directory. .RS .PP \fBCaution:\fR the choice of the \fIindir\fR parameter (less the optional stripped prefix) determines the later root name of the archive's content. .RE .TP \fBzipfs mkimg\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR? . Creates an image (potentially a new executable file) similar to \fBzipfs mkzip\fR; see that command for a description of most parameters to this command, as they behave identically here. .RS .PP If the \fIinfile\fR parameter is specified, this file is prepended in front of the ZIP archive, otherwise the file returned by \fBinfo nameofexecutable\fR (i.e., the executable file of the running process) is used. If the \fIpassword\fR parameter is not empty, an obfuscated version of that password (see \fBzipfs mkkey\fR) 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 \fIoutfile\fR before the new ZIP archive is added. .PP If there is a file, \fBmain.tcl\fR, in the root directory of the resulting archive and the image file that the archive is attached to is a \fBtclsh\fR (or \fBwish\fR) instance (true by default, but depends on your configuration), then the resulting image is an executable that will \fBsource\fR the script in that \fBmain.tcl\fR after mounting the ZIP archive, and will \fBexit\fR once that script has been executed. .PP \fBNote:\fR \fBtclsh\fR and \fBwish\fR 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 \fBlibtcl\fR and \fBlibtk\fR shared library, respectively. With a static binding, the Tcl_Library contents, etc., are attached to the application, \fBtclsh\fR or \fBwish\fR. When using \fBmkimg\fR 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. .PP \fBCaution:\fR highly experimental, not usable on Android, only partially tested on Linux and Windows. .RE .TP \fBzipfs mkkey\fR \fIpassword\fR . Given the clear text \fIpassword\fR argument, an obfuscated string version is returned with the same format used in the \fBzipfs mkimg\fR command. .TP \fBzipfs lmkimg\fR \fIoutfile inlist\fR ?\fIpassword infile\fR? . This command is like \fBzipfs mkimg\fR, but instead of an input directory, \fIinlist\fR 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. .TP \fBzipfs lmkzip\fR \fIoutfile inlist\fR ?\fIpassword\fR? . This command is like \fBzipfs mkzip\fR, but instead of an input directory, \fIinlist\fR 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. .SH "EXAMPLES" .PP Mounting an ZIP archive as an application directory and running code out of it before unmounting it again: .PP .CS set zip myApp.zip set base [file join [\fBzipfs root\fR] myApp] \fBzipfs mount\fR $zip $base # $base now has the contents of myApp.zip source [file join $base app.tcl] # use the contents, load libraries from it, etc... \fBzipfs unmount\fR $base .CE .PP 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. .PP .CS set sourceDirectory [file normalize myApp] set targetZip myApp.zip \fBzipfs mkzip\fR $targetZip $sourceDirectory $sourceDirectory .CE .PP Encryption can be applied to ZIP archives by providing a password when building the ZIP and when mounting it. .PP .CS set zip myApp.zip set sourceDir [file normalize myApp] set password "hunter2" set base [file join [\fBzipfs root\fR] myApp] # Create with password \fBzipfs mkzip\fR $targetZip $sourceDir $sourceDir $password # Mount with password \fBzipfs mount\fR $zip $base $password .CE .PP 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. .PP .CS 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] puts $f { puts "Hi. This is [info script]" } close $f # Create the executable \fBzipfs mkimg\fR $img $appDir $appDir $password # Launch the executable, printing its output to stdout exec $img >@stdout # prints: \fIHi. This is //zipfs:/app/main.tcl\fR .CE .SH "SEE ALSO" tclsh(1), file(n), zipfs(3), zlib(n) .SH "KEYWORDS" compress, filesystem, zip '\" Local Variables: '\" mode: nroff '\" End: