From 26bb2b5da7f034e47d6544e3d84e54c861f61206 Mon Sep 17 00:00:00 2001 From: das Date: Fri, 19 Apr 2002 14:18:33 +0000 Subject: 2002-04-20 Daniel Steffen * generic/tclInt.decls: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: * mac/tclMacFCmd.c: * mac/tclMacFile.c: * mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias file aware, and replaced various calls to FSpLocationFrom*Path by calls to new alias file aware versions FSpLLocationFrom*Path. The alias file aware routines don't resolve the last component of a path if it is an alias. This allows [file copy/delete] etc. to act correctly on alias files. (c.f. discussion in Bug #511666) --- ChangeLog | 14 +++++++++++++ generic/tclInt.decls | 6 +++++- generic/tclIntPlatDecls.h | 10 +++++++++- generic/tclStubInit.c | 3 ++- mac/tclMacFCmd.c | 32 +++++++++++++++++++---------- mac/tclMacFile.c | 36 +++++++++++++++++++++++++++------ mac/tclMacUtil.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 130 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2748cf5..098c648 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-04-20 Daniel Steffen + + * generic/tclInt.decls: + * generic/tclIntPlatDecls.h: + * generic/tclStubInit.c: + * mac/tclMacFCmd.c: + * mac/tclMacFile.c: + * mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias + file aware, and replaced various calls to FSpLocationFrom*Path + by calls to new alias file aware versions FSpLLocationFrom*Path. + The alias file aware routines don't resolve the last component of + a path if it is an alias. This allows [file copy/delete] etc. to + act correctly on alias files. (c.f. discussion in Bug #511666) + 2002-04-19 Donal K. Fellows * tests/lindex.test (lindex-3.7): diff --git a/generic/tclInt.decls b/generic/tclInt.decls index ca33071..4b6523c 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -12,7 +12,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: tclInt.decls,v 1.47 2002/03/20 22:47:36 dgp Exp $ +# RCS: @(#) $Id: tclInt.decls,v 1.48 2002/04/19 14:18:33 das Exp $ library tcl @@ -780,6 +780,10 @@ declare 24 mac { declare 25 mac { int TclMacChmod(CONST char *path, int mode) } +# version of FSpLocationFromPath that doesn't resolve the last path component +declare 26 mac { + int FSpLLocationFromPath(int length, CONST char *path, FSSpecPtr theSpec) +} ############################ # Windows specific internals diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index 907a648..090d3d1 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -9,7 +9,7 @@ * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * - * RCS: @(#) $Id: tclIntPlatDecls.h,v 1.16 2002/01/27 11:09:34 das Exp $ + * RCS: @(#) $Id: tclIntPlatDecls.h,v 1.17 2002/04/19 14:18:38 das Exp $ */ #ifndef _TCLINTPLATDECLS @@ -198,6 +198,9 @@ EXTERN FILE * TclMacFOpenHack _ANSI_ARGS_((CONST char * path, EXTERN char * TclpGetTZName _ANSI_ARGS_((int isdst)); /* 25 */ EXTERN int TclMacChmod _ANSI_ARGS_((CONST char * path, int mode)); +/* 26 */ +EXTERN int FSpLLocationFromPath _ANSI_ARGS_((int length, + CONST char * path, FSSpecPtr theSpec)); #endif /* MAC_TCL */ typedef struct TclIntPlatStubs { @@ -273,6 +276,7 @@ typedef struct TclIntPlatStubs { FILE * (*tclMacFOpenHack) _ANSI_ARGS_((CONST char * path, CONST char * mode)); /* 23 */ char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 24 */ int (*tclMacChmod) _ANSI_ARGS_((CONST char * path, int mode)); /* 25 */ + int (*fSpLLocationFromPath) _ANSI_ARGS_((int length, CONST char * path, FSSpecPtr theSpec)); /* 26 */ #endif /* MAC_TCL */ } TclIntPlatStubs; @@ -533,6 +537,10 @@ extern TclIntPlatStubs *tclIntPlatStubsPtr; #define TclMacChmod \ (tclIntPlatStubsPtr->tclMacChmod) /* 25 */ #endif +#ifndef FSpLLocationFromPath +#define FSpLLocationFromPath \ + (tclIntPlatStubsPtr->fSpLLocationFromPath) /* 26 */ +#endif #endif /* MAC_TCL */ #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 0ece7d5..52ee177 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclStubInit.c,v 1.68 2002/02/15 14:28:49 dkf Exp $ + * RCS: @(#) $Id: tclStubInit.c,v 1.69 2002/04/19 14:19:02 das Exp $ */ #include "tclInt.h" @@ -322,6 +322,7 @@ TclIntPlatStubs tclIntPlatStubs = { TclMacFOpenHack, /* 23 */ TclpGetTZName, /* 24 */ TclMacChmod, /* 25 */ + FSpLLocationFromPath, /* 26 */ #endif /* MAC_TCL */ }; diff --git a/mac/tclMacFCmd.c b/mac/tclMacFCmd.c index 1a75ce7..e22b365 100644 --- a/mac/tclMacFCmd.c +++ b/mac/tclMacFCmd.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: tclMacFCmd.c,v 1.16 2002/01/27 11:09:44 das Exp $ + * RCS: @(#) $Id: tclMacFCmd.c,v 1.17 2002/04/19 14:18:45 das Exp $ */ #include "tclInt.h" @@ -154,7 +154,7 @@ DoRenameFile( long srcID, dummy; Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked; - err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); + err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec); if (err == noErr) { FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory); } @@ -417,7 +417,7 @@ DoCopyFile( FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec; Str31 tmpName; - err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); + err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec); if (err == noErr) { err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, &dstIsDirectory); @@ -514,7 +514,7 @@ DoDeleteFile( Boolean isDirectory; long dirID; - err = FSpLocationFromPath(strlen(path), path, &fileSpec); + err = FSpLLocationFromPath(strlen(path), path, &fileSpec); if (err == noErr) { /* * Since FSpDeleteCompat will delete an empty directory, make sure @@ -1166,7 +1166,7 @@ GetFileFinderAttributes( CONST char *native; native=Tcl_FSGetNativePath(fileName); - err = FSpLocationFromPath(strlen(native), + err = FSpLLocationFromPath(strlen(native), native, &fileSpec); if (err == noErr) { @@ -1244,7 +1244,7 @@ GetFileReadOnly( CONST char *native; native=Tcl_FSGetNativePath(fileName); - err = FSpLocationFromPath(strlen(native), + err = FSpLLocationFromPath(strlen(native), native, &fileSpec); if (err == noErr) { @@ -1308,7 +1308,7 @@ SetFileFinderAttributes( CONST char *native; native=Tcl_FSGetNativePath(fileName); - err = FSpLocationFromPath(strlen(native), + err = FSpLLocationFromPath(strlen(native), native, &fileSpec); if (err == noErr) { @@ -1400,7 +1400,7 @@ SetFileReadOnly( CONST char *native; native=Tcl_FSGetNativePath(fileName); - err = FSpLocationFromPath(strlen(native), + err = FSpLLocationFromPath(strlen(native), native, &fileSpec); if (err == noErr) { @@ -1543,8 +1543,8 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) short vRefNum; long dirID; Boolean isDirectory; - Boolean wasAlias; - FSSpec fileSpec; + Boolean wasAlias=FALSE; + FSSpec fileSpec, lastFileSpec; Tcl_DString nativeds; @@ -1570,14 +1570,19 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) nextCheckpoint++; cur = path[nextCheckpoint]; } Tcl_UtfToExternalDString(NULL,path,nextCheckpoint,&nativeds); - err = FSpLocationFromPath(Tcl_DStringLength(&nativeds), + err = FSpLLocationFromPath(Tcl_DStringLength(&nativeds), Tcl_DStringValue(&nativeds), &fileSpec); Tcl_DStringFree(&nativeds); if (err == noErr) { + lastFileSpec=fileSpec; + err = ResolveAliasFile(&fileSpec, true, &isDirectory, + &wasAlias); + if (err == noErr) { err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); currDirValid = ((err == noErr) && isDirectory); vRefNum = fileSpec.vRefNum; + } } break; } @@ -1651,6 +1656,7 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) break; /* arrived at nonexistent file or dir */ } else { /* fileSpec could point to an alias, resolve it */ + lastFileSpec=fileSpec; err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias); if (err != noErr || !isDirectory) { @@ -1669,9 +1675,13 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) /* found a new valid subdir in path, continue processing path */ lastCheckpoint=nextCheckpoint+1; } + wasAlias=FALSE; nextCheckpoint++; } + if (wasAlias) + fileSpec=lastFileSpec; + /* * fileSpec now points to a possibly nonexisting file or dir * inside a valid dir; get full path name to it diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c index 243127c..01c2678 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.19 2002/04/08 09:02:43 das Exp $ + * RCS: @(#) $Id: tclMacFile.c,v 1.20 2002/04/19 14:18:50 das Exp $ */ /* @@ -35,6 +35,8 @@ static int NativeMatchType(Tcl_Obj *tempName, Tcl_GlobTypeData *types, HFileInfo fileInfo, OSType okType, OSType okCreator); static OSErr FspLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr, FSSpec* specPtr)); +static OSErr FspLLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr, + FSSpec* specPtr)); static OSErr FspLocationFromFsPath(pathPtr, specPtr) @@ -45,6 +47,15 @@ FspLocationFromFsPath(pathPtr, specPtr) return FSpLocationFromPath(strlen(native), native, specPtr); } +static OSErr +FspLLocationFromFsPath(pathPtr, specPtr) + Tcl_Obj *pathPtr; + FSSpec* specPtr; +{ + CONST char *native = Tcl_FSGetNativePath(pathPtr); + return FSpLLocationFromPath(strlen(native), native, specPtr); +} + /* *---------------------------------------------------------------------- @@ -166,7 +177,7 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) return TCL_OK; } - if (FspLocationFromFsPath(fileNamePtr, &fileSpec) == noErr) { + if (FspLLocationFromFsPath(fileNamePtr, &fileSpec) == noErr) { paramBlock.hFileInfo.ioCompletion = NULL; paramBlock.hFileInfo.ioNamePtr = fileSpec.name; paramBlock.hFileInfo.ioVRefNum = fileSpec.vRefNum; @@ -438,7 +449,7 @@ TclpObjAccess(pathPtr, mode) long dirID; int full_mode = 0; - err = FspLocationFromFsPath(pathPtr, &fileSpec); + err = FspLLocationFromFsPath(pathPtr, &fileSpec); if (err != noErr) { errno = TclMacOSErrorToPosixError(err); @@ -761,6 +772,10 @@ TclpReadlink( return Tcl_DStringValue(linkPtr); } + +static int +TclpObjStatAlias _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *bufPtr, Boolean resolveLink)); + /* *---------------------------------------------------------------------- @@ -783,8 +798,7 @@ TclpObjLstat(pathPtr, buf) Tcl_Obj *pathPtr; Tcl_StatBuf *buf; { - /* This needs to be enhanced to deal with aliases */ - return TclpObjStat(pathPtr, buf); + return TclpObjStatAlias(pathPtr, buf, FALSE); } /* @@ -808,6 +822,13 @@ TclpObjStat(pathPtr, bufPtr) Tcl_Obj *pathPtr; Tcl_StatBuf *bufPtr; { + return TclpObjStatAlias(pathPtr, bufPtr, TRUE); +} + + +static int +TclpObjStatAlias (Tcl_Obj *pathPtr, Tcl_StatBuf *bufPtr, Boolean resolveLink) +{ HFileInfo fpb; HVolumeParam vpb; OSErr err; @@ -815,7 +836,10 @@ TclpObjStat(pathPtr, bufPtr) Boolean isDirectory; long dirID; - err = FspLocationFromFsPath(pathPtr, &fileSpec); + if (resolveLink) + err = FspLocationFromFsPath(pathPtr, &fileSpec); + else + err = FspLLocationFromFsPath(pathPtr, &fileSpec); if (err != noErr) { errno = TclMacOSErrorToPosixError(err); diff --git a/mac/tclMacUtil.c b/mac/tclMacUtil.c index c505c64..a67eeef 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.5 2001/11/23 01:28:49 das Exp $ + * RCS: @(#) $Id: tclMacUtil.c,v 1.6 2002/04/19 14:18:55 das Exp $ */ #include "tcl.h" @@ -178,6 +178,10 @@ FSpFindFolder( err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec); return err; } + +static int +FSpLocationFromPathAlias _ANSI_ARGS_((int length, CONST char *path, + FSSpecPtr fileSpecPtr, Boolean resolveLink)); /* *---------------------------------------------------------------------- @@ -204,13 +208,52 @@ FSpLocationFromPath( CONST char *path, /* The path to convert. */ FSSpecPtr fileSpecPtr) /* On return the spec for the path. */ { + return FSpLocationFromPathAlias(length, path, fileSpecPtr, TRUE); +} + +/* + *---------------------------------------------------------------------- + * + * FSpLLocationFromPath -- + * + * This function obtains an FSSpec for a given macintosh path. + * Unlike the More Files function FSpLocationFromFullPath, this + * function will also accept partial paths and resolve any aliases + * along the path expect for the last path component. + * + * Results: + * OSErr code. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +FSpLLocationFromPath( + int length, /* Length of path. */ + CONST char *path, /* The path to convert. */ + FSSpecPtr fileSpecPtr) /* On return the spec for the path. */ +{ + return FSpLocationFromPathAlias(length, path, fileSpecPtr, FALSE); +} + +static int +FSpLocationFromPathAlias( + int length, /* Length of path. */ + CONST char *path, /* The path to convert. */ + FSSpecPtr fileSpecPtr, /* On return the spec for the path. */ + Boolean resolveLink) /* Resolve the last path component? */ +{ Str255 fileName; OSErr err; short vRefNum; long dirID; int pos, cur; Boolean isDirectory; - Boolean wasAlias; + Boolean wasAlias=FALSE; + FSSpec lastFileSpec; /* * Check to see if this is a full path. If partial @@ -277,6 +320,7 @@ FSpLocationFromPath( } err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr); if (err != noErr) return err; + lastFileSpec=*fileSpecPtr; err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias); if (err != noErr) return err; FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory); @@ -287,6 +331,9 @@ FSpLocationFromPath( } } + if(!resolveLink && wasAlias) + *fileSpecPtr=lastFileSpec; + return noErr; } -- cgit v0.12