1 /*
2 This file is part of the KDE libraries
3
4 SPDX-FileCopyrightText: 2011 David Faure <faure@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-only
7 */
8
9 #include "kfilesystemtype.h"
10 #include "kcoreaddons_debug.h"
11 #include "knetworkmounts.h"
12
13 #include <QCoreApplication>
14 #include <QFile>
15
16 #ifndef Q_OS_WIN
kde_typeFromName(const char * name)17 inline KFileSystemType::Type kde_typeFromName(const char *name)
18 {
19 /* clang-format off */
20 if (qstrncmp(name, "nfs", 3) == 0
21 || qstrncmp(name, "autofs", 6) == 0
22 || qstrncmp(name, "cachefs", 7) == 0
23 || qstrncmp(name, "fuse.sshfs", 10) == 0
24 || qstrncmp(name, "xtreemfs@", 9) == 0) { // #178678
25
26 return KFileSystemType::Nfs;
27 }
28 if (qstrncmp(name, "fat", 3) == 0
29 || qstrncmp(name, "vfat", 4) == 0
30 || qstrncmp(name, "msdos", 5) == 0) {
31 return KFileSystemType::Fat;
32 }
33 if (qstrncmp(name, "cifs", 4) == 0
34 || qstrncmp(name, "smbfs", 5) == 0) {
35 return KFileSystemType::Smb;
36 }
37 if (qstrncmp(name, "ramfs", 5) == 0) {
38 return KFileSystemType::Ramfs;
39 }
40 /* clang-format on */
41
42 return KFileSystemType::Other;
43 }
44
45 #if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
46 #include <sys/mount.h>
47 #include <sys/param.h>
48
determineFileSystemTypeImpl(const QByteArray & path)49 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
50 {
51 struct statfs buf;
52 if (statfs(path.constData(), &buf) != 0) {
53 return KFileSystemType::Unknown;
54 }
55 return kde_typeFromName(buf.f_fstypename);
56 }
57
58 #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
59 #include <sys/statfs.h>
60
61 #ifdef Q_OS_LINUX
62 #include <linux/magic.h> // A lot of the filesystem superblock MAGIC numbers
63 #endif
64
65 // From /usr/src/linux-5.13.2-1-vanilla/fs/ntfs/ntfs.h
66 #ifndef NTFS_SB_MAGIC
67 #define NTFS_SB_MAGIC 0x5346544e
68 #endif
69
70 // From /usr/src/linux-5.13.2-1-vanilla/fs/exfat/exfat_fs.h
71 #ifndef EXFAT_SUPER_MAGIC
72 #define EXFAT_SUPER_MAGIC 0x2011BAB0UL
73 #endif
74
75 // From /usr/src/linux-5.13.2-1-vanilla/fs/cifs/smb2glob.h
76 #ifndef SMB2_MAGIC_NUMBER
77 #define SMB2_MAGIC_NUMBER 0xFE534D42
78 #endif
79
80 // From /usr/src/linux-5.13.2-1-vanilla/fs/cifs/cifsglob.h
81 #ifndef CIFS_MAGIC_NUMBER
82 #define CIFS_MAGIC_NUMBER 0xFF534D42
83 #endif
84
85 // From /usr/src/linux-5.13.2-1-vanilla/fs/fuse/inode.c
86 #ifndef FUSE_SUPER_MAGIC
87 #define FUSE_SUPER_MAGIC 0x65735546
88 #endif
89
90 #ifndef AUTOFSNG_SUPER_MAGIC
91 #define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
92 #endif
93
94 #ifdef Q_OS_HURD
95 #ifndef NFS_SUPER_MAGIC
96 #define NFS_SUPER_MAGIC 0x00006969
97 #endif
98 #ifndef AUTOFS_SUPER_MAGIC
99 #define AUTOFS_SUPER_MAGIC 0x00000187
100 #endif
101 #ifndef MSDOS_SUPER_MAGIC
102 #define MSDOS_SUPER_MAGIC 0x00004d44
103 #endif
104 #ifndef SMB_SUPER_MAGIC
105 #define SMB_SUPER_MAGIC 0x0000517B
106 #endif
107 #ifndef RAMFS_MAGIC
108 #define RAMFS_MAGIC 0x858458F6
109 #endif
110 #endif
111
112 // Reverse-engineering without C++ code:
113 // strace stat -f /mnt 2>&1|grep statfs|grep mnt, and look for f_type
114 //
115 // Also grep'ing in /usr/src/<kernel-version>/fs/
116
determineFileSystemTypeImpl(const QByteArray & path)117 static KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
118 {
119 struct statfs buf;
120 if (statfs(path.constData(), &buf) != 0) {
121 return KFileSystemType::Unknown;
122 }
123
124 switch (static_cast<unsigned long>(buf.f_type)) {
125 case NFS_SUPER_MAGIC:
126 case AUTOFS_SUPER_MAGIC:
127 case AUTOFSNG_SUPER_MAGIC:
128 case FUSE_SUPER_MAGIC: // TODO could be anything. Need to use statfs() to find out more.
129 return KFileSystemType::Nfs;
130 case SMB_SUPER_MAGIC:
131 case SMB2_MAGIC_NUMBER:
132 case CIFS_MAGIC_NUMBER:
133 return KFileSystemType::Smb;
134 case MSDOS_SUPER_MAGIC:
135 return KFileSystemType::Fat;
136 case NTFS_SB_MAGIC:
137 return KFileSystemType::Ntfs;
138 case EXFAT_SUPER_MAGIC:
139 return KFileSystemType::Exfat;
140 case RAMFS_MAGIC:
141 return KFileSystemType::Ramfs;
142 default:
143 return KFileSystemType::Other;
144 }
145 }
146
147 #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) \
148 || defined(Q_OS_NETBSD)
149 #include <sys/statvfs.h>
150
determineFileSystemTypeImpl(const QByteArray & path)151 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
152 {
153 struct statvfs buf;
154 if (statvfs(path.constData(), &buf) != 0) {
155 return KFileSystemType::Unknown;
156 }
157 #if defined(Q_OS_NETBSD)
158 return kde_typeFromName(buf.f_fstypename);
159 #else
160 return kde_typeFromName(buf.f_basetype);
161 #endif
162 }
163 #endif
164 #else
determineFileSystemTypeImpl(const QByteArray & path)165 KFileSystemType::Type determineFileSystemTypeImpl(const QByteArray &path)
166 {
167 return KFileSystemType::Unknown;
168 }
169 #endif
170
fileSystemType(const QString & path)171 KFileSystemType::Type KFileSystemType::fileSystemType(const QString &path)
172 {
173 if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::SmbPaths)) {
174 return KFileSystemType::Smb;
175 } else if (KNetworkMounts::self()->isSlowPath(path, KNetworkMounts::KNetworkMountsType::NfsPaths)) {
176 return KFileSystemType::Nfs;
177 } else {
178 return determineFileSystemTypeImpl(QFile::encodeName(path));
179 }
180 }
181
fileSystemName(KFileSystemType::Type type)182 QString KFileSystemType::fileSystemName(KFileSystemType::Type type)
183 {
184 switch (type) {
185 case KFileSystemType::Nfs:
186 return QCoreApplication::translate("KFileSystemType", "NFS");
187 case KFileSystemType::Smb:
188 return QCoreApplication::translate("KFileSystemType", "SMB");
189 case KFileSystemType::Fat:
190 return QCoreApplication::translate("KFileSystemType", "FAT");
191 case KFileSystemType::Ramfs:
192 return QCoreApplication::translate("KFileSystemType", "RAMFS");
193 case KFileSystemType::Other:
194 return QCoreApplication::translate("KFileSystemType", "Other");
195 case KFileSystemType::Ntfs:
196 return QCoreApplication::translate("KFileSystemType", "NTFS");
197 case KFileSystemType::Exfat:
198 return QCoreApplication::translate("KFileSystemType", "ExFAT");
199 case KFileSystemType::Unknown:
200 return QCoreApplication::translate("KFileSystemType", "Unknown");
201 }
202
203 Q_UNREACHABLE();
204 return {};
205 }
206