📄 tclmacchan.c
字号:
if ((mode & TCL_ALWAYS_APPEND) || (mode & TCL_APPEND)) { if (Tcl_Seek(chan, 0, SEEK_END) < 0) { *errorCodePtr = errno = EFAULT; Tcl_SetErrno(errno); Tcl_Close(NULL, chan); FSClose(fileRef); ckfree((char *) fileState); return NULL; } } return chan;}/* *---------------------------------------------------------------------- * * FileBlockMode -- * * Set blocking or non-blocking mode on channel. Macintosh files * can never really be set to blocking or non-blocking modes. * However, we don't generate an error - we just return success. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */static intFileBlockMode( ClientData instanceData, /* Unused. */ int mode) /* The mode to set. */{ return 0;}/* *---------------------------------------------------------------------- * * FileClose -- * * Closes the IO channel. * * Results: * 0 if successful, the value of errno if failed. * * Side effects: * Closes the physical channel * *---------------------------------------------------------------------- */static intFileClose( ClientData instanceData, /* Unused. */ Tcl_Interp *interp) /* Unused. */{ FileState *fileState = (FileState *) instanceData; int errorCode = 0; OSErr err; err = FSClose(fileState->fileRef); FlushVol(NULL, fileState->volumeRef); if (err != noErr) { errorCode = errno = TclMacOSErrorToPosixError(err); panic("error during file close"); } ckfree((char *) fileState); Tcl_SetErrno(errorCode); return errorCode;}/* *---------------------------------------------------------------------- * * FileInput -- * * Reads input from the IO channel into the buffer given. Returns * count of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */intFileInput( ClientData instanceData, /* Unused. */ char *buffer, /* Where to store data read. */ int bufSize, /* How much space is available * in the buffer? */ int *errorCodePtr) /* Where to store error code. */{ FileState *fileState = (FileState *) instanceData; OSErr err; long length = bufSize; *errorCodePtr = 0; errno = 0; err = FSRead(fileState->fileRef, &length, buffer); if ((err == noErr) || (err == eofErr)) { return length; } else { switch (err) { case ioErr: *errorCodePtr = errno = EIO; case afpAccessDenied: *errorCodePtr = errno = EACCES; default: *errorCodePtr = errno = EINVAL; } return -1; } *errorCodePtr = errno; return -1;}/* *---------------------------------------------------------------------- * * FileOutput-- * * Writes the given output on the IO channel. Returns count of how * many characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an * error indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */static intFileOutput( ClientData instanceData, /* Unused. */ char *buffer, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCodePtr) /* Where to store error code. */{ FileState *fileState = (FileState *) instanceData; long length = toWrite; OSErr err; *errorCodePtr = 0; errno = 0; if (fileState->appendMode == true) { FileSeek(instanceData, 0, SEEK_END, errorCodePtr); *errorCodePtr = 0; } err = FSWrite(fileState->fileRef, &length, buffer); if (err == noErr) { err = FlushFile(fileState->fileRef); } else { *errorCodePtr = errno = TclMacOSErrorToPosixError(err); return -1; } return length;}/* *---------------------------------------------------------------------- * * FileSeek -- * * Seeks on an IO 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 intFileSeek( ClientData instanceData, /* Unused. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where * should we seek? */ int *errorCodePtr) /* To store error code. */{ FileState *fileState = (FileState *) instanceData; IOParam pb; OSErr err; *errorCodePtr = 0; pb.ioCompletion = NULL; pb.ioRefNum = fileState->fileRef; if (mode == SEEK_SET) { pb.ioPosMode = fsFromStart; } else if (mode == SEEK_END) { pb.ioPosMode = fsFromLEOF; } else if (mode == SEEK_CUR) { err = PBGetFPosSync((ParmBlkPtr) &pb); if (pb.ioResult == noErr) { if (offset == 0) { return pb.ioPosOffset; } offset += pb.ioPosOffset; } pb.ioPosMode = fsFromStart; } pb.ioPosOffset = offset; err = PBSetFPosSync((ParmBlkPtr) &pb); if (pb.ioResult == noErr){ return pb.ioPosOffset; } else if (pb.ioResult == eofErr) { long currentEOF, newEOF; long buffer, i, length; err = PBGetEOFSync((ParmBlkPtr) &pb); currentEOF = (long) pb.ioMisc; if (mode == SEEK_SET) { newEOF = offset; } else if (mode == SEEK_END) { newEOF = offset + currentEOF; } else if (mode == SEEK_CUR) { err = PBGetFPosSync((ParmBlkPtr) &pb); newEOF = offset + pb.ioPosOffset; } /* * Write 0's to the new EOF. */ pb.ioPosOffset = 0; pb.ioPosMode = fsFromLEOF; err = PBGetFPosSync((ParmBlkPtr) &pb); length = 1; buffer = 0; for (i = 0; i < (newEOF - currentEOF); i++) { err = FSWrite(fileState->fileRef, &length, &buffer); } err = PBGetFPosSync((ParmBlkPtr) &pb); if (pb.ioResult == noErr){ return pb.ioPosOffset; } } *errorCodePtr = errno = TclMacOSErrorToPosixError(err); return -1;}/* *---------------------------------------------------------------------- * * CommonWatch -- * * Initialize the notifier to watch handles from this channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidCommonWatch( ClientData instanceData, /* The file state. */ int mask) /* Events of interest; an OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */{ FileState **nextPtrPtr, *ptr; FileState *infoPtr = (FileState *) instanceData; int oldMask = infoPtr->watchMask; if (!initialized) { FileInit(); } infoPtr->watchMask = mask; if (infoPtr->watchMask) { if (!oldMask) { infoPtr->nextPtr = firstFilePtr; firstFilePtr = infoPtr; } } else { if (oldMask) { /* * Remove the file from the list of watched files. */ for (nextPtrPtr = &firstFilePtr, ptr = *nextPtrPtr; ptr != NULL; nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; } } } }}/* *---------------------------------------------------------------------- * * GetOpenMode -- * * Description: * Computes a POSIX mode mask from a given string and also sets * a flag to indicate whether the caller should seek to EOF during * opening of the file. * * Results: * On success, returns mode to pass to "open". If an error occurs, the * returns -1 and if interp is not NULL, sets interp->result to an * error message. * * Side effects: * Sets the integer referenced by seekFlagPtr to 1 if the caller * should seek to EOF during opening the file. * * Special note: * This code is based on a prototype implementation contributed * by Mark Diekhans. * *---------------------------------------------------------------------- */static intGetOpenMode( Tcl_Interp *interp, /* Interpreter to use for error * reporting - may be NULL. */ char *string) /* Mode string, e.g. "r+" or * "RDONLY CREAT". */{ int mode, modeArgc, c, i, gotRW; char **modeArgv, *flag; /* * Check for the simpler fopen-like access modes (e.g. "r"). They * are distinguished from the POSIX access modes by the presence * of a lower-case first letter. */ mode = 0; if (islower(UCHAR(string[0]))) { switch (string[0]) { case 'r': mode = TCL_RDONLY; break; case 'w': mode = TCL_WRONLY|TCL_CREAT|TCL_TRUNC; break; case 'a': mode = TCL_WRONLY|TCL_CREAT|TCL_APPEND; break; default: error: if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "illegal access mode \"", string, "\"", (char *) NULL); } return -1; } if (string[1] == '+') { mode &= ~(TCL_RDONLY|TCL_WRONLY); mode |= TCL_RDWR; if (string[2] != 0) { goto error; } } else if (string[1] != 0) { goto error; } return mode; } /* * The access modes are specified using a list of POSIX modes * such as TCL_CREAT. */ if (Tcl_SplitList(interp, string, &modeArgc, &modeArgv) != TCL_OK) { if (interp != (Tcl_Interp *) NULL) { Tcl_AddErrorInfo(interp, "\n while processing open access modes \""); Tcl_AddErrorInfo(interp, string); Tcl_AddErrorInfo(interp, "\""); } return -1; } gotRW = 0; for (i = 0; i < modeArgc; i++) { flag = modeArgv[i]; c = flag[0]; if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) { mode = (mode & ~TCL_RW_MODES) | TCL_RDONLY; gotRW = 1; } else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) { mode = (mode & ~TCL_RW_MODES) | TCL_WRONLY; gotRW = 1; } else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) { mode = (mode & ~TCL_RW_MODES) | TCL_RDWR; gotRW = 1; } else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) { mode |= TCL_ALWAYS_APPEND; } else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) { mode |= TCL_CREAT; } else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) { mode |= TCL_EXCL; } else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) { mode |= TCL_NOCTTY; } else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) { mode |= TCL_NONBLOCK; } else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) { mode |= TCL_TRUNC; } else { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "invalid access mode \"", flag, "\": must be RDONLY, WRONLY, RDWR, APPEND, CREAT", " EXCL, NOCTTY, NONBLOCK, or TRUNC", (char *) NULL); } ckfree((char *) modeArgv); return -1; } } ckfree((char *) modeArgv); if (!gotRW) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "access mode must include either", " RDONLY, WRONLY, or RDWR", (char *) NULL); } return -1; } return mode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -