void showSymlinkType(char *submitFileName, char *submitDir) /* Show symlink type */ { struct stat sb; char *lastPath = NULL; char *path = cloneString(submitFileName); // apply path to submitDir, giving an absolute path char *newPath = expandRelativePath(submitDir, path); verbose(3, "submitDir=[%s]\npath=[%s]\nnewPath=[%s]\n", submitDir, path, newPath); if (!newPath) errAbort("Too many .. in path %s to make relative to submitDir %s\n", path, submitDir); freeMem(path); path = newPath; struct dyString *dy = dyStringNew(256); int symlinkLevels = 0; boolean broken = FALSE; while (TRUE) { dyStringPrintf(dy,"path=%s", path); if (lstat(path, &sb) == -1) { if (errno == ENOENT) { dyStringPrintf(dy," NOT FOUND"); broken = TRUE; break; } errnoAbort("lstat failure on %s", path); } if ((sb.st_mode & S_IFMT) == S_IFLNK) dyStringPrintf(dy," SYMLINK "); else if ((sb.st_mode & S_IFMT) == S_IFREG) dyStringPrintf(dy," FILE"); else if ((sb.st_mode & S_IFMT) == S_IFDIR) dyStringPrintf(dy," DIR"); else dyStringPrintf(dy," SPECIAL"); if ((sb.st_mode & S_IFMT) != S_IFLNK) break; // follow the symlink ++symlinkLevels; if (symlinkLevels > 10) errAbort("Too many symlinks followed: %d symlinks. Probably a symlink loop.", symlinkLevels); // read the symlink ssize_t nbytes, bufsiz; // determine whether the buffer returned was truncated. bufsiz = sb.st_size + 1; char *symPath = needMem(bufsiz); nbytes = readlink(path, symPath, bufsiz); if (nbytes == -1) errnoAbort("readlink failure on symlink %s", path); if (nbytes == bufsiz) errAbort("readlink returned buffer truncated\n"); // apply symPath to path newPath = pathRelativeToFile(path, symPath); verbose(3, "path=%s\nsymPath=%s\nnewPath=%s\n", path, symPath, newPath); if (!newPath) errAbort("Too many .. in symlink path %s to make relative to %s\n", symPath, path); if (lastPath) freeMem(lastPath); lastPath = path; freeMem(symPath); path = newPath; } if (symlinkLevels < 1) { errAbort("Too few symlinks followed: %d symlinks. dy=[%s]", symlinkLevels, dy->string); } freeMem(path); if (!(brokenOnly && !broken)) printf("%s\n", dy->string); dyStringFree(&dy); }
char *htmlExpandUrl(char *base, char *url) /* Expand URL that is relative to base to stand on its own. * Return NULL if it's not http or https. */ { struct dyString *dy = NULL; char *hostName, *pastHostName; /* some mailto: have SGML char encoding, e.g a to hide from spambots */ url = cloneString(url); /* Clone because asciiEntityDecode may modify it. */ asciiEntityDecode(url, url, strlen(url)); /* In easiest case URL is actually absolute and begins with * protocol. Just return clone of url. */ if (startsWith("http:", url) || startsWith("https:", url)) return url; /* If it's got a colon, but no http or https, then it's some * protocol we don't understand, like a mailto. Just return NULL. */ if (strchr(url, ':') != NULL) { freez(&url); return NULL; } /* Figure out first character past host name. Load up * return string with protocol (if any) and host name. */ dy = dyStringNew(256); if (startsWith("http:", base) || startsWith("https:", base)) hostName = (strchr(base, ':') + 3); else hostName = base; pastHostName = strchr(hostName, '/'); if (pastHostName == NULL) pastHostName = hostName + strlen(hostName); dyStringAppendN(dy, base, pastHostName - base); /* Add url to return string after host name. */ if (startsWith("/", url)) /* New URL is absolute, just append to hostName */ { dyStringAppend(dy, url); } else { char *curDir = pastHostName; char *endDir; if (curDir[0] == '/') curDir += 1; dyStringAppendC(dy, '/'); endDir = strrchr(curDir, '/'); if (endDir == NULL) endDir = curDir; if (startsWith("../", url)) { char *dir = cloneStringZ(curDir, endDir-curDir); char *path = expandRelativePath(dir, url); if (path != NULL) { dyStringAppend(dy, path); } freez(&dir); freez(&path); } else { dyStringAppendN(dy, curDir, endDir-curDir); if (lastChar(dy->string) != '/') dyStringAppendC(dy, '/'); dyStringAppend(dy, url); } } freez(&url); return dyStringCannibalize(&dy); }