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 @*/ 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