94b3342ec1b9abe3993347c967b652f2e91ecf57 angie Thu May 16 12:18:49 2019 -0700 When saving a trash path that is already a link, if it is a relative link (e.g. to ../../userdata/ct/xyz) then resolve it to a full path. refs #22440 diff --git src/hg/hgSession/sessionData.c src/hg/hgSession/sessionData.c index 6c339e3..6d0b764 100644 --- src/hg/hgSession/sessionData.c +++ src/hg/hgSession/sessionData.c @@ -63,41 +63,53 @@ } } static void moveAndLink(char *oldPath, char *newPath) /* Make a hard link from newPath to oldPath; unlink oldPath; symlink oldPath to newPath. */ { if (link(oldPath, newPath) != 0) errnoAbort("moveAndLink: link(oldPath='%s', newPath='%s') failed", oldPath, newPath); if (unlink(oldPath) != 0) errnoAbort("moveAndLink: unlink(oldPath='%s') failed", oldPath); if (symlink(newPath, oldPath) != 0) errnoAbort("moveAndLink: symlink(newPath='%s', oldPath='%s') failed", newPath, oldPath); } static char *saveTrashFile(char *trashPath, char *sessionDir) -/* If trashPath exists and is not already a soft-link, alloc and return a new path in +/* If trashPath exists and is not already a soft-link to sessionDir, alloc and return a new path in * sessionDir; move trashPath to new path and soft-link from trashPath to new path. * If trashPath is already a soft-link, return the path that it links to. * Return NULL if trashPath does not exist (can happen with expired custom track files). */ { char *newPath = NULL; if (fileExists(trashPath)) { char *existingLink = maybeReadlink(trashPath); if (existingLink) + { + // It may be a multi-directory-level relative symlink created by the trashCleaner scripts + if (existingLink[0] != '/') + { + char trashPathDir[PATH_LEN]; + splitPath(trashPath, trashPathDir, NULL, NULL); + char fullLinkPath[strlen(trashPathDir) + strlen(existingLink) + 1]; + safef(fullLinkPath, sizeof fullLinkPath, "%s%s", trashPathDir, existingLink); + newPath = realpath(fullLinkPath, NULL); + } + else newPath = existingLink; + } else { newPath = sessionDataPathFromTrash(trashPath, sessionDir); if (fileExists(newPath)) errAbort("saveTrashFile: new path '%s' already exists", newPath); makeDirsForFile(newPath); moveAndLink(trashPath, newPath); } } return newPath; } static char *nextTrashPath(char *string, char *trashDirPrefix) /* Alloc & return the next file path in string that starts with "../trash/", or NULL. */ {