Qt 6.x
The Qt SDK
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/qdiriterator.h>
9#include <QtCore/qfileinfo.h>
10#include <QtCore/qtextstream.h>
11
12#include <QtCore/private/qcore_unix_p.h>
13#include <QtCore/private/qlocale_tools_p.h>
14
15#include <errno.h>
16#include <sys/stat.h>
17
18#if defined(Q_OS_BSD4)
19# include <sys/mount.h>
20# include <sys/statvfs.h>
21#elif defined(Q_OS_HURD)
22# include <mntent.h>
23# include <sys/statvfs.h>
24# include <sys/sysmacros.h>
25#elif defined(Q_OS_SOLARIS)
26# include <sys/mnttab.h>
27# include <sys/statvfs.h>
28#elif defined(Q_OS_HAIKU)
29# include <Directory.h>
30# include <Path.h>
31# include <Volume.h>
32# include <VolumeRoster.h>
33# include <fs_info.h>
34# include <sys/statvfs.h>
35#else
36# include <sys/statvfs.h>
37#endif
38
39#if defined(Q_OS_BSD4)
40# if defined(Q_OS_NETBSD)
41# define QT_STATFSBUF struct statvfs
42# define QT_STATFS ::statvfs
43# else
44# define QT_STATFSBUF struct statfs
45# define QT_STATFS ::statfs
46# endif
47
48# if !defined(ST_RDONLY)
49# define ST_RDONLY MNT_RDONLY
50# endif
51# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
52# define _STATFS_F_FLAGS 1
53# endif
54#elif defined(Q_OS_HAIKU)
55# define QT_STATFSBUF struct statvfs
56# define QT_STATFS ::statvfs
57#else
58# if defined(QT_LARGEFILE_SUPPORT)
59# define QT_STATFSBUF struct statvfs64
60# define QT_STATFS ::statvfs64
61# else
62# define QT_STATFSBUF struct statvfs
63# define QT_STATFS ::statvfs
64# endif // QT_LARGEFILE_SUPPORT
65#endif // Q_OS_BSD4
66
67#if __has_include(<paths.h>)
68# include <paths.h>
69#endif
70#ifndef _PATH_MOUNTED
71# define _PATH_MOUNTED "/etc/mnttab"
72#endif
73
75
76using namespace Qt::StringLiterals;
77
79{
80public:
83
84 inline bool isValid() const;
85 inline bool next();
86 inline QString rootPath() const;
87 inline QByteArray fileSystemType() const;
88 inline QByteArray device() const;
89 inline QByteArray options() const;
90 inline QByteArray subvolume() const;
91private:
92#if defined(Q_OS_BSD4)
93 QT_STATFSBUF *stat_buf;
94 int entryCount;
95 int currentIndex;
96#elif defined(Q_OS_SOLARIS)
97 FILE *fp;
98 mnttab mnt;
99#elif defined(Q_OS_HURD)
100 FILE *fp;
102 mountinfoent mnt;
103#elif defined(Q_OS_HAIKU)
104 BVolumeRoster m_volumeRoster;
105
106 QByteArray m_rootPath;
107 QByteArray m_fileSystemType;
108 QByteArray m_device;
109#endif
110};
111
112#if defined(Q_OS_BSD4)
113
114#ifndef MNT_NOWAIT
115# define MNT_NOWAIT 0
116#endif
117
119 : entryCount(::getmntinfo(&stat_buf, MNT_NOWAIT)),
120 currentIndex(-1)
121{
122}
123
125{
126}
127
128inline bool QStorageIterator::isValid() const
129{
130 return entryCount != -1;
131}
132
133inline bool QStorageIterator::next()
134{
135 return ++currentIndex < entryCount;
136}
137
139{
140 return QFile::decodeName(stat_buf[currentIndex].f_mntonname);
141}
142
144{
145 return QByteArray(stat_buf[currentIndex].f_fstypename);
146}
147
149{
150 return QByteArray(stat_buf[currentIndex].f_mntfromname);
151}
152
154{
155 return QByteArray();
156}
157
159{
160 return QByteArray();
161}
162#elif defined(Q_OS_SOLARIS)
163
165{
166 const int fd = qt_safe_open(_PATH_MOUNTED, O_RDONLY);
167 fp = ::fdopen(fd, "r");
168}
169
171{
172 if (fp)
173 ::fclose(fp);
174}
175
176inline bool QStorageIterator::isValid() const
177{
178 return fp != nullptr;
179}
180
181inline bool QStorageIterator::next()
182{
183 return ::getmntent(fp, &mnt) == 0;
184}
185
187{
188 return QFile::decodeName(mnt.mnt_mountp);
189}
190
192{
193 return QByteArray(mnt.mnt_fstype);
194}
195
197{
198 return QByteArray(mnt.mnt_mntopts);
199}
200
202{
203 return QByteArray();
204}
205
206#elif defined(Q_OS_HURD)
207
208static const int bufferSize = 1024; // 2 paths (mount point+device) and metainfo;
209 // should be enough
210
212 buffer(QByteArray(bufferSize, 0))
213{
214 fp = ::setmntent(_PATH_MOUNTED, "r");
215}
216
218{
219 if (fp)
220 ::endmntent(fp);
221}
222
223inline bool QStorageIterator::isValid() const
224{
225 return fp != nullptr;
226}
227
228inline bool QStorageIterator::next()
229{
230 return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr;
231}
232
234{
235 return QFile::decodeName(mnt.mnt_dir);
236}
237
239{
240 return QByteArray(mnt.mnt_type);
241}
242
244{
245 return QByteArray(mnt.mnt_fsname);
246}
247
249{
250 return QByteArray(mnt.mnt_opts);
251}
252
254{
255 return QByteArray();
256}
257#elif defined(Q_OS_HAIKU)
259{
260}
261
263{
264}
265
266inline bool QStorageIterator::isValid() const
267{
268 return true;
269}
270
271inline bool QStorageIterator::next()
272{
273 BVolume volume;
274
275 if (m_volumeRoster.GetNextVolume(&volume) != B_OK)
276 return false;
277
278 BDirectory directory;
279 if (volume.GetRootDirectory(&directory) != B_OK)
280 return false;
281
282 const BPath path(&directory);
283
284 fs_info fsInfo;
285 memset(&fsInfo, 0, sizeof(fsInfo));
286
287 if (fs_stat_dev(volume.Device(), &fsInfo) != 0)
288 return false;
289
290 m_rootPath = path.Path();
291 m_fileSystemType = QByteArray(fsInfo.fsh_name);
292
293 const QByteArray deviceName(fsInfo.device_name);
294 m_device = (deviceName.isEmpty() ? QByteArray::number(qint32(volume.Device())) : deviceName);
295
296 return true;
297}
298
300{
301 return QFile::decodeName(m_rootPath);
302}
303
305{
306 return m_fileSystemType;
307}
308
310{
311 return m_device;
312}
313
315{
316 return QByteArray();
317}
318
320{
321 return QByteArray();
322}
323
324#else
325
327{
328}
329
331{
332}
333
334inline bool QStorageIterator::isValid() const
335{
336 return false;
337}
338
340{
341 return false;
342}
343
345{
346 return QString();
347}
348
350{
351 return QByteArray();
352}
353
355{
356 return QByteArray();
357}
358
360{
361 return QByteArray();
362}
363
365{
366 return QByteArray();
367}
368#endif
369
371{
372#if defined Q_OS_HAIKU
373 fs_info fsInfo;
374 memset(&fsInfo, 0, sizeof(fsInfo));
375
376 int32 pos = 0;
377 dev_t dev;
378 while ((dev = next_dev(&pos)) >= 0) {
379 if (fs_stat_dev(dev, &fsInfo) != 0)
380 continue;
381
382 if (qstrcmp(fsInfo.device_name, device.constData()) == 0)
383 return QString::fromLocal8Bit(fsInfo.volume_name);
384 }
385#else
387#endif
388
389 return QString();
390}
391
392void QStorageInfoPrivate::doStat()
393{
394 initRootPath();
395 if (rootPath.isEmpty())
396 return;
397
398 retrieveVolumeInfo();
400}
401
402void QStorageInfoPrivate::retrieveVolumeInfo()
403{
404 QT_STATFSBUF statfs_buf;
405 int result;
406 EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
407 if (result == 0) {
408 valid = true;
409 ready = true;
410
411#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) || defined(Q_OS_RTEMS)
412 bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
413 bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
414 bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
415#else
416 bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
417 bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
418 bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
419#endif
420 blockSize = statfs_buf.f_bsize;
421#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
422#if defined(_STATFS_F_FLAGS)
423 readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
424#endif
425#else
426 readOnly = (statfs_buf.f_flag & ST_RDONLY) != 0;
427#endif
428 }
429}
430
431void QStorageInfoPrivate::initRootPath()
432{
433 rootPath = QFileInfo(rootPath).canonicalFilePath();
434
435 if (rootPath.isEmpty())
436 return;
437
439 if (!it.isValid()) {
440 rootPath = QStringLiteral("/");
441 return;
442 }
443
444 int maxLength = 0;
445 const QString oldRootPath = rootPath;
446 rootPath.clear();
447
448 while (it.next()) {
449 const QString mountDir = it.rootPath();
450 const QByteArray fsName = it.fileSystemType();
451 // we try to find most suitable entry
452 if (isParentOf(mountDir, oldRootPath) && maxLength < mountDir.size()) {
453 maxLength = mountDir.size();
454 rootPath = mountDir;
455 device = it.device();
456 fileSystemType = fsName;
457 subvolume = it.subvolume();
458 }
459 }
460}
461
462QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
463{
465 if (!it.isValid())
466 return QList<QStorageInfo>() << root();
467
468 QList<QStorageInfo> volumes;
469
470 while (it.next()) {
471 if (!shouldIncludeFs(it.rootPath(), it.fileSystemType()))
472 continue;
473
474 const QString mountDir = it.rootPath();
475 QStorageInfo info(mountDir);
476 info.d->device = it.device();
477 info.d->fileSystemType = it.fileSystemType();
478 info.d->subvolume = it.subvolume();
479 if (info.bytesTotal() == 0 && info != root())
480 continue;
481 volumes.append(info);
482 }
483
484 return volumes;
485}
486
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.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
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
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
\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:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
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 EINTR_LOOP(var, cmd)
GLenum GLuint buffer
GLuint64 GLenum GLint fd
GLuint name
GLsizei maxLength
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
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:44
QFileInfo info(fileName)
[8]