mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 23:28:14 +03:00
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:
parent
370dd99e47
commit
a50c39cd0c
7 changed files with 19 additions and 7 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
time_t _modtime;
|
||||
QByteArray _etag;
|
||||
quint64 _size;
|
||||
quint64 _inode;
|
||||
bool _should_update_etag;
|
||||
QByteArray _fileId;
|
||||
bool _blacklistedInDb;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue