From: Christian Kamm Date: Fri, 16 Jun 2017 13:43:21 +0000 (+0200) Subject: Journal: Don't use a ._ path if it won't work #5633 X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~710^2~3^2~6 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4291ea47f77752848e31341019e9be98f59526df;p=nextcloud-desktop.git Journal: Don't use a ._ path if it won't work #5633 When synchronizing a folder on a samba share, creating files that begin with ._ is often forbidden. This prevented the client from creating its ._sync_abcdef.db file. Now, it'll check whether the preferred filename is creatable, and if it isn't it'll use .sync_abcdef.db instead. The disadvantage is that this alternative path won't be ignored by older clients - that was the reason for the ._ prefix. --- diff --git a/csync/src/csync_exclude.c b/csync/src/csync_exclude.c index e125b3346..88dd61e75 100644 --- a/csync/src/csync_exclude.c +++ b/csync/src/csync_exclude.c @@ -235,6 +235,11 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch match = CSYNC_FILE_SILENTLY_EXCLUDED; goto out; } + rc = csync_fnmatch(".sync_*.db*", bname, 0); + if (rc == 0) { + match = CSYNC_FILE_SILENTLY_EXCLUDED; + goto out; + } rc = csync_fnmatch(".csync_journal.db*", bname, 0); if (rc == 0) { match = CSYNC_FILE_SILENTLY_EXCLUDED; diff --git a/csync/tests/csync_tests/check_csync_exclude.c b/csync/tests/csync_tests/check_csync_exclude.c index e7af73c67..bd4813c5e 100644 --- a/csync/tests/csync_tests/check_csync_exclude.c +++ b/csync/tests/csync_tests/check_csync_exclude.c @@ -157,7 +157,16 @@ static void check_csync_excluded(void **state) assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); rc = csync_excluded_no_ctx(csync->excludes, "subdir/._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); - + + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db.ctmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db-shm", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "subdir/.sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + /* pattern ]*.directory - ignore and remove */ rc = csync_excluded_no_ctx(csync->excludes, "my.~directory", CSYNC_FTW_TYPE_FILE); diff --git a/src/cmd/cmd.cpp b/src/cmd/cmd.cpp index 5421b2314..152f24996 100644 --- a/src/cmd/cmd.cpp +++ b/src/cmd/cmd.cpp @@ -469,7 +469,7 @@ restart_sync: } Cmd cmd; - QString dbPath = options.source_dir + SyncJournalDb::makeDbName(credentialFreeUrl, folder, user); + QString dbPath = options.source_dir + SyncJournalDb::makeDbName(options.source_dir, credentialFreeUrl, folder, user); SyncJournalDb db(dbPath); if (!selectiveSyncList.empty()) { diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 83ed5c531..7e2d12b1c 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -1003,7 +1003,7 @@ QString FolderDefinition::absoluteJournalPath() const QString FolderDefinition::defaultJournalPath(AccountPtr account) { - return SyncJournalDb::makeDbName(account->url(), targetPath, account->credentials()->user()); + return SyncJournalDb::makeDbName(localPath, account->url(), targetPath, account->credentials()->user()); } } // namespace OCC diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 1a230a28c..cb0fa90b5 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -235,11 +235,22 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account, foreach (const auto& folderAlias, settings.childGroups()) { FolderDefinition folderDefinition; if (FolderDefinition::load(settings, folderAlias, &folderDefinition)) { + auto defaultJournalPath = folderDefinition.defaultJournalPath(account->account()); + // Migration: Old settings don't have journalPath if (folderDefinition.journalPath.isEmpty()) { - folderDefinition.journalPath = folderDefinition.defaultJournalPath(account->account()); + folderDefinition.journalPath = defaultJournalPath; + } + + // Migration: ._ files sometimes don't work + // So if the configured journalPath is the default one ("._sync_*.db") + // but the current default doesn't have the underscore, switch to the + // new default. See SyncJournalDb::makeDbName(). + if (folderDefinition.journalPath.startsWith("._sync_") + && defaultJournalPath.startsWith(".sync_")) { + folderDefinition.journalPath = defaultJournalPath; } - folderDefinition.defaultJournalPath(account->account()); + // Migration: If an old db is found, move it to the new name. if (backwardsCompatible) { SyncJournalDb::maybeMigrateDb(folderDefinition.localPath, folderDefinition.absoluteJournalPath()); diff --git a/src/gui/folderwatcher_linux.cpp b/src/gui/folderwatcher_linux.cpp index c8024c00b..d647f6595 100644 --- a/src/gui/folderwatcher_linux.cpp +++ b/src/gui/folderwatcher_linux.cpp @@ -171,7 +171,8 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd) // qDebug() << Q_FUNC_INFO << event->name; if (fileName.startsWith("._sync_") || fileName.startsWith(".csync_journal.db") || - fileName.startsWith(".owncloudsync.log")) { + fileName.startsWith(".owncloudsync.log") || + fileName.startsWith(".sync_")) { // qDebug() << "ignore journal"; } else { const QString p = _watches[event->wd] + '/' + fileName; diff --git a/src/libsync/syncjournaldb.cpp b/src/libsync/syncjournaldb.cpp index 43ef9b37a..c6c4a9cd5 100644 --- a/src/libsync/syncjournaldb.cpp +++ b/src/libsync/syncjournaldb.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "ownsql.h" @@ -41,7 +42,8 @@ SyncJournalDb::SyncJournalDb(const QString& dbFilePath, QObject *parent) : } -QString SyncJournalDb::makeDbName(const QUrl& remoteUrl, +QString SyncJournalDb::makeDbName(const QString& localPath, + const QUrl& remoteUrl, const QString& remotePath, const QString& user) { @@ -56,6 +58,42 @@ QString SyncJournalDb::makeDbName(const QUrl& remoteUrl, journalPath.append( ba.left(6).toHex() ); journalPath.append(".db"); + // If the journal doesn't exist and we can't create a file + // at that location, try again with a journal name that doesn't + // have the ._ prefix. + // + // The disadvantage of that filename is that it will only be ignored + // by client versions >2.3.2. + // + // See #5633: "._*" is often forbidden on samba shared folders. + + // If it exists already, the path is clearly usable + QFile file(QDir(localPath).filePath(journalPath)); + if (file.exists()) { + return journalPath; + } + + // Try to create a file there + if (file.open(QIODevice::ReadWrite)) { + // Ok, all good. + file.close(); + file.remove(); + return journalPath; + } + + // Can we create it if we drop the underscore? + QString alternateJournalPath = journalPath.mid(2).prepend("."); + QFile file2(QDir(localPath).filePath(alternateJournalPath)); + if (file2.open(QIODevice::ReadWrite)) { + // The alternative worked, use it + qDebug() << "Using alternate database path" << alternateJournalPath; + file2.close(); + file2.remove(); + return alternateJournalPath; + } + + // Neither worked, just keep the original and throw errors later + qDebug() << "Could not find a writable database path" << file.fileName(); return journalPath; } diff --git a/src/libsync/syncjournaldb.h b/src/libsync/syncjournaldb.h index 72db1c463..37df8c81e 100644 --- a/src/libsync/syncjournaldb.h +++ b/src/libsync/syncjournaldb.h @@ -41,7 +41,8 @@ public: virtual ~SyncJournalDb(); /// Create a journal path for a specific configuration - static QString makeDbName(const QUrl& remoteUrl, + static QString makeDbName(const QString& localPath, + const QUrl& remoteUrl, const QString& remotePath, const QString& user);