moveToTrash/Unix: use the file's inode number as collision avoidance
Instead of a sequential and thus predictable counter. This improves the performance of when you keep creating and trashing the same file base name. The previous algorithm would try all occurrences from 0 to however many trashings have happened. This could have been any random number, but the source file's inode is "random" enough for us. strace of the second file's trashing: openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/info/tst_qfile.moveToTrashOpenFile.vLwfNe.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = -1 EEXIST (File exists) newfstatat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.vLwfNe", {st_mode=S_IFREG|0644, st_size=16, ...}, 0) = 0 openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/info/tst_qfile.moveToTrashOpenFile.vLwfNe-23527891.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 4 newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=2852, ...}, 0) = 0 write(4, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103 renameat2(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.vLwfNe", AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/files/tst_qfile.moveToTrashOpenFile.vLwfNe-23527891", RENAME_NOREPLACE) = 0 close(4) = 0 Change-Id: I9d43e5b91eb142d6945cfffd1786d73459c2eb3d Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
77c661b275
commit
25b1990784
@ -1418,14 +1418,25 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
|
||||
*/
|
||||
QString uniqueTrashedName = u'/' + sourcePath.fileName();
|
||||
if (!op.tryCreateInfoFile(uniqueTrashedName, error) && error.errorCode == EEXIST) {
|
||||
for (int counter = 0; op.infoFileFd == -1; ++counter) {
|
||||
uniqueTrashedName = QString::asprintf("/%ls-%04d", qUtf16Printable(sourcePath.fileName()),
|
||||
counter);
|
||||
// we'll use a counter, starting with the file's inode number to avoid
|
||||
// collisions
|
||||
qulonglong counter;
|
||||
if (QT_STATBUF st; Q_LIKELY(QT_STAT(source.nativeFilePath(), &st) == 0)) {
|
||||
counter = st.st_ino;
|
||||
} else {
|
||||
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString uniqueTrashBase = std::move(uniqueTrashedName);
|
||||
for (;;) {
|
||||
uniqueTrashedName = QString::asprintf("%ls-%llu", qUtf16Printable(uniqueTrashBase),
|
||||
counter++);
|
||||
if (op.tryCreateInfoFile(uniqueTrashedName, error))
|
||||
break;
|
||||
if (error.errorCode != EEXIST)
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
QByteArray info =
|
||||
|
Loading…
Reference in New Issue
Block a user