/* * findPath.c * * * Created by Steven J Abner on Wed Apr 28 2004. * Copyright (c) 2004. Any and All may use as they wish. * No warranties implied. * */ static void findPath(const char *orgPath, char **retPath, int *idx) { struct stat curStatBuf; char *newName = NULL; char *pathBuffer = *retPath; int pBdex = 0, oPdex = *idx, redex; int oPlen = strlen(orgPath); errno = 0; if (pathBuffer == NULL) { pathBuffer = (char *)malloc(2*MAXPATHLEN + 1); bzero(pathBuffer, MAXPATHLEN); *retPath = pathBuffer; } if (oPdex == 0 && orgPath[0] != '/') { /* home code needed for running cmdAH.test */ char *home = getenv("HOME"); int i = strlen(home); if (i != oPlen) { for (i--; i >= 0; i--) { if (home[i + 1] != orgPath[i] && home[i + 1] != '/') break; } if (i < 0) { oPlen = strlen(home); do { pathBuffer[pBdex] = home[oPdex]; pBdex++; oPdex++; } while (oPdex < oPlen); pathBuffer[pBdex] = 0; return; } } else if (orgPath[0] == '~') { do { pathBuffer[pBdex] = home[oPdex]; pBdex++; oPdex++; } while (oPdex < oPlen); pathBuffer[pBdex] = 0; return; } getcwd(pathBuffer, (2*MAXPATHLEN)); pBdex = *idx = strlen(pathBuffer); pathBuffer[pBdex++] = '/'; do { pathBuffer[pBdex] = orgPath[oPdex]; pBdex++; oPdex++; } while (oPdex < oPlen); pathBuffer[pBdex] = 0; findPath(pathBuffer, &newName, idx); free(pathBuffer); *retPath = newName; return; } while (pBdex < oPdex) pathBuffer[pBdex++] = orgPath[pBdex]; oPdex = pBdex; findnext: redex = oPdex + 1; do { pathBuffer[pBdex] = orgPath[oPdex]; pBdex++; oPdex++; } while (orgPath[oPdex] != '/' && oPdex < oPlen); if (oPdex == oPlen) { *idx = redex - 1; return; } lstat(pathBuffer, &curStatBuf); if (S_ISLNK(curStatBuf.st_mode)) { int normPathLen; normPathLen = readlink(pathBuffer, (&pathBuffer[redex]), (2*MAXPATHLEN - redex)); pathBuffer[redex + normPathLen] = 0; if (pathBuffer[redex] == '/') { pBdex = 0; do { pathBuffer[pBdex] = pathBuffer[redex]; pBdex++; redex++; } while (--normPathLen > 0); } else { pBdex = redex + normPathLen; } do { pathBuffer[pBdex] = orgPath[oPdex]; pBdex++; oPdex++; } while (oPdex < oPlen); pathBuffer[pBdex] = 0; *idx = 0; findPath(pathBuffer, &newName, idx); free(pathBuffer); *retPath = newName; return; } if (errno) { do { pathBuffer[pBdex] = orgPath[oPdex]; pBdex++; oPdex++; } while (oPdex < oPlen); pathBuffer[pBdex] = 0; *idx = redex - 1; return; } goto findnext; } /* * TclObjNormalizePath.c * * This function takes a path string and replaces it * with a normalized path. The entering path string * must be void of ../, ./ sequences. The returned path * will be normalized up to nextCheckpoint, which points to * either the last path separator or the offending separator. * The end word of the path will not be normalized, it is * totally ignored. * * Results: * pathPtr altered with result of normalization * nextCheckpoint points to end separator or offending, * ie.. the last good separator prior to problem path * * Side effects: * if nextCheckpoint points to end separator, do not * make assumption of a fully qualified path. * Occurance: when "join" adds to a file instead of directory. * The file will be normalized but is not a directory. * * Returns: * nextCheckpoint * pathPtr */ int TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) Tcl_Interp *interp; Tcl_Obj *pathPtr; int nextCheckpoint; { int pathLen; char *resolvedPath = NULL; char *path = Tcl_GetStringFromObj(pathPtr, &pathLen); nextCheckpoint = 0; findPath(path, &resolvedPath, &nextCheckpoint); if (resolvedPath) { Tcl_DString ds; pathLen = strlen(resolvedPath); Tcl_ExternalToUtfDString(NULL, resolvedPath, pathLen, &ds); Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); free(resolvedPath); } return nextCheckpoint; }