diff options
| author | vincentdarley <vincentdarley> | 2002-03-24 11:41:48 (GMT) | 
|---|---|---|
| committer | vincentdarley <vincentdarley> | 2002-03-24 11:41:48 (GMT) | 
| commit | d7fcb90540b8bbb6b22dd2ddbddcd14abc8d382c (patch) | |
| tree | 9e9a209ca39c12dd8d45b40c876c1478bd022c1a /unix/tclUnixFCmd.c | |
| parent | 6b2f093c42f3559f40f1c82297d09f5388d596f6 (diff) | |
| download | tcl-d7fcb90540b8bbb6b22dd2ddbddcd14abc8d382c.zip tcl-d7fcb90540b8bbb6b22dd2ddbddcd14abc8d382c.tar.gz tcl-d7fcb90540b8bbb6b22dd2ddbddcd14abc8d382c.tar.bz2  | |
4 fs fixes
Diffstat (limited to 'unix/tclUnixFCmd.c')
| -rw-r--r-- | unix/tclUnixFCmd.c | 80 | 
1 files changed, 64 insertions, 16 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 80383d8..49131de 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.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: tclUnixFCmd.c,v 1.17 2002/02/15 14:28:50 dkf Exp $ + * RCS: @(#) $Id: tclUnixFCmd.c,v 1.18 2002/03/24 11:41:51 vincentdarley Exp $   *   * Portions of this code were derived from NetBSD source code which has   * the following copyright notice: @@ -191,7 +191,7 @@ TclpObjRenameFile(srcPathPtr, destPathPtr)      Tcl_Obj *srcPathPtr;      Tcl_Obj *destPathPtr;  { -    return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr), +    return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),   			Tcl_FSGetNativePath(destPathPtr));  } @@ -308,7 +308,7 @@ TclpObjCopyFile(srcPathPtr, destPathPtr)      Tcl_Obj *srcPathPtr;      Tcl_Obj *destPathPtr;  { -    return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr), +    return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr),   		      Tcl_FSGetNativePath(destPathPtr));  } @@ -1618,17 +1618,17 @@ GetModeFromPermString(interp, modeStringPtr, modePtr)   * TclpObjNormalizePath --   *   *	This function scans through a path specification and replaces - *	it, in place, with a normalized version.  On unix, this simply - *	ascertains where the valid path ends, and makes no change in - *	place. + *	it, in place, with a normalized version.  A normalized version + *	is one in which all symlinks in the path are replaced with + *	their expanded form (except a symlink at the very end of the + *	path).   *   * Results:   *	The new 'nextCheckpoint' value, giving as far as we could   *	understand in the path.   *   * Side effects: - *	The pathPtr string, which must contain a valid path, is - *	not modified (unlike Windows, MacOS versions). + *	The pathPtr string, is modified.   *   *---------------------------------------------------------------------------   */ @@ -1640,13 +1640,15 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)      int nextCheckpoint;  {      char *currentPathEndPosition; -    char *path = Tcl_GetString(pathPtr); +    int pathLen; +    char cur; +    char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);      currentPathEndPosition = path + nextCheckpoint;      while (1) { -	char cur = *currentPathEndPosition; -	if ((cur == '/' || cur == 0) && (path != currentPathEndPosition)) { +	cur = *currentPathEndPosition; +	if ((cur == '/') && (path != currentPathEndPosition)) {  	    /* Reached directory separator, or end of string */  	    Tcl_DString ds;  	    CONST char *nativePath; @@ -1660,13 +1662,59 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)  		/* File doesn't exist */  		break;  	    } -	    if (cur == 0) { -		break; -	    } +	    /* Update the acceptable point */ +	    nextCheckpoint = currentPathEndPosition - path; +	} else if (cur == 0) { +	    break;  	}  	currentPathEndPosition++;      } -    nextCheckpoint = currentPathEndPosition - path; -    /* We should really now convert this to a canonical path */ +    /*  +     * We should really now convert this to a canonical path.  We do +     * that with 'realpath' if we have it available.  Otherwise we could +     * step through every single path component, checking whether it is a  +     * symlink, but that would be a lot of work, and most modern OSes  +     * have 'realpath'. +     */ +#ifndef NO_REALPATH +    if (1) { +	char normPath[MAXPATHLEN]; +	Tcl_DString ds; +	CONST char *nativePath = Tcl_UtfToExternalDString(NULL, path,  +						   nextCheckpoint, &ds); +	 +	if (realpath((char *) nativePath, normPath) != NULL) { +	    /*  +	     * Free up the native path and put in its place the +	     * converted, normalized path. +	     */ +	    Tcl_DStringFree(&ds); +	    Tcl_ExternalToUtfDString(NULL,normPath, +                                     strlen(normPath),&ds); + +	    if (path[nextCheckpoint] != '\0') { +		/* not at end, append remaining path */ +	        int normLen = Tcl_DStringLength(&ds); +		Tcl_DStringAppend(&ds, path + nextCheckpoint, +				  pathLen - nextCheckpoint); +                /*  +                 * We recognise up to and including the directory +                 * separator. +		 */	 +	        nextCheckpoint = normLen + 1; +	    } else { +	        /* We recognise the whole string */  +	        nextCheckpoint = Tcl_DStringLength(&ds); +	    } +	    /*  +	     * Overwrite with the normalized path. +	     */ +	    Tcl_SetStringObj(pathPtr,Tcl_DStringValue(&ds), +			     Tcl_DStringLength(&ds)); +	} +	Tcl_DStringFree(&ds); +    } +#endif	/* !NO_REALPATH */ +      return nextCheckpoint;  }  | 
