TIP: 430 Title: Add basic ZIP archive support to Tcl Version: $Revision: 1.6 $ Author: Sean Woods Author: Donal Fellows Author: Poor Yorick Author: Harald Oehlmann State: Draft Type: Project Vote: Pending Created: 03-Sep-2014 Post-History: Keywords: virtual filesystem,zip,tclkit,boot,bootstrap Tcl-Version: 8.6.3 ~ Abstract This proposal will add basic support for mounting zip archive files as virtual filesystems to the Tcl core. ~ Target Tcl-Version This TIP targets TCL Version 8.7 or 9.0, whatever comes first. ~ Rationale 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, [244]), 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. ~ Specification 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. * '''zvfs::unmount''' ''archive'' > 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. ~ Implementation 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. ~ C API * '''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 utilized as the password to decrypt the contents. ''mnpnt'' 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()''' ~ Bootstraping 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()''' ~ Copyright This document has been placed in the public domain.