xref: /petsc/src/sys/fileio/fpath.c (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
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 .seealso: `PetscGetRelativePath()`
21 @*/
22 PetscErrorCode PetscGetFullPath(const char path[], char fullpath[], size_t flen)
23 {
24   size_t    ln;
25   PetscBool flg;
26 
27   PetscFunctionBegin;
28   if (path[0] == '/') {
29     PetscCall(PetscStrncmp("/tmp_mnt/", path, 9, &flg));
30     if (flg) PetscCall(PetscStrncpy(fullpath, path + 8, flen));
31     else PetscCall(PetscStrncpy(fullpath, path, flen));
32     fullpath[flen - 1] = 0;
33     PetscFunctionReturn(PETSC_SUCCESS);
34   }
35   if (path[0] == '.' && path[1] == '/') {
36     PetscCall(PetscGetWorkingDirectory(fullpath, flen));
37     PetscCall(PetscStrlcat(fullpath, path + 1, flen));
38     PetscFunctionReturn(PETSC_SUCCESS);
39   }
40 
41   PetscCall(PetscStrncpy(fullpath, path, flen));
42   fullpath[flen - 1] = 0;
43   /* Remove the various "special" forms (~username/ and ~/) */
44   if (fullpath[0] == '~') {
45     char tmppath[PETSC_MAX_PATH_LEN], *rest;
46     if (fullpath[1] == '/') {
47       PetscCall(PetscGetHomeDirectory(tmppath, PETSC_MAX_PATH_LEN));
48       rest = fullpath + 2;
49     } else {
50 #if defined(PETSC_HAVE_PWD_H)
51       struct passwd *pwde;
52       char          *p, *name;
53 
54       /* Find username */
55       name = fullpath + 1;
56       p    = name;
57       while (*p && *p != '/') p++;
58       *p   = 0;
59       rest = p + 1;
60       pwde = getpwnam(name);
61       if (!pwde) PetscFunctionReturn(PETSC_SUCCESS);
62 
63       PetscCall(PetscStrncpy(tmppath, pwde->pw_dir, sizeof(tmppath)));
64 #else
65       PetscFunctionReturn(PETSC_SUCCESS);
66 #endif
67     }
68     PetscCall(PetscStrlen(tmppath, &ln));
69     if (tmppath[ln - 1] != '/') PetscCall(PetscStrlcat(tmppath + ln - 1, "/", sizeof(tmppath) - ln + 1));
70     PetscCall(PetscStrlcat(tmppath, rest, sizeof(tmppath)));
71     PetscCall(PetscStrncpy(fullpath, tmppath, flen));
72     fullpath[flen - 1] = 0;
73   } else {
74     PetscCall(PetscGetWorkingDirectory(fullpath, flen));
75     PetscCall(PetscStrlen(fullpath, &ln));
76     PetscCall(PetscStrncpy(fullpath + ln, "/", flen - ln));
77     fullpath[flen - 1] = 0;
78     PetscCall(PetscStrlen(fullpath, &ln));
79     if (path[0] == '.' && path[1] == '/') {
80       PetscCall(PetscStrlcat(fullpath, path + 2, flen));
81     } else {
82       PetscCall(PetscStrlcat(fullpath, path, flen));
83     }
84     fullpath[flen - 1] = 0;
85   }
86 
87   /* Remove the automounter part of the path */
88   PetscCall(PetscStrncmp(fullpath, "/tmp_mnt/", 9, &flg));
89   if (flg) {
90     char tmppath[PETSC_MAX_PATH_LEN];
91     PetscCall(PetscStrncpy(tmppath, fullpath + 8, sizeof(tmppath)));
92     PetscCall(PetscStrncpy(fullpath, tmppath, flen));
93   }
94   /* We could try to handle things like the removal of .. etc */
95   PetscFunctionReturn(PETSC_SUCCESS);
96 }
97