diff options
-rw-r--r-- | generic/tclZipfs.c | 77 | ||||
-rw-r--r-- | tests/zipfs.test | 14 |
2 files changed, 41 insertions, 50 deletions
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index cb8792f..ad65e72 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -4535,14 +4535,27 @@ static Tcl_Channel ZipChannelOpen( Tcl_Interp *interp, /* Current interpreter. */ char *filename, /* What are we opening. */ - int wr, /* True if we're opening in write mode. */ - int trunc) /* True if we're opening in truncate mode. */ + int mode) /* O_WRONLY O_RDWR O_TRUNC flags */ { ZipEntry *z; ZipChannel *info; int flags = 0; char cname[128]; + int wr = (mode & (O_WRONLY | O_RDWR)) != 0; + + /* Check for unsupported modes. */ + + if ((mode & O_APPEND) || ((ZipFS.wrmax <= 0) && wr)) { + Tcl_SetErrno(EACCES); + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "%s not supported: %s", + mode & O_APPEND ? "append mode" : "write access", + Tcl_PosixError(interp))); + } + return NULL; + } /* * Is the file there? */ @@ -4586,8 +4599,20 @@ ZipChannelOpen( ZIPFS_ERROR_CODE(interp, "COMP_METHOD"); goto error; } - if (!trunc) { + if (wr) { + if ((mode & O_TRUNC) == 0 && !z->data && (z->numBytes > ZipFS.wrmax)) { + Tcl_SetErrno(EFBIG); + ZIPFS_POSIX_ERROR(interp, "file size exceeds max writable"); + goto error; + } + flags = TCL_WRITABLE; + if (mode & O_RDWR) + flags |= TCL_READABLE; + } else { + /* Read-only */ flags |= TCL_READABLE; + } + if (flags & TCL_READABLE) { if (z->isEncrypted) { if (z->numCompressedBytes < 12) { ZIPFS_ERROR(interp, "decryption failed: truncated decryption header"); @@ -4601,14 +4626,6 @@ ZipChannelOpen( goto error; } } - if (wr && !z->data && (z->numBytes > ZipFS.wrmax)) { - Tcl_SetErrno(EFBIG); - ZIPFS_POSIX_ERROR(interp, "file size exceeds max writable"); - goto error; - } - } else { - /* If truncating anyways, we do not care about error checking */ - flags = TCL_WRITABLE; } info = AllocateZipChannel(interp); @@ -4618,31 +4635,23 @@ ZipChannelOpen( info->zipFilePtr = z->zipFilePtr; info->zipEntryPtr = z; if (wr) { - /* - * Set up a writable channel. - */ + /* Set up a writable channel. */ - flags |= TCL_WRITABLE; - if (InitWritableChannel(interp, info, z, trunc) == TCL_ERROR) { + if (InitWritableChannel(interp, info, z, mode & O_TRUNC) == TCL_ERROR) { ckfree(info); goto error; } } else if (z->data) { - /* - * Set up a readable channel for direct data. - */ + /* Set up a readable channel for direct data. */ - flags |= TCL_READABLE; info->numBytes = z->numBytes; info->ubuf = z->data; info->ubufToFree = NULL; /* Not dynamically allocated */ - } - else { + } else { /* * Set up a readable channel. */ - flags |= TCL_READABLE; if (InitReadableChannel(interp, info, z) == TCL_ERROR) { ckfree(info); goto error; @@ -5155,27 +5164,9 @@ ZipFSOpenFileChannelProc( return NULL; } - int trunc = (mode & O_TRUNC) != 0; - int wr = (mode & (O_WRONLY | O_RDWR)) != 0; - - /* - * Check for unsupported modes. - */ - - if ((mode & O_APPEND) || ((ZipFS.wrmax <= 0) && wr)) { - Tcl_SetErrno(EACCES); - if (interp) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s not supported: %s", - mode & O_APPEND ? "append mode" : "write access", - Tcl_PosixError(interp))); - } - return NULL; - } - - return ZipChannelOpen(interp, Tcl_GetString(pathPtr), wr, trunc); + return ZipChannelOpen(interp, Tcl_GetString(pathPtr), mode); } - + /* *------------------------------------------------------------------------- * diff --git a/tests/zipfs.test b/tests/zipfs.test index 333426e..705f26f 100644 --- a/tests/zipfs.test +++ b/tests/zipfs.test @@ -1137,7 +1137,7 @@ namespace eval test_ns_zipfs { append result [gets $fd], set pos [tell $fd] append result $pos, - puts -nonewline $fd "xyz" + puts -nonewline $fd "0123456789" append result [gets $fd], seek $fd $pos append result [gets $fd], @@ -1172,12 +1172,12 @@ namespace eval test_ns_zipfs { } -body $body -result $expected {*}$args } - testzipfsrw store-r+ teststored.zip "aaaaaaaaaaaaaa,15,bbbbbbbbbbb,xyzbbbbbbbbbbb,ccccc\n|aaaaaaaaaaaaaa\nxyzbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+ - testzipfsrw store-w+ teststored.zip ",0,,xyz,yz|" abac-repeat.txt w+ -constraints bug-00018ec7a0 - testzipfsrw store-a+ teststored.zip ",60,,xyz,cc\nxyz|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nxyz" abac-repeat.txt a+ - testzipfsrw deflate-r+ testdeflated2.zip "aaaaaaaaaaaaaa,15,bbbbbbbbbbb,xyzbbbbbbbbbbb,ccccc\n|aaaaaaaaaaaaaa\nxyzbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+ - testzipfsrw deflate-w+ testdeflated2.zip ",0,,xyz,yz|" abac-repeat.txt w+ -constraints bug-00018ec7a0 - testzipfsrw deflate-a+ testdeflated2.zip ",60,,xyz,cc\nxyz|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nxyz" abac-repeat.txt a+ + testzipfsrw store-r+ teststored.zip "aaaaaaaaaaaaaa,15,bbbb,0123456789bbbb,ccccc\n|aaaaaaaaaaaaaa\n0123456789bbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+ + testzipfsrw store-w+ teststored.zip ",0,,0123456789,456789|0123456789" abac-repeat.txt w+ + testzipfsrw store-a+ teststored.zip ",60,,0123456789,456789|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n0123456789" abac-repeat.txt a+ + testzipfsrw deflate-r+ testdeflated2.zip "aaaaaaaaaaaaaa,15,bbbb,0123456789bbbb,ccccc\n|aaaaaaaaaaaaaa\n0123456789bbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+ + testzipfsrw deflate-w+ testdeflated2.zip ",0,,0123456789,456789|0123456789" abac-repeat.txt w+ + testzipfsrw deflate-a+ testdeflated2.zip ",60,,0123456789,456789|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n0123456789" abac-repeat.txt a+ test zipfs-rw-bug-f91ee30d33 "Bug f91ee30d33 - truncates at last read" -setup { mount [zippath test.zip] } -cleanup { |