summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/zipfs.330
-rw-r--r--doc/zipfs.n127
-rw-r--r--generic/tcl.decls17
-rw-r--r--generic/tcl.h7
-rw-r--r--generic/tclDecls.h21
-rw-r--r--generic/tclIOCmd.c2
-rw-r--r--generic/tclIOUtil.c8
-rw-r--r--generic/tclStubInit.c2
-rw-r--r--generic/tclZipfs.c2597
-rw-r--r--generic/tclZlib.c6
-rw-r--r--tests/zipfs.test121
-rw-r--r--unix/Makefile.in4
-rw-r--r--win/tclWin32Dll.c8
13 files changed, 1543 insertions, 1407 deletions
diff --git a/doc/zipfs.3 b/doc/zipfs.3
index 568f461..8e2eacc 100644
--- a/doc/zipfs.3
+++ b/doc/zipfs.3
@@ -10,7 +10,7 @@
.so man.macros
.BS
.SH NAME
-TclZipfs_AppHook, Tclzipfs_Mount, Tclzipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
+TclZipfs_AppHook, Tclzipfs_Mount, TclZipfs_MountBuffer, Tclzipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
.SH SYNOPSIS
.nf
int
@@ -20,7 +20,10 @@ int
\fBTclzipfs_Mount\fR(\fIinterp, mountpoint, zipname, password\fR)
.sp
int
-\fBTclzipfs_Unmount\fR(\fIinterp, zipname\fR)
+\fBTclZipfs_MountBuffer\fR(\fIinterp, mountpoint, data, dataLen, copy\fR)
+.sp
+int
+\fBTclzipfs_Unmount\fR(\fIinterp, mountpoint\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *mountpoint in
@@ -40,6 +43,16 @@ Name of a mount point, which must be a legal Tcl file or directory name. May
be NULL to query current mount points.
.AP "const char" *password in
An (optional) password. Use NULL if no password is wanted to read the file.
+.AP "unsigned char" *data in
+A data buffer to mount. The data buffer must hold the contents of a ZIP
+archive, and must not be NULL.
+.AP size_t dataLen in
+The number of bytes in the supplied data buffer argument, \fIdata\fR.
+.AP int copy in
+If non-zero, the ZIP archive in the data buffer will be internally copied
+before mounting, allowing the data buffer to be disposed once
+\fBTclZipfs_MountBuffer\fR returns. If zero, the caller guarantees that the
+buffer will be valid to read from for the duration of the mount.
.BE
.SH DESCRIPTION
\fBTclZipfs_AppHook\fR is a utility function to perform standard application
@@ -85,11 +98,20 @@ given in \fImountpoint\fR using the optional ZIP password \fIpassword\fR.
Errors during that process are reported in the interpreter \fIinterp\fR. If
\fImountpoint\fR is a NULL pointer, information on all currently mounted ZIP
file systems is written into \fIinterp\fR's result as a sequence of mount
-points and ZIP file names.
+points and ZIP file names. The result of this call is a standard Tcl result
+code.
+.PP
+\fBTclzipfs_MountBuffer\fR mounts the ZIP archive in the buffer pointed to by
+\fIdata\fR on the mount point given in \fImountpoint\fR. The ZIP archive is
+assumed to be not password protected. Errors during that process are reported
+in the interpreter \fIinterp\fR. The \fIcopy\fR argument determines whether
+the buffer is internally copied before mounting or not. The result of this
+call is a standard Tcl result code.
.PP
\fBTclzipfs_Unmount\fR undoes the effect of \fBTclzipfs_Mount\fR, i.e., it
unmounts the mounted ZIP file system that was mounted from \fIzipname\fR (at
-\fImountpoint\fR). Errors are reported in the interpreter \fIinterp\fR.
+\fImountpoint\fR). Errors are reported in the interpreter \fIinterp\fR. The
+result of this call is a standard Tcl result code.
.SH "SEE ALSO"
zipfs(n)
.SH KEYWORDS
diff --git a/doc/zipfs.n b/doc/zipfs.n
index 31a0707..3600e64 100644
--- a/doc/zipfs.n
+++ b/doc/zipfs.n
@@ -19,19 +19,20 @@ zipfs \- Mount and work with ZIP files within Tcl
\fBzipfs exists\fR \fIfilename\fR
\fBzipfs find\fR \fIdir\fR
\fBzipfs info\fR \fIfilename\fR
-\fBzipfs list\fR \fB?(-glob|-regexp)?\fR \fI?pattern?\fR
-\fBzipfs mkimg\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR \fI?infile?\fR
+\fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR?
+\fBzipfs mkimg\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR?
\fBzipfs mkkey\fR \fIpassword\fR
-\fBzipfs mkzip\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR
-\fBzipfs mount\fR \fI?mountpoint?\fR \fI?zipfile?\fR \fI?password?\fR
+\fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR?
+\fBzipfs mount\fR ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR?
\fBzipfs root\fR
\fBzipfs unmount\fR \fImountpoint\fR
.fi
.BE
.SH DESCRIPTION
.PP
-The \fBzipfs\fR package provides tcl with the ability to mount
-the contents of a zip file as a virtual file system.
+The \fBzipfs\fR command (the sole public command provided by the built-in
+package with the same name) provides Tcl with the ability to mount the
+contents of a ZIP file as a virtual file system.
.TP
\fBzipfs exists\fR \fIfilename\fR
.
@@ -39,50 +40,84 @@ Return 1 if the given filename exists in the mounted zipfs and 0 if it does not.
.TP
\fBzipfs find\fR \fIdir\fR
.
-Recursively lists files including and below the directory \fIdir\fR.
-The result list consists of relative path names starting from the
-given directory. This command is also used by the \fBzipfs mkzip\fR
-and \fBzipfs mkimg\fR commands.
+Recursively lists files including and below the directory \fIdir\fR. The
+result list consists of relative path names starting from the given
+directory. 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 file in the mounted zipfs. The information
-consists of (1) the name of the ZIP archive file that contains the file,
-(2) the size of the file after decompressions, (3) the compressed size of
-the file, and (4) the offset of the compressed data in the ZIP archive file.
+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
-Note: querying the mount point gives the start of zip data offset in (4),
-which can be used to truncate the zip info off an executable.
+Note: 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.
.RE
.TP
-\fBzipfs list\fR \fB?(-glob|-regexp)?\fR \fI?pattern?\fR
+\fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? \fI?pattern?\fR
.
-Return a list of all files in the mounted zipfs. The order of the names
-in the list is arbitrary.
+Return a list of all files in the mounted zipfs, or just those matching
+\fIpattern\fR (optionally controlled by the option parameters). The order of
+the names in the list is arbitrary.
.TP
-\fBzipfs mkimg\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR \fI?infile?\fR
+\fBzipfs mount ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR?
+.
+The \fBzipfs mount\fR command mounts a ZIP archive file 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.
+.RS
+.PP
+With no \fIzipfile\fR, returns the zipfile mounted at \fImountpoint\fR. With
+no \fImountpoint\fR, return all zipfile/mount pairs. If \fImountpoint\fR is
+specified as an empty string, mount on file path.
+.RE
+.TP
+\fBzipfs root\fR
+.
+Returns a constant string which indicates the mount point for zipfs volumes
+for the current platform. On Windows, this value is
+.QW \fBzipfs:/\fR .
+On Unix, this value is
+.QW \fB//zipfs:/\fR .
+.RE
+.TP
+\fBzipfs unmount \fImountpoint\fR
+.
+Unmounts a previously mounted ZIP archive mounted to \fImountpoint\fR.
+.SS "ZIP CREATION COMMANDS"
+This package also provides several commands to aid the creation of ZIP
+archives as Tcl applications.
+.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. If the \fIinfile\fR parameter is specified,
-this file is prepended in front of the ZIP archive, otherwise the file
-returned by \fBTcl_NameOfExecutable(3)\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 is placed between the image and ZIP
-chunks of the output file and the contents of the ZIP chunk are protected
-with that password.
+Creates an image (potentially a new executable file) similar to \fBzipfs
+mkzip\fR. 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 is placed between the image and ZIP chunks of the output file
+and the contents of the ZIP chunk are protected with that password.
.RS
.PP
-Caution: highly experimental, not usable on Android, only partially tested
-on Linux and Windows.
+Caution: highly experimental, not usable on Android, only partially tested on
+Linux and Windows.
.RE
.TP
\fBzipfs mkkey\fR \fIpassword\fR
.
-For the clear text \fIpassword\fR argument an obfuscated string version
-is returned with the same format used in the \fBzipfs mkimg\fR command.
+For 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 mkzip\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR
+\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
@@ -91,31 +126,9 @@ optional file name prefix given in \fIstrip\fR is stripped off the beginning
of the respective file name.
.RS
.PP
-Caution: the choice of the \fIindir\fR parameter
-(less the optional stripped prefix) determines the later root name of the
-archive's content.
+Caution: 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 mount ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR?
-.
-The \fBzipfs mount\fR command mounts a ZIP archive file as a VFS.
-After this command executes, files contained in \fIzipfile\fR
-will appear to Tcl to be regular files at the mount point.
-.RS
-.PP
-With no \fIzipfile\fR, returns the zipfile mounted at \fImountpoint\fR.
-With no \fImountpoint\fR, return all zipfile/mount pairs.
-If \fImountpoint\fR is specified as an empty string, mount on file path.
-.RE
-.TP
-\fBzipfs root\fR
-Returns a constant string which indicates the mount point for zipfs volumes
-for the current platform. On Windows, this value is zipfs:/. On Unux, //zipfs:/
-.RE
-.TP
-\fBzipfs unmount \fImountpoint\fR
-.
-Unmounts a previously mounted ZIP archive mounted to \fImountpoint\fR.
.SH "SEE ALSO"
tclsh(1), file(n), zlib(n)
.SH "KEYWORDS"
diff --git a/generic/tcl.decls b/generic/tcl.decls
index 6352ae4..ede2aff 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -2378,25 +2378,18 @@ declare 631 {
# TIP #430
declare 632 {
- int TclZipfs_Mount(
- Tcl_Interp *interp,
- const char *mntpt,
- const char *zipname,
- const char *passwd)
+ int TclZipfs_Mount(Tcl_Interp *interp, const char *mountPoint,
+ const char *zipname, const char *passwd)
}
declare 633 {
- int TclZipfs_Unmount(Tcl_Interp *interp, const char *zipname)
+ int TclZipfs_Unmount(Tcl_Interp *interp, const char *mountPoint)
}
declare 634 {
Tcl_Obj *TclZipfs_TclLibrary(void)
}
declare 635 {
- int TclZipfs_Mount_Buffer(
- Tcl_Interp *interp,
- const char *mntpt,
- unsigned char *data,
- size_t datalen,
- int copy)
+ int TclZipfs_MountBuffer(Tcl_Interp *interp, const char *mountPoint,
+ unsigned char *data, size_t datalen, int copy)
}
# ----- BASELINE -- FOR -- 8.7.0 ----- #
diff --git a/generic/tcl.h b/generic/tcl.h
index d08b745..2fab295 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -2176,6 +2176,13 @@ typedef int (Tcl_ArgvGenFuncProc)(ClientData clientData, Tcl_Interp *interp,
#define TCL_TCPSERVER_REUSEPORT (1<<1)
/*
+ * Constants for special int-typed values, see TIP #494
+ */
+
+#define TCL_IO_FAILURE (-1)
+#define TCL_AUTO_LENGTH (-1)
+
+/*
*----------------------------------------------------------------------------
* Single public declaration for NRE.
*/
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index b2f7b69..56b6f81 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -1738,16 +1738,17 @@ EXTERN Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp,
Tcl_TcpAcceptProc *acceptProc,
ClientData callbackData);
/* 632 */
-EXTERN int TclZipfs_Mount(Tcl_Interp *interp, const char *mntpt,
- const char *zipname, const char *passwd);
+EXTERN int TclZipfs_Mount(Tcl_Interp *interp,
+ const char *mountPoint, const char *zipname,
+ const char *passwd);
/* 633 */
EXTERN int TclZipfs_Unmount(Tcl_Interp *interp,
- const char *zipname);
+ const char *mountPoint);
/* 634 */
EXTERN Tcl_Obj * TclZipfs_TclLibrary(void);
/* 635 */
-EXTERN int TclZipfs_Mount_Buffer(Tcl_Interp *interp,
- const char *mntpt, unsigned char *data,
+EXTERN int TclZipfs_MountBuffer(Tcl_Interp *interp,
+ const char *mountPoint, unsigned char *data,
size_t datalen, int copy);
typedef struct {
@@ -2416,10 +2417,10 @@ typedef struct TclStubs {
int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 631 */
- int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *mntpt, const char *zipname, const char *passwd); /* 632 */
- int (*tclZipfs_Unmount) (Tcl_Interp *interp, const char *zipname); /* 633 */
+ int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *mountPoint, const char *zipname, const char *passwd); /* 632 */
+ int (*tclZipfs_Unmount) (Tcl_Interp *interp, const char *mountPoint); /* 633 */
Tcl_Obj * (*tclZipfs_TclLibrary) (void); /* 634 */
- int (*tclZipfs_Mount_Buffer) (Tcl_Interp *interp, const char *mntpt, unsigned char *data, size_t datalen, int copy); /* 635 */
+ int (*tclZipfs_MountBuffer) (Tcl_Interp *interp, const char *mountPoint, unsigned char *data, size_t datalen, int copy); /* 635 */
} TclStubs;
extern const TclStubs *tclStubsPtr;
@@ -3674,8 +3675,8 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tclZipfs_Unmount) /* 633 */
#define TclZipfs_TclLibrary \
(tclStubsPtr->tclZipfs_TclLibrary) /* 634 */
-#define TclZipfs_Mount_Buffer \
- (tclStubsPtr->tclZipfs_Mount_Buffer) /* 635 */
+#define TclZipfs_MountBuffer \
+ (tclStubsPtr->tclZipfs_MountBuffer) /* 635 */
#endif /* defined(USE_TCL_STUBS) */
diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c
index 86f1ee6..ed1a04e 100644
--- a/generic/tclIOCmd.c
+++ b/generic/tclIOCmd.c
@@ -964,7 +964,7 @@ Tcl_ExecObjCmd(
resultPtr = Tcl_NewObj();
if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) {
- if (Tcl_ReadChars(chan, resultPtr, -1, 0) < 0) {
+ if (Tcl_ReadChars(chan, resultPtr, -1, 0) == TCL_IO_FAILURE) {
/*
* TIP #219.
* Capture error messages put by the driver into the bypass area
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 11cc22d..63d16be 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -1807,7 +1807,7 @@ Tcl_FSEvalFileEx(
* be handled especially.
*/
- if (Tcl_ReadChars(chan, objPtr, 1, 0) < 0) {
+ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
@@ -1822,7 +1822,7 @@ Tcl_FSEvalFileEx(
*/
if (Tcl_ReadChars(chan, objPtr, -1,
- memcmp(string, "\xef\xbb\xbf", 3)) < 0) {
+ memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
@@ -1942,7 +1942,7 @@ TclNREvalFile(
* be handled especially.
*/
- if (Tcl_ReadChars(chan, objPtr, 1, 0) < 0) {
+ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
@@ -1958,7 +1958,7 @@ TclNREvalFile(
*/
if (Tcl_ReadChars(chan, objPtr, -1,
- memcmp(string, "\xef\xbb\xbf", 3)) < 0) {
+ memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index 4ddce68..8e1ea44 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -1327,7 +1327,7 @@ const TclStubs tclStubs = {
TclZipfs_Mount, /* 632 */
TclZipfs_Unmount, /* 633 */
TclZipfs_TclLibrary, /* 634 */
- TclZipfs_Mount_Buffer, /* 635 */
+ TclZipfs_MountBuffer, /* 635 */
};
/* !END!: Do not edit above this line. */
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c
index 4e6cd8a..5342fb1 100644
--- a/generic/tclZipfs.c
+++ b/generic/tclZipfs.c
@@ -1,10 +1,10 @@
/*
* tclZipfs.c --
*
- * Implementation of the ZIP filesystem used in TIP 430
- * Adapted from the implentation for AndroWish.
+ * Implementation of the ZIP filesystem used in TIP 430
+ * Adapted from the implentation for AndroWish.
*
- * Coptright (c) 2016-2017 Sean Woods <yoda@etoyoc.com>
+ * Copyright (c) 2016-2017 Sean Woods <yoda@etoyoc.com>
* Copyright (c) 2013-2015 Christian Werner <chw@ch-werner.de>
*
* See the file "license.terms" for information on usage and redistribution of
@@ -21,9 +21,9 @@
#ifdef _WIN32
#include <winbase.h>
-#else
+#else /* !_WIN32 */
#include <sys/mman.h>
-#endif
+#endif /* _WIN32*/
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
@@ -33,40 +33,50 @@
#ifndef MAP_FILE
#define MAP_FILE 0
-#endif
+#endif /* !MAP_FILE */
#ifdef HAVE_ZLIB
#include "zlib.h"
#include "crypt.h"
#ifdef CFG_RUNTIME_DLLFILE
+
/*
** We are compiling as part of the core.
** TIP430 style zipfs prefix
*/
+
#define ZIPFS_VOLUME "//zipfs:/"
#define ZIPFS_VOLUME_LEN 9
#define ZIPFS_APP_MOUNT "//zipfs:/app"
#define ZIPFS_ZIP_MOUNT "//zipfs:/lib/tcl"
-#else
+
+#else /* !CFG_RUNTIME_DLLFILE */
+
/*
** We are compiling from the /compat folder of tclconfig
** Pre TIP430 style zipfs prefix
** //zipfs:/ doesn't work straight out of the box on either windows or Unix
** without other changes made to tip 430
*/
+
#define ZIPFS_VOLUME "zipfs:/"
#define ZIPFS_VOLUME_LEN 7
#define ZIPFS_APP_MOUNT "zipfs:/app"
#define ZIPFS_ZIP_MOUNT "zipfs:/lib/tcl"
-#endif
+
+#endif /* CFG_RUNTIME_DLLFILE */
+
/*
* Various constants and offsets found in ZIP archive files
*/
#define ZIP_SIG_LEN 4
-/* Local header of ZIP archive member (at very beginning of each member). */
+/*
+ * Local header of ZIP archive member (at very beginning of each member).
+ */
+
#define ZIP_LOCAL_HEADER_SIG 0x04034b50
#define ZIP_LOCAL_HEADER_LEN 30
#define ZIP_LOCAL_SIG_OFFS 0
@@ -81,7 +91,10 @@
#define ZIP_LOCAL_PATHLEN_OFFS 26
#define ZIP_LOCAL_EXTRALEN_OFFS 28
-/* Central header of ZIP archive member at end of ZIP file. */
+/*
+ * Central header of ZIP archive member at end of ZIP file.
+ */
+
#define ZIP_CENTRAL_HEADER_SIG 0x02014b50
#define ZIP_CENTRAL_HEADER_LEN 46
#define ZIP_CENTRAL_SIG_OFFS 0
@@ -102,7 +115,10 @@
#define ZIP_CENTRAL_EATTR_OFFS 38
#define ZIP_CENTRAL_LOCALHDR_OFFS 42
-/* Central end signature at very end of ZIP file. */
+/*
+ * Central end signature at very end of ZIP file.
+ */
+
#define ZIP_CENTRAL_END_SIG 0x06054b50
#define ZIP_CENTRAL_END_LEN 22
#define ZIP_CENTRAL_END_SIG_OFFS 0
@@ -120,31 +136,41 @@
#define ZIP_PASSWORD_END_SIG 0x5a5a4b50
-/* Macro to report errors only if an interp is present */
+/*
+ * Macros to report errors only if an interp is present.
+ */
+
#define ZIPFS_ERROR(interp,errstr) \
do { \
- if (interp != NULL) { \
+ if (interp) { \
Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1)); \
} \
} while (0)
+#define ZIPFS_POSIX_ERROR(interp,errstr) \
+ do { \
+ if (interp) { \
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf( \
+ "%s: %s", errstr, Tcl_PosixError(interp))); \
+ } \
+ } while (0)
/*
* Macros to read and write 16 and 32 bit integers from/to ZIP archives.
*/
-#define zip_read_int(p) \
+#define ZipReadInt(p) \
((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
-#define zip_read_short(p) \
+#define ZipReadShort(p) \
((p)[0] | ((p)[1] << 8))
-#define zip_write_int(p, v) \
+#define ZipWriteInt(p, v) \
do { \
(p)[0] = (v) & 0xff; \
(p)[1] = ((v) >> 8) & 0xff; \
(p)[2] = ((v) >> 16) & 0xff; \
(p)[3] = ((v) >> 24) & 0xff; \
} while (0)
-#define zip_write_short(p, v) \
+#define ZipWriteShort(p, v) \
do { \
(p)[0] = (v) & 0xff; \
(p)[1] = ((v) >> 8) & 0xff; \
@@ -157,7 +183,7 @@
#ifdef _WIN32
static const char drvletters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-#endif
+#endif /* _WIN32 */
/*
* Mutex to protect localtime(3) when no reentrant version available.
@@ -165,7 +191,7 @@ static const char drvletters[] =
#if !defined(_WIN32) && !defined(HAVE_LOCALTIME_R) && defined(TCL_THREADS)
TCL_DECLARE_MUTEX(localtimeMutex)
-#endif
+#endif /* !_WIN32 && !HAVE_LOCALTIME_R && TCL_THREADS */
/*
* In-core description of mounted ZIP archive file.
@@ -173,26 +199,25 @@ TCL_DECLARE_MUTEX(localtimeMutex)
typedef struct ZipFile {
char *name; /* Archive name */
- size_t namelen;
- char is_membuf; /* When true, not a file but a memory buffer */
+ size_t nameLength; /* Length of archive name */
+ char isMemBuffer; /* When true, not a file but a memory buffer */
Tcl_Channel chan; /* Channel handle or NULL */
unsigned char *data; /* Memory mapped or malloc'ed file */
size_t length; /* Length of memory mapped file */
- void *tofree; /* Non-NULL if malloc'ed file */
- size_t nfiles; /* Number of files in archive */
- size_t baseoffs; /* Archive start */
- size_t baseoffsp; /* Password start */
- size_t centoffs; /* Archive directory start */
- unsigned char pwbuf[264]; /* Password buffer */
- size_t nopen; /* Number of open files on archive */
+ void *ptrToFree; /* Non-NULL if malloc'ed file */
+ size_t numFiles; /* Number of files in archive */
+ size_t baseOffset; /* Archive start */
+ size_t passOffset; /* Password start */
+ size_t directoryOffset; /* Archive directory start */
+ unsigned char passBuf[264]; /* Password buffer */
+ size_t numOpen; /* Number of open files on archive */
struct ZipEntry *entries; /* List of files in archive */
- struct ZipEntry *topents; /* List of top-level dirs in archive */
- size_t mntptlen;
- char *mntpt; /* Mount point */
+ struct ZipEntry *topEnts; /* List of top-level dirs in archive */
+ char *mountPoint; /* Mount point name */
+ size_t mountPointLen; /* Length of mount point name */
#ifdef _WIN32
- HANDLE mh;
- int mntdrv; /* Drive letter of mount point */
-#endif
+ HANDLE mountHandle; /* Handle used for direct file access. */
+#endif /* _WIN32 */
} ZipFile;
/*
@@ -201,16 +226,16 @@ typedef struct ZipFile {
typedef struct ZipEntry {
char *name; /* The full pathname of the virtual file */
- ZipFile *zipfile; /* The ZIP file holding this virtual file */
+ ZipFile *zipFilePtr; /* The ZIP file holding this virtual file */
Tcl_WideInt offset; /* Data offset into memory mapped ZIP file */
- int nbyte; /* Uncompressed size of the virtual file */
- int nbytecompr; /* Compressed size of the virtual file */
- int cmeth; /* Compress method */
- int isdir; /* Set to 1 if directory, or -1 if root */
+ int numBytes; /* Uncompressed size of the virtual file */
+ int numCompressedBytes; /* Compressed size of the virtual file */
+ int compressMethod; /* Compress method */
+ int isDirectory; /* Set to 1 if directory, or -1 if root */
int depth; /* Number of slashes in path. */
int crc32; /* CRC-32 */
int timestamp; /* Modification time */
- int isenc; /* True if data is encrypted */
+ int isEncrypted; /* True if data is encrypted */
unsigned char *data; /* File data if written */
struct ZipEntry *next; /* Next file in the same archive */
struct ZipEntry *tnext; /* Next top-level dir in archive */
@@ -221,17 +246,17 @@ typedef struct ZipEntry {
*/
typedef struct ZipChannel {
- ZipFile *zipfile; /* The ZIP file holding this channel */
- ZipEntry *zipentry; /* Pointer back to virtual file */
- size_t nmax; /* Maximum size for write */
- size_t nbyte; /* Number of bytes of uncompressed data */
- size_t nread; /* Position of next byte to be read from the
+ ZipFile *zipFilePtr; /* The ZIP file holding this channel */
+ ZipEntry *zipEntryPtr; /* Pointer back to virtual file */
+ size_t maxWrite; /* Maximum size for write */
+ size_t numBytes; /* Number of bytes of uncompressed data */
+ size_t numRead; /* Position of next byte to be read from the
* channel */
unsigned char *ubuf; /* Pointer to the uncompressed data */
int iscompr; /* True if data is compressed */
- int isdir; /* Set to 1 if directory, or -1 if root */
- int isenc; /* True if data is encrypted */
- int iswr; /* True if open for writing */
+ int isDirectory; /* Set to 1 if directory, or -1 if root */
+ int isEncrypted; /* True if data is encrypted */
+ int isWriting; /* True if open for writing */
unsigned long keys[3]; /* Key for decryption */
} ZipChannel;
@@ -328,38 +353,48 @@ static const z_crc_t crc32tab[256] = {
0x2d02ef8d,
};
-const char *zipfs_literal_tcl_library = NULL;
+static const char *zipfs_literal_tcl_library = NULL;
/* Function prototypes */
-int TclZipfs_Mount(Tcl_Interp *interp, const char *mntpt,
- const char *zipname, const char *passwd);
-int TclZipfs_Mount_Buffer(Tcl_Interp *interp,
- const char *mntpt, unsigned char *data,
- size_t datalen, int copy);
-static int TclZipfs_AppHook_FindTclInit(const char *archive);
-static int Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr,
+static inline int DescribeMounted(Tcl_Interp *interp,
+ const char *mountPoint);
+static inline int ListMountPoints(Tcl_Interp *interp);
+static int ZipfsAppHookFindTclInit(const char *archive);
+static int ZipFSPathInFilesystemProc(Tcl_Obj *pathPtr,
ClientData *clientDataPtr);
-static Tcl_Obj * Zip_FSFilesystemPathTypeProc(Tcl_Obj *pathPtr);
-static Tcl_Obj * Zip_FSFilesystemSeparatorProc(Tcl_Obj *pathPtr);
-static int Zip_FSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
-static int Zip_FSAccessProc(Tcl_Obj *pathPtr, int mode);
-static Tcl_Channel Zip_FSOpenFileChannelProc(Tcl_Interp *interp,
+static Tcl_Obj * ZipFSFilesystemPathTypeProc(Tcl_Obj *pathPtr);
+static Tcl_Obj * ZipFSFilesystemSeparatorProc(Tcl_Obj *pathPtr);
+static int ZipFSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
+static int ZipFSAccessProc(Tcl_Obj *pathPtr, int mode);
+static Tcl_Channel ZipFSOpenFileChannelProc(Tcl_Interp *interp,
Tcl_Obj *pathPtr, int mode, int permissions);
-static int Zip_FSMatchInDirectoryProc(Tcl_Interp *interp,
+static int ZipFSMatchInDirectoryProc(Tcl_Interp *interp,
Tcl_Obj *result, Tcl_Obj *pathPtr,
const char *pattern, Tcl_GlobTypeData *types);
-static Tcl_Obj * Zip_FSListVolumesProc(void);
-static const char *const *Zip_FSFileAttrStringsProc(Tcl_Obj *pathPtr,
- Tcl_Obj** objPtrRef);
-static int Zip_FSFileAttrsGetProc(Tcl_Interp *interp, int index,
+static Tcl_Obj * ZipFSListVolumesProc(void);
+static const char *const *ZipFSFileAttrStringsProc(Tcl_Obj *pathPtr,
+ Tcl_Obj **objPtrRef);
+static int ZipFSFileAttrsGetProc(Tcl_Interp *interp, int index,
Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef);
-static int Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index,
+static int ZipFSFileAttrsSetProc(Tcl_Interp *interp, int index,
Tcl_Obj *pathPtr, Tcl_Obj *objPtr);
-static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path,
+static int ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path,
Tcl_LoadHandle *loadHandle,
Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
-static void TclZipfs_C_Init(void);
+static void ZipfsSetup(void);
+static int ZipChannelClose(ClientData instanceData,
+ Tcl_Interp *interp);
+static int ZipChannelGetFile(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int ZipChannelRead(ClientData instanceData, char *buf,
+ int toRead, int *errloc);
+static int ZipChannelSeek(ClientData instanceData, long offset,
+ int mode, int *errloc);
+static void ZipChannelWatchChannel(ClientData instanceData,
+ int mask);
+static int ZipChannelWrite(ClientData instanceData,
+ const char *buf, int toWrite, int *errloc);
/*
* Define the ZIP filesystem dispatch table.
@@ -369,26 +404,26 @@ MODULE_SCOPE const Tcl_Filesystem zipfsFilesystem;
const Tcl_Filesystem zipfsFilesystem = {
"zipfs",
- sizeof (Tcl_Filesystem),
+ sizeof(Tcl_Filesystem),
TCL_FILESYSTEM_VERSION_2,
- Zip_FSPathInFilesystemProc,
+ ZipFSPathInFilesystemProc,
NULL, /* dupInternalRepProc */
NULL, /* freeInternalRepProc */
NULL, /* internalToNormalizedProc */
NULL, /* createInternalRepProc */
NULL, /* normalizePathProc */
- Zip_FSFilesystemPathTypeProc,
- Zip_FSFilesystemSeparatorProc,
- Zip_FSStatProc,
- Zip_FSAccessProc,
- Zip_FSOpenFileChannelProc,
- Zip_FSMatchInDirectoryProc,
+ ZipFSFilesystemPathTypeProc,
+ ZipFSFilesystemSeparatorProc,
+ ZipFSStatProc,
+ ZipFSAccessProc,
+ ZipFSOpenFileChannelProc,
+ ZipFSMatchInDirectoryProc,
NULL, /* utimeProc */
NULL, /* linkProc */
- Zip_FSListVolumesProc,
- Zip_FSFileAttrStringsProc,
- Zip_FSFileAttrsGetProc,
- Zip_FSFileAttrsSetProc,
+ ZipFSListVolumesProc,
+ ZipFSFileAttrStringsProc,
+ ZipFSFileAttrsGetProc,
+ ZipFSFileAttrsSetProc,
NULL, /* createDirectoryProc */
NULL, /* removeDirectoryProc */
NULL, /* deleteFileProc */
@@ -396,22 +431,52 @@ const Tcl_Filesystem zipfsFilesystem = {
NULL, /* renameFileProc */
NULL, /* copyDirectoryProc */
NULL, /* lstatProc */
- (Tcl_FSLoadFileProc *) Zip_FSLoadFile,
+ (Tcl_FSLoadFileProc *) ZipFSLoadFile,
NULL, /* getCwdProc */
- NULL, /* chdirProc*/
+ NULL, /* chdirProc */
};
+
+/*
+ * The channel type/driver definition used for ZIP archive members.
+ */
+
+static Tcl_ChannelType ZipChannelType = {
+ "zip", /* Type name. */
+ TCL_CHANNEL_VERSION_5,
+ ZipChannelClose, /* Close channel, clean instance data */
+ ZipChannelRead, /* Handle read request */
+ ZipChannelWrite, /* Handle write request */
+ ZipChannelSeek, /* Move location of access point, NULL'able */
+ NULL, /* Set options, NULL'able */
+ NULL, /* Get options, NULL'able */
+ ZipChannelWatchChannel, /* Initialize notifier */
+ ZipChannelGetFile, /* Get OS handle from the channel */
+ NULL, /* 2nd version of close channel, NULL'able */
+ NULL, /* Set blocking mode for raw channel, NULL'able */
+ NULL, /* Function to flush channel, NULL'able */
+ NULL, /* Function to handle event, NULL'able */
+ NULL, /* Wide seek function, NULL'able */
+ NULL, /* Thread action function, NULL'able */
+ NULL, /* Truncate function, NULL'able */
+};
+
+/*
+ * Miscellaneous constants.
+ */
+
+#define ERROR_LENGTH ((size_t) -1)
/*
*-------------------------------------------------------------------------
*
* ReadLock, WriteLock, Unlock --
*
- * POSIX like rwlock functions to support multiple readers and single
- * writer on internal structs.
+ * POSIX like rwlock functions to support multiple readers and single
+ * writer on internal structs.
*
- * Limitations:
- * - a read lock cannot be promoted to a write lock
- * - a write lock may not be nested
+ * Limitations:
+ * - a read lock cannot be promoted to a write lock
+ * - a write lock may not be nested
*
*-------------------------------------------------------------------------
*/
@@ -489,7 +554,7 @@ DosTimeDate(
time_t ret;
memset(&tm, 0, sizeof(struct tm));
- tm.tm_year = (((dosDate & 0xfe00) >> 9) + 80);
+ tm.tm_year = ((dosDate & 0xfe00) >> 9) + 80;
tm.tm_mon = ((dosDate & 0x1e0) >> 5) - 1;
tm.tm_mday = dosDate & 0x1f;
tm.tm_hour = (dosTime & 0xf800) >> 11;
@@ -617,63 +682,60 @@ CanonicalPath(
int ZIPFSPATH)
{
char *path;
- int i, j, c, isunc = 0, isvfs = 0, n = 0;
- int zipfspath = 1;
+ int i, j, c, isUNC = 0, isVfs = 0, n = 0;
+ int haveZipfsPath = 1;
#ifdef _WIN32
- if ((tail[0] != '\0') && (strchr(drvletters, tail[0]) != NULL)
- && (tail[1] == ':')) {
+ if (tail[0] != '\0' && strchr(drvletters, tail[0]) && tail[1] == ':') {
tail += 2;
- zipfspath = 0;
+ haveZipfsPath = 0;
}
/* UNC style path */
if (tail[0] == '\\') {
root = "";
++tail;
- zipfspath = 0;
+ haveZipfsPath = 0;
}
if (tail[0] == '\\') {
root = "/";
++tail;
- zipfspath = 0;
+ haveZipfsPath = 0;
}
#endif /* _WIN32 */
- if (zipfspath) {
+ if (haveZipfsPath) {
/* UNC style path */
if (root && strncmp(root, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) {
- isvfs = 1;
+ isVfs = 1;
} else if (tail &&
strncmp(tail, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) {
- isvfs = 2;
+ isVfs = 2;
}
- if (isvfs != 1) {
- if ((root[0] == '/') && (root[1] == '/')) {
- isunc = 1;
- }
+ if (isVfs != 1 && (root[0] == '/') && (root[1] == '/')) {
+ isUNC = 1;
}
}
- if (isvfs != 2) {
+ if (isVfs != 2) {
if (tail[0] == '/') {
- if (isvfs != 1) {
+ if (isVfs != 1) {
root = "";
}
++tail;
- isunc = 0;
+ isUNC = 0;
}
if (tail[0] == '/') {
- if (isvfs != 1) {
+ if (isVfs != 1) {
root = "/";
}
++tail;
- isunc = 1;
+ isUNC = 1;
}
}
i = strlen(root);
j = strlen(tail);
- switch (isvfs) {
+ switch (isVfs) {
case 1:
if (i > ZIPFS_VOLUME_LEN) {
Tcl_DStringSetLength(dsPtr, i + j + 1);
@@ -715,7 +777,7 @@ CanonicalPath(
path[i] = '/';
}
}
-#endif
+#endif /* _WIN32 */
if (ZIPFSPATH) {
n = ZIPFS_VOLUME_LEN;
@@ -738,14 +800,14 @@ CanonicalPath(
continue;
}
if ((c3 == '.')
- && ((path[i + 3] == '/') || (path [i + 3] == '\0'))) {
+ && ((path[i + 3] == '/') || (path[i + 3] == '\0'))) {
i += 2;
while ((j > 0) && (path[j - 1] != '/')) {
j--;
}
- if (j > isunc) {
+ if (j > isUNC) {
--j;
- while ((j > 1 + isunc) && (path[j - 2] == '/')) {
+ while ((j > 1 + isUNC) && (path[j - 2] == '/')) {
j--;
}
}
@@ -769,7 +831,8 @@ CanonicalPath(
* ZipFSLookup --
*
* This function returns the ZIP entry struct corresponding to the ZIP
- * archive member of the given file name.
+ * archive member of the given file name. Caller must hold the right
+ * lock.
*
* Results:
* Returns the pointer to ZIP entry struct or NULL if the the given file
@@ -789,14 +852,12 @@ ZipFSLookup(
ZipEntry *z = NULL;
hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename);
- if (hPtr != NULL) {
+ if (hPtr) {
z = Tcl_GetHashValue(hPtr);
}
return z;
}
-#ifdef NEVER_USED
-
/*
*-------------------------------------------------------------------------
*
@@ -814,27 +875,23 @@ ZipFSLookup(
*-------------------------------------------------------------------------
*/
+#ifdef NEVER_USED
static int
ZipFSLookupMount(
char *filename)
{
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- ZipFile *zf;
- int match = 0;
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) == NULL) {
- continue;
- }
- if (strcmp(zf->mntpt, filename) == 0) {
- match = 1;
- break;
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ ZipFile *zf = Tcl_GetHashValue(hPtr);
+
+ if (strcmp(zf->mountPoint, filename) == 0) {
+ return 1;
}
- hPtr = Tcl_NextHashEntry(&search);
}
- return match;
+ return 0;
}
#endif /* NEVER_USED */
@@ -857,42 +914,42 @@ ZipFSLookupMount(
static void
ZipFSCloseArchive(
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
ZipFile *zf)
{
- if (zf->namelen) {
- free(zf->name); /* Allocated by strdup */
+ if (zf->nameLength) {
+ ckfree(zf->name);
}
- if (zf->is_membuf == 1) {
+ if (zf->isMemBuffer) {
/* Pointer to memory */
- if (zf->tofree != NULL) {
- Tcl_Free(zf->tofree);
- zf->tofree = NULL;
+ if (zf->ptrToFree) {
+ ckfree(zf->ptrToFree);
+ zf->ptrToFree = NULL;
}
zf->data = NULL;
return;
}
#ifdef _WIN32
- if ((zf->data != NULL) && (zf->tofree == NULL)) {
+ if (zf->data && !zf->ptrToFree) {
UnmapViewOfFile(zf->data);
zf->data = NULL;
}
- if (zf->mh != INVALID_HANDLE_VALUE) {
- CloseHandle(zf->mh);
+ if (zf->mountHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle(zf->mountHandle);
}
#else /* !_WIN32 */
- if ((zf->data != MAP_FAILED) && (zf->tofree == NULL)) {
+ if ((zf->data != MAP_FAILED) && !zf->ptrToFree) {
munmap(zf->data, zf->length);
zf->data = MAP_FAILED;
}
#endif /* _WIN32 */
- if (zf->tofree != NULL) {
- Tcl_Free(zf->tofree);
- zf->tofree = NULL;
+ if (zf->ptrToFree) {
+ ckfree(zf->ptrToFree);
+ zf->ptrToFree = NULL;
}
- if (zf->chan != NULL) {
+ if (zf->chan) {
Tcl_Close(interp, zf->chan);
zf->chan = NULL;
}
@@ -901,7 +958,7 @@ ZipFSCloseArchive(
/*
*-------------------------------------------------------------------------
*
- * ZipFS_Find_TOC --
+ * ZipFSFindTOC --
*
* This function takes a memory mapped zip file and indexes the contents.
* When "needZip" is zero an embedded ZIP archive in an executable file
@@ -919,8 +976,8 @@ ZipFSCloseArchive(
*/
static int
-ZipFS_Find_TOC(
- Tcl_Interp *interp,
+ZipFSFindTOC(
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
int needZip,
ZipFile *zf)
{
@@ -930,7 +987,7 @@ ZipFS_Find_TOC(
p = zf->data + zf->length - ZIP_CENTRAL_END_LEN;
while (p >= zf->data) {
if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
- if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) {
+ if (ZipReadInt(p) == ZIP_CENTRAL_END_SIG) {
break;
}
p -= ZIP_SIG_LEN;
@@ -940,58 +997,58 @@ ZipFS_Find_TOC(
}
if (p < zf->data) {
if (!needZip) {
- zf->baseoffs = zf->baseoffsp = zf->length;
+ zf->baseOffset = zf->passOffset = zf->length;
return TCL_OK;
}
ZIPFS_ERROR(interp, "wrong end signature");
goto error;
}
- zf->nfiles = zip_read_short(p + ZIP_CENTRAL_ENTS_OFFS);
- if (zf->nfiles == 0) {
+ zf->numFiles = ZipReadShort(p + ZIP_CENTRAL_ENTS_OFFS);
+ if (zf->numFiles == 0) {
if (!needZip) {
- zf->baseoffs = zf->baseoffsp = zf->length;
+ zf->baseOffset = zf->passOffset = zf->length;
return TCL_OK;
}
ZIPFS_ERROR(interp, "empty archive");
goto error;
}
- q = zf->data + zip_read_int(p + ZIP_CENTRAL_DIRSTART_OFFS);
- p -= zip_read_int(p + ZIP_CENTRAL_DIRSIZE_OFFS);
+ q = zf->data + ZipReadInt(p + ZIP_CENTRAL_DIRSTART_OFFS);
+ p -= ZipReadInt(p + ZIP_CENTRAL_DIRSIZE_OFFS);
if ((p < zf->data) || (p > zf->data + zf->length)
- || (q < zf->data) || (q > (zf->data + zf->length))) {
+ || (q < zf->data) || (q > zf->data + zf->length)) {
if (!needZip) {
- zf->baseoffs = zf->baseoffsp = zf->length;
+ zf->baseOffset = zf->passOffset = zf->length;
return TCL_OK;
}
ZIPFS_ERROR(interp, "archive directory not found");
goto error;
}
- zf->baseoffs = zf->baseoffsp = p - q;
- zf->centoffs = p - zf->data;
+ zf->baseOffset = zf->passOffset = p - q;
+ zf->directoryOffset = p - zf->data;
q = p;
- for (i = 0; i < zf->nfiles; i++) {
+ for (i = 0; i < zf->numFiles; i++) {
int pathlen, comlen, extra;
if (q + ZIP_CENTRAL_HEADER_LEN > zf->data + zf->length) {
ZIPFS_ERROR(interp, "wrong header length");
goto error;
}
- if (zip_read_int(q) != ZIP_CENTRAL_HEADER_SIG) {
+ if (ZipReadInt(q) != ZIP_CENTRAL_HEADER_SIG) {
ZIPFS_ERROR(interp, "wrong header signature");
goto error;
}
- pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
- comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
- extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
+ pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS);
+ comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
+ extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS);
q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
}
- q = zf->data + zf->baseoffs;
- if ((zf->baseoffs >= 6) && (zip_read_int(q - 4) == ZIP_PASSWORD_END_SIG)) {
+ q = zf->data + zf->baseOffset;
+ if ((zf->baseOffset >= 6) && (ZipReadInt(q - 4) == ZIP_PASSWORD_END_SIG)) {
i = q[-5];
if (q - 5 - i > zf->data) {
- zf->pwbuf[0] = i;
- memcpy(zf->pwbuf + 1, q - 5 - i, i);
- zf->baseoffsp -= i ? (5 + i) : 0;
+ zf->passBuf[0] = i;
+ memcpy(zf->passBuf + 1, q - 5 - i, i);
+ zf->passOffset -= i ? (5 + i) : 0;
}
}
return TCL_OK;
@@ -1025,51 +1082,54 @@ ZipFS_Find_TOC(
static int
ZipFSOpenArchive(
- Tcl_Interp *interp,
- const char *zipname,
- int needZip,
- ZipFile *zf)
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
+ const char *zipname, /* Path to ZIP file to open. */
+ int needZip,
+ ZipFile *zf)
{
size_t i;
ClientData handle;
- zf->namelen = 0;
- zf->is_membuf = 0;
+ zf->nameLength = 0;
+ zf->isMemBuffer = 0;
#ifdef _WIN32
zf->data = NULL;
- zf->mh = INVALID_HANDLE_VALUE;
+ zf->mountHandle = INVALID_HANDLE_VALUE;
#else /* !_WIN32 */
zf->data = MAP_FAILED;
#endif /* _WIN32 */
zf->length = 0;
- zf->nfiles = 0;
- zf->baseoffs = zf->baseoffsp = 0;
- zf->tofree = NULL;
- zf->pwbuf[0] = 0;
- zf->chan = Tcl_OpenFileChannel(interp, zipname, "r", 0);
- if (zf->chan == NULL) {
+ zf->numFiles = 0;
+ zf->baseOffset = zf->passOffset = 0;
+ zf->ptrToFree = NULL;
+ zf->passBuf[0] = 0;
+ zf->chan = Tcl_OpenFileChannel(interp, zipname, "rb", 0);
+ if (!zf->chan) {
return TCL_ERROR;
}
if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) {
- if (Tcl_SetChannelOption(interp, zf->chan, "-translation",
- "binary") != TCL_OK) {
+ zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
+ if (zf->length == ERROR_LENGTH) {
+ ZIPFS_POSIX_ERROR(interp, "seek error");
goto error;
}
- zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
if ((zf->length - ZIP_CENTRAL_END_LEN)
> (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
ZIPFS_ERROR(interp, "illegal file size");
goto error;
}
- Tcl_Seek(zf->chan, 0, SEEK_SET);
- zf->tofree = zf->data = (unsigned char *) Tcl_AttemptAlloc(zf->length);
- if (zf->tofree == NULL) {
+ if (Tcl_Seek(zf->chan, 0, SEEK_SET) == -1) {
+ ZIPFS_POSIX_ERROR(interp, "seek error");
+ goto error;
+ }
+ zf->ptrToFree = zf->data = attemptckalloc(zf->length);
+ if (!zf->ptrToFree) {
ZIPFS_ERROR(interp, "out of memory");
goto error;
}
i = Tcl_Read(zf->chan, (char *) zf->data, zf->length);
if (i != zf->length) {
- ZIPFS_ERROR(interp, "file read error");
+ ZIPFS_POSIX_ERROR(interp, "file read error");
goto error;
}
Tcl_Close(interp, zf->chan);
@@ -1085,36 +1145,37 @@ ZipFSOpenArchive(
readSuccessful = (zf->length != (size_t) INVALID_FILE_SIZE);
# endif /* _WIN64 */
if (!readSuccessful || (zf->length < ZIP_CENTRAL_END_LEN)) {
- ZIPFS_ERROR(interp, "invalid file size");
+ ZIPFS_POSIX_ERROR(interp, "invalid file size");
goto error;
}
- zf->mh = CreateFileMapping((HANDLE) handle, 0, PAGE_READONLY, 0,
- zf->length, 0);
- if (zf->mh == INVALID_HANDLE_VALUE) {
- ZIPFS_ERROR(interp, "file mapping failed");
+ zf->mountHandle = CreateFileMapping((HANDLE) handle, 0, PAGE_READONLY,
+ 0, zf->length, 0);
+ if (zf->mountHandle == INVALID_HANDLE_VALUE) {
+ ZIPFS_POSIX_ERROR(interp, "file mapping failed");
goto error;
}
- zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length);
- if (zf->data == NULL) {
- ZIPFS_ERROR(interp, "file mapping failed");
+ zf->data = MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0,
+ zf->length);
+ if (!zf->data) {
+ ZIPFS_POSIX_ERROR(interp, "file mapping failed");
goto error;
}
#else /* !_WIN32 */
zf->length = lseek(PTR2INT(handle), 0, SEEK_END);
- if ((zf->length == (size_t)-1) || (zf->length < ZIP_CENTRAL_END_LEN)) {
- ZIPFS_ERROR(interp, "invalid file size");
+ if (zf->length == ERROR_LENGTH || zf->length < ZIP_CENTRAL_END_LEN) {
+ ZIPFS_POSIX_ERROR(interp, "invalid file size");
goto error;
}
lseek(PTR2INT(handle), 0, SEEK_SET);
zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ,
MAP_FILE | MAP_PRIVATE, PTR2INT(handle), 0);
if (zf->data == MAP_FAILED) {
- ZIPFS_ERROR(interp, "file mapping failed");
+ ZIPFS_POSIX_ERROR(interp, "file mapping failed");
goto error;
}
#endif /* _WIN32 */
}
- return ZipFS_Find_TOC(interp, needZip, zf);
+ return ZipFSFindTOC(interp, needZip, zf);
error:
ZipFSCloseArchive(interp, zf);
@@ -1126,23 +1187,26 @@ ZipFSOpenArchive(
*
* ZipFSRootNode --
*
- * This function generates the root node for a ZIPFS filesystem
+ * This function generates the root node for a ZIPFS filesystem.
*
* Results:
- * TCL_OK on success, TCL_ERROR otherwise with an error message
- * placed into the given "interp" if it is not NULL.
+ * TCL_OK on success, TCL_ERROR otherwise with an error message placed
+ * into the given "interp" if it is not NULL.
*
* Side effects:
+ * ...
+ *
*-------------------------------------------------------------------------
*/
static int
-ZipFS_Catalogue_Filesystem(
- Tcl_Interp *interp,
+ZipFSCatalogFilesystem(
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
ZipFile *zf0,
- const char *mntpt,
- const char *passwd,
- const char *zipname)
+ const char *mountPoint, /* Mount point path. */
+ const char *passwd, /* Password for opening the ZIP, or NULL if
+ * the ZIP is unprotected. */
+ const char *zipname) /* Path to ZIP file to build a catalog of. */
{
int pwlen, isNew;
size_t i;
@@ -1157,9 +1221,9 @@ ZipFS_Catalogue_Filesystem(
*/
pwlen = 0;
- if (passwd != NULL) {
+ if (passwd) {
pwlen = strlen(passwd);
- if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) {
+ if ((pwlen > 255) || strchr(passwd, 0xff)) {
if (interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("illegal password", -1));
@@ -1177,25 +1241,25 @@ ZipFS_Catalogue_Filesystem(
Tcl_DStringInit(&ds);
Tcl_DStringInit(&dsm);
- if (strcmp(mntpt, "/") == 0) {
- mntpt = "";
+ if (strcmp(mountPoint, "/") == 0) {
+ mountPoint = "";
} else {
- mntpt = CanonicalPath("", mntpt, &dsm, 1);
+ mountPoint = CanonicalPath("", mountPoint, &dsm, 1);
}
- hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mntpt, &isNew);
+ hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew);
if (!isNew) {
- zf = (ZipFile *) Tcl_GetHashValue(hPtr);
- if (interp != NULL) {
- Tcl_AppendResult(interp, zf->name, " is already mounted on ",
- mntpt, (char *) NULL);
+ if (interp) {
+ zf = Tcl_GetHashValue(hPtr);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s is already mounted on %s", zf->name, mountPoint));
}
Unlock();
ZipFSCloseArchive(interp, zf0);
return TCL_ERROR;
}
- zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1);
- if (zf == NULL) {
- if (interp != NULL) {
+ zf = attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
+ if (!zf) {
+ if (interp) {
Tcl_AppendResult(interp, "out of memory", (char *) NULL);
}
Unlock();
@@ -1205,63 +1269,58 @@ ZipFS_Catalogue_Filesystem(
Unlock();
*zf = *zf0;
- zf->mntpt = Tcl_GetHashKey(&ZipFS.zipHash, hPtr);
- zf->mntptlen = strlen(zf->mntpt);
- zf->name = strdup(zipname);
- zf->namelen = strlen(zipname);
+ zf->mountPoint = Tcl_GetHashKey(&ZipFS.zipHash, hPtr);
+ zf->mountPointLen = strlen(zf->mountPoint);
+ zf->nameLength = strlen(zipname);
+ zf->name = ckalloc(zf->nameLength + 1);
+ memcpy(zf->name, zipname, zf->nameLength + 1);
zf->entries = NULL;
- zf->topents = NULL;
- zf->nopen = 0;
+ zf->topEnts = NULL;
+ zf->numOpen = 0;
Tcl_SetHashValue(hPtr, zf);
- if ((zf->pwbuf[0] == 0) && pwlen) {
+ if ((zf->passBuf[0] == 0) && pwlen) {
int k = 0;
- i = pwlen;
- zf->pwbuf[k++] = i;
- while (i > 0) {
- zf->pwbuf[k] = (passwd[i - 1] & 0x0f)
- | pwrot[(passwd[i - 1] >> 4) & 0x0f];
- k++;
- i--;
+ zf->passBuf[k++] = pwlen;
+ for (i = pwlen; i-- > 0 ;) {
+ zf->passBuf[k++] = (passwd[i] & 0x0f)
+ | pwrot[(passwd[i] >> 4) & 0x0f];
}
- zf->pwbuf[k] = '\0';
+ zf->passBuf[k] = '\0';
}
- if (mntpt[0] != '\0') {
- z = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry));
- z->name = NULL;
- z->tnext = NULL;
- z->depth = CountSlashes(mntpt);
- z->zipfile = zf;
- z->isdir = (zf->baseoffs == 0) ? 1 : -1; /* root marker */
- z->isenc = 0;
- z->offset = zf->baseoffs;
- z->crc32 = 0;
- z->timestamp = 0;
- z->nbyte = z->nbytecompr = 0;
- z->cmeth = ZIP_COMPMETH_STORED;
- z->data = NULL;
- hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mntpt, &isNew);
- if (!isNew) {
- /* skip it */
- Tcl_Free((char *) z);
- } else {
+ if (mountPoint[0] != '\0') {
+ hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew);
+ if (isNew) {
+ z = ckalloc(sizeof(ZipEntry));
Tcl_SetHashValue(hPtr, z);
+
+ z->tnext = NULL;
+ z->depth = CountSlashes(mountPoint);
+ z->zipFilePtr = zf;
+ z->isDirectory = (zf->baseOffset == 0) ? 1 : -1; /* root marker */
+ z->isEncrypted = 0;
+ z->offset = zf->baseOffset;
+ z->crc32 = 0;
+ z->timestamp = 0;
+ z->numBytes = z->numCompressedBytes = 0;
+ z->compressMethod = ZIP_COMPMETH_STORED;
+ z->data = NULL;
z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
z->next = zf->entries;
zf->entries = z;
}
}
- q = zf->data + zf->centoffs;
+ q = zf->data + zf->directoryOffset;
Tcl_DStringInit(&fpBuf);
- for (i = 0; i < zf->nfiles; i++) {
+ for (i = 0; i < zf->numFiles; i++) {
int extra, isdir = 0, dosTime, dosDate, nbcompr;
size_t offs, pathlen, comlen;
unsigned char *lq, *gq = NULL;
char *fullpath, *path;
- pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
- comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
- extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
+ pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS);
+ comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
+ extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS);
Tcl_DStringSetLength(&ds, 0);
Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen);
path = Tcl_DStringValue(&ds);
@@ -1273,26 +1332,26 @@ ZipFS_Catalogue_Filesystem(
if ((strcmp(path, ".") == 0) || (strcmp(path, "..") == 0)) {
goto nextent;
}
- lq = zf->data + zf->baseoffs
- + zip_read_int(q + ZIP_CENTRAL_LOCALHDR_OFFS);
+ lq = zf->data + zf->baseOffset
+ + ZipReadInt(q + ZIP_CENTRAL_LOCALHDR_OFFS);
if ((lq < zf->data) || (lq > zf->data + zf->length)) {
goto nextent;
}
- nbcompr = zip_read_int(lq + ZIP_LOCAL_COMPLEN_OFFS);
+ nbcompr = ZipReadInt(lq + ZIP_LOCAL_COMPLEN_OFFS);
if (!isdir && (nbcompr == 0)
- && (zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
- && (zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
+ && (ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
+ && (ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
gq = q;
- nbcompr = zip_read_int(gq + ZIP_CENTRAL_COMPLEN_OFFS);
+ nbcompr = ZipReadInt(gq + ZIP_CENTRAL_COMPLEN_OFFS);
}
offs = (lq - zf->data)
+ ZIP_LOCAL_HEADER_LEN
- + zip_read_short(lq + ZIP_LOCAL_PATHLEN_OFFS)
- + zip_read_short(lq + ZIP_LOCAL_EXTRALEN_OFFS);
- if ((offs + nbcompr) > zf->length) {
+ + ZipReadShort(lq + ZIP_LOCAL_PATHLEN_OFFS)
+ + ZipReadShort(lq + ZIP_LOCAL_EXTRALEN_OFFS);
+ if (offs + nbcompr > zf->length) {
goto nextent;
}
- if (!isdir && (mntpt[0] == '\0') && !CountSlashes(path)) {
+ if (!isdir && (mountPoint[0] == '\0') && !CountSlashes(path)) {
#ifdef ANDROID
/*
* When mounting the ZIP archive on the root directory try to
@@ -1308,7 +1367,7 @@ ZipFS_Catalogue_Filesystem(
Tcl_DStringAppend(&ds2, "assets/.root/", -1);
Tcl_DStringAppend(&ds2, path, -1);
hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, Tcl_DStringValue(&ds2));
- if (hPtr != NULL) {
+ if (hPtr) {
/* should not happen but skip it anyway */
Tcl_DStringFree(&ds2);
goto nextent;
@@ -1326,47 +1385,47 @@ ZipFS_Catalogue_Filesystem(
#endif /* ANDROID */
}
Tcl_DStringSetLength(&fpBuf, 0);
- fullpath = CanonicalPath(mntpt, path, &fpBuf, 1);
- z = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry));
+ fullpath = CanonicalPath(mountPoint, path, &fpBuf, 1);
+ z = ckalloc(sizeof(ZipEntry));
z->name = NULL;
z->tnext = NULL;
z->depth = CountSlashes(fullpath);
- z->zipfile = zf;
- z->isdir = isdir;
- z->isenc = (zip_read_short(lq + ZIP_LOCAL_FLAGS_OFFS) & 1)
+ z->zipFilePtr = zf;
+ z->isDirectory = isdir;
+ z->isEncrypted = (ZipReadShort(lq + ZIP_LOCAL_FLAGS_OFFS) & 1)
&& (nbcompr > 12);
z->offset = offs;
- if (gq != NULL) {
- z->crc32 = zip_read_int(gq + ZIP_CENTRAL_CRC32_OFFS);
- dosDate = zip_read_short(gq + ZIP_CENTRAL_MDATE_OFFS);
- dosTime = zip_read_short(gq + ZIP_CENTRAL_MTIME_OFFS);
+ if (gq) {
+ z->crc32 = ZipReadInt(gq + ZIP_CENTRAL_CRC32_OFFS);
+ dosDate = ZipReadShort(gq + ZIP_CENTRAL_MDATE_OFFS);
+ dosTime = ZipReadShort(gq + ZIP_CENTRAL_MTIME_OFFS);
z->timestamp = DosTimeDate(dosDate, dosTime);
- z->nbyte = zip_read_int(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);
- z->cmeth = zip_read_short(gq + ZIP_CENTRAL_COMPMETH_OFFS);
+ z->numBytes = ZipReadInt(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);
+ z->compressMethod = ZipReadShort(gq + ZIP_CENTRAL_COMPMETH_OFFS);
} else {
- z->crc32 = zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS);
- dosDate = zip_read_short(lq + ZIP_LOCAL_MDATE_OFFS);
- dosTime = zip_read_short(lq + ZIP_LOCAL_MTIME_OFFS);
+ z->crc32 = ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS);
+ dosDate = ZipReadShort(lq + ZIP_LOCAL_MDATE_OFFS);
+ dosTime = ZipReadShort(lq + ZIP_LOCAL_MTIME_OFFS);
z->timestamp = DosTimeDate(dosDate, dosTime);
- z->nbyte = zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS);
- z->cmeth = zip_read_short(lq + ZIP_LOCAL_COMPMETH_OFFS);
+ z->numBytes = ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS);
+ z->compressMethod = ZipReadShort(lq + ZIP_LOCAL_COMPMETH_OFFS);
}
- z->nbytecompr = nbcompr;
+ z->numCompressedBytes = nbcompr;
z->data = NULL;
hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew);
if (!isNew) {
/* should not happen but skip it anyway */
- Tcl_Free((char *) z);
+ ckfree(z);
} else {
Tcl_SetHashValue(hPtr, z);
z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
z->next = zf->entries;
zf->entries = z;
- if (isdir && (mntpt[0] == '\0') && (z->depth == 1)) {
- z->tnext = zf->topents;
- zf->topents = z;
+ if (isdir && (mountPoint[0] == '\0') && (z->depth == 1)) {
+ z->tnext = zf->topEnts;
+ zf->topEnts = z;
}
- if (!z->isdir && (z->depth > 1)) {
+ if (!z->isDirectory && (z->depth > 1)) {
char *dir, *end;
ZipEntry *zd;
@@ -1374,41 +1433,34 @@ ZipFS_Catalogue_Filesystem(
Tcl_DStringSetLength(&ds, 0);
Tcl_DStringAppend(&ds, z->name, -1);
dir = Tcl_DStringValue(&ds);
- end = strrchr(dir, '/');
- while ((end != NULL) && (end != dir)) {
+ for (end = strrchr(dir, '/'); end && (end != dir);
+ end = strrchr(dir, '/')) {
Tcl_DStringSetLength(&ds, end - dir);
- hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, dir);
- if (hPtr != NULL) {
+ hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew);
+ if (!isNew) {
break;
}
- zd = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry));
+ zd = ckalloc(sizeof(ZipEntry));
zd->name = NULL;
zd->tnext = NULL;
zd->depth = CountSlashes(dir);
- zd->zipfile = zf;
- zd->isdir = 1;
- zd->isenc = 0;
+ zd->zipFilePtr = zf;
+ zd->isDirectory = 1;
+ zd->isEncrypted = 0;
zd->offset = z->offset;
zd->crc32 = 0;
zd->timestamp = z->timestamp;
- zd->nbyte = zd->nbytecompr = 0;
- zd->cmeth = ZIP_COMPMETH_STORED;
+ zd->numBytes = zd->numCompressedBytes = 0;
+ zd->compressMethod = ZIP_COMPMETH_STORED;
zd->data = NULL;
- hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew);
- if (!isNew) {
- /* should not happen but skip it anyway */
- Tcl_Free((char *) zd);
- } else {
- Tcl_SetHashValue(hPtr, zd);
- zd->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
- zd->next = zf->entries;
- zf->entries = zd;
- if ((mntpt[0] == '\0') && (zd->depth == 1)) {
- zd->tnext = zf->topents;
- zf->topents = zd;
- }
+ Tcl_SetHashValue(hPtr, zd);
+ zd->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
+ zd->next = zf->entries;
+ zf->entries = zd;
+ if ((mountPoint[0] == '\0') && (zd->depth == 1)) {
+ zd->tnext = zf->topEnts;
+ zf->topEnts = zd;
}
- end = strrchr(dir, '/');
}
}
}
@@ -1422,25 +1474,114 @@ ZipFS_Catalogue_Filesystem(
return TCL_OK;
}
+/*
+ *-------------------------------------------------------------------------
+ *
+ * ZipfsSetup --
+ *
+ * Common initialisation code. ZipFS.initialized must *not* be set prior
+ * to the call.
+ *
+ *-------------------------------------------------------------------------
+ */
+
static void
-TclZipfs_C_Init(void)
+ZipfsSetup(void)
{
+#ifdef TCL_THREADS
static const Tcl_Time t = { 0, 0 };
- if (!ZipFS.initialized) {
-#ifdef TCL_THREADS
- /*
- * Inflate condition variable.
- */
- Tcl_MutexLock(&ZipFSMutex);
- Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t);
- Tcl_MutexUnlock(&ZipFSMutex);
+ /*
+ * Inflate condition variable.
+ */
+
+ Tcl_MutexLock(&ZipFSMutex);
+ Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t);
+ Tcl_MutexUnlock(&ZipFSMutex);
#endif /* TCL_THREADS */
- Tcl_FSRegister(NULL, &zipfsFilesystem);
- Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS);
- Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS);
- ZipFS.initialized = ZipFS.idCount = 1;
+
+ Tcl_FSRegister(NULL, &zipfsFilesystem);
+ Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS);
+ ZipFS.idCount = 1;
+ ZipFS.initialized = 1;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * ListMountPoints --
+ *
+ * This procedure lists the mount points and what's mounted there, or
+ * reports whether there are any mounts (if there's no interpreter). The
+ * read lock must be held by the caller.
+ *
+ * Results:
+ * A standard Tcl result. TCL_OK (or TCL_BREAK if no mounts and no
+ * interpreter).
+ *
+ * Side effects:
+ * Interpreter result may be updated.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static inline int
+ListMountPoints(
+ Tcl_Interp *interp)
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ ZipFile *zf;
+
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ if (!interp) {
+ return TCL_OK;
+ }
+ zf = Tcl_GetHashValue(hPtr);
+ Tcl_AppendElement(interp, zf->mountPoint);
+ Tcl_AppendElement(interp, zf->name);
+ }
+ return (interp ? TCL_OK : TCL_BREAK);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * DescribeMounted --
+ *
+ * This procedure describes what is mounted at the given the mount point.
+ * The interpreter result is not updated if there is nothing mounted at
+ * the given point. The read lock must be held by the caller.
+ *
+ * Results:
+ * A standard Tcl result. TCL_OK (or TCL_BREAK if nothing mounted there
+ * and no interpreter).
+ *
+ * Side effects:
+ * Interpreter result may be updated.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static inline int
+DescribeMounted(
+ Tcl_Interp *interp,
+ const char *mountPoint)
+{
+ Tcl_HashEntry *hPtr;
+ ZipFile *zf;
+
+ if (interp) {
+ hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
+ if (hPtr) {
+ zf = Tcl_GetHashValue(hPtr);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
+ return TCL_OK;
+ }
}
+ return (interp ? TCL_OK : TCL_BREAK);
}
/*
@@ -1463,61 +1604,47 @@ TclZipfs_C_Init(void)
int
TclZipfs_Mount(
- Tcl_Interp *interp,
- const char *mntpt,
- const char *zipname,
- const char *passwd)
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
+ const char *mountPoint, /* Mount point path. */
+ const char *zipname, /* Path to ZIP file to mount. */
+ const char *passwd) /* Password for opening the ZIP, or NULL if
+ * the ZIP is unprotected. */
{
- int i, pwlen;
ZipFile *zf;
ReadLock();
if (!ZipFS.initialized) {
- TclZipfs_C_Init();
- }
- if (mntpt == NULL) {
- Tcl_HashEntry *hPtr;
- Tcl_HashSearch search;
- int ret = TCL_OK;
-
- i = 0;
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) {
- if (interp != NULL) {
- Tcl_AppendElement(interp, zf->mntpt);
- Tcl_AppendElement(interp, zf->name);
- }
- ++i;
- }
- hPtr = Tcl_NextHashEntry(&search);
- }
- if (interp == NULL) {
- ret = (i > 0) ? TCL_OK : TCL_BREAK;
- }
+ ZipfsSetup();
+ }
+
+ /*
+ * No mount point, so list all mount points and what is mounted there.
+ */
+
+ if (!mountPoint) {
+ int ret = ListMountPoints(interp);
Unlock();
return ret;
}
- if (zipname == NULL) {
- if (interp != NULL) {
- Tcl_HashEntry *hPtr;
+ /*
+ * Mount point but no file, so describe what is mounted at that mount
+ * point.
+ */
- hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt);
- if (hPtr != NULL) {
- if ((zf = Tcl_GetHashValue(hPtr)) != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
- }
- }
- }
+ if (!zipname) {
+ DescribeMounted(interp, mountPoint);
Unlock();
return TCL_OK;
}
Unlock();
- pwlen = 0;
- if (passwd != NULL) {
- pwlen = strlen(passwd);
- if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) {
+
+ /*
+ * Have both a mount point and a file (name) to mount there.
+ */
+
+ if (passwd) {
+ if ((strlen(passwd) > 255) || strchr(passwd, 0xff)) {
if (interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("illegal password", -1));
@@ -1525,9 +1652,9 @@ TclZipfs_Mount(
return TCL_ERROR;
}
}
- zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1);
- if (zf == NULL) {
- if (interp != NULL) {
+ zf = attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
+ if (!zf) {
+ if (interp) {
Tcl_AppendResult(interp, "out of memory", (char *) NULL);
}
return TCL_ERROR;
@@ -1535,16 +1662,16 @@ TclZipfs_Mount(
if (ZipFSOpenArchive(interp, zipname, 1, zf) != TCL_OK) {
return TCL_ERROR;
}
- return ZipFS_Catalogue_Filesystem(interp, zf, mntpt, passwd, zipname);
+ return ZipFSCatalogFilesystem(interp, zf, mountPoint, passwd, zipname);
}
/*
*-------------------------------------------------------------------------
*
- * TclZipfs_Mount_Buffer --
+ * TclZipfs_MountBuffer --
*
- * This procedure is invoked to mount a given ZIP archive file on
- * a given mountpoint with optional ZIP password.
+ * This procedure is invoked to mount a given ZIP archive file on a given
+ * mountpoint with optional ZIP password.
*
* Results:
* A standard Tcl result.
@@ -1557,88 +1684,73 @@ TclZipfs_Mount(
*/
int
-TclZipfs_Mount_Buffer(
- Tcl_Interp *interp,
- const char *mntpt,
+TclZipfs_MountBuffer(
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
+ const char *mountPoint, /* Mount point path. */
unsigned char *data,
size_t datalen,
int copy)
{
- int i;
ZipFile *zf;
ReadLock();
if (!ZipFS.initialized) {
- TclZipfs_C_Init();
- }
- if (mntpt == NULL) {
- Tcl_HashEntry *hPtr;
- Tcl_HashSearch search;
- int ret = TCL_OK;
-
- i = 0;
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) {
- if (interp != NULL) {
- Tcl_AppendElement(interp, zf->mntpt);
- Tcl_AppendElement(interp, zf->name);
- }
- ++i;
- }
- hPtr = Tcl_NextHashEntry(&search);
- }
- if (interp == NULL) {
- ret = (i > 0) ? TCL_OK : TCL_BREAK;
- }
+ ZipfsSetup();
+ }
+
+ /*
+ * No mount point, so list all mount points and what is mounted there.
+ */
+
+ if (!mountPoint) {
+ int ret = ListMountPoints(interp);
Unlock();
return ret;
}
- if (data == NULL) {
- if (interp != NULL) {
- Tcl_HashEntry *hPtr;
+ /*
+ * Mount point but no data, so describe what is mounted at that mount
+ * point.
+ */
- hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt);
- if (hPtr != NULL) {
- zf = Tcl_GetHashValue(hPtr);
- if (zf != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
- }
- }
- }
+ if (!data) {
+ DescribeMounted(interp, mountPoint);
Unlock();
return TCL_OK;
}
Unlock();
- zf = (ZipFile *) Tcl_AttemptAlloc(sizeof(ZipFile) + strlen(mntpt) + 1);
- if (zf == NULL) {
- if (interp != NULL) {
+ /*
+ * Have both a mount point and data to mount there.
+ */
+
+ zf = attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
+ if (!zf) {
+ if (interp) {
Tcl_AppendResult(interp, "out of memory", (char *) NULL);
}
return TCL_ERROR;
}
- zf->is_membuf = 1;
+ zf->isMemBuffer = 1;
zf->length = datalen;
if (copy) {
- zf->data = (unsigned char *) Tcl_AttemptAlloc(datalen);
- if (zf->data == NULL) {
- if (interp != NULL) {
+ zf->data = attemptckalloc(datalen);
+ if (!zf->data) {
+ if (interp) {
Tcl_AppendResult(interp, "out of memory", (char *) NULL);
}
return TCL_ERROR;
}
memcpy(zf->data, data, datalen);
- zf->tofree = zf->data;
+ zf->ptrToFree = zf->data;
} else {
zf->data = data;
- zf->tofree = NULL;
+ zf->ptrToFree = NULL;
}
- if (ZipFS_Find_TOC(interp, 0, zf) != TCL_OK) {
+ if (ZipFSFindTOC(interp, 0, zf) != TCL_OK) {
return TCL_ERROR;
}
- return ZipFS_Catalogue_Filesystem(interp, zf, mntpt, NULL,
+ return ZipFSCatalogFilesystem(interp, zf, mountPoint, NULL,
"Memory Buffer");
}
@@ -1660,8 +1772,8 @@ TclZipfs_Mount_Buffer(
int
TclZipfs_Unmount(
- Tcl_Interp *interp,
- const char *mntpt)
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
+ const char *mountPoint) /* Mount point path. */
{
ZipFile *zf;
ZipEntry *z, *znext;
@@ -1680,16 +1792,16 @@ TclZipfs_Unmount(
*/
Tcl_DStringInit(&dsm);
- mntpt = CanonicalPath("", mntpt, &dsm, 1);
+ mountPoint = CanonicalPath("", mountPoint, &dsm, 1);
- hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt);
+ hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
/* don't report no-such-mount as an error */
- if (hPtr == NULL) {
+ if (!hPtr) {
goto done;
}
- zf = (ZipFile *) Tcl_GetHashValue(hPtr);
- if (zf->nopen > 0) {
+ zf = Tcl_GetHashValue(hPtr);
+ if (zf->numOpen > 0) {
ZIPFS_ERROR(interp, "filesystem is busy");
ret = TCL_ERROR;
goto done;
@@ -1701,13 +1813,13 @@ TclZipfs_Unmount(
if (hPtr) {
Tcl_DeleteHashEntry(hPtr);
}
- if (z->data != NULL) {
- Tcl_Free((char *) z->data);
+ if (z->data) {
+ ckfree(z->data);
}
- Tcl_Free((char *) z);
+ ckfree(z);
}
ZipFSCloseArchive(interp, zf);
- Tcl_Free((char *) zf);
+ ckfree(zf);
unmounted = 1;
done:
Unlock();
@@ -1736,7 +1848,7 @@ TclZipfs_Unmount(
static int
ZipFSMountObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -1747,16 +1859,16 @@ ZipFSMountObjCmd(
}
return TclZipfs_Mount(interp, (objc > 1) ? Tcl_GetString(objv[1]) : NULL,
- (objc > 2) ? Tcl_GetString(objv[2]) : NULL,
- (objc > 3) ? Tcl_GetString(objv[3]) : NULL);
+ (objc > 2) ? Tcl_GetString(objv[2]) : NULL,
+ (objc > 3) ? Tcl_GetString(objv[3]) : NULL);
}
/*
*-------------------------------------------------------------------------
*
- * ZipFSMountObjCmd --
+ * ZipFSMountBufferObjCmd --
*
- * This procedure is invoked to process the "zipfs::mount" command.
+ * This procedure is invoked to process the "zipfs::mount_data" command.
*
* Results:
* A standard Tcl result.
@@ -1770,11 +1882,11 @@ ZipFSMountObjCmd(
static int
ZipFSMountBufferObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
- const char *mntpt;
+ const char *mountPoint; /* Mount point path. */
unsigned char *data;
int length;
@@ -1783,52 +1895,24 @@ ZipFSMountBufferObjCmd(
return TCL_ERROR;
}
if (objc < 2) {
- int i;
- Tcl_HashEntry *hPtr;
- Tcl_HashSearch search;
- int ret = TCL_OK;
- ZipFile *zf;
+ int ret;
ReadLock();
- i = 0;
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) {
- if (interp != NULL) {
- Tcl_AppendElement(interp, zf->mntpt);
- Tcl_AppendElement(interp, zf->name);
- }
- ++i;
- }
- hPtr = Tcl_NextHashEntry(&search);
- }
- if (interp == NULL) {
- ret = (i > 0) ? TCL_OK : TCL_BREAK;
- }
+ ret = ListMountPoints(interp);
Unlock();
return ret;
}
- mntpt = Tcl_GetString(objv[1]);
+ mountPoint = Tcl_GetString(objv[1]);
if (objc < 3) {
- Tcl_HashEntry *hPtr;
- ZipFile *zf;
-
- if (interp != NULL) {
- hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt);
- if (hPtr != NULL) {
- zf = Tcl_GetHashValue(hPtr);
- if (zf != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
- }
- }
- }
+ ReadLock();
+ DescribeMounted(interp, mountPoint);
Unlock();
return TCL_OK;
}
data = Tcl_GetByteArrayFromObj(objv[2], &length);
- return TclZipfs_Mount_Buffer(interp, mntpt, data, length, 1);
+ return TclZipfs_MountBuffer(interp, mountPoint, data, length, 1);
}
/*
@@ -1850,7 +1934,7 @@ ZipFSMountBufferObjCmd(
static int
ZipFSRootObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -1877,7 +1961,7 @@ ZipFSRootObjCmd(
static int
ZipFSUnmountObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -1908,12 +1992,12 @@ ZipFSUnmountObjCmd(
static int
ZipFSMkKeyObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
int len, i = 0;
- char *pw, pwbuf[264];
+ char *pw, passBuf[264];
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "password");
@@ -1924,25 +2008,25 @@ ZipFSMkKeyObjCmd(
if (len == 0) {
return TCL_OK;
}
- if ((len > 255) || (strchr(pw, 0xff) != NULL)) {
+ if ((len > 255) || strchr(pw, 0xff)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1));
return TCL_ERROR;
}
while (len > 0) {
int ch = pw[len - 1];
- pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
+ passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
i++;
len--;
}
- pwbuf[i] = i;
+ passBuf[i] = i;
++i;
- pwbuf[i++] = (char) ZIP_PASSWORD_END_SIG;
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8);
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16);
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24);
- pwbuf[i] = '\0';
- Tcl_AppendResult(interp, pwbuf, (char *) NULL);
+ passBuf[i++] = (char) ZIP_PASSWORD_END_SIG;
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8);
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16);
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24);
+ passBuf[i] = '\0';
+ Tcl_AppendResult(interp, passBuf, (char *) NULL);
return TCL_OK;
}
@@ -1968,11 +2052,12 @@ ZipFSMkKeyObjCmd(
static int
ZipAddFile(
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
const char *path,
const char *name,
Tcl_Channel out,
- const char *passwd,
+ const char *passwd, /* Password for encoding the file, or NULL if
+ * the file is to be unprotected. */
char *buf,
int bufsize,
Tcl_HashTable *fileHash)
@@ -1985,29 +2070,34 @@ ZipAddFile(
int crc, flush, zpathlen;
size_t nbyte, nbytecompr, len, olen, align = 0;
Tcl_WideInt pos[3];
- int mtime = 0, isNew, cmeth;
+ int mtime = 0, isNew, compMeth;
unsigned long keys[3], keys0[3];
char obuf[4096];
+ /*
+ * Trim leading '/' characters. If this results in an empty string, we've
+ * nothing to do.
+ */
+
zpath = name;
- while (zpath != NULL && zpath[0] == '/') {
+ while (zpath && zpath[0] == '/') {
zpath++;
}
- if ((zpath == NULL) || (zpath[0] == '\0')) {
+ if (!zpath || (zpath[0] == '\0')) {
return TCL_OK;
}
+
zpathlen = strlen(zpath);
if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) {
- Tcl_AppendResult(interp, "path too long for \"", path, "\"",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "path too long for \"%s\"", path));
return TCL_ERROR;
}
- in = Tcl_OpenFileChannel(interp, path, "r", 0);
- if ((in == NULL) || Tcl_SetChannelOption(interp, in,
- "-translation", "binary") != TCL_OK) {
+ in = Tcl_OpenFileChannel(interp, path, "rb", 0);
+ if (!in) {
#ifdef _WIN32
- /* hopefully a directory */
- if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) {
+ /* hopefully a directory */
+ if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) {
Tcl_Close(interp, in);
return TCL_OK;
}
@@ -2027,26 +2117,27 @@ ZipAddFile(
Tcl_ResetResult(interp);
crc = 0;
nbyte = nbytecompr = 0;
- while ((len = Tcl_Read(in, buf, bufsize)) + 1 > 1) {
- crc = crc32(crc, (unsigned char *) buf, len);
- nbyte += len;
- }
- if (len == (size_t)-1) {
- if (nbyte == 0) {
- if (strcmp("illegal operation on a directory",
- Tcl_PosixError(interp)) == 0) {
+ while (1) {
+ len = Tcl_Read(in, buf, bufsize);
+ if (len == ERROR_LENGTH) {
+ if (nbyte == 0 && errno == EISDIR) {
Tcl_Close(interp, in);
return TCL_OK;
}
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s",
+ path, Tcl_PosixError(interp)));
+ Tcl_Close(interp, in);
+ return TCL_ERROR;
}
- Tcl_AppendResult(interp, "read error on \"", path, "\"",
- (char *) NULL);
- Tcl_Close(interp, in);
- return TCL_ERROR;
+ if (len == 0) {
+ break;
+ }
+ crc = crc32(crc, (unsigned char *) buf, len);
+ nbyte += len;
}
if (Tcl_Seek(in, 0, SEEK_SET) == -1) {
- Tcl_AppendResult(interp, "seek error on \"", path, "\"",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("seek error on \"%s\": %s",
+ path, Tcl_PosixError(interp)));
Tcl_Close(interp, in);
return TCL_ERROR;
}
@@ -2054,9 +2145,10 @@ ZipAddFile(
memset(buf, '\0', ZIP_LOCAL_HEADER_LEN);
memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen);
len = zpathlen + ZIP_LOCAL_HEADER_LEN;
- if ((size_t)Tcl_Write(out, buf, len) != len) {
+ if ((size_t) Tcl_Write(out, buf, len) != len) {
wrerr:
- Tcl_AppendResult(interp, "write error", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error on %s: %s", path, Tcl_PosixError(interp)));
Tcl_Close(interp, in);
return TCL_ERROR;
}
@@ -2069,69 +2161,74 @@ ZipAddFile(
*/
align = 4 + ((len + pos[0]) & 3);
- zip_write_short(abuf, 0xffff);
- zip_write_short(abuf + 2, align - 4);
- zip_write_int(abuf + 4, 0x03020100);
+ ZipWriteShort(abuf, 0xffff);
+ ZipWriteShort(abuf + 2, align - 4);
+ ZipWriteInt(abuf + 4, 0x03020100);
if ((size_t) Tcl_Write(out, (const char *) abuf, align) != align) {
goto wrerr;
}
}
- if (passwd != NULL) {
+ if (passwd) {
int i, ch, tmp;
unsigned char kvbuf[24];
Tcl_Obj *ret;
init_keys(passwd, keys, crc32tab);
for (i = 0; i < 12 - 2; i++) {
- if (Tcl_EvalEx(interp, "expr int(rand() * 256) % 256", -1,
- 0) != TCL_OK) {
- Tcl_AppendResult(interp, "PRNG error", (char *) NULL);
+ double r;
+
+ if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", -1, 0) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("PRNG error: %s",
+ Tcl_GetString(Tcl_GetObjResult(interp))));
Tcl_Close(interp, in);
return TCL_ERROR;
}
ret = Tcl_GetObjResult(interp);
- if (Tcl_GetIntFromObj(interp, ret, &ch) != TCL_OK) {
+ if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) {
Tcl_Close(interp, in);
return TCL_ERROR;
}
+ ch = (int) (r * 256);
kvbuf[i + 12] = (unsigned char) zencode(keys, crc32tab, ch, tmp);
}
Tcl_ResetResult(interp);
init_keys(passwd, keys, crc32tab);
for (i = 0; i < 12 - 2; i++) {
- kvbuf[i] = (unsigned char) zencode(keys, crc32tab, kvbuf[i + 12], tmp);
+ kvbuf[i] = (unsigned char)
+ zencode(keys, crc32tab, kvbuf[i + 12], tmp);
}
kvbuf[i++] = (unsigned char) zencode(keys, crc32tab, crc >> 16, tmp);
kvbuf[i++] = (unsigned char) zencode(keys, crc32tab, crc >> 24, tmp);
len = Tcl_Write(out, (char *) kvbuf, 12);
memset(kvbuf, 0, 24);
if (len != 12) {
- Tcl_AppendResult(interp, "write error", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error on %s: %s", path, Tcl_PosixError(interp)));
Tcl_Close(interp, in);
return TCL_ERROR;
}
- memcpy(keys0, keys, sizeof (keys0));
+ memcpy(keys0, keys, sizeof(keys0));
nbytecompr += 12;
}
Tcl_Flush(out);
pos[2] = Tcl_Tell(out);
- cmeth = ZIP_COMPMETH_DEFLATED;
- memset(&stream, 0, sizeof (stream));
+ compMeth = ZIP_COMPMETH_DEFLATED;
+ memset(&stream, 0, sizeof(z_stream));
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
- Tcl_AppendResult(interp, "compression init error on \"", path, "\"",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "compression init error on \"%s\"", path));
Tcl_Close(interp, in);
return TCL_ERROR;
}
do {
len = Tcl_Read(in, buf, bufsize);
- if (len == (size_t)-1) {
- Tcl_AppendResult(interp, "read error on \"", path, "\"",
- (char *) NULL);
+ if (len == ERROR_LENGTH) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "read error on %s: %s", path, Tcl_PosixError(interp)));
deflateEnd(&stream);
Tcl_Close(interp, in);
return TCL_ERROR;
@@ -2140,18 +2237,18 @@ ZipAddFile(
stream.next_in = (unsigned char *) buf;
flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH;
do {
- stream.avail_out = sizeof (obuf);
+ stream.avail_out = sizeof(obuf);
stream.next_out = (unsigned char *) obuf;
len = deflate(&stream, flush);
- if (len == (size_t)Z_STREAM_ERROR) {
- Tcl_AppendResult(interp, "deflate error on \"", path, "\"",
- (char *) NULL);
+ if (len == (size_t) Z_STREAM_ERROR) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "deflate error on %s", path));
deflateEnd(&stream);
Tcl_Close(interp, in);
return TCL_ERROR;
}
- olen = sizeof (obuf) - stream.avail_out;
- if (passwd != NULL) {
+ olen = sizeof(obuf) - stream.avail_out;
+ if (passwd) {
size_t i;
int tmp;
@@ -2159,8 +2256,9 @@ ZipAddFile(
obuf[i] = (char) zencode(keys, crc32tab, obuf[i], tmp);
}
}
- if (olen && ((size_t)Tcl_Write(out, obuf, olen) != olen)) {
- Tcl_AppendResult(interp, "write error", (char *) NULL);
+ if (olen && ((size_t) Tcl_Write(out, obuf, olen) != olen)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
deflateEnd(&stream);
Tcl_Close(interp, in);
return TCL_ERROR;
@@ -2181,21 +2279,23 @@ ZipAddFile(
if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) {
seekErr:
Tcl_Close(interp, in);
- Tcl_AppendResult(interp, "seek error", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "seek error: %s", Tcl_PosixError(interp)));
return TCL_ERROR;
}
- nbytecompr = (passwd != NULL) ? 12 : 0;
+ nbytecompr = (passwd ? 12 : 0);
while (1) {
len = Tcl_Read(in, buf, bufsize);
- if (len == (size_t)-1) {
- Tcl_AppendResult(interp, "read error on \"", path, "\"",
- (char *) NULL);
+ if (len == ERROR_LENGTH) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "read error on \"%s\": %s",
+ path, Tcl_PosixError(interp)));
Tcl_Close(interp, in);
return TCL_ERROR;
} else if (len == 0) {
break;
}
- if (passwd != NULL) {
+ if (passwd) {
size_t i;
int tmp;
@@ -2203,42 +2303,43 @@ ZipAddFile(
buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp);
}
}
- if ((size_t)Tcl_Write(out, buf, len) != len) {
- Tcl_AppendResult(interp, "write error", (char *) NULL);
+ if ((size_t) Tcl_Write(out, buf, len) != len) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
Tcl_Close(interp, in);
return TCL_ERROR;
}
nbytecompr += len;
}
- cmeth = ZIP_COMPMETH_STORED;
+ compMeth = ZIP_COMPMETH_STORED;
Tcl_Flush(out);
pos[1] = Tcl_Tell(out);
Tcl_TruncateChannel(out, pos[1]);
}
Tcl_Close(interp, in);
- z = (ZipEntry *) Tcl_Alloc(sizeof (*z));
+ z = ckalloc(sizeof(ZipEntry));
z->name = NULL;
z->tnext = NULL;
z->depth = 0;
- z->zipfile = NULL;
- z->isdir = 0;
- z->isenc = (passwd != NULL) ? 1 : 0;
+ z->zipFilePtr = NULL;
+ z->isDirectory = 0;
+ z->isEncrypted = (passwd ? 1 : 0);
z->offset = pos[0];
z->crc32 = crc;
z->timestamp = mtime;
- z->nbyte = nbyte;
- z->nbytecompr = nbytecompr;
- z->cmeth = cmeth;
+ z->numBytes = nbyte;
+ z->numCompressedBytes = nbytecompr;
+ z->compressMethod = compMeth;
z->data = NULL;
hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew);
if (!isNew) {
- Tcl_AppendResult(interp, "non-unique path name \"", path, "\"",
- (char *) NULL);
- Tcl_Free((char *) z);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "non-unique path name \"%s\"", path));
+ ckfree(z);
return TCL_ERROR;
} else {
- Tcl_SetHashValue(hPtr, (ClientData) z);
+ Tcl_SetHashValue(hPtr, z);
z->name = Tcl_GetHashKey(fileHash, hPtr);
z->next = NULL;
}
@@ -2246,34 +2347,37 @@ ZipAddFile(
/*
* Write final local header information.
*/
- zip_write_int(buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG);
- zip_write_short(buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION);
- zip_write_short(buf + ZIP_LOCAL_FLAGS_OFFS, z->isenc);
- zip_write_short(buf + ZIP_LOCAL_COMPMETH_OFFS, z->cmeth);
- zip_write_short(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp));
- zip_write_short(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp));
- zip_write_int(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
- zip_write_int(buf + ZIP_LOCAL_COMPLEN_OFFS, z->nbytecompr);
- zip_write_int(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->nbyte);
- zip_write_short(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen);
- zip_write_short(buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
+ ZipWriteInt(buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG);
+ ZipWriteShort(buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION);
+ ZipWriteShort(buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted);
+ ZipWriteShort(buf + ZIP_LOCAL_COMPMETH_OFFS, z->compressMethod);
+ ZipWriteShort(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp));
+ ZipWriteShort(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp));
+ ZipWriteInt(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
+ ZipWriteInt(buf + ZIP_LOCAL_COMPLEN_OFFS, z->numCompressedBytes);
+ ZipWriteInt(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->numBytes);
+ ZipWriteShort(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen);
+ ZipWriteShort(buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
if (Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) {
Tcl_DeleteHashEntry(hPtr);
- Tcl_Free((char *) z);
- Tcl_AppendResult(interp, "seek error", (char *) NULL);
+ ckfree(z);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "seek error: %s", Tcl_PosixError(interp)));
return TCL_ERROR;
}
if (Tcl_Write(out, buf, ZIP_LOCAL_HEADER_LEN) != ZIP_LOCAL_HEADER_LEN) {
Tcl_DeleteHashEntry(hPtr);
- Tcl_Free((char *) z);
- Tcl_AppendResult(interp, "write error", (char *) NULL);
+ ckfree(z);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
return TCL_ERROR;
}
Tcl_Flush(out);
if (Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) {
Tcl_DeleteHashEntry(hPtr);
- Tcl_Free((char *) z);
- Tcl_AppendResult(interp, "seek error", (char *) NULL);
+ ckfree(z);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "seek error: %s", Tcl_PosixError(interp)));
return TCL_ERROR;
}
return TCL_OK;
@@ -2301,7 +2405,7 @@ ZipAddFile(
static int
ZipFSMkZipOrImgObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int isImg,
int isList,
int objc,
@@ -2316,28 +2420,17 @@ ZipFSMkZipOrImgObjCmd(
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
Tcl_HashTable fileHash;
- char *strip = NULL, *pw = NULL, pwbuf[264], buf[4096];
+ char *strip = NULL, *pw = NULL, passBuf[264], buf[4096];
- if (isList) {
- if ((objc < 3) || (objc > (isImg ? 5 : 4))) {
- Tcl_WrongNumArgs(interp, 1, objv, isImg ?
- "outfile inlist ?password infile?" :
- "outfile inlist ?password?");
- return TCL_ERROR;
- }
- } else {
- if ((objc < 3) || (objc > (isImg ? 6 : 5))) {
- Tcl_WrongNumArgs(interp, 1, objv, isImg ?
- "outfile indir ?strip? ?password? ?infile?" :
- "outfile indir ?strip? ?password?");
- return TCL_ERROR;
- }
- }
- pwbuf[0] = 0;
+ /*
+ * Caller has verified that the number of arguments is correct.
+ */
+
+ passBuf[0] = 0;
if (objc > (isList ? 3 : 4)) {
pw = Tcl_GetString(objv[isList ? 3 : 4]);
pwlen = strlen(pw);
- if ((pwlen > 255) || (strchr(pw, 0xff) != NULL)) {
+ if ((pwlen > 255) || strchr(pw, 0xff)) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("illegal password", -1));
return TCL_ERROR;
@@ -2376,11 +2469,9 @@ ZipFSMkZipOrImgObjCmd(
Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1));
return TCL_ERROR;
}
- out = Tcl_OpenFileChannel(interp, Tcl_GetString(objv[1]), "w", 0755);
- if ((out == NULL) || (Tcl_SetChannelOption(interp, out,
- "-translation", "binary") != TCL_OK)) {
+ out = Tcl_OpenFileChannel(interp, Tcl_GetString(objv[1]), "wb", 0755);
+ if (out == NULL) {
Tcl_DecrRefCount(list);
- Tcl_Close(interp, out);
return TCL_ERROR;
}
if (pwlen <= 0) {
@@ -2401,34 +2492,34 @@ ZipFSMkZipOrImgObjCmd(
}
if (pwlen) {
i = 0;
- len = pwlen;
- while (len > 0) {
- int ch = pw[len - 1];
+ for (len = pwlen; len-- > 0;) {
+ int ch = pw[len];
- pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
+ passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
i++;
- len--;
}
- pwbuf[i] = i;
+ passBuf[i] = i;
++i;
- pwbuf[i++] = (char) ZIP_PASSWORD_END_SIG;
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8);
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16);
- pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24);
- pwbuf[i] = '\0';
+ passBuf[i++] = (char) ZIP_PASSWORD_END_SIG;
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8);
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16);
+ passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24);
+ passBuf[i] = '\0';
}
- /* Check for mounted image */
+
+ /*
+ * Check for mounted image.
+ */
+
WriteLock();
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) {
- if (strcmp(zf->name, imgName) == 0) {
- isMounted = 1;
- zf->nopen++;
- break;
- }
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ zf = Tcl_GetHashValue(hPtr);
+ if (strcmp(zf->name, imgName) == 0) {
+ isMounted = 1;
+ zf->numOpen++;
+ break;
}
- hPtr = Tcl_NextHashEntry(&search);
}
Unlock();
if (!isMounted) {
@@ -2436,16 +2527,17 @@ ZipFSMkZipOrImgObjCmd(
}
if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) {
if ((size_t) Tcl_Write(out, (char *) zf->data,
- zf->baseoffsp) != zf->baseoffsp) {
- memset(pwbuf, 0, sizeof (pwbuf));
+ zf->passOffset) != zf->passOffset) {
+ memset(passBuf, 0, sizeof(passBuf));
Tcl_DecrRefCount(list);
- Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
Tcl_Close(interp, out);
if (zf == &zf0) {
ZipFSCloseArchive(interp, zf);
} else {
WriteLock();
- zf->nopen--;
+ zf->numOpen--;
Unlock();
}
return TCL_ERROR;
@@ -2454,7 +2546,7 @@ ZipFSMkZipOrImgObjCmd(
ZipFSCloseArchive(interp, zf);
} else {
WriteLock();
- zf->nopen--;
+ zf->numOpen--;
Unlock();
}
} else {
@@ -2469,30 +2561,29 @@ ZipFSMkZipOrImgObjCmd(
*/
Tcl_ResetResult(interp);
- in = Tcl_OpenFileChannel(interp, imgName, "r", 0644);
- if (in == NULL) {
- memset(pwbuf, 0, sizeof (pwbuf));
+ in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644);
+ if (!in) {
+ memset(passBuf, 0, sizeof(passBuf));
Tcl_DecrRefCount(list);
Tcl_Close(interp, out);
return TCL_ERROR;
}
- Tcl_SetChannelOption(interp, in, "-translation", "binary");
i = Tcl_Seek(in, 0, SEEK_END);
- if (i == (size_t)-1) {
+ if (i == ERROR_LENGTH) {
cperr:
- memset(pwbuf, 0, sizeof (pwbuf));
+ memset(passBuf, 0, sizeof(passBuf));
Tcl_DecrRefCount(list);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s: %s", errMsg, Tcl_PosixError(interp)));
Tcl_Close(interp, out);
Tcl_Close(interp, in);
return TCL_ERROR;
}
Tcl_Seek(in, 0, SEEK_SET);
- k = 0;
- while (k < i) {
+ for (k = 0; k < i; k += m) {
m = i - k;
- if (m > (int)sizeof (buf)) {
- m = (int)sizeof (buf);
+ if (m > (int) sizeof(buf)) {
+ m = (int) sizeof(buf);
}
n = Tcl_Read(in, buf, m);
if (n == -1) {
@@ -2506,21 +2597,21 @@ ZipFSMkZipOrImgObjCmd(
errMsg = "write error";
goto cperr;
}
- k += m;
}
Tcl_Close(interp, in);
}
- len = strlen(pwbuf);
+ len = strlen(passBuf);
if (len > 0) {
- i = Tcl_Write(out, pwbuf, len);
+ i = Tcl_Write(out, passBuf, len);
if (i != len) {
Tcl_DecrRefCount(list);
- Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
Tcl_Close(interp, out);
return TCL_ERROR;
}
}
- memset(pwbuf, 0, sizeof (pwbuf));
+ memset(passBuf, 0, sizeof(passBuf));
Tcl_Flush(out);
}
Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
@@ -2529,7 +2620,7 @@ ZipFSMkZipOrImgObjCmd(
strip = Tcl_GetString(objv[3]);
slen = strlen(strip);
}
- for (i = 0; i < (size_t)lobjc; i += (isList ? 2 : 1)) {
+ for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) {
const char *path, *name;
path = Tcl_GetString(lobjv[i]);
@@ -2551,14 +2642,14 @@ ZipFSMkZipOrImgObjCmd(
if (name[0] == '\0') {
continue;
}
- if (ZipAddFile(interp, path, name, out, pw, buf, sizeof (buf),
- &fileHash) != TCL_OK) {
+ if (ZipAddFile(interp, path, name, out, pw, buf, sizeof(buf),
+ &fileHash) != TCL_OK) {
goto done;
}
}
pos[1] = Tcl_Tell(out);
count = 0;
- for (i = 0; i < (size_t)lobjc; i += (isList ? 2 : 1)) {
+ for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) {
const char *path, *name;
path = Tcl_GetString(lobjv[i]);
@@ -2581,52 +2672,55 @@ ZipFSMkZipOrImgObjCmd(
continue;
}
hPtr = Tcl_FindHashEntry(&fileHash, name);
- if (hPtr == NULL) {
+ if (!hPtr) {
continue;
}
z = Tcl_GetHashValue(hPtr);
len = strlen(z->name);
- zip_write_int(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG);
- zip_write_short(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION);
- zip_write_short(buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION);
- zip_write_short(buf + ZIP_CENTRAL_FLAGS_OFFS, z->isenc ? 1 : 0);
- zip_write_short(buf + ZIP_CENTRAL_COMPMETH_OFFS, z->cmeth);
- zip_write_short(buf + ZIP_CENTRAL_MTIME_OFFS, ToDosTime(z->timestamp));
- zip_write_short(buf + ZIP_CENTRAL_MDATE_OFFS, ToDosDate(z->timestamp));
- zip_write_int(buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32);
- zip_write_int(buf + ZIP_CENTRAL_COMPLEN_OFFS, z->nbytecompr);
- zip_write_int(buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->nbyte);
- zip_write_short(buf + ZIP_CENTRAL_PATHLEN_OFFS, len);
- zip_write_short(buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0);
- zip_write_short(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
- zip_write_short(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
- zip_write_short(buf + ZIP_CENTRAL_IATTR_OFFS, 0);
- zip_write_int(buf + ZIP_CENTRAL_EATTR_OFFS, 0);
- zip_write_int(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]);
+ ZipWriteInt(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG);
+ ZipWriteShort(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION);
+ ZipWriteShort(buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION);
+ ZipWriteShort(buf + ZIP_CENTRAL_FLAGS_OFFS, z->isEncrypted);
+ ZipWriteShort(buf + ZIP_CENTRAL_COMPMETH_OFFS, z->compressMethod);
+ ZipWriteShort(buf + ZIP_CENTRAL_MTIME_OFFS, ToDosTime(z->timestamp));
+ ZipWriteShort(buf + ZIP_CENTRAL_MDATE_OFFS, ToDosDate(z->timestamp));
+ ZipWriteInt(buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32);
+ ZipWriteInt(buf + ZIP_CENTRAL_COMPLEN_OFFS, z->numCompressedBytes);
+ ZipWriteInt(buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->numBytes);
+ ZipWriteShort(buf + ZIP_CENTRAL_PATHLEN_OFFS, len);
+ ZipWriteShort(buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0);
+ ZipWriteShort(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
+ ZipWriteShort(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
+ ZipWriteShort(buf + ZIP_CENTRAL_IATTR_OFFS, 0);
+ ZipWriteInt(buf + ZIP_CENTRAL_EATTR_OFFS, 0);
+ ZipWriteInt(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]);
if ((Tcl_Write(out, buf,
ZIP_CENTRAL_HEADER_LEN) != ZIP_CENTRAL_HEADER_LEN)
- || ((size_t)Tcl_Write(out, z->name, len) != len)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
+ || ((size_t) Tcl_Write(out, z->name, len) != len)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
goto done;
}
count++;
}
Tcl_Flush(out);
pos[2] = Tcl_Tell(out);
- zip_write_int(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG);
- zip_write_short(buf + ZIP_CENTRAL_DISKNO_OFFS, 0);
- zip_write_short(buf + ZIP_CENTRAL_DISKDIR_OFFS, 0);
- zip_write_short(buf + ZIP_CENTRAL_ENTS_OFFS, count);
- zip_write_short(buf + ZIP_CENTRAL_TOTALENTS_OFFS, count);
- zip_write_int(buf + ZIP_CENTRAL_DIRSIZE_OFFS, pos[2] - pos[1]);
- zip_write_int(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]);
- zip_write_short(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0);
+ ZipWriteInt(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG);
+ ZipWriteShort(buf + ZIP_CENTRAL_DISKNO_OFFS, 0);
+ ZipWriteShort(buf + ZIP_CENTRAL_DISKDIR_OFFS, 0);
+ ZipWriteShort(buf + ZIP_CENTRAL_ENTS_OFFS, count);
+ ZipWriteShort(buf + ZIP_CENTRAL_TOTALENTS_OFFS, count);
+ ZipWriteInt(buf + ZIP_CENTRAL_DIRSIZE_OFFS, pos[2] - pos[1]);
+ ZipWriteInt(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]);
+ ZipWriteShort(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0);
if (Tcl_Write(out, buf, ZIP_CENTRAL_END_LEN) != ZIP_CENTRAL_END_LEN) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "write error: %s", Tcl_PosixError(interp)));
goto done;
}
Tcl_Flush(out);
ret = TCL_OK;
+
done:
if (ret == TCL_OK) {
ret = Tcl_Close(interp, out);
@@ -2634,12 +2728,11 @@ ZipFSMkZipOrImgObjCmd(
Tcl_Close(interp, out);
}
Tcl_DecrRefCount(list);
- hPtr = Tcl_FirstHashEntry(&fileHash, &search);
- while (hPtr != NULL) {
- z = (ZipEntry *) Tcl_GetHashValue(hPtr);
- Tcl_Free((char *) z);
+ for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ z = Tcl_GetHashValue(hPtr);
+ ckfree(z);
Tcl_DeleteHashEntry(hPtr);
- hPtr = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(&fileHash);
return ret;
@@ -2665,20 +2758,38 @@ ZipFSMkZipOrImgObjCmd(
static int
ZipFSMkZipObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password?");
+ return TCL_ERROR;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "operation not permitted in a safe interpreter", -1));
+ return TCL_ERROR;
+ }
return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 0, objc, objv);
}
static int
ZipFSLMkZipObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password?");
+ return TCL_ERROR;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "operation not permitted in a safe interpreter", -1));
+ return TCL_ERROR;
+ }
return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 1, objc, objv);
}
@@ -2702,20 +2813,39 @@ ZipFSLMkZipObjCmd(
static int
ZipFSMkImgObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
+ if (objc < 3 || objc > 6) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "outfile indir ?strip? ?password? ?infile?");
+ return TCL_ERROR;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "operation not permitted in a safe interpreter", -1));
+ return TCL_ERROR;
+ }
return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 0, objc, objv);
}
static int
ZipFSLMkImgObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password infile?");
+ return TCL_ERROR;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "operation not permitted in a safe interpreter", -1));
+ return TCL_ERROR;
+ }
return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 1, objc, objv);
}
@@ -2739,16 +2869,16 @@ ZipFSLMkImgObjCmd(
static int
ZipFSCanonicalObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
- Tcl_Obj *const objv[]
-) {
+ Tcl_Obj *const objv[])
+{
char *mntpoint = NULL;
char *filename = NULL;
char *result;
Tcl_DString dPath;
- if (objc != 2 && objc != 3 && objc != 4) {
+ if (objc < 2 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv, "?mntpnt? filename ?ZIPFS?");
return TCL_ERROR;
}
@@ -2795,7 +2925,7 @@ ZipFSCanonicalObjCmd(
static int
ZipFSExistsObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -2848,7 +2978,7 @@ ZipFSExistsObjCmd(
static int
ZipFSInfoObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -2862,14 +2992,15 @@ ZipFSInfoObjCmd(
filename = Tcl_GetStringFromObj(objv[1], 0);
ReadLock();
z = ZipFSLookup(filename);
- if (z != NULL) {
+ if (z) {
Tcl_Obj *result = Tcl_GetObjResult(interp);
Tcl_ListObjAppendElement(interp, result,
- Tcl_NewStringObj(z->zipfile->name, -1));
- Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->nbyte));
+ Tcl_NewStringObj(z->zipFilePtr->name, -1));
Tcl_ListObjAppendElement(interp, result,
- Tcl_NewWideIntObj(z->nbytecompr));
+ Tcl_NewWideIntObj(z->numBytes));
+ Tcl_ListObjAppendElement(interp, result,
+ Tcl_NewWideIntObj(z->numCompressedBytes));
Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset));
}
Unlock();
@@ -2897,7 +3028,7 @@ ZipFSInfoObjCmd(
static int
ZipFSListObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -2919,19 +3050,19 @@ ZipFSListObjCmd(
pattern = Tcl_GetString(objv[2]);
} else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) {
regexp = Tcl_RegExpCompile(interp, Tcl_GetString(objv[2]));
- if (regexp == NULL) {
+ if (!regexp) {
return TCL_ERROR;
}
} else {
- Tcl_AppendResult(interp, "unknown option \"", what, "\"",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown option \"%s\"", what));
return TCL_ERROR;
}
} else if (objc == 2) {
pattern = Tcl_GetStringFromObj(objv[1], 0);
}
ReadLock();
- if (pattern != NULL) {
+ if (pattern) {
for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
ZipEntry *z = Tcl_GetHashValue(hPtr);
@@ -2941,9 +3072,9 @@ ZipFSListObjCmd(
Tcl_NewStringObj(z->name, -1));
}
}
- } else if (regexp != NULL) {
+ } else if (regexp) {
for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ hPtr; hPtr = Tcl_NextHashEntry(&search)) {
ZipEntry *z = Tcl_GetHashValue(hPtr);
if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) {
@@ -2953,7 +3084,7 @@ ZipFSListObjCmd(
}
} else {
for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ hPtr; hPtr = Tcl_NextHashEntry(&search)) {
ZipEntry *z = Tcl_GetHashValue(hPtr);
Tcl_ListObjAppendElement(interp, result,
@@ -2966,6 +3097,7 @@ ZipFSListObjCmd(
#ifdef _WIN32
#define LIBRARY_SIZE 64
+
static int
ToUtf(
const WCHAR *wSrc,
@@ -2981,7 +3113,7 @@ ToUtf(
*dst = '\0';
return (int) (dst - start);
}
-#endif
+#endif /* _WIN32 */
Tcl_Obj *
TclZipfs_TclLibrary(void)
@@ -3010,7 +3142,7 @@ TclZipfs_TclLibrary(void)
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
-#ifdef _WIN32
+#if defined(_WIN32)
if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
GetModuleFileNameA(hModule, dllname, MAX_PATH);
} else {
@@ -3021,31 +3153,29 @@ TclZipfs_TclLibrary(void)
* Mount zip file and dll before releasing to search.
*/
- if (TclZipfs_AppHook_FindTclInit(dllname) == TCL_OK) {
+ if (ZipfsAppHookFindTclInit(dllname) == TCL_OK) {
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
-#else /* !_WIN32 */
-#ifdef CFG_RUNTIME_DLLFILE
+#elif /* !_WIN32 && */ defined(CFG_RUNTIME_DLLFILE)
/*
* Mount zip file and dll before releasing to search.
*/
- if (TclZipfs_AppHook_FindTclInit(
+ if (ZipfsAppHookFindTclInit(
CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
-#endif /* CFG_RUNTIME_DLLFILE */
-#endif /* _WIN32 */
+#endif /* _WIN32 || CFG_RUNTIME_DLLFILE */
#ifdef CFG_RUNTIME_ZIPFILE
- if (TclZipfs_AppHook_FindTclInit(
+ if (ZipfsAppHookFindTclInit(
CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
- if (TclZipfs_AppHook_FindTclInit(
+ if (ZipfsAppHookFindTclInit(
CFG_RUNTIME_SCRDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
- if (TclZipfs_AppHook_FindTclInit(CFG_RUNTIME_ZIPFILE) == TCL_OK) {
+ if (ZipfsAppHookFindTclInit(CFG_RUNTIME_ZIPFILE) == TCL_OK) {
return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
}
#endif /* CFG_RUNTIME_ZIPFILE */
@@ -3061,8 +3191,8 @@ TclZipfs_TclLibrary(void)
*
* ZipFSTclLibraryObjCmd --
*
- * This procedure is invoked to process the "zipfs::root" command. It
- * returns the root that all zipfs file systems are mounted under.
+ * This procedure is invoked to process the "zipfs::tcl_library" command.
+ * It returns the root that all zipfs file systems are mounted under.
*
* Results:
* A standard Tcl result.
@@ -3075,7 +3205,7 @@ TclZipfs_TclLibrary(void)
static int
ZipFSTclLibraryObjCmd(
ClientData clientData,
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
int objc,
Tcl_Obj *const objv[])
{
@@ -3107,44 +3237,42 @@ ZipFSTclLibraryObjCmd(
static int
ZipChannelClose(
ClientData instanceData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp) /* Current interpreter. */
{
- ZipChannel *info = (ZipChannel *) instanceData;
+ ZipChannel *info = instanceData;
- if (info->iscompr && (info->ubuf != NULL)) {
- Tcl_Free((char *) info->ubuf);
+ if (info->iscompr && info->ubuf) {
+ ckfree(info->ubuf);
info->ubuf = NULL;
}
- if (info->isenc) {
- info->isenc = 0;
- memset(info->keys, 0, sizeof (info->keys));
+ if (info->isEncrypted) {
+ info->isEncrypted = 0;
+ memset(info->keys, 0, sizeof(info->keys));
}
- if (info->iswr) {
- ZipEntry *z = info->zipentry;
- unsigned char *newdata;
+ if (info->isWriting) {
+ ZipEntry *z = info->zipEntryPtr;
+ unsigned char *newdata = attemptckrealloc(info->ubuf, info->numRead);
- newdata = (unsigned char *)
- Tcl_AttemptRealloc((char *) info->ubuf, info->nread);
- if (newdata != NULL) {
- if (z->data != NULL) {
- Tcl_Free((char *) z->data);
+ if (newdata) {
+ if (z->data) {
+ ckfree(z->data);
}
z->data = newdata;
- z->nbyte = z->nbytecompr = info->nbyte;
- z->cmeth = ZIP_COMPMETH_STORED;
+ z->numBytes = z->numCompressedBytes = info->numBytes;
+ z->compressMethod = ZIP_COMPMETH_STORED;
z->timestamp = time(NULL);
- z->isdir = 0;
- z->isenc = 0;
+ z->isDirectory = 0;
+ z->isEncrypted = 0;
z->offset = 0;
z->crc32 = 0;
} else {
- Tcl_Free((char *) info->ubuf);
+ ckfree(info->ubuf);
}
}
WriteLock();
- info->zipfile->nopen--;
+ info->zipFilePtr->numOpen--;
Unlock();
- Tcl_Free((char *) info);
+ ckfree(info);
return TCL_OK;
}
@@ -3153,13 +3281,13 @@ ZipChannelClose(
*
* ZipChannelRead --
*
- * This function is called to read data from channel.
+ * This function is called to read data from channel.
*
* Results:
- * Number of bytes read or -1 on error with error number set.
+ * Number of bytes read or -1 on error with error number set.
*
* Side effects:
- * Data is read and file pointer is advanced.
+ * Data is read and file pointer is advanced.
*
*-------------------------------------------------------------------------
*/
@@ -3174,47 +3302,49 @@ ZipChannelRead(
ZipChannel *info = (ZipChannel *) instanceData;
unsigned long nextpos;
- if (info->isdir < 0) {
+ if (info->isDirectory < 0) {
/*
* Special case: when executable combined with ZIP archive file read
* data in front of ZIP, i.e. the executable itself.
*/
- nextpos = info->nread + toRead;
- if (nextpos > info->zipfile->baseoffs) {
- toRead = info->zipfile->baseoffs - info->nread;
- nextpos = info->zipfile->baseoffs;
+
+ nextpos = info->numRead + toRead;
+ if (nextpos > info->zipFilePtr->baseOffset) {
+ toRead = info->zipFilePtr->baseOffset - info->numRead;
+ nextpos = info->zipFilePtr->baseOffset;
}
if (toRead == 0) {
return 0;
}
- memcpy(buf, info->zipfile->data, toRead);
- info->nread = nextpos;
+ memcpy(buf, info->zipFilePtr->data, toRead);
+ info->numRead = nextpos;
*errloc = 0;
return toRead;
}
- if (info->isdir) {
+ if (info->isDirectory) {
*errloc = EISDIR;
return -1;
}
- nextpos = info->nread + toRead;
- if (nextpos > info->nbyte) {
- toRead = info->nbyte - info->nread;
- nextpos = info->nbyte;
+ nextpos = info->numRead + toRead;
+ if (nextpos > info->numBytes) {
+ toRead = info->numBytes - info->numRead;
+ nextpos = info->numBytes;
}
if (toRead == 0) {
return 0;
}
- if (info->isenc) {
- int i, ch;
+ if (info->isEncrypted) {
+ int i;
for (i = 0; i < toRead; i++) {
- ch = info->ubuf[i + info->nread];
+ int ch = info->ubuf[i + info->numRead];
+
buf[i] = zdecode(info->keys, crc32tab, ch);
}
} else {
- memcpy(buf, info->ubuf + info->nread, toRead);
+ memcpy(buf, info->ubuf + info->numRead, toRead);
}
- info->nread = nextpos;
+ info->numRead = nextpos;
*errloc = 0;
return toRead;
}
@@ -3245,22 +3375,22 @@ ZipChannelWrite(
ZipChannel *info = (ZipChannel *) instanceData;
unsigned long nextpos;
- if (!info->iswr) {
+ if (!info->isWriting) {
*errloc = EINVAL;
return -1;
}
- nextpos = info->nread + toWrite;
- if (nextpos > info->nmax) {
- toWrite = info->nmax - info->nread;
- nextpos = info->nmax;
+ nextpos = info->numRead + toWrite;
+ if (nextpos > info->maxWrite) {
+ toWrite = info->maxWrite - info->numRead;
+ nextpos = info->maxWrite;
}
if (toWrite == 0) {
return 0;
}
- memcpy(info->ubuf + info->nread, buf, toWrite);
- info->nread = nextpos;
- if (info->nread > info->nbyte) {
- info->nbyte = info->nread;
+ memcpy(info->ubuf + info->numRead, buf, toWrite);
+ info->numRead = nextpos;
+ if (info->numRead > info->numBytes) {
+ info->numBytes = info->numRead;
}
*errloc = 0;
return toWrite;
@@ -3271,13 +3401,13 @@ ZipChannelWrite(
*
* ZipChannelSeek --
*
- * This function is called to position file pointer of channel.
+ * This function is called to position file pointer of channel.
*
* Results:
- * New file position or -1 on error with error number set.
+ * New file position or -1 on error with error number set.
*
* Side effects:
- * File pointer is repositioned according to offset and mode.
+ * File pointer is repositioned according to offset and mode.
*
*-------------------------------------------------------------------------
*/
@@ -3292,21 +3422,21 @@ ZipChannelSeek(
ZipChannel *info = (ZipChannel *) instanceData;
unsigned long end;
- if (!info->iswr && (info->isdir < 0)) {
+ if (!info->isWriting && (info->isDirectory < 0)) {
/*
* Special case: when executable combined with ZIP archive file, seek
* within front of ZIP, i.e. the executable itself.
*/
- end = info->zipfile->baseoffs;
- } else if (info->isdir) {
+ end = info->zipFilePtr->baseOffset;
+ } else if (info->isDirectory) {
*errloc = EINVAL;
return -1;
} else {
- end = info->nbyte;
+ end = info->numBytes;
}
switch (mode) {
case SEEK_CUR:
- offset += info->nread;
+ offset += info->numRead;
break;
case SEEK_END:
offset += end;
@@ -3321,20 +3451,20 @@ ZipChannelSeek(
*errloc = EINVAL;
return -1;
}
- if (info->iswr) {
- if ((unsigned long) offset > info->nmax) {
+ if (info->isWriting) {
+ if ((unsigned long) offset > info->maxWrite) {
*errloc = EINVAL;
return -1;
}
- if ((unsigned long) offset > info->nbyte) {
- info->nbyte = offset;
+ if ((unsigned long) offset > info->numBytes) {
+ info->numBytes = offset;
}
} else if ((unsigned long) offset > end) {
*errloc = EINVAL;
return -1;
}
- info->nread = (unsigned long) offset;
- return info->nread;
+ info->numRead = (unsigned long) offset;
+ return info->numRead;
}
/*
@@ -3389,60 +3519,25 @@ ZipChannelGetFile(
}
/*
- * The channel type/driver definition used for ZIP archive members.
- */
-
-static Tcl_ChannelType ZipChannelType = {
- "zip", /* Type name. */
-#ifdef TCL_CHANNEL_VERSION_4
- TCL_CHANNEL_VERSION_4,
- ZipChannelClose, /* Close channel, clean instance data */
- ZipChannelRead, /* Handle read request */
- ZipChannelWrite, /* Handle write request */
- ZipChannelSeek, /* Move location of access point, NULL'able */
- NULL, /* Set options, NULL'able */
- NULL, /* Get options, NULL'able */
- ZipChannelWatchChannel, /* Initialize notifier */
- ZipChannelGetFile, /* Get OS handle from the channel */
- NULL, /* 2nd version of close channel, NULL'able */
- NULL, /* Set blocking mode for raw channel, NULL'able */
- NULL, /* Function to flush channel, NULL'able */
- NULL, /* Function to handle event, NULL'able */
- NULL, /* Wide seek function, NULL'able */
- NULL, /* Thread action function, NULL'able */
-#else
- NULL, /* Set blocking/nonblocking behaviour, NULL'able */
- ZipChannelClose, /* Close channel, clean instance data */
- ZipChannelRead, /* Handle read request */
- ZipChannelWrite, /* Handle write request */
- ZipChannelSeek, /* Move location of access point, NULL'able */
- NULL, /* Set options, NULL'able */
- NULL, /* Get options, NULL'able */
- ZipChannelWatchChannel, /* Initialize notifier */
- ZipChannelGetFile, /* Get OS handle from the channel */
-#endif
-};
-
-/*
*-------------------------------------------------------------------------
*
* ZipChannelOpen --
*
- * This function opens a Tcl_Channel on a file from a mounted ZIP
- * archive according to given open mode.
+ * This function opens a Tcl_Channel on a file from a mounted ZIP archive
+ * according to given open mode.
*
* Results:
- * Tcl_Channel on success, or NULL on error.
+ * Tcl_Channel on success, or NULL on error.
*
* Side effects:
- * Memory is allocated, the file from the ZIP archive is uncompressed.
+ * Memory is allocated, the file from the ZIP archive is uncompressed.
*
*-------------------------------------------------------------------------
*/
static Tcl_Channel
ZipChannelOpen(
- Tcl_Interp *interp,
+ Tcl_Interp *interp, /* Current interpreter. */
char *filename,
int mode,
int permissions)
@@ -3454,7 +3549,7 @@ ZipChannelOpen(
if ((mode & O_APPEND)
|| ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) {
- if (interp != NULL) {
+ if (interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("unsupported open mode", -1));
}
@@ -3462,185 +3557,184 @@ ZipChannelOpen(
}
WriteLock();
z = ZipFSLookup(filename);
- if (z == NULL) {
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj("file not found", -1));
- Tcl_AppendResult(interp, " \"", filename, "\"", NULL);
+ if (!z) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "file not found \"%s\"", filename));
}
goto error;
}
trunc = (mode & O_TRUNC) != 0;
wr = (mode & (O_WRONLY | O_RDWR)) != 0;
- if ((z->cmeth != ZIP_COMPMETH_STORED)
- && (z->cmeth != ZIP_COMPMETH_DEFLATED)) {
+ if ((z->compressMethod != ZIP_COMPMETH_STORED)
+ && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) {
ZIPFS_ERROR(interp, "unsupported compression method");
goto error;
}
- if (wr && z->isdir) {
+ if (wr && z->isDirectory) {
ZIPFS_ERROR(interp, "unsupported file type");
goto error;
}
if (!trunc) {
flags |= TCL_READABLE;
- if (z->isenc && (z->zipfile->pwbuf[0] == 0)) {
+ if (z->isEncrypted && (z->zipFilePtr->passBuf[0] == 0)) {
ZIPFS_ERROR(interp, "decryption failed");
goto error;
- } else if (wr && (z->data == NULL) && (z->nbyte > ZipFS.wrmax)) {
+ } else if (wr && !z->data && (z->numBytes > ZipFS.wrmax)) {
ZIPFS_ERROR(interp, "file too large");
goto error;
}
} else {
flags = TCL_WRITABLE;
}
- info = (ZipChannel *) Tcl_AttemptAlloc(sizeof (*info));
- if (info == NULL) {
+ info = attemptckalloc(sizeof(ZipChannel));
+ if (!info) {
ZIPFS_ERROR(interp, "out of memory");
goto error;
}
- info->zipfile = z->zipfile;
- info->zipentry = z;
- info->nread = 0;
+ info->zipFilePtr = z->zipFilePtr;
+ info->zipEntryPtr = z;
+ info->numRead = 0;
if (wr) {
flags |= TCL_WRITABLE;
- info->iswr = 1;
- info->isdir = 0;
- info->nmax = ZipFS.wrmax;
+ info->isWriting = 1;
+ info->isDirectory = 0;
+ info->maxWrite = ZipFS.wrmax;
info->iscompr = 0;
- info->isenc = 0;
- info->ubuf = (unsigned char *) Tcl_AttemptAlloc(info->nmax);
- if (info->ubuf == NULL) {
+ info->isEncrypted = 0;
+ info->ubuf = attemptckalloc(info->maxWrite);
+ if (!info->ubuf) {
merror0:
- if (info->ubuf != NULL) {
- Tcl_Free((char *) info->ubuf);
+ if (info->ubuf) {
+ ckfree(info->ubuf);
}
- Tcl_Free((char *) info);
+ ckfree(info);
ZIPFS_ERROR(interp, "out of memory");
goto error;
}
- memset(info->ubuf, 0, info->nmax);
+ memset(info->ubuf, 0, info->maxWrite);
if (trunc) {
- info->nbyte = 0;
- } else {
- if (z->data != NULL) {
- unsigned int j = z->nbyte;
+ info->numBytes = 0;
+ } else if (z->data) {
+ unsigned int j = z->numBytes;
- if (j > info->nmax) {
- j = info->nmax;
- }
- memcpy(info->ubuf, z->data, j);
- info->nbyte = j;
- } else {
- unsigned char *zbuf = z->zipfile->data + z->offset;
+ if (j > info->maxWrite) {
+ j = info->maxWrite;
+ }
+ memcpy(info->ubuf, z->data, j);
+ info->numBytes = j;
+ } else {
+ unsigned char *zbuf = z->zipFilePtr->data + z->offset;
- if (z->isenc) {
- int len = z->zipfile->pwbuf[0];
- char pwbuf[260];
+ if (z->isEncrypted) {
+ int len = z->zipFilePtr->passBuf[0];
+ char passBuf[260];
- for (i = 0; i < len; i++) {
- ch = z->zipfile->pwbuf[len - i];
- pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
- }
- pwbuf[i] = '\0';
- init_keys(pwbuf, info->keys, crc32tab);
- memset(pwbuf, 0, sizeof (pwbuf));
- for (i = 0; i < 12; i++) {
- ch = info->ubuf[i];
- zdecode(info->keys, crc32tab, ch);
- }
- zbuf += i;
+ for (i = 0; i < len; i++) {
+ ch = z->zipFilePtr->passBuf[len - i];
+ passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
}
- if (z->cmeth == ZIP_COMPMETH_DEFLATED) {
- z_stream stream;
- int err;
- unsigned char *cbuf = NULL;
-
- memset(&stream, 0, sizeof (stream));
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.avail_in = z->nbytecompr;
- if (z->isenc) {
- unsigned int j;
-
- stream.avail_in -= 12;
- cbuf = (unsigned char *)
- Tcl_AttemptAlloc(stream.avail_in);
- if (cbuf == NULL) {
- goto merror0;
- }
- for (j = 0; j < stream.avail_in; j++) {
- ch = info->ubuf[j];
- cbuf[j] = zdecode(info->keys, crc32tab, ch);
- }
- stream.next_in = cbuf;
- } else {
- stream.next_in = zbuf;
- }
- stream.next_out = info->ubuf;
- stream.avail_out = info->nmax;
- if (inflateInit2(&stream, -15) != Z_OK) goto cerror0;
- err = inflate(&stream, Z_SYNC_FLUSH);
- inflateEnd(&stream);
- if ((err == Z_STREAM_END)
- || ((err == Z_OK) && (stream.avail_in == 0))) {
- if (cbuf != NULL) {
- memset(info->keys, 0, sizeof (info->keys));
- Tcl_Free((char *) cbuf);
- }
- goto wrapchan;
- }
- cerror0:
- if (cbuf != NULL) {
- memset(info->keys, 0, sizeof (info->keys));
- Tcl_Free((char *) cbuf);
- }
- if (info->ubuf != NULL) {
- Tcl_Free((char *) info->ubuf);
+ passBuf[i] = '\0';
+ init_keys(passBuf, info->keys, crc32tab);
+ memset(passBuf, 0, sizeof(passBuf));
+ for (i = 0; i < 12; i++) {
+ ch = info->ubuf[i];
+ zdecode(info->keys, crc32tab, ch);
+ }
+ zbuf += i;
+ }
+ if (z->compressMethod == ZIP_COMPMETH_DEFLATED) {
+ z_stream stream;
+ int err;
+ unsigned char *cbuf = NULL;
+
+ memset(&stream, 0, sizeof(z_stream));
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ stream.avail_in = z->numCompressedBytes;
+ if (z->isEncrypted) {
+ unsigned int j;
+
+ stream.avail_in -= 12;
+ cbuf = attemptckalloc(stream.avail_in);
+ if (!cbuf) {
+ goto merror0;
}
- Tcl_Free((char *) info);
- ZIPFS_ERROR(interp, "decompression error");
- goto error;
- } else if (z->isenc) {
- for (i = 0; i < z->nbyte - 12; i++) {
- ch = zbuf[i];
- info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
+ for (j = 0; j < stream.avail_in; j++) {
+ ch = info->ubuf[j];
+ cbuf[j] = zdecode(info->keys, crc32tab, ch);
}
+ stream.next_in = cbuf;
} else {
- memcpy(info->ubuf, zbuf, z->nbyte);
+ stream.next_in = zbuf;
}
- memset(info->keys, 0, sizeof (info->keys));
- goto wrapchan;
+ stream.next_out = info->ubuf;
+ stream.avail_out = info->maxWrite;
+ if (inflateInit2(&stream, -15) != Z_OK) {
+ goto cerror0;
+ }
+ err = inflate(&stream, Z_SYNC_FLUSH);
+ inflateEnd(&stream);
+ if ((err == Z_STREAM_END)
+ || ((err == Z_OK) && (stream.avail_in == 0))) {
+ if (cbuf) {
+ memset(info->keys, 0, sizeof(info->keys));
+ ckfree(cbuf);
+ }
+ goto wrapchan;
+ }
+ cerror0:
+ if (cbuf) {
+ memset(info->keys, 0, sizeof(info->keys));
+ ckfree(cbuf);
+ }
+ if (info->ubuf) {
+ ckfree(info->ubuf);
+ }
+ ckfree(info);
+ ZIPFS_ERROR(interp, "decompression error");
+ goto error;
+ } else if (z->isEncrypted) {
+ for (i = 0; i < z->numBytes - 12; i++) {
+ ch = zbuf[i];
+ info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
+ }
+ } else {
+ memcpy(info->ubuf, zbuf, z->numBytes);
}
+ memset(info->keys, 0, sizeof(info->keys));
+ goto wrapchan;
}
- } else if (z->data != NULL) {
+ } else if (z->data) {
flags |= TCL_READABLE;
- info->iswr = 0;
+ info->isWriting = 0;
info->iscompr = 0;
- info->isdir = 0;
- info->isenc = 0;
- info->nbyte = z->nbyte;
- info->nmax = 0;
+ info->isDirectory = 0;
+ info->isEncrypted = 0;
+ info->numBytes = z->numBytes;
+ info->maxWrite = 0;
info->ubuf = z->data;
} else {
flags |= TCL_READABLE;
- info->iswr = 0;
- info->iscompr = z->cmeth == ZIP_COMPMETH_DEFLATED;
- info->ubuf = z->zipfile->data + z->offset;
- info->isdir = z->isdir;
- info->isenc = z->isenc;
- info->nbyte = z->nbyte;
- info->nmax = 0;
- if (info->isenc) {
- int len = z->zipfile->pwbuf[0];
- char pwbuf[260];
+ info->isWriting = 0;
+ info->iscompr = (z->compressMethod == ZIP_COMPMETH_DEFLATED);
+ info->ubuf = z->zipFilePtr->data + z->offset;
+ info->isDirectory = z->isDirectory;
+ info->isEncrypted = z->isEncrypted;
+ info->numBytes = z->numBytes;
+ info->maxWrite = 0;
+ if (info->isEncrypted) {
+ int len = z->zipFilePtr->passBuf[0];
+ char passBuf[260];
for (i = 0; i < len; i++) {
- ch = z->zipfile->pwbuf[len - i];
- pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
+ ch = z->zipFilePtr->passBuf[len - i];
+ passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
}
- pwbuf[i] = '\0';
- init_keys(pwbuf, info->keys, crc32tab);
- memset(pwbuf, 0, sizeof (pwbuf));
+ passBuf[i] = '\0';
+ init_keys(passBuf, info->keys, crc32tab);
+ memset(passBuf, 0, sizeof(passBuf));
for (i = 0; i < 12; i++) {
ch = info->ubuf[i];
zdecode(info->keys, crc32tab, ch);
@@ -3653,15 +3747,15 @@ ZipChannelOpen(
unsigned char *ubuf = NULL;
unsigned int j;
- memset(&stream, 0, sizeof (stream));
+ memset(&stream, 0, sizeof(z_stream));
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
- stream.avail_in = z->nbytecompr;
- if (info->isenc) {
+ stream.avail_in = z->numCompressedBytes;
+ if (info->isEncrypted) {
stream.avail_in -= 12;
- ubuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in);
- if (ubuf == NULL) {
+ ubuf = attemptckalloc(stream.avail_in);
+ if (!ubuf) {
info->ubuf = NULL;
goto merror;
}
@@ -3673,23 +3767,22 @@ ZipChannelOpen(
} else {
stream.next_in = info->ubuf;
}
- stream.next_out = info->ubuf = (unsigned char *)
- Tcl_AttemptAlloc(info->nbyte);
- if (info->ubuf == NULL) {
+ stream.next_out = info->ubuf = attemptckalloc(info->numBytes);
+ if (!info->ubuf) {
merror:
- if (ubuf != NULL) {
- info->isenc = 0;
- memset(info->keys, 0, sizeof (info->keys));
- Tcl_Free((char *) ubuf);
+ if (ubuf) {
+ info->isEncrypted = 0;
+ memset(info->keys, 0, sizeof(info->keys));
+ ckfree(ubuf);
}
- Tcl_Free((char *) info);
- if (interp != NULL) {
+ ckfree(info);
+ if (interp) {
Tcl_SetObjResult(interp,
- Tcl_NewStringObj("out of memory", -1));
+ Tcl_NewStringObj("out of memory", -1));
}
goto error;
}
- stream.avail_out = info->nbyte;
+ stream.avail_out = info->numBytes;
if (inflateInit2(&stream, -15) != Z_OK) {
goto cerror;
}
@@ -3697,33 +3790,34 @@ ZipChannelOpen(
inflateEnd(&stream);
if ((err == Z_STREAM_END)
|| ((err == Z_OK) && (stream.avail_in == 0))) {
- if (ubuf != NULL) {
- info->isenc = 0;
- memset(info->keys, 0, sizeof (info->keys));
- Tcl_Free((char *) ubuf);
+ if (ubuf) {
+ info->isEncrypted = 0;
+ memset(info->keys, 0, sizeof(info->keys));
+ ckfree(ubuf);
}
goto wrapchan;
}
cerror:
- if (ubuf != NULL) {
- info->isenc = 0;
+ if (ubuf) {
+ info->isEncrypted = 0;
memset(info->keys, 0, sizeof(info->keys));
- Tcl_Free((char *) ubuf);
+ ckfree(ubuf);
}
- if (info->ubuf != NULL) {
- Tcl_Free((char *) info->ubuf);
+ if (info->ubuf) {
+ ckfree(info->ubuf);
}
- Tcl_Free((char *) info);
+ ckfree(info);
ZIPFS_ERROR(interp, "decompression error");
goto error;
}
}
+
wrapchan:
sprintf(cname, "zipfs_%" TCL_LL_MODIFIER "x_%d", z->offset,
ZipFS.idCount++);
- z->zipfile->nopen++;
+ z->zipFilePtr->numOpen++;
Unlock();
- return Tcl_CreateChannel(&ZipChannelType, cname, (ClientData) info, flags);
+ return Tcl_CreateChannel(&ZipChannelType, cname, info, flags);
error:
Unlock();
@@ -3757,14 +3851,14 @@ ZipEntryStat(
ReadLock();
z = ZipFSLookup(path);
- if (z != NULL) {
- memset(buf, 0, sizeof (Tcl_StatBuf));
- if (z->isdir) {
+ if (z) {
+ memset(buf, 0, sizeof(Tcl_StatBuf));
+ if (z->isDirectory) {
buf->st_mode = S_IFDIR | 0555;
} else {
buf->st_mode = S_IFREG | 0555;
}
- buf->st_size = z->nbyte;
+ buf->st_size = z->numBytes;
buf->st_mtime = z->timestamp;
buf->st_ctime = z->timestamp;
buf->st_atime = z->timestamp;
@@ -3804,13 +3898,13 @@ ZipEntryAccess(
ReadLock();
z = ZipFSLookup(path);
Unlock();
- return (z != NULL) ? 0 : -1;
+ return (z ? 0 : -1);
}
/*
*-------------------------------------------------------------------------
*
- * Zip_FSOpenFileChannelProc --
+ * ZipFSOpenFileChannelProc --
*
* Results:
*
@@ -3820,8 +3914,8 @@ ZipEntryAccess(
*/
static Tcl_Channel
-Zip_FSOpenFileChannelProc(
- Tcl_Interp *interp,
+ZipFSOpenFileChannelProc(
+ Tcl_Interp *interp, /* Current interpreter. */
Tcl_Obj *pathPtr,
int mode,
int permissions)
@@ -3839,7 +3933,7 @@ Zip_FSOpenFileChannelProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSStatProc --
+ * ZipFSStatProc --
*
* This function implements the ZIP filesystem specific version of the
* library version of stat.
@@ -3854,7 +3948,7 @@ Zip_FSOpenFileChannelProc(
*/
static int
-Zip_FSStatProc(
+ZipFSStatProc(
Tcl_Obj *pathPtr,
Tcl_StatBuf *buf)
{
@@ -3870,7 +3964,7 @@ Zip_FSStatProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSAccessProc --
+ * ZipFSAccessProc --
*
* This function implements the ZIP filesystem specific version of the
* library version of access.
@@ -3885,7 +3979,7 @@ Zip_FSStatProc(
*/
static int
-Zip_FSAccessProc(
+ZipFSAccessProc(
Tcl_Obj *pathPtr,
int mode)
{
@@ -3901,7 +3995,7 @@ Zip_FSAccessProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSFilesystemSeparatorProc --
+ * ZipFSFilesystemSeparatorProc --
*
* This function returns the separator to be used for a given path. The
* object returned should have a refCount of zero
@@ -3918,7 +4012,7 @@ Zip_FSAccessProc(
*/
static Tcl_Obj *
-Zip_FSFilesystemSeparatorProc(
+ZipFSFilesystemSeparatorProc(
Tcl_Obj *pathPtr)
{
return Tcl_NewStringObj("/", -1);
@@ -3927,7 +4021,7 @@ Zip_FSFilesystemSeparatorProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSMatchInDirectoryProc --
+ * ZipFSMatchInDirectoryProc --
*
* This routine is used by the globbing code to search a directory for
* all files which match a given pattern.
@@ -3942,9 +4036,10 @@ Zip_FSFilesystemSeparatorProc(
*
*-------------------------------------------------------------------------
*/
+
static int
-Zip_FSMatchInDirectoryProc(
- Tcl_Interp *interp,
+ZipFSMatchInDirectoryProc(
+ Tcl_Interp *interp, /* Current interpreter. */
Tcl_Obj *result,
Tcl_Obj *pathPtr,
const char *pattern,
@@ -3952,24 +4047,29 @@ Zip_FSMatchInDirectoryProc(
{
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- Tcl_Obj *normPathPtr;
+ Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
int scnt, l, dirOnly = -1, prefixLen, strip = 0;
size_t len;
char *pat, *prefix, *path;
Tcl_DString dsPref;
- if (!(normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) {
+ if (!normPathPtr) {
return -1;
}
-
- if (types != NULL) {
+ if (types) {
dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR;
}
- /* the prefix that gets prepended to results */
+ /*
+ * The prefix that gets prepended to results.
+ */
+
prefix = Tcl_GetStringFromObj(pathPtr, &prefixLen);
- /* the (normalized) path we're searching */
+ /*
+ * The (normalized) path we're searching.
+ */
+
path = Tcl_GetString(normPathPtr);
len = normPathPtr->length;
@@ -3981,36 +4081,38 @@ Zip_FSMatchInDirectoryProc(
} else {
strip = len + 1;
}
- if (prefix != NULL) {
+ if (prefix) {
Tcl_DStringAppend(&dsPref, "/", 1);
prefixLen++;
prefix = Tcl_DStringValue(&dsPref);
}
ReadLock();
- if ((types != NULL) && (types->type == TCL_GLOB_TYPE_MOUNT)) {
+ if (types && (types->type == TCL_GLOB_TYPE_MOUNT)) {
l = CountSlashes(path);
if (path[len - 1] == '/') {
len--;
} else {
l++;
}
- if ((pattern == NULL) || (pattern[0] == '\0')) {
+ if (!pattern || (pattern[0] == '\0')) {
pattern = "*";
}
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ ZipFile *zf = Tcl_GetHashValue(hPtr);
- if (zf->mntptlen == 0) {
- ZipEntry *z = zf->topents;
- while (z != NULL) {
+ if (zf->mountPointLen == 0) {
+ ZipEntry *z;
+
+ for (z = zf->topEnts; z; z = z->tnext) {
size_t lenz = strlen(z->name);
+
if ((lenz > len + 1) && (strncmp(z->name, path, len) == 0)
&& (z->name[len] == '/')
&& (CountSlashes(z->name) == l)
&& Tcl_StringCaseMatch(z->name + len + 1, pattern,
0)) {
- if (prefix != NULL) {
+ if (prefix) {
Tcl_DStringAppend(&dsPref, z->name, lenz);
Tcl_ListObjAppendElement(NULL, result,
Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
@@ -4021,37 +4123,38 @@ Zip_FSMatchInDirectoryProc(
Tcl_NewStringObj(z->name, lenz));
}
}
- z = z->tnext;
}
- } else if ((zf->mntptlen > len + 1)
- && (strncmp(zf->mntpt, path, len) == 0)
- && (zf->mntpt[len] == '/')
- && (CountSlashes(zf->mntpt) == l)
- && Tcl_StringCaseMatch(zf->mntpt + len + 1, pattern, 0)) {
- if (prefix != NULL) {
- Tcl_DStringAppend(&dsPref, zf->mntpt, zf->mntptlen);
+ } else if ((zf->mountPointLen > len + 1)
+ && (strncmp(zf->mountPoint, path, len) == 0)
+ && (zf->mountPoint[len] == '/')
+ && (CountSlashes(zf->mountPoint) == l)
+ && Tcl_StringCaseMatch(zf->mountPoint + len + 1,
+ pattern, 0)) {
+ if (prefix) {
+ Tcl_DStringAppend(&dsPref, zf->mountPoint,
+ zf->mountPointLen);
Tcl_ListObjAppendElement(NULL, result,
Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
Tcl_DStringLength(&dsPref)));
Tcl_DStringSetLength(&dsPref, prefixLen);
} else {
Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(zf->mntpt, zf->mntptlen));
+ Tcl_NewStringObj(zf->mountPoint,
+ zf->mountPointLen));
}
}
- hPtr = Tcl_NextHashEntry(&search);
}
goto end;
}
- if ((pattern == NULL) || (pattern[0] == '\0')) {
+ if (!pattern || (pattern[0] == '\0')) {
hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
- if (hPtr != NULL) {
- ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr);
+ if (hPtr) {
+ ZipEntry *z = Tcl_GetHashValue(hPtr);
- if ((dirOnly < 0) || (!dirOnly && !z->isdir)
- || (dirOnly && z->isdir)) {
- if (prefix != NULL) {
+ if ((dirOnly < 0) || (!dirOnly && !z->isDirectory)
+ || (dirOnly && z->isDirectory)) {
+ if (prefix) {
Tcl_DStringAppend(&dsPref, z->name, -1);
Tcl_ListObjAppendElement(NULL, result,
Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
@@ -4067,7 +4170,7 @@ Zip_FSMatchInDirectoryProc(
}
l = strlen(pattern);
- pat = Tcl_Alloc(len + l + 2);
+ pat = ckalloc(len + l + 2);
memcpy(pat, path, len);
while ((len > 1) && (pat[len - 1] == '/')) {
--len;
@@ -4079,14 +4182,15 @@ Zip_FSMatchInDirectoryProc(
memcpy(pat + len, pattern, l + 1);
scnt = CountSlashes(pat);
for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr);
- if ((dirOnly >= 0) && ((dirOnly && !z->isdir)
- || (!dirOnly && z->isdir))) {
+ hPtr; hPtr = Tcl_NextHashEntry(&search)) {
+ ZipEntry *z = Tcl_GetHashValue(hPtr);
+
+ if ((dirOnly >= 0) && ((dirOnly && !z->isDirectory)
+ || (!dirOnly && z->isDirectory))) {
continue;
}
if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) {
- if (prefix != NULL) {
+ if (prefix) {
Tcl_DStringAppend(&dsPref, z->name + strip, -1);
Tcl_ListObjAppendElement(NULL, result,
Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
@@ -4098,7 +4202,7 @@ Zip_FSMatchInDirectoryProc(
}
}
}
- Tcl_Free(pat);
+ ckfree(pat);
end:
Unlock();
@@ -4109,7 +4213,7 @@ Zip_FSMatchInDirectoryProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSPathInFilesystemProc --
+ * ZipFSPathInFilesystemProc --
*
* This function determines if the given path object is in the ZIP
* filesystem.
@@ -4124,18 +4228,18 @@ Zip_FSMatchInDirectoryProc(
*/
static int
-Zip_FSPathInFilesystemProc(
+ZipFSPathInFilesystemProc(
Tcl_Obj *pathPtr,
ClientData *clientDataPtr)
{
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- ZipFile *zf;
int ret = -1;
size_t len;
char *path;
- if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) {
+ pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+ if (!pathPtr) {
return -1;
}
@@ -4148,31 +4252,31 @@ Zip_FSPathInFilesystemProc(
ReadLock();
hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
- if (hPtr != NULL) {
+ if (hPtr) {
ret = TCL_OK;
goto endloop;
}
- hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
- while (hPtr != NULL) {
- zf = (ZipFile *) Tcl_GetHashValue(hPtr);
- if (zf->mntptlen == 0) {
- ZipEntry *z = zf->topents;
- while (z != NULL) {
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ ZipFile *zf = Tcl_GetHashValue(hPtr);
+
+ if (zf->mountPointLen == 0) {
+ ZipEntry *z;
+
+ for (z = zf->topEnts; z != NULL; z = z->tnext) {
size_t lenz = strlen(z->name);
if ((len >= lenz) && (strncmp(path, z->name, lenz) == 0)) {
ret = TCL_OK;
goto endloop;
}
- z = z->tnext;
}
- } else if ((len >= zf->mntptlen) &&
- (strncmp(path, zf->mntpt, zf->mntptlen) == 0)) {
+ } else if ((len >= zf->mountPointLen) &&
+ (strncmp(path, zf->mountPoint, zf->mountPointLen) == 0)) {
ret = TCL_OK;
- goto endloop;
+ break;
}
- hPtr = Tcl_NextHashEntry(&search);
}
endloop:
@@ -4183,7 +4287,7 @@ Zip_FSPathInFilesystemProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSListVolumesProc --
+ * ZipFSListVolumesProc --
*
* Lists the currently mounted ZIP filesystem volumes.
*
@@ -4197,7 +4301,7 @@ Zip_FSPathInFilesystemProc(
*/
static Tcl_Obj *
-Zip_FSListVolumesProc(void)
+ZipFSListVolumesProc(void)
{
return Tcl_NewStringObj(ZIPFS_VOLUME, -1);
}
@@ -4205,7 +4309,7 @@ Zip_FSListVolumesProc(void)
/*
*-------------------------------------------------------------------------
*
- * Zip_FSFileAttrStringsProc --
+ * ZipFSFileAttrStringsProc --
*
* This function implements the ZIP filesystem dependent 'file
* attributes' subcommand, for listing the set of possible attribute
@@ -4221,9 +4325,9 @@ Zip_FSListVolumesProc(void)
*/
static const char *const *
-Zip_FSFileAttrStringsProc(
+ZipFSFileAttrStringsProc(
Tcl_Obj *pathPtr,
- Tcl_Obj** objPtrRef)
+ Tcl_Obj **objPtrRef)
{
static const char *const attrs[] = {
"-uncompsize",
@@ -4240,7 +4344,7 @@ Zip_FSFileAttrStringsProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSFileAttrsGetProc --
+ * ZipFSFileAttrsGetProc --
*
* This function implements the ZIP filesystem specific 'file attributes'
* subcommand, for 'get' operations.
@@ -4258,8 +4362,8 @@ Zip_FSFileAttrStringsProc(
*/
static int
-Zip_FSFileAttrsGetProc(
- Tcl_Interp *interp,
+ZipFSFileAttrsGetProc(
+ Tcl_Interp *interp, /* Current interpreter. */
int index,
Tcl_Obj *pathPtr,
Tcl_Obj **objPtrRef)
@@ -4268,39 +4372,43 @@ Zip_FSFileAttrsGetProc(
char *path;
ZipEntry *z;
- if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) {
+ pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+ if (!pathPtr) {
return -1;
}
path = Tcl_GetStringFromObj(pathPtr, &len);
ReadLock();
z = ZipFSLookup(path);
- if (z == NULL) {
+ if (!z) {
ZIPFS_ERROR(interp, "file not found");
ret = TCL_ERROR;
goto done;
}
switch (index) {
case 0:
- *objPtrRef = Tcl_NewWideIntObj(z->nbyte);
- goto done;
+ *objPtrRef = Tcl_NewWideIntObj(z->numBytes);
+ break;
case 1:
- *objPtrRef = Tcl_NewWideIntObj(z->nbytecompr);
- goto done;
+ *objPtrRef = Tcl_NewWideIntObj(z->numCompressedBytes);
+ break;
case 2:
*objPtrRef = Tcl_NewWideIntObj(z->offset);
- goto done;
+ break;
case 3:
- *objPtrRef = Tcl_NewStringObj(z->zipfile->mntpt, z->zipfile->mntptlen);
- goto done;
+ *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint,
+ z->zipFilePtr->mountPointLen);
+ break;
case 4:
- *objPtrRef = Tcl_NewStringObj(z->zipfile->name, -1);
- goto done;
+ *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->name, -1);
+ break;
case 5:
*objPtrRef = Tcl_NewStringObj("0555", -1);
- goto done;
+ break;
+ default:
+ ZIPFS_ERROR(interp, "unknown attribute");
+ ret = TCL_ERROR;
}
- ZIPFS_ERROR(interp, "unknown attribute");
- ret = TCL_ERROR;
+
done:
Unlock();
return ret;
@@ -4309,7 +4417,7 @@ Zip_FSFileAttrsGetProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSFileAttrsSetProc --
+ * ZipFSFileAttrsSetProc --
*
* This function implements the ZIP filesystem specific 'file attributes'
* subcommand, for 'set' operations.
@@ -4324,13 +4432,13 @@ Zip_FSFileAttrsGetProc(
*/
static int
-Zip_FSFileAttrsSetProc(
- Tcl_Interp *interp,
+ZipFSFileAttrsSetProc(
+ Tcl_Interp *interp, /* Current interpreter. */
int index,
Tcl_Obj *pathPtr,
Tcl_Obj *objPtr)
{
- if (interp != NULL) {
+ if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1));
}
return TCL_ERROR;
@@ -4339,7 +4447,7 @@ Zip_FSFileAttrsSetProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSFilesystemPathTypeProc --
+ * ZipFSFilesystemPathTypeProc --
*
* Results:
*
@@ -4349,7 +4457,7 @@ Zip_FSFileAttrsSetProc(
*/
static Tcl_Obj *
-Zip_FSFilesystemPathTypeProc(
+ZipFSFilesystemPathTypeProc(
Tcl_Obj *pathPtr)
{
return Tcl_NewStringObj("zip", -1);
@@ -4358,7 +4466,7 @@ Zip_FSFilesystemPathTypeProc(
/*
*-------------------------------------------------------------------------
*
- * Zip_FSLoadFile --
+ * ZipFSLoadFile --
*
* This functions deals with loading native object code. If the given
* path object refers to a file within the ZIP filesystem, an approriate
@@ -4377,8 +4485,8 @@ Zip_FSFilesystemPathTypeProc(
*/
static int
-Zip_FSLoadFile(
- Tcl_Interp *interp,
+ZipFSLoadFile(
+ Tcl_Interp *interp, /* Current interpreter. */
Tcl_Obj *path,
Tcl_LoadHandle *loadHandle,
Tcl_FSUnloadFileProc **unloadProcPtr,
@@ -4392,7 +4500,7 @@ Zip_FSLoadFile(
*/
loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc;
- if (loadFileProc != NULL) {
+ if (loadFileProc) {
return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags);
}
Tcl_SetErrno(ENOENT);
@@ -4401,6 +4509,7 @@ Zip_FSLoadFile(
#else /* !ANDROID */
Tcl_Obj *altPath = NULL;
int ret = TCL_ERROR;
+ Tcl_Obj *objs[2] = { NULL, NULL };
if (Tcl_FSAccess(path, R_OK) == 0) {
/*
@@ -4410,64 +4519,63 @@ Zip_FSLoadFile(
Tcl_SetErrno(EXDEV);
ZIPFS_ERROR(interp, Tcl_PosixError(interp));
return ret;
- } else {
- Tcl_Obj *objs[2] = { NULL, NULL };
+ }
- objs[1] = TclPathPart(interp, path, TCL_PATH_DIRNAME);
- if ((objs[1] != NULL) && (Zip_FSAccessProc(objs[1], R_OK) == 0)) {
- const char *execName = Tcl_GetNameOfExecutable();
+ objs[1] = TclPathPart(interp, path, TCL_PATH_DIRNAME);
+ if (objs[1] && (ZipFSAccessProc(objs[1], R_OK) == 0)) {
+ const char *execName = Tcl_GetNameOfExecutable();
- /*
- * Shared object is not in ZIP but its path prefix is, thus try to
- * load from directory where the executable came from.
- */
+ /*
+ * Shared object is not in ZIP but its path prefix is, thus try to
+ * load from directory where the executable came from.
+ */
- TclDecrRefCount(objs[1]);
- objs[1] = TclPathPart(interp, path, TCL_PATH_TAIL);
+ TclDecrRefCount(objs[1]);
+ objs[1] = TclPathPart(interp, path, TCL_PATH_TAIL);
- /*
- * Get directory name of executable manually to deal with cases
- * where [file dirname [info nameofexecutable]] is equal to [info
- * nameofexecutable] due to VFS effects.
- */
+ /*
+ * Get directory name of executable manually to deal with cases where
+ * [file dirname [info nameofexecutable]] is equal to [info
+ * nameofexecutable] due to VFS effects.
+ */
- if (execName != NULL) {
- const char *p = strrchr(execName, '/');
+ if (execName) {
+ const char *p = strrchr(execName, '/');
- if (p > execName + 1) {
- --p;
- objs[0] = Tcl_NewStringObj(execName, p - execName);
- }
- }
- if (objs[0] == NULL) {
- objs[0] = TclPathPart(interp, TclGetObjNameOfExecutable(),
- TCL_PATH_DIRNAME);
- }
- if (objs[0] != NULL) {
- altPath = TclJoinPath(2, objs);
- if (altPath != NULL) {
- Tcl_IncrRefCount(altPath);
- if (Tcl_FSAccess(altPath, R_OK) == 0) {
- path = altPath;
- }
- }
+ if (p > execName + 1) {
+ --p;
+ objs[0] = Tcl_NewStringObj(execName, p - execName);
}
}
- if (objs[0] != NULL) {
- Tcl_DecrRefCount(objs[0]);
+ if (!objs[0]) {
+ objs[0] = TclPathPart(interp, TclGetObjNameOfExecutable(),
+ TCL_PATH_DIRNAME);
}
- if (objs[1] != NULL) {
- Tcl_DecrRefCount(objs[1]);
+ if (objs[0]) {
+ altPath = TclJoinPath(2, objs);
+ if (altPath) {
+ Tcl_IncrRefCount(altPath);
+ if (Tcl_FSAccess(altPath, R_OK) == 0) {
+ path = altPath;
+ }
+ }
}
}
+ if (objs[0]) {
+ Tcl_DecrRefCount(objs[0]);
+ }
+ if (objs[1]) {
+ Tcl_DecrRefCount(objs[1]);
+ }
+
loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc;
- if (loadFileProc != NULL) {
+ if (loadFileProc) {
ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags);
} else {
Tcl_SetErrno(ENOENT);
ZIPFS_ERROR(interp, Tcl_PosixError(interp));
}
- if (altPath != NULL) {
+ if (altPath) {
Tcl_DecrRefCount(altPath);
}
return ret;
@@ -4495,54 +4603,58 @@ Zip_FSLoadFile(
MODULE_SCOPE int
TclZipfs_Init(
- Tcl_Interp *interp)
+ Tcl_Interp *interp) /* Current interpreter. */
{
#ifdef HAVE_ZLIB
- /* one-time initialization */
+ static const EnsembleImplMap initMap[] = {
+ {"mkimg", ZipFSMkImgObjCmd, NULL, NULL, NULL, 0},
+ {"mkzip", ZipFSMkZipObjCmd, NULL, NULL, NULL, 0},
+ {"lmkimg", ZipFSLMkImgObjCmd, NULL, NULL, NULL, 0},
+ {"lmkzip", ZipFSLMkZipObjCmd, NULL, NULL, NULL, 0},
+ /* The 4 entries above are not available in safe interpreters */
+ {"mount", ZipFSMountObjCmd, NULL, NULL, NULL, 0},
+ {"mount_data", ZipFSMountBufferObjCmd, NULL, NULL, NULL, 0},
+ {"unmount", ZipFSUnmountObjCmd, NULL, NULL, NULL, 0},
+ {"mkkey", ZipFSMkKeyObjCmd, NULL, NULL, NULL, 0},
+ {"exists", ZipFSExistsObjCmd, NULL, NULL, NULL, 1},
+ {"info", ZipFSInfoObjCmd, NULL, NULL, NULL, 1},
+ {"list", ZipFSListObjCmd, NULL, NULL, NULL, 1},
+ {"canonical", ZipFSCanonicalObjCmd, NULL, NULL, NULL, 1},
+ {"root", ZipFSRootObjCmd, NULL, NULL, NULL, 1},
+ {"tcl_library", ZipFSTclLibraryObjCmd, NULL, NULL, NULL, 0},
+ {NULL, NULL, NULL, NULL, NULL, 0}
+ };
+ static const char findproc[] =
+ "namespace eval ::tcl::zipfs {}\n"
+ "proc ::tcl::zipfs::Find dir {\n"
+ " set result {}\n"
+ " if {[catch {glob -directory $dir -nocomplain * .*} list]} {\n"
+ " return $result\n"
+ " }\n"
+ " foreach file $list {\n"
+ " if {[file tail $file] in {. ..}} {\n"
+ " continue\n"
+ " }\n"
+ " lappend result $file {*}[Find $file]\n"
+ " }\n"
+ " return $result\n"
+ "}\n"
+ "proc ::tcl::zipfs::find dir {\n"
+ " return [lsort [Find $dir]]\n"
+ "}\n";
+
+ /*
+ * One-time initialization.
+ */
+
WriteLock();
/* Tcl_StaticPackage(interp, "zipfs", TclZipfs_Init, TclZipfs_Init); */
if (!ZipFS.initialized) {
- TclZipfs_C_Init();
+ ZipfsSetup();
}
Unlock();
- if (interp != NULL) {
- static const EnsembleImplMap initMap[] = {
- {"mkimg", ZipFSMkImgObjCmd, NULL, NULL, NULL, 0},
- {"mkzip", ZipFSMkZipObjCmd, NULL, NULL, NULL, 0},
- {"lmkimg", ZipFSLMkImgObjCmd, NULL, NULL, NULL, 0},
- {"lmkzip", ZipFSLMkZipObjCmd, NULL, NULL, NULL, 0},
- /* The 4 entries above are not available in safe interpreters */
- {"mount", ZipFSMountObjCmd, NULL, NULL, NULL, 0},
- {"mount_data", ZipFSMountBufferObjCmd, NULL, NULL, NULL, 0},
- {"unmount", ZipFSUnmountObjCmd, NULL, NULL, NULL, 0},
- {"mkkey", ZipFSMkKeyObjCmd, NULL, NULL, NULL, 0},
- {"exists", ZipFSExistsObjCmd, NULL, NULL, NULL, 1},
- {"info", ZipFSInfoObjCmd, NULL, NULL, NULL, 1},
- {"list", ZipFSListObjCmd, NULL, NULL, NULL, 1},
- {"canonical", ZipFSCanonicalObjCmd, NULL, NULL, NULL, 1},
- {"root", ZipFSRootObjCmd, NULL, NULL, NULL, 1},
- {"tcl_library", ZipFSTclLibraryObjCmd, NULL, NULL, NULL, 0},
- {NULL, NULL, NULL, NULL, NULL, 0}
- };
- static const char findproc[] =
- "namespace eval ::tcl::zipfs::zipfs {}\n"
- "proc ::tcl::zipfs::find dir {\n"
- " set result {}\n"
- " if {[catch {glob -directory $dir -tails -nocomplain * .*} list]} {\n"
- " return $result\n"
- " }\n"
- " foreach file $list {\n"
- " if {$file eq \".\" || $file eq \"..\"} {\n"
- " continue\n"
- " }\n"
- " set file [file join $dir $file]\n"
- " lappend result $file\n"
- " foreach file [::tcl::zipfs::find $file] {\n"
- " lappend result $file\n"
- " }\n"
- " }\n"
- " return [lsort $result]\n"
- "}\n";
+
+ if (interp) {
Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL);
Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,
TCL_LINK_INT);
@@ -4558,10 +4670,10 @@ TclZipfs_Init(
}
static int
-TclZipfs_AppHook_FindTclInit(
+ZipfsAppHookFindTclInit(
const char *archive)
{
- Tcl_Obj *vfsinitscript;
+ Tcl_Obj *vfsInitScript;
int found;
if (zipfs_literal_tcl_library) {
@@ -4572,20 +4684,20 @@ TclZipfs_AppHook_FindTclInit(
return TCL_ERROR;
}
- vfsinitscript = Tcl_NewStringObj(ZIPFS_ZIP_MOUNT "/init.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- found = Tcl_FSAccess(vfsinitscript, F_OK);
- Tcl_DecrRefCount(vfsinitscript);
+ TclNewLiteralStringObj(vfsInitScript, ZIPFS_ZIP_MOUNT "/init.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ found = Tcl_FSAccess(vfsInitScript, F_OK);
+ Tcl_DecrRefCount(vfsInitScript);
if (found == 0) {
zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT;
return TCL_OK;
}
- vfsinitscript = Tcl_NewStringObj(
- ZIPFS_ZIP_MOUNT "/tcl_library/init.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- found = Tcl_FSAccess(vfsinitscript, F_OK);
- Tcl_DecrRefCount(vfsinitscript);
+ TclNewLiteralStringObj(vfsInitScript,
+ ZIPFS_ZIP_MOUNT "/tcl_library/init.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ found = Tcl_FSAccess(vfsInitScript, F_OK);
+ Tcl_DecrRefCount(vfsInitScript);
if (found == 0) {
zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT "/tcl_library";
return TCL_OK;
@@ -4597,7 +4709,7 @@ TclZipfs_AppHook_FindTclInit(
/*
*-------------------------------------------------------------------------
*
- * Tclkit_MainHook --
+ * TclZipfs_AppHook --
*
* Performs the argument munging for the shell
*
@@ -4606,20 +4718,17 @@ TclZipfs_AppHook_FindTclInit(
int
TclZipfs_AppHook(
- int *argc,
+ int *argcPtr, /* Pointer to argc */
#ifdef _WIN32
TCHAR
#else /* !_WIN32 */
char
#endif /* _WIN32 */
- ***argv)
+ ***argvPtr) /* Pointer to argv */
{
-#ifdef _WIN32
- Tcl_DString ds;
-#endif /* _WIN32 */
char *archive;
- Tcl_FindExecutable((*argv)[0]);
+ Tcl_FindExecutable((*argvPtr)[0]);
archive = (char *) Tcl_GetNameOfExecutable();
TclZipfs_Init(NULL);
@@ -4630,18 +4739,18 @@ TclZipfs_AppHook(
if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) {
int found;
- Tcl_Obj *vfsinitscript;
+ Tcl_Obj *vfsInitScript;
- vfsinitscript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- if (Tcl_FSAccess(vfsinitscript, F_OK) == 0) {
+ TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
/*
* Startup script should be set before calling Tcl_AppInit
*/
- Tcl_SetStartupScript(vfsinitscript, NULL);
+ Tcl_SetStartupScript(vfsInitScript, NULL);
} else {
- Tcl_DecrRefCount(vfsinitscript);
+ Tcl_DecrRefCount(vfsInitScript);
}
/*
@@ -4649,29 +4758,33 @@ TclZipfs_AppHook(
*/
if (!zipfs_literal_tcl_library) {
- vfsinitscript = Tcl_NewStringObj(
- ZIPFS_APP_MOUNT "/tcl_library/init.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- found = Tcl_FSAccess(vfsinitscript, F_OK);
- Tcl_DecrRefCount(vfsinitscript);
+ TclNewLiteralStringObj(vfsInitScript,
+ ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ found = Tcl_FSAccess(vfsInitScript, F_OK);
+ Tcl_DecrRefCount(vfsInitScript);
if (found == TCL_OK) {
zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
return TCL_OK;
}
}
- } else if (*argc>1) {
- return TCL_OK;
+#ifdef SUPPORT_BUILTIN_ZIP_INSTALL
+ } else if (*argcPtr > 1) {
#ifdef _WIN32
- archive = Tcl_WinTCharToUtf((*argv)[1], -1, &ds);
-#else
- archive = (*argv)[1];
-#endif
- if (strcmp(archive, "install") == 0) {
- /*
- * If the first argument is mkzip, run the mkzip program.
- */
+ Tcl_DString ds;
+#endif /* _WIN32 */
+ /*
+ * If the first argument is "install", run the supplied installer
+ * script.
+ */
- Tcl_Obj *vfsinitscript;
+#ifdef _WIN32
+ archive = Tcl_WinTCharToUtf((*argvPtr)[1], -1, &ds);
+#else /* !_WIN32 */
+ archive = (*argvPtr)[1];
+#endif /* _WIN32 */
+ if (strcmp(archive, "install") == 0) {
+ Tcl_Obj *vfsInitScript;
/*
* Run this now to ensure the file is present by the time Tcl_Main
@@ -4679,34 +4792,34 @@ TclZipfs_AppHook(
*/
TclZipfs_TclLibrary();
- vfsinitscript = Tcl_NewStringObj(
- ZIPFS_ZIP_MOUNT "/tcl_library/install.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- if (Tcl_FSAccess(vfsinitscript, F_OK) == 0) {
- Tcl_SetStartupScript(vfsinitscript, NULL);
+ TclNewLiteralStringObj(vfsInitScript,
+ ZIPFS_ZIP_MOUNT "/tcl_library/install.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
+ Tcl_SetStartupScript(vfsInitScript, NULL);
}
return TCL_OK;
} else if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) {
int found;
- Tcl_Obj *vfsinitscript;
+ Tcl_Obj *vfsInitScript;
- vfsinitscript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- if (Tcl_FSAccess(vfsinitscript, F_OK) == 0) {
+ TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
/*
* Startup script should be set before calling Tcl_AppInit
*/
- Tcl_SetStartupScript(vfsinitscript, NULL);
+ Tcl_SetStartupScript(vfsInitScript, NULL);
} else {
- Tcl_DecrRefCount(vfsinitscript);
+ Tcl_DecrRefCount(vfsInitScript);
}
/* Set Tcl Encodings */
- vfsinitscript = Tcl_NewStringObj(
- ZIPFS_APP_MOUNT "/tcl_library/init.tcl", -1);
- Tcl_IncrRefCount(vfsinitscript);
- found = Tcl_FSAccess(vfsinitscript, F_OK);
- Tcl_DecrRefCount(vfsinitscript);
+ TclNewLiteralStringObj(vfsInitScript,
+ ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ found = Tcl_FSAccess(vfsInitScript, F_OK);
+ Tcl_DecrRefCount(vfsInitScript);
if (found == TCL_OK) {
zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
return TCL_OK;
@@ -4715,6 +4828,7 @@ TclZipfs_AppHook(
#ifdef _WIN32
Tcl_DStringFree(&ds);
#endif /* _WIN32 */
+#endif /* SUPPORT_BUILTIN_ZIP_INSTALL */
}
return TCL_OK;
}
@@ -4724,7 +4838,7 @@ TclZipfs_AppHook(
/*
*-------------------------------------------------------------------------
*
- * TclZipfs_Mount, TclZipfs_Unmount --
+ * TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount --
*
* Dummy version when no ZLIB support available.
*
@@ -4733,20 +4847,35 @@ TclZipfs_AppHook(
int
TclZipfs_Mount(
- Tcl_Interp *interp,
- const char *mntpt,
- const char *zipname,
- const char *passwd)
+ Tcl_Interp *interp, /* Current interpreter. */
+ const char *mountPoint, /* Mount point path. */
+ const char *zipname, /* Path to ZIP file to mount. */
+ const char *passwd) /* Password for opening the ZIP, or NULL if
+ * the ZIP is unprotected. */
{
- return TclZipfs_Init(interp, 1);
+ ZIPFS_ERROR(interp, "no zlib available");
+ return TCL_ERROR;
+}
+
+int
+TclZipfs_MountBuffer(
+ Tcl_Interp *interp, /* Current interpreter. NULLable. */
+ const char *mountPoint, /* Mount point path. */
+ unsigned char *data,
+ size_t datalen,
+ int copy)
+{
+ ZIPFS_ERROR(interp, "no zlib available");
+ return TCL_ERROR;
}
int
TclZipfs_Unmount(
- Tcl_Interp *interp,
- const char *zipname)
+ Tcl_Interp *interp, /* Current interpreter. */
+ const char *mountPoint) /* Mount point path. */
{
- return TclZipfs_Init(interp, 1);
+ ZIPFS_ERROR(interp, "no zlib available");
+ return TCL_ERROR;
}
#endif /* !HAVE_ZLIB */
diff --git a/generic/tclZlib.c b/generic/tclZlib.c
index 644ac8b..9bad36d 100644
--- a/generic/tclZlib.c
+++ b/generic/tclZlib.c
@@ -2931,7 +2931,7 @@ ZlibTransformClose(
result = TCL_ERROR;
break;
}
- if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) < 0) {
+ if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) == TCL_IO_FAILURE) {
/* TODO: is this the right way to do errors on close?
* Note: when close is called from FinalizeIOSubsystem then
* interp may be NULL */
@@ -3130,7 +3130,7 @@ ZlibTransformOutput(
break;
}
- if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) {
+ if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) == TCL_IO_FAILURE) {
*errorCodePtr = Tcl_GetErrno();
return -1;
}
@@ -3186,7 +3186,7 @@ ZlibTransformFlush(
* Write the bytes we've received to the next layer.
*/
- if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) < 0) {
+ if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) == TCL_IO_FAILURE) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"problem flushing channel: %s",
Tcl_PosixError(interp)));
diff --git a/tests/zipfs.test b/tests/zipfs.test
index 1a5225c..9d60f8d 100644
--- a/tests/zipfs.test
+++ b/tests/zipfs.test
@@ -15,7 +15,10 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
-testConstraint zipfs [expr {[llength [info commands zlib]] && [regexp tcltest [info nameofexecutable]]}]
+testConstraint zipfs [expr {
+ [llength [info commands zlib]] && [regexp tcltest [info nameofexecutable]]
+}]
+testConstraint zipfslib 1
# Removed in tip430 - zipfs is no longer a static package
#test zipfs-0.0 {zipfs basics} -constraints zipfs -body {
@@ -27,10 +30,9 @@ set CWD [pwd]
set tmpdir [file join $CWD tmp]
file mkdir $tmpdir
-test zipfs-0.1 {zipfs basics} -constraints zipfs -body {
+test zipfs-0.0 {zipfs basics} -constraints zipfs -body {
package require zipfs
} -result {2.0}
-
test zipfs-0.1 {zipfs basics} -constraints zipfs -body {
expr {${ziproot} in [file volumes]}
} -result 1
@@ -43,114 +45,95 @@ if {![string match ${ziproot}* $tcl_library]} {
# archive
###
set tclzip [file join $CWD [::tcl::pkgconfig get zipfile,runtime]]
- if {[file exists $tclzip]} {
+ testConstraint zipfslib [file exists $tclzip]
+ if {[testConstraint zipfslib]} {
zipfs mount /lib/tcl $tclzip
set ::tcl_library ${ziproot}lib/tcl/tcl_library
- } else {
- tcltest::skip zipfs-0.*
}
}
-test zipfs-0.2 {zipfs basics} -constraints zipfs -body {
+test zipfs-0.2 {zipfs basics} -constraints zipfslib -body {
string match ${ziproot}* $tcl_library
} -result 1
-
-test zipfs-0.3 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.3 {zipfs basics: glob} -constraints zipfslib -setup {
set pwd [pwd]
+} -body {
cd $tcl_library
lsort [glob -dir . http*]
} -cleanup {
cd $pwd
} -result {./http}
-
-test zipfs-0.4 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.4 {zipfs basics: glob} -constraints zipfslib -setup {
set pwd [pwd]
+} -body {
cd $tcl_library
lsort [glob -dir [pwd] http*]
} -cleanup {
cd $pwd
} -result [list $tcl_library/http]
-
-test zipfs-0.5 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.5 {zipfs basics: glob} -constraints zipfslib -body {
lsort [glob -dir $tcl_library http*]
} -result [list $tcl_library/http]
-
-test zipfs-0.6 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.6 {zipfs basics: glob} -constraints zipfslib -body {
lsort [glob $tcl_library/http*]
} -result [list $tcl_library/http]
-
-test zipfs-0.7 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.7 {zipfs basics: glob} -constraints zipfslib -body {
lsort [glob -tails -dir $tcl_library http*]
} -result {http}
-
-test zipfs-0.8 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.8 {zipfs basics: glob} -constraints zipfslib -body {
lsort [glob -nocomplain -tails -types d -dir $tcl_library http*]
} -result {http}
-
-test zipfs-0.9 {zipfs basics: glob} -constraints zipfs -body {
+test zipfs-0.9 {zipfs basics: glob} -constraints zipfslib -body {
lsort [glob -nocomplain -tails -types f -dir $tcl_library http*]
} -result {}
-
-test zipfs-0.10 {zipfs basics: join} -constraints zipfs -body {
+test zipfs-0.10 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
file join [zipfs root] bar baz
} -result "[zipfs root]bar/baz"
-
-test zipfs-0.11 {zipfs basics: join} -constraints zipfs -body {
+test zipfs-0.11 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
file normalize [zipfs root]
} -result "[zipfs root]"
-
-test zipfs-0.12 {zipfs basics: join} -constraints zipfs -body {
+test zipfs-0.12 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
file normalize [zipfs root]//bar/baz//qux/../
} -result "[zipfs root]bar/baz"
test zipfs-1.3 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs mount a b c d e f
} -result {wrong # args: should be "zipfs mount ?mountpoint? ?zipfile? ?password?"}
-
test zipfs-1.4 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs unmount a b c d e f
} -result {wrong # args: should be "zipfs unmount zipfile"}
-
test zipfs-1.5 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs mkkey a b c d e f
} -result {wrong # args: should be "zipfs mkkey password"}
-
test zipfs-1.6 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs mkimg a b c d e f
} -result {wrong # args: should be "zipfs mkimg outfile indir ?strip? ?password? ?infile?"}
-
test zipfs-1.7 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs mkzip a b c d e f
} -result {wrong # args: should be "zipfs mkzip outfile indir ?strip? ?password?"}
-
test zipfs-1.8 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs exists a b c d e f
} -result {wrong # args: should be "zipfs exists filename"}
-
test zipfs-1.9 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs info a b c d e f
} -result {wrong # args: should be "zipfs info filename"}
-
test zipfs-1.10 {zipfs errors} -constraints zipfs -returnCodes error -body {
zipfs list a b c d e f
} -result {wrong # args: should be "zipfs list ?(-glob|-regexp)? ?pattern?"}
file mkdir tmp
-
test zipfs-2.1 {zipfs mkzip empty archive} -constraints zipfs -returnCodes error -body {
zipfs mkzip [file join $tmpdir empty.zip] $tcl_library/xxxx
} -result {empty archive}
-
###
-# The 2.2 series of tests operate within
-# a zipfile created a temporary directory
+# The next series of tests operate within a zipfile created a temporary
+# directory.
###
set zipfile [file join $tmpdir abc.zip]
if {[file exists $zipfile]} {
file delete $zipfile
}
-
-test zipfs-2.2.0 {zipfs mkzip} -constraints zipfs -body {
+test zipfs-2.2 {zipfs mkzip} -constraints zipfs -body {
cd $tcl_library/encoding
zipfs mkzip $zipfile .
zipfs mount ${ziproot}abc $zipfile
@@ -158,17 +141,12 @@ test zipfs-2.2.0 {zipfs mkzip} -constraints zipfs -body {
} -cleanup {
cd $CWD
} -result "[zipfs root]abc/cp850.enc"
-
-if {![zipfs exists /abc/cp850.enc]} {
- skip [concat [skip] zipfs-2.2.*]
-}
-
-test zipfs-2.2.1 {zipfs info} -constraints zipfs -body {
+testConstraint zipfsenc [zipfs exists /abc/cp850.enc]
+test zipfs-2.3 {zipfs info} -constraints {zipfs zipfsenc} -body {
set r [zipfs info ${ziproot}abc/cp850.enc]
lrange $r 0 2
} -result [list $zipfile 1090 527] ;# NOTE: Only the first 3 results are stable
-
-test zipfs-2.2.3 {zipfs data} -constraints zipfs -body {
+test zipfs-2.4 {zipfs data} -constraints {zipfs zipfsenc} -body {
set zipfd [open ${ziproot}/abc/cp850.enc] ;# FIXME: leave open - see later test
read $zipfd
} -result {# Encoding file: cp850, single-byte
@@ -192,48 +170,38 @@ S
00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4
00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0
} ;# FIXME: result depends on content of encodings dir
-
-test zipfs-2.2.4 {zipfs exists} -constraints zipfs -body {
+test zipfs-2.5 {zipfs exists} -constraints {zipfs zipfsenc} -body {
zipfs exists /abc/cp850.enc
} -result 1
-
-test zipfs-2.2.5 {zipfs unmount while busy} -constraints zipfs -body {
+test zipfs-2.6 {zipfs unmount while busy} -constraints {zipfs zipfsenc} -body {
zipfs unmount /abc
} -returnCodes error -result {filesystem is busy}
-
-test zipfs-2.2.6 {zipfs unmount} -constraints zipfs -body {
+test zipfs-2.7 {zipfs unmount} -constraints {zipfs zipfsenc} -body {
close $zipfd
zipfs unmount /abc
zipfs exists /abc/cp850.enc
} -result 0
-
-
###
# Repeat the tests for a buffer mounted archive
###
-test zipfs-2.3.0 {zipfs mkzip} -constraints zipfs -body {
- cd $tcl_library/encoding
- zipfs mkzip $zipfile .
- set fin [open $zipfile r]
- fconfigure $fin -translation binary
- set dat [read $fin]
- close $fin
- zipfs mount_data def $dat
+test zipfs-2.8 {zipfs mkzip} -constraints zipfs -body {
+ cd $tcl_library/encoding
+ zipfs mkzip $zipfile .
+ set fin [open $zipfile r]
+ fconfigure $fin -translation binary
+ set dat [read $fin]
+ close $fin
+ zipfs mount_data def $dat
zipfs list -glob ${ziproot}def/cp850.*
} -cleanup {
cd $CWD
} -result "[zipfs root]def/cp850.enc"
-
-if {![zipfs exists /def/cp850.enc]} {
- skip [concat [skip] zipfs-2.3.*]
-}
-
-test zipfs-2.3.1 {zipfs info} -constraints zipfs -body {
+testConstraint zipfsencbuf [zipfs exists /def/cp850.enc]
+test zipfs-2.9 {zipfs info} -constraints {zipfs zipfsencbuf} -body {
set r [zipfs info ${ziproot}def/cp850.enc]
lrange $r 0 2
} -result [list {Memory Buffer} 1090 527] ;# NOTE: Only the first 3 results are stable
-
-test zipfs-2.3.3 {zipfs data} -constraints zipfs -body {
+test zipfs-2.10 {zipfs data} -constraints {zipfs zipfsencbuf} -body {
set zipfd [open ${ziproot}/def/cp850.enc] ;# FIXME: leave open - see later test
read $zipfd
} -result {# Encoding file: cp850, single-byte
@@ -257,16 +225,13 @@ S
00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4
00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0
} ;# FIXME: result depends on content of encodings dir
-
-test zipfs-2.3.4 {zipfs exists} -constraints zipfs -body {
+test zipfs-2.11 {zipfs exists} -constraints {zipfs zipfsencbuf} -body {
zipfs exists /def/cp850.enc
} -result 1
-
-test zipfs-2.3.5 {zipfs unmount while busy} -constraints zipfs -body {
+test zipfs-2.12 {zipfs unmount while busy} -constraints {zipfs zipfsencbuf} -body {
zipfs unmount /def
} -returnCodes error -result {filesystem is busy}
-
-test zipfs-2.3.6 {zipfs unmount} -constraints zipfs -body {
+test zipfs-2.13 {zipfs unmount} -constraints {zipfs zipfsencbuf} -body {
close $zipfd
zipfs unmount /def
zipfs exists /def/cp850.enc
diff --git a/unix/Makefile.in b/unix/Makefile.in
index 9869a38..37e1adb 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -681,8 +681,8 @@ ${TCL_ZIP_FILE}: ${ZIP_INSTALL_OBJS}
@rm -rf ${TCL_VFS_ROOT}
@mkdir -p ${TCL_VFS_PATH}
cp -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}
- ( cd ${TCL_VFS_ROOT} ; \
- ${NATIVE_ZIP} ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH})
+ -find ${TCL_VFS_ROOT} -type d -empty -delete
+ ( cd ${TCL_VFS_ROOT} ; ${NATIVE_ZIP} ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH})
# The following target is configured by autoconf to generate either a shared
# library or non-shared library for Tcl.
diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c
index 1a33514..04d27dd 100644
--- a/win/tclWin32Dll.c
+++ b/win/tclWin32Dll.c
@@ -472,6 +472,9 @@ Tcl_WinUtfToTChar(
* converted string is stored. */
{
Tcl_DStringInit(dsPtr);
+ if (!string) {
+ return (TCHAR *)Tcl_DStringValue(dsPtr);
+ }
return Tcl_UtfToUniCharDString(string, len, dsPtr);
}
@@ -483,12 +486,15 @@ Tcl_WinTCharToUtf(
Tcl_DString *dsPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
{
+ Tcl_DStringInit(dsPtr);
+ if (!string) {
+ return Tcl_DStringValue(dsPtr);
+ }
if (len > 0) {
len /= 2;
} else if (len < 0) {
len = wcslen(string);
}
- Tcl_DStringInit(dsPtr);
return Tcl_UniCharToUtfDString(string, len, dsPtr);
}