Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qstorageinfo_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
3// Copyright (C) 2016 Intel Corporation.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qstorageinfo_p.h"
7
8#include <QtCore/qfileinfo.h>
9#include <QtCore/qtextstream.h>
10
11#include <QtCore/private/qcore_unix_p.h>
12#include <QtCore/private/qlocale_tools_p.h>
13
14#include <errno.h>
15#include <sys/stat.h>
16
17#if defined(Q_OS_BSD4)
18# include <sys/mount.h>
19# include <sys/statvfs.h>
20#elif defined(Q_OS_HURD)
21# include <mntent.h>
22# include <sys/statvfs.h>
23# include <sys/sysmacros.h>
24#elif defined(Q_OS_SOLARIS)
25# include <sys/mnttab.h>
26# include <sys/statvfs.h>
27#elif defined(Q_OS_HAIKU)
28# include <Directory.h>
29# include <Path.h>
30# include <Volume.h>
31# include <VolumeRoster.h>
32# include <fs_info.h>
33# include <sys/statvfs.h>
34#else
35# include <sys/statvfs.h>
36#endif
37
38#if defined(Q_OS_BSD4)
39# if defined(Q_OS_NETBSD)
40# define QT_STATFSBUF struct statvfs
41# define QT_STATFS ::statvfs
42# else
43# define QT_STATFSBUF struct statfs
44# define QT_STATFS ::statfs
45# endif
46
47# if !defined(ST_RDONLY)
48# define ST_RDONLY MNT_RDONLY
49# endif
50# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
51# define _STATFS_F_FLAGS 1
52# endif
53#elif defined(Q_OS_HAIKU)
54# define QT_STATFSBUF struct statvfs
55# define QT_STATFS ::statvfs
56#else
57# if defined(QT_LARGEFILE_SUPPORT)
58# define QT_STATFSBUF struct statvfs64
59# define QT_STATFS ::statvfs64
60# else
61# define QT_STATFSBUF struct statvfs
62# define QT_STATFS ::statvfs
63# endif // QT_LARGEFILE_SUPPORT
64#endif // Q_OS_BSD4
65
66#if __has_include(<paths.h>)
67# include <paths.h>
68#endif
69#ifndef _PATH_MOUNTED
70# define _PATH_MOUNTED "/etc/mnttab"
71#endif
72
74
75using namespace Qt::StringLiterals;
76
78{
79public:
82
83 inline bool isValid() const;
84 inline bool next();
85 inline QString rootPath() const;
86 inline QByteArray fileSystemType() const;
87 inline QByteArray device() const;
88 inline QByteArray options() const;
89 inline QByteArray subvolume() const;
90private:
91#if defined(Q_OS_BSD4)
92 QT_STATFSBUF *stat_buf;
93 int entryCount;
94 int currentIndex;
95#elif defined(Q_OS_SOLARIS)
96 FILE *fp;
97 mnttab mnt;
98#elif defined(Q_OS_HURD)
99 FILE *fp;
101 mountinfoent mnt;
102#elif defined(Q_OS_HAIKU)
103 BVolumeRoster m_volumeRoster;
104
105 QByteArray m_rootPath;
106 QByteArray m_fileSystemType;
107 QByteArray m_device;
108#endif
109};
110
111#if defined(Q_OS_BSD4)
112
113#ifndef MNT_NOWAIT
114# define MNT_NOWAIT 0
115#endif
116
118 : entryCount(::getmntinfo(&stat_buf, MNT_NOWAIT)),
119 currentIndex(-1)
120{
121}
122
124{
125}
126
127inline bool QStorageIterator::isValid() const
128{
129 return entryCount != -1;
130}
131
132inline bool QStorageIterator::next()
133{
134 return ++currentIndex < entryCount;
135}
136
138{
139 return QFile::decodeName(stat_buf[currentIndex].f_mntonname);
140}
141
143{
144 return QByteArray(stat_buf[currentIndex].f_fstypename);
145}
146
148{
149 return QByteArray(stat_buf[currentIndex].f_mntfromname);
150}
151
153{
154 return QByteArray();
155}
156
158{
159 return QByteArray();
160}
161#elif defined(Q_OS_SOLARIS)
162
164{
165 const int fd = qt_safe_open(_PATH_MOUNTED, O_RDONLY);
166 fp = ::fdopen(fd, "r");
167}
168
170{
171 if (fp)
172 ::fclose(fp);
173}
174
175inline bool QStorageIterator::isValid() const
176{
177 return fp != nullptr;
178}
179
180inline bool QStorageIterator::next()
181{
182 return ::getmntent(fp, &mnt) == 0;
183}
184
186{
187 return QFile::decodeName(mnt.mnt_mountp);
188}
189
191{
192 return QByteArray(mnt.mnt_fstype);
193}
194
196{
197 return QByteArray(mnt.mnt_mntopts);
198}
199
201{
202 return QByteArray();
203}
204
205#elif defined(Q_OS_HURD)
206
207static const int bufferSize = 1024; // 2 paths (mount point+device) and metainfo;
208 // should be enough
209
211 buffer(QByteArray(bufferSize, 0))
212{
213 fp = ::setmntent(_PATH_MOUNTED, "r");
214}
215
217{
218 if (fp)
219 ::endmntent(fp);
220}
221
222inline bool QStorageIterator::isValid() const
223{
224 return fp != nullptr;
225}
226
227inline bool QStorageIterator::next()
228{
229 return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr;
230}
231
233{
234 return QFile::decodeName(mnt.mnt_dir);
235}
236
238{
239 return QByteArray(mnt.mnt_type);
240}
241
243{
244 return QByteArray(mnt.mnt_fsname);
245}
246
248{
249 return QByteArray(mnt.mnt_opts);
250}
251
253{
254 return QByteArray();
255}
256#elif defined(Q_OS_HAIKU)
258{
259}
260
262{
263}
264
265inline bool QStorageIterator::isValid() const
266{
267 return true;
268}
269
270inline bool QStorageIterator::next()
271{
272 BVolume volume;
273
274 if (m_volumeRoster.GetNextVolume(&volume) != B_OK)
275 return false;
276
277 BDirectory directory;
278 if (volume.GetRootDirectory(&directory) != B_OK)
279 return false;
280
281 const BPath path(&directory);
282
283 fs_info fsInfo;
284 memset(&fsInfo, 0, sizeof(fsInfo));
285
286 if (fs_stat_dev(volume.Device(), &fsInfo) != 0)
287 return false;
288
289 m_rootPath = path.Path();
290 m_fileSystemType = QByteArray(fsInfo.fsh_name);
291
292 const QByteArray deviceName(fsInfo.device_name);
293 m_device = (deviceName.isEmpty() ? QByteArray::number(qint32(volume.Device())) : deviceName);
294
295 return true;
296}
297
299{
300 return QFile::decodeName(m_rootPath);
301}
302
304{
305 return m_fileSystemType;
306}
307
309{
310 return m_device;
311}
312
314{
315 return QByteArray();
316}
317
319{
320 return QByteArray();
321}
322
323#else
324
328
332
333inline bool QStorageIterator::isValid() const
334{
335 return false;
336}
337
339{
340 return false;
341}
342
344{
345 return QString();
346}
347
349{
350 return QByteArray();
351}
352
354{
355 return QByteArray();
356}
357
359{
360 return QByteArray();
361}
362
364{
365 return QByteArray();
366}
367#endif
368
370{
371#if defined Q_OS_HAIKU
372 fs_info fsInfo;
373 memset(&fsInfo, 0, sizeof(fsInfo));
374
375 int32 pos = 0;
376 dev_t dev;
377 while ((dev = next_dev(&pos)) >= 0) {
378 if (fs_stat_dev(dev, &fsInfo) != 0)
379 continue;
380
381 if (qstrcmp(fsInfo.device_name, device.constData()) == 0)
382 return QString::fromLocal8Bit(fsInfo.volume_name);
383 }
384#else
386#endif
387
388 return QString();
389}
390
391void QStorageInfoPrivate::doStat()
392{
393 initRootPath();
394 if (rootPath.isEmpty())
395 return;
396
397 retrieveVolumeInfo();
399}
400
401void QStorageInfoPrivate::retrieveVolumeInfo()
402{
403 QT_STATFSBUF statfs_buf;
404 int result;
405 QT_EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
406 if (result == 0) {
407 valid = true;
408 ready = true;
409
410#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) || defined(Q_OS_RTEMS)
411 bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
412 bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
413 bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
414#else
415 bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
416 bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
417 bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
418#endif
419 blockSize = int(statfs_buf.f_bsize);
420#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
421#if defined(_STATFS_F_FLAGS)
422 readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
423#endif
424#else
425 readOnly = (statfs_buf.f_flag & ST_RDONLY) != 0;
426#endif
427 }
428}
429
430void QStorageInfoPrivate::initRootPath()
431{
432 rootPath = QFileInfo(rootPath).canonicalFilePath();
433
434 if (rootPath.isEmpty())
435 return;
436
438 if (!it.isValid()) {
439 rootPath = QStringLiteral("/");
440 return;
441 }
442
443 int maxLength = 0;
444 const QString oldRootPath = rootPath;
445 rootPath.clear();
446
447 while (it.next()) {
448 const QString mountDir = it.rootPath();
449 const QByteArray fsName = it.fileSystemType();
450 // we try to find most suitable entry
451 if (maxLength < mountDir.size() && isParentOf(mountDir, oldRootPath)) {
452 maxLength = mountDir.size();
453 rootPath = mountDir;
454 device = it.device();
455 fileSystemType = fsName;
456 subvolume = it.subvolume();
457 }
458 }
459}
460
461QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
462{
464 if (!it.isValid())
465 return QList<QStorageInfo>() << root();
466
467 QList<QStorageInfo> volumes;
468
469 while (it.next()) {
470 if (!shouldIncludeFs(it.rootPath(), it.fileSystemType()))
471 continue;
472
473 const QString mountDir = it.rootPath();
474 QStorageInfo info(mountDir);
475 info.d->device = it.device();
476 info.d->fileSystemType = it.fileSystemType();
477 info.d->subvolume = it.subvolume();
478 if (info.bytesTotal() <= 0 && info != root())
479 continue;
480 volumes.append(info);
481 }
482
483 return volumes;
484}
485
IOBluetoothDevice * device
\inmodule QtCore
Definition qbytearray.h:57
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QString canonicalFilePath() const
Returns the file system entry's canonical path, including the entry's name, that is,...
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
qsizetype size() const
Definition qset.h:50
\inmodule QtCore
QByteArray device() const
QByteArray subvolume() const
QString rootPath() const
QByteArray options() const
QByteArray fileSystemType() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QString deviceName()
const int blockSize
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
#define QT_EINTR_LOOP(var, cmd)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
GLenum GLuint buffer
GLuint64 GLenum GLint fd
GLuint name
GLsizei maxLength
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
#define ST_RDONLY
static bool shouldIncludeFs(const QString &mountDir, const QByteArray &fsType)
QT_BEGIN_NAMESPACE static Q_LOGGING_CATEGORY(lcStorageInfo, "qt.core.qstorageinfo", QtWarningMsg) class QStorageInfoPrivate bool isParentOf(const String &parent, const QString &dirName)
#define _PATH_MOUNTED
#define QT_STATFS
static QString retrieveLabel(const QByteArray &device)
#define QT_STATFSBUF
#define QStringLiteral(str)
#define fp
#define Q_UNUSED(x)
int qint32
Definition qtypes.h:49
QHostInfo info
[0]