Attachment "TclObjNormalizePath.c" to
ticket [929534ffff]
added by
tauvan
2004-04-30 22:38:56.
/*
* 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;
}