diff --git a/src/ioslaves/file/CMakeLists.txt b/src/ioslaves/file/CMakeLists.txt --- a/src/ioslaves/file/CMakeLists.txt +++ b/src/ioslaves/file/CMakeLists.txt @@ -2,13 +2,16 @@ project(kioslave-file) include(ConfigureChecks.cmake) +include(CheckFunctionExists) ########### next target ############### if(WIN32) set(kio_file_PART_SRCS file.cpp file_win.cpp ) else() set(kio_file_PART_SRCS file.cpp file_unix.cpp fdreceiver.cpp ) + check_function_exists(statx HAVE_STATX) + set(HAVE_STATX ${HAVE_STATX}) endif() find_package(ACL) diff --git a/src/ioslaves/file/config-kioslave-file.h.cmake b/src/ioslaves/file/config-kioslave-file.h.cmake --- a/src/ioslaves/file/config-kioslave-file.h.cmake +++ b/src/ioslaves/file/config-kioslave-file.h.cmake @@ -13,3 +13,5 @@ /* Defined if system has extended file attributes support. */ #cmakedefine01 HAVE_SYS_XATTR_H +/* Defined if the statx() system call is available */ +#cmakedefine01 HAVE_STATX diff --git a/src/ioslaves/file/file.cpp b/src/ioslaves/file/file.cpp --- a/src/ioslaves/file/file.cpp +++ b/src/ioslaves/file/file.cpp @@ -77,6 +77,18 @@ #include #include +#if HAVE_STATX +// Since there's no glibc wrapper for statx() yet, we have to make the system call +// by hand +#include // AT_SYMLINK_NOFOLLOW constant comes from here +#include +#include +// 332 on my system +#define STAT(path, buf) syscall(__NR_statx,(AT_FDCWD),(path),(AT_SYMLINK_NOFOLLOW),(0),(buf)) +#else +#define STAT(path, buf) QT_LSTAT(path, buf) +#endif + Q_LOGGING_CATEGORY(KIO_FILE, "kf5.kio.kio_file") // Pseudo plugin class to embed meta data @@ -264,7 +276,7 @@ { const QString path(url.toLocalFile()); QT_STATBUF statbuf; - if (QT_LSTAT(QFile::encodeName(path).constData(), &statbuf) == 0) { + if (STAT(QFile::encodeName(path).constData(), &statbuf) == 0) { struct utimbuf utbuf; utbuf.actime = statbuf.st_atime; // access time, unchanged utbuf.modtime = mtime.toTime_t(); // modification time @@ -297,7 +309,7 @@ } QT_STATBUF buff; - if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { + if (STAT(QFile::encodeName(path).constData(), &buff) == -1) { bool dirCreated = QDir().mkdir(path); if (!dirCreated) { if (auto err = execWithElevatedPrivilege(MKDIR, {path}, errno)) { @@ -572,13 +584,13 @@ QString dest_part(dest_orig + QLatin1String(".part")); QT_STATBUF buff_orig; - const bool bOrigExists = (QT_LSTAT(QFile::encodeName(dest_orig).constData(), &buff_orig) != -1); + const bool bOrigExists = (STAT(QFile::encodeName(dest_orig).constData(), &buff_orig) != -1); bool bPartExists = false; const bool bMarkPartial = config()->readEntry("MarkPartial", true); if (bMarkPartial) { QT_STATBUF buff_part; - bPartExists = (QT_LSTAT(QFile::encodeName(dest_part).constData(), &buff_part) != -1); + bPartExists = (STAT(QFile::encodeName(dest_part).constData(), &buff_part) != -1); if (bPartExists && !(_flags & KIO::Resume) && !(_flags & KIO::Overwrite) && buff_part.st_size > 0 && ((buff_part.st_mode & QT_STAT_MASK) == QT_STAT_REG)) { // qDebug() << "calling canResume with" << KIO::number(buff_part.st_size); @@ -840,7 +852,7 @@ mode_t access; QT_STATBUF buff; - if (QT_LSTAT(path.data(), &buff) == 0) { + if (STAT(path.data(), &buff) == 0) { if (details > 2) { entry.insert(KIO::UDSEntry::UDS_DEVICE_ID, buff.st_dev); @@ -935,6 +947,13 @@ entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, buff.__st_birthtime); } #endif +#ifdef stx_btime + /* As above, but it's called "stx_btime" in Linux kernel 4.11+ + * where statx() is available */ + if (buff.stx_btime > 0) { + entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, buff.stx_btime); + } +#endif } // Note: buff.st_ctime isn't the creation time !