source: branches/work_311/FileSystemUtil.cpp @ 679

Revision 597, 9.2 KB checked in by jls17, 5 years ago (diff)
  • fixed an issue with the GetExecutableDirectory? function (using the buffer-pointer after the realloc call isn't valid; we need to use the pointer returned by realloc)
Line 
1//Copyright (C) 2009 Stefan Nerlich | stefan.nerlich@hotmail.com
2//
3//This file is part of ARInside.
4//
5//    ARInside 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, version 2 of the License.
8//
9//    ARInside is distributed in the hope that it will be useful,
10//    but WITHOUT ANY WARRANTY; without even the implied warranty of
11//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12//    GNU General Public License for more details.
13//
14//    You should have received a copy of the GNU General Public License
15//    along with ARInside.  If not, see <http://www.gnu.org/licenses/>.
16
17#include "stdafx.h"
18#include "resource.h"
19#include "FileSystemUtil.h"
20#include "AppException.h"
21#include "ARApi.h"
22
23#include <sys/types.h>
24#include <sys/stat.h>
25
26FileSystemUtil::FileSystemUtil(AppConfig &appConfig)
27: appConfig(appConfig)
28{
29}
30
31FileSystemUtil::~FileSystemUtil(void)
32{
33}
34
35bool FileSystemUtil::CreateAppDirectory()
36{
37        int nResult = 
38#ifdef WIN32
39        _mkdir(appConfig.targetFolder.c_str());
40#else
41        mkdir(appConfig.targetFolder.c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
42#endif
43        cout << "Create target directory: " << appConfig.targetFolder << " [" << (nResult == 0 ? "OK" : strerror(errno)) <<"]" << endl; 
44
45        return (nResult==0);
46}
47
48int FileSystemUtil::CreateSubDirectory(string name)
49{       
50        stringstream strm;
51        strm << appConfig.targetFolder << "/" << name;
52
53        try
54        {
55#ifdef WIN32           
56                return (_mkdir(strm.str().c_str()) == 0);
57#else
58                return (mkdir(strm.str().c_str(), S_IRWXU|S_IRWXG|S_IRWXO) == 0);
59#endif
60        }
61        catch(exception& e)
62        {
63                cout << "Error creating directory '" << strm.str() << "': " << e.what() << endl;
64        }
65
66        return 0;
67}
68
69string FileSystemUtil::GetRealPathName(const std::string &path)
70{
71#ifdef WIN32
72        char buffer[MAX_PATH]; buffer[0] = 0;
73        LPSTR *filePos = NULL;
74
75        DWORD len = GetFullPathName(path.c_str(), MAX_PATH, buffer, filePos);
76        if (len > MAX_PATH || len == 0)
77        {
78                stringstream tmp;
79                tmp << "Error: could not retrieve the full output path! (" << GetLastError() << ")";
80                throw AppException(tmp.str(), "filesystem");                   
81        }
82#else
83        // NOTE: realpath doesn't return the full path under SunOS if a relativ path is specified.
84        char buffer[PATH_MAX]; buffer[0] = 0;
85        char *p;
86        p = realpath(path.c_str(), buffer);
87        if (p == NULL)
88        {
89                if (errno == ENOENT) return path;
90                stringstream tmp;
91                tmp << strerror(errno) << ": " << path;
92                throw AppException(tmp.str(), "filesystem");                   
93        }
94#endif
95        return buffer;
96}
97
98bool FileSystemUtil::FileExistsAndReadable(const std::string &filename)
99{
100        bool result = false;
101
102        try
103        {
104                fstream fin;
105                fin.open(filename.c_str(),ios::in);
106                result = fin.is_open();
107                fin.close();
108        }
109        catch(exception& e)
110        {
111                cout << "EXCEPTION An error occured while checking file exists: " << e.what() << endl;
112        }
113
114        return result;
115}
116
117bool FileSystemUtil::DeleteDirectory(const char* sPath, bool topLevel)
118{
119#ifdef WIN32
120        try
121        {
122                HANDLE hFind; // file handle
123                WIN32_FIND_DATA FindFileData;
124
125                char DirPath[MAX_PATH+1];
126                char FileName[MAX_PATH+1];
127
128                strncpy(DirPath, sPath, MAX_PATH);
129                strncat(DirPath, "/", MAX_PATH);
130                DirPath[MAX_PATH] = 0;
131
132                strncpy(FileName, sPath, MAX_PATH);
133                strncat(FileName, "/*", MAX_PATH); // searching all files
134                FileName[MAX_PATH] = 0;
135
136                hFind = FindFirstFile(FileName, &FindFileData); // find the first file
137                if (hFind != INVALID_HANDLE_VALUE)
138                {
139                        do
140                        {
141                                if (IsDots(FindFileData.cFileName))
142                                        continue;
143
144                                strcpy(FileName + strlen(DirPath), FindFileData.cFileName);
145                                if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
146                                {
147                                        // we have found a directory, recurse
148                                        LOG << "Delete " << FileName << endl;
149
150                                        if( !DeleteDirectory(FileName, false) )
151                                                break; // directory couldn't be deleted
152                                }
153                                else
154                                {
155                                        if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
156                                                _chmod(FileName, _S_IWRITE); // change read-only file mode
157
158                                        LOG << "Delete " << FileName << endl;
159                                        if( !DeleteFile(FileName) )
160                                                break; // file couldn't be deleted
161                                }
162                        }
163
164                        while( FindNextFile(hFind,&FindFileData) );     
165                        FindClose(hFind); // closing file handle
166
167                }
168        }
169        catch(exception& e)
170        {
171                cout << "EXCEPTION in DeleteDirectory: " << e.what() << endl; 
172        }       
173
174        return (topLevel || _rmdir(sPath)==0 ? true : false); // remove the empty (maybe not) directory
175#else
176        if (strlen(sPath) == 0) return false;
177
178        // first off, we need to create a pointer to a directory
179        DIR *pdir;
180        pdir = opendir(sPath);
181       
182        struct dirent *pent = NULL;
183        if (pdir == NULL)
184                return false; // return false to say "we couldn't do it"
185
186        string file;
187        struct stat stats;
188
189        while (pent = readdir(pdir)) { // while there is still something in the directory to list
190                if (!IsDots(pent->d_name))
191                {
192                        file = sPath;
193                        char lastChar = file.at(file.length()-1);
194                  if (lastChar != '/' || lastChar != '\\') file += "/";
195                        file += pent->d_name;           
196
197                        if (stat(file.c_str(), &stats) != 0)
198                                return false;
199
200                        LOG << "Delete " << file << endl;
201
202                        if (S_ISDIR(stats.st_mode))
203                                DeleteDirectory(file.c_str(), false);
204                else
205                                remove(file.c_str());
206                }
207        }
208
209        // finally, let's clean up
210        closedir(pdir); // close the directory
211        if (!topLevel && !rmdir(sPath)) return false; // delete the directory
212        return true;
213#endif
214}
215
216bool FileSystemUtil::IsDots(const char* str) 
217{
218        if(strcmp(str,".") && strcmp(str,"..")) return false;
219        return true;
220}
221
222int FileSystemUtil::ValidateTargetDir(string targetFolder)
223{               
224        int nResult = -1;
225        try
226        {
227                cout << "Validating target folder: " << targetFolder << endl;
228
229                stringstream fName;
230                fName << targetFolder << "/valid.txt";
231
232                ofstream fout( fName.str().c_str(), ios::out);
233                fout << "arinside" << endl;
234                fout.close();
235
236                nResult = remove(fName.str().c_str());
237        }
238        catch(exception& e)
239        {
240                cout << "EXCEPTION ValidateTargetDir '" << targetFolder << "' -- " << e.what() << endl;
241        }
242
243        return nResult;
244}
245
246void FileSystemUtil::CompactFolder(string path)
247{
248#ifdef WIN32
249        string compactCmd = "compact /C /I /Q /S:" + path;
250        WinExec(compactCmd.c_str(), SW_SHOWNORMAL);
251#else
252        cout << "[WARN] CompactFolder is only supported on windows platform!" << endl;
253#endif
254}
255
256string FileSystemUtil::GetExecutableDirectory(const char* argv_0)
257{
258        // http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c
259#if WIN32
260        DWORD size = 1024;
261        LPTSTR buffer = NULL;
262ged_start:
263        buffer = (LPTSTR)realloc(buffer, size);
264        if (buffer == NULL)
265        {
266                cerr << "GetExecutableDirectory: Failed to realloc memory buffer to " << size << "!" << endl;
267                return "";
268        }
269       
270        if (GetModuleFileName(NULL, buffer, size) == 0)
271        {
272                cerr << "Failed to get executable directory" << GetFormattedMessage(GetLastError()) << endl;
273                return "";
274        }
275       
276        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
277        {
278                size = size << 1;
279                goto ged_start;
280        }
281
282        PathRemoveFileSpec(buffer);
283        string path = buffer;
284        free(buffer);
285
286        return path;
287#else
288        // first, we want to make sure we did get a valid argument
289        if (argv_0 == NULL || argv_0[0] == 0)
290        {
291                return "";
292        }
293
294        string path;
295
296        // if the program name starts with an '/', there is an absolute path specified
297        if (argv_0[0] == '/')
298        {
299                path = argv_0;
300               
301                string::size_type pos = path.find_last_of("/");
302                if (pos != -1)
303                {
304                        path.resize(pos+1);  // keep the slash at the end, it's safer.
305                }
306        }
307
308        // otherwise we use the current working directory or an additional relative path
309        else
310        {
311                char cwd[PATH_MAX+1];
312                ARZeroMemory(cwd);
313
314                if (getcwd(cwd, PATH_MAX) == NULL)
315                {
316                        // error while getting current working directory
317                        return "";
318                }
319                path = cwd;
320
321                // ok, do we have some relative path informations?
322                if (strchr(argv_0, '/') != NULL)
323                {
324                        if (path.length() > 0 && path[path.length()-1] != '/')
325                        {
326                                path += '/';
327                        }
328
329                        path += argv_0;
330                        string::size_type pos = path.find_last_of("/");
331                        if (pos != -1)
332                        {
333                                path.resize(pos+1);  // keep the slash at the end, it's safer.
334                        }
335                }
336        }
337        return path;
338#endif
339}
340
341#if WIN32
342string FileSystemUtil::GetFormattedMessage(unsigned int error)
343{
344        LPSTR buffer = NULL;
345        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, buffer, 200, NULL) == 0)
346        {
347                return "failed to get error message";
348        }
349        string errMessage = buffer;
350        LocalFree(buffer);
351        return errMessage;
352}
353#endif
354
355string FileSystemUtil::CombinePath(const std::string &path1, const std::string &path2)
356{
357        // if the second path points to the root (starts with PATH_SEPARATOR, we just return the 2nd path)
358        if (path2.length() > 0 && 
359#ifdef WIN32
360                (path2[0] == '/' || path2[0] == '\\')
361#else
362                path2[0] == '/'
363#endif
364                )
365        {
366                return path2;
367        }
368
369        stringstream result;
370
371        // add first part
372        result << path1;
373
374        // check if we need to add PATH_SEPARATOR
375        if (path1.length() > 0)
376        {
377                char lastPathChar = path1[path1.length()-1];
378#ifdef WIN32
379                if (lastPathChar != '/' && lastPathChar != '\\')
380#else
381                if (lastPathChar != '/')
382#endif
383                {
384                        result << ARINSIDE_PATH_SEPARATOR;
385                }
386        }
387
388        result << path2;
389        return result.str();
390}
Note: See TracBrowser for help on using the repository browser.