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> 18 19 /*@C 20 PetscGetRealPath - Get the path without symbolic links etc. in absolute form. 21 22 Not Collective 23 24 Input Parameter: 25 . path - path to resolve 26 27 Output Parameter: 28 . rpath - resolved path 29 30 Level: developer 31 32 Notes: 33 `rpath` is assumed to be of length `PETSC_MAX_PATH_LEN`. 34 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. 40 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; 51 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 99 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; 105 106 PetscCall(PetscStrncmp(garbage, rpath, garbage_len, &flg)); 107 if (flg) { 108 const size_t no_slash_len = garbage_len - 1; // 8 109 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 } 119