Author: Sean Woods <firstname.lastname@example.org> Author: Donal Fellows <email@example.com> Author: Poor Yorick <firstname.lastname@example.org> Author: Harald Oehlmann <email@example.com> State: Draft Type: Project Vote: Pending Created: 03-Sep-2014 Post-History: Keywords: virtual filesystem,zip,tclkit,boot,bootstrap Tcl-Version: 8.6.3
This proposal will add basic support for mounting zip archive files as virtual filesystems to the Tcl core.
This TIP targets TCL Version 8.7 or 9.0, whatever comes first.
Tcl/Tk relies on the presence of a file system containing Tcl scripts for bootstrapping the interpreter. When dealing with code packed in a self-contained executable, a chicken-and-egg problem arises when developers try to provide this bootstrap from their attached VFS with extensions like TclVfs. TclVfs runs in the Tcl interpreter. The interpreter needs init.tcl, which would mean that the filesystem containing init.tcl is not present until after TclVfs mounts it yet that mount cannot happen until after init.tcl has been loaded. Bootstrap filesystem mounts require built-in support for the filesystem that they use.
With the inclusion of Zlib in the core (starting with 8.6, ), all that is required to implement a zip file system based VFS is to add a C-level VFS implementation to decode the zip archive format. Thus: this project.
Note that we are prioritizing the zip archive format also because it is practical to generate the files without a Tcl installation being present; it is a format with widespread OS support. This makes it much easier to bootstrap a build of Tcl that uses it without requiring a native build of tclsh to be present.
There shall be new commands added to safe interpreters withing Tcl. All of which shall be in the ::zvfs namespace. These commands shall include:
zvfs::mount ?archive? ?mountpoint?
Mounts the ZIP file archive at the location given by mountpoint, which will default to zipfs:/archive if absent. With no arguments this command describes all current mounts, returning a list of pairs.
Unmounts the ZIP file archive, which must have been previously mounted.
Safe interpreters will not be given the mount or unmount commands. Already mounted file systems will be available via the glob and file commands. These commands, and any commands related to building archives will be marked with the unsafe bit within the zipfs ensemble, and will be removed from any interpreter through the normal mechanism to hide unsafe commands within the core.
I have adapted Richard Hipp's work on Tcl As One Big Executable (TOBE) to operate inside of a modern Tcl. That implementation consists of one C file (tclZipvfs.c). I have also prepared new behaviors for inside of Tcl_AppInit() to detect if a zip filesystem is attached to the current executable, and how to extract a "main.tcl" as well as the initial file systems for both Tcl and Tk.
This work is checked in as the "core_zip_vfs" branch on both Tcl and Tk.
int TclZipfsInit(Tcl_Interp *interp);
Initializes the C API for Zipfs. If called with a non-null interp, adds the commands for the zipfs Tcl API to the interpreter. Returns TCL_OK on success, and TCL_ERROR in all other cases.
int TclZipfsMount(Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd);
Mounts a zip file zipname to the mount point mntpt. If passwd is non-null, that string is used as the password to decrypt the contents. mntpnt will always be relative to zipfs:
int TclZipfsUnmount(Tcl_Interp *interp, const char *zipname);
Unmount the file system created by a prior call to TclZipfsMount()
The mount and unmount commands are usable within the core as just another feature engine. A call to TclZipfsInit() will be inserted into tclBasic.c, immediately after the code to initialize zlib.
A modified shell (
tclkit.exe) will be generated by Make. This shell will:
Check if the executable has a zip archive attached. If so, that archive shall be mounted as zipfs:/app.
If zipfs:/app is present the interpreter will look for boot/tcl/init.tcl. If that file is present, the location for $tcl_library will be set to zipfs:/app/boot/tcl.
If zipfs:/app is present the interpreter will look for boot/tk/tk.tcl. If present the location for $tk_library will be set to zipfs:/boot/tk.
If the file pkgIndex.tcl is present, the $dir variable will be set to zipfs:/app and the file will be sourced as if it were a package index.
If the file main.tcl is present, the file zipfs://app/main.tcl will be registered with Tcl_SetStartupScript()
This document has been placed in the public domain.