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