diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2021-03-06 16:28:43 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2021-03-06 16:28:43 (GMT) |
commit | a1d8e47ea7ef4acf4228052d71aa77bf788a9d15 (patch) | |
tree | 4e7f012e606eb46a1a03e80d4c516762bead6355 | |
parent | dd7f073e8b7bee2631f4a175359de6b99d8f3570 (diff) | |
download | tcl-a1d8e47ea7ef4acf4228052d71aa77bf788a9d15.zip tcl-a1d8e47ea7ef4acf4228052d71aa77bf788a9d15.tar.gz tcl-a1d8e47ea7ef4acf4228052d71aa77bf788a9d15.tar.bz2 |
Document that [zipfs mkimg] strips an existing ZIP. We ought to merge instead, but we don't yet.
-rw-r--r-- | doc/zipfs.n | 2 | ||||
-rw-r--r-- | generic/tclZipfs.c | 130 |
2 files changed, 87 insertions, 45 deletions
diff --git a/doc/zipfs.n b/doc/zipfs.n index da2e026..ada0d28 100644 --- a/doc/zipfs.n +++ b/doc/zipfs.n @@ -146,6 +146,8 @@ the ZIP archive, otherwise the file returned by \fBinfo nameofexecutable\fR (see \fBzipfs mkkey\fR) is placed between the image and ZIP chunks of the output file and the contents of the ZIP chunk are protected with that password. +If the starting image has a ZIP archive already attached to it, it is removed +from the copy in \fIoutfile\fR before the new ZIP archive is added. .PP If there is a file, \fBmain.tcl\fR, in the root directory of the resulting archive and the image file that the archive is attached to is a \fBtclsh\fR diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index ed3b42d..bf74823 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -360,7 +360,7 @@ static const Tcl_Filesystem zipfsFilesystem = { NULL, /* renameFileProc */ NULL, /* copyDirectoryProc */ NULL, /* lstatProc */ - (Tcl_FSLoadFileProc *)(void *)ZipFSLoadFile, + (Tcl_FSLoadFileProc *) (void *) ZipFSLoadFile, NULL, /* getCwdProc */ NULL, /* chdirProc */ }; @@ -779,7 +779,7 @@ ZipFSLookup( hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename); if (hPtr) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); } return z; } @@ -867,7 +867,7 @@ ZipFSCloseArchive( #else /* !_WIN32 */ if ((zf->data != MAP_FAILED) && !zf->ptrToFree) { munmap(zf->data, zf->length); - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; } #endif /* _WIN32 */ @@ -1037,7 +1037,7 @@ ZipFSOpenArchive( zf->data = NULL; zf->mountHandle = INVALID_HANDLE_VALUE; #else /* !_WIN32 */ - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; #endif /* _WIN32 */ zf->length = 0; zf->numFiles = 0; @@ -1066,7 +1066,7 @@ ZipFSOpenArchive( ZIPFS_POSIX_ERROR(interp, "seek error"); goto error; } - zf->ptrToFree = zf->data = (unsigned char *)attemptckalloc(zf->length); + zf->ptrToFree = zf->data = (unsigned char *) attemptckalloc(zf->length); if (!zf->ptrToFree) { ZIPFS_ERROR(interp, "out of memory"); if (interp) { @@ -1101,8 +1101,9 @@ ZipFSOpenArchive( ZIPFS_POSIX_ERROR(interp, "file mapping failed"); goto error; } - zf->data = (unsigned char *)MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0, - zf->length); + zf->data = (unsigned char *) + MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0, + zf->length); if (!zf->data) { ZIPFS_POSIX_ERROR(interp, "file mapping failed"); goto error; @@ -1197,7 +1198,7 @@ ZipFSCatalogFilesystem( hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew); if (!isNew) { if (interp) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s is already mounted on %s", zf->name, mountPoint)); Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "MOUNTED", NULL); @@ -1206,7 +1207,7 @@ ZipFSCatalogFilesystem( ZipFSCloseArchive(interp, zf0); return TCL_ERROR; } - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = (ZipFile *) attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); if (!zf) { if (interp) { Tcl_AppendResult(interp, "out of memory", (char *) NULL); @@ -1219,11 +1220,11 @@ ZipFSCatalogFilesystem( Unlock(); *zf = *zf0; - zf->mountPoint = (char *)Tcl_GetHashKey(&ZipFS.zipHash, hPtr); + zf->mountPoint = (char *) Tcl_GetHashKey(&ZipFS.zipHash, hPtr); Tcl_CreateExitHandler(ZipfsExitHandler, zf); zf->mountPointLen = strlen(zf->mountPoint); zf->nameLength = strlen(zipname); - zf->name = (char *)ckalloc(zf->nameLength + 1); + zf->name = (char *) ckalloc(zf->nameLength + 1); memcpy(zf->name, zipname, zf->nameLength + 1); zf->entries = NULL; zf->topEnts = NULL; @@ -1242,7 +1243,7 @@ ZipFSCatalogFilesystem( if (mountPoint[0] != '\0') { hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew); if (isNew) { - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + z = (ZipEntry *) ckalloc(sizeof(ZipEntry)); Tcl_SetHashValue(hPtr, z); z->tnext = NULL; @@ -1256,7 +1257,7 @@ ZipFSCatalogFilesystem( z->numBytes = z->numCompressedBytes = 0; z->compressMethod = ZIP_COMPMETH_STORED; z->data = NULL; - z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); z->next = zf->entries; zf->entries = z; } @@ -1337,7 +1338,7 @@ ZipFSCatalogFilesystem( } Tcl_DStringSetLength(&fpBuf, 0); fullpath = CanonicalPath(mountPoint, path, &fpBuf, 1); - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + z = (ZipEntry *) ckalloc(sizeof(ZipEntry)); z->name = NULL; z->tnext = NULL; z->depth = CountSlashes(fullpath); @@ -1369,7 +1370,7 @@ ZipFSCatalogFilesystem( ckfree(z); } else { Tcl_SetHashValue(hPtr, z); - z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); z->next = zf->entries; zf->entries = z; if (isdir && (mountPoint[0] == '\0') && (z->depth == 1)) { @@ -1391,7 +1392,7 @@ ZipFSCatalogFilesystem( if (!isNew) { break; } - zd = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + zd = (ZipEntry *) ckalloc(sizeof(ZipEntry)); zd->name = NULL; zd->tnext = NULL; zd->depth = CountSlashes(dir); @@ -1405,7 +1406,7 @@ ZipFSCatalogFilesystem( zd->compressMethod = ZIP_COMPMETH_STORED; zd->data = NULL; Tcl_SetHashValue(hPtr, zd); - zd->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + zd->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); zd->next = zf->entries; zf->entries = zd; if ((mountPoint[0] == '\0') && (zd->depth == 1)) { @@ -1491,7 +1492,7 @@ ListMountPoints( if (!interp) { return TCL_OK; } - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); Tcl_AppendElement(interp, zf->mountPoint); Tcl_AppendElement(interp, zf->name); } @@ -1528,7 +1529,7 @@ DescribeMounted( if (interp) { hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint); if (hPtr) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1)); return TCL_OK; } @@ -1605,7 +1606,7 @@ TclZipfs_Mount( return TCL_ERROR; } } - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = (ZipFile *) attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); if (!zf) { if (interp) { Tcl_AppendResult(interp, "out of memory", (char *) NULL); @@ -1686,7 +1687,7 @@ TclZipfs_MountBuffer( * Have both a mount point and data to mount there. */ - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = (ZipFile *) attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); if (!zf) { if (interp) { Tcl_AppendResult(interp, "out of memory", (char *) NULL); @@ -1697,7 +1698,7 @@ TclZipfs_MountBuffer( zf->isMemBuffer = 1; zf->length = datalen; if (copy) { - zf->data = (unsigned char *)attemptckalloc(datalen); + zf->data = (unsigned char *) attemptckalloc(datalen); if (!zf->data) { if (interp) { Tcl_AppendResult(interp, "out of memory", (char *) NULL); @@ -1767,7 +1768,7 @@ TclZipfs_Unmount( goto done; } - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->numOpen > 0) { ZIPFS_ERROR(interp, "filesystem is busy"); ret = TCL_ERROR; @@ -2309,7 +2310,7 @@ ZipAddFile( return TCL_ERROR; } - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + z = (ZipEntry *) ckalloc(sizeof(ZipEntry)); Tcl_SetHashValue(hPtr, z); z->name = NULL; z->tnext = NULL; @@ -2324,7 +2325,7 @@ ZipAddFile( z->numCompressedBytes = nbytecompr; z->compressMethod = compMeth; z->data = NULL; - z->name = (char *)Tcl_GetHashKey(fileHash, hPtr); + z->name = (char *) Tcl_GetHashKey(fileHash, hPtr); z->next = NULL; /* @@ -2425,6 +2426,10 @@ ZipFSMkZipOrImgObjCmd( } else { Tcl_Obj *cmd[3]; + /* + * Discover the list of files to add. + */ + cmd[1] = Tcl_NewStringObj("::tcl::zipfs::find", -1); cmd[2] = objv[2]; cmd[0] = Tcl_NewListObj(2, cmd + 1); @@ -2463,6 +2468,13 @@ ZipFSMkZipOrImgObjCmd( pw = NULL; pwlen = 0; } + + /* + * Copy the existing contents from the image if it is an executable image. + * Care must be taken because this might include an existing ZIP, which + * needs to be stripped. + */ + if (isImg) { ZipFile *zf, zf0; int isMounted = 0; @@ -2499,7 +2511,7 @@ ZipFSMkZipOrImgObjCmd( WriteLock(); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (strcmp(zf->name, imgName) == 0) { isMounted = 1; zf->numOpen++; @@ -2507,10 +2519,15 @@ ZipFSMkZipOrImgObjCmd( } } Unlock(); + if (!isMounted) { zf = &zf0; } if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) { + /* + * Copy everything up to the ZIP-related suffix. + */ + if ((size_t) Tcl_Write(out, (char *) zf->data, zf->passOffset) != zf->passOffset) { memset(passBuf, 0, sizeof(passBuf)); @@ -2585,6 +2602,11 @@ ZipFSMkZipOrImgObjCmd( } Tcl_Close(interp, in); } + + /* + * Store the password so that the automounter can find it. + */ + len = strlen(passBuf); if (len > 0) { i = Tcl_Write(out, passBuf, len); @@ -2599,6 +2621,11 @@ ZipFSMkZipOrImgObjCmd( memset(passBuf, 0, sizeof(passBuf)); Tcl_Flush(out); } + + /* + * Prepare the contents of the ZIP archive. + */ + Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS); pos[0] = Tcl_Tell(out); if (!isList && (objc > 3)) { @@ -2632,6 +2659,11 @@ ZipFSMkZipOrImgObjCmd( goto done; } } + + /* + * Construct the contents of the ZIP central directory. + */ + pos[1] = Tcl_Tell(out); count = 0; for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) { @@ -2660,7 +2692,7 @@ ZipFSMkZipOrImgObjCmd( if (!hPtr) { continue; } - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); len = strlen(z->name); ZipWriteInt(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG); ZipWriteShort(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION); @@ -2688,6 +2720,11 @@ ZipFSMkZipOrImgObjCmd( } count++; } + + /* + * Finalize the central directory. + */ + Tcl_Flush(out); pos[2] = Tcl_Tell(out); ZipWriteInt(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG); @@ -2715,7 +2752,7 @@ ZipFSMkZipOrImgObjCmd( Tcl_DecrRefCount(list); for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); ckfree(z); Tcl_DeleteHashEntry(hPtr); } @@ -3055,7 +3092,7 @@ ZipFSListObjCmd( if (pattern) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_StringMatch(z->name, pattern)) { Tcl_ListObjAppendElement(interp, result, @@ -3065,7 +3102,7 @@ ZipFSListObjCmd( } else if (regexp) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { Tcl_ListObjAppendElement(interp, result, @@ -3075,7 +3112,7 @@ ZipFSListObjCmd( } else { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); @@ -3235,7 +3272,7 @@ ZipChannelClose( TCL_UNUSED(Tcl_Interp *), int flags) { - ZipChannel *info = (ZipChannel *)instanceData; + ZipChannel *info = (ZipChannel *) instanceData; if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; @@ -3251,7 +3288,8 @@ ZipChannelClose( } if (info->isWriting) { ZipEntry *z = info->zipEntryPtr; - unsigned char *newdata = (unsigned char *)attemptckrealloc(info->ubuf, info->numRead); + unsigned char *newdata = (unsigned char *) + attemptckrealloc(info->ubuf, info->numRead); if (newdata) { if (z->data) { @@ -3614,7 +3652,7 @@ ZipChannelOpen( } else { flags = TCL_WRITABLE; } - info = (ZipChannel *)attemptckalloc(sizeof(ZipChannel)); + info = (ZipChannel *) attemptckalloc(sizeof(ZipChannel)); if (!info) { ZIPFS_ERROR(interp, "out of memory"); if (interp) { @@ -3632,7 +3670,7 @@ ZipChannelOpen( info->maxWrite = ZipFS.wrmax; info->iscompr = 0; info->isEncrypted = 0; - info->ubuf = (unsigned char *)attemptckalloc(info->maxWrite); + info->ubuf = (unsigned char *) attemptckalloc(info->maxWrite); if (!info->ubuf) { merror0: if (info->ubuf) { @@ -3690,7 +3728,7 @@ ZipChannelOpen( unsigned int j; stream.avail_in -= 12; - cbuf = (unsigned char *)attemptckalloc(stream.avail_in); + cbuf = (unsigned char *) attemptckalloc(stream.avail_in); if (!cbuf) { goto merror0; } @@ -3790,7 +3828,7 @@ ZipChannelOpen( stream.avail_in = z->numCompressedBytes; if (info->isEncrypted) { stream.avail_in -= 12; - ubuf = (unsigned char *)attemptckalloc(stream.avail_in); + ubuf = (unsigned char *) attemptckalloc(stream.avail_in); if (!ubuf) { info->ubuf = NULL; goto merror; @@ -3803,7 +3841,8 @@ ZipChannelOpen( } else { stream.next_in = info->ubuf; } - stream.next_out = info->ubuf = (unsigned char *)attemptckalloc(info->numBytes); + stream.next_out = info->ubuf = (unsigned char *) + attemptckalloc(info->numBytes); if (!info->ubuf) { merror: if (ubuf) { @@ -4164,7 +4203,7 @@ ZipFSMatchInDirectoryProc( } for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr); + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->mountPointLen == 0) { ZipEntry *z; @@ -4215,7 +4254,7 @@ ZipFSMatchInDirectoryProc( if (!pattern || (pattern[0] == '\0')) { hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); if (hPtr) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if ((dirOnly < 0) || (!dirOnly && !z->isDirectory) || (dirOnly && z->isDirectory)) { @@ -4235,7 +4274,7 @@ ZipFSMatchInDirectoryProc( } l = strlen(pattern); - pat = (char *)ckalloc(len + l + 2); + pat = (char *) ckalloc(len + l + 2); memcpy(pat, path, len); while ((len > 1) && (pat[len - 1] == '/')) { --len; @@ -4248,7 +4287,7 @@ ZipFSMatchInDirectoryProc( scnt = CountSlashes(pat); for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if ((dirOnly >= 0) && ((dirOnly && !z->isDirectory) || (!dirOnly && z->isDirectory))) { @@ -4324,7 +4363,7 @@ ZipFSPathInFilesystemProc( for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr); + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->mountPointLen == 0) { ZipEntry *z; @@ -4636,7 +4675,8 @@ ZipFSLoadFile( Tcl_DecrRefCount(objs[1]); } - loadFileProc = (Tcl_FSLoadFileProc2 *)(void *)tclNativeFilesystem.loadFileProc; + loadFileProc = (Tcl_FSLoadFileProc2 *) (void *) + tclNativeFilesystem.loadFileProc; if (loadFileProc) { ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { @@ -4792,7 +4832,7 @@ static void ZipfsExitHandler( ClientData clientData) { - ZipFile *zf = (ZipFile *)clientData; + ZipFile *zf = (ZipFile *) clientData; if (TCL_OK != TclZipfs_Unmount(NULL, zf->mountPoint)) { Tcl_Panic("tried to unmount busy filesystem"); |