xref: /petsc/src/sys/fileio/fpath.c (revision 7a5338279d92d13360d231b9bd26d284f35eaa49)
1 #include <petscsys.h>
2 #if defined(PETSC_HAVE_PWD_H)
3   #include <pwd.h>
4 #endif
5 
6 /*@C
7   PetscGetFullPath - Given a filename, returns the fully qualified file name.
8 
9   Not Collective
10 
11   Input Parameters:
12 + path - pathname to qualify
13 - flen - size of `fullpath`
14 
15   Output Parameter:
16 . fullpath - buffer to hold the full pathname
17 
18   Level: developer
19 
20   Note:
21   Converts `~username/` and `~/` to appropriate forms
22 
23   Developer Note:
24   On Microsoft Windows full paths may begin with DriveLetter\: so these must be properly handled
25 
26 .seealso: `PetscGetRelativePath()`
27 @*/
PetscGetFullPath(const char path[],char fullpath[],size_t flen)28 PetscErrorCode PetscGetFullPath(const char path[], char fullpath[], size_t flen)
29 {
30   size_t    ln;
31   PetscBool flg;
32 
33   PetscFunctionBegin;
34   if (path[0] == '/') {
35     PetscCall(PetscStrncmp("/tmp_mnt/", path, 9, &flg));
36     if (flg) PetscCall(PetscStrncpy(fullpath, path + 8, flen));
37     else PetscCall(PetscStrncpy(fullpath, path, flen));
38     fullpath[flen - 1] = 0;
39     PetscFunctionReturn(PETSC_SUCCESS);
40   }
41 #if defined(PETSC_HAVE_WINDOWS_H)
42   if (path[1] == ':') {
43     PetscCall(PetscStrncpy(fullpath, path, flen));
44     PetscFunctionReturn(PETSC_SUCCESS);
45   }
46 #endif
47   if (path[0] == '.' && path[1] == '/') {
48     PetscCall(PetscGetWorkingDirectory(fullpath, flen));
49     PetscCall(PetscStrlcat(fullpath, path + 1, flen));
50     PetscFunctionReturn(PETSC_SUCCESS);
51   }
52 
53   PetscCall(PetscStrncpy(fullpath, path, flen));
54   fullpath[flen - 1] = 0;
55   /* Remove the various "special" forms (~username/ and ~/) */
56   if (fullpath[0] == '~') {
57     char tmppath[PETSC_MAX_PATH_LEN], *rest;
58     if (fullpath[1] == '/') {
59       PetscCall(PetscGetHomeDirectory(tmppath, PETSC_MAX_PATH_LEN));
60       rest = fullpath + 2;
61     } else {
62 #if defined(PETSC_HAVE_PWD_H)
63       struct passwd *pwde;
64       char          *p, *name;
65 
66       /* Find username */
67       name = fullpath + 1;
68       p    = name;
69       while (*p && *p != '/') p++;
70       *p   = 0;
71       rest = p + 1;
72       pwde = getpwnam(name);
73       if (!pwde) PetscFunctionReturn(PETSC_SUCCESS);
74 
75       PetscCall(PetscStrncpy(tmppath, pwde->pw_dir, sizeof(tmppath)));
76 #else
77       PetscFunctionReturn(PETSC_SUCCESS);
78 #endif
79     }
80     PetscCall(PetscStrlen(tmppath, &ln));
81     if (tmppath[ln - 1] != '/') PetscCall(PetscStrlcat(tmppath + ln - 1, "/", sizeof(tmppath) - ln + 1));
82     PetscCall(PetscStrlcat(tmppath, rest, sizeof(tmppath)));
83     PetscCall(PetscStrncpy(fullpath, tmppath, flen));
84     fullpath[flen - 1] = 0;
85   } else {
86     PetscCall(PetscGetWorkingDirectory(fullpath, flen));
87     PetscCall(PetscStrlen(fullpath, &ln));
88     PetscCall(PetscStrncpy(fullpath + ln, "/", flen - ln));
89     fullpath[flen - 1] = 0;
90     PetscCall(PetscStrlen(fullpath, &ln));
91     if (path[0] == '.' && path[1] == '/') {
92       PetscCall(PetscStrlcat(fullpath, path + 2, flen));
93     } else {
94       PetscCall(PetscStrlcat(fullpath, path, flen));
95     }
96     fullpath[flen - 1] = 0;
97   }
98 
99   /* Remove the automounter part of the path */
100   PetscCall(PetscStrncmp(fullpath, "/tmp_mnt/", 9, &flg));
101   if (flg) {
102     char tmppath[PETSC_MAX_PATH_LEN];
103     PetscCall(PetscStrncpy(tmppath, fullpath + 8, sizeof(tmppath)));
104     PetscCall(PetscStrncpy(fullpath, tmppath, flen));
105   }
106   /* We could try to handle things like the removal of .. etc */
107   PetscFunctionReturn(PETSC_SUCCESS);
108 }
109