Map deletion button
[oweals/minetest.git] / src / filesys.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "filesys.h"
21 #include <iostream>
22 #include <string.h>
23
24 namespace fs
25 {
26
27 #ifdef _WIN32 // WINDOWS
28
29 #define _WIN32_WINNT 0x0501
30 #include <Windows.h>
31 #include <stdio.h>
32 #include <malloc.h>
33 #include <tchar.h> 
34 #include <wchar.h> 
35 #include <stdio.h>
36
37 #define BUFSIZE MAX_PATH
38
39 std::vector<DirListNode> GetDirListing(std::string pathstring)
40 {
41         std::vector<DirListNode> listing;
42
43         WIN32_FIND_DATA FindFileData;
44         HANDLE hFind = INVALID_HANDLE_VALUE;
45         DWORD dwError;
46         LPTSTR DirSpec;
47         INT retval;
48
49         DirSpec = (LPTSTR) malloc (BUFSIZE);
50
51         if( DirSpec == NULL )
52         {
53           printf( "Insufficient memory available\n" );
54           retval = 1;
55           goto Cleanup;
56         }
57
58         // Check that the input is not larger than allowed.
59         if (pathstring.size() > (BUFSIZE - 2))
60         {
61           _tprintf(TEXT("Input directory is too large.\n"));
62           retval = 3;
63           goto Cleanup;
64         }
65
66         //_tprintf (TEXT("Target directory is %s.\n"), pathstring.c_str());
67
68         sprintf(DirSpec, "%s", (pathstring + "\\*").c_str());
69
70         // Find the first file in the directory.
71         hFind = FindFirstFile(DirSpec, &FindFileData);
72
73         if (hFind == INVALID_HANDLE_VALUE) 
74         {
75           _tprintf (TEXT("Invalid file handle. Error is %u.\n"), 
76                                 GetLastError());
77           retval = (-1);
78         } 
79         else 
80         {
81                 DirListNode node;
82                 node.name = FindFileData.cFileName;
83                 node.dir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
84                 listing.push_back(node);
85
86                 // List all the other files in the directory.
87                 while (FindNextFile(hFind, &FindFileData) != 0) 
88                 {
89                         DirListNode node;
90                         node.name = FindFileData.cFileName;
91                         node.dir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
92                         listing.push_back(node);
93                 }
94
95                 dwError = GetLastError();
96                 FindClose(hFind);
97                 if (dwError != ERROR_NO_MORE_FILES) 
98                 {
99                  _tprintf (TEXT("FindNextFile error. Error is %u.\n"), 
100                                    dwError);
101                 retval = (-1);
102                 goto Cleanup;
103                 }
104         }
105         retval  = 0;
106
107 Cleanup:
108         free(DirSpec);
109
110         if(retval != 0) listing.clear();
111
112         //for(unsigned int i=0; i<listing.size(); i++){
113         //      std::cout<<listing[i].name<<(listing[i].dir?" (dir)":" (file)")<<std::endl;
114         //}
115         
116         return listing;
117 }
118
119 bool CreateDir(std::string path)
120 {
121         bool r = CreateDirectory(path.c_str(), NULL);
122         if(r == true)
123                 return true;
124         if(GetLastError() == ERROR_ALREADY_EXISTS)
125                 return true;
126         return false;
127 }
128
129 bool PathExists(std::string path)
130 {
131         return (GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES);
132 }
133
134 bool RecursiveDelete(std::string path)
135 {
136         std::cerr<<"Removing \""<<path<<"\""<<std::endl;
137
138         return false;
139         
140         // This silly function needs a double-null terminated string...
141         // Well, we'll just make sure it has at least two, then.
142         path += "\0\0";
143
144         SHFILEOPSTRUCT sfo;
145         sfo.hwnd = NULL;
146         sfo.wFunc = FO_DELETE;
147         sfo.pFrom = path.c_str();
148         sfo.pTo = NULL;
149         sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
150         
151         int r = SHFileOperation(&sfo);
152
153         return (r == 0);
154 }
155
156 #else // POSIX
157
158 #include <sys/types.h>
159 #include <dirent.h>
160 #include <errno.h>
161 #include <sys/stat.h>
162 #include <sys/wait.h>
163
164 std::vector<DirListNode> GetDirListing(std::string pathstring)
165 {
166         std::vector<DirListNode> listing;
167
168     DIR *dp;
169     struct dirent *dirp;
170     if((dp  = opendir(pathstring.c_str())) == NULL) {
171                 //std::cout<<"Error("<<errno<<") opening "<<pathstring<<std::endl;
172         return listing;
173     }
174
175     while ((dirp = readdir(dp)) != NULL) {
176                 if(dirp->d_name[0]!='.'){
177                         DirListNode node;
178                         node.name = dirp->d_name;
179                         if(dirp->d_type == DT_DIR) node.dir = true;
180                         else node.dir = false;
181                         listing.push_back(node);
182                 }
183     }
184     closedir(dp);
185
186         return listing;
187 }
188
189 bool CreateDir(std::string path)
190 {
191         int r = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
192         if(r == 0)
193         {
194                 return true;
195         }
196         else
197         {
198                 // If already exists, return true
199                 if(errno == EEXIST)
200                         return true;
201                 return false;
202         }
203 }
204
205 bool PathExists(std::string path)
206 {
207         struct stat st;
208         return (stat(path.c_str(),&st) == 0);
209 }
210
211 bool RecursiveDelete(std::string path)
212 {
213         /*
214                 Execute the 'rm' command directly, by fork() and execve()
215         */
216         
217         std::cerr<<"Removing \""<<path<<"\""<<std::endl;
218
219         //return false;
220         
221         pid_t child_pid = fork();
222
223         if(child_pid == 0)
224         {
225                 // Child
226                 char argv_data[3][10000];
227                 strcpy(argv_data[0], "/bin/rm");
228                 strcpy(argv_data[1], "-rf");
229                 strncpy(argv_data[2], path.c_str(), 10000);
230                 char *argv[4];
231                 argv[0] = argv_data[0];
232                 argv[1] = argv_data[1];
233                 argv[2] = argv_data[2];
234                 argv[3] = NULL;
235
236                 std::cerr<<"Executing '"<<argv[0]<<"' '"<<argv[1]<<"' '"
237                                 <<argv[2]<<"'"<<std::endl;
238                 
239                 execv(argv[0], argv);
240                 
241                 // Execv shouldn't return. Failed.
242                 return false;
243         }
244         else
245         {
246                 // Parent
247                 int child_status;
248                 pid_t tpid;
249                 do{
250                         tpid = wait(&child_status);
251                         //if(tpid != child_pid) process_terminated(tpid);
252                 }while(tpid != child_pid);
253                 return (child_status == 0);
254         }
255 }
256
257 #endif
258
259 bool RecursiveDeleteContent(std::string path)
260 {
261         std::cerr<<"Removing content of \""<<path<<"\""<<std::endl;
262         std::vector<DirListNode> list = GetDirListing(path);
263         for(unsigned int i=0; i<list.size(); i++)
264         {
265                 std::string childpath = path+"/"+list[i].name;
266                 bool r = RecursiveDelete(childpath);
267                 if(r == false)
268                 {
269                         std::cerr<<"Removing \""<<childpath<<"\" failed"<<std::endl;
270                         return false;
271                 }
272         }
273         return true;
274 }
275
276 } // namespace fs
277