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

 18: /*@C
 19:    PetscGetRealPath - Get the path without symbolic links etc. and in absolute form.

 21:    Not Collective

 23:    Input Parameter:
 24: .  path - path to resolve

 26:    Output Parameter:
 27: .  rpath - resolved path

 29:    Level: developer

 31:    Notes:
 32:    rpath is assumed to be of length `PETSC_MAX_PATH_LEN`.

 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.

 40: .seealso: `PetscGetFullPath()`
 41: @*/
 42: PetscErrorCode PetscGetRealPath(const char path[], char rpath[])
 43: {
 44:   char      tmp3[PETSC_MAX_PATH_LEN];
 45:   PetscBool flg;
 46: #if !defined(PETSC_HAVE_REALPATH) && defined(PETSC_HAVE_READLINK)
 47:   char   tmp1[PETSC_MAX_PATH_LEN], tmp4[PETSC_MAX_PATH_LEN], *tmp2;
 48:   size_t N, len, len1, len2;
 49:   int    n, m;
 50: #endif

 52:   PetscFunctionBegin;
 53: #if defined(PETSC_HAVE_REALPATH)
 54:   PetscCheck(realpath(path, rpath), PETSC_COMM_SELF, PETSC_ERR_LIB, "realpath()");
 55: #elif defined(PETSC_HAVE_READLINK)
 56:   /* Algorithm: we move through the path, replacing links with the real paths.   */
 57:   PetscCall(PetscStrcpy(rpath, path));
 58:   PetscCall(PetscStrlen(rpath, &N));
 59:   while (N) {
 60:     PetscCall(PetscStrncpy(tmp1, rpath, N));
 61:     tmp1[N] = 0;
 62:     n       = readlink(tmp1, tmp3, PETSC_MAX_PATH_LEN);
 63:     if (n > 0) {
 64:       tmp3[n] = 0; /* readlink does not automatically add 0 to string end */
 65:       if (tmp3[0] != '/') {
 66:         PetscCall(PetscStrchr(tmp1, '/', &tmp2));
 67:         PetscCall(PetscStrlen(tmp1, &len1));
 68:         PetscCall(PetscStrlen(tmp2, &len2));
 69:         m = len1 - len2;
 70:         PetscCall(PetscStrncpy(tmp4, tmp1, m));
 71:         tmp4[m] = 0;
 72:         PetscCall(PetscStrlen(tmp4, &len));
 73:         PetscCall(PetscStrlcat(tmp4, "/", PETSC_MAX_PATH_LEN));
 74:         PetscCall(PetscStrlcat(tmp4, tmp3, PETSC_MAX_PATH_LEN));
 75:         PetscCall(PetscGetRealPath(tmp4, rpath));
 76:         PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
 77:       } else {
 78:         PetscCall(PetscGetRealPath(tmp3, tmp1));
 79:         PetscCall(PetscStrncpy(rpath, tmp1, PETSC_MAX_PATH_LEN));
 80:         PetscCall(PetscStrlcat(rpath, path + N, PETSC_MAX_PATH_LEN));
 81:       }
 82:       PetscFunctionReturn(PETSC_SUCCESS);
 83:     }
 84:     PetscCall(PetscStrchr(tmp1, '/', &tmp2));
 85:     if (tmp2) {
 86:       PetscCall(PetscStrlen(tmp1, &len1));
 87:       PetscCall(PetscStrlen(tmp2, &len2));
 88:       N = len1 - len2;
 89:     } else {
 90:       PetscCall(PetscStrlen(tmp1, &N));
 91:     }
 92:   }
 93:   PetscCall(PetscStrncpy(rpath, path, PETSC_MAX_PATH_LEN));
 94: #else /* Just punt */
 95:   PetscCall(PetscStrcpy(rpath, path));
 96: #endif

 98:   /* remove garbage some automounters put at the beginning of the path */
 99:   PetscCall(PetscStrncmp("/tmp_mnt/", rpath, 9, &flg));
100:   if (flg) {
101:     PetscCall(PetscStrcpy(tmp3, rpath + 8));
102:     PetscCall(PetscStrcpy(rpath, tmp3));
103:   }
104:   PetscFunctionReturn(PETSC_SUCCESS);
105: }