Index: generic/tcl.decls ================================================================== --- generic/tcl.decls +++ generic/tcl.decls @@ -297,11 +297,11 @@ ClientData clientData) } declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, ClientData clientData) } -declare 81 { +declare 81 {deprecated {Use Tcl_CloseEx}} { int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) } declare 82 { int Tcl_CommandComplete(const char *cmd) } @@ -1413,11 +1413,11 @@ } declare 400 { Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) } -declare 401 { +declare 401 {deprecated {Use Tcl_ChannelClose2Proc}} { Tcl_DriverCloseProc *Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr) } declare 402 { Tcl_DriverClose2Proc *Tcl_ChannelClose2Proc( @@ -1429,11 +1429,11 @@ } declare 404 { Tcl_DriverOutputProc *Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr) } -declare 405 { +declare 405 {deprecated {Use Tcl_ChannelWideSeekProc}} { Tcl_DriverSeekProc *Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr) } declare 406 { Tcl_DriverSetOptionProc *Tcl_ChannelSetOptionProc( Index: generic/tcl.h ================================================================== --- generic/tcl.h +++ generic/tcl.h @@ -1398,14 +1398,16 @@ /* * Channel version tag. This was introduced in 8.3.2/8.4. */ +#ifndef TCL_NO_DEPRECATED #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) +#endif #define TCL_CHANNEL_VERSION_5 ((Tcl_ChannelTypeVersion) 0x5) /* * TIP #218: Channel Actions, Ids for Tcl_DriverThreadActionProc. */ @@ -1470,11 +1472,11 @@ * type. */ Tcl_ChannelTypeVersion version; /* 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. */ Tcl_DriverOutputProc *outputProc; /* Function to call for output on channel. */ Index: generic/tclDecls.h ================================================================== --- generic/tclDecls.h +++ generic/tclDecls.h @@ -286,11 +286,12 @@ ClientData clientData); /* 80 */ EXTERN void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, ClientData clientData); /* 81 */ -EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan); +TCL_DEPRECATED("Use Tcl_CloseEx") +int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan); /* 82 */ EXTERN int Tcl_CommandComplete(const char *cmd); /* 83 */ EXTERN char * Tcl_Concat(int argc, const char *const *argv); /* 84 */ @@ -1204,11 +1205,12 @@ const Tcl_ChannelType *chanTypePtr); /* 400 */ EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr); /* 401 */ -EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc( +TCL_DEPRECATED("Use Tcl_ChannelClose2Proc") +Tcl_DriverCloseProc * Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr); /* 402 */ EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr); /* 403 */ @@ -1216,11 +1218,12 @@ const Tcl_ChannelType *chanTypePtr); /* 404 */ EXTERN Tcl_DriverOutputProc * Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr); /* 405 */ -EXTERN Tcl_DriverSeekProc * Tcl_ChannelSeekProc( +TCL_DEPRECATED("Use Tcl_ChannelWideSeekProc") +Tcl_DriverSeekProc * Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr); /* 406 */ EXTERN Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr); /* 407 */ @@ -2025,11 +2028,11 @@ TCL_DEPRECATED_API("No longer in use, changed to macro") void (*tcl_BackgroundError) (Tcl_Interp *interp); /* 76 */ TCL_DEPRECATED_API("Use Tcl_UtfBackslash") char (*tcl_Backslash) (const char *src, int *readPtr); /* 77 */ int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */ void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */ void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */ - int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */ + TCL_DEPRECATED_API("Use Tcl_CloseEx") int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */ int (*tcl_CommandComplete) (const char *cmd); /* 82 */ char * (*tcl_Concat) (int argc, const char *const *argv); /* 83 */ int (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */ int (*tcl_ConvertCountedElement) (const char *src, int length, char *dst, int flags); /* 85 */ int (*tcl_CreateAlias) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, const char *const *argv); /* 86 */ @@ -2353,15 +2356,15 @@ Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */ int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */ 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 */ + TCL_DEPRECATED_API("Use Tcl_ChannelClose2Proc") Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */ 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 */ + TCL_DEPRECATED_API("Use Tcl_ChannelWideSeekProc") Tcl_DriverSeekProc * (*tcl_ChannelSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 405 */ 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 */ Tcl_DriverGetHandleProc * (*tcl_ChannelGetHandleProc) (const Tcl_ChannelType *chanTypePtr); /* 409 */ Tcl_DriverFlushProc * (*tcl_ChannelFlushProc) (const Tcl_ChannelType *chanTypePtr); /* 410 */ @@ -4168,7 +4171,12 @@ #define Tcl_EvalObj(interp, objPtr) \ Tcl_EvalObjEx(interp, objPtr, 0) #undef Tcl_GlobalEvalObj #define Tcl_GlobalEvalObj(interp, objPtr) \ Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL) + +#if defined(TCL_NO_DEPRECATED) && defined(USE_TCL_STUBS) +#undef Tcl_Close +#define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0) +#endif #endif /* _TCLDECLS */ Index: generic/tclIO.c ================================================================== --- generic/tclIO.c +++ generic/tclIO.c @@ -372,15 +372,16 @@ static inline int ChanClose( Channel *chanPtr, Tcl_Interp *interp) { - if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { +#ifndef TCL_NO_DEPRECATED + if ((chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) && (chanPtr->typePtr->closeProc != NULL)) { return chanPtr->typePtr->closeProc(chanPtr->instanceData, interp); - } else { - return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); } +#endif + return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); } static inline int ChanCloseHalf( Channel *chanPtr, @@ -488,22 +489,27 @@ /* * Note that we prefer the wideSeekProc if that field is available in the * type and non-NULL. */ - if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) { + if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) { +#ifndef TCL_NO_DEPRECATED + if (offsetLONG_MAX) { + *errnoPtr = EOVERFLOW; + return -1; + } + + return Tcl_ChannelSeekProc(chanPtr->typePtr)(chanPtr->instanceData, + offset, mode, errnoPtr); +#else + *errnoPtr = EINVAL; + return -1; +#endif + } + return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData, offset, mode, errnoPtr); - } - - if (offsetLONG_MAX) { - *errnoPtr = EOVERFLOW; - return -1; - } - - return Tcl_ChannelSeekProc(chanPtr->typePtr)(chanPtr->instanceData, - offset, mode, errnoPtr); } static inline void ChanThreadAction( Channel *chanPtr, @@ -1623,25 +1629,36 @@ * as well. */ 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); +#ifndef TCL_NO_DEPRECATED + if (((NULL == typePtr->closeProc) || (TCL_CLOSE2PROC == typePtr->closeProc)) && (typePtr->close2Proc == NULL)) { + Tcl_Panic("channel type %s must define closeProc or close2Proc", typePtr->typeName); } +#else + 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); + } +#endif if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) { Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName); } if ((TCL_WRITABLE & mask) && (NULL == typePtr->outputProc)) { Tcl_Panic("channel type %s must define outputProc when used for writer channel", typePtr->typeName); } if (NULL == typePtr->watchProc) { Tcl_Panic("channel type %s must define watchProc", typePtr->typeName); } - if ((NULL!=typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) { +#ifndef TCL_NO_DEPRECATED + if ((NULL != typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) { Tcl_Panic("channel type %s must define seekProc if defining wideSeekProc", typePtr->typeName); } +#endif /* * JH: We could subsequently memset these to 0 to avoid the numerous * assignments to 0/NULL below. */ @@ -3379,11 +3396,11 @@ { CloseCallback *cbPtr; /* Iterate over close callbacks for this * 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; if (chan == NULL) { return TCL_OK; @@ -3480,16 +3497,18 @@ /* * If this channel supports it, close the read side, since we don't need * 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; +#ifndef TCL_NO_DEPRECATED + if ((chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) || (chanPtr->typePtr->closeProc == NULL)) { + /* If this half-close fails, just continue the full close */ + (void)chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ); } +#else + (void)chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ); +#endif /* * The call to FlushChannel will flush any queued output and invoke the * close function of the channel driver, or it will set up the channel to * be flushed and closed asynchronously. @@ -3545,23 +3564,21 @@ /* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */ /* ARGSUSED */ @@ -3577,22 +3594,30 @@ if (chan == NULL) { return TCL_OK; } - /* TODO: assert flags validity ? */ - chanPtr = (Channel *) chan; statePtr = chanPtr->state; + + if ((flags & (TCL_READABLE | TCL_WRITABLE)) == 0) { + return Tcl_Close(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; } /* @@ -4210,16 +4235,19 @@ WillWrite( Channel *chanPtr) { int inputBuffered; - if ((Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) && - ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){ - int ignore; + if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) +#ifndef TCL_NO_DEPRECATED + || (Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) +#endif + ) && ((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); } } static int WillRead( @@ -4232,12 +4260,15 @@ DiscardInputQueued(chanPtr->state, 0); Tcl_SetErrno(EINVAL); return -1; } - if ((Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) - && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { + if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL) +#ifndef TCL_NO_DEPRECATED + || (Tcl_ChannelSeekProc(chanPtr->typePtr) != NULL) +#endif + ) && (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 * seekable channel, we assume it is not one that can block and force * bg flushing. Channels we know that can do that - sockets, pipes - @@ -6992,11 +7023,15 @@ /* * Disallow seek on channels whose type does not have a seek procedure * defined. This means that the channel does not support seeking. */ - if (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) { + if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) +#ifndef TCL_NO_DEPRECATED + && (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) +#endif + ) { Tcl_SetErrno(EINVAL); return -1; } /* @@ -7156,11 +7191,15 @@ /* * Disallow tell on channels whose type does not have a seek procedure * defined. This means that the channel does not support seeking. */ - if (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) { + if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) +#ifndef TCL_NO_DEPRECATED + && (Tcl_ChannelSeekProc(chanPtr->typePtr) == NULL) +#endif + ) { Tcl_SetErrno(EINVAL); return -1; } /* @@ -10494,18 +10533,20 @@ Tcl_ChannelTypeVersion Tcl_ChannelVersion( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if ((chanTypePtr->version < TCL_CHANNEL_VERSION_2) || (chanTypePtr->version > TCL_CHANNEL_VERSION_5)) { /* * In version; } /* *---------------------------------------------------------------------- @@ -10525,17 +10566,18 @@ Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { /* * The v1 structure had the blockModeProc in a different place. */ return (Tcl_DriverBlockModeProc *) chanTypePtr->version; } - +#endif return chanTypePtr->blockModeProc; } /* *---------------------------------------------------------------------- @@ -10551,17 +10593,19 @@ * None. * *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED Tcl_DriverCloseProc * Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->closeProc; } +#endif /* *---------------------------------------------------------------------- * * Tcl_ChannelClose2Proc -- @@ -10647,17 +10691,19 @@ * None. * *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED Tcl_DriverSeekProc * Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->seekProc; } +#endif /* *---------------------------------------------------------------------- * * Tcl_ChannelSetOptionProc -- @@ -10772,13 +10818,15 @@ Tcl_DriverFlushProc * Tcl_ChannelFlushProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { return NULL; } +#endif return chanTypePtr->flushProc; } /* *---------------------------------------------------------------------- @@ -10799,13 +10847,15 @@ Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_2) { return NULL; } +#endif return chanTypePtr->handlerProc; } /* *---------------------------------------------------------------------- @@ -10826,13 +10876,15 @@ Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_3) { return NULL; } +#endif return chanTypePtr->wideSeekProc; } /* *---------------------------------------------------------------------- @@ -10854,13 +10906,15 @@ Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { +#ifndef TCL_NO_DEPRECATED if (Tcl_ChannelVersion(chanTypePtr) < TCL_CHANNEL_VERSION_4) { return NULL; } +#endif return chanTypePtr->threadActionProc; } /* *---------------------------------------------------------------------- Index: generic/tclIOGT.c ================================================================== --- generic/tclIOGT.c +++ generic/tclIOGT.c @@ -20,17 +20,19 @@ */ 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); +#ifndef TCL_NO_DEPRECATED static int TransformSeekProc(ClientData instanceData, long offset, int mode, int *errorCodePtr); +#endif static int TransformSetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value); static int TransformGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, @@ -117,19 +119,23 @@ */ static const Tcl_ChannelType transformChannelType = { "transform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TransformCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ TransformInputProc, /* Input proc. */ TransformOutputProc, /* Output proc. */ +#ifndef TCL_NO_DEPRECATED TransformSeekProc, /* Seek proc. */ +#else + NULL, /* Seek proc. */ +#endif 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. */ TransformWideSeekProc, /* Wide seek proc. */ NULL, /* Thread action. */ @@ -531,13 +537,18 @@ */ static int TransformCloseProc( ClientData instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { TransformChannelData *dataPtr = instanceData; + + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } /* * Important: In this procedure 'dataPtr->self' already points to the * underlying channel. * @@ -826,10 +837,11 @@ * contains the POSIX error code if an error occurred, or zero. * *---------------------------------------------------------------------- */ +#ifndef TCL_NO_DEPRECATED static int TransformSeekProc( ClientData instanceData, /* The channel to manipulate. */ long offset, /* Size of movement. */ int mode, /* How to move. */ @@ -872,10 +884,11 @@ ReleaseData(dataPtr); return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode, errorCodePtr); } +#endif /* *---------------------------------------------------------------------- * * TransformWideSeekProc -- @@ -903,11 +916,13 @@ int *errorCodePtr) /* Location of error flag. */ { TransformChannelData *dataPtr = instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); +#ifndef TCL_NO_DEPRECATED Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); +#endif Tcl_DriverWideSeekProc *parentWideSeekProc = Tcl_ChannelWideSeekProc(parentType); ClientData parentData = Tcl_GetChannelInstanceData(parent); if ((offset == 0) && (mode == SEEK_CUR)) { @@ -916,13 +931,18 @@ * location. Simply pass the request down. */ if (parentWideSeekProc != NULL) { return parentWideSeekProc(parentData, offset, mode, errorCodePtr); +#ifndef TCL_NO_DEPRECATED + } else if (parentSeekProc) { + return parentSeekProc(parentData, 0, mode, errorCodePtr); +#endif + } else { + *errorCodePtr = EINVAL; + return -1; } - - return parentSeekProc(parentData, 0, 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 @@ -946,29 +966,33 @@ /* * 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 (offsetLONG_MAX) { - *errorCodePtr = EOVERFLOW; + if (parentWideSeekProc == NULL) { + /* + * 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. + */ + +#ifndef TCL_NO_DEPRECATED + if (offsetLONG_MAX) { + *errorCodePtr = EOVERFLOW; + return -1; + } + + return parentSeekProc(parentData, offset, + mode, errorCodePtr); +#else + *errorCodePtr = EINVAL; return -1; +#endif } - - return parentSeekProc(parentData, offset, - mode, errorCodePtr); + return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } /* *---------------------------------------------------------------------- * Index: generic/tclIORChan.c ================================================================== --- generic/tclIORChan.c +++ generic/tclIORChan.c @@ -30,11 +30,11 @@ /* * Signatures of all functions used in the C layer of the reflection. */ 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, int toWrite, int *errorCodePtr); static void ReflectWatch(ClientData clientData, int mask); @@ -44,12 +44,14 @@ static int ReflectEventRun(Tcl_Event *ev, int flags); static int ReflectEventDelete(Tcl_Event *ev, ClientData cd); #endif static Tcl_WideInt ReflectSeekWide(ClientData clientData, Tcl_WideInt offset, int mode, int *errorCodePtr); +#ifndef TCL_NO_DEPRECATED static int ReflectSeek(ClientData clientData, long offset, int mode, int *errorCodePtr); +#endif static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int ReflectSetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, @@ -63,27 +65,31 @@ */ static const Tcl_ChannelType tclRChannelType = { "tclrchannel", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - ReflectClose, /* Close channel, clean instance data */ + TCL_CLOSE2PROC, /* Close channel, clean instance data */ ReflectInput, /* Handle read request */ ReflectOutput, /* Handle write request */ +#ifndef TCL_NO_DEPRECATED ReflectSeek, /* Move location of access point. NULL'able */ +#else + NULL, +#endif 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 */ ReflectSeekWide, /* Move access point (64 bit). NULL'able */ #if TCL_THREADS ReflectThread, /* thread action, tracking owner */ #else - NULL, /* thread action */ + (void *)-1, /* thread action */ #endif NULL /* truncate */ }; /* @@ -694,11 +700,13 @@ } if (!(methods & FLAG(METH_BLOCKING))) { clonePtr->blockModeProc = NULL; } if (!(methods & FLAG(METH_SEEK))) { +#ifndef TCL_NO_DEPRECATED clonePtr->seekProc = NULL; +#endif clonePtr->wideSeekProc = NULL; } chanPtr->typePtr = clonePtr; } @@ -1148,19 +1156,24 @@ */ static int ReflectClose( ClientData clientData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ReflectedChannel *rcPtr = clientData; int result; /* Result code for 'close' */ Tcl_Obj *resObj; /* Result data for 'close' */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in * this interp */ 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 * interpreters, and therefore we cannot call upon the handler command @@ -1612,10 +1625,11 @@ *errorCodePtr = EINVAL; newLoc = -1; goto stop; } +#ifndef TCL_NO_DEPRECATED static int ReflectSeek( ClientData clientData, long offset, int seekMode, @@ -1629,10 +1643,11 @@ */ return ReflectSeekWide(clientData, offset, seekMode, errorCodePtr); } +#endif /* *---------------------------------------------------------------------- * * ReflectWatch -- Index: generic/tclIORTrans.c ================================================================== --- generic/tclIORTrans.c +++ generic/tclIORTrans.c @@ -30,21 +30,23 @@ /* * Signatures of all functions used in the C layer of the reflection. */ 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, int toWrite, int *errorCodePtr); 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); +#ifndef TCL_NO_DEPRECATED static int ReflectSeek(ClientData clientData, long offset, int mode, int *errorCodePtr); +#endif static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int ReflectSetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, @@ -58,19 +60,23 @@ */ static const Tcl_ChannelType tclRTransformType = { "tclrtransform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel. */ - ReflectClose, /* Close channel, clean instance data. */ + TCL_CLOSE2PROC, /* Close channel, clean instance data. */ ReflectInput, /* Handle read request. */ ReflectOutput, /* Handle write request. */ +#ifndef TCL_NO_DEPRECATED ReflectSeek, /* Move location of access point. */ +#else + NULL, /* Move location of access point. */ +#endif 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. */ ReflectNotify, /* Handle events. */ ReflectSeekWide, /* Move access point (64 bit). */ @@ -877,20 +883,25 @@ */ static int ReflectClose( ClientData clientData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ReflectedTransform *rtPtr = clientData; int errorCode, errorCodeSet = 0; int result = TCL_OK; /* Result code for 'close' */ Tcl_Obj *resObj; /* Result data for 'close' */ ReflectedTransformMap *rtmPtr; /* Map of reflected transforms with handlers * 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 * interpreters, and therefore we cannot call upon the handler command @@ -1325,22 +1336,10 @@ { ReflectedTransform *rtPtr = clientData; 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 * support neither flush, nor drain. For these cases we can pass the * request down and the result back up unchanged. @@ -1380,20 +1379,27 @@ * Now seek to the new position in the channel as requested by the * caller. Note that we prefer the wideSeekProc if that is available and * 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) { +#ifndef TCL_NO_DEPRECATED + if (offset < LONG_MIN || offset > LONG_MAX) { + *errorCodePtr = EOVERFLOW; + curPos = -1; + } else { + curPos = Tcl_ChannelSeekProc(parent->typePtr)( + parent->instanceData, offset, seekMode, + errorCodePtr); + } +#else + *errorCodePtr = EINVAL; curPos = -1; +#endif } 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); } @@ -1400,10 +1406,11 @@ *errorCodePtr = EOK; Tcl_Release(rtPtr); return curPos; } +#ifndef TCL_NO_DEPRECATED static int ReflectSeek( ClientData clientData, long offset, int seekMode, @@ -1417,10 +1424,11 @@ */ return ReflectSeekWide(clientData, offset, seekMode, errorCodePtr); } +#endif /* *---------------------------------------------------------------------- * * ReflectWatch -- Index: generic/tclStubInit.c ================================================================== --- generic/tclStubInit.c +++ generic/tclStubInit.c @@ -254,10 +254,13 @@ # define Tcl_NewIntObj 0 # define Tcl_NewLongObj 0 # define Tcl_DbNewLongObj 0 # define Tcl_BackgroundError 0 # define Tcl_FreeResult 0 +# define Tcl_ChannelSeekProc 0 +# define Tcl_ChannelCloseProc 0 +# define Tcl_Close 0 #else mp_err TclBN_mp_div_3(const mp_int *a, mp_int *c, unsigned int *d) { mp_digit d2; mp_err result = mp_div_d(a, 3, c, &d2); Index: generic/tclZipfs.c ================================================================== --- generic/tclZipfs.c +++ generic/tclZipfs.c @@ -383,17 +383,19 @@ Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); 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); +#ifndef TCL_NO_DEPRECATED static int ZipChannelSeek(void *instanceData, long offset, int mode, int *errloc); +#endif static Tcl_WideInt ZipChannelWideSeek(void *instanceData, Tcl_WideInt offset, int mode, int *errloc); static void ZipChannelWatchChannel(void *instanceData, int mask); static int ZipChannelWrite(void *instanceData, @@ -442,19 +444,23 @@ */ static Tcl_ChannelType ZipChannelType = { "zip", /* Type name. */ TCL_CHANNEL_VERSION_5, - ZipChannelClose, /* Close channel, clean instance data */ + TCL_CLOSE2PROC, /* Close channel, clean instance data */ ZipChannelRead, /* Handle read request */ ZipChannelWrite, /* Handle write request */ +#ifndef TCL_NO_DEPRECATED ZipChannelSeek, /* Move location of access point, NULL'able */ +#else + NULL, /* Move location of access point, NULL'able */ +#endif 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 */ ZipChannelWideSeek, /* Wide seek function, NULL'able */ NULL, /* Thread action function, NULL'able */ @@ -3310,13 +3316,18 @@ */ static int ZipChannelClose( void *instanceData, - Tcl_Interp *dummy) /* Current interpreter. */ + Tcl_Interp *dummy, /* Current interpreter. */ + int flags) { ZipChannel *info = instanceData; + + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } if (info->iscompr && info->ubuf) { ckfree(info->ubuf); info->ubuf = NULL; } @@ -3540,19 +3551,21 @@ } info->numRead = (size_t) offset; return info->numRead; } +#ifndef TCL_NO_DEPRECATED static int ZipChannelSeek( void *instanceData, long offset, int mode, int *errloc) { return ZipChannelWideSeek(instanceData, offset, mode, errloc); } +#endif /* *------------------------------------------------------------------------- * * ZipChannelWatchChannel -- Index: generic/tclZlib.c ================================================================== --- generic/tclZlib.c +++ generic/tclZlib.c @@ -158,11 +158,11 @@ * Prototypes for private procedures defined later in this file: */ 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; static Tcl_DriverInputProc ZlibTransformInput; static Tcl_DriverOutputProc ZlibTransformOutput; @@ -203,19 +203,19 @@ */ static const Tcl_ChannelType zlibChannelType = { "zlib", TCL_CHANNEL_VERSION_5, - ZlibTransformClose, + TCL_CLOSE2PROC, ZlibTransformInput, ZlibTransformOutput, NULL, /* seekProc */ ZlibTransformSetOption, ZlibTransformGetOption, ZlibTransformWatch, ZlibTransformGetHandle, - NULL, /* close2Proc */ + ZlibTransformClose, /* close2Proc */ ZlibTransformBlockMode, NULL, /* flushProc */ ZlibTransformEventHandler, NULL, /* wideSeekProc */ NULL, @@ -2893,14 +2893,19 @@ */ static int ZlibTransformClose( void *instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { ZlibChannelData *cd = instanceData; int e, written, result = TCL_OK; + + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } /* * Delete the support timer. */ Index: unix/tclUnixChan.c ================================================================== --- unix/tclUnixChan.c +++ unix/tclUnixChan.c @@ -119,27 +119,29 @@ * Static routines for this file: */ static int FileBlockModeProc(ClientData instanceData, int mode); static int FileCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static int FileGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static int FileInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); +#ifndef TCL_NO_DEPRECATED static int FileSeekProc(ClientData instanceData, long offset, int mode, int *errorCode); +#endif static int FileTruncateProc(ClientData instanceData, Tcl_WideInt length); static Tcl_WideInt FileWideSeekProc(ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCode); static void FileWatchProc(ClientData instanceData, int mask); #ifdef SUPPORTS_TTY static int TtyCloseProc(ClientData instanceData, - Tcl_Interp *interp); + Tcl_Interp *interp, int flags); static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr); static int TtyGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int TtyGetBaud(speed_t speed); @@ -159,19 +161,23 @@ */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - FileCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ +#ifndef TCL_NO_DEPRECATED FileSeekProc, /* Seek proc. */ +#else + NULL, +#endif 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. */ FileWideSeekProc, /* wide seek proc. */ NULL, @@ -185,19 +191,19 @@ */ static const Tcl_ChannelType ttyChannelType = { "tty", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TtyCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ NULL, /* Seek proc. */ TtySetOptionProc, /* Set option proc. */ 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. */ NULL, /* wide seek proc. */ NULL, /* thread action proc. */ @@ -351,14 +357,19 @@ */ static int FileCloseProc( ClientData instanceData, /* File state. */ - Tcl_Interp *interp) /* For error reporting - unused. */ + Tcl_Interp *dummy, /* For error reporting - unused. */ + int flags) { FileState *fsPtr = instanceData; int errorCode = 0; + + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } Tcl_DeleteFileHandler(fsPtr->fd); /* * Do not close standard channels while in thread-exit. @@ -376,14 +387,18 @@ #ifdef SUPPORTS_TTY static int TtyCloseProc( ClientData instanceData, - Tcl_Interp *interp) + Tcl_Interp *interp, + int flags) { TtyState *ttyPtr = 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. */ switch (ttyPtr->closeMode) { @@ -408,11 +423,11 @@ /* * Delegate to close for files. */ - return FileCloseProc(instanceData, interp); + return FileCloseProc(instanceData, interp, flags); } #endif /* SUPPORTS_TTY */ /* *---------------------------------------------------------------------- @@ -430,11 +445,11 @@ * Moves the location at which the channel will be accessed in future * operations. * *---------------------------------------------------------------------- */ - +#ifndef TCL_NO_DEPRECATED static int FileSeekProc( ClientData instanceData, /* File state. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? Can be @@ -471,10 +486,11 @@ } else { *errorCodePtr = (newLoc == -1) ? errno : 0; } return (int) newLoc; } +#endif /* *---------------------------------------------------------------------- * * FileWideSeekProc -- Index: unix/tclUnixSock.c ================================================================== --- unix/tclUnixSock.c +++ unix/tclUnixSock.c @@ -155,11 +155,15 @@ */ static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ +#ifndef TCL_NO_DEPRECATED TcpCloseProc, /* Close proc. */ +#else + TCL_CLOSE2PROC, /* Close proc. */ +#endif TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ Index: win/tclWinChan.c ================================================================== --- win/tclWinChan.c +++ win/tclWinChan.c @@ -74,21 +74,23 @@ 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); static ThreadSpecificData *FileInit(void); static int FileInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); +#ifndef TCL_NO_DEPRECATED static int FileSeekProc(ClientData instanceData, long offset, int mode, int *errorCode); +#endif static Tcl_WideInt FileWideSeekProc(ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCode); static void FileSetupProc(ClientData clientData, int flags); static void FileWatchProc(ClientData instanceData, int mask); static void FileThreadActionProc(ClientData instanceData, @@ -103,19 +105,23 @@ */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - FileCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ +#ifndef TCL_NO_DEPRECATED FileSeekProc, /* Seek proc. */ +#else + NULL, +#endif 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. */ FileWideSeekProc, /* Wide seek proc. */ FileThreadActionProc, /* Thread action proc. */ @@ -384,16 +390,22 @@ */ static int FileCloseProc( ClientData instanceData, /* Pointer to FileInfo structure. */ - Tcl_Interp *interp) /* Not used. */ + Tcl_Interp *dummy, /* Not used. */ + int flags) { FileInfo *fileInfoPtr = instanceData; FileInfo *infoPtr; ThreadSpecificData *tsdPtr; int errorCode = 0; + (void)dummy; + + if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { + return EINVAL; + } /* * Remove the file from the watch list. */ @@ -453,11 +465,11 @@ * Moves the location at which the channel will be accessed in future * operations. * *---------------------------------------------------------------------- */ - +#ifndef TCL_NO_DEPRECATED static int FileSeekProc( ClientData instanceData, /* File state. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? */ @@ -513,10 +525,11 @@ SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN); return -1; } return (int) newPos; } +#endif /* *---------------------------------------------------------------------- * * FileWideSeekProc -- Index: win/tclWinConsole.c ================================================================== --- win/tclWinConsole.c +++ win/tclWinConsole.c @@ -140,11 +140,11 @@ 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, int direction, ClientData *handlePtr); static int ConsoleGetOptionProc(ClientData instanceData, @@ -178,19 +178,19 @@ */ static const Tcl_ChannelType consoleChannelType = { "console", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - ConsoleCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ ConsoleInputProc, /* Input proc. */ ConsoleOutputProc, /* Output proc. */ NULL, /* Seek proc. */ ConsoleSetOptionProc, /* Set option proc. */ 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. */ NULL, /* Wide seek proc. */ ConsoleThreadActionProc, /* Thread action proc. */ @@ -529,16 +529,22 @@ */ static int ConsoleCloseProc( ClientData instanceData, /* Pointer to ConsoleInfo structure. */ - Tcl_Interp *interp) /* For error reporting. */ + Tcl_Interp *dummy, /* For error reporting. */ + int flags) { ConsoleInfo *consolePtr = instanceData; int errorCode = 0; ConsoleInfo *infoPtr, **nextPtrPtr; 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 * trying to read from the console. Index: win/tclWinSerial.c ================================================================== --- win/tclWinSerial.c +++ win/tclWinSerial.c @@ -166,11 +166,11 @@ */ 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, int direction, ClientData *handlePtr); static ThreadSpecificData *SerialInit(void); @@ -202,19 +202,19 @@ */ static const Tcl_ChannelType serialChannelType = { "serial", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - SerialCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ SerialInputProc, /* Input proc. */ SerialOutputProc, /* Output proc. */ NULL, /* Seek proc. */ SerialSetOptionProc, /* Set option proc. */ 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. */ NULL, /* wide seek proc */ SerialThreadActionProc, /* thread action proc */ @@ -595,18 +595,22 @@ */ static int SerialCloseProc( ClientData instanceData, /* Pointer to SerialInfo structure. */ - Tcl_Interp *interp) /* For error reporting. */ + Tcl_Interp *interp, /* 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); - 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); CloseHandle(serialPtr->osRead.hEvent); } Index: win/tclWinSock.c ================================================================== --- win/tclWinSock.c +++ win/tclWinSock.c @@ -278,11 +278,15 @@ */ static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ +#ifndef TCL_NO_DEPRECATED TcpCloseProc, /* Close proc. */ +#else + TCL_CLOSE2PROC, /* Close proc. */ +#endif TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ TcpSetOptionProc, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */