Skip to content

Commit

Permalink
Journal: Don't use a ._ path if it won't work #5633
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ckamm authored and guruz committed Jun 20, 2017
1 parent b50706a commit 4291ea4
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 8 deletions.
5 changes: 5 additions & 0 deletions csync/src/csync_exclude.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 10 additions & 1 deletion csync/tests/csync_tests/check_csync_exclude.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ int main(int argc, char **argv) {
}

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()) {
Expand Down
2 changes: 1 addition & 1 deletion src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
3 changes: 2 additions & 1 deletion src/gui/folderwatcher_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 39 additions & 1 deletion src/libsync/syncjournaldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <QDebug>
#include <QElapsedTimer>
#include <QUrl>
#include <QDir>

#include "ownsql.h"

Expand All @@ -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)
{
Expand All @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion src/libsync/syncjournaldb.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class OWNCLOUDSYNC_EXPORT SyncJournalDb : public QObject
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);

Expand Down

0 comments on commit 4291ea4

Please sign in to comment.