diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2020-02-28 14:07:17 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2020-02-28 14:07:17 (GMT) |
commit | 35cf0ba42a45bd84f012db9a49c7634d93c1e18a (patch) | |
tree | 555a3eed5ad37908606345b86af2393246746e2c | |
parent | 4a07460db0fde8052d2d749cb79d56446d2eae48 (diff) | |
parent | 57b1d9531c5dc0a0a8c5d8055b2bf09f9e966842 (diff) | |
download | tcl-35cf0ba42a45bd84f012db9a49c7634d93c1e18a.zip tcl-35cf0ba42a45bd84f012db9a49c7634d93c1e18a.tar.gz tcl-35cf0ba42a45bd84f012db9a49c7634d93c1e18a.tar.bz2 |
Merge 8.7
-rw-r--r-- | generic/tcl.decls | 25 | ||||
-rw-r--r-- | generic/tcl.h | 6 | ||||
-rw-r--r-- | generic/tclDecls.h | 28 | ||||
-rw-r--r-- | generic/tclEncoding.c | 2 | ||||
-rw-r--r-- | generic/tclIO.c | 169 | ||||
-rw-r--r-- | generic/tclIOCmd.c | 6 | ||||
-rw-r--r-- | generic/tclIOGT.c | 110 | ||||
-rw-r--r-- | generic/tclIORChan.c | 38 | ||||
-rw-r--r-- | generic/tclIORTrans.c | 59 | ||||
-rw-r--r-- | generic/tclIOUtil.c | 28 | ||||
-rw-r--r-- | generic/tclInt.h | 2 | ||||
-rw-r--r-- | generic/tclMain.c | 2 | ||||
-rw-r--r-- | generic/tclPipe.c | 2 | ||||
-rw-r--r-- | generic/tclStubInit.c | 6 | ||||
-rw-r--r-- | generic/tclZipfs.c | 81 | ||||
-rw-r--r-- | generic/tclZlib.c | 13 | ||||
-rw-r--r-- | unix/tclUnixChan.c | 93 | ||||
-rw-r--r-- | unix/tclUnixPipe.c | 2 | ||||
-rw-r--r-- | unix/tclUnixSock.c | 6 | ||||
-rw-r--r-- | win/tclWinChan.c | 97 | ||||
-rw-r--r-- | win/tclWinConsole.c | 13 | ||||
-rw-r--r-- | win/tclWinPipe.c | 2 | ||||
-rw-r--r-- | win/tclWinSerial.c | 16 | ||||
-rw-r--r-- | win/tclWinSock.c | 12 |
24 files changed, 242 insertions, 576 deletions
diff --git a/generic/tcl.decls b/generic/tcl.decls index 63995be..8dfc2e4 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -312,9 +312,10 @@ declare 79 { declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData) } -declare 81 { - int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) -} +# Removed in 9.0: +#declare 81 { +# int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) +#} declare 82 { int Tcl_CommandComplete(const char *cmd) } @@ -1468,10 +1469,11 @@ declare 400 { Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) } -declare 401 { - Tcl_DriverCloseProc *Tcl_ChannelCloseProc( - const Tcl_ChannelType *chanTypePtr) -} +# Removed in 9.0 +#declare 401 { +# Tcl_DriverCloseProc *Tcl_ChannelCloseProc( +# const Tcl_ChannelType *chanTypePtr) +#} declare 402 { Tcl_DriverClose2Proc *Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr) @@ -1484,10 +1486,11 @@ declare 404 { Tcl_DriverOutputProc *Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr) } -declare 405 { - Tcl_DriverSeekProc *Tcl_ChannelSeekProc( - const Tcl_ChannelType *chanTypePtr) -} +# Removed in 9.0 +#declare 405 { +# Tcl_DriverSeekProc *Tcl_ChannelSeekProc( +# const Tcl_ChannelType *chanTypePtr) +#} declare 406 { Tcl_DriverSetOptionProc *Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr) diff --git a/generic/tcl.h b/generic/tcl.h index 003a28d..8dbf5fe 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -1226,10 +1226,6 @@ typedef void (Tcl_ScaleTimeProc) (Tcl_Time *timebuf, void *clientData); * Channel version tag. This was introduced in 8.3.2/8.4. */ -#define TCL_CHANNEL_VERSION_1 ((Tcl_ChannelTypeVersion) 0x1) -#define TCL_CHANNEL_VERSION_2 ((Tcl_ChannelTypeVersion) 0x2) -#define TCL_CHANNEL_VERSION_3 ((Tcl_ChannelTypeVersion) 0x3) -#define TCL_CHANNEL_VERSION_4 ((Tcl_ChannelTypeVersion) 0x4) #define TCL_CHANNEL_VERSION_5 ((Tcl_ChannelTypeVersion) 0x5) /* @@ -1298,7 +1294,7 @@ typedef struct Tcl_ChannelType { /* Version of the channel type. */ Tcl_DriverCloseProc *closeProc; /* Function to call to close the channel, or - * TCL_CLOSE2PROC if the close2Proc should be + * NULL or TCL_CLOSE2PROC if the close2Proc should be * used instead. */ Tcl_DriverInputProc *inputProc; /* Function to call for input on channel. */ diff --git a/generic/tclDecls.h b/generic/tclDecls.h index ba18baf..66ee818 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -255,8 +255,7 @@ EXTERN void Tcl_CallWhenDeleted(Tcl_Interp *interp, /* 80 */ EXTERN void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData); -/* 81 */ -EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan); +/* Slot 81 is reserved */ /* 82 */ EXTERN int Tcl_CommandComplete(const char *cmd); /* 83 */ @@ -1067,9 +1066,7 @@ EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion( /* 400 */ EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr); -/* 401 */ -EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc( - const Tcl_ChannelType *chanTypePtr); +/* Slot 401 is reserved */ /* 402 */ EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr); @@ -1079,9 +1076,7 @@ EXTERN Tcl_DriverInputProc * Tcl_ChannelInputProc( /* 404 */ EXTERN Tcl_DriverOutputProc * Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr); -/* 405 */ -EXTERN Tcl_DriverSeekProc * Tcl_ChannelSeekProc( - const Tcl_ChannelType *chanTypePtr); +/* Slot 405 is reserved */ /* 406 */ EXTERN Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr); @@ -1865,7 +1860,7 @@ typedef struct TclStubs { int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */ void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 79 */ void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, void *clientData); /* 80 */ - int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */ + void (*reserved81)(void); int (*tcl_CommandComplete) (const char *cmd); /* 82 */ char * (*tcl_Concat) (int argc, const char *const *argv); /* 83 */ size_t (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */ @@ -2193,11 +2188,11 @@ typedef struct TclStubs { const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */ Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */ Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */ - Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */ + void (*reserved401)(void); Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) (const Tcl_ChannelType *chanTypePtr); /* 402 */ Tcl_DriverInputProc * (*tcl_ChannelInputProc) (const Tcl_ChannelType *chanTypePtr); /* 403 */ Tcl_DriverOutputProc * (*tcl_ChannelOutputProc) (const Tcl_ChannelType *chanTypePtr); /* 404 */ - Tcl_DriverSeekProc * (*tcl_ChannelSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 405 */ + void (*reserved405)(void); Tcl_DriverSetOptionProc * (*tcl_ChannelSetOptionProc) (const Tcl_ChannelType *chanTypePtr); /* 406 */ Tcl_DriverGetOptionProc * (*tcl_ChannelGetOptionProc) (const Tcl_ChannelType *chanTypePtr); /* 407 */ Tcl_DriverWatchProc * (*tcl_ChannelWatchProc) (const Tcl_ChannelType *chanTypePtr); /* 408 */ @@ -2616,8 +2611,7 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_CallWhenDeleted) /* 79 */ #define Tcl_CancelIdleCall \ (tclStubsPtr->tcl_CancelIdleCall) /* 80 */ -#define Tcl_Close \ - (tclStubsPtr->tcl_Close) /* 81 */ +/* Slot 81 is reserved */ #define Tcl_CommandComplete \ (tclStubsPtr->tcl_CommandComplete) /* 82 */ #define Tcl_Concat \ @@ -3221,16 +3215,14 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_ChannelVersion) /* 399 */ #define Tcl_ChannelBlockModeProc \ (tclStubsPtr->tcl_ChannelBlockModeProc) /* 400 */ -#define Tcl_ChannelCloseProc \ - (tclStubsPtr->tcl_ChannelCloseProc) /* 401 */ +/* Slot 401 is reserved */ #define Tcl_ChannelClose2Proc \ (tclStubsPtr->tcl_ChannelClose2Proc) /* 402 */ #define Tcl_ChannelInputProc \ (tclStubsPtr->tcl_ChannelInputProc) /* 403 */ #define Tcl_ChannelOutputProc \ (tclStubsPtr->tcl_ChannelOutputProc) /* 404 */ -#define Tcl_ChannelSeekProc \ - (tclStubsPtr->tcl_ChannelSeekProc) /* 405 */ +/* Slot 405 is reserved */ #define Tcl_ChannelSetOptionProc \ (tclStubsPtr->tcl_ChannelSetOptionProc) /* 406 */ #define Tcl_ChannelGetOptionProc \ @@ -3933,4 +3925,6 @@ extern const TclStubs *tclStubsPtr; # endif #endif +#define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0) + #endif /* _TCLDECLS */ diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index ff327e0..418ac0f 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1638,7 +1638,7 @@ LoadEncodingFile( "invalid encoding file \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL); } - Tcl_Close(NULL, chan); + Tcl_CloseEx(NULL, chan, 0); return encoding; } diff --git a/generic/tclIO.c b/generic/tclIO.c index 9230fd3..fcf8085 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -374,11 +374,7 @@ ChanClose( Channel *chanPtr, Tcl_Interp *interp) { - if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { - return chanPtr->typePtr->closeProc(chanPtr->instanceData, interp); - } else { - return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); - } + return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); } static inline int @@ -490,18 +486,13 @@ ChanSeek( * type and non-NULL. */ - if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) { - return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData, - offset, mode, errnoPtr); - } - - if (offset<LONG_MIN || offset>LONG_MAX) { - *errnoPtr = EOVERFLOW; + if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) { + *errnoPtr = EINVAL; return -1; } - return Tcl_ChannelSeekProc(chanPtr->typePtr)(chanPtr->instanceData, - offset, mode, errnoPtr); + return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData, + offset, mode, errnoPtr); } static inline void @@ -677,7 +668,7 @@ TclFinalizeIOSubsystem(void) * interpreter will close the channel when it gets destroyed. */ - (void) Tcl_Close(NULL, (Tcl_Channel) chanPtr); + (void) Tcl_CloseEx(NULL, (Tcl_Channel) chanPtr, 0); } else { /* * The refcount is greater than zero, so flush the channel. @@ -1047,7 +1038,7 @@ DeleteChannelTable( statePtr->epoch++; if (statePtr->refCount-- <= 1) { if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { - (void) Tcl_Close(interp, (Tcl_Channel) chanPtr); + (void) Tcl_CloseEx(interp, (Tcl_Channel) chanPtr, 0); } } @@ -1270,11 +1261,11 @@ Tcl_UnregisterChannel( Tcl_Preserve(statePtr); if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { /* - * We don't want to re-enter Tcl_Close(). + * We don't want to re-enter Tcl_CloseEx(). */ if (!GotFlag(statePtr, CHANNEL_CLOSED)) { - if (Tcl_Close(interp, chan) != TCL_OK) { + if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { SetFlag(statePtr, CHANNEL_CLOSED); Tcl_Release(statePtr); return TCL_ERROR; @@ -1626,8 +1617,11 @@ Tcl_CreateChannel( assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc *)); assert(typePtr->typeName != NULL); - if (NULL == typePtr->closeProc) { - Tcl_Panic("channel type %s must define closeProc", typePtr->typeName); + if (Tcl_ChannelVersion(typePtr) != TCL_CHANNEL_VERSION_5) { + Tcl_Panic("channel type %s must be version TCL_CHANNEL_VERSION_5", typePtr->typeName); + } + if (typePtr->close2Proc == NULL) { + Tcl_Panic("channel type %s must define close2Proc", typePtr->typeName); } if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) { Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName); @@ -1638,9 +1632,6 @@ Tcl_CreateChannel( if (NULL == typePtr->watchProc) { Tcl_Panic("channel type %s must define watchProc", typePtr->typeName); } - if ((NULL!=typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) { - Tcl_Panic("channel type %s must define seekProc if defining wideSeekProc", typePtr->typeName); - } /* * JH: We could subsequently memset these to 0 to avoid the numerous @@ -2186,7 +2177,7 @@ Tcl_UnstackChannel( */ if (statePtr->refCount + 1 <= 1) { - if (Tcl_Close(interp, chan) != TCL_OK) { + if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { /* * TIP #219, Tcl Channel Reflection API. * "TclChanCaughtErrorBypass" is not required here, it was @@ -3134,7 +3125,7 @@ CloseChannel( ChannelFree(chanPtr); - return Tcl_Close(interp, (Tcl_Channel) downChanPtr); + return Tcl_CloseEx(interp, (Tcl_Channel) downChanPtr, 0); } /* @@ -3373,7 +3364,7 @@ Tcl_SpliceChannel( /* ARGSUSED */ int -Tcl_Close( +TclClose( Tcl_Interp *interp, /* Interpreter for errors. */ Tcl_Channel chan) /* The channel being closed. Must not be * referenced in any interpreter. */ @@ -3382,7 +3373,7 @@ Tcl_Close( * channel. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of real IO channel. */ - int result; /* Of calling FlushChannel. */ + int result = 0; /* Of calling FlushChannel. */ int flushcode; int stickyError; @@ -3483,12 +3474,7 @@ Tcl_Close( * it anymore and this will help avoid deadlocks on some channel types. */ - if (chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) { - result = chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, - TCL_CLOSE_READ); - } else { - result = 0; - } + (void)chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ); /* * The call to FlushChannel will flush any queued output and invoke the @@ -3548,19 +3534,17 @@ Tcl_Close( * * Tcl_CloseEx -- * - * Closes one side of a channel, read or write. + * Closes one side of a channel, read or write, close all. * * Results: * A standard Tcl result. * * Side effects: - * Closes one direction of the channel. + * Closes one direction of the channel, or do a full close. * * NOTE: * Tcl_CloseEx closes the specified direction of the channel as far as - * the user is concerned. The channel keeps existing however. You cannot - * calls this function to close the last possible direction of the - * channel. Use Tcl_Close for that. + * the user is concerned. If flags = 0, this is equivalent to Tcl_Close. * *---------------------------------------------------------------------- */ @@ -3580,18 +3564,26 @@ Tcl_CloseEx( return TCL_OK; } - /* TODO: assert flags validity ? */ - chanPtr = (Channel *) chan; statePtr = chanPtr->state; + if ((flags & (TCL_READABLE | TCL_WRITABLE)) == 0) { + return TclClose(interp, chan); + } + if ((flags & (TCL_READABLE | TCL_WRITABLE)) == (TCL_READABLE | TCL_WRITABLE)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "double-close of channels not supported by %ss", + chanPtr->typePtr->typeName)); + return TCL_ERROR; + } + /* * Does the channel support half-close anyway? Error if not. */ if (!chanPtr->typePtr->close2Proc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "half-close of channels not supported by %ss", + "half-close of channels not supported by %ss", chanPtr->typePtr->typeName)); return TCL_ERROR; } @@ -4214,12 +4206,12 @@ WillWrite( { int inputBuffered; - if ((Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) && - ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){ - int ignore; + if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) + ) && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){ + int ignore; - DiscardInputQueued(chanPtr->state, 0); - ChanSeek(chanPtr, -inputBuffered, SEEK_CUR, &ignore); + DiscardInputQueued(chanPtr->state, 0); + ChanSeek(chanPtr, -inputBuffered, SEEK_CUR, &ignore); } } @@ -4236,8 +4228,8 @@ WillRead( Tcl_SetErrno(EINVAL); return -1; } - if ((Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) - && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { + if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) + ) && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { /* * CAVEAT - The assumption here is that FlushChannel() will push out * the bytes of any writes that are in progress. Since this is a @@ -7000,7 +6992,8 @@ Tcl_Seek( * defined. This means that the channel does not support seeking. */ - if (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) { + if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) + ) { Tcl_SetErrno(EINVAL); return -1; } @@ -7164,7 +7157,8 @@ Tcl_Tell( * defined. This means that the channel does not support seeking. */ - if (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) { + if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) + ) { Tcl_SetErrno(EINVAL); return -1; } @@ -10488,14 +10482,6 @@ Tcl_ChannelVersion( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if ((chanTypePtr->version < TCL_CHANNEL_VERSION_2) - || (chanTypePtr->version > TCL_CHANNEL_VERSION_5)) { - /* - * In <v2 channel versions, the version field is occupied by the - * Tcl_DriverBlockModeProc - */ - return TCL_CHANNEL_VERSION_1; - } return chanTypePtr->version; } @@ -10519,43 +10505,12 @@ Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { - /* - * The v1 structure had the blockModeProc in a different place. - */ - return (Tcl_DriverBlockModeProc *) chanTypePtr->version; - } - return chanTypePtr->blockModeProc; } /* *---------------------------------------------------------------------- * - * Tcl_ChannelCloseProc -- - * - * Return the Tcl_DriverCloseProc of the channel type. - * - * Results: - * A pointer to the proc. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_DriverCloseProc * -Tcl_ChannelCloseProc( - const Tcl_ChannelType *chanTypePtr) - /* Pointer to channel type. */ -{ - return chanTypePtr->closeProc; -} - -/* - *---------------------------------------------------------------------- - * * Tcl_ChannelClose2Proc -- * * Return the Tcl_DriverClose2Proc of the channel type. @@ -10628,30 +10583,6 @@ Tcl_ChannelOutputProc( /* *---------------------------------------------------------------------- * - * Tcl_ChannelSeekProc -- - * - * Return the Tcl_DriverSeekProc of the channel type. - * - * Results: - * A pointer to the proc. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_DriverSeekProc * -Tcl_ChannelSeekProc( - const Tcl_ChannelType *chanTypePtr) - /* Pointer to channel type. */ -{ - return chanTypePtr->seekProc; -} - -/* - *---------------------------------------------------------------------- - * * Tcl_ChannelSetOptionProc -- * * Return the Tcl_DriverSetOptionProc of the channel type. @@ -10766,9 +10697,6 @@ Tcl_ChannelFlushProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { - return NULL; - } return chanTypePtr->flushProc; } @@ -10793,9 +10721,6 @@ Tcl_ChannelHandlerProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { - return NULL; - } return chanTypePtr->handlerProc; } @@ -10820,9 +10745,6 @@ Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_3) { - return NULL; - } return chanTypePtr->wideSeekProc; } @@ -10848,9 +10770,6 @@ Tcl_ChannelThreadActionProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { - if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_4) { - return NULL; - } return chanTypePtr->threadActionProc; } diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 2e492b8..e10be42 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -967,7 +967,7 @@ Tcl_ExecObjCmd( */ TclGetAndDetachPids(interp, chan); - if (Tcl_Close(interp, chan) != TCL_OK) { + if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { return TCL_ERROR; } return TCL_OK; @@ -999,7 +999,7 @@ Tcl_ExecObjCmd( * string. */ - result = Tcl_Close(interp, chan); + result = Tcl_CloseEx(interp, chan, 0); Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp)); /* @@ -1405,7 +1405,7 @@ AcceptCallbackProc( * the client socket - just close it. */ - Tcl_Close(NULL, chan); + Tcl_CloseEx(NULL, chan, 0); } } diff --git a/generic/tclIOGT.c b/generic/tclIOGT.c index 5f0f55e..e9c4fae 100644 --- a/generic/tclIOGT.c +++ b/generic/tclIOGT.c @@ -22,13 +22,11 @@ static int TransformBlockModeProc(ClientData instanceData, int mode); static int TransformCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int TransformInputProc(ClientData instanceData, char *buf, int toRead, int *errorCodePtr); static int TransformOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCodePtr); -static int TransformSeekProc(ClientData instanceData, long offset, - int mode, int *errorCodePtr); static int TransformSetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value); @@ -119,15 +117,15 @@ static inline void ResultAdd(ResultBuffer *r, unsigned char *buf, static const Tcl_ChannelType transformChannelType = { "transform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TransformCloseProc, /* Close proc. */ + NULL, /* Close proc. */ TransformInputProc, /* Input proc. */ TransformOutputProc, /* Output proc. */ - TransformSeekProc, /* Seek proc. */ + NULL, /* Seek proc. */ TransformSetOptionProc, /* Set option proc. */ TransformGetOptionProc, /* Get option proc. */ TransformWatchProc, /* Initialize notifier. */ TransformGetFileHandleProc, /* Get OS handles out of channel. */ - NULL, /* close2proc */ + TransformCloseProc, /* close2proc */ TransformBlockModeProc, /* Set blocking/nonblocking mode.*/ NULL, /* Flush proc. */ TransformNotifyProc, /* Handling of events bubbling up. */ @@ -533,10 +531,15 @@ TransformBlockModeProc( static int TransformCloseProc( ClientData instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + /* * Important: In this procedure 'dataPtr->self' already points to the * underlying channel. @@ -811,73 +814,6 @@ TransformOutputProc( /* *---------------------------------------------------------------------- * - * TransformSeekProc -- - * - * This procedure is called by the generic IO level to move the access - * point in a channel. - * - * Side effects: - * Moves the location at which the channel will be accessed in future - * operations. Flushes all transformation buffers, then forwards it to - * the underlying channel. - * - * Result: - * -1 if failed, the new position if successful. An output argument - * contains the POSIX error code if an error occurred, or zero. - * - *---------------------------------------------------------------------- - */ - -static int -TransformSeekProc( - ClientData instanceData, /* The channel to manipulate. */ - long offset, /* Size of movement. */ - int mode, /* How to move. */ - int *errorCodePtr) /* Location of error flag. */ -{ - TransformChannelData *dataPtr = (TransformChannelData *)instanceData; - Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); - const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); - Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); - - if ((offset == 0) && (mode == SEEK_CUR)) { - /* - * This is no seek but a request to tell the caller the current - * location. Simply pass the request down. - */ - - return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, - mode, errorCodePtr); - } - - /* - * It is a real request to change the position. Flush all data waiting for - * output and discard everything in the input buffers. Then pass the - * request down, unchanged. - */ - - PreserveData(dataPtr); - if (dataPtr->mode & TCL_WRITABLE) { - ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, - P_NO_PRESERVE); - } - - if (dataPtr->mode & TCL_READABLE) { - ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT, - P_NO_PRESERVE); - ResultClear(&dataPtr->result); - dataPtr->readIsFlushed = 0; - dataPtr->eofPending = 0; - } - ReleaseData(dataPtr); - - return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode, - errorCodePtr); -} - -/* - *---------------------------------------------------------------------- - * * TransformWideSeekProc -- * * This procedure is called by the generic IO level to move the access @@ -905,7 +841,6 @@ TransformWideSeekProc( TransformChannelData *dataPtr = (TransformChannelData *)instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); - Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); Tcl_DriverWideSeekProc *parentWideSeekProc = Tcl_ChannelWideSeekProc(parentType); ClientData parentData = Tcl_GetChannelInstanceData(parent); @@ -918,9 +853,10 @@ TransformWideSeekProc( if (parentWideSeekProc != NULL) { return parentWideSeekProc(parentData, offset, mode, errorCodePtr); + } else { + *errorCodePtr = EINVAL; + return -1; } - - return parentSeekProc(parentData, 0, mode, errorCodePtr); } /* @@ -948,25 +884,11 @@ TransformWideSeekProc( * If we have a wide seek capability, we should stick with that. */ - if (parentWideSeekProc != NULL) { - return parentWideSeekProc(parentData, offset, mode, errorCodePtr); - } - - /* - * We're transferring to narrow seeks at this point; this is a bit complex - * because we have to check whether the seek is possible first (i.e. - * whether we are losing information in truncating the bits of the - * offset). Luckily, there's a defined error for what happens when trying - * to go out of the representable range. - */ - - if (offset<LONG_MIN || offset>LONG_MAX) { - *errorCodePtr = EOVERFLOW; + if (parentWideSeekProc == NULL) { + *errorCodePtr = EINVAL; return -1; } - - return parentSeekProc(parentData, offset, - mode, errorCodePtr); + return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } /* diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index a460090..018c59f 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -32,7 +32,7 @@ */ static int ReflectClose(ClientData clientData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int ReflectInput(ClientData clientData, char *buf, int toRead, int *errorCodePtr); static int ReflectOutput(ClientData clientData, const char *buf, @@ -46,8 +46,6 @@ static int ReflectEventDelete(Tcl_Event *ev, ClientData cd); #endif static Tcl_WideInt ReflectSeekWide(ClientData clientData, Tcl_WideInt offset, int mode, int *errorCodePtr); -static int ReflectSeek(ClientData clientData, long offset, - int mode, int *errorCodePtr); static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); @@ -65,15 +63,15 @@ static void TimerRunWrite(ClientData clientData); static const Tcl_ChannelType tclRChannelType = { "tclrchannel", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - ReflectClose, /* Close channel, clean instance data */ + NULL, /* Close channel, clean instance data */ ReflectInput, /* Handle read request */ ReflectOutput, /* Handle write request */ - ReflectSeek, /* Move location of access point. NULL'able */ + NULL, ReflectSetOption, /* Set options. NULL'able */ ReflectGetOption, /* Get options. NULL'able */ ReflectWatch, /* Initialize notifier */ NULL, /* Get OS handle from the channel. NULL'able */ - NULL, /* No close2 support. NULL'able */ + ReflectClose, /* No close2 support. NULL'able */ ReflectBlock, /* Set blocking/nonblocking. NULL'able */ NULL, /* Flush channel. Not used by core. NULL'able */ NULL, /* Handle events. NULL'able */ @@ -81,7 +79,7 @@ static const Tcl_ChannelType tclRChannelType = { #if TCL_THREADS ReflectThread, /* thread action, tracking owner */ #else - NULL, /* thread action */ + (void *)-1, /* thread action */ #endif NULL /* truncate */ }; @@ -697,7 +695,6 @@ TclChanCreateObjCmd( clonePtr->blockModeProc = NULL; } if (!(methods & FLAG(METH_SEEK))) { - clonePtr->seekProc = NULL; clonePtr->wideSeekProc = NULL; } @@ -1153,7 +1150,8 @@ TclChanCaughtErrorBypass( static int ReflectClose( ClientData clientData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; int result; /* Result code for 'close' */ @@ -1163,6 +1161,10 @@ ReflectClose( Tcl_HashEntry *hPtr; /* Entry in the above map */ const Tcl_ChannelType *tctPtr; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + if (TclInThreadExit()) { /* * This call comes from TclFinalizeIOSystem. There are no @@ -1616,24 +1618,6 @@ ReflectSeekWide( newLoc = -1; goto stop; } - -static int -ReflectSeek( - ClientData clientData, - long offset, - int seekMode, - int *errorCodePtr) -{ - /* - * This function can be invoked from a transformation which is based on - * standard seeking, i.e. non-wide. Because of this we have to implement - * it, a dummy is not enough. We simply delegate the call to the wide - * routine. - */ - - return ReflectSeekWide(clientData, offset, seekMode, - errorCodePtr); -} /* *---------------------------------------------------------------------- diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index 0a68518..9e18a05 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -32,7 +32,7 @@ */ static int ReflectClose(ClientData clientData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int ReflectInput(ClientData clientData, char *buf, int toRead, int *errorCodePtr); static int ReflectOutput(ClientData clientData, const char *buf, @@ -41,8 +41,6 @@ static void ReflectWatch(ClientData clientData, int mask); static int ReflectBlock(ClientData clientData, int mode); static Tcl_WideInt ReflectSeekWide(ClientData clientData, Tcl_WideInt offset, int mode, int *errorCodePtr); -static int ReflectSeek(ClientData clientData, long offset, - int mode, int *errorCodePtr); static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); @@ -60,15 +58,15 @@ static int ReflectNotify(ClientData clientData, int mask); static const Tcl_ChannelType tclRTransformType = { "tclrtransform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel. */ - ReflectClose, /* Close channel, clean instance data. */ + NULL, /* Close channel, clean instance data. */ ReflectInput, /* Handle read request. */ ReflectOutput, /* Handle write request. */ - ReflectSeek, /* Move location of access point. */ + NULL, /* Move location of access point. */ ReflectSetOption, /* Set options. */ ReflectGetOption, /* Get options. */ ReflectWatch, /* Initialize notifier. */ ReflectHandle, /* Get OS handle from the channel. */ - NULL, /* No close2 support. NULL'able. */ + ReflectClose, /* No close2 support. NULL'able. */ ReflectBlock, /* Set blocking/nonblocking. */ NULL, /* Flush channel. Not used by core. * NULL'able. */ @@ -881,7 +879,8 @@ UnmarshallErrorResult( static int ReflectClose( ClientData clientData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; int errorCode, errorCodeSet = 0; @@ -892,6 +891,10 @@ ReflectClose( * in this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + if (TclInThreadExit()) { /* * This call comes from TclFinalizeIOSystem. There are no @@ -1329,18 +1332,6 @@ ReflectSeekWide( Channel *parent = (Channel *) rtPtr->parent; Tcl_WideInt curPos; /* Position on the device. */ - Tcl_DriverSeekProc *seekProc = - Tcl_ChannelSeekProc(Tcl_GetChannelType(rtPtr->parent)); - - /* - * Fail if the parent channel is not seekable. - */ - - if (seekProc == NULL) { - Tcl_SetErrno(EINVAL); - return -1; - } - /* * Check if we can leave out involving the Tcl level, i.e. transformation * handler. This is true for tell requests, and transformations which @@ -1384,16 +1375,12 @@ ReflectSeekWide( * non-NULL... */ - if (Tcl_ChannelWideSeekProc(parent->typePtr) != NULL) { - curPos = Tcl_ChannelWideSeekProc(parent->typePtr)(parent->instanceData, offset, - seekMode, errorCodePtr); - } else if (offset < LONG_MIN || offset > LONG_MAX) { - *errorCodePtr = EOVERFLOW; + if (Tcl_ChannelWideSeekProc(parent->typePtr) == NULL) { + *errorCodePtr = EINVAL; curPos = -1; } else { - curPos = Tcl_ChannelSeekProc(parent->typePtr)( - parent->instanceData, offset, seekMode, - errorCodePtr); + curPos = Tcl_ChannelWideSeekProc(parent->typePtr)(parent->instanceData, offset, + seekMode, errorCodePtr); } if (curPos == -1) { Tcl_SetErrno(*errorCodePtr); @@ -1403,24 +1390,6 @@ ReflectSeekWide( Tcl_Release(rtPtr); return curPos; } - -static int -ReflectSeek( - ClientData clientData, - long offset, - int seekMode, - int *errorCodePtr) -{ - /* - * This function can be invoked from a transformation which is based on - * standard seeking, i.e. non-wide. Because of this we have to implement - * it, a dummy is not enough. We simply delegate the call to the wide - * routine. - */ - - return ReflectSeekWide(clientData, offset, seekMode, - errorCodePtr); -} /* *---------------------------------------------------------------------- diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 5c0ce0b..26ff1d8 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -1733,7 +1733,7 @@ Tcl_FSEvalFileEx( if (encodingName != NULL) { if (Tcl_SetChannelOption(interp, chan, "-encoding", encodingName) != TCL_OK) { - Tcl_Close(interp,chan); + Tcl_CloseEx(interp,chan,0); return result; } } @@ -1746,7 +1746,7 @@ Tcl_FSEvalFileEx( */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { - Tcl_Close(interp, chan); + Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); @@ -1761,14 +1761,14 @@ Tcl_FSEvalFileEx( if (Tcl_ReadChars(chan, objPtr, -1, memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) { - Tcl_Close(interp, chan); + Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); goto end; } - if (Tcl_Close(interp, chan) != TCL_OK) { + if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { goto end; } @@ -1869,7 +1869,7 @@ TclNREvalFile( if (encodingName != NULL) { if (Tcl_SetChannelOption(interp, chan, "-encoding", encodingName) != TCL_OK) { - Tcl_Close(interp,chan); + Tcl_CloseEx(interp, chan, 0); return TCL_ERROR; } } @@ -1882,7 +1882,7 @@ TclNREvalFile( */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { - Tcl_Close(interp, chan); + Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); @@ -1898,7 +1898,7 @@ TclNREvalFile( if (Tcl_ReadChars(chan, objPtr, -1, memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) { - Tcl_Close(interp, chan); + Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); @@ -1906,7 +1906,7 @@ TclNREvalFile( return TCL_ERROR; } - if (Tcl_Close(interp, chan) != TCL_OK) { + if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { Tcl_DecrRefCount(objPtr); return TCL_ERROR; } @@ -2238,7 +2238,7 @@ Tcl_FSOpenFileChannel( "could not seek to end of file while opening \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } - Tcl_Close(NULL, retVal); + Tcl_CloseEx(NULL, retVal, 0); return NULL; } if (binary) { @@ -3248,11 +3248,11 @@ Tcl_LoadFile( } buffer = TclpLoadMemoryGetBuffer(interp, size); if (!buffer) { - Tcl_Close(interp, data); + Tcl_CloseEx(interp, data, 0); goto mustCopyToTempAnyway; } ret = Tcl_Read(data, (char *)buffer, size); - Tcl_Close(interp, data); + Tcl_CloseEx(interp, data, 0); ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr, &unloadProcPtr, flags); if (ret == TCL_OK && *handlePtr != NULL) { @@ -4251,7 +4251,7 @@ TclCrossFilesystemCopy( * Could not open an input channel. Why didn't the caller check this? */ - Tcl_Close(interp, out); + Tcl_CloseEx(interp, out, 0); goto done; } @@ -4268,8 +4268,8 @@ TclCrossFilesystemCopy( * If the copy failed, assume that copy channel left an error message. */ - Tcl_Close(interp, in); - Tcl_Close(interp, out); + Tcl_CloseEx(interp, in, 0); + Tcl_CloseEx(interp, out, 0); /* * Set modification date of copied file. diff --git a/generic/tclInt.h b/generic/tclInt.h index 4eb929a..15f6b54 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4099,7 +4099,7 @@ MODULE_SCOPE void TclProcessCreated(Tcl_Pid pid); MODULE_SCOPE TclProcessWaitStatus TclProcessWait(Tcl_Pid pid, int options, int *codePtr, Tcl_Obj **msgObjPtr, Tcl_Obj **errorObjPtr); - +MODULE_SCOPE int TclClose(Tcl_Interp *, Tcl_Channel chan); /* * TIP #508: [array default] */ diff --git a/generic/tclMain.c b/generic/tclMain.c index 16e2159..8b8daf3 100644 --- a/generic/tclMain.c +++ b/generic/tclMain.c @@ -250,7 +250,7 @@ Tcl_SourceRCFile( c = Tcl_OpenFileChannel(NULL, fullName, "r", 0); if (c != NULL) { - Tcl_Close(NULL, c); + Tcl_CloseEx(NULL, c, 0); if (Tcl_EvalFile(interp, fullName) != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { diff --git a/generic/tclPipe.c b/generic/tclPipe.c index 6c73f92..61a2080 100644 --- a/generic/tclPipe.c +++ b/generic/tclPipe.c @@ -351,7 +351,7 @@ TclCleanupChildren( Tcl_DecrRefCount(objPtr); } } - Tcl_Close(NULL, errorChan); + Tcl_CloseEx(NULL, errorChan, 0); } /* diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 48ff391..753b604 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -834,7 +834,7 @@ const TclStubs tclStubs = { Tcl_BadChannelOption, /* 78 */ Tcl_CallWhenDeleted, /* 79 */ Tcl_CancelIdleCall, /* 80 */ - Tcl_Close, /* 81 */ + 0, /* 81 */ Tcl_CommandComplete, /* 82 */ Tcl_Concat, /* 83 */ Tcl_ConvertElement, /* 84 */ @@ -1162,11 +1162,11 @@ const TclStubs tclStubs = { Tcl_ChannelName, /* 398 */ Tcl_ChannelVersion, /* 399 */ Tcl_ChannelBlockModeProc, /* 400 */ - Tcl_ChannelCloseProc, /* 401 */ + 0, /* 401 */ Tcl_ChannelClose2Proc, /* 402 */ Tcl_ChannelInputProc, /* 403 */ Tcl_ChannelOutputProc, /* 404 */ - Tcl_ChannelSeekProc, /* 405 */ + 0, /* 405 */ Tcl_ChannelSetOptionProc, /* 406 */ Tcl_ChannelGetOptionProc, /* 407 */ Tcl_ChannelWatchProc, /* 408 */ diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index fbbe1ed..afba76b 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -385,13 +385,11 @@ static int ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, static void ZipfsExitHandler(ClientData clientData); static void ZipfsSetup(void); static int ZipChannelClose(void *instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int ZipChannelGetFile(void *instanceData, int direction, void **handlePtr); static int ZipChannelRead(void *instanceData, char *buf, int toRead, int *errloc); -static int ZipChannelSeek(void *instanceData, long offset, - int mode, int *errloc); static Tcl_WideInt ZipChannelWideSeek(void *instanceData, Tcl_WideInt offset, int mode, int *errloc); static void ZipChannelWatchChannel(void *instanceData, @@ -444,15 +442,15 @@ static const Tcl_Filesystem zipfsFilesystem = { static Tcl_ChannelType ZipChannelType = { "zip", /* Type name. */ TCL_CHANNEL_VERSION_5, - ZipChannelClose, /* Close channel, clean instance data */ + NULL, /* Close channel, clean instance data */ ZipChannelRead, /* Handle read request */ ZipChannelWrite, /* Handle write request */ - ZipChannelSeek, /* Move location of access point, NULL'able */ + NULL, /* 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 */ + ZipChannelClose, /* 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 */ @@ -938,7 +936,7 @@ ZipFSCloseArchive( zf->ptrToFree = NULL; } if (zf->chan) { - Tcl_Close(interp, zf->chan); + Tcl_CloseEx(interp, zf->chan, 0); zf->chan = NULL; } } @@ -1141,7 +1139,7 @@ ZipFSOpenArchive( ZIPFS_POSIX_ERROR(interp, "file read error"); goto error; } - Tcl_Close(interp, zf->chan); + Tcl_CloseEx(interp, zf->chan, 0); zf->chan = NULL; } else { #ifdef _WIN32 @@ -2139,11 +2137,11 @@ ZipAddFile( #ifdef _WIN32 /* hopefully a directory */ if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_OK; } #endif /* _WIN32 */ - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } else { Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); @@ -2162,12 +2160,12 @@ ZipAddFile( len = Tcl_Read(in, buf, bufsize); if (len == TCL_IO_FAILURE) { if (nbyte == 0 && errno == EISDIR) { - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } if (len == 0) { @@ -2179,7 +2177,7 @@ ZipAddFile( if (Tcl_Seek(in, 0, SEEK_SET) == -1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("seek error on \"%s\": %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } pos[0] = Tcl_Tell(out); @@ -2190,7 +2188,7 @@ ZipAddFile( wrerr: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error on %s: %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } if ((len + pos[0]) & 3) { @@ -2224,7 +2222,7 @@ ZipAddFile( i); Tcl_AppendObjToErrorInfo(interp, eiPtr); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } ret = Tcl_GetObjResult(interp); @@ -2234,7 +2232,7 @@ ZipAddFile( i); Tcl_AppendObjToErrorInfo(interp, eiPtr); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } ch = (int) (r * 256); @@ -2253,7 +2251,7 @@ ZipAddFile( if (len != 12) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error on %s: %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } memcpy(keys0, keys, sizeof(keys0)); @@ -2271,7 +2269,7 @@ ZipAddFile( Tcl_SetObjResult(interp, Tcl_ObjPrintf( "compression init error on \"%s\"", path)); Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE_INIT", NULL); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } do { @@ -2280,7 +2278,7 @@ ZipAddFile( Tcl_SetObjResult(interp, Tcl_ObjPrintf( "read error on %s: %s", path, Tcl_PosixError(interp))); deflateEnd(&stream); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } stream.avail_in = len; @@ -2295,7 +2293,7 @@ ZipAddFile( "deflate error on %s", path)); Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE", NULL); deflateEnd(&stream); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } olen = sizeof(obuf) - stream.avail_out; @@ -2311,7 +2309,7 @@ ZipAddFile( Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); deflateEnd(&stream); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } nbytecompr += olen; @@ -2329,7 +2327,7 @@ ZipAddFile( } if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { seekErr: - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "seek error: %s", Tcl_PosixError(interp))); return TCL_ERROR; @@ -2341,7 +2339,7 @@ ZipAddFile( Tcl_SetObjResult(interp, Tcl_ObjPrintf( "read error on \"%s\": %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } else if (len == 0) { break; @@ -2357,7 +2355,7 @@ ZipAddFile( if (Tcl_Write(out, buf, len) != len) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } nbytecompr += len; @@ -2367,7 +2365,7 @@ ZipAddFile( pos[1] = Tcl_Tell(out); Tcl_TruncateChannel(out, pos[1]); } - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew); if (!isNew) { @@ -2585,7 +2583,7 @@ ZipFSMkZipOrImgObjCmd( Tcl_DecrRefCount(list); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); - Tcl_Close(interp, out); + Tcl_CloseEx(interp, out, 0); if (zf == &zf0) { ZipFSCloseArchive(interp, zf); } else { @@ -2618,7 +2616,7 @@ ZipFSMkZipOrImgObjCmd( if (!in) { memset(passBuf, 0, sizeof(passBuf)); Tcl_DecrRefCount(list); - Tcl_Close(interp, out); + Tcl_CloseEx(interp, out, 0); return TCL_ERROR; } i = Tcl_Seek(in, 0, SEEK_END); @@ -2628,8 +2626,8 @@ ZipFSMkZipOrImgObjCmd( Tcl_DecrRefCount(list); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s: %s", errMsg, Tcl_PosixError(interp))); - Tcl_Close(interp, out); - Tcl_Close(interp, in); + Tcl_CloseEx(interp, out, 0); + Tcl_CloseEx(interp, in, 0); return TCL_ERROR; } Tcl_Seek(in, 0, SEEK_SET); @@ -2651,7 +2649,7 @@ ZipFSMkZipOrImgObjCmd( goto cperr; } } - Tcl_Close(interp, in); + Tcl_CloseEx(interp, in, 0); } len = strlen(passBuf); if (len > 0) { @@ -2660,7 +2658,7 @@ ZipFSMkZipOrImgObjCmd( Tcl_DecrRefCount(list); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); - Tcl_Close(interp, out); + Tcl_CloseEx(interp, out, 0); return TCL_ERROR; } } @@ -2776,9 +2774,9 @@ ZipFSMkZipOrImgObjCmd( done: if (ret == TCL_OK) { - ret = Tcl_Close(interp, out); + ret = Tcl_CloseEx(interp, out, 0); } else { - Tcl_Close(interp, out); + Tcl_CloseEx(interp, out, 0); } Tcl_DecrRefCount(list); for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr; @@ -3332,11 +3330,16 @@ ZipFSTclLibraryObjCmd( static int ZipChannelClose( void *instanceData, - Tcl_Interp *dummy) /* Current interpreter. */ + Tcl_Interp *dummy, /* Current interpreter. */ + int flags) { ZipChannel *info = (ZipChannel *)instanceData; (void)dummy; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + if (info->iscompr && info->ubuf) { Tcl_Free(info->ubuf); info->ubuf = NULL; @@ -3562,16 +3565,6 @@ ZipChannelWideSeek( info->numRead = (size_t) offset; return info->numRead; } - -static int -ZipChannelSeek( - void *instanceData, - long offset, - int mode, - int *errloc) -{ - return ZipChannelWideSeek(instanceData, offset, mode, errloc); -} /* *------------------------------------------------------------------------- diff --git a/generic/tclZlib.c b/generic/tclZlib.c index d520739..4a91e26 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -160,7 +160,7 @@ typedef struct { static Tcl_CmdDeleteProc ZlibStreamCmdDelete; static Tcl_DriverBlockModeProc ZlibTransformBlockMode; -static Tcl_DriverCloseProc ZlibTransformClose; +static Tcl_DriverClose2Proc ZlibTransformClose; static Tcl_DriverGetHandleProc ZlibTransformGetHandle; static Tcl_DriverGetOptionProc ZlibTransformGetOption; static Tcl_DriverHandlerProc ZlibTransformEventHandler; @@ -205,7 +205,7 @@ static void ZlibTransformTimerRun(void *clientData); static const Tcl_ChannelType zlibChannelType = { "zlib", TCL_CHANNEL_VERSION_5, - ZlibTransformClose, + NULL, ZlibTransformInput, ZlibTransformOutput, NULL, /* seekProc */ @@ -213,7 +213,7 @@ static const Tcl_ChannelType zlibChannelType = { ZlibTransformGetOption, ZlibTransformWatch, ZlibTransformGetHandle, - NULL, /* close2Proc */ + ZlibTransformClose, /* close2Proc */ ZlibTransformBlockMode, NULL, /* flushProc */ ZlibTransformEventHandler, @@ -2905,12 +2905,17 @@ ZlibStreamHeaderCmd( static int ZlibTransformClose( void *instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ZlibChannelData *cd = (ZlibChannelData *)instanceData; int e, result = TCL_OK; size_t written; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + /* * Delete the support timer. */ diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 2314ba3..7478627 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -121,15 +121,13 @@ typedef struct { static int FileBlockModeProc(void *instanceData, int mode); static int FileCloseProc(void *instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int FileGetHandleProc(void *instanceData, int direction, void **handlePtr); static int FileInputProc(void *instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCode); -static int FileSeekProc(void *instanceData, long offset, - int mode, int *errorCode); static int FileTruncateProc(void *instanceData, Tcl_WideInt length); static Tcl_WideInt FileWideSeekProc(void *instanceData, @@ -137,7 +135,7 @@ static Tcl_WideInt FileWideSeekProc(void *instanceData, static void FileWatchProc(void *instanceData, int mask); #ifdef SUPPORTS_TTY static int TtyCloseProc(void *instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr); static int TtyGetOptionProc(void *instanceData, Tcl_Interp *interp, const char *optionName, @@ -161,15 +159,15 @@ static int TtySetOptionProc(void *instanceData, static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - FileCloseProc, /* Close proc. */ + NULL, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ - FileSeekProc, /* Seek proc. */ + NULL, NULL, /* Set option proc. */ NULL, /* Get option proc. */ FileWatchProc, /* Initialize notifier. */ FileGetHandleProc, /* Get OS handles out of channel. */ - NULL, /* close2proc. */ + FileCloseProc, /* close2proc. */ FileBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -187,7 +185,7 @@ static const Tcl_ChannelType fileChannelType = { static const Tcl_ChannelType ttyChannelType = { "tty", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TtyCloseProc, /* Close proc. */ + NULL, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -195,7 +193,7 @@ static const Tcl_ChannelType ttyChannelType = { TtyGetOptionProc, /* Get option proc. */ FileWatchProc, /* Initialize notifier. */ FileGetHandleProc, /* Get OS handles out of channel. */ - NULL, /* close2proc. */ + TtyCloseProc, /* close2proc. */ FileBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -353,12 +351,17 @@ FileOutputProc( static int FileCloseProc( void *instanceData, /* File state. */ - Tcl_Interp *dummy) /* For error reporting - unused. */ + Tcl_Interp *dummy, /* For error reporting - unused. */ + int flags) { FileState *fsPtr = (FileState *)instanceData; int errorCode = 0; (void)dummy; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + Tcl_DeleteFileHandler(fsPtr->fd); /* @@ -379,10 +382,14 @@ FileCloseProc( static int TtyCloseProc( void *instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { TtyState *ttyPtr = (TtyState*)instanceData; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } /* * If we've been asked by the user to drain or flush, do so now. */ @@ -411,73 +418,13 @@ TtyCloseProc( * Delegate to close for files. */ - return FileCloseProc(instanceData, interp); + return FileCloseProc(instanceData, interp, flags); } #endif /* SUPPORTS_TTY */ /* *---------------------------------------------------------------------- * - * FileSeekProc -- - * - * This function is called by the generic IO level to move the access - * point in a file based channel. - * - * Results: - * -1 if failed, the new position if successful. An output argument - * contains the POSIX error code if an error occurred, or zero. - * - * Side effects: - * Moves the location at which the channel will be accessed in future - * operations. - * - *---------------------------------------------------------------------- - */ - -static int -FileSeekProc( - void *instanceData, /* File state. */ - long offset, /* Offset to seek to. */ - int mode, /* Relative to where should we seek? Can be - * one of SEEK_START, SEEK_SET or SEEK_END. */ - int *errorCodePtr) /* To store error code. */ -{ - FileState *fsPtr = (FileState *)instanceData; - Tcl_WideInt oldLoc, newLoc; - - /* - * Save our current place in case we need to roll-back the seek. - */ - - oldLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) 0, SEEK_CUR); - if (oldLoc == -1) { - /* - * Bad things are happening. Error out... - */ - - *errorCodePtr = errno; - return -1; - } - - newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode); - - /* - * Check for expressability in our return type, and roll-back otherwise. - */ - - if (newLoc > INT_MAX) { - *errorCodePtr = EOVERFLOW; - TclOSseek(fsPtr->fd, (Tcl_SeekOffset) oldLoc, SEEK_SET); - return -1; - } else { - *errorCodePtr = (newLoc == -1) ? errno : 0; - } - return (int) newLoc; -} - -/* - *---------------------------------------------------------------------- - * * FileWideSeekProc -- * * This function is called by the generic IO level to move the access @@ -1738,7 +1685,7 @@ TclpOpenFileChannel( if (Tcl_SetChannelOption(interp, fsPtr->fileState.channel, "-translation", translation) != TCL_OK) { - Tcl_Close(NULL, fsPtr->fileState.channel); + Tcl_CloseEx(NULL, fsPtr->fileState.channel, 0); return NULL; } } diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 55fd03d..a0445a2 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -69,7 +69,7 @@ static int SetupStdFile(TclFile file, int type); static const Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TCL_CLOSE2PROC, /* Close proc. */ + NULL, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ NULL, /* Seek proc. */ diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 0fa4edf..f72a888 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -157,7 +157,7 @@ static void WrapNotify(void *clientData, int mask); static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TcpCloseProc, /* Close proc. */ + NULL, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -1419,7 +1419,7 @@ Tcl_OpenTcpClient( statePtr, TCL_READABLE | TCL_WRITABLE); if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation", "auto crlf") == TCL_ERROR) { - Tcl_Close(NULL, statePtr->channel); + Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; @@ -1486,7 +1486,7 @@ TclpMakeTcpClientChannelMode( statePtr, mode); if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf") == TCL_ERROR) { - Tcl_Close(NULL, statePtr->channel); + Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; diff --git a/win/tclWinChan.c b/win/tclWinChan.c index 23a3545..aa002f3 100644 --- a/win/tclWinChan.c +++ b/win/tclWinChan.c @@ -76,7 +76,7 @@ static int FileBlockProc(ClientData instanceData, int mode); static void FileChannelExitHandler(ClientData clientData); static void FileCheckProc(ClientData clientData, int flags); static int FileCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int FileEventProc(Tcl_Event *evPtr, int flags); static int FileGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); @@ -85,8 +85,6 @@ static int FileInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); -static int FileSeekProc(ClientData instanceData, long offset, - int mode, int *errorCode); static Tcl_WideInt FileWideSeekProc(ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCode); static void FileSetupProc(ClientData clientData, int flags); @@ -105,15 +103,15 @@ static int NativeIsComPort(const WCHAR *nativeName); static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - FileCloseProc, /* Close proc. */ + NULL, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ - FileSeekProc, /* Seek proc. */ + NULL, NULL, /* Set option proc. */ NULL, /* Get option proc. */ FileWatchProc, /* Set up the notifier to watch the channel. */ FileGetHandleProc, /* Get an OS handle from channel. */ - NULL, /* close2proc. */ + FileCloseProc, /* close2proc. */ FileBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -390,7 +388,8 @@ FileBlockProc( static int FileCloseProc( ClientData instanceData, /* Pointer to FileInfo structure. */ - Tcl_Interp *dummy) /* Not used. */ + Tcl_Interp *dummy, /* Not used. */ + int flags) { FileInfo *fileInfoPtr = (FileInfo *)instanceData; FileInfo *infoPtr; @@ -398,6 +397,10 @@ FileCloseProc( int errorCode = 0; (void)dummy; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + /* * Remove the file from the watch list. */ @@ -446,84 +449,6 @@ FileCloseProc( /* *---------------------------------------------------------------------- * - * FileSeekProc -- - * - * Seeks on a file-based channel. Returns the new position. - * - * Results: - * -1 if failed, the new position if successful. If failed, it also sets - * *errorCodePtr to the error code. - * - * Side effects: - * Moves the location at which the channel will be accessed in future - * operations. - * - *---------------------------------------------------------------------- - */ - -static int -FileSeekProc( - ClientData instanceData, /* File state. */ - long offset, /* Offset to seek to. */ - int mode, /* Relative to where should we seek? */ - int *errorCodePtr) /* To store error code. */ -{ - FileInfo *infoPtr = (FileInfo *)instanceData; - LONG newPos, newPosHigh, oldPos, oldPosHigh; - DWORD moveMethod; - - *errorCodePtr = 0; - if (mode == SEEK_SET) { - moveMethod = FILE_BEGIN; - } else if (mode == SEEK_CUR) { - moveMethod = FILE_CURRENT; - } else { - moveMethod = FILE_END; - } - - /* - * Save our current place in case we need to roll-back the seek. - */ - - oldPosHigh = 0; - oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); - if (oldPos == (LONG) INVALID_SET_FILE_POINTER) { - DWORD winError = GetLastError(); - - if (winError != NO_ERROR) { - TclWinConvertError(winError); - *errorCodePtr = errno; - return -1; - } - } - - newPosHigh = (offset < 0 ? -1 : 0); - newPos = SetFilePointer(infoPtr->handle, offset, &newPosHigh, moveMethod); - if (newPos == (LONG) INVALID_SET_FILE_POINTER) { - DWORD winError = GetLastError(); - - if (winError != NO_ERROR) { - TclWinConvertError(winError); - *errorCodePtr = errno; - return -1; - } - } - - /* - * Check for expressability in our return type, and roll-back otherwise. - */ - - if (newPosHigh != 0) { - *errorCodePtr = EOVERFLOW; - SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN); - return -1; - } - return (int) newPos; -} - -/* - *---------------------------------------------------------------------- - * * FileWideSeekProc -- * * Seeks on a file-based channel. Returns the new position. @@ -1320,7 +1245,7 @@ TclpGetDefaultStdChannel( if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK || Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK || Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) { - Tcl_Close(NULL, channel); + Tcl_CloseEx(NULL, channel, 0); return (Tcl_Channel) NULL; } return channel; diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index b92be89..58082d7 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -142,7 +142,7 @@ static int ConsoleBlockModeProc(ClientData instanceData, int mode); static void ConsoleCheckProc(ClientData clientData, int flags); static int ConsoleCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int ConsoleEventProc(Tcl_Event *evPtr, int flags); static void ConsoleExitHandler(ClientData clientData); static int ConsoleGetHandleProc(ClientData instanceData, @@ -180,7 +180,7 @@ static BOOL WriteConsoleBytes(HANDLE hConsole, static const Tcl_ChannelType consoleChannelType = { "console", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - ConsoleCloseProc, /* Close proc. */ + NULL, /* Close proc. */ ConsoleInputProc, /* Input proc. */ ConsoleOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -188,7 +188,7 @@ static const Tcl_ChannelType consoleChannelType = { ConsoleGetOptionProc, /* Get option proc. */ ConsoleWatchProc, /* Set up notifier to watch the channel. */ ConsoleGetHandleProc, /* Get an OS handle from channel. */ - NULL, /* close2proc. */ + ConsoleCloseProc, /* close2proc. */ ConsoleBlockModeProc, /* Set blocking or non-blocking mode. */ NULL, /* Flush proc. */ NULL, /* Handler proc. */ @@ -537,7 +537,8 @@ ConsoleBlockModeProc( static int ConsoleCloseProc( ClientData instanceData, /* Pointer to ConsoleInfo structure. */ - Tcl_Interp *dummy) /* For error reporting. */ + Tcl_Interp *dummy, /* For error reporting. */ + int flags) { ConsoleInfo *consolePtr = (ConsoleInfo *)instanceData; int errorCode = 0; @@ -545,6 +546,10 @@ ConsoleCloseProc( ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); (void)dummy; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + /* * Clean up the background thread if necessary. Note that this must be * done before we can close the file, since the thread may be blocking diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c index 4d2b20a..d21425b 100644 --- a/win/tclWinPipe.c +++ b/win/tclWinPipe.c @@ -203,7 +203,7 @@ static void PipeThreadActionProc(ClientData instanceData, static const Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TCL_CLOSE2PROC, /* Close proc. */ + NULL, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ NULL, /* Seek proc. */ diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c index bcc7983..e529f77 100644 --- a/win/tclWinSerial.c +++ b/win/tclWinSerial.c @@ -168,7 +168,7 @@ static COMMTIMEOUTS no_timeout = { static int SerialBlockProc(ClientData instanceData, int mode); static void SerialCheckProc(ClientData clientData, int flags); static int SerialCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int SerialEventProc(Tcl_Event *evPtr, int flags); static void SerialExitHandler(ClientData clientData); static int SerialGetHandleProc(ClientData instanceData, @@ -204,7 +204,7 @@ static int SerialBlockingWrite(SerialInfo *infoPtr, LPVOID buf, static const Tcl_ChannelType serialChannelType = { "serial", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - SerialCloseProc, /* Close proc. */ + NULL, /* Close proc. */ SerialInputProc, /* Input proc. */ SerialOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -212,7 +212,7 @@ static const Tcl_ChannelType serialChannelType = { SerialGetOptionProc, /* Get option proc. */ SerialWatchProc, /* Set up notifier to watch the channel. */ SerialGetHandleProc, /* Get an OS handle from channel. */ - NULL, /* close2proc. */ + SerialCloseProc, /* close2proc. */ SerialBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -606,15 +606,19 @@ SerialBlockProc( static int SerialCloseProc( ClientData instanceData, /* Pointer to SerialInfo structure. */ - Tcl_Interp *dummy) /* For error reporting. */ + Tcl_Interp *dummy, /* For error reporting. */ + int flags) { SerialInfo *serialPtr = (SerialInfo *) instanceData; - int errorCode, result = 0; + int errorCode = 0, result = 0; SerialInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); (void)dummy; - errorCode = 0; + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } + if (serialPtr->validMask & TCL_READABLE) { PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR); diff --git a/win/tclWinSock.c b/win/tclWinSock.c index c6d5501..a1eaa18 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -280,7 +280,7 @@ static Tcl_DriverGetHandleProc TcpGetHandleProc; static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TcpCloseProc, /* Close proc. */ + NULL, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -2108,11 +2108,11 @@ Tcl_OpenTcpClient( statePtr, (TCL_READABLE | TCL_WRITABLE)); if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf")) { - Tcl_Close(NULL, statePtr->channel); + Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } else if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel, "-eofchar", "")) { - Tcl_Close(NULL, statePtr->channel); + Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; @@ -2360,7 +2360,7 @@ Tcl_OpenTcpServerEx( SendSelectMessage(tsdPtr, SELECT, statePtr); if (Tcl_SetChannelOption(interp, statePtr->channel, "-eofchar", "") == TCL_ERROR) { - Tcl_Close(NULL, statePtr->channel); + Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; @@ -2433,12 +2433,12 @@ TcpAccept( newInfoPtr, (TCL_READABLE | TCL_WRITABLE)); if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation", "auto crlf") == TCL_ERROR) { - Tcl_Close(NULL, newInfoPtr->channel); + Tcl_CloseEx(NULL, newInfoPtr->channel, 0); return; } if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-eofchar", "") == TCL_ERROR) { - Tcl_Close(NULL, newInfoPtr->channel); + Tcl_CloseEx(NULL, newInfoPtr->channel, 0); return; } |