#include #if defined(PETSC_HAVE_PWD_H) #include #endif /*@C PetscGetFullPath - Given a filename, returns the fully qualified file name. Not Collective Input Parameters: + path - pathname to qualify - flen - size of `fullpath` Output Parameter: . fullpath - buffer to hold the full pathname Level: developer Note: Converts `~username/` and `~/` to appropriate forms Developer Note: On Microsoft Windows full paths may begin with DriveLetter\: so these must be properly handled .seealso: `PetscGetRelativePath()` @*/ PetscErrorCode PetscGetFullPath(const char path[], char fullpath[], size_t flen) { size_t ln; PetscBool flg; PetscFunctionBegin; if (path[0] == '/') { PetscCall(PetscStrncmp("/tmp_mnt/", path, 9, &flg)); if (flg) PetscCall(PetscStrncpy(fullpath, path + 8, flen)); else PetscCall(PetscStrncpy(fullpath, path, flen)); fullpath[flen - 1] = 0; PetscFunctionReturn(PETSC_SUCCESS); } #if defined(PETSC_HAVE_WINDOWS_H) if (path[1] == ':') { PetscCall(PetscStrncpy(fullpath, path, flen)); PetscFunctionReturn(PETSC_SUCCESS); } #endif if (path[0] == '.' && path[1] == '/') { PetscCall(PetscGetWorkingDirectory(fullpath, flen)); PetscCall(PetscStrlcat(fullpath, path + 1, flen)); PetscFunctionReturn(PETSC_SUCCESS); } PetscCall(PetscStrncpy(fullpath, path, flen)); fullpath[flen - 1] = 0; /* Remove the various "special" forms (~username/ and ~/) */ if (fullpath[0] == '~') { char tmppath[PETSC_MAX_PATH_LEN], *rest; if (fullpath[1] == '/') { PetscCall(PetscGetHomeDirectory(tmppath, PETSC_MAX_PATH_LEN)); rest = fullpath + 2; } else { #if defined(PETSC_HAVE_PWD_H) struct passwd *pwde; char *p, *name; /* Find username */ name = fullpath + 1; p = name; while (*p && *p != '/') p++; *p = 0; rest = p + 1; pwde = getpwnam(name); if (!pwde) PetscFunctionReturn(PETSC_SUCCESS); PetscCall(PetscStrncpy(tmppath, pwde->pw_dir, sizeof(tmppath))); #else PetscFunctionReturn(PETSC_SUCCESS); #endif } PetscCall(PetscStrlen(tmppath, &ln)); if (tmppath[ln - 1] != '/') PetscCall(PetscStrlcat(tmppath + ln - 1, "/", sizeof(tmppath) - ln + 1)); PetscCall(PetscStrlcat(tmppath, rest, sizeof(tmppath))); PetscCall(PetscStrncpy(fullpath, tmppath, flen)); fullpath[flen - 1] = 0; } else { PetscCall(PetscGetWorkingDirectory(fullpath, flen)); PetscCall(PetscStrlen(fullpath, &ln)); PetscCall(PetscStrncpy(fullpath + ln, "/", flen - ln)); fullpath[flen - 1] = 0; PetscCall(PetscStrlen(fullpath, &ln)); if (path[0] == '.' && path[1] == '/') { PetscCall(PetscStrlcat(fullpath, path + 2, flen)); } else { PetscCall(PetscStrlcat(fullpath, path, flen)); } fullpath[flen - 1] = 0; } /* Remove the automounter part of the path */ PetscCall(PetscStrncmp(fullpath, "/tmp_mnt/", 9, &flg)); if (flg) { char tmppath[PETSC_MAX_PATH_LEN]; PetscCall(PetscStrncpy(tmppath, fullpath + 8, sizeof(tmppath))); PetscCall(PetscStrncpy(fullpath, tmppath, flen)); } /* We could try to handle things like the removal of .. etc */ PetscFunctionReturn(PETSC_SUCCESS); }