Actual source code: grpath.c
1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for realpath() */
2: #include <petscsys.h>
3: #if defined(PETSC_HAVE_PWD_H)
4: #include <pwd.h>
5: #endif
6: #include <ctype.h>
7: #include <sys/stat.h>
8: #if defined(PETSC_HAVE_UNISTD_H)
9: #include <unistd.h>
10: #endif
11: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
12: #include <sys/utsname.h>
13: #endif
14: #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
15: #include <sys/systeminfo.h>
16: #endif
17: #include <errno.h>
19: /*@C
20: PetscGetRealPath - Get the path without symbolic links etc. in absolute form.
22: Not Collective
24: Input Parameter:
25: . path - path to resolve
27: Output Parameter:
28: . rpath - resolved path
30: Level: developer
32: Notes:
33: rpath is assumed to be of length `PETSC_MAX_PATH_LEN`.
35: Systems that use the automounter often generate absolute paths
36: of the form "/tmp_mnt....". However, the automounter will fail to
37: mount this path if it is not already mounted, so we remove this from
38: the head of the line. This may cause problems if, for some reason,
39: /tmp_mnt is valid and not the result of the automounter.
41: .seealso: `PetscGetFullPath()`
42: @*/
43: PetscErrorCode PetscGetRealPath(const char path[], char rpath[])
44: {
45: #if !defined(PETSC_HAVE_REALPATH) && defined(PETSC_HAVE_READLINK)
46: char tmp1[PETSC_MAX_PATH_LEN], char tmp3[PETSC_MAX_PATH_LEN], tmp4[PETSC_MAX_PATH_LEN], *tmp2;
47: size_t N, len1, len2;
48: int n, m;
49: #endif
50: size_t len;
52: PetscFunctionBegin;
53: #if defined(PETSC_HAVE_REALPATH)
54: PetscCheck(realpath(path, rpath), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in realpath() due to \"%s\"", strerror(errno));
55: #else
56: #if defined(PETSC_HAVE_READLINK)
57: /* Algorithm: we move through the path, replacing links with the real paths. */
58: PetscCall(PetscStrlen(path, &N));
59: PetscCall(PetscStrncpy(rpath, path, N + 1)); /* assuming adequate buffer */
60: PetscCall(PetscStrlen(rpath, &N));
61: while (N) {
62: PetscCall(PetscStrncpy(tmp1, rpath, N));
63: tmp1[N] = 0;
64: n = readlink(tmp1, tmp3, PETSC_MAX_PATH_LEN);
65: PetscCheck(n > -1, PETSC_COMM_SELF, PETSC_ERR_SYS, "Error in readlink() due to \"%\"", strerror(errno));
66: if (n > 0) {
67: tmp3[n] = 0; /* readlink does not automatically add 0 to string end */
68: if (tmp3[0] != '/') {
69: PetscCall(PetscStrchr(tmp1, '/', &tmp2));
70: PetscCall(PetscStrlen(tmp1, &len1));
71: PetscCall(PetscStrlen(tmp2, &len2));
72: m = len1 - len2;
73: PetscCall(PetscStrncpy(tmp4, tmp1, m));
74: tmp4[m] = 0;
75: PetscCall(PetscStrlen(tmp4, &len));
76: PetscCall(PetscStrlcat(tmp4, "/", PETSC_MAX_PATH_LEN));
77: PetscCall(PetscStrlcat(tmp4, tmp3, PETSC_MAX_PATH_LEN));
78: PetscCall(PetscGetRealPath(tmp4, rpath));
79: PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
80: } else {
81: PetscCall(PetscGetRealPath(tmp3, tmp1));
82: PetscCall(PetscStrncpy(rpath, tmp1, PETSC_MAX_PATH_LEN));
83: PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
84: }
85: PetscFunctionReturn(PETSC_SUCCESS);
86: }
87: PetscCall(PetscStrchr(tmp1, '/', &tmp2));
88: if (tmp2) {
89: PetscCall(PetscStrlen(tmp1, &len1));
90: PetscCall(PetscStrlen(tmp2, &len2));
91: N = len1 - len2;
92: } else {
93: PetscCall(PetscStrlen(tmp1, &N));
94: }
95: }
96: #endif
97: PetscCall(PetscStrncpy(rpath, path, PETSC_MAX_PATH_LEN)); /* assuming adequate buffer */
98: #endif
100: /* remove garbage some automounters put at the beginning of the path */
101: {
102: const char garbage[] = "/tmp_mnt/";
103: const size_t garbage_len = sizeof(garbage) - 1; // 9
104: PetscBool flg;
106: PetscCall(PetscStrncmp(garbage, rpath, garbage_len, &flg));
107: if (flg) {
108: const size_t no_slash_len = garbage_len - 1; // 8
110: PetscCall(PetscStrlen(rpath, &len));
111: // shift the array left by no_slash_len
112: PetscCall(PetscArraymove(rpath, rpath + no_slash_len, len - no_slash_len));
113: // zero out the end we just moved from
114: PetscCall(PetscArrayzero(rpath + len - no_slash_len, no_slash_len));
115: }
116: }
117: PetscFunctionReturn(PETSC_SUCCESS);
118: }