Maintain the original inode value for renamed files.

In case two renames are done on the same file/folder very quickly we
lost the information that the second operation was also a rename. That
was because we tried to get the inode value from a stat on the file once
the first rename was finished. But at that point, the file was already
gone because of the second rename.

Now the original inode is kept and written to db in case the file can
not be stat'ed.

This fixes bug #1737
This commit is contained in:
Klaas Freitag 2014-05-06 12:55:54 +02:00
parent 370dd99e47
commit a50c39cd0c
7 changed files with 19 additions and 7 deletions

View file

@ -444,6 +444,7 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
trav.rename_path = cur->destpath;
trav.etag = cur->etag;
trav.file_id = cur->file_id;
trav.inode = cur->inode;
trav.error_status = cur->error_status;
trav.should_update_etag = cur->should_update_etag;

View file

@ -170,6 +170,7 @@ enum csync_notify_type_e {
struct csync_tree_walk_file_s {
const char *path;
int64_t size;
int64_t inode;
time_t modtime;
#ifdef _WIN32
uint32_t uid;

View file

@ -183,6 +183,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
if( !c_streq(cur->file_id, "") ) {
csync_vio_set_file_id( other->file_id, cur->file_id );
}
other->inode = cur->inode;
cur->instruction = CSYNC_INSTRUCTION_NONE;
} else if (other->instruction == CSYNC_INSTRUCTION_REMOVE) {
other->instruction = CSYNC_INSTRUCTION_RENAME;
@ -191,7 +192,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
if( !c_streq(cur->file_id, "") ) {
csync_vio_set_file_id( other->file_id, cur->file_id );
}
other->inode = cur->inode;
cur->instruction = CSYNC_INSTRUCTION_NONE;
} else if (other->instruction == CSYNC_INSTRUCTION_NEW) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "OOOO=> NEW detected in other tree!");

View file

@ -276,6 +276,8 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
/* check if it's a file and has been renamed */
if (ctx->current == LOCAL_REPLICA) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode);
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
/* translate the file type between the two stat types csync has. */

View file

@ -292,6 +292,8 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
item._modtime = file->modtime;
item._etag = file->etag;
item._size = file->size;
item._inode = file->inode;
item._should_update_etag = file->should_update_etag;
switch( file->type ) {
case CSYNC_FTW_TYPE_DIR:

View file

@ -83,6 +83,7 @@ public:
time_t _modtime;
QByteArray _etag;
quint64 _size;
quint64 _inode;
bool _should_update_etag;
QByteArray _fileId;
bool _blacklistedInDb;

View file

@ -36,15 +36,20 @@ SyncJournalFileRecord::SyncJournalFileRecord(const SyncFileItem &item, const QSt
_type(item._type), _etag(item._etag), _fileId(item._fileId),
_uid(0), _gid(0), _mode(0)
{
// use the "old" inode coming with the item for the case where the
// filesystem stat fails. That can happen if the the file was removed
// or renamed meanwhile. For the rename case we still need the inode to
// detect the rename tough.
_inode = item._inode;
// Query the inode:
// based on code from csync_vio_local.c (csync_vio_local_stat)
#ifdef Q_OS_WIN
/* Get the Windows file id as an inode replacement. */
/* Query the inode:
based on code from csync_vio_local.c (csync_vio_local_stat)
Get the Windows file id as an inode replacement. */
HANDLE h = CreateFileW( (wchar_t*)localFileName.utf16(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS, NULL );
if( h == INVALID_HANDLE_VALUE ) {
_inode = 0;
qWarning() << "Failed to query the 'inode' because CreateFileW failed for file " << localFileName;
} else {
BY_HANDLE_FILE_INFORMATION fileInfo;
@ -60,7 +65,7 @@ SyncJournalFileRecord::SyncJournalFileRecord(const SyncFileItem &item, const QSt
_inode = FileIndex.QuadPart;
} else {
qWarning() << "Failed to query the 'inode' for file " << localFileName;
_inode = 0;
}
CloseHandle(h);
}
@ -68,7 +73,6 @@ SyncJournalFileRecord::SyncJournalFileRecord(const SyncFileItem &item, const QSt
struct stat sb;
if( stat(QFile::encodeName(localFileName).constData(), &sb) < 0) {
qWarning() << "Failed to query the 'inode' for file " << localFileName;
_inode = 0;
} else {
_inode = sb.st_ino;
}