Actual source code: ftest.c
1: #include <petscsys.h>
2: #include <errno.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_IO_H)
15: #include <io.h>
16: #endif
17: #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
18: #include <sys/systeminfo.h>
19: #endif
21: #if defined(PETSC_HAVE__ACCESS) || defined(PETSC_HAVE_ACCESS)
23: #include <errno.h>
24: static PetscErrorCode PetscTestOwnership(const char fname[], char mode, uid_t fuid, gid_t fgid, int fmode, PetscBool *flg)
25: {
26: int m = R_OK;
28: PetscFunctionBegin;
29: if (mode == 'r') m = R_OK;
30: else if (mode == 'w') m = W_OK;
31: else if (mode == 'x') m = X_OK;
32: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mode must be one of r, w, or x");
33: #if defined(PETSC_HAVE_ACCESS)
34: if (!access(fname, m)) {
35: PetscCall(PetscInfo(NULL, "System call access() succeeded on file %s\n", fname));
36: *flg = PETSC_TRUE;
37: } else {
38: PetscCall(PetscInfo(NULL, "System call access() failed on file %s due to \"%s\"\n", fname, strerror(errno)));
39: *flg = PETSC_FALSE;
40: }
41: #else
42: PetscCheck(m != X_OK, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unable to check execute permission for file %s", fname);
43: if (!_access(fname, m)) *flg = PETSC_TRUE;
44: #endif
45: PetscFunctionReturn(PETSC_SUCCESS);
46: }
48: #else /* PETSC_HAVE_ACCESS or PETSC_HAVE__ACCESS */
50: static PetscErrorCode PetscTestOwnership(const char fname[], char mode, uid_t fuid, gid_t fgid, int fmode, PetscBool *flg)
51: {
52: uid_t uid;
53: gid_t *gid = NULL;
54: int numGroups;
55: int rbit = S_IROTH;
56: int wbit = S_IWOTH;
57: int ebit = S_IXOTH;
58: #if !defined(PETSC_MISSING_GETGROUPS)
59: int err;
60: #endif
62: PetscFunctionBegin;
63: /* Get the number of supplementary group IDs */
64: #if !defined(PETSC_MISSING_GETGROUPS)
65: numGroups = getgroups(0, gid);
66: PetscCheck(numGroups >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to count supplementary group IDs due to \"%s\"", strerror(errno));
67: PetscCall(PetscMalloc1(numGroups + 1, &gid));
68: #else
69: numGroups = 0;
70: #endif
72: /* Get the (effective) user and group of the caller */
73: uid = geteuid();
74: gid[0] = getegid();
76: /* Get supplementary group IDs */
77: #if !defined(PETSC_MISSING_GETGROUPS)
78: err = getgroups(numGroups, gid + 1);
79: PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to obtain supplementary group IDs due to \"%s\"", strerror(errno));
80: #endif
82: /* Test for accessibility */
83: if (fuid == uid) {
84: rbit = S_IRUSR;
85: wbit = S_IWUSR;
86: ebit = S_IXUSR;
87: } else {
88: int g;
90: for (g = 0; g <= numGroups; g++) {
91: if (fgid == gid[g]) {
92: rbit = S_IRGRP;
93: wbit = S_IWGRP;
94: ebit = S_IXGRP;
95: break;
96: }
97: }
98: }
99: PetscCall(PetscFree(gid));
101: if (mode == 'r') {
102: if (fmode & rbit) *flg = PETSC_TRUE;
103: } else if (mode == 'w') {
104: if (fmode & wbit) *flg = PETSC_TRUE;
105: } else if (mode == 'x') {
106: if (fmode & ebit) *flg = PETSC_TRUE;
107: }
108: PetscFunctionReturn(PETSC_SUCCESS);
109: }
111: #endif /* PETSC_HAVE_ACCESS */
113: static PetscErrorCode PetscGetFileStat(const char fname[], uid_t *fileUid, gid_t *fileGid, int *fileMode, PetscBool *exists)
114: {
115: struct stat statbuf;
116: int ierr;
118: PetscFunctionBegin;
119: *fileMode = 0;
120: *exists = PETSC_FALSE;
121: #if defined(PETSC_HAVE_STAT_NO_CONST)
122: ierr = stat((char *)fname, &statbuf);
123: #else
124: ierr = stat(fname, &statbuf);
125: #endif
126: if (ierr) {
127: #if defined(EOVERFLOW)
128: PetscCheck(errno != EOVERFLOW, PETSC_COMM_SELF, PETSC_ERR_SYS, "EOVERFLOW in stat(), configure PETSc --with-large-file-io=1 to support files larger than 2GiB");
129: #endif
130: PetscCall(PetscInfo(NULL, "System call stat() failed on file %s due to \"%s\"\n", fname, strerror(errno)));
131: *exists = PETSC_FALSE;
132: } else {
133: PetscCall(PetscInfo(NULL, "System call stat() succeeded on file %s\n", fname));
134: *exists = PETSC_TRUE;
135: *fileUid = statbuf.st_uid;
136: *fileGid = statbuf.st_gid;
137: *fileMode = statbuf.st_mode;
138: }
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: /*@
143: PetscTestFile - checks for the existence of a file
145: Not Collective
147: Input Parameters:
148: + fname - the filename
149: - mode - either 'r', 'w', 'x' or '\0'
151: Output Parameter:
152: . flg - the file exists and satisfies the mode
154: Level: intermediate
156: Note:
157: If mode is '\0', no permissions checks are performed
159: .seealso: `PetscTestDirectory()`, `PetscLs()`
160: @*/
161: PetscErrorCode PetscTestFile(const char fname[], char mode, PetscBool *flg)
162: {
163: uid_t fuid;
164: gid_t fgid;
165: int fmode;
166: PetscBool exists;
168: PetscFunctionBegin;
169: *flg = PETSC_FALSE;
170: if (!fname) PetscFunctionReturn(PETSC_SUCCESS);
172: PetscCall(PetscGetFileStat(fname, &fuid, &fgid, &fmode, &exists));
173: if (!exists) PetscFunctionReturn(PETSC_SUCCESS);
174: /* Except for systems that have this broken stat macros (rare), this is the correct way to check for a regular file */
175: if (!S_ISREG(fmode)) PetscFunctionReturn(PETSC_SUCCESS);
176: /* return if asked to check for existence only */
177: if (mode == '\0') {
178: *flg = exists;
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
181: PetscCall(PetscTestOwnership(fname, mode, fuid, fgid, fmode, flg));
182: PetscFunctionReturn(PETSC_SUCCESS);
183: }
185: /*@
186: PetscTestDirectory - checks for the existence of a directory
188: Not Collective
190: Input Parameters:
191: + dirname - the directory name
192: - mode - either 'r', 'w', or 'x'
194: Output Parameter:
195: . flg - the directory exists and satisfies the mode
197: Level: intermediate
199: .seealso: `PetscTestFile()`, `PetscLs()`, `PetscRMTree()`
200: @*/
201: PetscErrorCode PetscTestDirectory(const char dirname[], char mode, PetscBool *flg)
202: {
203: uid_t fuid;
204: gid_t fgid;
205: int fmode;
206: PetscBool exists;
208: PetscFunctionBegin;
209: *flg = PETSC_FALSE;
210: if (!dirname) PetscFunctionReturn(PETSC_SUCCESS);
212: PetscCall(PetscGetFileStat(dirname, &fuid, &fgid, &fmode, &exists));
213: if (!exists) PetscFunctionReturn(PETSC_SUCCESS);
214: /* Except for systems that have this broken stat macros (rare), this
215: is the correct way to check for a directory */
216: if (!S_ISDIR(fmode)) PetscFunctionReturn(PETSC_SUCCESS);
218: PetscCall(PetscTestOwnership(dirname, mode, fuid, fgid, fmode, flg));
219: PetscFunctionReturn(PETSC_SUCCESS);
220: }
222: /*@C
223: PetscLs - produce a listing of the files in a directory
225: Collective
227: Input Parameters:
228: + comm - the MPI communicator
229: . dirname - the directory name
230: - tlen - the length of the buffer `found`
232: Output Parameters:
233: + found - listing of files
234: - flg - the directory exists
236: Level: intermediate
238: .seealso: `PetscTestFile()`, `PetscRMTree()`, `PetscTestDirectory()`
239: @*/
240: PetscErrorCode PetscLs(MPI_Comm comm, const char dirname[], char found[], size_t tlen, PetscBool *flg)
241: {
242: size_t len;
243: char *f, program[PETSC_MAX_PATH_LEN];
244: FILE *fp;
246: PetscFunctionBegin;
247: PetscCall(PetscStrncpy(program, "ls ", sizeof(program)));
248: PetscCall(PetscStrlcat(program, dirname, sizeof(program)));
249: #if defined(PETSC_HAVE_POPEN)
250: PetscCall(PetscPOpen(comm, NULL, program, "r", &fp));
251: #else
252: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
253: #endif
254: f = fgets(found, (int)tlen, fp);
255: if (f) *flg = PETSC_TRUE;
256: else *flg = PETSC_FALSE;
257: while (f) {
258: PetscCall(PetscStrlen(found, &len));
259: f = fgets(found + len, (int)(tlen - len), fp);
260: }
261: if (*flg) PetscCall(PetscInfo(NULL, "ls on %s gives \n%s\n", dirname, found));
262: #if defined(PETSC_HAVE_POPEN)
263: PetscCall(PetscPClose(comm, fp));
264: #else
265: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
266: #endif
267: PetscFunctionReturn(PETSC_SUCCESS);
268: }