diff --git a/src/core/kfileitem.h b/src/core/kfileitem.h --- a/src/core/kfileitem.h +++ b/src/core/kfileitem.h @@ -274,6 +274,14 @@ */ bool isWritable() const; +#ifndef Q_OS_WIN // Function uses low level xattr library for extracting extended attributes that is not available on Windows + /** + * Checks whether the file is hidden NTFS file. + * @return true if the file is hidden. + */ + bool isHiddenNtfs() const; +#endif + /** * Checks whether the file is hidden. * @return true if the file is hidden. diff --git a/src/core/kfileitem.cpp b/src/core/kfileitem.cpp --- a/src/core/kfileitem.cpp +++ b/src/core/kfileitem.cpp @@ -41,6 +41,7 @@ #ifndef Q_OS_WIN #include #include +#include #endif #include diff --git a/src/ioslaves/file/file_unix.cpp b/src/ioslaves/file/file_unix.cpp --- a/src/ioslaves/file/file_unix.cpp +++ b/src/ioslaves/file/file_unix.cpp @@ -43,6 +43,8 @@ #include "fdreceiver.h" +#include + //sendfile has different semantics in different platforms #if defined HAVE_SENDFILE && defined Q_OS_LINUX #define USE_SENDFILE 1 @@ -410,6 +412,42 @@ return (QString::compare(url.host(), QLatin1String(hostname), Qt::CaseInsensitive) == 0); } +#ifdef Q_OS_LINUX +bool isNtfsHidden(const QString &filename) +{ + constexpr auto attrName = "system.ntfs_attrib_be"; + auto length = getxattr(filename.toLocal8Bit().data(), attrName, nullptr, 0); + if (length <= 0) { + return false; + } + constexpr size_t xattr_size = 1024; + char strAttr[xattr_size]; + length = getxattr(filename.toLocal8Bit().data(), attrName, strAttr, xattr_size); + if (length <= 0) { + return false; + } + + // Decode result to hex string + static const auto digits = "0123456789abcdef"; + auto hexAttr = new char[length * 2 + 4]; + char *c = strAttr, *e = hexAttr; + *e++='0'; *e++ = 'x'; + for (auto n = 0; n < length; n++, c++) { + *e++ = digits[(static_cast(*c) >> 4)]; + *e++ = digits[(static_cast(*c) & 0x0F)]; + } + *e = '\0'; + + // Decode hex string to int + auto intAttr = static_cast(strtol(hexAttr, nullptr, 16)); + delete[] hexAttr; + + constexpr auto FILE_ATTRIBUTE_HIDDEN = 0x2u; + return static_cast(intAttr & FILE_ATTRIBUTE_HIDDEN); +} +#endif + + void FileProtocol::listDir(const QUrl &url) { if (!isLocalFileSameHost(url)) { @@ -506,6 +544,11 @@ } else { if (createUDSEntry(filename, QByteArray(ep->d_name), entry, details)) { +#ifdef Q_OS_LINUX + if (isNtfsHidden(filename)) { + entry.insert(KIO::UDSEntry::UDS_HIDDEN, 1); + } +#endif listEntry(entry); } }