mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-24 22:15:57 +03:00
Support Windows .lnk files with VFS Cf API.
Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
parent
d5c4c7e665
commit
f70d1c1079
27 changed files with 311 additions and 103 deletions
|
@ -52,8 +52,11 @@ QString FileSystem::longWinPath(const QString &inpath)
|
|||
|
||||
void FileSystem::setFileHidden(const QString &filename, bool hidden)
|
||||
{
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
QString fName = longWinPath(filename);
|
||||
const QString fName = longWinPath(filename);
|
||||
DWORD dwAttrs = 0;
|
||||
|
||||
dwAttrs = GetFileAttributesW((wchar_t *)fName.utf16());
|
||||
|
@ -71,6 +74,24 @@ void FileSystem::setFileHidden(const QString &filename, bool hidden)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool FileSystem::isFileHidden(const QString &filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (isLnkFile(filename)) {
|
||||
const QString fName = longWinPath(filename);
|
||||
DWORD dwAttrs = 0;
|
||||
|
||||
dwAttrs = GetFileAttributesW((wchar_t *)fName.utf16());
|
||||
|
||||
if (dwAttrs == INVALID_FILE_ATTRIBUTES) {
|
||||
return false;
|
||||
}
|
||||
return dwAttrs & FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
#endif
|
||||
return QFileInfo(filename).isHidden();
|
||||
}
|
||||
|
||||
static QFile::Permissions getDefaultWritePermissions()
|
||||
{
|
||||
QFile::Permissions result = QFile::WriteUser;
|
||||
|
@ -89,11 +110,27 @@ static QFile::Permissions getDefaultWritePermissions()
|
|||
|
||||
void FileSystem::setFileReadOnly(const QString &filename, bool readonly)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
if (!fileExists(filename)) {
|
||||
return;
|
||||
}
|
||||
const auto permissions = filePermissionsWin(filename);
|
||||
|
||||
std::filesystem::perms allWritePermissions = std::filesystem::perms::_All_write;
|
||||
static std::filesystem::perms defaultWritePermissions = std::filesystem::perms::others_write;
|
||||
|
||||
std::filesystem::permissions(filename.toStdString(), allWritePermissions, std::filesystem::perm_options::remove);
|
||||
|
||||
if (!readonly) {
|
||||
std::filesystem::permissions(filename.toStdString(), defaultWritePermissions, std::filesystem::perm_options::add);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
QFile file(filename);
|
||||
QFile::Permissions permissions = file.permissions();
|
||||
|
||||
QFile::Permissions allWritePermissions =
|
||||
QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther | QFile::WriteOwner;
|
||||
QFile::Permissions allWritePermissions = QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther | QFile::WriteOwner;
|
||||
static QFile::Permissions defaultWritePermissions = getDefaultWritePermissions();
|
||||
|
||||
permissions &= ~allWritePermissions;
|
||||
|
@ -116,6 +153,18 @@ void FileSystem::setFolderMinimumPermissions(const QString &filename)
|
|||
|
||||
bool FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
const auto permissions = filePermissionsWin(filename);
|
||||
|
||||
if (!readonly && static_cast<bool>((permissions & std::filesystem::perms::owner_write))) {
|
||||
return false; // already writable enough
|
||||
}
|
||||
|
||||
setFileReadOnly(filename, readonly);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
QFile file(filename);
|
||||
QFile::Permissions permissions = file.permissions();
|
||||
|
||||
|
@ -193,7 +242,7 @@ bool FileSystem::uncheckedRenameReplace(const QString &originFileName,
|
|||
|
||||
#else //Q_OS_WIN
|
||||
// You can not overwrite a read-only file on windows.
|
||||
if (!QFileInfo(destinationFileName).isWritable()) {
|
||||
if (!isWritable(destinationFileName)) {
|
||||
setFileReadOnly(destinationFileName, false);
|
||||
}
|
||||
|
||||
|
@ -289,11 +338,24 @@ bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qi
|
|||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
std::filesystem::perms FileSystem::filePermissionsWin(const QString &filename)
|
||||
{
|
||||
return std::filesystem::status(filename.toStdString()).permissions();
|
||||
}
|
||||
|
||||
void FileSystem::setFilePermissionsWin(const QString &filename, const std::filesystem::perms &perms)
|
||||
{
|
||||
if (!fileExists(filename)) {
|
||||
return;
|
||||
}
|
||||
std::filesystem::permissions(filename.toStdString(), perms);
|
||||
}
|
||||
|
||||
static bool fileExistsWin(const QString &filename)
|
||||
{
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
HANDLE hFind = nullptr;
|
||||
QString fName = FileSystem::longWinPath(filename);
|
||||
const QString fName = FileSystem::longWinPath(filename);
|
||||
|
||||
hFind = FindFirstFileW((wchar_t *)fName.utf16(), &FindFileData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
|
@ -302,6 +364,25 @@ static bool fileExistsWin(const QString &filename)
|
|||
FindClose(hFind);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isDirWin(const QString &filename)
|
||||
{
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
HANDLE hFind = nullptr;
|
||||
const QString fName = FileSystem::longWinPath(filename);
|
||||
|
||||
hFind = FindFirstFileW((wchar_t *)fName.utf16(), &FindFileData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
FindClose(hFind);
|
||||
return FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
static bool isFileWin(const QString &filename)
|
||||
{
|
||||
return !isDirWin(filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool FileSystem::fileExists(const QString &filename, const QFileInfo &fileInfo)
|
||||
|
@ -323,6 +404,100 @@ bool FileSystem::fileExists(const QString &filename, const QFileInfo &fileInfo)
|
|||
return re;
|
||||
}
|
||||
|
||||
bool FileSystem::isDir(const QString &filename, const QFileInfo &fileInfo)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
// Use a native check.
|
||||
return isDirWin(filename);
|
||||
}
|
||||
#endif
|
||||
bool re = fileInfo.isDir();
|
||||
// if the filename is different from the filename in fileInfo, the fileInfo is
|
||||
// not valid. There needs to be one initialised here. Otherwise the incoming
|
||||
// fileInfo is re-used.
|
||||
if (fileInfo.filePath() != filename) {
|
||||
QFileInfo myFI(filename);
|
||||
re = myFI.isDir();
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
bool FileSystem::isFile(const QString &filename, const QFileInfo &fileInfo)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
// Use a native check.
|
||||
return isFileWin(filename);
|
||||
}
|
||||
#endif
|
||||
bool re = fileInfo.isDir();
|
||||
// if the filename is different from the filename in fileInfo, the fileInfo is
|
||||
// not valid. There needs to be one initialised here. Otherwise the incoming
|
||||
// fileInfo is re-used.
|
||||
if (fileInfo.filePath() != filename) {
|
||||
QFileInfo myFI(filename);
|
||||
re = myFI.isFile();
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
bool FileSystem::isWritable(const QString &filename, const QFileInfo &fileInfo)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
const auto permissions = filePermissionsWin(filename);
|
||||
return static_cast<bool>((permissions & std::filesystem::perms::owner_write));
|
||||
}
|
||||
#endif
|
||||
bool re = fileInfo.isWritable();
|
||||
// if the filename is different from the filename in fileInfo, the fileInfo is
|
||||
// not valid. There needs to be one initialised here. Otherwise the incoming
|
||||
// fileInfo is re-used.
|
||||
if (fileInfo.filePath() != filename) {
|
||||
QFileInfo myFI(filename);
|
||||
re = myFI.isWritable();
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
bool FileSystem::isReadable(const QString &filename, const QFileInfo &fileInfo)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
const auto permissions = filePermissionsWin(filename);
|
||||
return static_cast<bool>((permissions & std::filesystem::perms::owner_read));
|
||||
}
|
||||
#endif
|
||||
bool re = fileInfo.isReadable();
|
||||
// if the filename is different from the filename in fileInfo, the fileInfo is
|
||||
// not valid. There needs to be one initialised here. Otherwise the incoming
|
||||
// fileInfo is re-used.
|
||||
if (fileInfo.filePath() != filename) {
|
||||
QFileInfo myFI(filename);
|
||||
re = myFI.isReadable();
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
bool FileSystem::isSymLink(const QString &filename, const QFileInfo &fileInfo)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (isLnkFile(filename)) {
|
||||
return isJunction(filename);
|
||||
}
|
||||
#endif
|
||||
bool re = fileInfo.isSymLink();
|
||||
// if the filename is different from the filename in fileInfo, the fileInfo is
|
||||
// not valid. There needs to be one initialised here. Otherwise the incoming
|
||||
// fileInfo is re-used.
|
||||
if (fileInfo.filePath() != filename) {
|
||||
QFileInfo myFI(filename);
|
||||
re = myFI.isSymLink();
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString FileSystem::fileSystemForPath(const QString &path)
|
||||
{
|
||||
|
@ -351,7 +526,7 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)
|
|||
#ifdef Q_OS_WIN
|
||||
// You cannot delete a read-only file on windows, but we want to
|
||||
// allow that.
|
||||
if (!QFileInfo(fileName).isWritable()) {
|
||||
if (!isWritable(fileName)) {
|
||||
setFileReadOnly(fileName, false);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <ctime>
|
||||
|
||||
#if !defined(Q_OS_MACOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
|
||||
#include <filesystem>
|
||||
#endif
|
||||
|
||||
class QFile;
|
||||
|
||||
namespace OCC {
|
||||
|
@ -53,6 +57,8 @@ namespace FileSystem {
|
|||
*/
|
||||
void OCSYNC_EXPORT setFileHidden(const QString &filename, bool hidden);
|
||||
|
||||
bool OCSYNC_EXPORT isFileHidden(const QString &filename);
|
||||
|
||||
/**
|
||||
* @brief Marks the file as read-only.
|
||||
*
|
||||
|
@ -89,6 +95,34 @@ namespace FileSystem {
|
|||
*/
|
||||
bool OCSYNC_EXPORT fileExists(const QString &filename, const QFileInfo & = QFileInfo());
|
||||
|
||||
/**
|
||||
* @brief Checks whether it is a dir.
|
||||
*
|
||||
* Use this over QFileInfo::isDir() and QFile::isDir() to avoid bugs with lnk
|
||||
* files, see above.
|
||||
*/
|
||||
bool OCSYNC_EXPORT isDir(const QString &filename, const QFileInfo& = QFileInfo());
|
||||
|
||||
/**
|
||||
* @brief Checks whether it is a file.
|
||||
*
|
||||
* Use this over QFileInfo::isDir() and QFile::isDir() to avoid bugs with lnk
|
||||
* files, see above.
|
||||
*/
|
||||
bool OCSYNC_EXPORT isFile(const QString &filename, const QFileInfo& fileInfo = QFileInfo());
|
||||
|
||||
/**
|
||||
* @brief Checks whether the file is writable.
|
||||
*
|
||||
* Use this over QFileInfo::isDir() and QFile::isDir() to avoid bugs with lnk
|
||||
* files, see above.
|
||||
*/
|
||||
bool OCSYNC_EXPORT isWritable(const QString &filename, const QFileInfo &fileInfo = QFileInfo());
|
||||
|
||||
bool OCSYNC_EXPORT isReadable(const QString &filename, const QFileInfo &fileInfo = QFileInfo());
|
||||
|
||||
bool OCSYNC_EXPORT isSymLink(const QString &filename, const QFileInfo &fileInfo = QFileInfo());
|
||||
|
||||
/**
|
||||
* @brief Rename the file \a originFileName to \a destinationFileName.
|
||||
*
|
||||
|
@ -146,6 +180,9 @@ namespace FileSystem {
|
|||
* the windows API functions work with the normal "unixoid" representation too.
|
||||
*/
|
||||
QString OCSYNC_EXPORT pathtoUNC(const QString &str);
|
||||
|
||||
std::filesystem::perms OCSYNC_EXPORT filePermissionsWin(const QString &filename);
|
||||
void OCSYNC_EXPORT setFilePermissionsWin(const QString &filename, const std::filesystem::perms &perms);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "csync_exclude.h"
|
||||
|
||||
#include "common/utility.h"
|
||||
#include "common/filesystembase.h"
|
||||
#include "../version.h"
|
||||
|
||||
#include <QString>
|
||||
|
@ -402,7 +403,7 @@ bool ExcludedFiles::isExcluded(
|
|||
while (path.size() > basePath.size()) {
|
||||
QFileInfo fi(path);
|
||||
if (fi.fileName() != QStringLiteral(".sync-exclude.lst")
|
||||
&& (fi.isHidden() || fi.fileName().startsWith(QLatin1Char('.')))) {
|
||||
&& (FileSystem::isFileHidden(path) || fi.fileName().startsWith(QLatin1Char('.')))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -411,9 +412,8 @@ bool ExcludedFiles::isExcluded(
|
|||
}
|
||||
}
|
||||
|
||||
QFileInfo fi(filePath);
|
||||
ItemType type = ItemTypeFile;
|
||||
if (fi.isDir()) {
|
||||
if (OCC::FileSystem::isDir(filePath)) {
|
||||
type = ItemTypeDirectory;
|
||||
}
|
||||
|
||||
|
@ -437,9 +437,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
|
|||
if (filetype == ItemTypeDirectory) {
|
||||
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
|
||||
const QString absolutePath = basePath + QStringLiteral(".sync-exclude.lst");
|
||||
QFileInfo excludeFileInfo(absolutePath);
|
||||
|
||||
if (excludeFileInfo.isReadable()) {
|
||||
if (FileSystem::isReadable(absolutePath)) {
|
||||
addExcludeFilePath(absolutePath);
|
||||
reloadExcludeFiles();
|
||||
} else {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "account.h"
|
||||
#include "folder.h"
|
||||
#include "common/filesystembase.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QDir>
|
||||
|
@ -180,12 +181,12 @@ QString CaseClashFilenameDialog::caseClashConflictFile(const QString &conflictFi
|
|||
while(it.hasNext()) {
|
||||
const auto filePath = it.next();
|
||||
qCDebug(lcCaseClashConflictFialog) << filePath;
|
||||
QFileInfo fileInfo(filePath);
|
||||
|
||||
if(fileInfo.isDir()) {
|
||||
if (FileSystem::isDir(filePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo fileInfo(filePath);
|
||||
const auto currentFileName = fileInfo.fileName();
|
||||
if (currentFileName.compare(conflictFileName, Qt::CaseInsensitive) == 0 &&
|
||||
currentFileName != conflictFileName) {
|
||||
|
|
|
@ -80,18 +80,19 @@ bool ConflictSolver::deleteLocalVersion()
|
|||
return false;
|
||||
}
|
||||
|
||||
QFileInfo info(_localVersionFilename);
|
||||
if (!info.exists()) {
|
||||
if (!FileSystem::fileExists(_localVersionFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto message = info.isDir() ? tr("Do you want to delete the directory <i>%1</i> and all its contents permanently?").arg(info.dir().dirName())
|
||||
QFileInfo info(_localVersionFilename);
|
||||
const auto message = FileSystem::isDir(_localVersionFilename)
|
||||
? tr("Do you want to delete the directory <i>%1</i> and all its contents permanently?").arg(info.dir().dirName())
|
||||
: tr("Do you want to delete the file <i>%1</i> permanently?").arg(info.fileName());
|
||||
const auto result = QMessageBox::question(_parentWidget, tr("Confirm deletion"), message, QMessageBox::Yes, QMessageBox::No);
|
||||
if (result != QMessageBox::Yes)
|
||||
return false;
|
||||
|
||||
if (info.isDir()) {
|
||||
if (FileSystem::isDir(_localVersionFilename)) {
|
||||
return FileSystem::removeRecursively(_localVersionFilename);
|
||||
} else {
|
||||
return QFile(_localVersionFilename).remove();
|
||||
|
@ -118,7 +119,7 @@ bool ConflictSolver::renameLocalVersion()
|
|||
const auto targetFilename = [=] {
|
||||
uint i = 1;
|
||||
auto result = renamePattern.arg(i);
|
||||
while (QFileInfo::exists(result)) {
|
||||
while (FileSystem::fileExists(result)) {
|
||||
Q_ASSERT(i > 0);
|
||||
i++;
|
||||
result = renamePattern.arg(i);
|
||||
|
@ -146,8 +147,7 @@ bool ConflictSolver::overwriteRemoteVersion()
|
|||
return false;
|
||||
}
|
||||
|
||||
QFileInfo info(_localVersionFilename);
|
||||
if (!info.exists()) {
|
||||
if (!FileSystem::fileExists(_localVersionFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,17 +175,17 @@ void Folder::checkLocalPath()
|
|||
|
||||
_canonicalLocalPath = Utility::trailingSlashPath(_canonicalLocalPath);
|
||||
|
||||
if (fi.isDir() && fi.isReadable()) {
|
||||
if (FileSystem::isDir(_definition.localPath) && FileSystem::isReadable(_definition.localPath)) {
|
||||
qCDebug(lcFolder) << "Checked local path ok";
|
||||
} else {
|
||||
// Check directory again
|
||||
if (!FileSystem::fileExists(_definition.localPath, fi)) {
|
||||
_syncResult.appendErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath));
|
||||
_syncResult.setStatus(SyncResult::SetupError);
|
||||
} else if (!fi.isDir()) {
|
||||
} else if (!FileSystem::isDir(_definition.localPath)) {
|
||||
_syncResult.appendErrorString(tr("%1 should be a folder but is not.").arg(_definition.localPath));
|
||||
_syncResult.setStatus(SyncResult::SetupError);
|
||||
} else if (!fi.isReadable()) {
|
||||
} else if (!FileSystem::isReadable(_definition.localPath)) {
|
||||
_syncResult.appendErrorString(tr("%1 is not readable.").arg(_definition.localPath));
|
||||
_syncResult.setStatus(SyncResult::SetupError);
|
||||
}
|
||||
|
@ -1471,8 +1471,9 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
|
|||
// Note: This assumes we're getting file watcher notifications
|
||||
// for folders only on creation and deletion - if we got a notification
|
||||
// on content change that would create spurious warnings.
|
||||
QFileInfo fi(_canonicalLocalPath + path);
|
||||
if (!fi.exists())
|
||||
const auto fullPath = _canonicalLocalPath + path;
|
||||
QFileInfo fi(fullPath);
|
||||
if (!FileSystem::fileExists(fullPath))
|
||||
return;
|
||||
|
||||
bool ok = false;
|
||||
|
@ -1482,7 +1483,7 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
|
|||
if (!blacklist.contains(path + "/"))
|
||||
return;
|
||||
|
||||
const auto message = fi.isDir()
|
||||
const auto message = FileSystem::isDir(fullPath)
|
||||
? tr("The folder %1 was created but was excluded from synchronization previously. "
|
||||
"Data inside it will not be synchronized.")
|
||||
.arg(fi.filePath())
|
||||
|
|
|
@ -1320,7 +1320,7 @@ QStringList FolderMan::findFileInLocalFolders(const QString &relPath, const Acco
|
|||
|
||||
QString path = folder->cleanPath() + '/';
|
||||
path += serverPath.mid(folder->remotePathTrailingSlash().length());
|
||||
if (QFile::exists(path)) {
|
||||
if (FileSystem::fileExists(path)) {
|
||||
re.append(path);
|
||||
}
|
||||
}
|
||||
|
@ -1754,19 +1754,19 @@ static QString checkPathValidityRecursive(const QString &path)
|
|||
#endif
|
||||
const QFileInfo selFile(path);
|
||||
|
||||
if (!selFile.exists()) {
|
||||
if (!FileSystem::fileExists(path)) {
|
||||
QString parentPath = selFile.dir().path();
|
||||
if (parentPath != path)
|
||||
return checkPathValidityRecursive(parentPath);
|
||||
return FolderMan::tr("The selected path does not exist!");
|
||||
}
|
||||
|
||||
if (!selFile.isDir()) {
|
||||
if (!FileSystem::isDir(path)) {
|
||||
return FolderMan::tr("The selected path is not a folder!");
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (!selFile.isWritable()) {
|
||||
if (!FileSystem::isWritable(path)) {
|
||||
// isWritable() doesn't cover all NTFS permissions
|
||||
// try creating and removing a test file, and make sure it is excluded from sync
|
||||
if (!Utility::canCreateFileInPath(path)) {
|
||||
|
@ -1774,7 +1774,7 @@ static QString checkPathValidityRecursive(const QString &path)
|
|||
}
|
||||
}
|
||||
#else
|
||||
if (!selFile.isWritable()) {
|
||||
if (!FileSystem::isWritable(path)) {
|
||||
return FolderMan::tr("You have no permission to write to the selected folder!");
|
||||
}
|
||||
#endif
|
||||
|
@ -1787,7 +1787,7 @@ static QString checkPathValidityRecursive(const QString &path)
|
|||
static QString canonicalPath(const QString &path)
|
||||
{
|
||||
QFileInfo selFile(path);
|
||||
if (!selFile.exists()) {
|
||||
if (!FileSystem::fileExists(path)) {
|
||||
const auto parentPath = selFile.dir().path();
|
||||
|
||||
// It's possible for the parentPath to match the path
|
||||
|
@ -1880,7 +1880,7 @@ QString FolderMan::findGoodPathForNewSyncFolder(const QString &basePath, const Q
|
|||
int attempt = 1;
|
||||
forever {
|
||||
const auto isGood = FolderMan::instance()->checkPathValidityForNewFolder(folder, serverUrl).second.isEmpty() &&
|
||||
(allowExisting == GoodPathStrategy::AllowOverrideExistingPath || !QFileInfo::exists(folder));
|
||||
(allowExisting == GoodPathStrategy::AllowOverrideExistingPath || !FileSystem::fileExists(folder));
|
||||
if (isGood) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ void FolderWatcher::appendSubPaths(QDir dir, QStringList& subPaths) {
|
|||
QString path = dir.path() + "/" + newSubPaths[i];
|
||||
QFileInfo fileInfo(path);
|
||||
subPaths.append(path);
|
||||
if (fileInfo.isDir()) {
|
||||
if (FileSystem::isDir(path)) {
|
||||
QDir dir(path);
|
||||
appendSubPaths(dir, subPaths);
|
||||
}
|
||||
|
@ -176,9 +176,8 @@ int FolderWatcher::lockChangeDebouncingTimout() const
|
|||
|
||||
void FolderWatcher::changeDetected(const QString &path)
|
||||
{
|
||||
QFileInfo fileInfo(path);
|
||||
QStringList paths(path);
|
||||
if (fileInfo.isDir()) {
|
||||
if (FileSystem::isDir(path)) {
|
||||
QDir dir(path);
|
||||
appendSubPaths(dir, paths);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
|
|||
// and new files in a folder, probably because of the folder's mtime
|
||||
// changing. We don't need them.
|
||||
const bool skip = curEntry->Action == FILE_ACTION_MODIFIED
|
||||
&& QFileInfo(longfile).isDir();
|
||||
&& FileSystem::isDir(longfile);
|
||||
|
||||
if (!skip) {
|
||||
emit changed(longfile);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "tray/sortedactivitylistmodel.h"
|
||||
#include "tray/syncstatussummary.h"
|
||||
#include "tray/unifiedsearchresultslistmodel.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#ifdef WITH_LIBCLOUDPROVIDERS
|
||||
#include "cloudproviders/cloudprovidermanager.h"
|
||||
|
@ -513,7 +514,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &
|
|||
Folder *f = FolderMan::instance()->folder(folder);
|
||||
if (f) {
|
||||
QString fullPath = f->path() + '/' + progress._lastCompletedItem._file;
|
||||
if (QFile(fullPath).exists()) {
|
||||
if (FileSystem::fileExists(fullPath)) {
|
||||
connect(action, &QAction::triggered, this, [this, fullPath] { this->slotOpenPath(fullPath); });
|
||||
} else {
|
||||
action->setEnabled(false);
|
||||
|
|
|
@ -1058,8 +1058,8 @@ void SocketApi::command_MOVE_ITEM(const QString &localFile, SocketListener *)
|
|||
// If the parent doesn't accept new files, go to the root of the sync folder
|
||||
QFileInfo fileInfo(localFile);
|
||||
const auto parentRecord = parentDir.journalRecord();
|
||||
if ((fileInfo.isFile() && !parentRecord._remotePerm.hasPermission(RemotePermissions::CanAddFile))
|
||||
|| (fileInfo.isDir() && !parentRecord._remotePerm.hasPermission(RemotePermissions::CanAddSubDirectories))) {
|
||||
if ((FileSystem::isFile(localFile) && !parentRecord._remotePerm.hasPermission(RemotePermissions::CanAddFile))
|
||||
|| (FileSystem::isDir(localFile) && !parentRecord._remotePerm.hasPermission(RemotePermissions::CanAddSubDirectories))) {
|
||||
defaultDirAndName = QFileInfo(defaultDirAndName).fileName();
|
||||
}
|
||||
|
||||
|
@ -1234,7 +1234,7 @@ void SocketApi::sendEncryptFolderCommandMenuEntries(const QFileInfo &fileInfo,
|
|||
!fileData.folder->accountState() ||
|
||||
!fileData.folder->accountState()->account() ||
|
||||
!fileData.folder->accountState()->account()->capabilities().clientSideEncryptionAvailable() ||
|
||||
!fileInfo.isDir() ||
|
||||
!FileSystem::isDir(fileInfo.absoluteFilePath()) ||
|
||||
isE2eEncryptedPath) {
|
||||
return;
|
||||
}
|
||||
|
@ -1262,7 +1262,7 @@ void SocketApi::sendLockFileCommandMenuEntries(const QFileInfo &fileInfo,
|
|||
const FileData &fileData,
|
||||
const OCC::SocketListener* const listener) const
|
||||
{
|
||||
if (!fileInfo.isDir() && syncFolder->accountState()->account()->capabilities().filesLockAvailable()) {
|
||||
if (!FileSystem::isDir(fileInfo.absoluteFilePath()) && syncFolder->accountState()->account()->capabilities().filesLockAvailable()) {
|
||||
if (syncFolder->accountState()->account()->fileLockStatus(syncFolder->journalDb(), fileData.folderRelativePath) == SyncFileItem::LockStatus::UnlockedItem) {
|
||||
listener->sendMessage(QLatin1String("MENU_ITEM:LOCK_FILE::") + tr("Lock file"));
|
||||
} else {
|
||||
|
@ -1280,7 +1280,7 @@ void SocketApi::sendLockFileInfoMenuEntries(const QFileInfo &fileInfo,
|
|||
const SyncJournalFileRecord &record) const
|
||||
{
|
||||
static constexpr auto SECONDS_PER_MINUTE = 60;
|
||||
if (!fileInfo.isDir() && syncFolder->accountState()->account()->capabilities().filesLockAvailable() &&
|
||||
if (!FileSystem::isDir(fileInfo.absoluteFilePath()) && syncFolder->accountState()->account()->capabilities().filesLockAvailable() &&
|
||||
syncFolder->accountState()->account()->fileLockStatus(syncFolder->journalDb(), fileData.folderRelativePath) == SyncFileItem::LockStatus::LockedItem) {
|
||||
listener->sendMessage(QLatin1String("MENU_ITEM:LOCKED_FILE_OWNER:d:") + tr("Locked by %1").arg(record._lockstate._lockOwnerDisplayName));
|
||||
const auto lockExpirationTime = record._lockstate._lockTime + record._lockstate._lockTimeout;
|
||||
|
@ -1381,7 +1381,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
|
|||
const QFileInfo fileInfo(fileData.localPath);
|
||||
sendLockFileInfoMenuEntries(fileInfo, syncFolder, fileData, listener, record);
|
||||
|
||||
if (!fileInfo.isDir()) {
|
||||
if (!FileSystem::isDir(fileData.localPath)) {
|
||||
listener->sendMessage(QLatin1String("MENU_ITEM:ACTIVITY") + flagString + tr("Activity"));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void SyncRunFileLog::start(const QString &folderPath)
|
|||
QString filename = logpath + QLatin1String("/") + filenameSingle + QLatin1String("_sync.log");
|
||||
|
||||
int depthIndex = 2;
|
||||
while(QFile::exists(filename)) {
|
||||
while (FileSystem::fileExists(filename)) {
|
||||
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly| QIODevice::Text);
|
||||
|
@ -65,9 +65,8 @@ void SyncRunFileLog::start(const QString &folderPath)
|
|||
}
|
||||
|
||||
// When the file is too big, just rename it to an old name.
|
||||
QFileInfo info(filename);
|
||||
bool exists = info.exists();
|
||||
if (exists && info.size() > logfileMaxSize) {
|
||||
bool exists = FileSystem::fileExists(filename);
|
||||
if (exists && FileSystem::getSize(filename) > logfileMaxSize) {
|
||||
exists = false;
|
||||
QString newFilename = filename + QLatin1String(".1");
|
||||
QFile::remove(newFilename);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "notificationhandler.h"
|
||||
#include "usermodel.h"
|
||||
#include "common/filesystembase.h"
|
||||
|
||||
#include "accountmanager.h"
|
||||
#include "owncloudgui.h"
|
||||
|
@ -576,24 +577,24 @@ void User::slotProgressInfo(const QString &folder, const ProgressInfo &progress)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (activity._syncFileItemStatus == SyncFileItem::Conflict && !QFileInfo::exists(f->path() + activity._file)) {
|
||||
if (activity._syncFileItemStatus == SyncFileItem::Conflict && !FileSystem::fileExists(f->path() + activity._file)) {
|
||||
_activityModel->removeActivityFromActivityList(activity);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (activity._syncFileItemStatus == SyncFileItem::FileLocked && !QFileInfo::exists(f->path() + activity._file)) {
|
||||
if (activity._syncFileItemStatus == SyncFileItem::FileLocked && !FileSystem::fileExists(f->path() + activity._file)) {
|
||||
_activityModel->removeActivityFromActivityList(activity);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (activity._syncFileItemStatus == SyncFileItem::FileIgnored && !QFileInfo::exists(f->path() + activity._file)) {
|
||||
if (activity._syncFileItemStatus == SyncFileItem::FileIgnored && !FileSystem::fileExists(f->path() + activity._file)) {
|
||||
_activityModel->removeActivityFromActivityList(activity);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!QFileInfo::exists(f->path() + activity._file)) {
|
||||
if (!FileSystem::fileExists(f->path() + activity._file)) {
|
||||
_activityModel->removeActivityFromActivityList(activity);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ CaseClashConflictSolver::CaseClashConflictSolver(const QString &targetFilePath,
|
|||
#if !defined(QT_NO_DEBUG)
|
||||
QFileInfo targetFileInfo(_targetFilePath);
|
||||
Q_ASSERT(targetFileInfo.isAbsolute());
|
||||
Q_ASSERT(QFileInfo::exists(_conflictFilePath));
|
||||
Q_ASSERT(FileSystem::fileExists(_conflictFilePath));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -606,7 +606,6 @@ void ProcessDirectoryJob::postProcessServerNew(const SyncFileItemPtr &item,
|
|||
if (!localEntry.isValid() &&
|
||||
item->_type == ItemTypeFile &&
|
||||
opts._vfs->mode() != Vfs::Off &&
|
||||
!FileSystem::isLnkFile(item->_file) &&
|
||||
_pinState != PinState::AlwaysLocal &&
|
||||
!FileSystem::isExcludeFile(item->_file)) {
|
||||
|
||||
|
@ -2165,7 +2164,7 @@ bool ProcessDirectoryJob::isVfsWithSuffix() const
|
|||
void ProcessDirectoryJob::computePinState(PinState parentState)
|
||||
{
|
||||
_pinState = parentState;
|
||||
if (_queryLocal != ParentDontExist && QFileInfo::exists(_discoveryData->_localDir + _currentFolder._local)) {
|
||||
if (_queryLocal != ParentDontExist && FileSystem::fileExists(_discoveryData->_localDir + _currentFolder._local)) {
|
||||
if (auto state = _discoveryData->_syncOptions._vfs->pinState(_currentFolder._local)) // ouch! pin local or original?
|
||||
_pinState = *state;
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ bool FileSystem::removeRecursively(const QString &path, const std::function<void
|
|||
bool removeOk = false;
|
||||
// The use of isSymLink here is okay:
|
||||
// we never want to go into this branch for .lnk files
|
||||
bool isDir = fi.isDir() && !fi.isSymLink() && !FileSystem::isJunction(fi.absoluteFilePath());
|
||||
bool isDir = FileSystem::isDir(fi.absoluteFilePath()) && !FileSystem::isSymLink(fi.absoluteFilePath()) && !FileSystem::isJunction(fi.absoluteFilePath());
|
||||
if (isDir) {
|
||||
removeOk = removeRecursively(path + QLatin1Char('/') + di.fileName(), onDeleted, errors); // recursive
|
||||
} else {
|
||||
|
|
|
@ -24,9 +24,7 @@
|
|||
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#if !defined(Q_OS_MACOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
|
||||
#include <filesystem>
|
||||
#endif
|
||||
#include <functional>
|
||||
|
||||
class QFile;
|
||||
|
||||
|
@ -96,7 +94,6 @@ namespace FileSystem {
|
|||
bool OWNCLOUDSYNC_EXPORT fileChanged(const QString &fileName,
|
||||
qint64 previousSize,
|
||||
time_t previousMtime);
|
||||
|
||||
/**
|
||||
* @brief Like !fileChanged() but with verbose logging if the file *did* change.
|
||||
*/
|
||||
|
|
|
@ -1070,6 +1070,7 @@ Result<Vfs::ConvertToPlaceholderResult, QString> OwncloudPropagator::staticUpdat
|
|||
if (!dBresult) {
|
||||
return dBresult.error();
|
||||
}
|
||||
|
||||
const auto result = vfs->convertToPlaceholder(fsPath, item, {}, updateType);
|
||||
if (!result) {
|
||||
return result.error();
|
||||
|
@ -1460,13 +1461,13 @@ void PropagateDirectory::slotSubJobsFinished(SyncFileItem::Status status)
|
|||
!_item->_remotePerm.hasPermission(RemotePermissions::CanMove) &&
|
||||
!_item->_remotePerm.hasPermission(RemotePermissions::CanAddSubDirectories)) {
|
||||
try {
|
||||
if (QFileInfo::exists(propagator()->fullLocalPath(_item->_file))) {
|
||||
if (FileSystem::fileExists(propagator()->fullLocalPath(_item->_file))) {
|
||||
FileSystem::setFolderPermissions(propagator()->fullLocalPath(_item->_file), FileSystem::FolderPermissions::ReadOnly);
|
||||
qCDebug(lcDirectory) << "old permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_file).toStdWString()).permissions());
|
||||
std::filesystem::permissions(propagator()->fullLocalPath(_item->_file).toStdWString(), std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write, std::filesystem::perm_options::remove);
|
||||
qCDebug(lcDirectory) << "new permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_file).toStdWString()).permissions());
|
||||
}
|
||||
if (!_item->_renameTarget.isEmpty() && QFileInfo::exists(propagator()->fullLocalPath(_item->_renameTarget))) {
|
||||
if (!_item->_renameTarget.isEmpty() && FileSystem::fileExists(propagator()->fullLocalPath(_item->_renameTarget))) {
|
||||
FileSystem::setFolderPermissions(propagator()->fullLocalPath(_item->_renameTarget), FileSystem::FolderPermissions::ReadOnly);
|
||||
qCDebug(lcDirectory) << "old permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_renameTarget).toStdWString()).permissions());
|
||||
std::filesystem::permissions(propagator()->fullLocalPath(_item->_renameTarget).toStdWString(), std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write, std::filesystem::perm_options::remove);
|
||||
|
@ -1485,13 +1486,13 @@ void PropagateDirectory::slotSubJobsFinished(SyncFileItem::Status status)
|
|||
!_item->_remotePerm.hasPermission(RemotePermissions::CanMove) ||
|
||||
!_item->_remotePerm.hasPermission(RemotePermissions::CanAddSubDirectories))) {
|
||||
try {
|
||||
if (QFileInfo::exists(propagator()->fullLocalPath(_item->_file))) {
|
||||
if (FileSystem::fileExists(propagator()->fullLocalPath(_item->_file))) {
|
||||
FileSystem::setFolderPermissions(propagator()->fullLocalPath(_item->_file), FileSystem::FolderPermissions::ReadWrite);
|
||||
qCDebug(lcDirectory) << "old permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_file).toStdWString()).permissions());
|
||||
std::filesystem::permissions(propagator()->fullLocalPath(_item->_file).toStdWString(), std::filesystem::perms::owner_write, std::filesystem::perm_options::add);
|
||||
qCDebug(lcDirectory) << "new permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_file).toStdWString()).permissions());
|
||||
}
|
||||
if (!_item->_renameTarget.isEmpty() && QFileInfo::exists(propagator()->fullLocalPath(_item->_renameTarget))) {
|
||||
if (!_item->_renameTarget.isEmpty() && FileSystem::fileExists(propagator()->fullLocalPath(_item->_renameTarget))) {
|
||||
FileSystem::setFolderPermissions(propagator()->fullLocalPath(_item->_renameTarget), FileSystem::FolderPermissions::ReadWrite);
|
||||
qCDebug(lcDirectory) << "old permissions" << static_cast<int>(std::filesystem::status(propagator()->fullLocalPath(_item->_renameTarget).toStdWString()).permissions());
|
||||
std::filesystem::permissions(propagator()->fullLocalPath(_item->_renameTarget).toStdWString(), std::filesystem::perms::owner_write, std::filesystem::perm_options::add);
|
||||
|
|
|
@ -1007,7 +1007,7 @@ void PropagateDownloadFile::checksumValidateFailedAbortDownload(const QString &e
|
|||
void PropagateDownloadFile::deleteExistingFolder()
|
||||
{
|
||||
QString existingDir = propagator()->fullLocalPath(_item->_file);
|
||||
if (!QFileInfo(existingDir).isDir()) {
|
||||
if (!FileSystem::isDir(existingDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1204,9 +1204,17 @@ void PropagateDownloadFile::downloadFinished()
|
|||
if (previousFileExists) {
|
||||
// Preserve the existing file permissions.
|
||||
const auto existingFile = QFileInfo{filename};
|
||||
#ifdef Q_OS_WIN
|
||||
const auto existingPermissions = FileSystem::filePermissionsWin(filename);
|
||||
const auto tmpFilePermissions = FileSystem::filePermissionsWin(_tmpFile.fileName());
|
||||
if (existingPermissions != tmpFilePermissions) {
|
||||
FileSystem::setFilePermissionsWin(_tmpFile.fileName(), existingPermissions);
|
||||
}
|
||||
#else
|
||||
if (existingFile.permissions() != _tmpFile.permissions()) {
|
||||
_tmpFile.setPermissions(existingFile.permissions());
|
||||
}
|
||||
#endif
|
||||
preserveGroupOwnership(_tmpFile.fileName(), existingFile);
|
||||
|
||||
// Make the file a hydrated placeholder if possible
|
||||
|
@ -1228,7 +1236,7 @@ void PropagateDownloadFile::downloadFinished()
|
|||
}
|
||||
|
||||
const auto isConflict = (_item->_instruction == CSYNC_INSTRUCTION_CONFLICT
|
||||
&& (QFileInfo(filename).isDir() || !FileSystem::fileEquals(filename, _tmpFile.fileName()))) ||
|
||||
&& (FileSystem::isDir(filename) || !FileSystem::fileEquals(filename, _tmpFile.fileName()))) ||
|
||||
_item->_instruction == CSYNC_INSTRUCTION_CASE_CLASH_CONFLICT;
|
||||
|
||||
if (isConflict) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "account.h"
|
||||
#include "common/syncjournalfilerecord.h"
|
||||
#include "filesystem.h"
|
||||
#include "common/filesystembase.h"
|
||||
#include "common/asserts.h"
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
|
@ -253,7 +254,7 @@ void PropagateRemoteMove::finalize()
|
|||
|
||||
const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
|
||||
if (QFileInfo::exists(targetFile)) {
|
||||
if (FileSystem::fileExists(targetFile)) {
|
||||
// Delete old db data.
|
||||
if (!propagator()->_journal->deleteFileRecord(_item->_originalFile)) {
|
||||
qCWarning(lcPropagateRemoteMove) << "could not delete file from local DB" << _item->_originalFile;
|
||||
|
@ -277,7 +278,7 @@ void PropagateRemoteMove::finalize()
|
|||
}
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(targetFile)) {
|
||||
if (!FileSystem::fileExists(targetFile)) {
|
||||
propagator()->_journal->commit("Remote Rename");
|
||||
done(SyncFileItem::Success, {}, ErrorCategory::NoError);
|
||||
return;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "clientsideencryption.h"
|
||||
#include "foldermetadata.h"
|
||||
#include "encryptedfoldermetadatahandler.h"
|
||||
#include "filesystem.h"
|
||||
#include "account.h"
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
@ -182,7 +183,7 @@ void PropagateUploadEncrypted::slotUploadMetadataFinished(int statusCode, const
|
|||
qCDebug(lcPropagateUploadEncrypted) << "Finalizing the upload part, now the actuall uploader will take over";
|
||||
emit finalized(Utility::trailingSlashPath(outputInfo.path()) + outputInfo.fileName(),
|
||||
Utility::trailingSlashPath(_remoteParentPath) + outputInfo.fileName(),
|
||||
outputInfo.size());
|
||||
FileSystem::getSize(_completeFileName));
|
||||
}
|
||||
|
||||
} // namespace OCC
|
|
@ -163,8 +163,7 @@ void PropagateLocalMkdir::startLocalMkdir()
|
|||
|
||||
// When turning something that used to be a file into a directory
|
||||
// we need to delete the file first.
|
||||
QFileInfo fi(newDirStr);
|
||||
if (fi.exists() && fi.isFile()) {
|
||||
if (FileSystem::fileExists(newDirStr) && FileSystem::isFile(newDirStr)) {
|
||||
if (_deleteExistingFile) {
|
||||
QString removeError;
|
||||
if (!FileSystem::remove(newDirStr, &removeError)) {
|
||||
|
@ -282,7 +281,7 @@ void PropagateLocalRename::start()
|
|||
const auto existingFile = propagator()->fullLocalPath(previousNameInDb);
|
||||
const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
|
||||
const auto fileAlreadyMoved = !QFileInfo::exists(propagator()->fullLocalPath(_item->_originalFile)) && QFileInfo::exists(existingFile);
|
||||
const auto fileAlreadyMoved = !FileSystem::fileExists(propagator()->fullLocalPath(_item->_originalFile)) && FileSystem::fileExists(existingFile);
|
||||
auto pinState = OCC::PinState::Unspecified;
|
||||
if (!fileAlreadyMoved) {
|
||||
auto pinStateResult = vfs->pinState(propagator()->adjustRenamedPath(_item->_file));
|
||||
|
@ -294,7 +293,7 @@ void PropagateLocalRename::start()
|
|||
// if the file is a file underneath a moved dir, the _item->file is equal
|
||||
// to _item->renameTarget and the file is not moved as a result.
|
||||
qCDebug(lcPropagateLocalRename) << _item->_file << _item->_renameTarget << _item->_originalFile << previousNameInDb << (fileAlreadyMoved ? "original file has already moved" : "original file is still there");
|
||||
Q_ASSERT(QFileInfo::exists(propagator()->fullLocalPath(_item->_originalFile)) || QFileInfo::exists(existingFile));
|
||||
Q_ASSERT(FileSystem::fileExists(propagator()->fullLocalPath(_item->_originalFile)) || FileSystem::fileExists(existingFile));
|
||||
if (_item->_file != _item->_renameTarget) {
|
||||
propagator()->reportProgress(*_item, 0);
|
||||
qCDebug(lcPropagateLocalRename) << "MOVE " << existingFile << " => " << targetFile;
|
||||
|
|
|
@ -287,7 +287,7 @@ void SyncEngine::conflictRecordMaintenance()
|
|||
const auto conflictRecordPaths = _journal->conflictRecordPaths();
|
||||
for (const auto &path : conflictRecordPaths) {
|
||||
auto fsPath = _propagator->fullLocalPath(QString::fromUtf8(path));
|
||||
if (!QFileInfo::exists(fsPath)) {
|
||||
if (!FileSystem::fileExists(fsPath)) {
|
||||
_journal->deleteConflictRecord(path);
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ void SyncEngine::caseClashConflictRecordMaintenance()
|
|||
const auto conflictRecordPaths = _journal->caseClashConflictRecordPaths();
|
||||
for (const auto &path : conflictRecordPaths) {
|
||||
const auto fsPath = _propagator->fullLocalPath(QString::fromUtf8(path));
|
||||
if (!QFileInfo::exists(fsPath)) {
|
||||
if (!FileSystem::fileExists(fsPath)) {
|
||||
_journal->deleteCaseClashConflictByPathRecord(path);
|
||||
}
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ void SyncEngine::startSync()
|
|||
_discoveryPhase->_account = _account;
|
||||
_discoveryPhase->_excludes = _excludedFiles.data();
|
||||
const QString excludeFilePath = _localPath + QStringLiteral(".sync-exclude.lst");
|
||||
if (QFile::exists(excludeFilePath)) {
|
||||
if (FileSystem::fileExists(excludeFilePath)) {
|
||||
_discoveryPhase->_excludes->addExcludeFilePath(excludeFilePath);
|
||||
_discoveryPhase->_excludes->reloadExcludeFiles();
|
||||
}
|
||||
|
@ -1237,7 +1237,7 @@ void SyncEngine::wipeVirtualFiles(const QString &localPath, SyncJournalDb &journ
|
|||
// If the local file is a dehydrated placeholder, wipe it too.
|
||||
// Otherwise leave it to allow the next sync to have a new-new conflict.
|
||||
QString localFile = localPath + rec._path;
|
||||
if (QFile::exists(localFile) && vfs.isDehydratedPlaceholder(localFile)) {
|
||||
if (FileSystem::fileExists(localFile) && vfs.isDehydratedPlaceholder(localFile)) {
|
||||
qCDebug(lcEngine) << "Removing local dehydrated placeholder" << rec.path();
|
||||
QFile::remove(localFile);
|
||||
}
|
||||
|
|
|
@ -784,12 +784,11 @@ OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &pa
|
|||
return {};
|
||||
}
|
||||
|
||||
QFileInfo pathFileInfo(path);
|
||||
if (!pathFileInfo.exists()) {
|
||||
if (!FileSystem::fileExists(path)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (pathFileInfo.isDir()) {
|
||||
if (FileSystem::isDir(path)) {
|
||||
HANDLE handle = nullptr;
|
||||
const qint64 openResult = CfOpenFileWithOplock(path.toStdWString().data(), CF_OPEN_FILE_FLAG_NONE, &handle);
|
||||
if (openResult == S_OK) {
|
||||
|
@ -797,7 +796,7 @@ OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &pa
|
|||
} else {
|
||||
qCWarning(lcCfApiWrapper) << "Could not open handle for " << path << " result: " << QString::fromWCharArray(_com_error(openResult).ErrorMessage());
|
||||
}
|
||||
} else if (pathFileInfo.isFile()) {
|
||||
} else if (FileSystem::isFile(path)) {
|
||||
const auto longpath = OCC::FileSystem::longWinPath(path);
|
||||
const auto handle = CreateFile(longpath.toStdWString().data(), 0, 0, nullptr,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "hydrationjob.h"
|
||||
#include "syncfileitem.h"
|
||||
#include "filesystem.h"
|
||||
#include "common/filesystembase.h"
|
||||
#include "common/syncjournaldb.h"
|
||||
#include "config.h"
|
||||
|
||||
|
@ -48,7 +49,7 @@ bool registerShellExtension()
|
|||
// assume CFAPI_SHELL_EXTENSIONS_LIB_NAME is always in the same folder as the main executable
|
||||
// assume CFAPI_SHELL_EXTENSIONS_LIB_NAME is always in the same folder as the main executable
|
||||
const auto shellExtensionDllPath = QDir::toNativeSeparators(QString(QCoreApplication::applicationDirPath() + QStringLiteral("/") + CFAPI_SHELL_EXTENSIONS_LIB_NAME + QStringLiteral(".dll")));
|
||||
if (!QFileInfo::exists(shellExtensionDllPath)) {
|
||||
if (!OCC::FileSystem::fileExists(shellExtensionDllPath)) {
|
||||
Q_ASSERT(false);
|
||||
qCWarning(lcCfApi) << "Register CfAPI shell extensions failed. Dll does not exist in " << QCoreApplication::applicationDirPath();
|
||||
return false;
|
||||
|
@ -236,16 +237,6 @@ Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item)
|
|||
Result<Vfs::ConvertToPlaceholderResult, QString> VfsCfApi::convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile, UpdateMetadataTypes updateType)
|
||||
{
|
||||
const auto localPath = QDir::toNativeSeparators(filename);
|
||||
|
||||
if (item._type != ItemTypeDirectory && OCC::FileSystem::isLnkFile(filename)) {
|
||||
qCInfo(lcCfApi) << "File \"" << filename << "\" is a Windows shortcut. Not converting it to a placeholder.";
|
||||
const auto pinState = pinStateLocal(localPath);
|
||||
if (!pinState || *pinState != PinState::Excluded) {
|
||||
setPinStateLocal(localPath, PinState::Excluded);
|
||||
}
|
||||
return Vfs::ConvertToPlaceholderResult::Ok;
|
||||
}
|
||||
|
||||
const auto replacesPath = QDir::toNativeSeparators(replacesFile);
|
||||
|
||||
if (cfapi::findPlaceholderInfo(localPath)) {
|
||||
|
@ -281,8 +272,6 @@ bool VfsCfApi::statTypeVirtualFile(csync_file_stat_t *stat, void *statData)
|
|||
const auto hasReparsePoint = (ffd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
|
||||
const auto hasCloudTag = hasReparsePoint && (ffd->dwReserved0 & ~IO_REPARSE_TAG_CLOUD_MASK) == (IO_REPARSE_TAG_CLOUD & ~IO_REPARSE_TAG_CLOUD_MASK);
|
||||
|
||||
const auto isWindowsShortcut = !isDirectory && FileSystem::isLnkFile(stat->path);
|
||||
|
||||
const auto isExcludeFile = !isDirectory && FileSystem::isExcludeFile(stat->path);
|
||||
|
||||
stat->is_metadata_missing = !hasCloudTag;
|
||||
|
@ -298,7 +287,7 @@ bool VfsCfApi::statTypeVirtualFile(csync_file_stat_t *stat, void *statData)
|
|||
} else if (isSparseFile && isPinned) {
|
||||
stat->type = ItemTypeVirtualFileDownload;
|
||||
return true;
|
||||
} else if (!isSparseFile && isUnpinned && !isWindowsShortcut && !isExcludeFile) {
|
||||
} else if (!isSparseFile && isUnpinned && !isExcludeFile) {
|
||||
stat->type = ItemTypeVirtualFileDehydration;
|
||||
return true;
|
||||
} else if (isSparseFile) {
|
||||
|
@ -522,9 +511,10 @@ int VfsCfApi::finalizeHydrationJob(const QString &requestId)
|
|||
VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinStates(const QString &folderPath, const Optional<PinState> &basePinState)
|
||||
{
|
||||
Q_ASSERT(!folderPath.endsWith('/'));
|
||||
const auto fullPath = params().filesystemPath + folderPath;
|
||||
QFileInfo info(params().filesystemPath + folderPath);
|
||||
|
||||
if (!info.exists()) {
|
||||
if (!FileSystem::fileExists(fullPath)) {
|
||||
return {};
|
||||
}
|
||||
const auto effectivePin = pinState(folderPath);
|
||||
|
@ -533,7 +523,7 @@ VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinState
|
|||
: (*effectivePin == *basePinState) ? *effectivePin
|
||||
: PinState::Inherited;
|
||||
|
||||
if (info.isDir()) {
|
||||
if (FileSystem::isDir(fullPath)) {
|
||||
const auto dirState = HydratationAndPinStates {
|
||||
pinResult,
|
||||
{}
|
||||
|
|
|
@ -150,8 +150,7 @@ bool VfsSuffix::isDehydratedPlaceholder(const QString &filePath)
|
|||
{
|
||||
if (!filePath.endsWith(fileSuffix()))
|
||||
return false;
|
||||
QFileInfo fi(filePath);
|
||||
return fi.exists() && fi.size() == 1;
|
||||
return FileSystem::fileExists(filePath) && FileSystem::getSize(filePath) == 1;
|
||||
}
|
||||
|
||||
bool VfsSuffix::statTypeVirtualFile(csync_file_stat_t *stat, void *)
|
||||
|
|
|
@ -1363,9 +1363,8 @@ private slots:
|
|||
QVERIFY(!localFileLocked.isWritable());
|
||||
}
|
||||
|
||||
void testLinkFileDoesNotConvertToPlaceholder()
|
||||
void testLinkFileDownload()
|
||||
{
|
||||
// inspired by GH issue #6041
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
auto vfs = setupVfs(fakeFolder);
|
||||
|
||||
|
@ -1375,8 +1374,11 @@ private slots:
|
|||
QVERIFY(fakeFolder.syncOnce());
|
||||
ItemCompletedSpy completeSpy(fakeFolder);
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QVERIFY(!vfs->pinState("linkfile.lnk").isValid() || vfs->pinState("linkfile.lnk").get() == PinState::Excluded);
|
||||
QVERIFY(vfs->pinState("linkfile.lnk").isValid());
|
||||
QVERIFY(itemInstruction(completeSpy, "linkfile.lnk", CSYNC_INSTRUCTION_NONE));
|
||||
triggerDownload(fakeFolder, "linkfile.lnk");
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QVERIFY(itemInstruction(completeSpy, "linkfile.lnk", CSYNC_INSTRUCTION_SYNC));
|
||||
}
|
||||
|
||||
void testFolderDoesNotUpdatePlaceholderMetadata()
|
||||
|
|
Loading…
Reference in a new issue