bool PathHelper::isSymlink(QString path) { QFileInfo fileInfo(path); return fileInfo.isSymLink() #ifdef Q_OS_MAC && !getSymlinkTarget(fileInfo.absoluteFilePath()).isEmpty() #endif ; }
QString PathHelper::getSymlinkTarget(QString symlink, int buffSize) { if (buffSize > INT_MAX) return ""; char buff[buffSize]; ssize_t len = readlink(symlink.toStdString().c_str(), buff, sizeof(buff)-1); if (len != -1) { buff[len] = '\0'; return QString(buff); } else { if (errno == EFAULT) return getSymlinkTarget(symlink, buffSize * 10); else return ""; } }
bool Global::copyDir(const QString src, const QString dst, const bool hidden) { if (!QDir().exists(src)) return false; if (QDir().exists(dst)) rmDir(dst); if (!QDir().mkpath(dst)) return false; // Keep same folder permission preserveDirectoryPermission(src, dst); // Error isn't critical bool success = true; // Copy content of dir QStringList list; if (hidden) list = QDir(src).entryList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden, QDir::Name); else list = QDir(src).entryList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System, QDir::Name); foreach (const QString file, list) { QFileInfo info(src + "/" + file); if (info.isDir()) { if (!copyDir(src + "/" + file, dst + "/" + file, hidden)) success = false; } else if (info.isSymLink()) { QString symlinkTarget = getSymlinkTarget(src + "/" + file); if (symlinkTarget.isEmpty() || !QFile::link(symlinkTarget, dst + "/" + file)) success = false; } else { if (!QFile::copy(src + "/" + file, dst + "/" + file)) success = false; } }
bool PathHelper::copyWholeDirectory_recursive(QString sourceDirPath, QString destDirPath, SymlinkHandlingModeEnum symlinkHandlingMode, bool isFailWhenContentCopyFails) { #ifdef ENABLE_PATH_MANAGER_LOGGING DLog(QString("copyWholeDirectory_recursive - sourceDir:%1 | destDir:%2").arg(sourceDirPath).arg(destDirPath)); #endif QDir sourceDir(sourceDirPath); if(!sourceDir.exists()) { WLogS << " ! The specified source path does not exists: " << sourceDirPath; return false; } QDir destDir(destDirPath); if(!destDir.exists()) { if(!PathHelper::ensureDirectoryCreated(destDirPath)) { WLogS << " ! The specified destination path cannot be created: " << destDirPath; return false; } } if(!PathHelper::copyOnlyFilesOfDirectory(sourceDirPath, destDirPath, symlinkHandlingMode, true)) { if(isFailWhenContentCopyFails) { return false; } } // and get sub-directories as well QStringList dirs = sourceDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden/* | QDir::NoSymLinks*/); // !!! No symlink folders allowed for(int i = 0; i < dirs.count(); i++) { QString srcDirFullPath = PathHelper::combineAndCleanPathes(sourceDirPath, dirs[i]); QString destDirFullPath = PathHelper::combineAndCleanPathes(destDirPath, dirs[i]); QFileInfo srcFInfo(srcDirFullPath); if(PathHelper::isSymlink(srcDirFullPath)) { DLog(QString(" - Symlink %1 found for target %2").arg(srcDirFullPath).arg(srcFInfo.symLinkTarget())); if(symlinkHandlingMode == SHM_UseAsFile) { // use as file #ifdef Q_OS_WIN // copy it as a normal file if(!QFile::copy(srcDirFullPath, destDirFullPath)) { WLog(QString(" ! Cannot copy the symlink-file from [%1] to [%2]").arg(srcDirFullPath).arg(destDirFullPath)); if(QFile::exists(destDirFullPath)) { WLog("Dest file is already exists: ") << destDirFullPath; } return false; } #endif #ifdef Q_OS_MAC // if(QFileInfo(srcDirFullPath).symLinkTarget().isEmpty()) { // WLog("Symlink found, but target is empty: ") << srcDirFullPath; // continue; // } ///// //QDir sourceDir(sourceDirPath); QString symlinkPath = getSymlinkTarget(QFileInfo(srcDirFullPath).absoluteFilePath()); //sourceDir.relativeFilePath(srcFInfo.symLinkTarget()); DLog(QString("Symlink created at path %1 with target %2").arg(destDirFullPath).arg(symlinkPath)); ///// if( !QFile::link(symlinkPath, destDirFullPath) ) { WLog("Symlink cannot be created!"); if(isFailWhenContentCopyFails) { WLog(" - Fail"); return false; } } #endif } else if(symlinkHandlingMode == SHM_UseAsTarget) { WLog("!!!!!!!! Not yet implemented! (will be ignored)"); } else { DLog("Symlink handling mode: ignore."); } } else { if(!PathHelper::copyWholeDirectory_recursive(srcDirFullPath, destDirFullPath, symlinkHandlingMode, isFailWhenContentCopyFails)) { return false; } } } return true; }
bool PathHelper::copyOnlyFilesOfDirectory(QString sourceDirPath, QString destDirPath, SymlinkHandlingModeEnum symlinkHandlingMode, bool isIgnoreDirectorySymlinks) { // FLAG_FOR_REVIEW_WITH_HINT("Should copy symlink / shortcut files as well?? Temporarily removed / turned off."); QDir sourceDir(sourceDirPath); // // get everything, but handle only files and symlinks (pointing for other targets, like Drives) // QDir::Filters entryListFilters = QDir::NoDotAndDotDot | QDir::Files | QDir::Drives | QDir::Hidden | QDir::System; if(!isIgnoreDirectorySymlinks) { entryListFilters |= QDir::Dirs; } QStringList files = sourceDir.entryList(entryListFilters); for(int i = 0; i < files.count(); i++) { QString srcFullPath = PathHelper::combineAndCleanPathes(sourceDirPath, files[i]); QString destFullPath = PathHelper::combineAndCleanPathes(destDirPath, files[i]); // SYMLINKS // QFile cannot copy the file, when destName exists if(PathHelper::isSymlink(srcFullPath)) { // Symlink! DLogS << QString("Symlink found (%1) - target: (%2). Symlink-handling-mode: (%3) ").arg(srcFullPath).arg(QFileInfo(srcFullPath).symLinkTarget()).arg(symlinkHandlingMode); // WLog(QString("The file [%1] is a symlink to file [%2]").arg(srcName).arg( QFileInfo(srcName).symLinkTarget() )); if(symlinkHandlingMode == SHM_UseAsFile) { DLog(" - Symlink will be used as file, will be saved to path: ") << destFullPath; #ifdef Q_OS_WIN // copy it as a normal file if(!QFile::copy(srcFullPath, destFullPath)) { WLog(QString(" ! Cannot copy the symlink-file from [%1] to [%2]").arg(srcFullPath).arg(destFullPath)); return false; } #endif #ifdef Q_OS_MAC // if(QFileInfo(srcFullPath).symLinkTarget().isEmpty()) { // WLog("Symlink found, but target is empty: ") << srcFullPath; // continue; // } // QDir sourceDir(sourceDirPath); QString symlinkPath = getSymlinkTarget(QFileInfo(srcFullPath).absoluteFilePath()); //sourceDir.relativeFilePath(QFileInfo(srcFullPath).symLinkTarget()); DLog(QString("Symlink created at path %1 with target %2").arg(destFullPath).arg(symlinkPath)); if( !QFile::link(symlinkPath, destFullPath) ) { WLog("Symlink cannot be created!"); return false; } #endif } else if(symlinkHandlingMode == SHM_UseAsTarget) { WLog(" - Symlink handling is set to 'UseAsTarget' - not yet implemented."); // QString linkTargetPath = QFileInfo(srcFullPath).symLinkTarget(); // QFileInfo linkTargetFInfo(linkTargetPath); // if(linkTargetFInfo.isDir()) // { // // symlink target is a dir! // DLog(" - Symlink target is a directory!"); // QDir linkTargetDir(linkTargetPath); // if(!linkTargetDir.exists()) { // WLog(" - Symlink target directory does NOT exists: ") << linkTargetPath; // } // QString destTargetDirPath = PathHelper::combineAndCleanPathes(destDirPath, linkTargetDir.dirName()); // DLog(" - Symlink dest target dir path: ") << destTargetDirPath; // if(!PathHelper::copyWholeDirectory_recursive(srcFullPath, destTargetDirPath, symlinkHandlingMode, isFailWhenContentCopyFails)) { // return false; // } // } // else { // DLog("Symlink target is a file: ") << linkTargetPath; // QString destTargetFilePath = PathHelper::combineAndCleanPathes(destDirPath, linkTargetFInfo.fileName()); // DLog(" - Dest target File path: ") << destTargetFilePath; // QFile::copy(linkTargetPath, destTargetFilePath); // } } else { DLog(" - Symlink ignored"); } } else { // NOT symlink - handle only files if(QFileInfo(srcFullPath).isFile()) { if(!QFile::copy(srcFullPath, destFullPath)) { WLog(QString(" ! Cannot copy file from [%1] to [%2]").arg(srcFullPath).arg(destFullPath)); return false; } else { #ifdef ENABLE_PATH_MANAGER_LOGGING DLog(QString("Copy succeeded - file from [%1] to [%2]").arg(srcFullPath).arg(destFullPath)); #endif } } else { WLog("Not a symlink and not a file (will be ignored): ") << srcFullPath; } } } files.clear(); return true; }
bool PathHelper::copyWholeDirectory(QString sourceDirPath, QString destDirPath, bool isCopyOnlyContentOfSource, SymlinkHandlingModeEnum symlinkHandlingMode, bool isFailWhenContentCopyFails) { if(!isCopyOnlyContentOfSource) { // copy the folder as well QDir sourceDir(sourceDirPath); QString newDestDirPath = PathHelper::combineAndCleanPathes(destDirPath, sourceDir.dirName()); return PathHelper::copyWholeDirectory_recursive(sourceDirPath, newDestDirPath, symlinkHandlingMode, isFailWhenContentCopyFails); } // copy only the sub dirs QDir sourceDir(sourceDirPath); if(!sourceDir.exists()) { WLogS << " ! The specified source path does not exists: " << sourceDirPath; return false; } QStringList subDirs = sourceDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden/*| QDir::NoSymLinks*/); if(subDirs.isEmpty()) { #ifdef ENABLE_PATH_MANAGER_LOGGING DLogS << "The specified source directory is empty."; #endif return true; } for(int i = 0; i < subDirs.count(); i++) { QString srcDirFullPath = PathHelper::combineAndCleanPathes(sourceDirPath, subDirs[i]); QString destDirFullPath = PathHelper::combineAndCleanPathes(destDirPath, subDirs[i]); QFileInfo srcFInfo(srcDirFullPath); if(PathHelper::isSymlink(srcDirFullPath)) { DLog(QString(" - (Dir)Symlink %1 found for target %2").arg(srcDirFullPath).arg(srcFInfo.symLinkTarget())); if(symlinkHandlingMode == SHM_UseAsFile) { // use as file #ifdef Q_OS_WIN // copy it as a normal file if(!QFile::copy(srcDirFullPath, destDirFullPath)) { WLog(QString(" ! Cannot copy the symlink-file from [%1] to [%2]").arg(srcDirFullPath).arg(destDirFullPath)); return false; } #endif #ifdef Q_OS_MAC // if(QFileInfo(srcDirFullPath).symLinkTarget().isEmpty()) { // WLog("Symlink found, but target is empty: ") << srcDirFullPath; // continue; // } ///// //QDir sourceDir(sourceDirPath); QString symlinkPath = getSymlinkTarget(QFileInfo(srcDirFullPath).absoluteFilePath()); //sourceDir.relativeFilePath(srcFInfo.symLinkTarget()); DLog(QString("Symlink created at path %1 with target %2").arg(destDirFullPath).arg(symlinkPath)); ///// if( !QFile::link(symlinkPath, destDirFullPath) ) { WLog("Symlink cannot be created!"); if(isFailWhenContentCopyFails) { WLog(" - Fail"); return false; } } #endif } else if(symlinkHandlingMode == SHM_UseAsTarget) { WLog("!!!!!!!! Not yet implemented! (will be ignored)"); } else { DLog("Symlink handling mode: ignore."); } } else { QString destName = PathHelper::combineAndCleanPathes(destDirPath, subDirs[i]); if(!PathHelper::copyWholeDirectory_recursive(srcDirFullPath, destName, symlinkHandlingMode, isFailWhenContentCopyFails)) { return false; } } } // also copy the files from sourceDirPath if(!PathHelper::copyOnlyFilesOfDirectory(sourceDirPath, destDirPath, symlinkHandlingMode, true)) { if(isFailWhenContentCopyFails) { return false; } } return true; }