From 55bb78dc4fdf14318cfcbbeb264b7ef0a3e0a57e Mon Sep 17 00:00:00 2001 From: das Date: Mon, 3 Mar 2003 20:22:35 +0000 Subject: Mac OS Classic specific fixes: * generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC, skip potential directory separator at the beginning of addStrRep. * mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup fixes to cut and splice implementation for file channels. * mac/tclMacFile.c (TclpUtime): pass native path to utime(). * mac/tclMacFile.c (TclpObjLink): correctly implemented creation of alias files via new static proc CreateAliasFile(). * mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links. * mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable stat'ing of broken links. --- ChangeLog | 14 +++++++++ generic/tclIOUtil.c | 14 ++++++++- mac/tclMacChan.c | 33 +++++---------------- mac/tclMacFile.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++---- mac/tclMacPort.h | 6 +++- mac/tclMacUtil.c | 8 +++-- 6 files changed, 125 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11c0585..ea92d8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,20 @@ *** 8.4.2 TAGGED FOR RELEASE *** +2003-03-03 Daniel Steffen + + Mac OS Classic specific fixes: + * generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC, + skip potential directory separator at the beginning of addStrRep. + * mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup + fixes to cut and splice implementation for file channels. + * mac/tclMacFile.c (TclpUtime): pass native path to utime(). + * mac/tclMacFile.c (TclpObjLink): correctly implemented creation + of alias files via new static proc CreateAliasFile(). + * mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links. + * mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable + stat'ing of broken links. + 2003-03-03 Kevin Kenny * win/Makefile.vc: corrected bug introduced by 'g' for debug builds. diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 43c9f5a..29ba700 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -17,7 +17,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIOUtil.c,v 1.76 2003/02/27 23:47:16 hobbs Exp $ + * RCS: @(#) $Id: tclIOUtil.c,v 1.77 2003/03/03 20:22:41 das Exp $ */ #include "tclInt.h" @@ -4020,6 +4020,18 @@ TclNewFSPathObj(Tcl_Obj *dirPtr, CONST char *addStrRep, int len) objPtr = Tcl_NewObj(); fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath)); + if (tclPlatform == TCL_PLATFORM_MAC) { + /* + * Mac relative paths may begin with a directory separator ':'. + * If present, we need to skip this ':' because we assume that + * we can join dirPtr and addStrRep by concatenating them as + * strings (and we ensure that dirPtr is terminated by a ':'). + */ + if (addStrRep[0] == ':') { + addStrRep++; + len--; + } + } /* Setup the path */ fsPathPtr->translatedPathPtr = NULL; fsPathPtr->normPathPtr = Tcl_NewStringObj(addStrRep, len); diff --git a/mac/tclMacChan.c b/mac/tclMacChan.c index 414309e..555e333 100644 --- a/mac/tclMacChan.c +++ b/mac/tclMacChan.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacChan.c,v 1.20 2003/02/21 20:11:35 das Exp $ + * RCS: @(#) $Id: tclMacChan.c,v 1.21 2003/03/03 20:22:42 das Exp $ */ #include "tclInt.h" @@ -801,7 +801,10 @@ OpenFileChannel( short fileRef; FileState *fileState; char channelName[16 + TCL_INTEGER_SPACE]; + ThreadSpecificData *tsdPtr; + tsdPtr = FileInit(); + /* * Note we use fsRdWrShPerm instead of fsRdWrPerm which allows shared * writes on a file. This isn't common on a mac but is common with @@ -874,6 +877,8 @@ OpenFileChannel( } fileState->fileChan = chan; + fileState->nextPtr = tsdPtr->firstFilePtr; + tsdPtr->firstFilePtr = fileState; fileState->volumeRef = fileSpec.vRefNum; fileState->fileRef = fileRef; fileState->pending = 0; @@ -1195,34 +1200,12 @@ CommonWatch( * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */ { - FileState **nextPtrPtr, *ptr; FileState *infoPtr = (FileState *) instanceData; - int oldMask = infoPtr->watchMask; - ThreadSpecificData *tsdPtr; - - tsdPtr = FileInit(); + Tcl_Time blockTime = { 0, 0 }; infoPtr->watchMask = mask; if (infoPtr->watchMask) { - if (!oldMask) { - infoPtr->nextPtr = tsdPtr->firstFilePtr; - tsdPtr->firstFilePtr = infoPtr; - } - } else { - if (oldMask) { - /* - * Remove the file from the list of watched files. - */ - - for (nextPtrPtr = &(tsdPtr->firstFilePtr), ptr = *nextPtrPtr; - ptr != NULL; - nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { - if (infoPtr == ptr) { - *nextPtrPtr = ptr->nextPtr; - break; - } - } - } + Tcl_SetMaxBlockTime(&blockTime); } } diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c index c20d056..0311ecd 100644 --- a/mac/tclMacFile.c +++ b/mac/tclMacFile.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacFile.c,v 1.26 2003/01/09 10:38:29 vincentdarley Exp $ + * RCS: @(#) $Id: tclMacFile.c,v 1.27 2003/03/03 20:22:43 das Exp $ */ /* @@ -23,6 +23,8 @@ #include "tclPort.h" #include "tclMacInt.h" #include +#include +#include #include #include #include @@ -38,6 +40,8 @@ static OSErr FspLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr, static OSErr FspLLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr, FSSpec* specPtr)); +static OSErr CreateAliasFile _ANSI_ARGS_((FSSpec *theAliasFile, FSSpec *targetFile)); + static OSErr FspLocationFromFsPath(pathPtr, specPtr) Tcl_Obj *pathPtr; @@ -1173,7 +1177,6 @@ TclpObjLink(pathPtr, toPtr, linkAction) FSSpec linkSpec; OSErr err; CONST char *path; - AliasHandle alias; err = FspLocationFromFsPath(toPtr, &spec); if (err != noErr) { @@ -1186,7 +1189,7 @@ TclpObjLink(pathPtr, toPtr, linkAction) if (err == noErr) { err = dupFNErr; /* EEXIST. */ } else { - err = NewAlias(&spec, &linkSpec, &alias); + err = CreateAliasFile(&linkSpec, &spec); } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); @@ -1265,7 +1268,78 @@ TclpUtime(pathPtr, tval) struct utimbuf local_tval; local_tval.actime=tval->actime+gmt_offset; local_tval.modtime=tval->modtime+gmt_offset; - return utime(Tcl_GetString(Tcl_FSGetNormalizedPath(NULL,pathPtr)), + return utime(Tcl_FSGetNativePath(Tcl_FSGetNormalizedPath(NULL,pathPtr)), &local_tval); } - + +/* + *--------------------------------------------------------------------------- + * + * CreateAliasFile -- + * + * Creates an alias file located at aliasDest referring to the targetFile. + * + * Results: + * 0 on success, OS error code on error. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ +static OSErr +CreateAliasFile(FSSpec *theAliasFile, FSSpec *targetFile) +{ + CInfoPBRec cat; + FInfo fndrInfo; + AliasHandle theAlias; + short saveRef, rsrc = -1; + OSErr err; + + saveRef = CurResFile(); + /* set up the Finder information record for the alias file */ + cat.dirInfo.ioNamePtr = targetFile->name; + cat.dirInfo.ioVRefNum = targetFile->vRefNum; + cat.dirInfo.ioFDirIndex = 0; + cat.dirInfo.ioDrDirID = targetFile->parID; + err = PBGetCatInfoSync(&cat); + if (err != noErr) goto bail; + if ((cat.dirInfo.ioFlAttrib & 16) == 0) { + /* file alias */ + switch (cat.hFileInfo.ioFlFndrInfo.fdType) { + case 'APPL': fndrInfo.fdType = kApplicationAliasType; break; + case 'APPC': fndrInfo.fdType = kApplicationCPAliasType; break; + case 'APPD': fndrInfo.fdType = kApplicationDAAliasType; break; + default: fndrInfo.fdType = cat.hFileInfo.ioFlFndrInfo.fdType; break; + } + fndrInfo.fdCreator = cat.hFileInfo.ioFlFndrInfo.fdCreator; + } else { + /* folder alias */ + fndrInfo.fdType = kContainerFolderAliasType; + fndrInfo.fdCreator = 'MACS'; + } + fndrInfo.fdFlags = kIsAlias; + fndrInfo.fdLocation.v = 0; + fndrInfo.fdLocation.h = 0; + fndrInfo.fdFldr = 0; + /* create new file and set the file information */ + FSpCreateResFile( theAliasFile, fndrInfo.fdCreator, fndrInfo.fdType, smSystemScript); + if ((err = ResError()) != noErr) goto bail; + err = FSpSetFInfo( theAliasFile, &fndrInfo); + if (err != noErr) goto bail; + /* save the alias resource */ + rsrc = FSpOpenResFile(theAliasFile, fsRdWrPerm); + if (rsrc == -1) { err = ResError(); goto bail; } + UseResFile(rsrc); + err = NewAlias(theAliasFile, targetFile, &theAlias); + if (err != noErr) goto bail; + AddResource((Handle) theAlias, rAliasType, 0, theAliasFile->name); + if ((err = ResError()) != noErr) goto bail; + CloseResFile(rsrc); + rsrc = -1; + /* done */ + bail: + if (rsrc != -1) CloseResFile(rsrc); + UseResFile(saveRef); + return err; +} diff --git a/mac/tclMacPort.h b/mac/tclMacPort.h index a868733..482f6e8 100644 --- a/mac/tclMacPort.h +++ b/mac/tclMacPort.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacPort.h,v 1.16 2002/10/09 11:54:34 das Exp $ + * RCS: @(#) $Id: tclMacPort.h,v 1.17 2003/03/03 20:22:44 das Exp $ */ @@ -77,6 +77,10 @@ #endif /* __MWERKS__ */ +#if defined(S_IFBLK) && !defined(S_ISLNK) +#define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK)) +#endif + /* * Many signals are not supported on the Mac and are thus not defined in * . They are defined here so that Tcl will compile with less diff --git a/mac/tclMacUtil.c b/mac/tclMacUtil.c index a67eeef..ab65815 100644 --- a/mac/tclMacUtil.c +++ b/mac/tclMacUtil.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacUtil.c,v 1.6 2002/04/19 14:18:55 das Exp $ + * RCS: @(#) $Id: tclMacUtil.c,v 1.7 2003/03/03 20:22:44 das Exp $ */ #include "tcl.h" @@ -322,7 +322,11 @@ FSpLocationFromPathAlias( if (err != noErr) return err; lastFileSpec=*fileSpecPtr; err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias); - if (err != noErr) return err; + if (err != noErr) { + /* ignore alias resolve errors on last path component */ + if (pos < length) return err; + else *fileSpecPtr=lastFileSpec; + } FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory); vRefNum = fileSpecPtr->vRefNum; cur = pos; -- cgit v0.12