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