VirtualFiles: Ensure the target location supports vfs
authorHannah von Reth <hannah.vonreth@owncloud.com>
Wed, 21 Oct 2020 10:31:21 +0000 (12:31 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:59:20 +0000 (10:59 +0100)
Fixes: #8131
src/common/vfs.cpp
src/common/vfs.h
src/gui/accountsettings.cpp
src/gui/folder.cpp
src/gui/folder.h
src/gui/folderstatusmodel.cpp
src/gui/folderwizard.cpp
src/gui/socketapi.cpp
src/gui/wizard/owncloudadvancedsetuppage.cpp

index d97ea69cc1370d21e89f9fe62ed8e89c07dd4797..8c5c53d7b86014afac26490ad0827de69482c5bf 100644 (file)
@@ -21,6 +21,8 @@
 #include "version.h"
 #include "syncjournaldb.h"
 
+#include "common/filesystembase.h"
+
 #include <QPluginLoader>
 #include <QLoggingCategory>
 
@@ -60,6 +62,22 @@ Optional<Vfs::Mode> Vfs::modeFromString(const QString &str)
     return {};
 }
 
+Result<bool, QString> Vfs::checkAvailability(const QString &path)
+{
+    const auto mode = bestAvailableVfsMode();
+#ifdef Q_OS_WIN
+    if (mode == Mode::WindowsCfApi) {
+        const auto fs = FileSystem::fileSystemForPath(path);
+        if (fs != QLatin1String("NTFS")) {
+            return tr("The Virtual filesystem feature requires a NTFS file system, %1 is using %2").arg(path, fs);
+        }
+    }
+#else
+    Q_UNUSED(path);
+#endif
+    return true;
+}
+
 void Vfs::start(const VfsSetupParams &params)
 {
     _setupParams = params;
index 3e17a17f9d4358a3e948d4cbd6dd3f61758e1b5c..c11f59bb2834d0e368820120533fc2fb4fc30c4a 100644 (file)
@@ -99,6 +99,8 @@ public:
     static QString modeToString(Mode mode);
     static Optional<Mode> modeFromString(const QString &str);
 
+    static Result<bool, QString> checkAvailability(const QString &path);
+
     enum class AvailabilityError
     {
         // Availability can't be retrieved due to db error
index 7f3b019b750c13c4fe9e35bb7808482b3446cbf2..d5606ec73fa7173b1ee6406f766c3e2ba550c7d6 100644 (file)
@@ -445,7 +445,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
     ac = menu->addAction(tr("Remove folder sync connection"));
     connect(ac, &QAction::triggered, this, &AccountSettings::slotRemoveCurrentFolder);
 
-    if (folder->supportsVirtualFiles()) {
+    if (folder->virtualFilesEnabled()) {
         auto availabilityMenu = menu->addMenu(tr("Availability"));
         auto availability = folder->vfs().availability(QString());
         if (availability) {
@@ -468,11 +468,12 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
     }
 
     if (Theme::instance()->showVirtualFilesOption()
-        && !folder->supportsVirtualFiles()
-        && bestAvailableVfsMode() != Vfs::Off
-        && !folder->isVfsOnOffSwitchPending()) {
-        ac = menu->addAction(tr("Enable virtual file support%1...").arg(bestAvailableVfsMode() == Vfs::WindowsCfApi ? QString() : tr(" (experimental)")));
-        connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder);
+        && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path())) {
+        const auto mode = bestAvailableVfsMode();
+        if (mode == Vfs::WindowsCfApi || ConfigFile().showExperimentalOptions()) {
+            ac = menu->addAction(tr("Enable virtual file support%1...").arg(mode == Vfs::WindowsCfApi ? QString() : tr(" (experimental)")));
+            connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder);
+        }
     }
 
 
@@ -688,7 +689,7 @@ void AccountSettings::slotEnableVfsCurrentFolder()
             folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
 
             // Change the folder vfs mode and load the plugin
-            folder->setSupportsVirtualFiles(true);
+            folder->setVirtualFilesEnabled(true);
             folder->setVfsOnOffSwitchPending(false);
 
             // Setting to Unspecified retains existing data.
@@ -754,7 +755,7 @@ void AccountSettings::slotDisableVfsCurrentFolder()
             qCInfo(lcAccountSettings) << "Disabling vfs support for folder" << folder->path();
 
             // Also wipes virtual files, schedules remote discovery
-            folder->setSupportsVirtualFiles(false);
+            folder->setVirtualFilesEnabled(false);
             folder->setVfsOnOffSwitchPending(false);
 
             // Wipe pin states and selective sync db
index 4a793f611bae4062412f9c1c8c2e912e7f3e095e..59c762ecd83bf77e607835aca05bd355df72a871 100644 (file)
@@ -631,7 +631,7 @@ void Folder::implicitlyHydrateFile(const QString &relativepath)
     slotScheduleThisFolder();
 }
 
-void Folder::setSupportsVirtualFiles(bool enabled)
+void Folder::setVirtualFilesEnabled(bool enabled)
 {
     Vfs::Mode newMode = _definition.virtualFilesMode;
     if (enabled && _definition.virtualFilesMode == Vfs::Off) {
@@ -671,7 +671,7 @@ void Folder::setRootPinState(PinState state)
 
 bool Folder::supportsSelectiveSync() const
 {
-    return !supportsVirtualFiles() && !isVfsOnOffSwitchPending();
+    return !virtualFilesEnabled() && !isVfsOnOffSwitchPending();
 }
 
 void Folder::saveToSettings() const
@@ -688,7 +688,7 @@ void Folder::saveToSettings() const
         return other != this && other->cleanPath() == this->cleanPath();
     });
 
