diff options
| author | vincentdarley <vincentdarley> | 2003-12-17 17:47:27 (GMT) | 
|---|---|---|
| committer | vincentdarley <vincentdarley> | 2003-12-17 17:47:27 (GMT) | 
| commit | 298b0c4ef39a21c71fcb823f41bb903203d8430b (patch) | |
| tree | 90eee000212ab783686879d39d2836490e8198c8 /unix/tclUnixFile.c | |
| parent | 1e34c25106c2c1a8713ef0aef0ffc4d2eccdbeeb (diff) | |
| download | tcl-298b0c4ef39a21c71fcb823f41bb903203d8430b.zip tcl-298b0c4ef39a21c71fcb823f41bb903203d8430b.tar.gz tcl-298b0c4ef39a21c71fcb823f41bb903203d8430b.tar.bz2 | |
fix to file normalization with relative links
Diffstat (limited to 'unix/tclUnixFile.c')
| -rw-r--r-- | unix/tclUnixFile.c | 58 | 
1 files changed, 47 insertions, 11 deletions
| diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 66c31b9..96d2fda 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.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: tclUnixFile.c,v 1.35 2003/12/12 17:09:34 vincentdarley Exp $ + * RCS: @(#) $Id: tclUnixFile.c,v 1.36 2003/12/17 17:47:28 vincentdarley Exp $   */  #include "tclInt.h" @@ -715,21 +715,57 @@ TclpObjLink(pathPtr, toPtr, linkAction)  {      if (toPtr != NULL) {  	CONST char *src = Tcl_FSGetNativePath(pathPtr); -	CONST char *target = Tcl_FSGetNativePath(toPtr); +	CONST char *target = NULL; +	if (src == NULL) return NULL; -	if (src == NULL || target == NULL) { -	    return NULL; +	/*  +	 * If we're making a symbolic link and the path is relative, +	 * then we must check whether it exists _relative_ to the +	 * directory in which the src is found (not relative to the +	 * current cwd which is just not relevant in this case). +	 *  +	 * If we're making a hard link, then a relative path is +	 * just converted to absolute relative to the cwd. +	 */ +	if ((linkAction & TCL_CREATE_SYMBOLIC_LINK) +	  && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) { +	    Tcl_Obj *dirPtr, *absPtr; +	    dirPtr = TclFileDirname(NULL, pathPtr); +	    if (dirPtr == NULL) { +	        return NULL; +	    } +	    absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr); +	    Tcl_IncrRefCount(absPtr); +	    if (Tcl_FSAccess(absPtr, F_OK) == -1) { +		Tcl_DecrRefCount(absPtr); +		Tcl_DecrRefCount(dirPtr); +		/* target doesn't exist */ +		errno = ENOENT; +	        return NULL; +	    } +	    /*  +	     * Target exists; we'll construct the relative +	     * path we want below. +	     */ +	    Tcl_DecrRefCount(absPtr); +	    Tcl_DecrRefCount(dirPtr); +	} else { +	    target = Tcl_FSGetNativePath(toPtr); +	    if (access(target, F_OK) == -1) { +		/* target doesn't exist */ +		errno = ENOENT; +		return NULL; +	    } +	    if (target == NULL) { +		return NULL; +	    }  	} +	  	if (access(src, F_OK) != -1) {  	    /* src exists */  	    errno = EEXIST;  	    return NULL;  	} -	if (access(target, F_OK) == -1) { -	    /* target doesn't exist */ -	    errno = ENOENT; -	    return NULL; -	}  	/*   	 * Check symbolic link flag first, since we prefer to  	 * create these. @@ -740,8 +776,8 @@ TclpObjLink(pathPtr, toPtr, linkAction)  	    Tcl_Obj *transPtr;  	    /*   	     * Now we don't want to link to the absolute, normalized path. -	     * Relative links are quite acceptable, as are links to '~user', -	     * for example. +	     * Relative links are quite acceptable (but links to ~user +	     * are not -- these must be expanded first).  	     */  	    transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);  	    if (transPtr == NULL) { | 
