From: Vince Darley Date: Sat, 20 Jul 2002 01:05:12 +0000 (+0000) Subject: link fix X-Git-Tag: vfs-1-2~36 X-Git-Url: http://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=4a9db371737794fdfbfe8427ecc3c1a260d67198;p=tclvfs link fix --- diff --git a/ChangeLog b/ChangeLog index 5a75aec..4f17e6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-07-18 Vince Darley + * generic/vfs.c: ensure all mount activity is with fully + normalized paths in which the last path element is not a link. + Solves (together with latest cvs head changes) a problem in + starting up a tclkit(sh) from a link. + 2002-07-08 Vince Darley * generic/vfs.c: update for latest cvs head. * win/makefile.vc: compilation into Release and Debug diff --git a/generic/vfs.c b/generic/vfs.c index 796cc63..b674424 100644 --- a/generic/vfs.c +++ b/generic/vfs.c @@ -266,6 +266,7 @@ static void Vfs_RegisterWithInterp _ANSI_ARGS_((Tcl_Interp*)); static VfsNativeRep* VfsGetNativePath(Tcl_Obj* pathObjPtr); static Tcl_CloseProc VfsCloseProc; static void VfsExitProc(ClientData clientData); +static Tcl_Obj* VfsFullyNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr); static Tcl_Obj* VfsBuildCommandForPath(Tcl_Interp **iRef, CONST char* cmd, Tcl_Obj * pathPtr); @@ -679,11 +680,11 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) int index; static CONST char *optionStrings[] = { - "info", "mount", "unmount", + "info", "mount", "unmount", "fullynormalize", NULL }; enum options { - VFS_INFO, VFS_MOUNT, VFS_UNMOUNT + VFS_INFO, VFS_MOUNT, VFS_UNMOUNT, VFS_NORMALIZE }; if (objc < 2) { @@ -696,8 +697,24 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) } switch ((enum options) index) { - case VFS_MOUNT: { - int i; + case VFS_NORMALIZE: { + Tcl_Obj *path; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "path"); + return TCL_ERROR; + } + path = VfsFullyNormalizePath(interp, objv[2]); + if (path == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "not a valid path \"", Tcl_GetString(objv[2]), + "\"", (char *) NULL); + } else { + Tcl_SetObjResult(interp, path); + Tcl_DecrRefCount(path); + return TCL_OK; + } + } + case VFS_MOUNT: { if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "mount ?-volume? path cmd"); return TCL_ERROR; @@ -710,13 +727,14 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) "\": must be -volume", (char *) NULL); return TCL_ERROR; } - i = 3; - return Vfs_AddMount(objv[i], 1, interp, objv[i+1]); + return Vfs_AddMount(objv[3], 1, interp, objv[4]); } else { Tcl_Obj *path; - i = 2; - path = Tcl_FSGetNormalizedPath(interp, objv[i]); - return Vfs_AddMount(path, 0, interp, objv[i+1]); + int retVal; + path = VfsFullyNormalizePath(interp, objv[2]); + retVal = Vfs_AddMount(path, 0, interp, objv[3]); + if (path != NULL) Tcl_DecrRefCount(path); + return retVal; } break; } @@ -732,8 +750,10 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) val = Vfs_FindMount(objv[2], -1); if (val == NULL) { - Tcl_Obj *path = Tcl_FSGetNormalizedPath(interp, objv[2]); + Tcl_Obj *path; + path = VfsFullyNormalizePath(interp, objv[2]); val = Vfs_FindMount(path, -1); + Tcl_DecrRefCount(path); if (val == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such mount \"", Tcl_GetString(objv[2]), @@ -751,9 +771,12 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) return TCL_ERROR; } if (Vfs_RemoveMount(objv[2], interp) == TCL_ERROR) { - Tcl_Obj * path; - path = Tcl_FSGetNormalizedPath(interp, objv[2]); - if (Vfs_RemoveMount(path, interp) == TCL_ERROR) { + Tcl_Obj *path; + int retVal; + path = VfsFullyNormalizePath(interp, objv[2]); + retVal = Vfs_RemoveMount(path, interp); + Tcl_DecrRefCount(path); + if (retVal == TCL_ERROR) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such mount \"", Tcl_GetString(objv[2]), "\"", (char *) NULL); @@ -765,7 +788,33 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv) } return TCL_OK; } - + +/* Return fully normalized path owned by the caller */ +static Tcl_Obj* +VfsFullyNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr) { + Tcl_Obj *path; + int counter = 0; + + Tcl_IncrRefCount(pathPtr); + while (1) { + path = Tcl_FSLink(pathPtr,NULL,0); + if (path == NULL) { + break; + } + Tcl_DecrRefCount(pathPtr); + pathPtr = path; + counter++; + if (counter > 10) { + /* Too many links */ + Tcl_DecrRefCount(pathPtr); + return NULL; + } + } + path = Tcl_FSGetNormalizedPath(interp, pathPtr); + Tcl_IncrRefCount(path); + Tcl_DecrRefCount(pathPtr); + return path; +} /* *---------------------------------------------------------------------- *