Skip to content

Commit

Permalink
newly created folders will be read-only when needed
Browse files Browse the repository at this point in the history
Close #6296

Signed-off-by: Matthieu Gallien <[email protected]>
  • Loading branch information
mgallien committed Feb 2, 2024
1 parent 38dee92 commit e04851b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/libsync/propagatedownload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@
#include <QNetworkAccessManager>
#include <QFileInfo>
#include <QDir>
#include <cmath>

#ifdef Q_OS_UNIX
#include <unistd.h>
#endif
#include <cmath>

namespace OCC {

Expand Down Expand Up @@ -672,8 +669,21 @@ void PropagateDownloadFile::startDownload()

// Can't open(Append) read-only files, make sure to make
// file writable if it exists.
if (_tmpFile.exists())
if (_tmpFile.exists()) {
FileSystem::setFileReadOnly(_tmpFile.fileName(), false);
}
const auto newDirPath = std::filesystem::path{_tmpFile.fileName().toStdWString()};
Q_ASSERT(newDirPath.has_parent_path());
_parentFolderPath = newDirPath.parent_path();
auto parentFolderStatus = std::filesystem::status(_parentFolderPath);
_parentPermissions = parentFolderStatus.permissions();
if ((_parentPermissions & std::filesystem::perms::owner_write) != std::filesystem::perms::owner_write) {
std::filesystem::permissions(_parentFolderPath, _parentPermissions | std::filesystem::perms::owner_write, std::filesystem::perm_options::replace);
emit propagator()->touchedFile(QString::fromStdWString(_parentFolderPath.wstring()));
_needParentFolderRestorePermissions = true;
}


if (!_tmpFile.open(QIODevice::Append | QIODevice::Unbuffered)) {
propagator()->account()->reportClientStatus(ClientStatusReportingStatus::DownloadError_Cannot_Create_File);
qCWarning(lcPropagateDownload) << "could not open temporary file" << _tmpFile.fileName();
Expand Down Expand Up @@ -1274,6 +1284,12 @@ void PropagateDownloadFile::downloadFinished()
return;
}

if (_needParentFolderRestorePermissions) {
std::filesystem::permissions(_parentFolderPath, _parentPermissions, std::filesystem::perm_options::replace);
emit propagator()->touchedFile(QString::fromStdWString(_parentFolderPath.wstring()));
_needParentFolderRestorePermissions = false;
}

FileSystem::setFileHidden(filename, false);

// Maybe we downloaded a newer version of the file than we thought we would...
Expand Down
6 changes: 6 additions & 0 deletions src/libsync/propagatedownload.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <QBuffer>
#include <QFile>

#include <filesystem>

namespace OCC {
class PropagateDownloadEncrypted;

Expand Down Expand Up @@ -260,5 +262,9 @@ private slots:
QElapsedTimer _stopwatch;

PropagateDownloadEncrypted *_downloadEncryptedHelper = nullptr;

std::filesystem::perms _parentPermissions;
std::filesystem::path _parentFolderPath;
bool _needParentFolderRestorePermissions = false;
};
}
25 changes: 25 additions & 0 deletions src/libsync/propagatorjobs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <qstack.h>
#include <QCoreApplication>

#include <filesystem>
#include <ctime>


Expand Down Expand Up @@ -181,13 +182,37 @@ void PropagateLocalMkdir::startLocalMkdir()
done(SyncFileItem::FileNameClash, tr("Folder %1 cannot be created because of a local file or folder name clash!").arg(newDirStr), ErrorCategory::GenericError);
return;
}

const auto newDirPath = std::filesystem::path{newDirStr.toStdWString()};
Q_ASSERT(newDirPath.has_parent_path());
const auto parentFolderPath = newDirPath.parent_path();
auto parentFolderStatus = std::filesystem::status(parentFolderPath);
const auto parentPermissions = parentFolderStatus.permissions();
if ((parentPermissions & std::filesystem::perms::owner_write) != std::filesystem::perms::owner_write) {
std::filesystem::permissions(parentFolderPath, parentPermissions | std::filesystem::perms::owner_write, std::filesystem::perm_options::replace);
emit propagator()->touchedFile(QString::fromStdWString(parentFolderPath.wstring()));
}

emit propagator()->touchedFile(newDirStr);
QDir localDir(propagator()->localPath());
if (!localDir.mkpath(_item->_file)) {
done(SyncFileItem::NormalError, tr("Could not create folder %1").arg(newDirStr), ErrorCategory::GenericError);
return;
}

if ((parentPermissions & std::filesystem::perms::owner_write) != std::filesystem::perms::owner_write) {
std::filesystem::permissions(parentFolderPath, parentPermissions, std::filesystem::perm_options::replace);
emit propagator()->touchedFile(QString::fromStdWString(parentFolderPath.wstring()));
}

if (!_item->_remotePerm.isNull() &&
!_item->_remotePerm.hasPermission(RemotePermissions::CanAddFile) &&
!_item->_remotePerm.hasPermission(RemotePermissions::CanRename) &&
!_item->_remotePerm.hasPermission(RemotePermissions::CanMove) &&
!_item->_remotePerm.hasPermission(RemotePermissions::CanAddSubDirectories)) {
std::filesystem::permissions(newDirStr.toStdWString(), std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::owner_write, std::filesystem::perm_options::remove);
}

// Insert the directory into the database. The correct etag will be set later,
// once all contents have been propagated, because should_update_metadata is true.
// Adding an entry with a dummy etag to the database still makes sense here
Expand Down

0 comments on commit e04851b

Please sign in to comment.