Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not modify discovered files on disk if not necessary #5872

Merged
merged 8 commits into from
Aug 7, 2023
6 changes: 3 additions & 3 deletions src/common/filesystembase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,17 @@ void FileSystem::setFolderMinimumPermissions(const QString &filename)
#endif
}


void FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly)
bool FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly)
{
QFile file(filename);
QFile::Permissions permissions = file.permissions();

if (!readonly && (permissions & QFile::WriteOwner)) {
return; // already writable enough
return false; // already writable enough
}

setFileReadOnly(filename, readonly);
return true;
}

bool FileSystem::rename(const QString &originFileName,
Expand Down
2 changes: 1 addition & 1 deletion src/common/filesystembase.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ namespace FileSystem {
* This means that it will preserve explicitly set rw-r--r-- permissions even
* when the umask is 0002. (setFileReadOnly() would adjust to rw-rw-r--)
*/
void OCSYNC_EXPORT setFileReadOnlyWeak(const QString &filename, bool readonly);
bool OCSYNC_EXPORT setFileReadOnlyWeak(const QString &filename, bool readonly);

/**
* @brief Try to set permissions so that other users on the local machine can not
Expand Down
13 changes: 9 additions & 4 deletions src/libsync/syncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
// mini-jobs later on, we just update metadata right now.

if (item->_direction == SyncFileItem::Down) {
auto modificationHappened = false; // Decides whether or not we modify file metadata
QString filePath = _localPath + item->_file;

// If the 'W' remote permission changed, update the local filesystem
Expand All @@ -365,15 +366,18 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
&& prev.isValid()
&& prev._remotePerm.hasPermission(RemotePermissions::CanWrite) != item->_remotePerm.hasPermission(RemotePermissions::CanWrite)) {
const bool isReadOnly = !item->_remotePerm.isNull() && !item->_remotePerm.hasPermission(RemotePermissions::CanWrite);
FileSystem::setFileReadOnlyWeak(filePath, isReadOnly);
modificationHappened = FileSystem::setFileReadOnlyWeak(filePath, isReadOnly);
}

modificationHappened |= item->_size != prev._fileSize;

auto rec = item->toSyncJournalFileRecordWithInode(filePath);
if (rec._checksumHeader.isEmpty())
rec._checksumHeader = prev._checksumHeader;
rec._serverHasIgnoredFiles |= prev._serverHasIgnoredFiles;

// Ensure it's a placeholder file on disk
if (item->_type == ItemTypeFile) {
if (item->_type == ItemTypeFile && _syncOptions._vfs->mode() != Vfs::Off) {
const auto result = _syncOptions._vfs->convertToPlaceholder(filePath, *item);
if (!result) {
item->_status = SyncFileItem::Status::NormalError;
Expand All @@ -382,10 +386,11 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
emit itemCompleted(item, ErrorCategory::GenericError);
return;
}
modificationHappened = true;
}

// Update on-disk virtual file metadata
if (item->_type == ItemTypeVirtualFile) {
if (modificationHappened && item->_type == ItemTypeVirtualFile) {
auto r = _syncOptions._vfs->updateMetadata(filePath, item->_modtime, item->_size, item->_fileId);
if (!r) {
item->_status = SyncFileItem::Status::NormalError;
Expand All @@ -394,7 +399,7 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
emit itemCompleted(item, ErrorCategory::GenericError);
return;
}
} else {
} else if (modificationHappened || prev._modtime != item->_modtime) {
if (!FileSystem::setModTime(filePath, item->_modtime)) {
item->_instruction = CSYNC_INSTRUCTION_ERROR;
item->_errorString = tr("Could not update file metadata: %1").arg(filePath);
Expand Down
6 changes: 6 additions & 0 deletions test/syncenginetestutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ void DiskFileModifier::setE2EE([[maybe_unused]] const QString &relativePath, [[m
{
}

QFile DiskFileModifier::find(const QString &relativePath) const
{
const auto path = _rootDir.filePath(relativePath);
return QFile(path);
}

FileInfo FileInfo::A12_B12_C12_S12()
{
FileInfo fi { QString {}, {
Expand Down
2 changes: 2 additions & 0 deletions test/syncenginetestutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class DiskFileModifier : public FileModifier
void setModTime(const QString &relativePath, const QDateTime &modTime) override;
void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) override;
void setE2EE(const QString &relativepath, const bool enabled) override;

[[nodiscard]] QFile find(const QString &relativePath) const;
};

class FileInfo : public FileModifier
Expand Down
24 changes: 24 additions & 0 deletions test/testsyncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "propagatorjobs.h"
#include "syncengine.h"

#include <QFile>
#include <QtTest>

using namespace OCC;
Expand Down Expand Up @@ -921,6 +922,29 @@ private slots:
QCOMPARE(QFileInfo(fakeFolder.localPath() + "foo").lastModified(), datetime);
}

// A local file should not be modified after upload to server if nothing has changed.
void testLocalFileInitialMtime()
{
constexpr auto fooFolder = "foo/";
constexpr auto barFile = "foo/bar";

FakeFolder fakeFolder{FileInfo{}};
fakeFolder.localModifier().mkdir(fooFolder);
fakeFolder.localModifier().insert(barFile);

const auto localDiskFileModifier = dynamic_cast<DiskFileModifier &>(fakeFolder.localModifier());

const auto localFile = localDiskFileModifier.find(barFile);
const auto localFileInfo = QFileInfo(localFile);
const auto expectedMtime = localFileInfo.metadataChangeTime();

claucambra marked this conversation as resolved.
Show resolved Hide resolved
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());

const auto currentMtime = localFileInfo.metadataChangeTime();
QCOMPARE(currentMtime, expectedMtime);
}

/**
* Checks whether subsequent large uploads are skipped after a 507 error
*/
Expand Down
Loading