File indexing completed on 2024-05-19 03:56:20
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2011 David Faure <faure@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only 0007 */ 0008 0009 #include "kfilesystemtype.h" 0010 #include "knetworkmounts.h" 0011 0012 #include <config-kfilesystemtype.h> 0013 #if HAVE_UDEV 0014 #include <libudev.h> 0015 #endif 0016 0017 #include <QCoreApplication> 0018 #include <QFile> 0019 0020 #include <array> 0021 0022 struct FsInfo { 0023 KFileSystemType::Type type = KFileSystemType::Unknown; 0024 const char *name = nullptr; 0025 }; 0026 0027 static const std::array<FsInfo, 19> s_fsMap = {{ 0028 {KFileSystemType::Nfs, "nfs"}, 0029 {KFileSystemType::Smb, "smb"}, 0030 {KFileSystemType::Fat, "fat"}, 0031 {KFileSystemType::Ramfs, "ramfs"}, 0032 {KFileSystemType::Other, "other"}, 0033 {KFileSystemType::Ntfs, "ntfs"}, 0034 {KFileSystemType::Ntfs, "ntfs3"}, 0035 {KFileSystemType::Exfat, "exfat"}, 0036 {KFileSystemType::Unknown, "unknown"}, 0037 {KFileSystemType::Nfs, "autofs"}, 0038 {KFileSystemType::Nfs, "cachefs"}, 0039 {KFileSystemType::Nfs, "fuse.sshfs"}, 0040 {KFileSystemType::Nfs, "xtreemfs@"}, // #178678 0041 {KFileSystemType::Smb, "smbfs"}, 0042 {KFileSystemType::Smb, "cifs"}, 0043 {KFileSystemType::Fat, "vfat"}, 0044 {KFileSystemType::Fat, "msdos"}, 0045 {KFileSystemType::Fuse, "fuseblk"}, 0046 }}; 0047 0048 #ifndef Q_OS_WIN 0049 inline KFileSystemType::Type kde_typeFromName(const QLatin1String name) 0050 { 0051 auto it = std::find_if(s_fsMap.cbegin(), s_fsMap.cend(), [name](const auto &fsInfo) { 0052 return QLatin1String(fsInfo.name) == name; 0053 }); 0054 return it != s_fsMap.cend() ? it->type : KFileSystemType::Other; 0055 } 0056 0057 inline KFileSystemType::Type kde_typeFromName(const char *c) 0058 { 0059 return kde_typeFromName(QLatin1String(c)); 0060 } 0061 0062 #if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD) 0063 #include <sys/mount.h> 0064 #include <sys/param.h> 0065 0066 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path) 0067 { 0068 struct statfs buf; 0069 if (statfs(path.constData(), &buf) != 0) { 0070 return KFileSystemType::Unknown; 0071 } 0072 return kde_typeFromName(buf.f_fstypename); 0073 } 0074 0075 #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) 0076 #include <sys/statfs.h> 0077 0078 #ifdef Q_OS_LINUX 0079 #include <linux/magic.h> // A lot of the filesystem superblock MAGIC numbers 0080 #include <sys/stat.h> 0081 #endif 0082 0083 // Add known missig magics 0084 // Can use https://github.com/systemd/systemd/blob/main/src/basic/missing_magic.h 0085 // as reference 0086 0087 // From linux/fs/ntfs/ntfs.h 0088 #ifndef NTFS_SB_MAGIC 0089 #define NTFS_SB_MAGIC 0x5346544e 0090 #endif 0091 0092 // From linux/fs/ntfs3/super.c 0093 #ifndef NTFS3_MAGIC 0094 #define NTFS3_MAGIC 0x7366746E 0095 #endif 0096 0097 // From linux/fs/exfat/exfat_fs.h 0098 #ifndef EXFAT_SUPER_MAGIC 0099 #define EXFAT_SUPER_MAGIC 0x2011BAB0UL 0100 #endif 0101 0102 // From linux/fs/cifs/smb2glob.h 0103 #ifndef SMB2_MAGIC_NUMBER 0104 #define SMB2_MAGIC_NUMBER 0xFE534D42 0105 #endif 0106 0107 // From linux/fs/cifs/cifsglob.h 0108 #ifndef CIFS_MAGIC_NUMBER 0109 #define CIFS_MAGIC_NUMBER 0xFF534D42 0110 #endif 0111 0112 // From linux/fs/fuse/inode.c 0113 #ifndef FUSE_SUPER_MAGIC 0114 #define FUSE_SUPER_MAGIC 0x65735546 0115 #endif 0116 0117 #ifndef AUTOFSNG_SUPER_MAGIC 0118 #define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0 0119 #endif 0120 0121 #ifdef Q_OS_HURD 0122 #ifndef NFS_SUPER_MAGIC 0123 #define NFS_SUPER_MAGIC 0x00006969 0124 #endif 0125 #ifndef AUTOFS_SUPER_MAGIC 0126 #define AUTOFS_SUPER_MAGIC 0x00000187 0127 #endif 0128 #ifndef MSDOS_SUPER_MAGIC 0129 #define MSDOS_SUPER_MAGIC 0x00004d44 0130 #endif 0131 #ifndef SMB_SUPER_MAGIC 0132 #define SMB_SUPER_MAGIC 0x0000517B 0133 #endif 0134 #ifndef RAMFS_MAGIC 0135 #define RAMFS_MAGIC 0x858458F6 0136 #endif 0137 #endif 0138 0139 KFileSystemType::Type probeFuseBlkType(const QByteArray &path) 0140 { 0141 using namespace KFileSystemType; 0142 0143 #if HAVE_UDEV 0144 struct stat buf; 0145 if (stat(path.constData(), &buf) != 0) { 0146 return Fuse; 0147 } 0148 0149 using UdevPtr = std::unique_ptr<struct udev, decltype(&udev_unref)>; 0150 using UDevicePtr = std::unique_ptr<struct udev_device, decltype(&udev_device_unref)>; 0151 0152 // Code originally copied from util-linux/misc-utils/lsblk.c 0153 auto udevP = UdevPtr(udev_new(), udev_unref); 0154 if (!udevP) { 0155 return Fuse; 0156 } 0157 0158 // 'b' for block devices 0159 auto devPtr = UDevicePtr(udev_device_new_from_devnum(udevP.get(), 'b', buf.st_dev), udev_device_unref); 0160 if (!devPtr) { 0161 // If is not block device, assume conservatively it is a remote FS under FUSE. 0162 return Nfs; 0163 } 0164 0165 const QLatin1String fsType(udev_device_get_property_value(devPtr.get(), "ID_FS_TYPE")); 0166 return kde_typeFromName(fsType); 0167 #endif 0168 0169 return Fuse; 0170 } 0171 0172 // Reverse-engineering without C++ code: 0173 // strace stat -f /mnt 2>&1|grep statfs|grep mnt, and look for f_type 0174 // 0175 // Also grep'ing in /usr/src/<kernel-version>/fs/ 0176 0177 static KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path) 0178 { 0179 struct statfs buf; 0180 if (statfs(path.constData(), &buf) != 0) { 0181 return KFileSystemType::Unknown; 0182 } 0183 0184 switch (static_cast<unsigned long>(buf.f_type)) { 0185 case NFS_SUPER_MAGIC: 0186 case AUTOFS_SUPER_MAGIC: 0187 case AUTOFSNG_SUPER_MAGIC: 0188 return KFileSystemType::Nfs; 0189 case FUSE_SUPER_MAGIC: 0190 return probeFuseBlkType(path); 0191 case SMB_SUPER_MAGIC: 0192 case SMB2_MAGIC_NUMBER: 0193 case CIFS_MAGIC_NUMBER: 0194 return KFileSystemType::Smb; 0195 case MSDOS_SUPER_MAGIC: 0196 return KFileSystemType::Fat; 0197 case NTFS_SB_MAGIC: 0198 case NTFS3_MAGIC: 0199 return KFileSystemType::Ntfs; 0200 case EXFAT_SUPER_MAGIC: 0201 return KFileSystemType::Exfat; 0202 case RAMFS_MAGIC: 0203 return KFileSystemType::Ramfs; 0204 default: 0205 return KFileSystemType::Other; 0206 } 0207 } 0208 0209 #elif defined(Q_OS_AIX) || defined(Q_OS_HPUX) || defined(Q_OS_QNX) || defined(Q_OS_SCO) || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) \ 0210 || defined(Q_OS_NETBSD) 0211 #include <sys/statvfs.h> 0212 0213 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path) 0214 { 0215 struct statvfs buf; 0216 if (statvfs(path.constData(), &buf) != 0) { 0217 return KFileSystemType::Unknown; 0218 } 0219 #if defined(Q_OS_NETBSD) 0220 return kde_typeFromName(buf.f_fstypename); 0221 #else 0222 return kde_typeFromName(buf.f_basetype); 0223 #endif 0224 } 0225 #endif 0226 #else 0227 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path) 0228 { 0229 return KFileSystemType::Unknown; 0230 } 0231 #endif 0232 0233 KFileSystemType::Type KFileSystemType::fileSystemType(const QString &path) 0234 { 0235 if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::SmbPaths)) { 0236 return KFileSystemType::Smb; 0237 } else if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::NfsPaths)) { 0238 return KFileSystemType::Nfs; 0239 } else { 0240 return determineFileSystemTypeImpl(QFile::encodeName(path)); 0241 } 0242 } 0243 0244 QString KFileSystemType::fileSystemName(KFileSystemType::Type type) 0245 { 0246 switch (type) { 0247 case KFileSystemType::Nfs: 0248 return QCoreApplication::translate("KFileSystemType", "NFS"); 0249 case KFileSystemType::Smb: 0250 return QCoreApplication::translate("KFileSystemType", "SMB"); 0251 case KFileSystemType::Fat: 0252 return QCoreApplication::translate("KFileSystemType", "FAT"); 0253 case KFileSystemType::Ramfs: 0254 return QCoreApplication::translate("KFileSystemType", "RAMFS"); 0255 case KFileSystemType::Other: 0256 return QCoreApplication::translate("KFileSystemType", "Other"); 0257 case KFileSystemType::Ntfs: 0258 return QCoreApplication::translate("KFileSystemType", "NTFS"); 0259 case KFileSystemType::Exfat: 0260 return QCoreApplication::translate("KFileSystemType", "ExFAT"); 0261 case KFileSystemType::Fuse: 0262 return QCoreApplication::translate("KFileSystemType", "FUSE"); 0263 case KFileSystemType::Unknown: 0264 return QCoreApplication::translate("KFileSystemType", "Unknown"); 0265 } 0266 0267 Q_UNREACHABLE(); 0268 return {}; 0269 }