/* * "$Id: rsdir.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" * * RetroShare C++ Interface. * * Copyright 2004-2007 by Robert Fernie. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License Version 2 as published by the Free Software Foundation. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. * * Please report all bugs and problems to "retroshare@lunamutt.com". * */ // Includes for directory creation. #include #include #include #include #include "util/rsdir.h" #include "util/rsstring.h" #include "util/rsrandom.h" #include "retroshare/rstypes.h" #include "rsthreads.h" #include #include #include #include #include #include #include #include #if defined(WIN32) || defined(__CYGWIN__) #include "util/rsstring.h" #include "wtypes.h" #include #else #include #endif /**** * #define RSDIR_DEBUG 1 ****/ std::string RsDirUtil::getTopDir(const std::string& dir) { std::string top; /* find the subdir: [/][dir1.../][/] */ int i,j; int len = dir.length(); for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ; for(i = j; (i > 0) && (dir[i] != '/'); i--) ; if (dir[i] == '/') i++; for(; i <= j; i++) { top += dir[i]; } return top; } const char *RsDirUtil::scanf_string_for_uint(int bytes) { const char *strgs[3] = { "%u","%lu","%llu" } ; //std::cerr << "RsDirUtil::scanf_string_for_uint(): returning for bytes=" << bytes << std::endl; if(sizeof(unsigned int) == bytes) return strgs[0] ; if(sizeof(long unsigned int) == bytes) return strgs[1] ; if(sizeof(long long unsigned int) == bytes) return strgs[2] ; std::cerr << "RsDirUtil::scanf_string_for_uint(): no corresponding scan string for "<< bytes << " bytes. This will probably cause inconsistencies." << std::endl; return strgs[0] ; } void RsDirUtil::removeTopDir(const std::string& dir, std::string& path) { path.clear(); /* remove the subdir: [/][dir1.../][/] */ int j = dir.find_last_not_of('/'); int i = dir.rfind('/', j); /* remove any more slashes */ if (i > 0) { i = dir.find_last_not_of('/', i); } if (i > 0) { path.assign(dir, 0, i + 1); } } std::string RsDirUtil::getRootDir(const std::string& dir) { std::string root; /* find the subdir: [/]root[/...] */ int i,j; int len = dir.length(); for(i = 0; (i < len) && (dir[i] == '/'); i++) ; for(j = i; (j < len) && (dir[j] != '/'); j++) ; if (i == j) return root; /* empty */ for(; i < j; i++) { root += dir[i]; } return root; } std::string RsDirUtil::removeRootDir(const std::string& path) { unsigned int i, j; unsigned int len = path.length(); std::string output; /* chew leading '/'s */ for(i = 0; (i < len) && (path[i] == '/'); i++) ; if (i == len) return output; /* empty string */ for(j = i; (j < len) && (path[j] != '/'); j++) ; /* run to next '/' */ for(; (j < len) && (path[j] == '/'); j++) ; /* chew leading '/'s */ for(; j < len; j++) { output += path[j]; } return output; } std::string RsDirUtil::removeRootDirs(const std::string& path, const std::string& root) { /* too tired */ std::string notroot; unsigned int i = 0, j = 0; /* catch empty data */ if ((root.length() < 1) || (path.length() < 1)) return notroot; if ((path[0] == '/') && (root[0] != '/')) { i++; } for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++) ; /* should have consumed root. */ if (j == root.length()) { //std::cerr << "matched root!" << std::endl; } else { //std::cerr << "failed i: " << i << ", j: " << j << std::endl; //std::cerr << "root: " << root << " path: " << path << std::endl; return notroot; } if (path[i] == '/') { i++; } for(; i < path.length(); i++) { notroot += path[i]; } //std::cerr << "Found NotRoot: " << notroot << std::endl; return notroot; } int RsDirUtil::breakupDirList(const std::string& path, std::list &subdirs) { int start = 0; unsigned int i; for(i = 0; i < path.length(); i++) { if (path[i] == '/') { if (i - start > 0) { subdirs.push_back(path.substr(start, i-start)); } start = i+1; } } // get the final one. if (i - start > 0) { subdirs.push_back(path.substr(start, i-start)); } return 1; } /**** Copied and Tweaked from ftcontroller ***/ bool RsDirUtil::fileExists(const std::string& filename) { return ( access( filename.c_str(), F_OK ) != -1 ); } /**** Copied and Tweaked from ftcontroller ***/ bool RsDirUtil::copyFile(const std::string& source,const std::string& dest) { #ifdef WINDOWS_SYS std::wstring sourceW; std::wstring destW; librs::util::ConvertUtf8ToUtf16(source,sourceW); librs::util::ConvertUtf8ToUtf16(dest,destW); return (CopyFileW(sourceW.c_str(), destW.c_str(), FALSE) != 0); #else FILE *in = fopen64(source.c_str(),"rb") ; if(in == NULL) { return false ; } FILE *out = fopen64(dest.c_str(),"wb") ; if(out == NULL) { fclose (in); return false ; } size_t s=0; size_t T=0; static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up. void *buffer = malloc(BUFF_SIZE) ; bool bRet = true; while( (s = fread(buffer,1,BUFF_SIZE,in)) > 0) { size_t t = fwrite(buffer,1,s,out) ; T += t ; if(t != s) { bRet = false ; break; } } fclose(in) ; fclose(out) ; free(buffer) ; return true ; #endif } bool RsDirUtil::checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file) { int val; mode_t st_mode; #ifdef WINDOWS_SYS std::wstring wfilename; librs::util::ConvertUtf8ToUtf16(filename, wfilename); struct _stat buf; val = _wstat(wfilename.c_str(), &buf); st_mode = buf.st_mode; #else struct stat64 buf; val = stat64(filename.c_str(), &buf); st_mode = buf.st_mode; #endif if (val == -1) { #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkFile() "; std::cerr << filename << " doesn't exist" << std::endl; #endif return false; } else if (!S_ISREG(st_mode)) { // Some other type - error. #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkFile() "; std::cerr << filename << " is not a Regular File" << std::endl; #endif return false; } file_size = buf.st_size ; if(disallow_empty_file && buf.st_size == 0) return false ; return true; } bool RsDirUtil::checkDirectory(const std::string& dir) { int val; mode_t st_mode; #ifdef WINDOWS_SYS std::wstring wdir; librs::util::ConvertUtf8ToUtf16(dir, wdir); struct _stat buf; val = _wstat(wdir.c_str(), &buf); st_mode = buf.st_mode; #else struct stat buf; val = stat(dir.c_str(), &buf); st_mode = buf.st_mode; #endif if (val == -1) { #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkDirectory() "; std::cerr << dir << " doesn't exist" << std::endl; #endif return false; } else if (!S_ISDIR(st_mode)) { // Some other type - error. #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkDirectory() "; std::cerr << dir << " is not Directory" << std::endl; #endif return false; } return true; } bool RsDirUtil::checkCreateDirectory(const std::string& dir) { #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkCreateDirectory() dir: " << dir << std::endl; #endif #ifdef WINDOWS_SYS std::wstring wdir; librs::util::ConvertUtf8ToUtf16(dir, wdir); _WDIR *direc = _wopendir(wdir.c_str()); if (!direc) #else DIR *direc = opendir(dir.c_str()); if (!direc) #endif { // directory don't exist. create. /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS // UNIX if (-1 == mkdir(dir.c_str(), 0777)) #else // WIN if (-1 == _wmkdir(wdir.c_str())) #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ { #ifdef RSDIR_DEBUG std::cerr << "check_create_directory() Fatal Error et oui--"; std::cerr < &keepFiles) { /* check for the dir existance */ #ifdef WINDOWS_SYS std::wstring wcleandir; librs::util::ConvertUtf8ToUtf16(cleandir, wcleandir); _WDIR *dir = _wopendir(wcleandir.c_str()); #else DIR *dir = opendir(cleandir.c_str()); #endif if (!dir) { return false; } #ifdef WINDOWS_SYS struct _wdirent *dent; struct _stat buf; while(NULL != (dent = _wreaddir(dir))) #else struct dirent *dent; struct stat buf; while(NULL != (dent = readdir(dir))) #endif { /* check entry type */ #ifdef WINDOWS_SYS const std::wstring &wfname = dent -> d_name; std::wstring wfullname = wcleandir + L"/" + wfname; #else const std::string &fname = dent -> d_name; std::string fullname = cleandir + "/" + fname; #endif #ifdef WINDOWS_SYS if (-1 != _wstat(wfullname.c_str(), &buf)) #else if (-1 != stat(fullname.c_str(), &buf)) #endif { /* only worry about files */ if (S_ISREG(buf.st_mode)) { #ifdef WINDOWS_SYS std::string fname; librs::util::ConvertUtf16ToUtf8(wfname, fname); #endif /* check if we should keep it */ if (keepFiles.end() == std::find(keepFiles.begin(), keepFiles.end(), fname)) { /* can remove */ #ifdef WINDOWS_SYS _wremove(wfullname.c_str()); #else remove(fullname.c_str()); #endif } } } } /* close directory */ #ifdef WINDOWS_SYS _wclosedir(dir); #else closedir(dir); #endif return true; } /* faster cleanup - first construct two sets - then iterate over together */ bool RsDirUtil::cleanupDirectoryFaster(const std::string& cleandir, const std::set &keepFiles) { /* check for the dir existance */ #ifdef WINDOWS_SYS std::map fileMap; std::map::const_iterator fit; std::wstring wcleandir; librs::util::ConvertUtf8ToUtf16(cleandir, wcleandir); _WDIR *dir = _wopendir(wcleandir.c_str()); #else std::map fileMap; std::map::const_iterator fit; DIR *dir = opendir(cleandir.c_str()); #endif if (!dir) { return false; } #ifdef WINDOWS_SYS struct _wdirent *dent; struct _stat buf; while(NULL != (dent = _wreaddir(dir))) { const std::wstring &wfname = dent -> d_name; std::wstring wfullname = wcleandir + L"/" + wfname; if (-1 != _wstat(wfullname.c_str(), &buf)) { /* only worry about files */ if (S_ISREG(buf.st_mode)) { std::string fname; librs::util::ConvertUtf16ToUtf8(wfname, fname); fileMap[fname] = wfullname; } } } #else struct dirent *dent; struct stat buf; while(NULL != (dent = readdir(dir))) { const std::string &fname = dent -> d_name; std::string fullname = cleandir + "/" + fname; if (-1 != stat(fullname.c_str(), &buf)) { /* only worry about files */ if (S_ISREG(buf.st_mode)) { fileMap[fname] = fullname; } } } #endif std::set::const_iterator kit; fit = fileMap.begin(); kit = keepFiles.begin(); while(fit != fileMap.end() && kit != keepFiles.end()) { if (fit->first < *kit) // fit is not in keep list; { #ifdef WINDOWS_SYS _wremove(fit->second.c_str()); #else remove(fit->second.c_str()); #endif ++fit; } else if (*kit < fit->first) // keepitem doesn't exist. { ++kit; } else // in keep list. { ++fit; ++kit; } } // cleanup extra that aren't in keep list. while(fit != fileMap.end()) { #ifdef WINDOWS_SYS _wremove(fit->second.c_str()); #else remove(fit->second.c_str()); #endif ++fit; } /* close directory */ #ifdef WINDOWS_SYS _wclosedir(dir); #else closedir(dir); #endif return true; } /* slightly nicer helper function */ bool RsDirUtil::hashFile(const std::string& filepath, std::string &name, RsFileHash &hash, uint64_t &size) { if (getFileHash(filepath, hash, size)) { /* extract file name */ name = RsDirUtil::getTopDir(filepath); return true; } return false; } #include #include /* Function to hash, and get details of a file */ bool RsDirUtil::getFileHash(const std::string& filepath, RsFileHash &hash, uint64_t &size, RsThread *thread /*= NULL*/) { FILE *fd; int len; SHA_CTX *sha_ctx = new SHA_CTX; unsigned char sha_buf[SHA_DIGEST_LENGTH]; unsigned char gblBuf[512]; if (NULL == (fd = RsDirUtil::rs_fopen(filepath.c_str(), "rb"))) return false; /* determine size */ fseeko64(fd, 0, SEEK_END); size = ftello64(fd); fseeko64(fd, 0, SEEK_SET); /* check if thread is running */ bool isRunning = thread ? thread->isRunning() : true; int runningCheckCount = 0; SHA1_Init(sha_ctx); while(isRunning && (len = fread(gblBuf,1, 512, fd)) > 0) { SHA1_Update(sha_ctx, gblBuf, len); if (thread && ++runningCheckCount > (10 * 1024)) { /* check all 50MB if thread is running */ isRunning = thread->isRunning(); runningCheckCount = 0; } } /* Thread has ended */ if (isRunning == false) { delete sha_ctx; fclose(fd); return false; } /* reading failed for some reason */ if (ferror(fd)) { delete sha_ctx; fclose(fd); return false; } SHA1_Final(&sha_buf[0], sha_ctx); hash = Sha1CheckSum(sha_buf); delete sha_ctx; fclose(fd); return true; } /* Function to hash, and get details of a file */ Sha1CheckSum RsDirUtil::sha1sum(const unsigned char *data, uint32_t size) { SHA_CTX sha_ctx ; if(SHA_DIGEST_LENGTH != 20) throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 20") ; SHA1_Init(&sha_ctx); while(size > 512) { SHA1_Update(&sha_ctx, data, 512); data = &data[512] ; size -= 512 ; } SHA1_Update(&sha_ctx, data, size); unsigned char sha_buf[SHA_DIGEST_LENGTH]; SHA1_Final(&sha_buf[0], &sha_ctx); return Sha1CheckSum(sha_buf) ; } bool RsDirUtil::renameFile(const std::string& from, const std::string& to) { int loops = 0; #ifdef WINDOWS_SYS std::wstring f; librs::util::ConvertUtf8ToUtf16(from, f); std::wstring t; librs::util::ConvertUtf8ToUtf16(to, t); while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) #else std::string f(from),t(to) ; while (rename(from.c_str(), to.c_str()) < 0) #endif { #ifdef WIN32 if (GetLastError() != ERROR_ACCESS_DENIED) #else if (errno != EACCES) #endif /* set errno? */ return false ; #ifdef WIN32 Sleep(200); /* 200 milliseconds */ #else usleep(100000); /* 100000 microseconds */ #endif if (loops >= 30) return false ; loops++; } return true ; } #ifdef UNUSED_CODE // not used bool RsDirUtil::createBackup (const std::string& sFilename, unsigned int nCount) { #ifdef WINDOWS_SYS if (GetFileAttributesA (sFilename.c_str ()) == -1) { // file doesn't exist return true; } // search last backup int nLast; for (nLast = nCount; nLast >= 1; nLast--) { std::ostringstream sStream; // please do not use std::ostringstream sStream << sFilename << nLast << ".bak"; if (GetFileAttributesA (sStream.str ().c_str ()) != -1) { break; } } // delete max backup if (nLast == nCount) { std::ostringstream sStream; // please do not use std::ostringstream sStream << sFilename << nCount << ".bak"; if (DeleteFileA (sStream.str ().c_str ()) == FALSE) { getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File delete error", "Error while deleting file " + sStream.str ()); return false; } nLast--; } // rename backups for (int nIndex = nLast; nIndex >= 1; nIndex--) { std::ostringstream sStream; // please do not use std::ostringstream sStream << sFilename << nIndex << ".bak"; std::ostringstream sStream1; // please do not use std::ostringstream sStream1 << sFilename << nIndex + 1 << ".bak"; if (renameFile (sStream.str (), sStream1.str ()) == false) { getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sStream.str () + " to " + sStream1.str ()); return false; } } // copy backup std::ostringstream sStream; // please do not use std::ostringstream sStream << sFilename << 1 << ".bak"; if (CopyFileA (sFilename.c_str (), sStream.str ().c_str (), FALSE) == FALSE) { getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sFilename + " to " + sStream.str ()); return false; } #else /* remove unused parameter warnings */ (void) sFilename; (void) nCount; #endif return true; } #endif FILE *RsDirUtil::rs_fopen(const char* filename, const char* mode) { #ifdef WINDOWS_SYS std::wstring wfilename; librs::util::ConvertUtf8ToUtf16(filename, wfilename); std::wstring wmode; librs::util::ConvertUtf8ToUtf16(mode, wmode); return _wfopen(wfilename.c_str(), wmode.c_str()); #else return fopen64(filename, mode); #endif } std::string RsDirUtil::convertPathToUnix(std::string path) { for (unsigned int i = 0; i < path.length(); i++) { if (path[i] == '\\') path[i] = '/'; } return path; } std::string RsDirUtil::makePath(const std::string &path1, const std::string &path2) { std::string path = path1; if (path.empty() == false && *path.rbegin() != '/') { path += "/"; } path += path2; return path; } int RsDirUtil::createLockFile(const std::string& lock_file_path, rs_lock_handle_t &lock_handle) { /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS // Suspended. The user should make sure he's not already using the file descriptor. // if(lock_handle != -1) // close(lock_handle); // open the file in write mode, create it if necessary, truncate it (it should be empty) lock_handle = open(lock_file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(lock_handle == -1) { std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::flush; perror(NULL); return 2; } // see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents struct flock lockDetails; lockDetails.l_type = F_WRLCK; lockDetails.l_whence = SEEK_SET; lockDetails.l_start = 0; lockDetails.l_len = 0; if(fcntl(lock_handle, F_SETLK, &lockDetails) == -1) { int fcntlErr = errno; std::cerr << "Could not request lock on file " << lock_file_path.c_str() << std::flush; perror(NULL); // there's no lock so let's release the file handle immediately close(lock_handle); lock_handle = -1; if(fcntlErr == EACCES || fcntlErr == EAGAIN) return 1; else return 2; } return 0; #else // Suspended. The user should make sure he's not already using the file descriptor. // // if (lock_handle) { // CloseHandle(lock_handle); // } std::wstring wlockFile; librs::util::ConvertUtf8ToUtf16(lock_file_path, wlockFile); // open the file in write mode, create it if necessary lock_handle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (lock_handle == INVALID_HANDLE_VALUE) { DWORD lasterror = GetLastError(); std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::endl; std::cerr << "Last error: " << lasterror << std::endl << std::flush; perror(NULL); if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED) return 1; return 2; } return 0; #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ } void RsDirUtil::releaseLockFile(rs_lock_handle_t lockHandle) { /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS if(lockHandle != -1) { close(lockHandle); lockHandle = -1; } #else if(lockHandle) { CloseHandle(lockHandle); lockHandle = 0; } #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ } RsStackFileLock::RsStackFileLock(const std::string& file_path) { while(RsDirUtil::createLockFile(file_path,_file_handle)) { std::cerr << "Cannot acquire file lock " << file_path << ", waiting 1 sec." << std::endl; #ifdef WINDOWS_SYS Sleep(1000) ; #else sleep(1) ; #endif } #ifdef RSDIR_DEBUG std::cerr << "Acquired file handle " << _file_handle << ", lock file:" << file_path << std::endl; #endif } RsStackFileLock::~RsStackFileLock() { RsDirUtil::releaseLockFile(_file_handle) ; #ifdef RSDIR_DEBUG std::cerr << "Released file lock with handle " << _file_handle << std::endl; #endif } #if 0 // NOT ENABLED YET! /************************* WIDE STRING ***************************/ /************************* WIDE STRING ***************************/ /************************* WIDE STRING ***************************/ std::wstring RsDirUtil::getWideTopDir(std::wstring dir) { std::wstring top; /* find the subdir: [/][dir1.../][/] */ int i,j; int len = dir.length(); for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); for(i = j; (i > 0) && (dir[i] != '/'); i--); if (dir[i] == '/') i++; for(; i <= j; i++) { top += dir[i]; } return top; } std::wstring RsDirUtil::removeWideTopDir(std::wstring dir) { std::wstring rest; /* remove the subdir: [/][dir1.../][/] */ int i,j; int len = dir.length(); for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); for(i = j; (i >= 0) && (dir[i] != '/'); i--); /* remove any more slashes */ for(; (i >= 0) && (dir[i] == '/'); i--); for(j = 0; j <= i; j++) { rest += dir[j]; } return rest; } std::wstring RsDirUtil::getWideRootDir(std::wstring dir) { std::wstring root; /* find the subdir: [/]root[/...] */ int i,j; int len = dir.length(); for(i = 0; (i < len) && (dir[i] == '/'); i++); for(j = i; (j < len) && (dir[j] != '/'); j++); if (i == j) return root; /* empty */ for(; i < j; i++) { root += dir[i]; } return root; } std::wstring RsDirUtil::removeWideRootDir(std::wstring path) { unsigned int i, j; unsigned int len = path.length(); std::wstring output; /* chew leading '/'s */ for(i = 0; (i < len) && (path[i] == '/'); i++); if (i == len) return output; /* empty string */ for(j = i; (j < len) && (path[j] != '/'); j++); /* run to next '/' */ for(; (j < len) && (path[j] == '/'); j++); /* chew leading '/'s */ for(; j < len; j++) { output += path[j]; } return output; } std::wstring RsDirUtil::removeWideRootDirs(std::wstring path, std::wstring root) { /* too tired */ std::wstring notroot; unsigned int i = 0, j = 0; /* catch empty data */ if ((root.length() < 1) || (path.length() < 1)) return notroot; if ((path[0] == '/') && (root[0] != '/')) { i++; } for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++); /* should have consumed root. */ if (j == root.length()) { //std::cerr << "matched root!" << std::endl; } else { //std::cerr << "failed i: " << i << ", j: " << j << std::endl; //std::cerr << "root: " << root << " path: " << path << std::endl; return notroot; } if (path[i] == '/') { i++; } for(; i < path.length(); i++) { notroot += path[i]; } //std::cerr << "Found NotRoot: " << notroot << std::endl; return notroot; } int RsDirUtil::breakupWideDirList(std::wstring path, std::list &subdirs) { int start = 0; unsigned int i; for(i = 0; i < path.length(); i++) { if (path[i] == '/') { if (i - start > 0) { subdirs.push_back(path.substr(start, i-start)); } start = i+1; } } // get the final one. if (i - start > 0) { subdirs.push_back(path.substr(start, i-start)); } return 1; } bool RsDirUtil::checkWideDirectory(std::wstring dir) { struct stat buf; /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::string d(dir.begin(), dir.end()); int val = stat(d.c_str(), &buf); /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ if (val == -1) { #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkDirectory() "; std::cerr << d << " doesn't exist" << std::endl; #endif return false; } else if (!S_ISDIR(buf.st_mode)) { // Some other type - error. #ifdef RSDIR_DEBUG std::cerr << "RsDirUtil::checkDirectory() "; std::cerr << d << " is not Directory" << std::endl; #endif return false; } return true; } bool RsDirUtil::checkWideCreateDirectory(std::wstring dir) { struct stat buf; /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::string d(dir.begin(), dir.end()); int val = stat(d.c_str(), &buf); /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ if (val == -1) { // directory don't exist. create. /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ #ifndef WINDOWS_SYS // UNIX /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ if (-1 == mkdir(d.c_str(), 0777)) /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ #else // WIN if (-1 == mkdir(d.c_str())) #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ { #ifdef RSDIR_DEBUG std::cerr << "check_create_directory() Fatal Error --"; std::cerr < bool RsDirUtil::cleanupWideDirectory(std::wstring cleandir, std::list keepFiles) { /* check for the dir existance */ /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::string cd(cleandir.begin(), cleandir.end()); DIR *dir = opendir(cd.c_str()); /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::list::const_iterator it; if (!dir) { return false; } struct dirent *dent; struct stat buf; while(NULL != (dent = readdir(dir))) { /* check entry type */ /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::string fname(dent -> d_name); std::wstring wfname(fname.begin(), fname.end()); std::string fullname = cd + "/" + fname; if (-1 != stat(fullname.c_str(), &buf)) /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ { /* only worry about files */ if (S_ISREG(buf.st_mode)) { /* check if we should keep it */ if (keepFiles.end() == (it = std::find(keepFiles.begin(), keepFiles.end(), wfname))) { /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ /* can remove */ remove(fullname.c_str()); /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ } } } } /* close directory */ closedir(dir); return true; } /* slightly nicer helper function */ bool RsDirUtil::hashWideFile(std::wstring filepath, std::wstring &name, std::string &hash, uint64_t &size) { if (getWideFileHash(filepath, hash, size)) { /* extract file name */ name = RsDirUtil::getWideTopDir(filepath); return true; } return false; } #include #include #include /* Function to hash, and get details of a file */ bool RsDirUtil::getWideFileHash(std::wstring filepath, std::string &hash, uint64_t &size) { FILE *fd; int len; SHA_CTX *sha_ctx = new SHA_CTX; unsigned char sha_buf[SHA_DIGEST_LENGTH]; unsigned char gblBuf[512]; /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ std::string fp(filepath.begin(), filepath.end()); if (NULL == (fd = fopen64(fp.c_str(), "rb"))) return false; /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ /* determine size */ fseeko64(fd, 0, SEEK_END); size = ftello64(fd); fseeko64(fd, 0, SEEK_SET); SHA1_Init(sha_ctx); while((len = fread(gblBuf,1, 512, fd)) > 0) { SHA1_Update(sha_ctx, gblBuf, len); } /* reading failed for some reason */ if (ferror(fd)) { delete sha_ctx; fclose(fd); return false; } SHA1_Final(&sha_buf[0], sha_ctx); std::ostringstream tmpout; // please do not use std::ostringstream for(int i = 0; i < SHA_DIGEST_LENGTH; i++) { tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); } hash = tmpout.str(); delete sha_ctx; fclose(fd); return true; } bool RsDirUtil::renameWideFile(const std::wstring& from, const std::wstring& to) { int loops = 0; #if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) #ifdef WIN_CROSS_UBUNTU std::wstring f,t ; for(int i=0;i= 30) return false ; loops++; } return true ; } #endif // WIDE STUFF NOT ENABLED YET!