xref: /petsc/src/sys/fileio/grpath.c (revision 55cda6f51c86a483abe5781578f3bbdf986e1625)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for realpath() */
2c6db04a5SJed Brown #include <petscsys.h>
3e5c89e4eSSatish Balay #if defined(PETSC_HAVE_PWD_H)
4e5c89e4eSSatish Balay   #include <pwd.h>
5e5c89e4eSSatish Balay #endif
6e5c89e4eSSatish Balay #include <ctype.h>
7e5c89e4eSSatish Balay #include <sys/stat.h>
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
9e5c89e4eSSatish Balay   #include <unistd.h>
10e5c89e4eSSatish Balay #endif
11e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_UTSNAME_H)
12e5c89e4eSSatish Balay   #include <sys/utsname.h>
13e5c89e4eSSatish Balay #endif
14e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
15e5c89e4eSSatish Balay   #include <sys/systeminfo.h>
16e5c89e4eSSatish Balay #endif
17bf31d2d3SBarry Smith #include <errno.h>
18e5c89e4eSSatish Balay 
19e5c89e4eSSatish Balay /*@C
2021532e8aSBarry Smith   PetscGetRealPath - Get the path without symbolic links etc. in absolute form.
21e5c89e4eSSatish Balay 
22e5c89e4eSSatish Balay   Not Collective
23e5c89e4eSSatish Balay 
24e5c89e4eSSatish Balay   Input Parameter:
25e5c89e4eSSatish Balay . path - path to resolve
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay   Output Parameter:
28e5c89e4eSSatish Balay . rpath - resolved path
29e5c89e4eSSatish Balay 
30e5c89e4eSSatish Balay   Level: developer
31e5c89e4eSSatish Balay 
32e5c89e4eSSatish Balay   Notes:
33*a3b724e8SBarry Smith   `rpath` is assumed to be of length `PETSC_MAX_PATH_LEN`.
34e5c89e4eSSatish Balay 
35e5c89e4eSSatish Balay   Systems that use the automounter often generate absolute paths
36e5c89e4eSSatish Balay   of the form "/tmp_mnt....".  However, the automounter will fail to
37e5c89e4eSSatish Balay   mount this path if it is not already mounted, so we remove this from
38e5c89e4eSSatish Balay   the head of the line.  This may cause problems if, for some reason,
39e5c89e4eSSatish Balay   /tmp_mnt is valid and not the result of the automounter.
40e5c89e4eSSatish Balay 
41db781477SPatrick Sanan .seealso: `PetscGetFullPath()`
42e5c89e4eSSatish Balay @*/
PetscGetRealPath(const char path[],char rpath[])43d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetRealPath(const char path[], char rpath[])
44d71ae5a4SJacob Faibussowitsch {
45e5c89e4eSSatish Balay #if !defined(PETSC_HAVE_REALPATH) && defined(PETSC_HAVE_READLINK)
46363da2dcSJacob Faibussowitsch   char tmp1[PETSC_MAX_PATH_LEN], char tmp3[PETSC_MAX_PATH_LEN], tmp4[PETSC_MAX_PATH_LEN], *tmp2;
47c6a7a370SJeremy L Thompson   size_t N, len1, len2;
48e5c89e4eSSatish Balay   int    n, m;
49e5c89e4eSSatish Balay #endif
50c6a7a370SJeremy L Thompson   size_t len;
51e5c89e4eSSatish Balay 
52e5c89e4eSSatish Balay   PetscFunctionBegin;
53e5c89e4eSSatish Balay #if defined(PETSC_HAVE_REALPATH)
54bf31d2d3SBarry Smith   PetscCheck(realpath(path, rpath), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in realpath() due to \"%s\"", strerror(errno));
55363da2dcSJacob Faibussowitsch #else
56363da2dcSJacob Faibussowitsch   #if defined(PETSC_HAVE_READLINK)
57e5c89e4eSSatish Balay   /* Algorithm: we move through the path, replacing links with the real paths.   */
58c6a7a370SJeremy L Thompson   PetscCall(PetscStrlen(path, &N));
59c6a7a370SJeremy L Thompson   PetscCall(PetscStrncpy(rpath, path, N + 1)); /* assuming adequate buffer */
609566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(rpath, &N));
61e5c89e4eSSatish Balay   while (N) {
629566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(tmp1, rpath, N));
63e5c89e4eSSatish Balay     tmp1[N] = 0;
64e5c89e4eSSatish Balay     n       = readlink(tmp1, tmp3, PETSC_MAX_PATH_LEN);
65bf31d2d3SBarry Smith     PetscCheck(n > -1, PETSC_COMM_SELF, PETSC_ERR_SYS, "Error in readlink() due to \"%\"", strerror(errno));
66e5c89e4eSSatish Balay     if (n > 0) {
67e5c89e4eSSatish Balay       tmp3[n] = 0; /* readlink does not automatically add 0 to string end */
68e5c89e4eSSatish Balay       if (tmp3[0] != '/') {
699566063dSJacob Faibussowitsch         PetscCall(PetscStrchr(tmp1, '/', &tmp2));
709566063dSJacob Faibussowitsch         PetscCall(PetscStrlen(tmp1, &len1));
719566063dSJacob Faibussowitsch         PetscCall(PetscStrlen(tmp2, &len2));
72e5c89e4eSSatish Balay         m = len1 - len2;
739566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(tmp4, tmp1, m));
74e5c89e4eSSatish Balay         tmp4[m] = 0;
759566063dSJacob Faibussowitsch         PetscCall(PetscStrlen(tmp4, &len));
769566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmp4, "/", PETSC_MAX_PATH_LEN));
779566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmp4, tmp3, PETSC_MAX_PATH_LEN));
789566063dSJacob Faibussowitsch         PetscCall(PetscGetRealPath(tmp4, rpath));
799566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
80e5c89e4eSSatish Balay       } else {
819566063dSJacob Faibussowitsch         PetscCall(PetscGetRealPath(tmp3, tmp1));
829566063dSJacob Faibussowitsch         PetscCall(PetscStrncpy(rpath, tmp1, PETSC_MAX_PATH_LEN));
839566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
84e5c89e4eSSatish Balay       }
853ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
86e5c89e4eSSatish Balay     }
879566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(tmp1, '/', &tmp2));
88e5c89e4eSSatish Balay     if (tmp2) {
899566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(tmp1, &len1));
909566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(tmp2, &len2));
91e5c89e4eSSatish Balay       N = len1 - len2;
92e5c89e4eSSatish Balay     } else {
939566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(tmp1, &N));
94e5c89e4eSSatish Balay     }
95e5c89e4eSSatish Balay   }
96363da2dcSJacob Faibussowitsch   #endif
97363da2dcSJacob Faibussowitsch   PetscCall(PetscStrncpy(rpath, path, PETSC_MAX_PATH_LEN)); /* assuming adequate buffer */
98e5c89e4eSSatish Balay #endif
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay   /* remove garbage some automounters put at the beginning of the path */
101363da2dcSJacob Faibussowitsch   {
102363da2dcSJacob Faibussowitsch     const char   garbage[]   = "/tmp_mnt/";
103363da2dcSJacob Faibussowitsch     const size_t garbage_len = sizeof(garbage) - 1; // 9
104363da2dcSJacob Faibussowitsch     PetscBool    flg;
105363da2dcSJacob Faibussowitsch 
106363da2dcSJacob Faibussowitsch     PetscCall(PetscStrncmp(garbage, rpath, garbage_len, &flg));
107e5c89e4eSSatish Balay     if (flg) {
108363da2dcSJacob Faibussowitsch       const size_t no_slash_len = garbage_len - 1; // 8
109363da2dcSJacob Faibussowitsch 
110363da2dcSJacob Faibussowitsch       PetscCall(PetscStrlen(rpath, &len));
111363da2dcSJacob Faibussowitsch       // shift the array left by no_slash_len
112363da2dcSJacob Faibussowitsch       PetscCall(PetscArraymove(rpath, rpath + no_slash_len, len - no_slash_len));
113363da2dcSJacob Faibussowitsch       // zero out the end we just moved from
114363da2dcSJacob Faibussowitsch       PetscCall(PetscArrayzero(rpath + len - no_slash_len, no_slash_len));
115363da2dcSJacob Faibussowitsch     }
116e5c89e4eSSatish Balay   }
1173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118e5c89e4eSSatish Balay }
119