Tcl Source Code

Artifact [7a5b85f57a]
Login

Artifact 7a5b85f57a1d44f4bb48b8faf94f2ce930dc2e37:

Attachment "tcl-mac-aliases.patch" to ticket [511666ffff] added by das 2002-04-19 21:17:25.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.959
diff -u -3 -r1.959 ChangeLog
--- ChangeLog	18 Apr 2002 18:05:55 -0000	1.959
+++ ChangeLog	19 Apr 2002 14:10:24 -0000
@@ -1,3 +1,17 @@
+2002-04-20  Daniel Steffen  <[email protected]>
+
+	* 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-18  Miguel Sofer  <[email protected]>
 
 	* generic/tclNamesp.c:
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.47
diff -u -3 -r1.47 tclInt.decls
--- generic/tclInt.decls	20 Mar 2002 22:47:36 -0000	1.47
+++ generic/tclInt.decls	19 Apr 2002 14:10:14 -0000
@@ -780,6 +780,10 @@
 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
Index: generic/tclIntPlatDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntPlatDecls.h,v
retrieving revision 1.16
diff -u -3 -r1.16 tclIntPlatDecls.h
--- generic/tclIntPlatDecls.h	27 Jan 2002 11:09:34 -0000	1.16
+++ generic/tclIntPlatDecls.h	19 Apr 2002 14:10:14 -0000
@@ -198,6 +198,9 @@
 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 @@
     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;
 
@@ -532,6 +536,10 @@
 #ifndef TclMacChmod
 #define TclMacChmod \
 	(tclIntPlatStubsPtr->tclMacChmod) /* 25 */
+#endif
+#ifndef FSpLLocationFromPath
+#define FSpLLocationFromPath \
+	(tclIntPlatStubsPtr->fSpLLocationFromPath) /* 26 */
 #endif
 #endif /* MAC_TCL */
 
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.68
diff -u -3 -r1.68 tclStubInit.c
--- generic/tclStubInit.c	15 Feb 2002 14:28:49 -0000	1.68
+++ generic/tclStubInit.c	19 Apr 2002 14:10:14 -0000
@@ -322,6 +322,7 @@
     TclMacFOpenHack, /* 23 */
     TclpGetTZName, /* 24 */
     TclMacChmod, /* 25 */
+    FSpLLocationFromPath, /* 26 */
 #endif /* MAC_TCL */
 };
 
Index: mac/tclMacFCmd.c
===================================================================
RCS file: /cvsroot/tcl/tcl/mac/tclMacFCmd.c,v
retrieving revision 1.16
diff -u -3 -r1.16 tclMacFCmd.c
--- mac/tclMacFCmd.c	27 Jan 2002 11:09:44 -0000	1.16
+++ mac/tclMacFCmd.c	19 Apr 2002 14:10:16 -0000
@@ -154,7 +154,7 @@
     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 @@
     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 @@
     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 @@
     CONST char *native;
 
     native=Tcl_FSGetNativePath(fileName);
-    err = FSpLocationFromPath(strlen(native),
+    err = FSpLLocationFromPath(strlen(native),
 	    native, &fileSpec);
 
     if (err == noErr) {
@@ -1244,7 +1244,7 @@
     CONST char *native;
 
     native=Tcl_FSGetNativePath(fileName);
-    err = FSpLocationFromPath(strlen(native),
+    err = FSpLLocationFromPath(strlen(native),
 	    native, &fileSpec);
     
     if (err == noErr) {
@@ -1308,7 +1308,7 @@
     CONST char *native;
 
     native=Tcl_FSGetNativePath(fileName);
-    err = FSpLocationFromPath(strlen(native),
+    err = FSpLLocationFromPath(strlen(native),
 	    native, &fileSpec);
     
     if (err == noErr) {
@@ -1400,7 +1400,7 @@
     CONST char *native;
 
     native=Tcl_FSGetNativePath(fileName);
-    err = FSpLocationFromPath(strlen(native),
+    err = FSpLLocationFromPath(strlen(native),
 	    native, &fileSpec);
     
     if (err == noErr) {
@@ -1543,8 +1543,8 @@
     short vRefNum;
     long dirID;
     Boolean isDirectory;
-    Boolean wasAlias;
-    FSSpec fileSpec;
+    Boolean wasAlias=FALSE;
+    FSSpec fileSpec, lastFileSpec;
     
     Tcl_DString nativeds;
 
@@ -1570,14 +1570,19 @@
 		    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 @@
     		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,8 +1675,12 @@
 	    /* 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
Index: mac/tclMacFile.c
===================================================================
RCS file: /cvsroot/tcl/tcl/mac/tclMacFile.c,v
retrieving revision 1.19
diff -u -3 -r1.19 tclMacFile.c
--- mac/tclMacFile.c	8 Apr 2002 09:02:43 -0000	1.19
+++ mac/tclMacFile.c	19 Apr 2002 14:10:16 -0000
@@ -35,6 +35,8 @@
 			   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 @@
     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 @@
 	    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 @@
     long dirID;
     int full_mode = 0;
 
-    err = FspLocationFromFsPath(pathPtr, &fileSpec);
+    err = FspLLocationFromFsPath(pathPtr, &fileSpec);
 
     if (err != noErr) {
 	errno = TclMacOSErrorToPosixError(err);
@@ -761,6 +772,10 @@
     
     return Tcl_DStringValue(linkPtr);
 }
+
+static int 
+TclpObjStatAlias _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *bufPtr, Boolean resolveLink));
+
 
 /*
  *----------------------------------------------------------------------
@@ -783,8 +798,7 @@
     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 @@
     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 @@
     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);
Index: mac/tclMacUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/mac/tclMacUtil.c,v
retrieving revision 1.5
diff -u -3 -r1.5 tclMacUtil.c
--- mac/tclMacUtil.c	23 Nov 2001 01:28:49 -0000	1.5
+++ mac/tclMacUtil.c	19 Apr 2002 14:10:16 -0000
@@ -178,6 +178,10 @@
     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 @@
     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 @@
 	}
 	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);
@@ -286,6 +330,9 @@
 	    cur++;
 	}
     }
+    
+    if(!resolveLink && wasAlias)
+    	*fileSpecPtr=lastFileSpec;
     
     return noErr;
 }