-    if (supportsVirtualFiles() || _saveInFoldersWithPlaceholders) {
+    if (virtualFilesEnabled() || _saveInFoldersWithPlaceholders) {
         // If virtual files are enabled or even were enabled at some point,
         // save the folder to a group that will not be read by older (<2.5.0) clients.
         // The name is from when virtual files were called placeholders.
@@ -1221,7 +1221,7 @@ void Folder::registerFolderWatcher()
     _folderWatcher->startNotificatonTest(path() + QLatin1String(".owncloudsync.log"));
 }
 
-bool Folder::supportsVirtualFiles() const
+bool Folder::virtualFilesEnabled() const
 {
     return _definition.virtualFilesMode != Vfs::Off && !isVfsOnOffSwitchPending();
 }
index 771d9e460607da0397933d1645928145c0b3c110..811ef7e99b1f3854fd04dfd254978ab4b7c77c60 100644 (file)
@@ -276,8 +276,8 @@ public:
      * and never have an automatic virtual file. But when it's on, the shell context menu will allow
      * users to make existing files virtual.
      */
-    bool supportsVirtualFiles() const;
-    void setSupportsVirtualFiles(bool enabled);
+    bool virtualFilesEnabled() const;
+    void setVirtualFilesEnabled(bool enabled);
 
     void setRootPinState(PinState state);
 
index 5839bd83434b3a5ff673ab38b453b1f168808494..0ebab24b894d39d53051adb24bc7b18a9a8a6151 100644 (file)
@@ -219,7 +219,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
     case FolderStatusDelegate::FolderErrorMsg:
         return f->syncResult().errorStrings();
     case FolderStatusDelegate::FolderInfoMsg:
-        return f->supportsVirtualFiles() && f->vfs().mode() != Vfs::Mode::WindowsCfApi
+        return f->virtualFilesEnabled() && f->vfs().mode() != Vfs::Mode::WindowsCfApi
             ? QStringList(tr("Virtual file support is enabled."))
             : QStringList();
     case FolderStatusDelegate::SyncRunning:
@@ -283,7 +283,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
     case FolderStatusDelegate::SyncProgressOverallString:
         return progress._overallSyncString;
     case FolderStatusDelegate::FolderSyncText:
-        if (f->supportsVirtualFiles()) {
+        if (f->virtualFilesEnabled()) {
             return tr("Synchronizing VirtualFiles with local folder");
         } else {
             return tr("Synchronizing with local folder");
index fd40ef611149ac0b3130f159af1d34fe2a5b67c4..27345b46ffdeb14a20cd8d9ed3a7c876ed97e92d 100644 (file)
@@ -37,6 +37,7 @@
 #include <QVBoxLayout>
 #include <QEvent>
 #include <QCheckBox>
+#include <QMessageBox>
 
 #include <cstdlib>
 
@@ -520,7 +521,16 @@ void FolderWizardSelectiveSync::initializePage()
 
 bool FolderWizardSelectiveSync::validatePage()
 {
-    bool useVirtualFiles = _virtualFilesCheckBox && _virtualFilesCheckBox->isChecked();
+    const bool useVirtualFiles = _virtualFilesCheckBox && _virtualFilesCheckBox->isChecked();
+    if (useVirtualFiles) {
+        const auto availability = Vfs::checkAvailability(wizard()->field(QStringLiteral("sourceFolder")).toString());
+        if (!availability) {
+            auto msg = new QMessageBox(QMessageBox::Warning, tr("Virtual files are not available for the selected folder"), availability.error(), QMessageBox::Ok, this);
+            msg->setAttribute(Qt::WA_DeleteOnClose);
+            msg->open();
+            return false;
+        }
+    }
     wizard()->setProperty("selectiveSyncBlackList", useVirtualFiles ? QVariant() : QVariant(_selectiveSync->createBlackList()));
     wizard()->setProperty("useVirtualFiles", QVariant(useVirtualFiles));
     return true;
index e1bfcdf610df8f1f97bfcfb85e5a6060c29c016d..3be2d1455c09d06e84659705647e00b3002308b3 100644 (file)
@@ -1107,7 +1107,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
 
     // File availability actions
     if (syncFolder
-        && syncFolder->supportsVirtualFiles()
+        && syncFolder->virtualFilesEnabled()
         && syncFolder->vfs().socketApiPinStateActionsShown()) {
         ENFORCE(!files.isEmpty());
 
index 66686f6f21cd5c095acb77d8217d127b6bee430d..dba276ec85efe3db9b0d3b01f3d0b20af556a81b 100644 (file)
@@ -268,6 +268,16 @@ bool OwncloudAdvancedSetupPage::isConfirmBigFolderChecked() const
 
 bool OwncloudAdvancedSetupPage::validatePage()
 {
+    if (useVirtualFileSync()) {
+        const auto availability = Vfs::checkAvailability(localFolder());
+        if (!availability) {
+            auto msg = new QMessageBox(QMessageBox::Warning, tr("Virtual files are not available for the selected folder"), availability.error(), QMessageBox::Ok, this);
+            msg->setAttribute(Qt::WA_DeleteOnClose);
+            msg->open();
+            return false;
+        }
+    }
+
     if (!_created) {
         setErrorString(QString());
         _checking = true;