\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#430: Add basic ZIP archive support to Tcl}
\date{September 03, 2014}
\author{Sean Woods, Donal Fellows, Poor Yorick, Harald Oehlmann}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#430}&\textbf{Add basic ZIP archive support to Tcl}\\\hline
Author&

Sean Woods \tipmail{yoda}{etoyoc.com}
\par
Donal Fellows \tipmail{donal.k.fellows}{manchester.ac.uk}
\par
Poor Yorick \tipmail{tk.tcl.tip}{pooryorick.com}
\par
Harald Oehlmann \tipmail{oehhar}{users.sourceforge.net}
\\
Created&Wednesday, \(\text{3}^{\text{rd}}\) September 2014\\
Type&Project\\
Tcl Version&\(8.6.3\)\\
State&Draft\\
Vote&Pending\\
Version&\tipversion$Revision: 1.6 $\\
Keywords&virtual filesystem, zip, tclkit, boot, bootstrap\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This proposal will add basic support for mounting zip archive files as virtual filesystems to the Tcl core.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Target Tcl-Version}

This TIP targets TCL Version 8.7 or 9.0, whatever comes first.

\section{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 \textit{init.tcl}, which would mean that the filesystem containing \textit{init.tcl} is not present until after TclVfs mounts it yet that mount cannot happen until after \textit{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, \cite{tip244}), 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.

\section{Specification}

There shall be new commands added to safe interpreters withing Tcl. All of which shall be in the \textbf{::zvfs} namespace. These commands shall include:
\begin{itemize}
\item{}
\textbf{zvfs::mount} ?\textit{archive}? ?\textit{mountpoint}?

Mounts the ZIP file \textit{archive} at the location given by \textit{mountpoint}, which will default to \textit{'zipfs:}/\textit{archive} if absent. With no arguments this command describes all current mounts, returning a list of pairs.
\item{}
\textbf{zvfs::unmount} \textit{archive}

Unmounts the ZIP file \textit{archive}, which must have been previously mounted.
\end{itemize}

Safe interpreters will not be given the mount or unmount commands. Already mounted file systems will be available via the \textbf{glob} and \textbf{file} commands. These commands, and any commands related to building archives will be marked with the unsafe bit within the \textbf{zipfs} ensemble, and will be removed from any interpreter through the normal mechanism to hide unsafe commands within the core.

\section{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 (\textit{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 ``\textit{main.tcl}'' as well as the initial file systems for both Tcl and Tk.

This work is checked in as the ``\textit{core\_zip\_vfs}'' branch on both Tcl and Tk.

\section{C API}

* \textbf{int TclZipfsInit(Tcl\_Interp *interp);} \tiprangle{} Initializes the C API for Zipfs. If called with a non-null \textit{interp}, adds the commands for the zipfs Tcl API to the interpreter. Returns \textbf{TCL\_OK} on success, and \textbf{TCL\_ERROR} in all other cases.

* \textbf{int TclZipfsMount(Tcl\_Interp *interp, const char *zipname, const char *mntpt, const char *passwd);} \tiprangle{} Mounts a zip file \textit{zipname} to the mount point \textit{mntpt}. If \textit{passwd} is non-null, that string is utilized as the password to decrypt the contents. \textit{mnpnt} will always be relative to \textbf{zipfs:}

* \textbf{int TclZipfsUnmount(Tcl\_Interp *interp, const char *zipname);} \tiprangle{} Unmount the file system created by a prior call to \textbf{TclZipfsMount()}

\section{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 \textbf{zipfs:/app}. * If \(''\)zipfs:/app" is present the interpreter will look for \textbf{boot/tcl/init.tcl}. If that file is present, the location for \textbf{\$tcl\_library} will be set to \textbf{zipfs:/app/boot/tcl}. * If \textit{zipfs:/app} is present the interpreter will look for \textbf{boot/tk/tk.tcl'. If present the location for }\$tk\_library\textbf{ will be set to }zipfs:/boot/tk\textbf{. * If the file }pkgIndex.tcl\textbf{ is present, the }\$dir\textbf{ variable will be set to }zipfs:/app\textbf{ and the file will be sourced as if it were a package index. * If the file }main.tcl\textbf{ is present, the file }zipfs://app/main.tcl\textbf{ will be registered with }Tcl\_SetStartupScript()\('''\)

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\begin{thebibliography}{TIP \#1}
\addcontentsline{toc}{section}{References}
\bibitem[TIP \#244]{tip244}
Michael Kirkham,
\emph{PNG Photo Image Support for Tk},
on-line at \url{http://purl.org/tcl/tip/244.html}
\end{thebibliography}
\end{document}
