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 @@ -1103,6 +1104,42 @@ return true; } +#ifndef Q_OS_WIN +bool KFileItem::isHiddenNtfs() const +{ + const auto fileName = localPath().toLocal8Bit().constData(); + constexpr auto attrName = "system.ntfs_attrib_be"; + auto length = getxattr(fileName, attrName, nullptr, 0); + if (length <= 0) { + return false; + } + constexpr size_t xattr_size = 1024; + char strAttr[xattr_size]; + length = getxattr(fileName, 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 + bool KFileItem::isHidden() const { if (!d) { @@ -1119,7 +1156,11 @@ if (fileName.isEmpty()) { // e.g. "trash:/" fileName = d->m_strName; } - return fileName.length() > 1 && fileName[0] == '.'; // Just "." is current directory, not hidden. + auto result = fileName.length() > 1 && fileName[0] == '.'; // Just "." is current directory, not hidden. +#ifndef Q_OS_WIN + result = result || isHiddenNtfs(); +#endif + return result; } void KFileItem::setHidden()