Actual source code: fdir.c
1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for lstat() */
2: #include <petscsys.h>
3: #include <sys/stat.h>
4: #if defined(PETSC_HAVE_DIRECT_H)
5: #include <direct.h>
6: #endif
7: #if defined(PETSC_HAVE_IO_H)
8: #include <io.h>
9: #endif
10: #if defined(PETSC_HAVE_STDINT_H)
11: #include <stdint.h>
12: #endif
13: #if defined(PETSC_HAVE_UNISTD_H) /* for mkdtemp */
14: #include <unistd.h>
15: #endif
17: PetscErrorCode PetscPathJoin(const char dname[], const char fname[], size_t n, char fullname[])
18: {
19: size_t l1, l2;
20: PetscFunctionBegin;
21: PetscCall(PetscStrlen(dname, &l1));
22: PetscCall(PetscStrlen(fname, &l2));
23: PetscCheck((l1 + l2 + 2) <= n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Path length is greater than buffer size");
24: PetscCall(PetscStrncpy(fullname, dname, n));
25: PetscCall(PetscStrlcat(fullname, "/", n));
26: PetscCall(PetscStrlcat(fullname, fname, n));
27: PetscFunctionReturn(PETSC_SUCCESS);
28: }
30: PetscErrorCode PetscMkdir(const char dir[])
31: {
32: int err;
33: PetscBool flg;
35: PetscFunctionBegin;
36: PetscCall(PetscTestDirectory(dir, 'w', &flg));
37: if (flg) PetscFunctionReturn(PETSC_SUCCESS);
38: #if defined(PETSC_HAVE__MKDIR) && defined(PETSC_HAVE_DIRECT_H)
39: err = _mkdir(dir);
40: #else
41: err = mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP);
42: #endif
43: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not create dir: %s", dir);
44: PetscFunctionReturn(PETSC_SUCCESS);
45: }
47: /*@C
48: PetscMkdtemp - Create a folder with a unique name given a filename template.
50: Not Collective
52: Input Parameters:
53: . dir - file name template, the last six characters must be 'XXXXXX', and they will be modified upon return
55: Level: developer
57: .seealso: `PetscMkdir()`
58: @*/
59: PetscErrorCode PetscMkdtemp(char dir[])
60: {
61: PetscFunctionBegin;
62: #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_IO_H) && defined(PETSC_HAVE__MKDIR) && defined(PETSC_HAVE_DIRECT_H)
63: {
64: int err = 1;
65: char name[PETSC_MAX_PATH_LEN];
66: PetscInt i = 0, max_retry = 26;
67: size_t len;
69: while (err && i < max_retry) {
70: PetscCall(PetscStrncpy(name, dir, sizeof(name)));
71: PetscCall(PetscStrlen(name, &len));
72: err = _mktemp_s(name, len + 1);
73: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not generate a unique name using the template: %s", dir);
74: err = _mkdir(name);
75: i++;
76: }
77: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Exceeds maximum retry time when creating temporary dir using the template: %s", dir);
78: PetscCall(PetscStrncpy(dir, name, len + 1));
79: }
80: #else
81: dir = mkdtemp(dir);
82: PetscCheck(dir, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not create temporary dir");
83: #endif
84: PetscFunctionReturn(PETSC_SUCCESS);
85: }
87: #if defined(PETSC_HAVE_DIRECT_H)
88: PetscErrorCode PetscRMTree(const char dir[])
89: {
90: struct _finddata_t data;
91: char loc[PETSC_MAX_PATH_LEN];
92: PetscBool flg1, flg2;
93: #if defined(PETSC_HAVE_STDINT_H)
94: intptr_t handle;
95: #else
96: long handle;
97: #endif
99: PetscFunctionBegin;
100: PetscCall(PetscPathJoin(dir, "*", PETSC_MAX_PATH_LEN, loc));
101: handle = _findfirst(loc, &data);
102: if (handle == -1) {
103: PetscBool flg;
104: PetscCall(PetscTestDirectory(loc, 'r', &flg));
105: PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Cannot access directory to delete: %s", dir);
106: PetscCall(PetscTestFile(loc, 'r', &flg));
107: PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Specified path is a file - not a dir: %s", dir);
108: PetscFunctionReturn(PETSC_SUCCESS); /* perhaps the dir was not yet created */
109: }
110: while (_findnext(handle, &data) != -1) {
111: PetscCall(PetscStrcmp(data.name, ".", &flg1));
112: PetscCall(PetscStrcmp(data.name, "..", &flg2));
113: if (flg1 || flg2) continue;
114: PetscCall(PetscPathJoin(dir, data.name, PETSC_MAX_PATH_LEN, loc));
115: if (data.attrib & _A_SUBDIR) {
116: PetscCall(PetscRMTree(loc));
117: } else {
118: PetscCheck(!remove(loc), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not delete file: %s", loc);
119: }
120: }
121: _findclose(handle);
122: PetscCheck(!_rmdir(dir), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not delete dir: %s", dir);
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
125: #else
126: #include <dirent.h>
127: #include <unistd.h>
128: PetscErrorCode PetscRMTree(const char dir[])
129: {
130: struct dirent *data;
131: char loc[PETSC_MAX_PATH_LEN];
132: PetscBool flg1, flg2;
133: DIR *dirp;
134: struct stat statbuf;
136: PetscFunctionBegin;
137: dirp = opendir(dir);
138: if (!dirp) {
139: PetscBool flg;
140: PetscCall(PetscTestDirectory(dir, 'r', &flg));
141: PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Cannot access directory to delete: %s", dir);
142: PetscCall(PetscTestFile(dir, 'r', &flg));
143: PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Specified path is a file - not a dir: %s", dir);
144: PetscFunctionReturn(PETSC_SUCCESS); /* perhaps the dir was not yet created */
145: }
146: while ((data = readdir(dirp))) {
147: PetscCall(PetscStrcmp(data->d_name, ".", &flg1));
148: PetscCall(PetscStrcmp(data->d_name, "..", &flg2));
149: if (flg1 || flg2) continue;
150: PetscCall(PetscPathJoin(dir, data->d_name, PETSC_MAX_PATH_LEN, loc));
151: PetscCheck(lstat(loc, &statbuf) >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "cannot run lstat() on: %s", loc);
152: if (S_ISDIR(statbuf.st_mode)) {
153: PetscCall(PetscRMTree(loc));
154: } else {
155: PetscCheck(!unlink(loc), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not delete file: %s", loc);
156: }
157: }
158: closedir(dirp);
159: PetscCheck(!rmdir(dir), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Could not delete dir: %s", dir);
160: PetscFunctionReturn(PETSC_SUCCESS);
161: }
162: #endif