diff options
| -rw-r--r-- | doc/zipfs.3 | 102 | ||||
| -rw-r--r-- | generic/tclZipfs.c | 5329 | ||||
| -rwxr-xr-x | library/reg/pkgIndex.tcl | 4 | ||||
| -rw-r--r-- | win/tclWinReg.c | 27 |
4 files changed, 2860 insertions, 2602 deletions
diff --git a/doc/zipfs.3 b/doc/zipfs.3 index ce5d5eb..568f461 100644 --- a/doc/zipfs.3 +++ b/doc/zipfs.3 @@ -10,61 +10,87 @@ .so man.macros .BS .SH NAME -TclZipfs_AppHook, Tclzipfs_Mount, Tclzipfs_Unmount, \- handle ZIP files as VFS +TclZipfs_AppHook, Tclzipfs_Mount, Tclzipfs_Unmount \- handle ZIP files as Tcl virtual filesystems .SH SYNOPSIS .nf -.sp int -\fBTclZipfs_AppHook(\fIint *argc, char ***argv\fR) +\fBTclZipfs_AppHook(\fIargcPtr, argvPtr\fR) .sp int -\fBTclzipfs_Mount\fR(\fIinterp, mntpt, zipname, passwd\fR) +\fBTclzipfs_Mount\fR(\fIinterp, mountpoint, zipname, password\fR) .sp int \fBTclzipfs_Unmount\fR(\fIinterp, zipname\fR) +.fi .SH ARGUMENTS -.AP "int" *argc in -Number of command line arguments from main() -.AP "char" ***argv in -Pointer to an array of strings containing the command -line arguments to main() -.AS Tcl_Interp **termPtr +.AS Tcl_Interp *mountpoint in +.AP "int" *argcPtr in +Pointer to a variable holding the number of command line arguments from +\fBmain\fR(). +.AP "char" ***argvPtr in +Pointer to an array of strings containing the command line arguments to +\fBmain\fR(). .AP Tcl_Interp *interp in -Interpreter in which the zip file system is mounted. The interpreter's result is +Interpreter in which the ZIP file system is mounted. The interpreter's result is modified to hold the result or error message from the script. .AP "const char" *zipname in -Name of a zipfile. -.AP "const char" *mntpt in -Name of a mount point. -.AP "const char" *passwd in -An (optional) password. +Name of a ZIP file. Must not be NULL when either mounting or unmounting a ZIP. +.AP "const char" *mountpoint in +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. .BE .SH DESCRIPTION -\fBTclZipfs_AppHook()\fR is a utility function to perform standard -application initialization procedures. If the current application has -a mountable zip file system, that file system is mounted under \fIZIPROOT\fR\fB/app\fR. -If a file named \fBmain.tcl\fR is located in that file system, it is treated -as the startup script for the process. If the file \fIZIPROOT\fR\fB/app/tcl_library/init.tcl\fR -is present, \fBtcl_library\fR is set to \fIZIPROOT\fR\fB/app/tcl_library. +\fBTclZipfs_AppHook\fR is a utility function to perform standard application +initialization procedures, taking into account available ZIP archives as +follows: +.IP [1] +If the current application has a mountable ZIP archive, that archive is +mounted under \fIZIPFS_VOLUME\fB/app\fR as a read-only Tcl virtual file +system. \fIZIPFS_VOLUME\fR is usually \fB//zipfs:\fR on all platforms, but +\fBzipfs:\fR may also be used on Windows (due to differences in the +platform's filename parsing). +.IP [2] +If a file named \fBmain.tcl\fR is located in the root directory of that file +system (i.e., at \fIZIPROOT\fB/app/main.tcl\fR after the ZIP archive is +mounted as described above) it is treated as the startup script for the +process. +.IP [3] +If the file \fIZIPROOT\fB/app/tcl_library/init.tcl\fR is present, the +\fBtcl_library\fR global variable in the initial Tcl interpreter is set to +\fIZIPROOT\fB/app/tcl_library\fR. +.IP [4] +If the directory \fBtcl_library\fR was not found in the main application +mount, the system will then search for it as either a VFS attached to the +application dynamic library, or as a zip archive named +\fBlibtcl_\fImajor\fB_\fIminor\fB_\fIpatchlevel\fB.zip\fR either in the +present working directory or in the standard Tcl install location. (For +example, the Tcl 8.7.2 release would be searched for in a file +\fBlibtcl_8_7_2.zip\fR.) That archive, if located, is also mounted read-only. .PP -On Windows, \fBTclZipfs_AppHook()\fR has a slightly different signature, it uses -WCHAR in stead of char. As a result, it only works if your application is compiled -using -DUNICODE. +On Windows, \fBTclZipfs_AppHook\fR has a slightly different signature, since +it uses WCHAR in stead of char. As a result, it requires your application to +be compiled with the UNICODE preprocessor symbol defined (e.g., via the +\fB-DUNICODE\fR compiler flag). .PP -If the \fBtcl_library\fR was not found in the application, the system will then search for it -as either a VFS attached to the application dynamic library, or as a zip archive named -libtcl_\fIMAJOR\fR_\fIMINOR\fR_\fIpatchLevel\fR.zip either in the present working directory -or in the standard tcl install location. +The result of \fBTclZipfs_AppHook\fR is a Tcl result code (e.g., \fBTCL_OK\fR +when the function is successful). The function \fImay\fR modify the variables +pointed to by \fIargcPtr\fR and \fIargvPtr\fR to remove arguments; the +current implementation does not do so, but callers \fIshould not\fR assume +that this will be true in the future. .PP -\fBTclzipfs_Mount()\fR mount the ZIP archive \fIzipname\fR on the mount -point given in \fImntpt\fR using the optional ZIP password \fIpasswd\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. +\fBTclzipfs_Mount\fR mounts the ZIP archive \fIzipname\fR on the mount point +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. .PP -\fBTclzipfs_Unmount()\fR undoes the effect of \fBTclzipfs_Mount()\fR, -i.e. it unmounts the mounted ZIP file system at \fImountpoint\fR. Errors are -reported in the interpreter \fIinterp\fR. +\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. +.SH "SEE ALSO" +zipfs(n) .SH KEYWORDS compress, filesystem, zip diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index e634754..4e6cd8a 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -11,8 +11,9 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This file is distributed in two ways: - * generic/tclZipfs.c file in the TIP430 enabled tcl cores - * compat/tclZipfs.c file in the tclconfig (TEA) file system, for pre-tip430 projects + * generic/tclZipfs.c file in the TIP430-enabled Tcl cores. + * compat/tclZipfs.c file in the tclconfig (TEA) file system, for pre-tip430 + * projects. */ #include "tclInt.h" @@ -43,10 +44,10 @@ ** We are compiling as part of the core. ** TIP430 style zipfs prefix */ -#define ZIPFS_VOLUME "//zipfs:/" +#define ZIPFS_VOLUME "//zipfs:/" #define ZIPFS_VOLUME_LEN 9 -#define ZIPFS_APP_MOUNT "//zipfs:/app" -#define ZIPFS_ZIP_MOUNT "//zipfs:/lib/tcl" +#define ZIPFS_APP_MOUNT "//zipfs:/app" +#define ZIPFS_ZIP_MOUNT "//zipfs:/lib/tcl" #else /* ** We are compiling from the /compat folder of tclconfig @@ -54,89 +55,100 @@ ** //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 "zipfs:/" #define ZIPFS_VOLUME_LEN 7 -#define ZIPFS_APP_MOUNT "zipfs:/app" -#define ZIPFS_ZIP_MOUNT "zipfs:/lib/tcl" +#define ZIPFS_APP_MOUNT "zipfs:/app" +#define ZIPFS_ZIP_MOUNT "zipfs:/lib/tcl" #endif /* * Various constants and offsets found in ZIP archive files */ -#define ZIP_SIG_LEN 4 +#define ZIP_SIG_LEN 4 /* 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 -#define ZIP_LOCAL_VERSION_OFFS 4 -#define ZIP_LOCAL_FLAGS_OFFS 6 -#define ZIP_LOCAL_COMPMETH_OFFS 8 -#define ZIP_LOCAL_MTIME_OFFS 10 -#define ZIP_LOCAL_MDATE_OFFS 12 -#define ZIP_LOCAL_CRC32_OFFS 14 -#define ZIP_LOCAL_COMPLEN_OFFS 18 -#define ZIP_LOCAL_UNCOMPLEN_OFFS 22 -#define ZIP_LOCAL_PATHLEN_OFFS 26 -#define ZIP_LOCAL_EXTRALEN_OFFS 28 +#define ZIP_LOCAL_HEADER_SIG 0x04034b50 +#define ZIP_LOCAL_HEADER_LEN 30 +#define ZIP_LOCAL_SIG_OFFS 0 +#define ZIP_LOCAL_VERSION_OFFS 4 +#define ZIP_LOCAL_FLAGS_OFFS 6 +#define ZIP_LOCAL_COMPMETH_OFFS 8 +#define ZIP_LOCAL_MTIME_OFFS 10 +#define ZIP_LOCAL_MDATE_OFFS 12 +#define ZIP_LOCAL_CRC32_OFFS 14 +#define ZIP_LOCAL_COMPLEN_OFFS 18 +#define ZIP_LOCAL_UNCOMPLEN_OFFS 22 +#define ZIP_LOCAL_PATHLEN_OFFS 26 +#define ZIP_LOCAL_EXTRALEN_OFFS 28 /* 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 -#define ZIP_CENTRAL_VERSIONMADE_OFFS 4 -#define ZIP_CENTRAL_VERSION_OFFS 6 -#define ZIP_CENTRAL_FLAGS_OFFS 8 -#define ZIP_CENTRAL_COMPMETH_OFFS 10 -#define ZIP_CENTRAL_MTIME_OFFS 12 -#define ZIP_CENTRAL_MDATE_OFFS 14 -#define ZIP_CENTRAL_CRC32_OFFS 16 -#define ZIP_CENTRAL_COMPLEN_OFFS 20 -#define ZIP_CENTRAL_UNCOMPLEN_OFFS 24 -#define ZIP_CENTRAL_PATHLEN_OFFS 28 -#define ZIP_CENTRAL_EXTRALEN_OFFS 30 -#define ZIP_CENTRAL_FCOMMENTLEN_OFFS 32 -#define ZIP_CENTRAL_DISKFILE_OFFS 34 -#define ZIP_CENTRAL_IATTR_OFFS 36 -#define ZIP_CENTRAL_EATTR_OFFS 38 -#define ZIP_CENTRAL_LOCALHDR_OFFS 42 +#define ZIP_CENTRAL_HEADER_SIG 0x02014b50 +#define ZIP_CENTRAL_HEADER_LEN 46 +#define ZIP_CENTRAL_SIG_OFFS 0 +#define ZIP_CENTRAL_VERSIONMADE_OFFS 4 +#define ZIP_CENTRAL_VERSION_OFFS 6 +#define ZIP_CENTRAL_FLAGS_OFFS 8 +#define ZIP_CENTRAL_COMPMETH_OFFS 10 +#define ZIP_CENTRAL_MTIME_OFFS 12 +#define ZIP_CENTRAL_MDATE_OFFS 14 +#define ZIP_CENTRAL_CRC32_OFFS 16 +#define ZIP_CENTRAL_COMPLEN_OFFS 20 +#define ZIP_CENTRAL_UNCOMPLEN_OFFS 24 +#define ZIP_CENTRAL_PATHLEN_OFFS 28 +#define ZIP_CENTRAL_EXTRALEN_OFFS 30 +#define ZIP_CENTRAL_FCOMMENTLEN_OFFS 32 +#define ZIP_CENTRAL_DISKFILE_OFFS 34 +#define ZIP_CENTRAL_IATTR_OFFS 36 +#define ZIP_CENTRAL_EATTR_OFFS 38 +#define ZIP_CENTRAL_LOCALHDR_OFFS 42 /* 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 -#define ZIP_CENTRAL_DISKNO_OFFS 4 -#define ZIP_CENTRAL_DISKDIR_OFFS 6 -#define ZIP_CENTRAL_ENTS_OFFS 8 -#define ZIP_CENTRAL_TOTALENTS_OFFS 10 -#define ZIP_CENTRAL_DIRSIZE_OFFS 12 -#define ZIP_CENTRAL_DIRSTART_OFFS 16 -#define ZIP_CENTRAL_COMMENTLEN_OFFS 20 - -#define ZIP_MIN_VERSION 20 -#define ZIP_COMPMETH_STORED 0 -#define ZIP_COMPMETH_DEFLATED 8 - -#define ZIP_PASSWORD_END_SIG 0x5a5a4b50 +#define ZIP_CENTRAL_END_SIG 0x06054b50 +#define ZIP_CENTRAL_END_LEN 22 +#define ZIP_CENTRAL_END_SIG_OFFS 0 +#define ZIP_CENTRAL_DISKNO_OFFS 4 +#define ZIP_CENTRAL_DISKDIR_OFFS 6 +#define ZIP_CENTRAL_ENTS_OFFS 8 +#define ZIP_CENTRAL_TOTALENTS_OFFS 10 +#define ZIP_CENTRAL_DIRSIZE_OFFS 12 +#define ZIP_CENTRAL_DIRSTART_OFFS 16 +#define ZIP_CENTRAL_COMMENTLEN_OFFS 20 + +#define ZIP_MIN_VERSION 20 +#define ZIP_COMPMETH_STORED 0 +#define ZIP_COMPMETH_DEFLATED 8 + +#define ZIP_PASSWORD_END_SIG 0x5a5a4b50 /* Macro to report errors only if an interp is present */ #define ZIPFS_ERROR(interp,errstr) \ - if(interp != NULL) Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1)); + do { \ + if (interp != NULL) { \ + Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1)); \ + } \ + } while (0) /* * Macros to read and write 16 and 32 bit integers from/to ZIP archives. */ -#define zip_read_int(p) \ +#define zip_read_int(p) \ ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)) -#define zip_read_short(p) \ +#define zip_read_short(p) \ ((p)[0] | ((p)[1] << 8)) -#define zip_write_int(p, v) \ - (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; \ - (p)[2] = ((v) >> 16) & 0xff; (p)[3] = ((v) >> 24) & 0xff; -#define zip_write_short(p, v) \ - (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; +#define zip_write_int(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) \ + do { \ + (p)[0] = (v) & 0xff; \ + (p)[1] = ((v) >> 8) & 0xff; \ + } while (0) /* * Windows drive letters. @@ -151,39 +163,35 @@ static const char drvletters[] = * Mutex to protect localtime(3) when no reentrant version available. */ -#ifndef _WIN32 -#ifndef HAVE_LOCALTIME_R -#ifdef TCL_THREADS +#if !defined(_WIN32) && !defined(HAVE_LOCALTIME_R) && defined(TCL_THREADS) TCL_DECLARE_MUTEX(localtimeMutex) #endif -#endif -#endif /* * In-core description of mounted ZIP archive file. */ typedef struct ZipFile { - char *name; /* Archive name */ + char *name; /* Archive name */ size_t namelen; - char is_membuf; /* 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 */ - struct ZipEntry *entries; /* List of files in archive */ - struct ZipEntry *topents; /* List of top-level dirs in archive */ + char is_membuf; /* 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 */ + 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 */ + char *mntpt; /* Mount point */ #ifdef _WIN32 HANDLE mh; - int mntdrv; /* Drive letter of mount point */ + int mntdrv; /* Drive letter of mount point */ #endif } ZipFile; @@ -192,20 +200,20 @@ typedef struct ZipFile { */ typedef struct ZipEntry { - char *name; /* The full pathname of the virtual file */ - ZipFile *zipfile; /* 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 depth; /* Number of slashes in path. */ - int crc32; /* CRC-32 */ - int timestamp; /* Modification time */ - int isenc; /* 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 */ + char *name; /* The full pathname of the virtual file */ + ZipFile *zipfile; /* 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 depth; /* Number of slashes in path. */ + int crc32; /* CRC-32 */ + int timestamp; /* Modification time */ + int isenc; /* 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 */ } ZipEntry; /* @@ -213,40 +221,41 @@ typedef struct ZipEntry { */ typedef struct ZipChannel { - ZipFile *zipfile; /* The ZIP file holding this channel */ - ZipEntry *zipentry; /* Pointer back to virtual file */ - size_t nmax; /* Max. size for write */ - size_t nbyte; /* Number of bytes of uncompressed data */ - size_t nread; /* Pos 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 */ - unsigned long keys[3]; /* Key for decryption */ + 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 + * 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 */ + unsigned long keys[3]; /* Key for decryption */ } ZipChannel; /* * Global variables. * - * Most are kept in single ZipFS struct. When build with threading - * support this struct is protected by the ZipFSMutex (see below). + * Most are kept in single ZipFS struct. When build with threading support + * this struct is protected by the ZipFSMutex (see below). * - * The "fileHash" component is the process wide global table of all known - * ZIP archive members in all mounted ZIP archives. + * The "fileHash" component is the process wide global table of all known ZIP + * archive members in all mounted ZIP archives. * * The "zipHash" components is the process wide global table of all mounted * ZIP archive files. */ static struct { - int initialized; /* True when initialized */ - int lock; /* RW lock, see below */ - int waiters; /* RW lock, see below */ - int wrmax; /* Maximum write size of a file */ - int idCount; /* Counter for channel names */ - Tcl_HashTable fileHash; /* File name to ZipEntry mapping */ - Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ + int initialized; /* True when initialized */ + int lock; /* RW lock, see below */ + int waiters; /* RW lock, see below */ + int wrmax; /* Maximum write size of a file */ + int idCount; /* Counter for channel names */ + Tcl_HashTable fileHash; /* File name to ZipEntry mapping */ + Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ } ZipFS = { 0, 0, 0, 0, 0, }; @@ -319,47 +328,38 @@ static const z_crc_t crc32tab[256] = { 0x2d02ef8d, }; -const char *zipfs_literal_tcl_library=NULL; +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, 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, Tcl_Obj *pathPtr, - int mode, int permissions -); -static int Zip_FSMatchInDirectoryProc( - 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, Tcl_Obj *pathPtr, - Tcl_Obj **objPtrRef -); -static int Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr,Tcl_Obj *objPtr); -static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, - Tcl_FSUnloadFileProc **unloadProcPtr, int flags); -static void TclZipfs_C_Init(void); + +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, + 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, + Tcl_Obj *pathPtr, int mode, int permissions); +static int Zip_FSMatchInDirectoryProc(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, + Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); +static int Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index, + Tcl_Obj *pathPtr, Tcl_Obj *objPtr); +static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, + Tcl_LoadHandle *loadHandle, + Tcl_FSUnloadFileProc **unloadProcPtr, int flags); +static void TclZipfs_C_Init(void); /* * Define the ZIP filesystem dispatch table. @@ -400,16 +400,14 @@ const Tcl_Filesystem zipfsFilesystem = { NULL, /* getCwdProc */ NULL, /* chdirProc*/ }; - - /* *------------------------------------------------------------------------- * * 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 @@ -429,9 +427,9 @@ ReadLock(void) { Tcl_MutexLock(&ZipFSMutex); while (ZipFS.lock < 0) { - ZipFS.waiters++; - Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); - ZipFS.waiters--; + ZipFS.waiters++; + Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); + ZipFS.waiters--; } ZipFS.lock++; Tcl_MutexUnlock(&ZipFSMutex); @@ -442,9 +440,9 @@ WriteLock(void) { Tcl_MutexLock(&ZipFSMutex); while (ZipFS.lock != 0) { - ZipFS.waiters++; - Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); - ZipFS.waiters--; + ZipFS.waiters++; + Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); + ZipFS.waiters--; } ZipFS.lock = -1; Tcl_MutexUnlock(&ZipFSMutex); @@ -455,42 +453,42 @@ Unlock(void) { Tcl_MutexLock(&ZipFSMutex); if (ZipFS.lock > 0) { - --ZipFS.lock; + --ZipFS.lock; } else if (ZipFS.lock < 0) { - ZipFS.lock = 0; + ZipFS.lock = 0; } if ((ZipFS.lock == 0) && (ZipFS.waiters > 0)) { - Tcl_ConditionNotify(&ZipFSCond); + Tcl_ConditionNotify(&ZipFSCond); } Tcl_MutexUnlock(&ZipFSMutex); } -#else - -#define ReadLock() do {} while (0) -#define WriteLock() do {} while (0) -#define Unlock() do {} while (0) - -#endif +#else /* !TCL_THREADS */ +#define ReadLock() do {} while (0) +#define WriteLock() do {} while (0) +#define Unlock() do {} while (0) +#endif /* TCL_THREADS */ /* *------------------------------------------------------------------------- * * DosTimeDate, ToDosTime, ToDosDate -- * - * Functions to perform conversions between DOS time stamps - * and POSIX time_t. + * Functions to perform conversions between DOS time stamps and POSIX + * time_t. * *------------------------------------------------------------------------- */ static time_t -DosTimeDate(int dosDate, int dosTime) +DosTimeDate( + int dosDate, + int dosTime) { struct tm tm; time_t ret; - memset(&tm, 0, sizeof (tm)); + memset(&tm, 0, sizeof(struct tm)); tm.tm_year = (((dosDate & 0xfe00) >> 9) + 80); tm.tm_mon = ((dosDate & 0x1e0) >> 5) - 1; tm.tm_mday = dosDate & 0x1f; @@ -499,65 +497,65 @@ DosTimeDate(int dosDate, int dosTime) tm.tm_sec = (dosTime & 0x1f) << 1; ret = mktime(&tm); if (ret == (time_t) -1) { - /* fallback to 1980-01-01T00:00:00+00:00 (DOS epoch) */ - ret = (time_t) 315532800; + /* fallback to 1980-01-01T00:00:00+00:00 (DOS epoch) */ + ret = (time_t) 315532800; } return ret; } static int -ToDosTime(time_t when) +ToDosTime( + time_t when) { struct tm *tmp, tm; -#ifdef TCL_THREADS -#ifdef _WIN32 +#if !defined(TCL_THREADS) + /* Not threaded */ + tmp = localtime(&when); + tm = *tmp; +#elif defined(_WIN32) /* Win32 uses thread local storage */ tmp = localtime(&when); tm = *tmp; -#else -#ifdef HAVE_LOCALTIME_R +#elif defined(HAVE_LOCALTIME_R) + /* Threaded, have reentrant API */ tmp = &tm; localtime_r(&when, tmp); -#else +#else /* TCL_THREADS && !_WIN32 && !HAVE_LOCALTIME_R */ + /* Only using a mutex is safe. */ Tcl_MutexLock(&localtimeMutex); tmp = localtime(&when); tm = *tmp; Tcl_MutexUnlock(&localtimeMutex); #endif -#endif -#else - tmp = localtime(&when); - tm = *tmp; -#endif return (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1); } static int -ToDosDate(time_t when) +ToDosDate( + time_t when) { struct tm *tmp, tm; -#ifdef TCL_THREADS -#ifdef _WIN32 +#if !defined(TCL_THREADS) + /* Not threaded */ + tmp = localtime(&when); + tm = *tmp; +#elif /* TCL_THREADS && */ defined(_WIN32) /* Win32 uses thread local storage */ tmp = localtime(&when); tm = *tmp; -#else -#ifdef HAVE_LOCALTIME_R +#elif /* TCL_THREADS && !_WIN32 && */ defined(HAVE_LOCALTIME_R) + /* Threaded, have reentrant API */ tmp = &tm; localtime_r(&when, tmp); -#else +#else /* TCL_THREADS && !_WIN32 && !HAVE_LOCALTIME_R */ + /* Only using a mutex is safe. */ Tcl_MutexLock(&localtimeMutex); tmp = localtime(&when); tm = *tmp; Tcl_MutexUnlock(&localtimeMutex); #endif -#endif -#else - tmp = localtime(&when); - tm = *tmp; -#endif return ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday; } @@ -566,28 +564,29 @@ ToDosDate(time_t when) * * CountSlashes -- * - * This function counts the number of slashes in a pathname string. + * This function counts the number of slashes in a pathname string. * * Results: - * Number of slashes found in string. + * Number of slashes found in string. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -CountSlashes(const char *string) +CountSlashes( + const char *string) { int count = 0; const char *p = string; while (*p != '\0') { - if (*p == '/') { - count++; - } - p++; + if (*p == '/') { + count++; + } + p++; } return count; } @@ -597,162 +596,171 @@ CountSlashes(const char *string) * * CanonicalPath -- * - * This function computes the canonical path from a directory - * and file name components into the specified Tcl_DString. + * This function computes the canonical path from a directory and file + * name components into the specified Tcl_DString. * * Results: - * Returns the pointer to the canonical path contained in the - * specified Tcl_DString. + * Returns the pointer to the canonical path contained in the specified + * Tcl_DString. * * Side effects: - * Modifies the specified Tcl_DString. + * Modifies the specified Tcl_DString. * *------------------------------------------------------------------------- */ static char * -CanonicalPath(const char *root, const char *tail, Tcl_DString *dsPtr,int ZIPFSPATH) +CanonicalPath( + const char *root, + const char *tail, + Tcl_DString *dsPtr, + int ZIPFSPATH) { char *path; - char *result; - int i, j, c, isunc = 0, isvfs=0, n=0; + int i, j, c, isunc = 0, isvfs = 0, n = 0; + int zipfspath = 1; + #ifdef _WIN32 - int zipfspath=1; - if ( - (tail[0] != '\0') - && (strchr(drvletters, tail[0]) != NULL) - && (tail[1] == ':') - ) { - tail += 2; - zipfspath=0; + if ((tail[0] != '\0') && (strchr(drvletters, tail[0]) != NULL) + && (tail[1] == ':')) { + tail += 2; + zipfspath = 0; } /* UNC style path */ if (tail[0] == '\\') { - root = ""; - ++tail; - zipfspath=0; + root = ""; + ++tail; + zipfspath = 0; } if (tail[0] == '\\') { - root = "/"; - ++tail; - zipfspath=0; - } - if(zipfspath) { -#endif - /* UNC style path */ - if(root && strncmp(root,ZIPFS_VOLUME,ZIPFS_VOLUME_LEN)==0) { - isvfs=1; - } else if (tail && strncmp(tail,ZIPFS_VOLUME,ZIPFS_VOLUME_LEN) == 0) { - isvfs=2; - } - if(isvfs!=1) { - if ((root[0] == '/') && (root[1] == '/')) { - isunc = 1; - } - } -#ifdef _WIN32 - } -#endif - if(isvfs!=2) { - if (tail[0] == '/') { - if(isvfs!=1) { - root = ""; - } - ++tail; - isunc = 0; - } - if (tail[0] == '/') { - if(isvfs!=1) { - root = "/"; - } - ++tail; - isunc = 1; - } + root = "/"; + ++tail; + zipfspath = 0; + } +#endif /* _WIN32 */ + + if (zipfspath) { + /* UNC style path */ + if (root && strncmp(root, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) { + isvfs = 1; + } else if (tail && + strncmp(tail, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) { + isvfs = 2; + } + if (isvfs != 1) { + if ((root[0] == '/') && (root[1] == '/')) { + isunc = 1; + } + } + } + + if (isvfs != 2) { + if (tail[0] == '/') { + if (isvfs != 1) { + root = ""; + } + ++tail; + isunc = 0; + } + if (tail[0] == '/') { + if (isvfs != 1) { + root = "/"; + } + ++tail; + isunc = 1; + } } i = strlen(root); j = strlen(tail); - if(isvfs==1) { - if(i>ZIPFS_VOLUME_LEN) { - Tcl_DStringSetLength(dsPtr, i + j + 1); - path = Tcl_DStringValue(dsPtr); - memcpy(path, root, i); - path[i++] = '/'; - memcpy(path + i, tail, j); - } else { - Tcl_DStringSetLength(dsPtr, i + j); - path = Tcl_DStringValue(dsPtr); - memcpy(path, root, i); - memcpy(path + i, tail, j); - } - } else if(isvfs==2) { - Tcl_DStringSetLength(dsPtr, j); - path = Tcl_DStringValue(dsPtr); - memcpy(path, tail, j); - } else { - if (ZIPFSPATH) { - Tcl_DStringSetLength(dsPtr, i + j + ZIPFS_VOLUME_LEN); - path = Tcl_DStringValue(dsPtr); - memcpy(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN); - memcpy(path + ZIPFS_VOLUME_LEN + i , tail, j); - } else { - Tcl_DStringSetLength(dsPtr, i + j + 1); - path = Tcl_DStringValue(dsPtr); - memcpy(path, root, i); - path[i++] = '/'; - memcpy(path + i, tail, j); - } + + switch (isvfs) { + case 1: + if (i > ZIPFS_VOLUME_LEN) { + Tcl_DStringSetLength(dsPtr, i + j + 1); + path = Tcl_DStringValue(dsPtr); + memcpy(path, root, i); + path[i++] = '/'; + memcpy(path + i, tail, j); + } else { + Tcl_DStringSetLength(dsPtr, i + j); + path = Tcl_DStringValue(dsPtr); + memcpy(path, root, i); + memcpy(path + i, tail, j); + } + break; + case 2: + Tcl_DStringSetLength(dsPtr, j); + path = Tcl_DStringValue(dsPtr); + memcpy(path, tail, j); + break; + default: + if (ZIPFSPATH) { + Tcl_DStringSetLength(dsPtr, i + j + ZIPFS_VOLUME_LEN); + path = Tcl_DStringValue(dsPtr); + memcpy(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN); + memcpy(path + ZIPFS_VOLUME_LEN + i , tail, j); + } else { + Tcl_DStringSetLength(dsPtr, i + j + 1); + path = Tcl_DStringValue(dsPtr); + memcpy(path, root, i); + path[i++] = '/'; + memcpy(path + i, tail, j); + } + break; } + #ifdef _WIN32 for (i = 0; path[i] != '\0'; i++) { - if (path[i] == '\\') { - path[i] = '/'; - } + if (path[i] == '\\') { + path[i] = '/'; + } } #endif - if(ZIPFSPATH) { - n=ZIPFS_VOLUME_LEN; + + if (ZIPFSPATH) { + n = ZIPFS_VOLUME_LEN; } else { - n=0; + n = 0; } + for (i = j = n; (c = path[i]) != '\0'; i++) { - if (c == '/') { - int c2 = path[i + 1]; - if (c2 == '/') { - continue; - } - if (c2 == '.') { - int c3 = path[i + 2]; - if ((c3 == '/') || (c3 == '\0')) { - i++; - continue; - } - if ( - (c3 == '.') - && ((path[i + 3] == '/') || (path [i + 3] == '\0')) - ) { - i += 2; - while ((j > 0) && (path[j - 1] != '/')) { - j--; - } - if (j > isunc) { - --j; - while ((j > 1 + isunc) && (path[j - 2] == '/')) { - j--; - } - } - continue; - } - } - } - path[j++] = c; + if (c == '/') { + int c2 = path[i + 1]; + + if (c2 == '\0' || c2 == '/') { + continue; + } + if (c2 == '.') { + int c3 = path[i + 2]; + + if ((c3 == '/') || (c3 == '\0')) { + i++; + continue; + } + if ((c3 == '.') + && ((path[i + 3] == '/') || (path [i + 3] == '\0'))) { + i += 2; + while ((j > 0) && (path[j - 1] != '/')) { + j--; + } + if (j > isunc) { + --j; + while ((j > 1 + isunc) && (path[j - 2] == '/')) { + j--; + } + } + continue; + } + } + } + path[j++] = c; } if (j == 0) { - path[j++] = '/'; + path[j++] = '/'; } path[j] = 0; Tcl_DStringSetLength(dsPtr, j); - result=Tcl_DStringValue(dsPtr); - return result; + return Tcl_DStringValue(dsPtr); } /* @@ -760,263 +768,279 @@ CanonicalPath(const char *root, const char *tail, Tcl_DString *dsPtr,int ZIPFSPA * * ZipFSLookup -- * - * This function returns the ZIP entry struct corresponding to - * the ZIP archive member of the given file name. + * This function returns the ZIP entry struct corresponding to the ZIP + * archive member of the given file name. * * Results: - * Returns the pointer to ZIP entry struct or NULL if the - * the given file name could not be found in the global list - * of ZIP archive members. + * Returns the pointer to ZIP entry struct or NULL if the the given file + * name could not be found in the global list of ZIP archive members. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static ZipEntry * -ZipFSLookup(char *filename) +ZipFSLookup( + char *filename) { Tcl_HashEntry *hPtr; - ZipEntry *z; - Tcl_DString ds; - Tcl_DStringInit(&ds); + ZipEntry *z = NULL; + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename); - z = hPtr ? (ZipEntry *) Tcl_GetHashValue(hPtr) : NULL; - Tcl_DStringFree(&ds); + if (hPtr != NULL) { + z = Tcl_GetHashValue(hPtr); + } return z; } - -#ifdef NEVER_USED +#ifdef NEVER_USED + /* *------------------------------------------------------------------------- * * ZipFSLookupMount -- * - * This function returns an indication if the given file name - * corresponds to a mounted ZIP archive file. + * This function returns an indication if the given file name corresponds + * to a mounted ZIP archive file. * * Results: - * Returns true, if the given file name is a mounted ZIP archive file. + * Returns true, if the given file name is a mounted ZIP archive file. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -ZipFSLookupMount(char *filename) +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; - } - hPtr = Tcl_NextHashEntry(&search); + if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) == NULL) { + continue; + } + if (strcmp(zf->mntpt, filename) == 0) { + match = 1; + break; + } + hPtr = Tcl_NextHashEntry(&search); } return match; } -#endif +#endif /* NEVER_USED */ /* *------------------------------------------------------------------------- * * ZipFSCloseArchive -- * - * This function closes a mounted ZIP archive file. + * This function closes a mounted ZIP archive file. * * Results: - * None. + * None. * * Side effects: - * A memory mapped ZIP archive is unmapped, allocated memory is - * released. + * A memory mapped ZIP archive is unmapped, allocated memory is released. + * The ZipFile pointer is *NOT* deallocated by this function. * *------------------------------------------------------------------------- */ static void -ZipFSCloseArchive(Tcl_Interp *interp, ZipFile *zf) +ZipFSCloseArchive( + Tcl_Interp *interp, + ZipFile *zf) { - if(zf->namelen) { - free(zf->name); //Allocated by strdup - } - if(zf->is_membuf==1) { - /* Pointer to memory */ - if (zf->tofree != NULL) { - Tcl_Free(zf->tofree); - zf->tofree = NULL; - } - zf->data = NULL; - return; + if (zf->namelen) { + free(zf->name); /* Allocated by strdup */ } + if (zf->is_membuf == 1) { + /* Pointer to memory */ + if (zf->tofree != NULL) { + Tcl_Free(zf->tofree); + zf->tofree = NULL; + } + zf->data = NULL; + return; + } + #ifdef _WIN32 if ((zf->data != NULL) && (zf->tofree == NULL)) { - UnmapViewOfFile(zf->data); - zf->data = NULL; + UnmapViewOfFile(zf->data); + zf->data = NULL; } if (zf->mh != INVALID_HANDLE_VALUE) { - CloseHandle(zf->mh); + CloseHandle(zf->mh); } -#else +#else /* !_WIN32 */ if ((zf->data != MAP_FAILED) && (zf->tofree == NULL)) { - munmap(zf->data, zf->length); - zf->data = MAP_FAILED; + munmap(zf->data, zf->length); + zf->data = MAP_FAILED; } -#endif +#endif /* _WIN32 */ + if (zf->tofree != NULL) { - Tcl_Free(zf->tofree); - zf->tofree = NULL; + Tcl_Free(zf->tofree); + zf->tofree = NULL; } - if(zf->chan != NULL) { - Tcl_Close(interp, zf->chan); - zf->chan = NULL; + if (zf->chan != NULL) { + Tcl_Close(interp, zf->chan); + zf->chan = NULL; } } - + /* *------------------------------------------------------------------------- * * ZipFS_Find_TOC -- * - * This function takes a memory mapped zip file and indexes the contents. - * When "needZip" is zero an embedded ZIP archive in an executable file is accepted. + * This function takes a memory mapped zip file and indexes the contents. + * When "needZip" is zero an embedded ZIP archive in an executable file + * is accepted. * * 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: - * The given ZipFile struct is filled with information about the ZIP archive file. + * The given ZipFile struct is filled with information about the ZIP + * archive file. * *------------------------------------------------------------------------- */ + static int -ZipFS_Find_TOC(Tcl_Interp *interp, int needZip, ZipFile *zf) +ZipFS_Find_TOC( + Tcl_Interp *interp, + int needZip, + ZipFile *zf) { size_t i; unsigned char *p, *q; + 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) { - break; - } - p -= ZIP_SIG_LEN; - } else { - --p; - } + if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) { + if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) { + break; + } + p -= ZIP_SIG_LEN; + } else { + --p; + } } if (p < zf->data) { - if (!needZip) { - zf->baseoffs = zf->baseoffsp = zf->length; - return TCL_OK; - } - ZIPFS_ERROR(interp,"wrong end signature"); - goto error; + if (!needZip) { + zf->baseoffs = zf->baseoffsp = 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) { - if (!needZip) { - zf->baseoffs = zf->baseoffsp = zf->length; - return TCL_OK; - } - ZIPFS_ERROR(interp,"empty archive"); - goto error; + if (!needZip) { + zf->baseoffs = zf->baseoffsp = 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); - if ( - (p < zf->data) || (p > (zf->data + zf->length)) || - (q < zf->data) || (q > (zf->data + zf->length)) - ) { - if (!needZip) { - zf->baseoffs = zf->baseoffsp = zf->length; - return TCL_OK; - } - ZIPFS_ERROR(interp,"archive directory not found"); - goto error; + if ((p < zf->data) || (p > zf->data + zf->length) + || (q < zf->data) || (q > (zf->data + zf->length))) { + if (!needZip) { + zf->baseoffs = zf->baseoffsp = 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; q = p; for (i = 0; i < zf->nfiles; 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) { - 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); - q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; + 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) { + 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); + 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)) { - 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; - } + 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; + } } - return TCL_OK; -error: + error: ZipFSCloseArchive(interp, zf); return TCL_ERROR; } - + /* *------------------------------------------------------------------------- * * ZipFSOpenArchive -- * - * This function opens a ZIP archive file for reading. An attempt - * is made to memory map that file. Otherwise it is read into - * an allocated memory buffer. The ZIP archive header is verified - * and must be valid for the function to succeed. When "needZip" - * is zero an embedded ZIP archive in an executable file is accepted. + * This function opens a ZIP archive file for reading. An attempt is made + * to memory map that file. Otherwise it is read into an allocated memory + * buffer. The ZIP archive header is verified and must be valid for the + * function to succeed. When "needZip" is zero an embedded ZIP archive in + * an executable file is accepted. * * 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: - * ZIP archive is memory mapped or read into allocated memory, - * the given ZipFile struct is filled with information about - * the ZIP archive file. + * ZIP archive is memory mapped or read into allocated memory, the given + * ZipFile struct is filled with information about the ZIP archive file. * *------------------------------------------------------------------------- */ static int -ZipFSOpenArchive(Tcl_Interp *interp, const char *zipname, int needZip, ZipFile *zf) +ZipFSOpenArchive( + Tcl_Interp *interp, + const char *zipname, + int needZip, + ZipFile *zf) { size_t i; ClientData handle; - zf->namelen=0; - zf->is_membuf=0; + + zf->namelen = 0; + zf->is_membuf = 0; #ifdef _WIN32 zf->data = NULL; zf->mh = INVALID_HANDLE_VALUE; -#else +#else /* !_WIN32 */ zf->data = MAP_FAILED; -#endif +#endif /* _WIN32 */ zf->length = 0; zf->nfiles = 0; zf->baseoffs = zf->baseoffsp = 0; @@ -1024,83 +1048,79 @@ ZipFSOpenArchive(Tcl_Interp *interp, const char *zipname, int needZip, ZipFile * zf->pwbuf[0] = 0; zf->chan = Tcl_OpenFileChannel(interp, zipname, "r", 0); if (zf->chan == NULL) { - return TCL_ERROR; + return TCL_ERROR; } if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) { - if (Tcl_SetChannelOption(interp, zf->chan, "-translation", "binary") != TCL_OK) { - goto error; - } - if (Tcl_SetChannelOption(interp, zf->chan, "-encoding", "binary") != TCL_OK) { - 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) { - 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"); - goto error; - } - Tcl_Close(interp, zf->chan); - zf->chan = NULL; + if (Tcl_SetChannelOption(interp, zf->chan, "-translation", + "binary") != TCL_OK) { + 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) { + 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"); + goto error; + } + Tcl_Close(interp, zf->chan); + zf->chan = NULL; } else { #ifdef _WIN32 + int readSuccessful; # ifdef _WIN64 - i = GetFileSizeEx((HANDLE) handle, (PLARGE_INTEGER)&zf->length); - if ( - (i == 0) || -# else - zf->length = GetFileSize((HANDLE) handle, 0); - if ( - (zf->length == (size_t)INVALID_FILE_SIZE) || -# endif - (zf->length < ZIP_CENTRAL_END_LEN) - ) { - ZIPFS_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"); - goto error; - } - zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length); - if (zf->data == NULL) { - ZIPFS_ERROR(interp,"file mapping failed"); - goto error; - } -#else - 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"); - 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"); - goto error; - } -#endif - } - return ZipFS_Find_TOC(interp,needZip,zf); - -error: + i = GetFileSizeEx((HANDLE) handle, (PLARGE_INTEGER) &zf->length); + readSuccessful = (i != 0); +# else /* !_WIN64 */ + zf->length = GetFileSize((HANDLE) handle, 0); + readSuccessful = (zf->length != (size_t) INVALID_FILE_SIZE); +# endif /* _WIN64 */ + if (!readSuccessful || (zf->length < ZIP_CENTRAL_END_LEN)) { + ZIPFS_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"); + goto error; + } + zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length); + if (zf->data == NULL) { + ZIPFS_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"); + 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"); + goto error; + } +#endif /* _WIN32 */ + } + return ZipFS_Find_TOC(interp, needZip, zf); + + error: ZipFSCloseArchive(interp, zf); return TCL_ERROR; } - + /* *------------------------------------------------------------------------- * @@ -1117,7 +1137,12 @@ error: */ static int -ZipFS_Catalogue_Filesystem(Tcl_Interp *interp, ZipFile *zf0, const char *mntpt, const char *passwd, const char *zipname) +ZipFS_Catalogue_Filesystem( + Tcl_Interp *interp, + ZipFile *zf0, + const char *mntpt, + const char *passwd, + const char *zipname) { int pwlen, isNew; size_t i; @@ -1126,259 +1151,269 @@ ZipFS_Catalogue_Filesystem(Tcl_Interp *interp, ZipFile *zf0, const char *mntpt, Tcl_HashEntry *hPtr; Tcl_DString ds, dsm, fpBuf; unsigned char *q; - WriteLock(); + + /* + * Basic verification of the password for sanity. + */ pwlen = 0; if (passwd != NULL) { - pwlen = strlen(passwd); - if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - } - return TCL_ERROR; - } + pwlen = strlen(passwd); + if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); + } + return TCL_ERROR; + } } + + WriteLock(); + /* * Mount point sometimes is a relative or otherwise denormalized path. * But an absolute name is needed as mount point here. */ + Tcl_DStringInit(&ds); Tcl_DStringInit(&dsm); if (strcmp(mntpt, "/") == 0) { - mntpt = ""; + mntpt = ""; } else { - mntpt = CanonicalPath("",mntpt, &dsm, 1); + mntpt = CanonicalPath("", mntpt, &dsm, 1); } hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mntpt, &isNew); if (!isNew) { - zf = (ZipFile *) Tcl_GetHashValue(hPtr); - if (interp != NULL) { - Tcl_AppendResult(interp, zf->name, " is already mounted on ", mntpt, (char *) NULL); - } - Unlock(); - ZipFSCloseArchive(interp, zf0); - return TCL_ERROR; + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + if (interp != NULL) { + Tcl_AppendResult(interp, zf->name, " is already mounted on ", + mntpt, (char *) NULL); + } + Unlock(); + ZipFSCloseArchive(interp, zf0); + return TCL_ERROR; } zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1); if (zf == NULL) { - if (interp != NULL) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - } - Unlock(); - ZipFSCloseArchive(interp, zf0); - return TCL_ERROR; + if (interp != NULL) { + Tcl_AppendResult(interp, "out of memory", (char *) NULL); + } + Unlock(); + ZipFSCloseArchive(interp, zf0); + return TCL_ERROR; } Unlock(); + *zf = *zf0; zf->mntpt = Tcl_GetHashKey(&ZipFS.zipHash, hPtr); - zf->mntptlen=strlen(zf->mntpt); + zf->mntptlen = strlen(zf->mntpt); zf->name = strdup(zipname); - zf->namelen= strlen(zipname); + zf->namelen = strlen(zipname); zf->entries = NULL; zf->topents = NULL; zf->nopen = 0; - Tcl_SetHashValue(hPtr, (ClientData) zf); + Tcl_SetHashValue(hPtr, zf); if ((zf->pwbuf[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->pwbuf[k] = '\0'; + 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->pwbuf[k] = '\0'; } if (mntpt[0] != '\0') { - z = (ZipEntry *) Tcl_Alloc(sizeof (*z)); - 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 { - Tcl_SetHashValue(hPtr, (ClientData) z); - z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr); - z->next = zf->entries; - zf->entries = z; - } + 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 { + Tcl_SetHashValue(hPtr, z); + z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->next = zf->entries; + zf->entries = z; + } } q = zf->data + zf->centoffs; Tcl_DStringInit(&fpBuf); for (i = 0; i < zf->nfiles; 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); - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen); - path = Tcl_DStringValue(&ds); - if ((pathlen > 0) && (path[pathlen - 1] == '/')) { - Tcl_DStringSetLength(&ds, pathlen - 1); - path = Tcl_DStringValue(&ds); - isdir = 1; - } - if ((strcmp(path, ".") == 0) || (strcmp(path, "..") == 0)) { - goto nextent; - } - lq = zf->data + zf->baseoffs + zip_read_int(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); - if ( - !isdir && (nbcompr == 0) - && (zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) - && (zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS) == 0) - ) { - gq = q; - nbcompr = zip_read_int(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) { - goto nextent; - } - if (!isdir && (mntpt[0] == '\0') && !CountSlashes(path)) { + 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); + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen); + path = Tcl_DStringValue(&ds); + if ((pathlen > 0) && (path[pathlen - 1] == '/')) { + Tcl_DStringSetLength(&ds, pathlen - 1); + path = Tcl_DStringValue(&ds); + isdir = 1; + } + if ((strcmp(path, ".") == 0) || (strcmp(path, "..") == 0)) { + goto nextent; + } + lq = zf->data + zf->baseoffs + + zip_read_int(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); + if (!isdir && (nbcompr == 0) + && (zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) + && (zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { + gq = q; + nbcompr = zip_read_int(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) { + goto nextent; + } + if (!isdir && (mntpt[0] == '\0') && !CountSlashes(path)) { #ifdef ANDROID - /* - * When mounting the ZIP archive on the root directory try - * to remap top level regular files of the archive to - * /assets/.root/... since this directory should not be - * in a valid APK due to the leading dot in the file name - * component. This trick should make the files - * AndroidManifest.xml, resources.arsc, and classes.dex - * visible to Tcl. - */ - Tcl_DString ds2; - - Tcl_DStringInit(&ds2); - Tcl_DStringAppend(&ds2, "assets/.root/", -1); - Tcl_DStringAppend(&ds2, path, -1); - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, Tcl_DStringValue(&ds2)); - if (hPtr != NULL) { - /* should not happen but skip it anyway */ - Tcl_DStringFree(&ds2); - goto nextent; - } - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, Tcl_DStringValue(&ds2), Tcl_DStringLength(&ds2)); - path = Tcl_DStringValue(&ds); - Tcl_DStringFree(&ds2); -#else - /* - * Regular files skipped when mounting on root. - */ - goto nextent; -#endif - } - Tcl_DStringSetLength(&fpBuf, 0); - fullpath = CanonicalPath(mntpt, path, &fpBuf, 1); - z = (ZipEntry *) Tcl_Alloc(sizeof (*z)); - 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) && (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); - 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); - } 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->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->nbytecompr = nbcompr; - z->data = NULL; - hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew); - if (!isNew) { - /* should not happen but skip it anyway */ - Tcl_Free((char *) z); - } else { - Tcl_SetHashValue(hPtr, (ClientData) 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 (!z->isdir && (z->depth > 1)) { - char *dir, *end; - ZipEntry *zd; - - Tcl_DStringSetLength(&ds, strlen(z->name) + 8); - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, z->name, -1); - dir = Tcl_DStringValue(&ds); - end = strrchr(dir, '/'); - while ((end != NULL) && (end != dir)) { - Tcl_DStringSetLength(&ds, end - dir); - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, dir); - if (hPtr != NULL) { - break; - } - zd = (ZipEntry *) Tcl_Alloc(sizeof (*zd)); - zd->name = NULL; - zd->tnext = NULL; - zd->depth = CountSlashes(dir); - zd->zipfile = zf; - zd->isdir = 1; - zd->isenc = 0; - zd->offset = z->offset; - zd->crc32 = 0; - zd->timestamp = z->timestamp; - zd->nbyte = zd->nbytecompr = 0; - zd->cmeth = 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, (ClientData) 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; - } - } - end = strrchr(dir, '/'); - } - } - } -nextent: - q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; + /* + * When mounting the ZIP archive on the root directory try to + * remap top level regular files of the archive to + * /assets/.root/... since this directory should not be in a valid + * APK due to the leading dot in the file name component. This + * trick should make the files AndroidManifest.xml, + * resources.arsc, and classes.dex visible to Tcl. + */ + Tcl_DString ds2; + + Tcl_DStringInit(&ds2); + Tcl_DStringAppend(&ds2, "assets/.root/", -1); + Tcl_DStringAppend(&ds2, path, -1); + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, Tcl_DStringValue(&ds2)); + if (hPtr != NULL) { + /* should not happen but skip it anyway */ + Tcl_DStringFree(&ds2); + goto nextent; + } + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, Tcl_DStringValue(&ds2), + Tcl_DStringLength(&ds2)); + path = Tcl_DStringValue(&ds); + Tcl_DStringFree(&ds2); +#else /* !ANDROID */ + /* + * Regular files skipped when mounting on root. + */ + goto nextent; +#endif /* ANDROID */ + } + Tcl_DStringSetLength(&fpBuf, 0); + fullpath = CanonicalPath(mntpt, path, &fpBuf, 1); + z = (ZipEntry *) Tcl_Alloc(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) + && (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); + 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); + } 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->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->nbytecompr = nbcompr; + z->data = NULL; + hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew); + if (!isNew) { + /* should not happen but skip it anyway */ + Tcl_Free((char *) 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 (!z->isdir && (z->depth > 1)) { + char *dir, *end; + ZipEntry *zd; + + Tcl_DStringSetLength(&ds, strlen(z->name) + 8); + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, z->name, -1); + dir = Tcl_DStringValue(&ds); + end = strrchr(dir, '/'); + while ((end != NULL) && (end != dir)) { + Tcl_DStringSetLength(&ds, end - dir); + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, dir); + if (hPtr != NULL) { + break; + } + zd = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry)); + zd->name = NULL; + zd->tnext = NULL; + zd->depth = CountSlashes(dir); + zd->zipfile = zf; + zd->isdir = 1; + zd->isenc = 0; + zd->offset = z->offset; + zd->crc32 = 0; + zd->timestamp = z->timestamp; + zd->nbyte = zd->nbytecompr = 0; + zd->cmeth = 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; + } + } + end = strrchr(dir, '/'); + } + } + } + nextent: + q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; } Tcl_DStringFree(&fpBuf); Tcl_DStringFree(&ds); @@ -1386,40 +1421,42 @@ nextent: Unlock(); return TCL_OK; } - -static void TclZipfs_C_Init(void) { + +static void +TclZipfs_C_Init(void) +{ 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); -#endif - Tcl_FSRegister(NULL, &zipfsFilesystem); - Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS); - Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS); - ZipFS.initialized = ZipFS.idCount = 1; + /* + * 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; } } - /* *------------------------------------------------------------------------- * * TclZipfs_Mount -- * - * 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. + * A standard Tcl result. * * Side effects: - * A ZIP archive file is read, analyzed and mounted, resources are - * allocated. + * A ZIP archive file is read, analyzed and mounted, resources are + * allocated. * *------------------------------------------------------------------------- */ @@ -1429,76 +1466,76 @@ TclZipfs_Mount( Tcl_Interp *interp, const char *mntpt, const char *zipname, - const char *passwd -) { + const char *passwd) +{ int i, pwlen; ZipFile *zf; ReadLock(); if (!ZipFS.initialized) { - TclZipfs_C_Init(); + 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; - } - Unlock(); - return ret; + 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; + } + Unlock(); + return ret; } if (zipname == NULL) { - Tcl_HashEntry *hPtr; - if (interp == NULL) { - Unlock(); - return TCL_OK; - } - hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); - if (hPtr != NULL) { - if ((zf = Tcl_GetHashValue(hPtr)) != NULL) { - Tcl_SetObjResult(interp,Tcl_NewStringObj(zf->name, -1)); - } - } - Unlock(); - return TCL_OK; + if (interp != NULL) { + Tcl_HashEntry *hPtr; + + hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); + if (hPtr != NULL) { + if ((zf = Tcl_GetHashValue(hPtr)) != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1)); + } + } + } + Unlock(); + return TCL_OK; } Unlock(); pwlen = 0; if (passwd != NULL) { - pwlen = strlen(passwd); - if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - } - return TCL_ERROR; - } + pwlen = strlen(passwd); + if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); + } + return TCL_ERROR; + } } zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1); if (zf == NULL) { - if (interp != NULL) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - } - return TCL_ERROR; + if (interp != NULL) { + Tcl_AppendResult(interp, "out of memory", (char *) NULL); + } + return TCL_ERROR; } if (ZipFSOpenArchive(interp, zipname, 1, zf) != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } - return ZipFS_Catalogue_Filesystem(interp,zf,mntpt,passwd,zipname); + return ZipFS_Catalogue_Filesystem(interp, zf, mntpt, passwd, zipname); } /* @@ -1506,15 +1543,15 @@ TclZipfs_Mount( * * TclZipfs_Mount_Buffer -- * - * 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. + * A standard Tcl result. * * Side effects: - * A ZIP archive file is read, analyzed and mounted, resources are - * allocated. + * A ZIP archive file is read, analyzed and mounted, resources are + * allocated. * *------------------------------------------------------------------------- */ @@ -1525,83 +1562,84 @@ TclZipfs_Mount_Buffer( const char *mntpt, unsigned char *data, size_t datalen, - int copy -) { + int copy) +{ int i; ZipFile *zf; ReadLock(); if (!ZipFS.initialized) { - TclZipfs_C_Init(); + 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; - } - Unlock(); - return ret; + 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; + } + Unlock(); + return ret; } if (data == NULL) { - Tcl_HashEntry *hPtr; - - if (interp == NULL) { - Unlock(); - return TCL_OK; - } - hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); - if (hPtr != NULL) { - if ((zf = Tcl_GetHashValue(hPtr)) != NULL) { - Tcl_SetObjResult(interp,Tcl_NewStringObj(zf->name, -1)); - } - } - Unlock(); - return TCL_OK; + if (interp != NULL) { + Tcl_HashEntry *hPtr; + + hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); + if (hPtr != NULL) { + zf = Tcl_GetHashValue(hPtr); + if (zf != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1)); + } + } + } + Unlock(); + return TCL_OK; } Unlock(); - zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1); + + zf = (ZipFile *) Tcl_AttemptAlloc(sizeof(ZipFile) + strlen(mntpt) + 1); if (zf == NULL) { - if (interp != NULL) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - } - return TCL_ERROR; - } - zf->is_membuf=1; - zf->length=datalen; - if(copy) { - zf->data=(unsigned char *)Tcl_AttemptAlloc(datalen); - if (zf->data == NULL) { - if (interp != NULL) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - } - return TCL_ERROR; - } - memcpy(zf->data,data,datalen); - zf->tofree=zf->data; + if (interp != NULL) { + Tcl_AppendResult(interp, "out of memory", (char *) NULL); + } + return TCL_ERROR; + } + zf->is_membuf = 1; + zf->length = datalen; + if (copy) { + zf->data = (unsigned char *) Tcl_AttemptAlloc(datalen); + if (zf->data == NULL) { + if (interp != NULL) { + Tcl_AppendResult(interp, "out of memory", (char *) NULL); + } + return TCL_ERROR; + } + memcpy(zf->data, data, datalen); + zf->tofree = zf->data; } else { - zf->data=data; - zf->tofree=NULL; + zf->data = data; + zf->tofree = NULL; } - if(ZipFS_Find_TOC(interp,0,zf)!=TCL_OK) { - return TCL_ERROR; + if (ZipFS_Find_TOC(interp, 0, zf) != TCL_OK) { + return TCL_ERROR; } - return ZipFS_Catalogue_Filesystem(interp,zf,mntpt,NULL,"Memory Buffer"); + return ZipFS_Catalogue_Filesystem(interp, zf, mntpt, NULL, + "Memory Buffer"); } /* @@ -1609,19 +1647,21 @@ TclZipfs_Mount_Buffer( * * TclZipfs_Unmount -- * - * This procedure is invoked to unmount a given ZIP archive. + * This procedure is invoked to unmount a given ZIP archive. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * A mounted ZIP archive file is unmounted, resources are free'd. + * A mounted ZIP archive file is unmounted, resources are free'd. * *------------------------------------------------------------------------- */ int -TclZipfs_Unmount(Tcl_Interp *interp, const char *mntpt) +TclZipfs_Unmount( + Tcl_Interp *interp, + const char *mntpt) { ZipFile *zf; ZipEntry *z, *znext; @@ -1630,44 +1670,49 @@ TclZipfs_Unmount(Tcl_Interp *interp, const char *mntpt) int ret = TCL_OK, unmounted = 0; WriteLock(); - if (!ZipFS.initialized) goto done; + if (!ZipFS.initialized) { + goto done; + } + /* * Mount point sometimes is a relative or otherwise denormalized path. * But an absolute name is needed as mount point here. */ + Tcl_DStringInit(&dsm); mntpt = CanonicalPath("", mntpt, &dsm, 1); hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); - - /* don't report error */ - if (hPtr == NULL) goto done; + /* don't report no-such-mount as an error */ + if (hPtr == NULL) { + goto done; + } zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->nopen > 0) { - ZIPFS_ERROR(interp,"filesystem is busy"); - ret = TCL_ERROR; - goto done; + ZIPFS_ERROR(interp, "filesystem is busy"); + ret = TCL_ERROR; + goto done; } Tcl_DeleteHashEntry(hPtr); for (z = zf->entries; z; z = znext) { - znext = z->next; - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name); - if (hPtr) { - Tcl_DeleteHashEntry(hPtr); - } - if (z->data != NULL) { - Tcl_Free((char *) z->data); - } - Tcl_Free((char *) z); + znext = z->next; + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name); + if (hPtr) { + Tcl_DeleteHashEntry(hPtr); + } + if (z->data != NULL) { + Tcl_Free((char *) z->data); + } + Tcl_Free((char *) z); } ZipFSCloseArchive(interp, zf); Tcl_Free((char *) zf); unmounted = 1; -done: + done: Unlock(); if (unmounted) { - Tcl_FSMountsChanged(NULL); + Tcl_FSMountsChanged(NULL); } return ret; } @@ -1677,104 +1722,113 @@ done: * * ZipFSMountObjCmd -- * - * This procedure is invoked to process the "zipfs::mount" command. + * This procedure is invoked to process the "zipfs::mount" command. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * A ZIP archive file is mounted, resources are allocated. + * A ZIP archive file is mounted, resources are allocated. * *------------------------------------------------------------------------- */ static int ZipFSMountObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ if (objc > 4) { - Tcl_WrongNumArgs(interp, 1, objv, - "?mountpoint? ?zipfile? ?password?"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, + "?mountpoint? ?zipfile? ?password?"); + return TCL_ERROR; } + 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 -- * - * This procedure is invoked to process the "zipfs::mount" command. + * This procedure is invoked to process the "zipfs::mount" command. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * A ZIP archive file is mounted, resources are allocated. + * A ZIP archive file is mounted, resources are allocated. * *------------------------------------------------------------------------- */ static int ZipFSMountBufferObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ const char *mntpt; unsigned char *data; int length; + if (objc > 4) { - Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?data?"); - return TCL_ERROR; - } - if(objc<2) { - int i; - Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - int ret = TCL_OK; - ZipFile *zf; - - 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; - } - Unlock(); - return ret; - } - mntpt=Tcl_GetString(objv[1]); - if(objc<3) { - Tcl_HashEntry *hPtr; - ZipFile *zf; - - if (interp == NULL) { - Unlock(); - return TCL_OK; - } - hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mntpt); - if (hPtr != NULL) { - if ((zf = Tcl_GetHashValue(hPtr)) != NULL) { - Tcl_SetObjResult(interp,Tcl_NewStringObj(zf->name, -1)); - } - } - Unlock(); - return TCL_OK; - } - data=Tcl_GetByteArrayFromObj(objv[2],&length); - return TclZipfs_Mount_Buffer(interp, mntpt,data,length,1); + Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?data?"); + return TCL_ERROR; + } + if (objc < 2) { + int i; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + int ret = TCL_OK; + ZipFile *zf; + + 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; + } + Unlock(); + return ret; + } + + mntpt = 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)); + } + } + } + Unlock(); + return TCL_OK; + } + + data = Tcl_GetByteArrayFromObj(objv[2], &length); + return TclZipfs_Mount_Buffer(interp, mntpt, data, length, 1); } /* @@ -1782,11 +1836,11 @@ ZipFSMountBufferObjCmd( * * ZipFSRootObjCmd -- * - * 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::root" command. It + * returns the root that all zipfs file systems are mounted under. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: * @@ -1795,9 +1849,12 @@ ZipFSMountBufferObjCmd( static int ZipFSRootObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { - Tcl_SetObjResult(interp,Tcl_NewStringObj(ZIPFS_VOLUME, -1)); + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + Tcl_SetObjResult(interp, Tcl_NewStringObj(ZIPFS_VOLUME, -1)); return TCL_OK; } @@ -1806,24 +1863,27 @@ ZipFSRootObjCmd( * * ZipFSUnmountObjCmd -- * - * This procedure is invoked to process the "zipfs::unmount" command. + * This procedure is invoked to process the "zipfs::unmount" command. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * A mounted ZIP archive file is unmounted, resources are free'd. + * A mounted ZIP archive file is unmounted, resources are free'd. * *------------------------------------------------------------------------- */ static int ZipFSUnmountObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "zipfile"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "zipfile"); + return TCL_ERROR; } return TclZipfs_Unmount(interp, Tcl_GetString(objv[1])); } @@ -1833,44 +1893,47 @@ ZipFSUnmountObjCmd( * * ZipFSMkKeyObjCmd -- * - * This procedure is invoked to process the "zipfs::mkkey" command. - * It produces a rotated password to be embedded into an image file. + * This procedure is invoked to process the "zipfs::mkkey" command. It + * produces a rotated password to be embedded into an image file. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipFSMkKeyObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ int len, i = 0; char *pw, pwbuf[264]; if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "password"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "password"); + return TCL_ERROR; } pw = Tcl_GetString(objv[1]); len = strlen(pw); if (len == 0) { - return TCL_OK; + return TCL_OK; } if ((len > 255) || (strchr(pw, 0xff) != NULL)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1)); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1)); + return TCL_ERROR; } while (len > 0) { - int ch = pw[len - 1]; + int ch = pw[len - 1]; - pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; - i++; - len--; + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + i++; + len--; } pwbuf[i] = i; ++i; @@ -1888,27 +1951,32 @@ ZipFSMkKeyObjCmd( * * ZipAddFile -- * - * This procedure is used by ZipFSMkZipOrImgCmd() to add a single - * file to the output ZIP archive file being written. A ZipEntry - * struct about the input file is added to the given fileHash table - * for later creation of the central ZIP directory. + * This procedure is used by ZipFSMkZipOrImgCmd() to add a single file to + * the output ZIP archive file being written. A ZipEntry struct about the + * input file is added to the given fileHash table for later creation of + * the central ZIP directory. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * Input file is read and (compressed and) written to the output - * ZIP archive file. + * Input file is read and (compressed and) written to the output ZIP + * archive file. * *------------------------------------------------------------------------- */ static int ZipAddFile( - Tcl_Interp *interp, const char *path, const char *name, - Tcl_Channel out, const char *passwd, - char *buf, int bufsize, Tcl_HashTable *fileHash -) { + Tcl_Interp *interp, + const char *path, + const char *name, + Tcl_Channel out, + const char *passwd, + char *buf, + int bufsize, + Tcl_HashTable *fileHash) +{ Tcl_Channel in; Tcl_HashEntry *hPtr; ZipEntry *z; @@ -1923,127 +1991,127 @@ ZipAddFile( zpath = name; while (zpath != NULL && zpath[0] == '/') { - zpath++; + zpath++; } if ((zpath == NULL) || (zpath[0] == '\0')) { - return TCL_OK; + return TCL_OK; } zpathlen = strlen(zpath); if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) { - Tcl_AppendResult(interp, "path too long for \"", path, "\"", (char *) NULL); - return TCL_ERROR; + Tcl_AppendResult(interp, "path too long for \"", path, "\"", + (char *) NULL); + return TCL_ERROR; } in = Tcl_OpenFileChannel(interp, path, "r", 0); - if ( - (in == NULL) - || (Tcl_SetChannelOption(interp, in, "-translation", "binary") != TCL_OK) - || (Tcl_SetChannelOption(interp, in, "-encoding", "binary") != TCL_OK) - ) { + if ((in == NULL) || Tcl_SetChannelOption(interp, in, + "-translation", "binary") != TCL_OK) { #ifdef _WIN32 - /* hopefully a directory */ - if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { - Tcl_Close(interp, in); - return TCL_OK; - } -#endif - Tcl_Close(interp, in); - return TCL_ERROR; + /* hopefully a directory */ + if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { + Tcl_Close(interp, in); + return TCL_OK; + } +#endif /* _WIN32 */ + Tcl_Close(interp, in); + return TCL_ERROR; } else { - Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); - Tcl_StatBuf statBuf; + Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); + Tcl_StatBuf statBuf; - Tcl_IncrRefCount(pathObj); - if (Tcl_FSStat(pathObj, &statBuf) != -1) { - mtime = statBuf.st_mtime; - } - Tcl_DecrRefCount(pathObj); + Tcl_IncrRefCount(pathObj); + if (Tcl_FSStat(pathObj, &statBuf) != -1) { + mtime = statBuf.st_mtime; + } + Tcl_DecrRefCount(pathObj); } 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; + 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) { - Tcl_Close(interp, in); - return TCL_OK; - } - } - Tcl_AppendResult(interp, "read error on \"", path, "\"", - (char *) NULL); - Tcl_Close(interp, in); - return TCL_ERROR; + if (nbyte == 0) { + if (strcmp("illegal operation on a directory", + Tcl_PosixError(interp)) == 0) { + Tcl_Close(interp, in); + return TCL_OK; + } + } + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; } if (Tcl_Seek(in, 0, SEEK_SET) == -1) { - Tcl_AppendResult(interp, "seek error on \"", path, "\"", - (char *) NULL); - Tcl_Close(interp, in); - return TCL_ERROR; + Tcl_AppendResult(interp, "seek error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; } pos[0] = Tcl_Tell(out); 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) { -wrerr: - Tcl_AppendResult(interp, "write error", (char *) NULL); - Tcl_Close(interp, in); - return TCL_ERROR; + wrerr: + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; } if ((len + pos[0]) & 3) { - unsigned char abuf[8]; - - /* - * Align payload to next 4-byte boundary using a dummy extra - * entry similar to the zipalign tool from Android's SDK. - */ - align = 4 + ((len + pos[0]) & 3); - zip_write_short(abuf, 0xffff); - zip_write_short(abuf + 2, align - 4); - zip_write_int(abuf + 4, 0x03020100); - if ((size_t)Tcl_Write(out, (const char *)abuf, align) != align) { - goto wrerr; - } + unsigned char abuf[8]; + + /* + * Align payload to next 4-byte boundary using a dummy extra entry + * similar to the zipalign tool from Android's SDK. + */ + + align = 4 + ((len + pos[0]) & 3); + zip_write_short(abuf, 0xffff); + zip_write_short(abuf + 2, align - 4); + zip_write_int(abuf + 4, 0x03020100); + if ((size_t) Tcl_Write(out, (const char *) abuf, align) != align) { + goto wrerr; + } } if (passwd != NULL) { - 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); - Tcl_Close(interp, in); - return TCL_ERROR; - } - ret = Tcl_GetObjResult(interp); - if (Tcl_GetIntFromObj(interp, ret, &ch) != TCL_OK) { - Tcl_Close(interp, in); - return TCL_ERROR; - } - 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, 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_Close(interp, in); - return TCL_ERROR; - } - memcpy(keys0, keys, sizeof (keys0)); - nbytecompr += 12; + 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); + Tcl_Close(interp, in); + return TCL_ERROR; + } + ret = Tcl_GetObjResult(interp); + if (Tcl_GetIntFromObj(interp, ret, &ch) != TCL_OK) { + Tcl_Close(interp, in); + return TCL_ERROR; + } + 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, 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_Close(interp, in); + return TCL_ERROR; + } + memcpy(keys0, keys, sizeof (keys0)); + nbytecompr += 12; } Tcl_Flush(out); pos[2] = Tcl_Tell(out); @@ -2052,100 +2120,100 @@ wrerr: 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_Close(interp, in); - return TCL_ERROR; + if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8, + Z_DEFAULT_STRATEGY) != Z_OK) { + Tcl_AppendResult(interp, "compression init error on \"", path, "\"", + (char *) NULL); + 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); - deflateEnd(&stream); - Tcl_Close(interp, in); - return TCL_ERROR; - } - stream.avail_in = len; - stream.next_in = (unsigned char *) buf; - flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH; - do { - 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); - deflateEnd(&stream); - Tcl_Close(interp, in); - return TCL_ERROR; - } - olen = sizeof (obuf) - stream.avail_out; - if (passwd != NULL) { - size_t i; - int tmp; - - for (i = 0; i < olen; i++) { - 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); - deflateEnd(&stream); - Tcl_Close(interp, in); - return TCL_ERROR; - } - nbytecompr += olen; - } while (stream.avail_out == 0); + len = Tcl_Read(in, buf, bufsize); + if (len == (size_t)-1) { + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + stream.avail_in = len; + stream.next_in = (unsigned char *) buf; + flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH; + do { + 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); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + olen = sizeof (obuf) - stream.avail_out; + if (passwd != NULL) { + size_t i; + int tmp; + + for (i = 0; i < olen; i++) { + 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); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + nbytecompr += olen; + } while (stream.avail_out == 0); } while (flush != Z_FINISH); deflateEnd(&stream); Tcl_Flush(out); pos[1] = Tcl_Tell(out); if (nbyte - nbytecompr <= 0) { - /* - * Compressed file larger than input, - * write it again uncompressed. - */ - if (Tcl_Seek(in, 0, SEEK_SET) != 0) { - goto seekErr; - } - if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { -seekErr: - Tcl_Close(interp, in); - Tcl_AppendResult(interp, "seek error", (char *) NULL); - return TCL_ERROR; - } - nbytecompr = (passwd != NULL) ? 12 : 0; - while (1) { - len = Tcl_Read(in, buf, bufsize); - if (len == (size_t)-1) { - Tcl_AppendResult(interp, "read error on \"", path, "\"", - (char *) NULL); - Tcl_Close(interp, in); - return TCL_ERROR; - } else if (len == 0) { - break; - } - if (passwd != NULL) { - size_t i; - int tmp; - - for (i = 0; i < len; i++) { - 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); - Tcl_Close(interp, in); - return TCL_ERROR; - } - nbytecompr += len; - } - cmeth = ZIP_COMPMETH_STORED; - Tcl_Flush(out); - pos[1] = Tcl_Tell(out); - Tcl_TruncateChannel(out, pos[1]); + /* + * Compressed file larger than input, write it again uncompressed. + */ + if (Tcl_Seek(in, 0, SEEK_SET) != 0) { + goto seekErr; + } + if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { + seekErr: + Tcl_Close(interp, in); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + return TCL_ERROR; + } + nbytecompr = (passwd != NULL) ? 12 : 0; + while (1) { + len = Tcl_Read(in, buf, bufsize); + if (len == (size_t)-1) { + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } else if (len == 0) { + break; + } + if (passwd != NULL) { + size_t i; + int tmp; + + for (i = 0; i < len; i++) { + 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); + Tcl_Close(interp, in); + return TCL_ERROR; + } + nbytecompr += len; + } + cmeth = ZIP_COMPMETH_STORED; + Tcl_Flush(out); + pos[1] = Tcl_Tell(out); + Tcl_TruncateChannel(out, pos[1]); } Tcl_Close(interp, in); @@ -2165,14 +2233,14 @@ seekErr: 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); - return TCL_ERROR; + Tcl_AppendResult(interp, "non-unique path name \"", path, "\"", + (char *) NULL); + Tcl_Free((char *) z); + return TCL_ERROR; } else { - Tcl_SetHashValue(hPtr, (ClientData) z); - z->name = Tcl_GetHashKey(fileHash, hPtr); - z->next = NULL; + Tcl_SetHashValue(hPtr, (ClientData) z); + z->name = Tcl_GetHashKey(fileHash, hPtr); + z->next = NULL; } /* @@ -2190,23 +2258,23 @@ seekErr: zip_write_short(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen); zip_write_short(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); - return TCL_ERROR; + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + 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); - return TCL_ERROR; + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "write error", (char *) NULL); + 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); - return TCL_ERROR; + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + return TCL_ERROR; } return TCL_OK; } @@ -2216,23 +2284,28 @@ seekErr: * * ZipFSMkZipOrImgObjCmd -- * - * This procedure is creates a new ZIP archive file or image file - * given output filename, input directory of files to be archived, - * optional password, and optional image to be prepended to the - * output ZIP archive file. + * This procedure is creates a new ZIP archive file or image file given + * output filename, input directory of files to be archived, optional + * password, and optional image to be prepended to the output ZIP archive + * file. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * A new ZIP archive file or image file is written. + * A new ZIP archive file or image file is written. * *------------------------------------------------------------------------- */ static int -ZipFSMkZipOrImgObjCmd(ClientData clientData, Tcl_Interp *interp, - int isImg, int isList, int objc, Tcl_Obj *const objv[]) +ZipFSMkZipOrImgObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int isImg, + int isList, + int objc, + Tcl_Obj *const objv[]) { Tcl_Channel out; int pwlen = 0, count, ret = TCL_ERROR, lobjc; @@ -2246,300 +2319,297 @@ ZipFSMkZipOrImgObjCmd(ClientData clientData, Tcl_Interp *interp, char *strip = NULL, *pw = NULL, pwbuf[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; - } + 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; - } + 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; if (objc > (isList ? 3 : 4)) { - pw = Tcl_GetString(objv[isList ? 3 : 4]); - pwlen = strlen(pw); - if ((pwlen > 255) || (strchr(pw, 0xff) != NULL)) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - return TCL_ERROR; - } + pw = Tcl_GetString(objv[isList ? 3 : 4]); + pwlen = strlen(pw); + if ((pwlen > 255) || (strchr(pw, 0xff) != NULL)) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); + return TCL_ERROR; + } } if (isList) { - list = objv[2]; - Tcl_IncrRefCount(list); + list = objv[2]; + Tcl_IncrRefCount(list); } else { - Tcl_Obj *cmd[3]; - - cmd[1] = Tcl_NewStringObj("::tcl::zipfs::find", -1); - cmd[2] = objv[2]; - cmd[0] = Tcl_NewListObj(2, cmd + 1); - Tcl_IncrRefCount(cmd[0]); - if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) { - Tcl_DecrRefCount(cmd[0]); - return TCL_ERROR; - } - Tcl_DecrRefCount(cmd[0]); - list = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(list); + Tcl_Obj *cmd[3]; + + cmd[1] = Tcl_NewStringObj("::tcl::zipfs::find", -1); + cmd[2] = objv[2]; + cmd[0] = Tcl_NewListObj(2, cmd + 1); + Tcl_IncrRefCount(cmd[0]); + if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) { + Tcl_DecrRefCount(cmd[0]); + return TCL_ERROR; + } + Tcl_DecrRefCount(cmd[0]); + list = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(list); } if (Tcl_ListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) { - Tcl_DecrRefCount(list); - return TCL_ERROR; + Tcl_DecrRefCount(list); + return TCL_ERROR; } if (isList && (lobjc % 2)) { - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, - Tcl_NewStringObj("need even number of elements", -1)); - return TCL_ERROR; + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, + Tcl_NewStringObj("need even number of elements", -1)); + return TCL_ERROR; } if (lobjc == 0) { - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1)); - return TCL_ERROR; + Tcl_DecrRefCount(list); + 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) - || (Tcl_SetChannelOption(interp, out, "-encoding", "binary") != TCL_OK) - ) { - Tcl_DecrRefCount(list); - Tcl_Close(interp, out); - return TCL_ERROR; + if ((out == NULL) || (Tcl_SetChannelOption(interp, out, + "-translation", "binary") != TCL_OK)) { + Tcl_DecrRefCount(list); + Tcl_Close(interp, out); + return TCL_ERROR; } if (pwlen <= 0) { - pw = NULL; - pwlen = 0; + pw = NULL; + pwlen = 0; } if (isImg) { - ZipFile *zf, zf0; - int isMounted = 0; - const char *imgName; - - if (isList) { - imgName = (objc > 4) ? Tcl_GetString(objv[4]) : Tcl_GetNameOfExecutable(); - } else { - imgName = (objc > 5) ? Tcl_GetString(objv[5]) : Tcl_GetNameOfExecutable(); - } - if (pwlen) { - i = 0; - len = pwlen; - while (len > 0) { - int ch = pw[len - 1]; - - pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; - i++; - len--; - } - pwbuf[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'; - } - /* 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; - } - } - hPtr = Tcl_NextHashEntry(&search); - } - Unlock(); - if (!isMounted) { - zf = &zf0; - } - 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)); - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); - Tcl_Close(interp, out); - if (zf == &zf0) { - ZipFSCloseArchive(interp, zf); - } else { - WriteLock(); - zf->nopen--; - Unlock(); - } - return TCL_ERROR; - } - if (zf == &zf0) { - ZipFSCloseArchive(interp, zf); - } else { - WriteLock(); - zf->nopen--; - Unlock(); - } - } else { - size_t k; - int m, n; - Tcl_Channel in; - const char *errMsg = "seek error"; - - /* - * Fall back to read it as plain file which - * hopefully is a static tclsh or wish binary - * with proper zipfs infrastructure built in. - */ - Tcl_ResetResult(interp); - in = Tcl_OpenFileChannel(interp, imgName, "r", 0644); - if (in == NULL) { - memset(pwbuf, 0, sizeof (pwbuf)); - Tcl_DecrRefCount(list); - Tcl_Close(interp, out); - return TCL_ERROR; - } - Tcl_SetChannelOption(interp, in, "-translation", "binary"); - Tcl_SetChannelOption(interp, in, "-encoding", "binary"); - i = Tcl_Seek(in, 0, SEEK_END); - if (i == (size_t)-1) { -cperr: - memset(pwbuf, 0, sizeof (pwbuf)); - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1)); - Tcl_Close(interp, out); - Tcl_Close(interp, in); - return TCL_ERROR; - } - Tcl_Seek(in, 0, SEEK_SET); - k = 0; - while (k < i) { - m = i - k; - if (m > (int)sizeof (buf)) { - m = (int)sizeof (buf); - } - n = Tcl_Read(in, buf, m); - if (n == -1) { - errMsg = "read error"; - goto cperr; - } else if (n == 0) { - break; - } - m = Tcl_Write(out, buf, n); - if (m != n) { - errMsg = "write error"; - goto cperr; - } - k += m; - } - Tcl_Close(interp, in); - } - len = strlen(pwbuf); - if (len > 0) { - i = Tcl_Write(out, pwbuf, len); - if (i != len) { - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); - Tcl_Close(interp, out); - return TCL_ERROR; - } - } - memset(pwbuf, 0, sizeof (pwbuf)); - Tcl_Flush(out); + ZipFile *zf, zf0; + int isMounted = 0; + const char *imgName; + + if (isList) { + imgName = (objc > 4) ? Tcl_GetString(objv[4]) : + Tcl_GetNameOfExecutable(); + } else { + imgName = (objc > 5) ? Tcl_GetString(objv[5]) : + Tcl_GetNameOfExecutable(); + } + if (pwlen) { + i = 0; + len = pwlen; + while (len > 0) { + int ch = pw[len - 1]; + + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + i++; + len--; + } + pwbuf[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'; + } + /* 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; + } + } + hPtr = Tcl_NextHashEntry(&search); + } + Unlock(); + if (!isMounted) { + zf = &zf0; + } + 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)); + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); + Tcl_Close(interp, out); + if (zf == &zf0) { + ZipFSCloseArchive(interp, zf); + } else { + WriteLock(); + zf->nopen--; + Unlock(); + } + return TCL_ERROR; + } + if (zf == &zf0) { + ZipFSCloseArchive(interp, zf); + } else { + WriteLock(); + zf->nopen--; + Unlock(); + } + } else { + size_t k; + int m, n; + Tcl_Channel in; + const char *errMsg = "seek error"; + + /* + * Fall back to read it as plain file which hopefully is a static + * tclsh or wish binary with proper zipfs infrastructure built in. + */ + + Tcl_ResetResult(interp); + in = Tcl_OpenFileChannel(interp, imgName, "r", 0644); + if (in == NULL) { + memset(pwbuf, 0, sizeof (pwbuf)); + 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) { + cperr: + memset(pwbuf, 0, sizeof (pwbuf)); + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1)); + Tcl_Close(interp, out); + Tcl_Close(interp, in); + return TCL_ERROR; + } + Tcl_Seek(in, 0, SEEK_SET); + k = 0; + while (k < i) { + m = i - k; + if (m > (int)sizeof (buf)) { + m = (int)sizeof (buf); + } + n = Tcl_Read(in, buf, m); + if (n == -1) { + errMsg = "read error"; + goto cperr; + } else if (n == 0) { + break; + } + m = Tcl_Write(out, buf, n); + if (m != n) { + errMsg = "write error"; + goto cperr; + } + k += m; + } + Tcl_Close(interp, in); + } + len = strlen(pwbuf); + if (len > 0) { + i = Tcl_Write(out, pwbuf, len); + if (i != len) { + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); + Tcl_Close(interp, out); + return TCL_ERROR; + } + } + memset(pwbuf, 0, sizeof (pwbuf)); + Tcl_Flush(out); } Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS); pos[0] = Tcl_Tell(out); if (!isList && (objc > 3)) { - strip = Tcl_GetString(objv[3]); - slen = strlen(strip); + strip = Tcl_GetString(objv[3]); + slen = strlen(strip); } for (i = 0; i < (size_t)lobjc; i += (isList ? 2 : 1)) { - const char *path, *name; - - path = Tcl_GetString(lobjv[i]); - if (isList) { - name = Tcl_GetString(lobjv[i + 1]); - } else { - name = path; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { - continue; - } - name += slen; - } - } - while (name[0] == '/') { - ++name; - } - if (name[0] == '\0') { - continue; - } - if (ZipAddFile(interp, path, name, out, pw, buf, sizeof (buf), - &fileHash) != TCL_OK) { - goto done; - } + const char *path, *name; + + path = Tcl_GetString(lobjv[i]); + if (isList) { + name = Tcl_GetString(lobjv[i + 1]); + } else { + name = path; + if (slen > 0) { + len = strlen(name); + if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { + continue; + } + name += slen; + } + } + while (name[0] == '/') { + ++name; + } + if (name[0] == '\0') { + continue; + } + 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)) { - const char *path, *name; - - path = Tcl_GetString(lobjv[i]); - if (isList) { - name = Tcl_GetString(lobjv[i + 1]); - } else { - name = path; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { - continue; - } - name += slen; - } - } - while (name[0] == '/') { - ++name; - } - if (name[0] == '\0') { - continue; - } - hPtr = Tcl_FindHashEntry(&fileHash, name); - if (hPtr == NULL) { - continue; - } - z = (ZipEntry *) 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]); - 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)); - goto done; - } - count++; + const char *path, *name; + + path = Tcl_GetString(lobjv[i]); + if (isList) { + name = Tcl_GetString(lobjv[i + 1]); + } else { + name = path; + if (slen > 0) { + len = strlen(name); + if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { + continue; + } + name += slen; + } + } + while (name[0] == '/') { + ++name; + } + if (name[0] == '\0') { + continue; + } + hPtr = Tcl_FindHashEntry(&fileHash, name); + if (hPtr == NULL) { + 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]); + 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)); + goto done; + } + count++; } Tcl_Flush(out); pos[2] = Tcl_Tell(out); @@ -2552,24 +2622,24 @@ cperr: zip_write_int(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]); zip_write_short(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)); - goto done; + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); + goto done; } Tcl_Flush(out); ret = TCL_OK; -done: + done: if (ret == TCL_OK) { - ret = Tcl_Close(interp, out); + ret = Tcl_Close(interp, out); } else { - Tcl_Close(interp, out); + Tcl_Close(interp, out); } Tcl_DecrRefCount(list); hPtr = Tcl_FirstHashEntry(&fileHash, &search); while (hPtr != NULL) { - z = (ZipEntry *) Tcl_GetHashValue(hPtr); - Tcl_Free((char *) z); - Tcl_DeleteHashEntry(hPtr); - hPtr = Tcl_NextHashEntry(&search); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); + Tcl_Free((char *) z); + Tcl_DeleteHashEntry(hPtr); + hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&fileHash); return ret; @@ -2580,29 +2650,35 @@ done: * * ZipFSMkZipObjCmd -- * - * This procedure is invoked to process the "zipfs::mkzip" command. - * See description of ZipFSMkZipOrImgCmd(). + * This procedure is invoked to process the "zipfs::mkzip" command. See + * description of ZipFSMkZipOrImgCmd(). * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImgCmd(). * *------------------------------------------------------------------------- */ static int ZipFSMkZipObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 0, objc, objv); } static int ZipFSLMkZipObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 1, objc, objv); } @@ -2611,28 +2687,34 @@ ZipFSLMkZipObjCmd( * * ZipFSZipFSOpenArchiveObjCmd -- * - * This procedure is invoked to process the "zipfs::mkimg" command. - * See description of ZipFSMkZipOrImgCmd(). + * This procedure is invoked to process the "zipfs::mkimg" command. See + * description of ZipFSMkZipOrImgCmd(). * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImgCmd(). * *------------------------------------------------------------------------- */ static int -ZipFSMkImgObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) +ZipFSMkImgObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) { return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 0, objc, objv); } static int -ZipFSLMkImgObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) +ZipFSLMkImgObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) { return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 1, objc, objv); } @@ -2642,87 +2724,97 @@ ZipFSLMkImgObjCmd(ClientData clientData, Tcl_Interp *interp, * * ZipFSCanonicalObjCmd -- * - * This procedure is invoked to process the "zipfs::canonical" command. - * It returns the canonical name for a file within zipfs + * This procedure is invoked to process the "zipfs::canonical" command. + * It returns the canonical name for a file within zipfs * * Results: - * Always TCL_OK. + * Always TCL_OK provided the right number of arguments are supplied. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipFSCanonicalObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[] ) { - char *mntpoint=NULL; - char *filename=NULL; + char *mntpoint = NULL; + char *filename = NULL; char *result; Tcl_DString dPath; - if (objc != 2 && objc != 3 && objc!=4) { - Tcl_WrongNumArgs(interp, 1, objv, "?mntpnt? filename ?ZIPFS?"); - return TCL_ERROR; + if (objc != 2 && objc != 3 && objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "?mntpnt? filename ?ZIPFS?"); + return TCL_ERROR; } Tcl_DStringInit(&dPath); - if(objc==2) { - filename = Tcl_GetString(objv[1]); - result=CanonicalPath("",filename,&dPath,1); - } else if (objc==3) { - mntpoint = Tcl_GetString(objv[1]); - filename = Tcl_GetString(objv[2]); - result=CanonicalPath(mntpoint,filename,&dPath,1); + if (objc == 2) { + filename = Tcl_GetString(objv[1]); + result = CanonicalPath("", filename, &dPath, 1); + } else if (objc == 3) { + mntpoint = Tcl_GetString(objv[1]); + filename = Tcl_GetString(objv[2]); + result = CanonicalPath(mntpoint, filename, &dPath, 1); } else { - int zipfs=0; - if(Tcl_GetBooleanFromObj(interp,objv[3],&zipfs)) { - return TCL_ERROR; - } - mntpoint = Tcl_GetString(objv[1]); - filename = Tcl_GetString(objv[2]); - result=CanonicalPath(mntpoint,filename,&dPath,zipfs); - } - Tcl_SetObjResult(interp,Tcl_NewStringObj(result,-1)); + int zipfs = 0; + + if (Tcl_GetBooleanFromObj(interp, objv[3], &zipfs)) { + return TCL_ERROR; + } + mntpoint = Tcl_GetString(objv[1]); + filename = Tcl_GetString(objv[2]); + result = CanonicalPath(mntpoint, filename, &dPath, zipfs); + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); return TCL_OK; } - + /* *------------------------------------------------------------------------- * * ZipFSExistsObjCmd -- * - * This procedure is invoked to process the "zipfs::exists" command. - * It tests for the existence of a file in the ZIP filesystem and - * places a boolean into the interp's result. + * This procedure is invoked to process the "zipfs::exists" command. It + * tests for the existence of a file in the ZIP filesystem and places a + * boolean into the interp's result. * * Results: - * Always TCL_OK. + * Always TCL_OK provided the right number of arguments are supplied. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipFSExistsObjCmd( - ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ char *filename; int exists; Tcl_DString ds; if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "filename"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "filename"); + return TCL_ERROR; } - /* prepend ZIPFS_VOLUME to filename, eliding the final / */ + /* + * Prepend ZIPFS_VOLUME to filename, eliding the final / + */ + filename = Tcl_GetStringFromObj(objv[1], 0); Tcl_DStringInit(&ds); - Tcl_DStringAppend(&ds, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN-1); + Tcl_DStringAppend(&ds, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN - 1); Tcl_DStringAppend(&ds, filename, -1); filename = Tcl_DStringValue(&ds); @@ -2730,7 +2822,7 @@ ZipFSExistsObjCmd( exists = ZipFSLookup(filename) != NULL; Unlock(); - Tcl_SetObjResult(interp,Tcl_NewBooleanObj(exists)); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists)); return TCL_OK; } @@ -2739,42 +2831,46 @@ ZipFSExistsObjCmd( * * ZipFSInfoObjCmd -- * - * This procedure is invoked to process the "zipfs::info" command. - * On success, it returns a Tcl list made up of name of ZIP archive - * file, size uncompressed, size compressed, and archive offset of - * a file in the ZIP filesystem. + * This procedure is invoked to process the "zipfs::info" command. On + * success, it returns a Tcl list made up of name of ZIP archive file, + * size uncompressed, size compressed, and archive offset of a file in + * the ZIP filesystem. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipFSInfoObjCmd( - ClientData clientData, Tcl_Interp *interp,int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ char *filename; ZipEntry *z; if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "filename"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "filename"); + return TCL_ERROR; } filename = Tcl_GetStringFromObj(objv[1], 0); ReadLock(); z = ZipFSLookup(filename); if (z != NULL) { - Tcl_Obj *result = Tcl_GetObjResult(interp); + 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_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->nbytecompr)); - Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset)); + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->zipfile->name, -1)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->nbyte)); + Tcl_ListObjAppendElement(interp, result, + Tcl_NewWideIntObj(z->nbytecompr)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset)); } Unlock(); return TCL_OK; @@ -2785,23 +2881,26 @@ ZipFSInfoObjCmd( * * ZipFSListObjCmd -- * - * This procedure is invoked to process the "zipfs::list" command. - * On success, it returns a Tcl list of files of the ZIP filesystem - * which match a search pattern (glob or regexp). + * This procedure is invoked to process the "zipfs::list" command. On + * success, it returns a Tcl list of files of the ZIP filesystem which + * match a search pattern (glob or regexp). * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipFSListObjCmd( - ClientData clientData, Tcl_Interp *interp,int objc, Tcl_Obj *const objv[] -) { + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ char *pattern = NULL; Tcl_RegExp regexp = NULL; Tcl_HashEntry *hPtr; @@ -2809,68 +2908,64 @@ ZipFSListObjCmd( Tcl_Obj *result = Tcl_GetObjResult(interp); if (objc > 3) { - Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?"); + return TCL_ERROR; } if (objc == 3) { - int n; - char *what = Tcl_GetStringFromObj(objv[1], &n); - - if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) { - 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) { - return TCL_ERROR; - } - } else { - Tcl_AppendResult(interp, "unknown option \"", what,"\"", (char *) NULL); - return TCL_ERROR; - } + int n; + char *what = Tcl_GetStringFromObj(objv[1], &n); + + if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) { + 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) { + return TCL_ERROR; + } + } else { + Tcl_AppendResult(interp, "unknown option \"", what, "\"", + (char *) NULL); + return TCL_ERROR; + } } else if (objc == 2) { - pattern = Tcl_GetStringFromObj(objv[1], 0); + pattern = Tcl_GetStringFromObj(objv[1], 0); } ReadLock(); if (pattern != NULL) { - for ( - hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search) - ) { - ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); - - if (Tcl_StringMatch(z->name, pattern)) { - Tcl_ListObjAppendElement(interp, result,Tcl_NewStringObj(z->name, -1)); - } - } + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = Tcl_GetHashValue(hPtr); + + if (Tcl_StringMatch(z->name, pattern)) { + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } + } } else if (regexp != NULL) { - for ( - hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search) - ) { - ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); - if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { - Tcl_ListObjAppendElement(interp, result,Tcl_NewStringObj(z->name, -1)); - } - } + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = Tcl_GetHashValue(hPtr); + + if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } + } } else { - for ( - hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search) - ) { - ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = Tcl_GetHashValue(hPtr); - Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); - } + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } } Unlock(); return TCL_OK; } - + #ifdef _WIN32 -#define LIBRARY_SIZE 64 +#define LIBRARY_SIZE 64 static int ToUtf( const WCHAR *wSrc, @@ -2880,82 +2975,97 @@ ToUtf( start = dst; while (*wSrc != '\0') { - dst += Tcl_UniCharToUtf(*wSrc, dst); - wSrc++; + dst += Tcl_UniCharToUtf(*wSrc, dst); + wSrc++; } *dst = '\0'; return (int) (dst - start); } #endif -Tcl_Obj *TclZipfs_TclLibrary(void) { - if(zipfs_literal_tcl_library) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); +Tcl_Obj * +TclZipfs_TclLibrary(void) +{ + if (zipfs_literal_tcl_library) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); } else { - Tcl_Obj *vfsinitscript; - int found=0; + Tcl_Obj *vfsinitscript; + int found = 0; #ifdef _WIN32 - HMODULE hModule = TclWinGetTclInstance(); - WCHAR wName[MAX_PATH + LIBRARY_SIZE]; - char dllname[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX]; -#endif - /* Look for the library file system within the executable */ - vfsinitscript=Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",-1); - 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_NewStringObj(zipfs_literal_tcl_library,-1); - } + HMODULE hModule = TclWinGetTclInstance(); + WCHAR wName[MAX_PATH + LIBRARY_SIZE]; + char dllname[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX]; +#endif /* _WIN32 */ + /* + * Look for the library file system within the executable. + */ + + vfsinitscript = Tcl_NewStringObj( + ZIPFS_APP_MOUNT "/tcl_library/init.tcl", -1); + 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_NewStringObj(zipfs_literal_tcl_library, -1); + } + #ifdef _WIN32 - if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) { - GetModuleFileNameA(hModule, dllname, MAX_PATH); - } else { - ToUtf(wName, dllname); - } - /* Mount zip file and dll before releasing to search */ - if(TclZipfs_AppHook_FindTclInit(dllname)==TCL_OK) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); - } -#else + if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) { + GetModuleFileNameA(hModule, dllname, MAX_PATH); + } else { + ToUtf(wName, dllname); + } + + /* + * Mount zip file and dll before releasing to search. + */ + + if (TclZipfs_AppHook_FindTclInit(dllname) == TCL_OK) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + } +#else /* !_WIN32 */ #ifdef CFG_RUNTIME_DLLFILE - /* Mount zip file and dll before releasing to search */ - if(TclZipfs_AppHook_FindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE)==TCL_OK) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); - } -#endif -#endif -#ifdef CFG_RUNTIME_ZIPFILE - if(TclZipfs_AppHook_FindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_ZIPFILE)==TCL_OK) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); - } - if(TclZipfs_AppHook_FindTclInit(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) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); - } -#else + /* + * Mount zip file and dll before releasing to search. + */ + if (TclZipfs_AppHook_FindTclInit( + CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + } +#endif /* CFG_RUNTIME_DLLFILE */ +#endif /* _WIN32 */ -#endif - } - if(zipfs_literal_tcl_library) { - return Tcl_NewStringObj(zipfs_literal_tcl_library,-1); +#ifdef CFG_RUNTIME_ZIPFILE + if (TclZipfs_AppHook_FindTclInit( + CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + } + if (TclZipfs_AppHook_FindTclInit( + 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) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + } +#endif /* CFG_RUNTIME_ZIPFILE */ + } + if (zipfs_literal_tcl_library) { + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); } return NULL; } - + /* *------------------------------------------------------------------------- * * 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::root" command. It + * returns the root that all zipfs file systems are mounted under. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: * @@ -2963,16 +3073,18 @@ Tcl_Obj *TclZipfs_TclLibrary(void) { */ static int -ZipFSTclLibraryObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) +ZipFSTclLibraryObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) { - Tcl_Obj *pResult; + Tcl_Obj *pResult = TclZipfs_TclLibrary(); - pResult=TclZipfs_TclLibrary(); - if(!pResult) { - pResult=Tcl_NewObj(); + if (!pResult) { + pResult = Tcl_NewObj(); } - Tcl_SetObjResult(interp,pResult); + Tcl_SetObjResult(interp, pResult); return TCL_OK; } @@ -2981,50 +3093,53 @@ ZipFSTclLibraryObjCmd(ClientData clientData, Tcl_Interp *interp, * * ZipChannelClose -- * - * This function is called to close a channel. + * This function is called to close a channel. * * Results: - * Always TCL_OK. + * Always TCL_OK. * * Side effects: - * Resources are free'd. + * Resources are free'd. * *------------------------------------------------------------------------- */ static int -ZipChannelClose(ClientData instanceData, Tcl_Interp *interp) +ZipChannelClose( + ClientData instanceData, + Tcl_Interp *interp) { ZipChannel *info = (ZipChannel *) instanceData; if (info->iscompr && (info->ubuf != NULL)) { - Tcl_Free((char *) info->ubuf); - info->ubuf = NULL; + Tcl_Free((char *) info->ubuf); + info->ubuf = NULL; } if (info->isenc) { - info->isenc = 0; - memset(info->keys, 0, sizeof (info->keys)); + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); } if (info->iswr) { - ZipEntry *z = info->zipentry; - unsigned char *newdata; - - newdata = (unsigned char *) Tcl_AttemptRealloc((char *) info->ubuf, info->nread); - if (newdata != NULL) { - if (z->data != NULL) { - Tcl_Free((char *) z->data); - } - z->data = newdata; - z->nbyte = z->nbytecompr = info->nbyte; - z->cmeth = ZIP_COMPMETH_STORED; - z->timestamp = time(NULL); - z->isdir = 0; - z->isenc = 0; - z->offset = 0; - z->crc32 = 0; - } else { - Tcl_Free((char *) info->ubuf); - } + ZipEntry *z = info->zipentry; + unsigned char *newdata; + + newdata = (unsigned char *) + Tcl_AttemptRealloc((char *) info->ubuf, info->nread); + if (newdata != NULL) { + if (z->data != NULL) { + Tcl_Free((char *) z->data); + } + z->data = newdata; + z->nbyte = z->nbytecompr = info->nbyte; + z->cmeth = ZIP_COMPMETH_STORED; + z->timestamp = time(NULL); + z->isdir = 0; + z->isenc = 0; + z->offset = 0; + z->crc32 = 0; + } else { + Tcl_Free((char *) info->ubuf); + } } WriteLock(); info->zipfile->nopen--; @@ -3038,62 +3153,66 @@ ZipChannelClose(ClientData instanceData, Tcl_Interp *interp) * * 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. * *------------------------------------------------------------------------- */ static int -ZipChannelRead(ClientData instanceData, char *buf, int toRead, int *errloc) +ZipChannelRead( + ClientData instanceData, + char *buf, + int toRead, + int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; unsigned long nextpos; if (info->isdir < 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; - } - if (toRead == 0) { - return 0; - } - memcpy(buf, info->zipfile->data, toRead); - info->nread = nextpos; - *errloc = 0; - return toRead; + /* + * 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; + } + if (toRead == 0) { + return 0; + } + memcpy(buf, info->zipfile->data, toRead); + info->nread = nextpos; + *errloc = 0; + return toRead; } if (info->isdir) { - *errloc = EISDIR; - return -1; + *errloc = EISDIR; + return -1; } nextpos = info->nread + toRead; if (nextpos > info->nbyte) { - toRead = info->nbyte - info->nread; - nextpos = info->nbyte; + toRead = info->nbyte - info->nread; + nextpos = info->nbyte; } if (toRead == 0) { - return 0; + return 0; } if (info->isenc) { - int i, ch; + int i, ch; - for (i = 0; i < toRead; i++) { - ch = info->ubuf[i + info->nread]; - buf[i] = zdecode(info->keys, crc32tab, ch); - } + for (i = 0; i < toRead; i++) { + ch = info->ubuf[i + info->nread]; + buf[i] = zdecode(info->keys, crc32tab, ch); + } } else { - memcpy(buf, info->ubuf + info->nread, toRead); + memcpy(buf, info->ubuf + info->nread, toRead); } info->nread = nextpos; *errloc = 0; @@ -3105,40 +3224,43 @@ ZipChannelRead(ClientData instanceData, char *buf, int toRead, int *errloc) * * ZipChannelWrite -- * - * This function is called to write data into channel. + * This function is called to write data into channel. * * Results: - * Number of bytes written or -1 on error with error number set. + * Number of bytes written or -1 on error with error number set. * * Side effects: - * Data is written and file pointer is advanced. + * Data is written and file pointer is advanced. * *------------------------------------------------------------------------- */ static int -ZipChannelWrite(ClientData instanceData, const char *buf, - int toWrite, int *errloc) +ZipChannelWrite( + ClientData instanceData, + const char *buf, + int toWrite, + int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; unsigned long nextpos; if (!info->iswr) { - *errloc = EINVAL; - return -1; + *errloc = EINVAL; + return -1; } nextpos = info->nread + toWrite; if (nextpos > info->nmax) { - toWrite = info->nmax - info->nread; - nextpos = info->nmax; + toWrite = info->nmax - info->nread; + nextpos = info->nmax; } if (toWrite == 0) { - return 0; + return 0; } memcpy(info->ubuf + info->nread, buf, toWrite); info->nread = nextpos; if (info->nread > info->nbyte) { - info->nbyte = info->nread; + info->nbyte = info->nread; } *errloc = 0; return toWrite; @@ -3149,63 +3271,67 @@ ZipChannelWrite(ClientData instanceData, const char *buf, * * 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. * *------------------------------------------------------------------------- */ static int -ZipChannelSeek(ClientData instanceData, long offset, int mode, int *errloc) +ZipChannelSeek( + ClientData instanceData, + long offset, + int mode, + int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; unsigned long end; if (!info->iswr && (info->isdir < 0)) { - /* - * Special case: when executable combined with ZIP archive file, - * seek within front of ZIP, i.e. the executable itself. - */ - end = info->zipfile->baseoffs; + /* + * 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) { - *errloc = EINVAL; - return -1; + *errloc = EINVAL; + return -1; } else { - end = info->nbyte; + end = info->nbyte; } switch (mode) { case SEEK_CUR: - offset += info->nread; - break; + offset += info->nread; + break; case SEEK_END: - offset += end; - break; + offset += end; + break; case SEEK_SET: - break; + break; default: - *errloc = EINVAL; - return -1; + *errloc = EINVAL; + return -1; } if (offset < 0) { - *errloc = EINVAL; - return -1; + *errloc = EINVAL; + return -1; } if (info->iswr) { - if ((unsigned long) offset > info->nmax) { - *errloc = EINVAL; - return -1; - } - if ((unsigned long) offset > info->nbyte) { - info->nbyte = offset; - } + if ((unsigned long) offset > info->nmax) { + *errloc = EINVAL; + return -1; + } + if ((unsigned long) offset > info->nbyte) { + info->nbyte = offset; + } } else if ((unsigned long) offset > end) { - *errloc = EINVAL; - return -1; + *errloc = EINVAL; + return -1; } info->nread = (unsigned long) offset; return info->nread; @@ -3216,19 +3342,22 @@ ZipChannelSeek(ClientData instanceData, long offset, int mode, int *errloc) * * ZipChannelWatchChannel -- * - * This function is called for event notifications on channel. + * This function is called for event notifications on channel. Does + * nothing. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static void -ZipChannelWatchChannel(ClientData instanceData, int mask) +ZipChannelWatchChannel( + ClientData instanceData, + int mask) { return; } @@ -3238,57 +3367,59 @@ ZipChannelWatchChannel(ClientData instanceData, int mask) * * ZipChannelGetFile -- * - * This function is called to retrieve OS handle for channel. + * This function is called to retrieve OS handle for channel. * * Results: - * Always TCL_ERROR since there's never an OS handle for a - * file within a ZIP archive. + * Always TCL_ERROR since there's never an OS handle for a file within a + * ZIP archive. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int ZipChannelGetFile( - ClientData instanceData, int direction,ClientData *handlePtr -) { + ClientData instanceData, + int direction, + ClientData *handlePtr) +{ return TCL_ERROR; } - + /* * The channel type/driver definition used for ZIP archive members. */ static Tcl_ChannelType ZipChannelType = { - "zip", /* Type name. */ + "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 */ + 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 */ + 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 */ + 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 */ + ZipChannelGetFile, /* Get OS handle from the channel */ #endif }; @@ -3310,283 +3441,291 @@ static Tcl_ChannelType ZipChannelType = { */ static Tcl_Channel -ZipChannelOpen(Tcl_Interp *interp, char *filename, int mode, int permissions) +ZipChannelOpen( + Tcl_Interp *interp, + char *filename, + int mode, + int permissions) { ZipEntry *z; ZipChannel *info; int i, ch, trunc, wr, flags = 0; char cname[128]; - if ( - (mode & O_APPEND) - || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR))) - ) { - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported open mode", -1)); - } - return NULL; + if ((mode & O_APPEND) + || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("unsupported open mode", -1)); + } + return NULL; } WriteLock(); z = ZipFSLookup(filename); if (z == NULL) { - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("file not found", -1)); - Tcl_AppendResult(interp, " \"", filename, "\"", NULL); - } - goto error; + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("file not found", -1)); + Tcl_AppendResult(interp, " \"", filename, "\"", NULL); + } + 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)) { - ZIPFS_ERROR(interp,"unsupported compression method"); - goto error; + if ((z->cmeth != ZIP_COMPMETH_STORED) + && (z->cmeth != ZIP_COMPMETH_DEFLATED)) { + ZIPFS_ERROR(interp, "unsupported compression method"); + goto error; } if (wr && z->isdir) { - ZIPFS_ERROR(interp,"unsupported file type"); - goto error; + ZIPFS_ERROR(interp, "unsupported file type"); + goto error; } if (!trunc) { - flags |= TCL_READABLE; - if (z->isenc && (z->zipfile->pwbuf[0] == 0)) { - ZIPFS_ERROR(interp,"decryption failed"); - goto error; - } else if (wr && (z->data == NULL) && (z->nbyte > ZipFS.wrmax)) { - ZIPFS_ERROR(interp,"file too large"); - goto error; - } + flags |= TCL_READABLE; + if (z->isenc && (z->zipfile->pwbuf[0] == 0)) { + ZIPFS_ERROR(interp, "decryption failed"); + goto error; + } else if (wr && (z->data == NULL) && (z->nbyte > ZipFS.wrmax)) { + ZIPFS_ERROR(interp, "file too large"); + goto error; + } } else { - flags = TCL_WRITABLE; + flags = TCL_WRITABLE; } info = (ZipChannel *) Tcl_AttemptAlloc(sizeof (*info)); if (info == NULL) { - ZIPFS_ERROR(interp,"out of memory"); - goto error; + ZIPFS_ERROR(interp, "out of memory"); + goto error; } info->zipfile = z->zipfile; info->zipentry = z; info->nread = 0; if (wr) { - flags |= TCL_WRITABLE; - info->iswr = 1; - info->isdir = 0; - info->nmax = ZipFS.wrmax; - info->iscompr = 0; - info->isenc = 0; - info->ubuf = (unsigned char *) Tcl_AttemptAlloc(info->nmax); - if (info->ubuf == NULL) { -merror0: - if (info->ubuf != NULL) { - Tcl_Free((char *) info->ubuf); - } - Tcl_Free((char *) info); - ZIPFS_ERROR(interp,"out of memory"); - goto error; - } - memset(info->ubuf, 0, info->nmax); - if (trunc) { - info->nbyte = 0; - } else { - if (z->data != NULL) { - unsigned int j = z->nbyte; - - 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 (z->isenc) { - int len = z->zipfile->pwbuf[0]; - char pwbuf[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; - } - 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); - } - 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); - } - } else { - memcpy(info->ubuf, zbuf, z->nbyte); - } - memset(info->keys, 0, sizeof (info->keys)); - goto wrapchan; - } - } + flags |= TCL_WRITABLE; + info->iswr = 1; + info->isdir = 0; + info->nmax = ZipFS.wrmax; + info->iscompr = 0; + info->isenc = 0; + info->ubuf = (unsigned char *) Tcl_AttemptAlloc(info->nmax); + if (info->ubuf == NULL) { + merror0: + if (info->ubuf != NULL) { + Tcl_Free((char *) info->ubuf); + } + Tcl_Free((char *) info); + ZIPFS_ERROR(interp, "out of memory"); + goto error; + } + memset(info->ubuf, 0, info->nmax); + if (trunc) { + info->nbyte = 0; + } else { + if (z->data != NULL) { + unsigned int j = z->nbyte; + + 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 (z->isenc) { + int len = z->zipfile->pwbuf[0]; + char pwbuf[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; + } + 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); + } + 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); + } + } else { + memcpy(info->ubuf, zbuf, z->nbyte); + } + memset(info->keys, 0, sizeof (info->keys)); + goto wrapchan; + } + } } else if (z->data != NULL) { - flags |= TCL_READABLE; - info->iswr = 0; - info->iscompr = 0; - info->isdir = 0; - info->isenc = 0; - info->nbyte = z->nbyte; - info->nmax = 0; - info->ubuf = z->data; + flags |= TCL_READABLE; + info->iswr = 0; + info->iscompr = 0; + info->isdir = 0; + info->isenc = 0; + info->nbyte = z->nbyte; + info->nmax = 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]; - - 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); - } - info->ubuf += i; - } - if (info->iscompr) { - z_stream stream; - int err; - unsigned char *ubuf = NULL; - unsigned int j; - - memset(&stream, 0, sizeof (stream)); - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - stream.avail_in = z->nbytecompr; - if (info->isenc) { - stream.avail_in -= 12; - ubuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); - if (ubuf == NULL) { - info->ubuf = NULL; - goto merror; - } - for (j = 0; j < stream.avail_in; j++) { - ch = info->ubuf[j]; - ubuf[j] = zdecode(info->keys, crc32tab, ch); - } - stream.next_in = ubuf; - } else { - stream.next_in = info->ubuf; - } - stream.next_out = info->ubuf = (unsigned char *) Tcl_AttemptAlloc(info->nbyte); - if (info->ubuf == NULL) { -merror: - if (ubuf != NULL) { - info->isenc = 0; - memset(info->keys, 0, sizeof (info->keys)); - Tcl_Free((char *) ubuf); - } - Tcl_Free((char *) info); - if (interp != NULL) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("out of memory", -1)); - } - goto error; - } - stream.avail_out = info->nbyte; - if (inflateInit2(&stream, -15) != Z_OK) { - goto cerror; - } - err = inflate(&stream, Z_SYNC_FLUSH); - 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); - } - goto wrapchan; - } -cerror: - if (ubuf != NULL) { - info->isenc = 0; - memset(info->keys, 0, sizeof (info->keys)); - Tcl_Free((char *) ubuf); - } - if (info->ubuf != NULL) { - Tcl_Free((char *) info->ubuf); - } - Tcl_Free((char *) info); - ZIPFS_ERROR(interp,"decompression error"); - goto error; - } - } -wrapchan: - sprintf(cname, "zipfs_%" TCL_LL_MODIFIER "x_%d", z->offset, ZipFS.idCount++); + 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]; + + 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); + } + info->ubuf += i; + } + if (info->iscompr) { + z_stream stream; + int err; + unsigned char *ubuf = NULL; + unsigned int j; + + memset(&stream, 0, sizeof (stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = z->nbytecompr; + if (info->isenc) { + stream.avail_in -= 12; + ubuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); + if (ubuf == NULL) { + info->ubuf = NULL; + goto merror; + } + for (j = 0; j < stream.avail_in; j++) { + ch = info->ubuf[j]; + ubuf[j] = zdecode(info->keys, crc32tab, ch); + } + stream.next_in = ubuf; + } else { + stream.next_in = info->ubuf; + } + stream.next_out = info->ubuf = (unsigned char *) + Tcl_AttemptAlloc(info->nbyte); + if (info->ubuf == NULL) { + merror: + if (ubuf != NULL) { + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) ubuf); + } + Tcl_Free((char *) info); + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("out of memory", -1)); + } + goto error; + } + stream.avail_out = info->nbyte; + if (inflateInit2(&stream, -15) != Z_OK) { + goto cerror; + } + err = inflate(&stream, Z_SYNC_FLUSH); + 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); + } + goto wrapchan; + } + cerror: + if (ubuf != NULL) { + info->isenc = 0; + memset(info->keys, 0, sizeof(info->keys)); + Tcl_Free((char *) ubuf); + } + if (info->ubuf != NULL) { + Tcl_Free((char *) info->ubuf); + } + Tcl_Free((char *) info); + ZIPFS_ERROR(interp, "decompression error"); + goto error; + } + } + wrapchan: + sprintf(cname, "zipfs_%" TCL_LL_MODIFIER "x_%d", z->offset, + ZipFS.idCount++); z->zipfile->nopen++; Unlock(); return Tcl_CreateChannel(&ZipChannelType, cname, (ClientData) info, flags); -error: + error: Unlock(); return NULL; } @@ -3596,40 +3735,41 @@ error: * * ZipEntryStat -- * - * This function implements the ZIP filesystem specific version - * of the library version of stat. + * This function implements the ZIP filesystem specific version of the + * library version of stat. * * Results: - * See stat documentation. + * See stat documentation. * * Side effects: - * See stat documentation. + * See stat documentation. * *------------------------------------------------------------------------- */ static int -ZipEntryStat(char *path, Tcl_StatBuf *buf) +ZipEntryStat( + char *path, + Tcl_StatBuf *buf) { ZipEntry *z; int ret = -1; ReadLock(); z = ZipFSLookup(path); - if (z == NULL) goto done; - - memset(buf, 0, sizeof (Tcl_StatBuf)); - if (z->isdir) { - buf->st_mode = S_IFDIR | 0555; - } else { - buf->st_mode = S_IFREG | 0555; - } - buf->st_size = z->nbyte; - buf->st_mtime = z->timestamp; - buf->st_ctime = z->timestamp; - buf->st_atime = z->timestamp; - ret = 0; -done: + if (z != NULL) { + memset(buf, 0, sizeof (Tcl_StatBuf)); + if (z->isdir) { + buf->st_mode = S_IFDIR | 0555; + } else { + buf->st_mode = S_IFREG | 0555; + } + buf->st_size = z->nbyte; + buf->st_mtime = z->timestamp; + buf->st_ctime = z->timestamp; + buf->st_atime = z->timestamp; + ret = 0; + } Unlock(); return ret; } @@ -3639,24 +3779,28 @@ done: * * ZipEntryAccess -- * - * This function implements the ZIP filesystem specific version - * of the library version of access. + * This function implements the ZIP filesystem specific version of the + * library version of access. * * Results: - * See access documentation. + * See access documentation. * * Side effects: - * See access documentation. + * See access documentation. * *------------------------------------------------------------------------- */ static int -ZipEntryAccess(char *path, int mode) +ZipEntryAccess( + char *path, + int mode) { ZipEntry *z; - if (mode & 3) return -1; + if (mode & 3) { + return -1; + } ReadLock(); z = ZipFSLookup(path); Unlock(); @@ -3676,12 +3820,20 @@ ZipEntryAccess(char *path, int mode) */ static Tcl_Channel -Zip_FSOpenFileChannelProc(Tcl_Interp *interp, Tcl_Obj *pathPtr, - int mode, int permissions) +Zip_FSOpenFileChannelProc( + Tcl_Interp *interp, + Tcl_Obj *pathPtr, + int mode, + int permissions) { int len; - if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return NULL; - return ZipChannelOpen(interp, Tcl_GetStringFromObj(pathPtr, &len), mode, permissions); + + pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); + if (!pathPtr) { + return NULL; + } + return ZipChannelOpen(interp, Tcl_GetStringFromObj(pathPtr, &len), mode, + permissions); } /* @@ -3689,23 +3841,29 @@ Zip_FSOpenFileChannelProc(Tcl_Interp *interp, Tcl_Obj *pathPtr, * * Zip_FSStatProc -- * - * This function implements the ZIP filesystem specific version - * of the library version of stat. + * This function implements the ZIP filesystem specific version of the + * library version of stat. * * Results: - * See stat documentation. + * See stat documentation. * * Side effects: - * See stat documentation. + * See stat documentation. * *------------------------------------------------------------------------- */ static int -Zip_FSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) +Zip_FSStatProc( + Tcl_Obj *pathPtr, + Tcl_StatBuf *buf) { int len; - if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1; + + pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); + if (!pathPtr) { + return -1; + } return ZipEntryStat(Tcl_GetStringFromObj(pathPtr, &len), buf); } @@ -3714,23 +3872,29 @@ Zip_FSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) * * Zip_FSAccessProc -- * - * This function implements the ZIP filesystem specific version - * of the library version of access. + * This function implements the ZIP filesystem specific version of the + * library version of access. * * Results: - * See access documentation. + * See access documentation. * * Side effects: - * See access documentation. + * See access documentation. * *------------------------------------------------------------------------- */ static int -Zip_FSAccessProc(Tcl_Obj *pathPtr, int mode) +Zip_FSAccessProc( + Tcl_Obj *pathPtr, + int mode) { int len; - if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1; + + pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); + if (!pathPtr) { + return -1; + } return ZipEntryAccess(Tcl_GetStringFromObj(pathPtr, &len), mode); } @@ -3739,22 +3903,23 @@ Zip_FSAccessProc(Tcl_Obj *pathPtr, int mode) * * Zip_FSFilesystemSeparatorProc -- * - * This function returns the separator to be used for a given path. The - * object returned should have a refCount of zero + * This function returns the separator to be used for a given path. The + * object returned should have a refCount of zero * * Results: - * A Tcl object, with a refCount of zero. If the caller needs to retain a - * reference to the object, it should call Tcl_IncrRefCount, and should - * otherwise free the object. + * A Tcl object, with a refCount of zero. If the caller needs to retain a + * reference to the object, it should call Tcl_IncrRefCount, and should + * otherwise free the object. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static Tcl_Obj * -Zip_FSFilesystemSeparatorProc(Tcl_Obj *pathPtr) +Zip_FSFilesystemSeparatorProc( + Tcl_Obj *pathPtr) { return Tcl_NewStringObj("/", -1); } @@ -3764,23 +3929,26 @@ Zip_FSFilesystemSeparatorProc(Tcl_Obj *pathPtr) * * Zip_FSMatchInDirectoryProc -- * - * This routine is used by the globbing code to search a directory for - * all files which match a given pattern. + * This routine is used by the globbing code to search a directory for + * all files which match a given pattern. * * Results: - * The return value is a standard Tcl result indicating whether an - * error occurred in globbing. Errors are left in interp, good - * results are lappend'ed to resultPtr (which must be a valid object). + * The return value is a standard Tcl result indicating whether an error + * occurred in globbing. Errors are left in interp, good results are + * lappend'ed to resultPtr (which must be a valid object). * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result, - Tcl_Obj *pathPtr, const char *pattern, - Tcl_GlobTypeData *types) +Zip_FSMatchInDirectoryProc( + Tcl_Interp *interp, + Tcl_Obj *result, + Tcl_Obj *pathPtr, + const char *pattern, + Tcl_GlobTypeData *types) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -3790,10 +3958,12 @@ Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result, char *pat, *prefix, *path; Tcl_DString dsPref; - if (!(normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1; + if (!(normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) { + return -1; + } if (types != NULL) { - dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR; + dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR; } /* the prefix that gets prepended to results */ @@ -3807,138 +3977,130 @@ Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result, Tcl_DStringAppend(&dsPref, prefix, prefixLen); if (strcmp(prefix, path) == 0) { - prefix = NULL; + prefix = NULL; } else { - strip = len + 1; + strip = len + 1; } if (prefix != NULL) { - Tcl_DStringAppend(&dsPref, "/", 1); - prefixLen++; - prefix = Tcl_DStringValue(&dsPref); + Tcl_DStringAppend(&dsPref, "/", 1); + prefixLen++; + prefix = Tcl_DStringValue(&dsPref); } ReadLock(); if ((types != NULL) && (types->type == TCL_GLOB_TYPE_MOUNT)) { - l = CountSlashes(path); - if (path[len - 1] == '/') { - len--; - } else { - l++; - } - if ((pattern == NULL) || (pattern[0] == '\0')) { - pattern = "*"; - } - hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); - while (hPtr != NULL) { - ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); - - if (zf->mntptlen == 0) { - ZipEntry *z = zf->topents; - while (z != NULL) { - 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) { - Tcl_DStringAppend(&dsPref, z->name, lenz); - Tcl_ListObjAppendElement( - NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref)) - ); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, 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); - 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)); - } - } - hPtr = Tcl_NextHashEntry(&search); - } - goto end; + l = CountSlashes(path); + if (path[len - 1] == '/') { + len--; + } else { + l++; + } + if ((pattern == NULL) || (pattern[0] == '\0')) { + pattern = "*"; + } + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); + + if (zf->mntptlen == 0) { + ZipEntry *z = zf->topents; + while (z != NULL) { + 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) { + Tcl_DStringAppend(&dsPref, z->name, lenz); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + 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); + 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)); + } + } + hPtr = Tcl_NextHashEntry(&search); + } + goto end; } + if ((pattern == NULL) || (pattern[0] == '\0')) { - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); - if (hPtr != NULL) { - ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); - - if ((dirOnly < 0) || - (!dirOnly && !z->isdir) || - (dirOnly && z->isdir)) { - if (prefix != NULL) { - Tcl_DStringAppend(&dsPref, z->name, -1); - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref))); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(z->name, -1)); - } - } - } - goto end; + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); + if (hPtr != NULL) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + if ((dirOnly < 0) || (!dirOnly && !z->isdir) + || (dirOnly && z->isdir)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, z->name, -1); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(z->name, -1)); + } + } + } + goto end; } + l = strlen(pattern); pat = Tcl_Alloc(len + l + 2); memcpy(pat, path, len); while ((len > 1) && (pat[len - 1] == '/')) { - --len; + --len; } if ((len > 1) || (pat[0] != '/')) { - pat[len] = '/'; - ++len; + pat[len] = '/'; + ++len; } 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)) - ) { - continue; - } - if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) { - if (prefix != NULL) { - Tcl_DStringAppend(&dsPref, z->name + strip, -1); - Tcl_ListObjAppendElement( - NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref)) - ); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(z->name + strip, -1)); - } - } + 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))) { + continue; + } + if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, z->name + strip, -1); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(z->name + strip, -1)); + } + } } Tcl_Free(pat); -end: + + end: Unlock(); Tcl_DStringFree(&dsPref); return TCL_OK; @@ -3949,20 +4111,22 @@ end: * * Zip_FSPathInFilesystemProc -- * - * This function determines if the given path object is in the - * ZIP filesystem. + * This function determines if the given path object is in the ZIP + * filesystem. * * Results: - * TCL_OK when the path object is in the ZIP filesystem, -1 otherwise. + * TCL_OK when the path object is in the ZIP filesystem, -1 otherwise. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr) +Zip_FSPathInFilesystemProc( + Tcl_Obj *pathPtr, + ClientData *clientDataPtr) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -3971,11 +4135,13 @@ Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr) size_t len; char *path; - if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1; + if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) { + return -1; + } path = Tcl_GetString(pathPtr); - if(strncmp(path,ZIPFS_VOLUME,ZIPFS_VOLUME_LEN)!=0) { - return -1; + if (strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) != 0) { + return -1; } len = pathPtr->length; @@ -3983,33 +4149,33 @@ Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr) ReadLock(); hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); if (hPtr != NULL) { - ret = TCL_OK; - goto endloop; + 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) { - 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) - ) { - ret = TCL_OK; - goto endloop; - } - hPtr = Tcl_NextHashEntry(&search); - } -endloop: + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + if (zf->mntptlen == 0) { + ZipEntry *z = zf->topents; + while (z != NULL) { + 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)) { + ret = TCL_OK; + goto endloop; + } + hPtr = Tcl_NextHashEntry(&search); + } + + endloop: Unlock(); return ret; } @@ -4019,18 +4185,20 @@ endloop: * * Zip_FSListVolumesProc -- * - * Lists the currently mounted ZIP filesystem volumes. + * Lists the currently mounted ZIP filesystem volumes. * * Results: - * The list of volumes. + * The list of volumes. * * Side effects: - * None + * None * *------------------------------------------------------------------------- */ + static Tcl_Obj * -Zip_FSListVolumesProc(void) { +Zip_FSListVolumesProc(void) +{ return Tcl_NewStringObj(ZIPFS_VOLUME, -1); } @@ -4039,29 +4207,32 @@ Zip_FSListVolumesProc(void) { * * Zip_FSFileAttrStringsProc -- * - * This function implements the ZIP filesystem dependent 'file attributes' - * subcommand, for listing the set of possible attribute strings. + * This function implements the ZIP filesystem dependent 'file + * attributes' subcommand, for listing the set of possible attribute + * strings. * * Results: - * An array of strings + * An array of strings * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static const char *const * -Zip_FSFileAttrStringsProc(Tcl_Obj *pathPtr, Tcl_Obj** objPtrRef) +Zip_FSFileAttrStringsProc( + Tcl_Obj *pathPtr, + Tcl_Obj** objPtrRef) { static const char *const attrs[] = { - "-uncompsize", - "-compsize", - "-offset", - "-mount", - "-archive", - "-permissions", - NULL, + "-uncompsize", + "-compsize", + "-offset", + "-mount", + "-archive", + "-permissions", + NULL, }; return attrs; } @@ -4071,61 +4242,66 @@ Zip_FSFileAttrStringsProc(Tcl_Obj *pathPtr, Tcl_Obj** objPtrRef) * * Zip_FSFileAttrsGetProc -- * - * This function implements the ZIP filesystem specific - * 'file attributes' subcommand, for 'get' operations. + * This function implements the ZIP filesystem specific 'file attributes' + * subcommand, for 'get' operations. * * Results: - * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK - * was returned) is likely to have a refCount of zero. Either way we must - * either store it somewhere (e.g. the Tcl result), or Incr/Decr its - * refCount to ensure it is properly freed. + * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK + * was returned) is likely to have a refCount of zero. Either way we must + * either store it somewhere (e.g. the Tcl result), or Incr/Decr its + * refCount to ensure it is properly freed. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -Zip_FSFileAttrsGetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, - Tcl_Obj **objPtrRef) +Zip_FSFileAttrsGetProc( + Tcl_Interp *interp, + int index, + Tcl_Obj *pathPtr, + Tcl_Obj **objPtrRef) { int len, ret = TCL_OK; char *path; ZipEntry *z; - if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1; + if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) { + return -1; + } path = Tcl_GetStringFromObj(pathPtr, &len); ReadLock(); z = ZipFSLookup(path); if (z == NULL) { - ZIPFS_ERROR(interp,"file not found"); - ret = TCL_ERROR; - goto done; + ZIPFS_ERROR(interp, "file not found"); + ret = TCL_ERROR; + goto done; } switch (index) { - case 0: - *objPtrRef = Tcl_NewWideIntObj(z->nbyte); - goto done; - case 1: - *objPtrRef = Tcl_NewWideIntObj(z->nbytecompr); - goto done; - case 2: - *objPtrRef= Tcl_NewWideIntObj(z->offset); - goto done; - case 3: - *objPtrRef= Tcl_NewStringObj(z->zipfile->mntpt, z->zipfile->mntptlen); - goto done; - case 4: - *objPtrRef= Tcl_NewStringObj(z->zipfile->name, -1); - goto done; - case 5: - *objPtrRef= Tcl_NewStringObj("0555", -1); - goto done; - } - ZIPFS_ERROR(interp,"unknown attribute"); + case 0: + *objPtrRef = Tcl_NewWideIntObj(z->nbyte); + goto done; + case 1: + *objPtrRef = Tcl_NewWideIntObj(z->nbytecompr); + goto done; + case 2: + *objPtrRef = Tcl_NewWideIntObj(z->offset); + goto done; + case 3: + *objPtrRef = Tcl_NewStringObj(z->zipfile->mntpt, z->zipfile->mntptlen); + goto done; + case 4: + *objPtrRef = Tcl_NewStringObj(z->zipfile->name, -1); + goto done; + case 5: + *objPtrRef = Tcl_NewStringObj("0555", -1); + goto done; + } + ZIPFS_ERROR(interp, "unknown attribute"); ret = TCL_ERROR; -done: + done: Unlock(); return ret; } @@ -4135,23 +4311,27 @@ done: * * Zip_FSFileAttrsSetProc -- * - * This function implements the ZIP filesystem specific - * 'file attributes' subcommand, for 'set' operations. + * This function implements the ZIP filesystem specific 'file attributes' + * subcommand, for 'set' operations. * * Results: - * Standard Tcl return code. + * Standard Tcl return code. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static int -Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr,Tcl_Obj *objPtr) +Zip_FSFileAttrsSetProc( + Tcl_Interp *interp, + int index, + Tcl_Obj *pathPtr, + Tcl_Obj *objPtr) { if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1)); } return TCL_ERROR; } @@ -4169,358 +4349,407 @@ Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr,Tcl_Obj * */ static Tcl_Obj * -Zip_FSFilesystemPathTypeProc(Tcl_Obj *pathPtr) +Zip_FSFilesystemPathTypeProc( + Tcl_Obj *pathPtr) { return Tcl_NewStringObj("zip", -1); } - /* *------------------------------------------------------------------------- * * Zip_FSLoadFile -- * - * This functions deals with loading native object code. If - * the given path object refers to a file within the ZIP - * filesystem, an approriate error code is returned to delegate - * loading to the caller (by copying the file to temp store - * and loading from there). As fallback when the file refers - * to the ZIP file system but is not present, it is looked up - * relative to the executable and loaded from there when available. + * This functions deals with loading native object code. If the given + * path object refers to a file within the ZIP filesystem, an approriate + * error code is returned to delegate loading to the caller (by copying + * the file to temp store and loading from there). As fallback when the + * file refers to the ZIP file system but is not present, it is looked up + * relative to the executable and loaded from there when available. * * Results: - * TCL_OK on success, TCL_ERROR otherwise with error message left. + * TCL_OK on success, TCL_ERROR otherwise with error message left. * * Side effects: - * Loads native code into the process address space. + * Loads native code into the process address space. * *------------------------------------------------------------------------- */ static int -Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, - Tcl_FSUnloadFileProc **unloadProcPtr, int flags) +Zip_FSLoadFile( + Tcl_Interp *interp, + Tcl_Obj *path, + Tcl_LoadHandle *loadHandle, + Tcl_FSUnloadFileProc **unloadProcPtr, + int flags) { Tcl_FSLoadFileProc2 *loadFileProc; #ifdef ANDROID /* - * Force loadFileProc to native implementation since the - * package manager already extracted the shared libraries - * from the APK at install time. + * Force loadFileProc to native implementation since the package manager + * already extracted the shared libraries from the APK at install time. */ loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; if (loadFileProc != NULL) { - return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } Tcl_SetErrno(ENOENT); - ZIPFS_ERROR(interp,Tcl_PosixError(interp)); + ZIPFS_ERROR(interp, Tcl_PosixError(interp)); return TCL_ERROR; -#else +#else /* !ANDROID */ Tcl_Obj *altPath = NULL; int ret = TCL_ERROR; if (Tcl_FSAccess(path, R_OK) == 0) { - /* - * EXDEV should trigger loading by copying to temp store. - */ + /* + * EXDEV should trigger loading by copying to temp store. + */ - Tcl_SetErrno(EXDEV); - ZIPFS_ERROR(interp,Tcl_PosixError(interp)); - return ret; + 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(); - - /* - * 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); - /* - * 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 (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 (objs[0] != NULL) { - Tcl_DecrRefCount(objs[0]); - } - if (objs[1] != NULL) { - Tcl_DecrRefCount(objs[1]); - } + 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(); + + /* + * 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); + + /* + * 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 (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 (objs[0] != NULL) { + Tcl_DecrRefCount(objs[0]); + } + if (objs[1] != NULL) { + Tcl_DecrRefCount(objs[1]); + } } loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; if (loadFileProc != NULL) { - ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { - Tcl_SetErrno(ENOENT); - ZIPFS_ERROR(interp,Tcl_PosixError(interp)); + Tcl_SetErrno(ENOENT); + ZIPFS_ERROR(interp, Tcl_PosixError(interp)); } if (altPath != NULL) { - Tcl_DecrRefCount(altPath); + Tcl_DecrRefCount(altPath); } return ret; -#endif +#endif /* ANDROID */ } #endif /* HAVE_ZLIB */ - - /* *------------------------------------------------------------------------- * * TclZipfs_Init -- * - * Perform per interpreter initialization of this module. + * Perform per interpreter initialization of this module. * * Results: - * The return value is a standard Tcl result. + * The return value is a standard Tcl result. * * Side effects: - * Initializes this module if not already initialized, and adds - * module related commands to the given interpreter. + * Initializes this module if not already initialized, and adds module + * related commands to the given interpreter. * *------------------------------------------------------------------------- */ MODULE_SCOPE int -TclZipfs_Init(Tcl_Interp *interp) +TclZipfs_Init( + Tcl_Interp *interp) { #ifdef HAVE_ZLIB /* one-time initialization */ WriteLock(); /* Tcl_StaticPackage(interp, "zipfs", TclZipfs_Init, TclZipfs_Init); */ if (!ZipFS.initialized) { - TclZipfs_C_Init(); + TclZipfs_C_Init(); } 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"; - Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL); - Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,TCL_LINK_INT); - TclMakeEnsemble(interp, "zipfs", Tcl_IsSafe(interp) ? (initMap+4) : initMap); - Tcl_PkgProvide(interp, "zipfs", "2.0"); + 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"; + Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL); + Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax, + TCL_LINK_INT); + TclMakeEnsemble(interp, "zipfs", + Tcl_IsSafe(interp) ? (initMap + 4) : initMap); + Tcl_PkgProvide(interp, "zipfs", "2.0"); } return TCL_OK; #else - ZIPFS_ERROR(interp,"no zlib available"); + ZIPFS_ERROR(interp, "no zlib available"); return TCL_ERROR; #endif } - -static int TclZipfs_AppHook_FindTclInit(const char *archive){ + +static int +TclZipfs_AppHook_FindTclInit( + const char *archive) +{ Tcl_Obj *vfsinitscript; int found; - if(zipfs_literal_tcl_library) { - return TCL_ERROR; + + if (zipfs_literal_tcl_library) { + return TCL_ERROR; } - if(TclZipfs_Mount(NULL, ZIPFS_ZIP_MOUNT, archive, NULL)) { - /* Either the file doesn't exist or it is not a zip archive */ - return TCL_ERROR; + if (TclZipfs_Mount(NULL, ZIPFS_ZIP_MOUNT, archive, NULL)) { + /* Either the file doesn't exist or it is not a zip archive */ + return TCL_ERROR; } - vfsinitscript=Tcl_NewStringObj(ZIPFS_ZIP_MOUNT "/init.tcl",-1); + + vfsinitscript = Tcl_NewStringObj(ZIPFS_ZIP_MOUNT "/init.tcl", -1); Tcl_IncrRefCount(vfsinitscript); - found=Tcl_FSAccess(vfsinitscript,F_OK); + found = Tcl_FSAccess(vfsinitscript, F_OK); Tcl_DecrRefCount(vfsinitscript); - if(found==0) { - zipfs_literal_tcl_library=ZIPFS_ZIP_MOUNT; - return TCL_OK; + if (found == 0) { + zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT; + return TCL_OK; } - vfsinitscript=Tcl_NewStringObj(ZIPFS_ZIP_MOUNT "/tcl_library/init.tcl",-1); + + vfsinitscript = Tcl_NewStringObj( + ZIPFS_ZIP_MOUNT "/tcl_library/init.tcl", -1); Tcl_IncrRefCount(vfsinitscript); - found=Tcl_FSAccess(vfsinitscript,F_OK); + found = Tcl_FSAccess(vfsinitscript, F_OK); Tcl_DecrRefCount(vfsinitscript); - if(found==0) { - zipfs_literal_tcl_library=ZIPFS_ZIP_MOUNT "/tcl_library"; - return TCL_OK; + if (found == 0) { + zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT "/tcl_library"; + return TCL_OK; } + return TCL_ERROR; } + +/* + *------------------------------------------------------------------------- + * + * Tclkit_MainHook -- + * + * Performs the argument munging for the shell + * + *------------------------------------------------------------------------- + */ +int +TclZipfs_AppHook( + int *argc, #ifdef _WIN32 -int TclZipfs_AppHook(int *argc, TCHAR ***argv) -#else -int TclZipfs_AppHook(int *argc, char ***argv) -#endif + TCHAR +#else /* !_WIN32 */ + char +#endif /* _WIN32 */ + ***argv) { #ifdef _WIN32 Tcl_DString ds; -#endif - /* - * Tclkit_MainHook -- - * Performs the argument munging for the shell - */ +#endif /* _WIN32 */ char *archive; Tcl_FindExecutable((*argv)[0]); - archive=(char *)Tcl_GetNameOfExecutable(); + archive = (char *) Tcl_GetNameOfExecutable(); TclZipfs_Init(NULL); + /* - ** Look for init.tcl in one of the locations mounted later in this function - */ - if(!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { - int found; - Tcl_Obj *vfsinitscript; - vfsinitscript=Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl",-1); - Tcl_IncrRefCount(vfsinitscript); - if(Tcl_FSAccess(vfsinitscript,F_OK)==0) { - /* Startup script should be set before calling Tcl_AppInit */ - Tcl_SetStartupScript(vfsinitscript,NULL); - } else { - Tcl_DecrRefCount(vfsinitscript); - } - /* Set Tcl Encodings */ - 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); - if(found==TCL_OK) { - zipfs_literal_tcl_library=ZIPFS_APP_MOUNT "/tcl_library"; - return TCL_OK; - } - } + * Look for init.tcl in one of the locations mounted later in this + * function. + */ + + if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { + int found; + Tcl_Obj *vfsinitscript; + + vfsinitscript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl", -1); + Tcl_IncrRefCount(vfsinitscript); + if (Tcl_FSAccess(vfsinitscript, F_OK) == 0) { + /* + * Startup script should be set before calling Tcl_AppInit + */ + + Tcl_SetStartupScript(vfsinitscript, NULL); + } else { + Tcl_DecrRefCount(vfsinitscript); + } + + /* + * Set Tcl Encodings + */ + + 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); + if (found == TCL_OK) { + zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; + return TCL_OK; + } + } } else if (*argc>1) { - return TCL_OK; + return TCL_OK; #ifdef _WIN32 - archive = Tcl_WinTCharToUtf((*argv)[1], -1, &ds); + archive = Tcl_WinTCharToUtf((*argv)[1], -1, &ds); #else - archive=(*argv)[1]; + archive = (*argv)[1]; #endif - if (strcmp(archive,"install")==0) { - /* If the first argument is mkzip, run the mkzip program */ - Tcl_Obj *vfsinitscript; - /* Run this now to ensure the file is present by the time Tcl_Main wants it */ - 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); - } - return TCL_OK; - } else { - if(!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { - int found; - Tcl_Obj *vfsinitscript; - vfsinitscript=Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl",-1); - Tcl_IncrRefCount(vfsinitscript); - if(Tcl_FSAccess(vfsinitscript,F_OK)==0) { - /* Startup script should be set before calling Tcl_AppInit */ - Tcl_SetStartupScript(vfsinitscript,NULL); - } else { - 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); - if(found==TCL_OK) { - zipfs_literal_tcl_library=ZIPFS_APP_MOUNT "/tcl_library"; - return TCL_OK; - } - } - } + if (strcmp(archive, "install") == 0) { + /* + * If the first argument is mkzip, run the mkzip program. + */ + + Tcl_Obj *vfsinitscript; + + /* + * Run this now to ensure the file is present by the time Tcl_Main + * wants it. + */ + + 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); + } + return TCL_OK; + } else if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { + int found; + Tcl_Obj *vfsinitscript; + + vfsinitscript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/main.tcl", -1); + Tcl_IncrRefCount(vfsinitscript); + if (Tcl_FSAccess(vfsinitscript, F_OK) == 0) { + /* + * Startup script should be set before calling Tcl_AppInit + */ + + Tcl_SetStartupScript(vfsinitscript, NULL); + } else { + 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); + if (found == TCL_OK) { + zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; + return TCL_OK; + } + } #ifdef _WIN32 - Tcl_DStringFree(&ds); -#endif + Tcl_DStringFree(&ds); +#endif /* _WIN32 */ } return TCL_OK; } - #ifndef HAVE_ZLIB - + /* *------------------------------------------------------------------------- * * TclZipfs_Mount, TclZipfs_Unmount -- * - * Dummy version when no ZLIB support available. + * Dummy version when no ZLIB support available. * *------------------------------------------------------------------------- */ int -TclZipfs_Mount(Tcl_Interp *interp, const char *mntpt, const char *zipname, - const char *passwd) +TclZipfs_Mount( + Tcl_Interp *interp, + const char *mntpt, + const char *zipname, + const char *passwd) { return TclZipfs_Init(interp, 1); } int -TclZipfs_Unmount(Tcl_Interp *interp, const char *zipname) +TclZipfs_Unmount( + Tcl_Interp *interp, + const char *zipname) { return TclZipfs_Init(interp, 1); } - -#endif - +#endif /* !HAVE_ZLIB */ + /* * Local Variables: * mode: c diff --git a/library/reg/pkgIndex.tcl b/library/reg/pkgIndex.tcl index b1fe234..ee559b5 100755 --- a/library/reg/pkgIndex.tcl +++ b/library/reg/pkgIndex.tcl @@ -1,9 +1,9 @@ if {([info commands ::tcl::pkgconfig] eq "") || ([info sharedlibextension] ne ".dll")} return if {[::tcl::pkgconfig get debug]} { - package ifneeded registry 1.3.2 \ + package ifneeded registry 1.3.3 \ [list load [file join $dir tclreg13g.dll] registry] } else { - package ifneeded registry 1.3.2 \ + package ifneeded registry 1.3.3 \ [list load [file join $dir tclreg13.dll] registry] } diff --git a/win/tclWinReg.c b/win/tclWinReg.c index 95ab499..f3d7a07 100644 --- a/win/tclWinReg.c +++ b/win/tclWinReg.c @@ -156,7 +156,7 @@ Registry_Init( cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd, interp, DeleteCmd); Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd); - return Tcl_PkgProvide(interp, "registry", "1.3.2"); + return Tcl_PkgProvide(interp, "registry", "1.3.3"); } /* @@ -407,12 +407,12 @@ DeleteKey( */ keyName = Tcl_GetString(keyNameObj); - buffer = ckalloc(keyNameObj->length + 1); + buffer = Tcl_Alloc(keyNameObj->length + 1); strcpy(buffer, keyName); if (ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName) != TCL_OK) { - ckfree(buffer); + Tcl_Free(buffer); return TCL_ERROR; } @@ -420,7 +420,7 @@ DeleteKey( Tcl_SetObjResult(interp, Tcl_NewStringObj("bad key: cannot delete root keys", -1)); Tcl_SetErrorCode(interp, "WIN_REG", "DEL_ROOT_KEY", NULL); - ckfree(buffer); + Tcl_Free(buffer); return TCL_ERROR; } @@ -435,7 +435,7 @@ DeleteKey( mode |= KEY_ENUMERATE_SUB_KEYS | DELETE; result = OpenSubKey(hostName, rootKey, keyName, mode, 0, &subkey); if (result != ERROR_SUCCESS) { - ckfree(buffer); + Tcl_Free(buffer); if (result == ERROR_FILE_NOT_FOUND) { return TCL_OK; } @@ -463,7 +463,7 @@ DeleteKey( } RegCloseKey(subkey); - ckfree(buffer); + Tcl_Free(buffer); return result; } @@ -596,8 +596,7 @@ GetKeyNames( } break; } - Tcl_WinTCharToUtf(buffer, bufSize * sizeof(TCHAR), &ds); - name = Tcl_DStringValue(&ds); + name = Tcl_WinTCharToUtf(buffer, bufSize * sizeof(TCHAR), &ds); if (pattern && !Tcl_StringMatch(name, pattern)) { Tcl_DStringFree(&ds); continue; @@ -943,7 +942,7 @@ OpenKey( keyName = Tcl_GetString(keyNameObj); length = keyNameObj->length; - buffer = ckalloc(length + 1); + buffer = Tcl_Alloc(length + 1); strcpy(buffer, keyName); result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName); @@ -959,7 +958,7 @@ OpenKey( } } - ckfree(buffer); + Tcl_Free(buffer); return result; } @@ -1012,7 +1011,9 @@ OpenSubKey( * this key must be closed by the caller. */ - keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf); + if (keyName) { + keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf); + } if (flags & REG_CREATE) { DWORD create; @@ -1030,7 +1031,9 @@ OpenSubKey( result = RegOpenKeyEx(rootKey, (TCHAR *)keyName, 0, mode, keyPtr); } - Tcl_DStringFree(&buf); + if (keyName) { + Tcl_DStringFree(&buf); + } /* * Be sure to close the root key since we are done with it now. |
