xref: /petsc/src/sys/fileio/fdir.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203)
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
16 
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(0);
28 }
29 
30 PetscErrorCode PetscMkdir(const char dir[])
31 {
32   int            err;
33   PetscBool      flg;
34 
35   PetscFunctionBegin;
36   PetscCall(PetscTestDirectory(dir,'w',&flg));
37   if (flg) PetscFunctionReturn(0);
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(0);
45 }
46 
47 #if defined(PETSC_USING_DARWIN) && defined(PETSC_HAVE_FSTATAT)
48 /*
49     Apple's mkdtemp() crashes under Valgrind so this replaces it with a version that does not crash under valgrind
50 */
51 #include "apple_fdir.h"
52 #endif
53 
54 /*@C
55   PetscMkdtemp - Create a folder with a unique name given a filename template.
56 
57   Not Collective
58 
59   Input Parameters:
60 . dir - file name template, the last six characters must be 'XXXXXX', and they will be modified upon return
61 
62   Level: developer
63 
64 .seealso: `PetscMkdir()`
65 @*/
66 PetscErrorCode PetscMkdtemp(char dir[])
67 {
68   PetscFunctionBegin;
69 #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_IO_H) && defined(PETSC_HAVE__MKDIR) && defined(PETSC_HAVE_DIRECT_H)
70   {
71     int            err = 1;
72     char           name[PETSC_MAX_PATH_LEN];
73     PetscInt       i = 0,max_retry = 26;
74     size_t         len;
75 
76     while (err && i < max_retry) {
77       PetscCall(PetscStrncpy(name,dir,sizeof(name)));
78       PetscCall(PetscStrlen(name,&len));
79       err = _mktemp_s(name,len+1);
80       PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not generate a unique name using the template: %s",dir);
81       err = _mkdir(name);
82       i++;
83     }
84     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Exceeds maximum retry time when creating temporary dir using the template: %s",dir);
85     PetscCall(PetscStrncpy(dir,name,len+1));
86   }
87 #else
88   dir = mkdtemp(dir);
89   PetscCheck(dir,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not create temporary dir");
90 #endif
91   PetscFunctionReturn(0);
92 }
93 
94 #if defined(PETSC_HAVE_DIRECT_H)
95 PetscErrorCode PetscRMTree(const char dir[])
96 {
97   struct _finddata_t data;
98   char loc[PETSC_MAX_PATH_LEN];
99   PetscBool flg1, flg2;
100 #if defined (PETSC_HAVE_STDINT_H)
101   intptr_t handle;
102 #else
103   long handle;
104   #endif
105 
106   PetscFunctionBegin;
107   PetscCall(PetscPathJoin(dir,"*",PETSC_MAX_PATH_LEN,loc));
108   handle = _findfirst(loc, &data);
109   if (handle == -1) {
110     PetscBool flg;
111     PetscCall(PetscTestDirectory(loc,'r',&flg));
112     PetscCheck(!flg,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Cannot access directory to delete: %s",dir);
113     PetscCall(PetscTestFile(loc,'r',&flg));
114     PetscCheck(!flg,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Specified path is a file - not a dir: %s",dir);
115     PetscFunctionReturn(0); /* perhaps the dir was not yet created */
116   }
117   while (_findnext(handle, &data) != -1) {
118     PetscCall(PetscStrcmp(data.name, ".",&flg1));
119     PetscCall(PetscStrcmp(data.name, "..",&flg2));
120     if (flg1 || flg2) continue;
121     PetscCall(PetscPathJoin(dir,data.name,PETSC_MAX_PATH_LEN,loc));
122     if (data.attrib & _A_SUBDIR) {
123       PetscCall(PetscRMTree(loc));
124     } else{
125       PetscCheck(!remove(loc),PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not delete file: %s",loc);
126     }
127   }
128   _findclose(handle);
129   PetscCheck(!_rmdir(dir),PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not delete dir: %s",dir);
130   PetscFunctionReturn(0);
131 }
132 #else
133 #include <dirent.h>
134 #include <unistd.h>
135 PetscErrorCode PetscRMTree(const char dir[])
136 {
137   struct dirent *data;
138   char loc[PETSC_MAX_PATH_LEN];
139   PetscBool flg1, flg2;
140   DIR *dirp;
141   struct stat statbuf;
142 
143   PetscFunctionBegin;
144   dirp = opendir(dir);
145   if (!dirp) {
146     PetscBool flg;
147     PetscCall(PetscTestDirectory(dir,'r',&flg));
148     PetscCheck(!flg,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Cannot access directory to delete: %s",dir);
149     PetscCall(PetscTestFile(dir,'r',&flg));
150     PetscCheck(!flg,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Specified path is a file - not a dir: %s",dir);
151     PetscFunctionReturn(0); /* perhaps the dir was not yet created */
152   }
153   while ((data = readdir(dirp))) {
154     PetscCall(PetscStrcmp(data->d_name, ".",&flg1));
155     PetscCall(PetscStrcmp(data->d_name, "..",&flg2));
156     if (flg1 || flg2) continue;
157     PetscCall(PetscPathJoin(dir,data->d_name,PETSC_MAX_PATH_LEN,loc));
158     PetscCheck(lstat(loc,&statbuf) >=0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"cannot run lstat() on: %s",loc);
159     if (S_ISDIR(statbuf.st_mode)) {
160       PetscCall(PetscRMTree(loc));
161     } else {
162       PetscCheck(!unlink(loc),PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not delete file: %s",loc);
163     }
164   }
165   closedir(dirp);
166   PetscCheck(!rmdir(dir),PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Could not delete dir: %s",dir);
167   PetscFunctionReturn(0);
168 }
169 #endif
170