KCoreAddons

kfilesystemtype.cpp
1 /*
2  This file is part of the KDE libraries
3 
4  SPDX-FileCopyrightText: 2011 David Faure <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.1-only
7 */
8 
9 #include "kfilesystemtype.h"
10 #include "knetworkmounts.h"
11 
12 #include <config-kfilesystemtype.h>
13 #if HAVE_UDEV
14 #include <libudev.h>
15 #endif
16 
17 #include <QCoreApplication>
18 #include <QFile>
19 
20 #include <array>
21 
22 struct FsInfo {
23  KFileSystemType::Type type = KFileSystemType::Unknown;
24  const char *name = nullptr;
25 };
26 
27 static const std::array<FsInfo, 18> s_fsMap = {{
28  {KFileSystemType::Nfs, "nfs"},
29  {KFileSystemType::Smb, "smb"},
30  {KFileSystemType::Fat, "fat"},
31  {KFileSystemType::Ramfs, "ramfs"},
32  {KFileSystemType::Other, "other"},
33  {KFileSystemType::Ntfs, "ntfs"},
34  {KFileSystemType::Exfat, "exfat"},
35  {KFileSystemType::Unknown, "unknown"},
36  {KFileSystemType::Nfs, "autofs"},
37  {KFileSystemType::Nfs, "cachefs"},
38  {KFileSystemType::Nfs, "fuse.sshfs"},
40  {KFileSystemType::Smb, "smbfs"},
41  {KFileSystemType::Smb, "cifs"},
42  {KFileSystemType::Fat, "vfat"},
43  {KFileSystemType::Fat, "msdos"},
44  {KFileSystemType::Fuse, "fuseblk"},
45 }};
46 
47 #ifndef Q_OS_WIN
48 inline KFileSystemType::Type kde_typeFromName(const QLatin1String name)
49 {
50  auto it = std::find_if(s_fsMap.cbegin(), s_fsMap.cend(), [name](const auto &fsInfo) {
51  return QLatin1String(fsInfo.name) == name;
52  });
53  return it != s_fsMap.cend() ? it->type : KFileSystemType::Other;
54 }
55 
56 inline KFileSystemType::Type kde_typeFromName(const char *c)
57 {
58  return kde_typeFromName(QLatin1String(c));
59 }
60 
61 #if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
62 #include <sys/mount.h>
63 #include <sys/param.h>
64 
65 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
66 {
67  struct statfs buf;
68  if (statfs(path.constData(), &buf) != 0) {
69  return KFileSystemType::Unknown;
70  }
71  return kde_typeFromName(buf.f_fstypename);
72 }
73 
74 #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
75 #include <sys/statfs.h>
76 
77 #ifdef Q_OS_LINUX
78 #include <linux/magic.h> // A lot of the filesystem superblock MAGIC numbers
79 #include <sys/stat.h>
80 #endif
81 
82 // From /usr/src/linux-5.13.2-1-vanilla/fs/ntfs/ntfs.h
83 #ifndef NTFS_SB_MAGIC
84 #define NTFS_SB_MAGIC 0x5346544e
85 #endif
86 
87 // From /usr/src/linux-5.13.2-1-vanilla/fs/exfat/exfat_fs.h
88 #ifndef EXFAT_SUPER_MAGIC
89 #define EXFAT_SUPER_MAGIC 0x2011BAB0UL
90 #endif
91 
92 // From /usr/src/linux-5.13.2-1-vanilla/fs/cifs/smb2glob.h
93 #ifndef SMB2_MAGIC_NUMBER
94 #define SMB2_MAGIC_NUMBER 0xFE534D42
95 #endif
96 
97 // From /usr/src/linux-5.13.2-1-vanilla/fs/cifs/cifsglob.h
98 #ifndef CIFS_MAGIC_NUMBER
99 #define CIFS_MAGIC_NUMBER 0xFF534D42
100 #endif
101 
102 // From /usr/src/linux-5.13.2-1-vanilla/fs/fuse/inode.c
103 #ifndef FUSE_SUPER_MAGIC
104 #define FUSE_SUPER_MAGIC 0x65735546
105 #endif
106 
107 #ifndef AUTOFSNG_SUPER_MAGIC
108 #define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
109 #endif
110 
111 #ifdef Q_OS_HURD
112 #ifndef NFS_SUPER_MAGIC
113 #define NFS_SUPER_MAGIC 0x00006969
114 #endif
115 #ifndef AUTOFS_SUPER_MAGIC
116 #define AUTOFS_SUPER_MAGIC 0x00000187
117 #endif
118 #ifndef MSDOS_SUPER_MAGIC
119 #define MSDOS_SUPER_MAGIC 0x00004d44
120 #endif
121 #ifndef SMB_SUPER_MAGIC
122 #define SMB_SUPER_MAGIC 0x0000517B
123 #endif
124 #ifndef RAMFS_MAGIC
125 #define RAMFS_MAGIC 0x858458F6
126 #endif
127 #endif
128 
129 KFileSystemType::Type probeFuseBlkType(const QByteArray &path)
130 {
131  using namespace KFileSystemType;
132 
133 #if HAVE_UDEV
134  struct stat buf;
135  if (stat(path.constData(), &buf) != 0) {
136  return Fuse;
137  }
138 
139  using UdevPtr = std::unique_ptr<struct udev, decltype(&udev_unref)>;
140  using UDevicePtr = std::unique_ptr<struct udev_device, decltype(&udev_device_unref)>;
141 
142  // Code originally copied from util-linux/misc-utils/lsblk.c
143  auto udevP = UdevPtr(udev_new(), udev_unref);
144  if (!udevP) {
145  return Fuse;
146  }
147 
148  // 'b' for block devices
149  auto devPtr = UDevicePtr(udev_device_new_from_devnum(udevP.get(), 'b', buf.st_dev), udev_device_unref);
150  if (!devPtr) {
151  return Fuse;
152  }
153 
154  const QLatin1String fsType(udev_device_get_property_value(devPtr.get(), "ID_FS_TYPE"));
155  return kde_typeFromName(fsType);
156 #endif
157 
158  return Fuse;
159 }
160 
161 // Reverse-engineering without C++ code:
162 // strace stat -f /mnt 2>&1|grep statfs|grep mnt, and look for f_type
163 //
164 // Also grep'ing in /usr/src/<kernel-version>/fs/
165 
166 static KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
167 {
168  struct statfs buf;
169  if (statfs(path.constData(), &buf) != 0) {
170  return KFileSystemType::Unknown;
171  }
172 
173  switch (static_cast<unsigned long>(buf.f_type)) {
174  case NFS_SUPER_MAGIC:
175  case AUTOFS_SUPER_MAGIC:
176  case AUTOFSNG_SUPER_MAGIC:
177  return KFileSystemType::Nfs;
178  case FUSE_SUPER_MAGIC:
179  return probeFuseBlkType(path);
180  case SMB_SUPER_MAGIC:
181  case SMB2_MAGIC_NUMBER:
182  case CIFS_MAGIC_NUMBER:
183  return KFileSystemType::Smb;
184  case MSDOS_SUPER_MAGIC:
185  return KFileSystemType::Fat;
186  case NTFS_SB_MAGIC:
187  return KFileSystemType::Ntfs;
188  case EXFAT_SUPER_MAGIC:
189  return KFileSystemType::Exfat;
190  case RAMFS_MAGIC:
191  return KFileSystemType::Ramfs;
192  default:
193  return KFileSystemType::Other;
194  }
195 }
196 
197 #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) \
198  || defined(Q_OS_NETBSD)
199 #include <sys/statvfs.h>
200 
201 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
202 {
203  struct statvfs buf;
204  if (statvfs(path.constData(), &buf) != 0) {
205  return KFileSystemType::Unknown;
206  }
207 #if defined(Q_OS_NETBSD)
208  return kde_typeFromName(buf.f_fstypename);
209 #else
210  return kde_typeFromName(buf.f_basetype);
211 #endif
212 }
213 #endif
214 #else
215 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
216 {
217  return KFileSystemType::Unknown;
218 }
219 #endif
220 
222 {
223  if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::SmbPaths)) {
224  return KFileSystemType::Smb;
225  } else if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::NfsPaths)) {
226  return KFileSystemType::Nfs;
227  } else {
228  return determineFileSystemTypeImpl(QFile::encodeName(path));
229  }
230 }
231 
233 {
234  switch (type) {
236  return QCoreApplication::translate("KFileSystemType", "NFS");
238  return QCoreApplication::translate("KFileSystemType", "SMB");
240  return QCoreApplication::translate("KFileSystemType", "FAT");
242  return QCoreApplication::translate("KFileSystemType", "RAMFS");
244  return QCoreApplication::translate("KFileSystemType", "Other");
246  return QCoreApplication::translate("KFileSystemType", "NTFS");
248  return QCoreApplication::translate("KFileSystemType", "ExFAT");
250  return QCoreApplication::translate("KFileSystemType", "FUSE");
251  case KFileSystemType::Unknown:
252  return QCoreApplication::translate("KFileSystemType", "Unknown");
253  }
254 
255  Q_UNREACHABLE();
256  return {};
257 }
static KNetworkMounts * self()
Returns (and creates if necessary) the singleton instance.
const QChar * constData() const const
@ Fuse
FUSE (Filesystem in USErspace), this is used for a variety of underlying filesystems.
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
Type type(const QSqlDatabase &db)
QByteArray encodeName(const QString &fileName)
KCOREADDONS_EXPORT Type fileSystemType(const QString &path)
For a given path, returns the filesystem type, one of KFileSystemType::Type values.
@ Exfat
ExFat filesystem.
@ Nfs
NFS or other full-featured networked filesystems (autofs, subfs, cachefs, sshfs)
@ Smb
SMB/CIFS mount (networked but with some FAT-like behavior)
@ Ntfs
NTFS filesystem.
@ Fat
FAT or similar (msdos, FAT, VFAT)
QString path(const QString &relativePath)
Absolute libexec path resolved in relative relation to the current shared object.
Definition: klibexec.h:48
QString name(StandardShortcut id)
@ Ramfs
RAMDISK mount.
KCOREADDONS_EXPORT QString fileSystemName(KFileSystemType::Type type)
Returns the possibly translated name of a filesystem corresponding to a value from KFileSystemType::T...
@ Other
Ext3, Ext4, ReiserFs, and so on. "Normal" local filesystems.
int stat(const QString &path, KDE_struct_stat *buf)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 04:04:52 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.