/////////////////////////////////////////////////////////////////////////////// // MQ4CPP - Message queuing for C++ // Copyright (C) 2004-2007 Riccardo Pompeo (Italy) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Directory management documentation link: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/listing_the_files_in_a_directory.asp // #define SILENT #include "Logger.h" #include "FileSystem.h" #ifndef WIN32 #include #include #include #include #include #include #include #include #define IOBUFSIZE 16384 #endif FileSystemException::FileSystemException() { #ifdef WIN32 LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); msg=(char*)lpMsgBuf; LocalFree(lpMsgBuf); #else char aMsg[256]; aMsg[0]=0; int err=errno; msg=strerror(err); #endif } string Persistent::getName() { TRACE("Persistent::getName - start") if(itsPath.size()==0) throw FileSystemException("Persistent::getName: path descriptor empty"); string& aString=itsPath[itsPath.size()-1]; TRACE("Persistent::getName - end") return aString; } void Persistent::setCreationTime(FSTimeType& theTime) { TRACE("Persistent::setCreationTime - start") #ifdef WIN32 itsCreationTime.dwLowDateTime=theTime.dwLowDateTime; itsCreationTime.dwHighDateTime=theTime.dwHighDateTime; #else itsCreationTime=theTime; #endif TRACE("Persistent::setCreationTime - end") } void Persistent::setSize(FSSizeType& theSize) { TRACE("Persistent::setSize - start") itsSize.size_low=theSize.size_low; itsSize.size_high=theSize.size_high; TRACE("Persistent::setSize - end") } void Persistent::decodePath(const char* thePath) { TRACE("Persistent::decodePath - start") TRACE("Path=" << thePath) itsPath.clear(); char aBuffer[256]; istrstream aStream(thePath); while(!aStream==false) { aStream.getline(aBuffer,sizeof(aBuffer),PATH_DELIM); if(!aStream==false) { if(aBuffer[0]!=0) { TRACE("Value=" << aBuffer) itsPath.push_back(aBuffer); } } } TRACE("Persistent::decodePath - end") } string Persistent::encodeFullName() { TRACE("Persistent::encodeFullName - start") #ifdef WIN32 string res; #else string res; res=PATH_DELIM; #endif if(itsPath.size()>0) { unsigned cnt=1; for(vector::iterator i = itsPath.begin(); i < itsPath.end(); ++i, ++cnt) { res+=*i; if(cnt0) { for(unsigned cnt=1; cntitsPath; itsReadOnly=theObj->itsReadOnly; itsHidden=theObj->itsHidden; memcpy(&itsCreationTime,&theObj->itsCreationTime,sizeof(FSTimeType)); memcpy(&itsSize,&theObj->itsSize,sizeof(FSSizeType)); TRACE("File::File - end") } fstream& File::open() { TRACE("File::open - start") string aFullName=encodeFullName(); itsStream.open(aFullName.c_str(),fstream::in|fstream::binary); if(!itsStream) throw FileSystemException("Failed to open file"); itsStream.seekg(0, ios::end); if(!itsStream) throw FileSystemException("Failed to seek file"); itsSize.size_low = itsStream.tellg(); itsSize.size_high = 0L; itsStream.seekg(0, ios::beg); if(!itsStream) throw FileSystemException("Failed to seek file"); TRACE("File::open - end") return itsStream; } fstream& File::create() { TRACE("File::create - start") string aFullName=encodeFullName(); itsStream.open(aFullName.c_str(),fstream::out|fstream::trunc|fstream::binary); if(!itsStream) throw FileSystemException("Failed to open file"); return itsStream; TRACE("File::create - end") } void File::close() { TRACE("File::close - start") itsStream.close(); TRACE("File::close - end") } File* File::copy(const char* theDestFullName) { TRACE("File::copy - start") TRACE("Destination=" << theDestFullName) string aSrcName=encodeFullName(); #ifdef WIN32 BOOL success=CopyFile(aSrcName.c_str(),theDestFullName,TRUE); if(success==FALSE) throw FileSystemException(); #else struct stat statbuf; int in_fd = ::open(aSrcName.c_str(), O_RDONLY); if(in_fd<0) throw FileSystemException(); fstat(in_fd, &statbuf); int out_fd = ::open(theDestFullName, O_WRONLY|O_CREAT|O_TRUNC, statbuf.st_mode); if(out_fd<0) { ::close(in_fd); throw FileSystemException(); } char* aBuffer=new char[IOBUFSIZE]; unsigned long bytesleft=statbuf.st_size; while(bytesleft>0) { ssize_t bytesread=read(in_fd, aBuffer, ((bytesleft>IOBUFSIZE)? IOBUFSIZE : bytesleft)); if(bytesread==-1) { ::close(out_fd); ::close(in_fd); throw FileSystemException(); } ssize_t bytewritten=write(out_fd, aBuffer, bytesread); if(bytewritten==-1 || bytewritten!=bytesread) { ::close(out_fd); ::close(in_fd); throw FileSystemException(); } bytesleft-=bytewritten; } delete [] aBuffer; fsync(out_fd); ::close(out_fd); ::close(in_fd); #endif File* ret=new File(theDestFullName); ret->itsHidden=itsHidden; ret->itsReadOnly=itsReadOnly; ret->itsSize=itsSize; memcpy(&ret->itsCreationTime,&itsCreationTime,sizeof(FSTimeType)); memcpy(&ret->itsSize,&itsSize,sizeof(FSSizeType)); TRACE("File::copy - end") return ret; } void File::remove() { TRACE("File::remove - start") string aFullName=encodeFullName(); #ifdef WIN32 BOOL ret=DeleteFile(aFullName.c_str()); if(ret==FALSE) throw FileSystemException(); #else if(::remove(aFullName.c_str())<0) throw FileSystemException(); #endif TRACE("File::remove - end") } Directory::Directory(Directory* theObj) : Persistent("Directory") //++1.7 { TRACE("Directory::Directory - start") itsPath=theObj->itsPath; itsReadOnly=theObj->itsReadOnly; itsHidden=theObj->itsHidden; memcpy(&itsCreationTime,&theObj->itsCreationTime,sizeof(FSTimeType)); memcpy(&itsSize,&theObj->itsSize,sizeof(FSSizeType)); TRACE("Directory::Directory - end") } Directory* Directory::upper() //++1.7 { TRACE("Directory::upper") return new Directory(encodePath()); } Directory* Directory::getCurrent() { TRACE("Directory::getCurrent - start") #ifdef WIN32 char buf[256]; BOOL success=GetCurrentDirectory(sizeof(buf),buf); if(success==FALSE) throw FileSystemException(); TRACE("Current directory=" << buf) string path = replaceAll(string(buf), "\\", "/"); Directory* ret=new Directory(path); ret->search(); #else #ifdef __FreeBSD__ char* ptr=getcwd (NULL, PATH_MAX); #else char* ptr=get_current_dir_name(); #endif TRACE("Current directory=" << ptr) Directory* ret=new Directory(ptr); ret->search(); ::free(ptr); #endif TRACE("Directory::getCurrent - end") return ret; } void Directory::free() { TRACE("Directory::free - start") if(itsContent.size()>0) { for(vector::iterator i = itsContent.begin(); i < itsContent.end(); ++i) { delete *i; } } itsContent.clear(); TRACE("Directory::free - end") } string Directory::replaceAll(string strBase, string strOld, string strNew) { TRACE("Directory::replaceAll - start") unsigned long iIndex1 = strBase.find(strOld, 0); unsigned long iIndex2 = 0; unsigned long iLengthOld = strOld.length(); unsigned long iLengthNew = strNew.length(); while (iIndex1 != string::npos) { iIndex2 = iIndex1 + iLengthNew + 1; strBase = strBase.erase(iIndex1, iLengthOld); strBase = strBase.insert(iIndex1, strNew); iIndex1 = strBase.find(strOld, iIndex2); } TRACE("Directory::replaceAll - end") return strBase; } void Directory::search(const char* thePattern) { TRACE("Directory::search - start") TRACE("Pattern=" << thePattern) free(); string aCurPath=encodeFullName(); #ifdef WIN32 aCurPath+=PATH_DELIM; string aDirSpec=aCurPath; aDirSpec+=thePattern; TRACE("Search path=" << aDirSpec.c_str()) if(aCurPath=="/") //++v1.7 { BOOL bFlag; TCHAR Buf[MAX_PATH]; // temporary buffer for volume name TCHAR Drive[] = TEXT("c:\\"); // template drive specifier TCHAR I; // generic loop counter for (I = TEXT('a'); I < TEXT('z'); I++ ) { // Stamp the drive for the appropriate letter. Drive[0] = I; bFlag = GetVolumeNameForVolumeMountPoint( Drive, // input volume mount point or directory Buf, // output volume name buffer MAX_PATH // size of volume name buffer ); if (bFlag) { TRACE("Found drive=" << Drive) string drv; drv+=(char)Drive[0]; drv+=":"; itsContent.push_back(new Directory(drv)); } } } else { WIN32_FIND_DATA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; hFind = FindFirstFile(aDirSpec.c_str(), &FindFileData); if (hFind == INVALID_HANDLE_VALUE) throw FileSystemException(); do { TRACE("Current file name is " << FindFileData.cFileName) string aFileName=FindFileData.cFileName; string aFullName=aCurPath+aFileName; if(aFileName!="." && aFileName!="..") //++v1.7 { Persistent* aPersistent=NULL; if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) aPersistent=new Directory(aFullName); else aPersistent=new File(aFullName); if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) aPersistent->setReadOnly(); if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) aPersistent->setHidden(); if(FindFileData.ftCreationTime.dwLowDateTime!=0 && FindFileData.ftCreationTime.dwHighDateTime!=0) aPersistent->setCreationTime(FindFileData.ftCreationTime); else aPersistent->setCreationTime(FindFileData.ftLastAccessTime); FSSizeType aSize; aSize.size_low=FindFileData.nFileSizeLow; aSize.size_high=FindFileData.nFileSizeHigh; aPersistent->setSize(aSize); itsContent.push_back(aPersistent); } } while (FindNextFile(hFind, &FindFileData) != 0); FindClose(hFind); } #else string pattern = replaceAll(thePattern, ".", "\\."); pattern = replaceAll(pattern, "*", ".*"); pattern = pattern + "$"; TRACE("Pattern=" << pattern.c_str()) regex_t regex; if (regcomp(®ex, pattern.c_str(), REG_EXTENDED|REG_NOSUB) == -1) throw FileSystemException(); dirent* dp=NULL; DIR* dirp = opendir(aCurPath.c_str()); if(dirp==NULL) throw FileSystemException(); while ((dp = readdir(dirp))!= NULL) { if (regexec(®ex, dp->d_name, 0, NULL, 0) == 0) { TRACE("Current file name is " << dp->d_name) string aFileName=dp->d_name; string aFullName=aCurPath; aFullName+=PATH_DELIM; aFullName+=aFileName; TRACE("Full path name=" << aFullName.c_str()) if(aFileName!="." && aFileName!="..") //++v1.7 { Persistent* aPersistent=NULL; struct stat aStat; if(stat(aFullName.c_str(),&aStat)<0) throw FileSystemException(); if(dp->d_type==DT_UNKNOWN) { // Fix reiserfs problem on kernel 2.6 if((aStat.st_mode & S_IFDIR)) aPersistent=new Directory(aFullName); else aPersistent=new File(aFullName); } else if(dp->d_type==DT_DIR) aPersistent=new Directory(aFullName); else aPersistent=new File(aFullName); if(!(aStat.st_mode & S_IWUSR)) aPersistent->setReadOnly(); if(dp->d_name[0]=='.') aPersistent->setHidden(); aPersistent->setCreationTime(aStat.st_mtime); FSSizeType aSize; aSize.size_low=aStat.st_size; aSize.size_high=0; aPersistent->setSize(aSize); itsContent.push_back(aPersistent); } } } closedir(dirp); regfree(®ex); #endif TRACE("Directory::search - end") } Persistent* Directory::get(const char* theName) { TRACE("Directory::get - start") TRACE("Searching for " << theName) Persistent* res=NULL; if(itsContent.size()>0) { for(vector::iterator i = itsContent.begin(); i < itsContent.end(); ++i) { Persistent* anObj=*i; if(anObj->getName()==theName) { res=anObj; break; } } } TRACE("Directory::get - end") return res; } Persistent* Directory::get(unsigned thePosition) // ++v1.7 { TRACE("Directory::get - start") TRACE("Position=" << thePosition) Persistent* res=NULL; if(thePosition < itsContent.size()) { res=itsContent[thePosition]; } TRACE("Directory::get - end") return res; } vector::iterator Directory::getIterator() { return itsContent.begin(); } bool Directory::testIterator(vector::iterator& i) { return (i < itsContent.end()); } void Directory::find(vector& theResult,Directory& theDir,const char* thePattern) { TRACE("Directory::find - start") theDir.search(thePattern); for(vector::iterator i = theDir.getIterator(); theDir.testIterator(i) ; ++i) { Persistent* anObj=*i; if(anObj->is("File")) { theResult.push_back((File*)anObj); } else if(anObj->is("Directory")) { find(theResult,(Directory&)*anObj,thePattern); } } TRACE("Directory::find - end") } void Directory::copy(Directory& theDestDir,Directory& theSrcDir) { TRACE("Directory::copy - start") theSrcDir.search(); for(vector::iterator i = theSrcDir.getIterator(); theSrcDir.testIterator(i) ; ++i) { Persistent* anObj=*i; if(anObj->is("File")) { theDestDir.copy((File*)anObj); } else if(anObj->is("Directory")) { string aName=theSrcDir.getName(); Directory* aDir=theDestDir.mkdir(aName.c_str()); copy(*aDir,(Directory&)*anObj); } } TRACE("Directory::copy - end") } void Directory::rmdir() { TRACE("Directory::rmdir - start") string aFullName=encodeFullName(); #ifdef WIN32 BOOL ret=RemoveDirectory(aFullName.c_str()); if(ret==FALSE) throw FileSystemException(); #else if(::rmdir(aFullName.c_str())<0) throw FileSystemException(); #endif TRACE("Directory::rmdir - end") } void Directory::rmdir(Directory& theDir) { TRACE("Directory::rmdir - start") theDir.search(); for(vector::iterator i = theDir.getIterator(); theDir.testIterator(i) ; ++i) { Persistent* anObj=*i; if(anObj->is("File")) { ((File*)anObj)->remove(); } else if(anObj->is("Directory")) { rmdir((Directory&)*anObj); } } theDir.rmdir(); TRACE("Directory::rmdir - end") } void Directory::move(Directory& theDestDir,Directory& theSrcDir) { TRACE("Directory::move - start") theSrcDir.search(); for(vector::iterator i = theSrcDir.getIterator(); theSrcDir.testIterator(i) ; ++i) { Persistent* anObj=*i; if(anObj->is("File")) { theDestDir.copy((File*)anObj); ((File*)anObj)->remove(); } else if(anObj->is("Directory")) { string aName=theSrcDir.getName(); Directory* aDir=theDestDir.mkdir(aName.c_str()); move(*aDir,(Directory&)*anObj); } } theSrcDir.rmdir(); TRACE("Directory::move - end") } Directory* Directory::mkdir(const char* theName) { TRACE("Directory::mkdir - start") string aFullName=encodeFullName(); aFullName+=PATH_DELIM; aFullName+=theName; #ifdef WIN32 BOOL ret=CreateDirectory(aFullName.c_str(),NULL); if(ret==FALSE) throw FileSystemException(); #else if(::mkdir(aFullName.c_str(),S_IWUSR|S_IRUSR|S_IXUSR|S_IWGRP|S_IRGRP|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH)<0) throw FileSystemException(); #endif Directory* aDir=new Directory(aFullName); itsContent.push_back(aDir); TRACE("Directory::mkdir - end") return aDir; } Directory* Directory::mkfulldir(const char* theFullPath) { TRACE("Directory::mkfulldir - start") TRACE("Path=" << theFullPath) char aBuffer[256]; Directory* aDir=NULL; Directory* aRoot=NULL; Directory* ret=NULL; istrstream aStream(theFullPath); while(!aStream==false) { aStream.getline(aBuffer,sizeof(aBuffer),PATH_DELIM); if(!aStream==false && aBuffer[0]!=0) { if(aDir==NULL) { aRoot=new Directory(aBuffer); aDir=aRoot; } else { aDir->search(); Persistent* aPersistent=aDir->get(aBuffer); if(aPersistent!=NULL && aPersistent->is("Directory")) { TRACE("Found dir=" << aBuffer) aDir=(Directory*)aPersistent; } else { TRACE("Create new dir=" << aBuffer) aDir=aDir->mkdir(aBuffer); } } } } if(aDir!=NULL) ret=new Directory(aDir); else throw FileSystemException(); if(aRoot!=NULL) delete aRoot; TRACE("Directory::mkfulldir - end") return ret; } File* Directory::create(const char* theFileName) { TRACE("Directory::create - start") string aFullName=encodeFullName(); aFullName+=PATH_DELIM; aFullName+=theFileName; File* aFile=new File(aFullName.c_str()); itsContent.push_back(aFile); TRACE("Directory::create - end") return aFile; } void Directory::copy(File* theFile) { TRACE("Directory::copy - start") string aFullName=encodeFullName(); aFullName+=PATH_DELIM; aFullName+=theFile->getName(); File* aFile=theFile->copy(aFullName.c_str()); itsContent.push_back(aFile); TRACE("Directory::copy - end") } void testFS() { char* TMPDIR="/tmp"; char* TLOGDIR="/tmp/tlog/test_copy.log"; char* TLOG1DIR="/tmp/tlog1"; DISPLAY("Start test") Directory* aTlogDir=NULL; Directory* aTlogDir1=NULL; Directory* aCurDir=Directory::getCurrent(); Directory* aTmpDir=new Directory(TMPDIR); aTmpDir->search(); aTlogDir=(Directory*)aTmpDir->get("tlog"); if(aTlogDir==NULL) { aTlogDir=aTmpDir->mkdir("tlog"); DISPLAY(aTlogDir->getName() << " created") } aTlogDir1=(Directory*)aTmpDir->get("tlog1"); if(aTlogDir1==NULL) { aTlogDir1=aTmpDir->mkdir("tlog1"); DISPLAY(aTlogDir1->getName() << " created") } File* aFile=((Directory*)aTlogDir)->create("test.log"); fstream& aStream=aFile->create(); aStream << "Hello World!"; aFile->close(); DISPLAY(aFile->getName() << " created") aFile->move(TLOG1DIR); File* aFile1=aFile->copy(TLOGDIR); DISPLAY(aFile1->getName() << " copied") aFile->remove(); aFile1->remove(); aTlogDir->rmdir(); aTlogDir1->rmdir(); delete aCurDir; delete aTmpDir; DISPLAY("Test done") }