FileInfo.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   (c) Jürgen Riegel (juergen.riegel@web.de) 2005                        *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU Library General Public License (LGPL)   *
00008  *   as published by the Free Software Foundation; either version 2 of     *
00009  *   the License, or (at your option) any later version.                   *
00010  *   for detail see the LICENCE text file.                                 *
00011  *                                                                         *
00012  *   FreeCAD is distributed in the hope that it will be useful,            *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with FreeCAD; if not, write to the Free Software        *
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020  *   USA                                                                   *
00021  *                                                                         *
00022  *   Juergen Riegel 2002                                                   *
00023  ***************************************************************************/
00024 
00025 
00026 #include "PreCompiled.h"
00027 
00028 #ifndef _PreComp_
00029 # include <cassert>
00030 # include <cstdio>
00031 # include <cstdlib>
00032 # include <fstream>
00033 # include <climits>
00034 # include <cstring>
00035 # if defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00036 # include <dirent.h>
00037 # include <unistd.h>
00038 # include <sys/stat.h>
00039 # elif defined (FC_OS_WIN32)
00040 # include <direct.h>
00041 # include <io.h>
00042 # include <windows.h>
00043 # endif
00044 #endif
00045 
00046 
00047 #include "FileInfo.h"
00048 #include "Exception.h"
00049 #include "Stream.h"
00050 #include <sys/types.h>
00051 #include <sys/stat.h>
00052 #include <cstdio>
00053 
00054 #define new DEBUG_CLIENTBLOCK
00055 
00056 using namespace Base;
00057 
00058 
00059 //**********************************************************************************
00060 // helper
00061 
00062 #ifdef FC_OS_WIN32
00063 std::string ConvertFromWideString(const std::wstring& string)
00064 {
00065     int neededSize = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), -1, 0, 0,0,0);
00066     char * CharString = new char[neededSize];
00067     WideCharToMultiByte(CP_UTF8, 0, string.c_str(), -1, CharString, neededSize,0,0);
00068     std::string String((char*)CharString);
00069     delete [] CharString;
00070     CharString = NULL;
00071     return String;
00072 }
00073 
00074 std::wstring ConvertToWideString(const std::string& string)
00075 {
00076     int neededSize = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, 0, 0);
00077     wchar_t* wideCharString = new wchar_t[neededSize];
00078     MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, wideCharString, neededSize);
00079     std::wstring wideString(wideCharString);
00080     delete [] wideCharString;
00081     wideCharString = NULL;
00082     return wideString;
00083 }
00084 #endif
00085 
00086 
00087 //**********************************************************************************
00088 // FileInfo
00089 
00090 
00091 FileInfo::FileInfo (const char* _FileName)
00092 {
00093     setFile(_FileName);
00094 }
00095 
00096 FileInfo::FileInfo (const std::string &_FileName)
00097 {
00098     setFile(_FileName.c_str());
00099 }
00100 
00101 const std::string &FileInfo::getTempPath(void)
00102 {
00103     static std::string tempPath;
00104 
00105     if (tempPath == "") {
00106 #ifdef FC_OS_WIN32
00107         wchar_t buf[MAX_PATH + 2];
00108         GetTempPathW(MAX_PATH + 1,buf);
00109         int neededSize = WideCharToMultiByte(CP_UTF8, 0, buf, -1, 0, 0, 0, 0);
00110         char* dest = new char[neededSize];
00111         WideCharToMultiByte(CP_UTF8, 0, buf, -1,dest, neededSize, 0, 0);
00112         tempPath = dest;
00113         delete [] dest;
00114 #else
00115         const char* tmp = getenv("TMPDIR");
00116         if (tmp && tmp[0] != '\0') {
00117             tempPath = tmp;
00118             FileInfo fi(tempPath);
00119             if (tempPath.empty() || !fi.isDir()) // still empty or non-existent
00120                 tempPath = "/tmp/";
00121             else if (tempPath.at(tempPath.size()-1)!='/')
00122                 tempPath.append("/");
00123         }
00124         else {
00125             tempPath = "/tmp/";
00126         }
00127 #endif
00128     }
00129 
00130     return tempPath;
00131 }
00132 
00133 std::string FileInfo::getTempFileName(const char* FileName, const char* Path)
00134 {
00135     //FIXME: To avoid race conditons we should rather return a file pointer
00136     //than a file name.
00137 #ifdef FC_OS_WIN32
00138     wchar_t buf[MAX_PATH + 2];
00139 
00140     // Path where the file is located
00141     std::wstring path; 
00142     if (Path)
00143         path = ConvertToWideString(std::string(Path));
00144     else
00145         path = ConvertToWideString(getTempPath());
00146 
00147     // File name in the path 
00148     std::wstring file; 
00149     if (FileName)
00150         file = ConvertToWideString(std::string(FileName));
00151     else
00152         file = L"FCTempFile";
00153 
00154 
00155     // this already creates the file
00156     GetTempFileNameW(path.c_str(),file.c_str(),0,buf);
00157 
00158     return std::string(ConvertFromWideString(std::wstring(buf)));
00159 #else
00160     char buf[PATH_MAX+1];
00161 
00162     // Path where the file is located
00163     if (Path)
00164         std::strncpy(buf, Path, PATH_MAX);
00165     else
00166         std::strncpy(buf, getTempPath().c_str(), PATH_MAX);
00167 
00168     buf[PATH_MAX] = 0; // null termination needed
00169 
00170     // File name in the path 
00171     if (FileName) {
00172         std::strcat(buf, "/");
00173         std::strcat(buf, FileName);
00174         std::strcat(buf, "XXXXXX");
00175     }
00176     else
00177         std::strcat(buf, "/fileXXXXXX");
00178 
00179     /*int id =*/ (void) mkstemp(buf);
00180     //FILE* file = fdopen(id, "w");
00181     return std::string(buf);
00182 #endif
00183 }
00184 
00185 void FileInfo::setFile(const char* name)
00186 {
00187     std::string result;
00188     const char *It=name;
00189 
00190     while(*It != '\0') {
00191         switch(*It)
00192         {
00193         case '\\':
00194             result += "/";
00195             break;
00196         default:
00197             result += *It;
00198         }
00199         It++;
00200     }
00201 
00202     FileName = result;
00203 }
00204 
00205 std::string FileInfo::filePath () const
00206 {
00207     return FileName;
00208 }
00209 
00210 std::string FileInfo::fileName () const
00211 {
00212     return FileName.substr(FileName.find_last_of('/')+1);
00213 }
00214 
00215 std::string FileInfo::dirPath () const
00216 {
00217     return FileName.substr(0,FileName.find_last_of('/'));
00218 }
00219 
00220 std::string FileInfo::fileNamePure () const
00221 {
00222     std::string temp = fileName();
00223     std::string::size_type pos = temp.find_last_of('.');
00224   
00225     if (pos != std::string::npos)
00226         return temp.substr(0,pos);
00227     else 
00228         return temp;
00229 }
00230 
00231 std::wstring FileInfo::toStdWString() const
00232 {
00233     // As FileName is UTF-8 is encoded we have to convert it
00234     // for Windows because the path names are UCS-2 encoded.
00235 #ifdef FC_OS_WIN32
00236     return ConvertToWideString(FileName);
00237 #else
00238     // FIXME: For MacOS the path names are UCS-4 encoded.
00239     // For the moment we cannot handle path names containing
00240     // non-ASCII characters.
00241     // For Linux the paths names are encoded in UTF-8 so we actually
00242     // don't need this method therefore.
00243     return std::wstring();
00244 #endif
00245 }
00246 
00247 std::string FileInfo::extension (bool complete) const
00248 {
00249     // complete not implemented
00250     assert(complete==false);
00251     std::string::size_type pos = FileName.find_last_of('.');
00252     if (pos == std::string::npos)
00253         return std::string();
00254     return FileName.substr(pos+1);
00255 }
00256 
00257 bool FileInfo::hasExtension (const char* Ext) const
00258 {
00259 #if defined (FC_OS_WIN32)
00260     return _stricmp(Ext,extension().c_str()) == 0;
00261 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00262     return strcasecmp(Ext,extension().c_str()) == 0;
00263 #endif
00264 }
00265 
00266 bool FileInfo::exists () const
00267 {
00268 #if defined (FC_OS_WIN32)
00269     std::wstring wstr = toStdWString();
00270     return _waccess(wstr.c_str(),0) == 0;
00271 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00272     return access(FileName.c_str(),0) == 0;
00273 #endif
00274 }
00275 
00276 bool FileInfo::isReadable () const
00277 {
00278 #if defined (FC_OS_WIN32)
00279     std::wstring wstr = toStdWString();
00280     return _waccess(wstr.c_str(),4) == 0;
00281 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00282     return access(FileName.c_str(),4) == 0;
00283 #endif
00284 }
00285 
00286 bool FileInfo::isWritable () const
00287 {
00288 #if defined (FC_OS_WIN32)
00289     std::wstring wstr = toStdWString();
00290     return _waccess(wstr.c_str(),2) == 0;
00291 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00292     return access(FileName.c_str(),2) == 0;
00293 #endif
00294 }
00295 
00296 bool FileInfo::isFile () const
00297 {
00298 #ifdef FC_OS_WIN32
00299     if (exists()) {
00300         std::wstring wstr = toStdWString();
00301         FILE* fd = _wfopen(wstr.c_str(), L"rb");
00302         bool ok = (fd != 0);
00303         fclose(fd);
00304         return ok;
00305     }
00306 #else
00307     if (exists()) {
00308         // If we can open it must be an existing file, otherwise we assume it
00309         // is a directory (which doesn't need to be true for any cases)
00310         std::ifstream str(FileName.c_str(), std::ios::in | std::ios::binary);
00311         if (!str) return false;
00312         str.close();
00313         return true;
00314     }
00315 #endif
00316 
00317     // TODO: Check for valid file name
00318     return true;
00319 }
00320 
00321 bool FileInfo::isDir () const
00322 {
00323     if (exists()) {
00324         // if we can chdir then it must be a directory, otherwise we assume it
00325         // is a file (which doesn't need to be true for any cases)
00326 #if defined (FC_OS_WIN32)
00327         std::wstring wstr = toStdWString();
00328         struct _stat st;
00329 
00330         if (_wstat(wstr.c_str(), &st) != 0)
00331             return false;
00332         return ((st.st_mode & _S_IFDIR) != 0);
00333 
00334 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00335         struct stat st;
00336         if (stat(FileName.c_str(), &st) != 0) {
00337             return false;
00338         }
00339         return S_ISDIR(st.st_mode);
00340 #endif
00341         return false;
00342     }
00343     else
00344         return false;
00345 
00346     // TODO: Check for valid path name
00347     return true;
00348 }
00349 
00350 unsigned int FileInfo::size () const
00351 {
00352     // not implemented
00353     assert(0);
00354     return 0;
00355 }
00356 
00357 TimeInfo FileInfo::lastModified() const
00358 {
00359     TimeInfo ti = TimeInfo::null();
00360     if (exists()) {
00361 
00362 #if defined (FC_OS_WIN32)
00363         std::wstring wstr = toStdWString();
00364         struct _stat st;
00365         if (_wstat(wstr.c_str(), &st) == 0) {
00366             ti.setTime_t(st.st_mtime);
00367         }
00368 
00369 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00370         struct stat st;
00371         if (stat(FileName.c_str(), &st) == 0) {
00372             ti.setTime_t(st.st_mtime);
00373         }
00374 #endif
00375 
00376     }
00377     return ti;
00378 }
00379 
00380 TimeInfo FileInfo::lastRead() const
00381 {
00382     TimeInfo ti = TimeInfo::null();
00383     if (exists()) {
00384 
00385 #if defined (FC_OS_WIN32)
00386         std::wstring wstr = toStdWString();
00387         struct _stat st;
00388         if (_wstat(wstr.c_str(), &st) == 0) {
00389             ti.setTime_t(st.st_atime);
00390         }
00391 
00392 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00393         struct stat st;
00394         if (stat(FileName.c_str(), &st) == 0) {
00395             ti.setTime_t(st.st_atime);
00396         }
00397 #endif
00398 
00399     }
00400     return ti;
00401 }
00402 
00403 bool FileInfo::deleteFile(void) const
00404 {
00405 #if defined (FC_OS_WIN32)
00406     std::wstring wstr = toStdWString();
00407     return ::_wremove(wstr.c_str()) == 0;
00408 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00409     return (::remove(FileName.c_str())==0);
00410 #else
00411 #   error "FileInfo::deleteFile() not implemented for this platform!"
00412 #endif
00413 }
00414 
00415 bool FileInfo::renameFile(const char* NewName)
00416 {
00417     bool res;
00418 #if defined (FC_OS_WIN32)
00419     std::wstring oldname = toStdWString();
00420     std::wstring newname = ConvertToWideString(NewName);
00421     res = ::_wrename(oldname.c_str(),newname.c_str()) == 0;
00422 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00423     res = ::rename(FileName.c_str(),NewName) == 0;
00424 #else
00425 #   error "FileInfo::renameFile() not implemented for this platform!"
00426 #endif
00427     setFile(NewName);
00428 
00429     return res;
00430 }
00431 
00432 bool FileInfo::copyTo(const char* NewName) const
00433 {
00434 #if defined (FC_OS_WIN32)
00435     std::wstring oldname = toStdWString();
00436     std::wstring newname = ConvertToWideString(NewName);
00437     return CopyFileW(oldname.c_str(),newname.c_str(),true) != 0;
00438 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00439     FileInfo fi1(FileName);
00440     FileInfo fi2(NewName);
00441     Base::ifstream file(fi1, std::ios::in | std::ios::binary);
00442     Base::ofstream copy(fi2, std::ios::out | std::ios::binary);
00443     file >> copy.rdbuf();
00444     return file.is_open() && copy.is_open();
00445 #else
00446 #   error "FileInfo::copyTo() not implemented for this platform!"
00447 #endif
00448 }
00449 
00450 bool FileInfo::createDirectory(void) const
00451 {
00452 #if defined (FC_OS_WIN32)
00453     std::wstring wstr = toStdWString();
00454     return _wmkdir(wstr.c_str()) == 0;
00455 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00456     return mkdir(FileName.c_str(), 0777) == 0;
00457 #else
00458 #   error "FileInfo::createDirectory() not implemented for this platform!"
00459 #endif
00460 }
00461 
00462 bool FileInfo::deleteDirectory(void) const
00463 {
00464     if (isDir() == false ) return false;
00465 #if defined (FC_OS_WIN32)
00466     std::wstring wstr = toStdWString();
00467     return _wrmdir(wstr.c_str()) == 0;
00468 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00469     return rmdir(FileName.c_str()) == 0;
00470 #else
00471 #   error "FileInfo::createDirectory() not implemented for this platform!"
00472 #endif
00473 }
00474 
00475 bool FileInfo::deleteDirectoryRecursive(void) const
00476 {
00477     if (isDir() == false ) return false;
00478     std::vector<Base::FileInfo> List = getDirectoryContent();
00479 
00480     for (std::vector<Base::FileInfo>::iterator It = List.begin();It!=List.end();++It) {
00481         if (It->isDir())
00482             It->deleteDirectoryRecursive();
00483         else if(It->isFile())
00484             It->deleteFile();
00485         else
00486             Base::Exception("FileInfo::deleteDirectoryRecursive(): Unknown object Type in directory!");
00487     }
00488     return deleteDirectory();
00489 }
00490 
00491 std::vector<Base::FileInfo> FileInfo::getDirectoryContent(void) const
00492 {
00493     std::vector<Base::FileInfo> List;
00494 #if defined (FC_OS_WIN32)
00495     struct _wfinddata_t dentry;
00496     long hFile;
00497 
00498     // Find first directory entry
00499     std::wstring wstr = toStdWString();
00500     wstr += L"/*";
00501 
00502     if ((hFile = _wfindfirst( wstr.c_str(), &dentry)) == -1L)
00503         return List;
00504 
00505     while (_wfindnext(hFile, &dentry) == 0)
00506         if (wcscmp(dentry.name,L"..") != 0)
00507             List.push_back(FileInfo(FileName + "/" +ConvertFromWideString(std::wstring(dentry.name))));
00508 
00509     _findclose(hFile);
00510 
00511 #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00512     DIR* dp(0);
00513     struct dirent* dentry(0);
00514     if ((dp = opendir(FileName.c_str())) == NULL)
00515     {
00516         return List;
00517     }
00518 
00519     while ((dentry = readdir(dp)) != NULL)
00520     {
00521         std::string dir = dentry->d_name;
00522         if (dir != "." && dir != "..")
00523             List.push_back(FileInfo(FileName + "/" + dir));
00524     }
00525     closedir(dp);
00526 #else
00527 #   error "FileInfo::getDirectoryContent() not implemented for this platform!"
00528 #endif
00529     return List;
00530 }

Generated on Wed Nov 23 19:00:14 2011 for FreeCAD by  doxygen 1.6.1