1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2015 Ivan Komissarov <ABBAPOH@gmail.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qstorageinfo.h"
6#include "qstorageinfo_p.h"
7
8#include "qdebug.h"
9
10QT_BEGIN_NAMESPACE
11
12QT_IMPL_METATYPE_EXTERN(QStorageInfo)
13
14/*!
15 \class QStorageInfo
16 \inmodule QtCore
17 \since 5.4
18 \brief Provides information about currently mounted storage and drives.
19
20 \ingroup io
21 \ingroup shared
22
23 Allows retrieving information about the volume's space, its mount point,
24 label, and filesystem name.
25
26 You can create an instance of QStorageInfo by passing the path to the
27 volume's mount point as a constructor parameter, or you can set it using
28 the setPath() method. The static mountedVolumes() method can be used to get the
29 list of all mounted filesystems.
30
31 QStorageInfo always caches the retrieved information, but you can call
32 refresh() to invalidate the cache.
33
34 The following example retrieves the most common information about the root
35 volume of the system, and prints information about it.
36
37 \snippet code/src_corelib_io_qstorageinfo.cpp 2
38*/
39
40/*!
41 Constructs an empty QStorageInfo object.
42
43 Objects created with the default constructor will be invalid and therefore
44 not ready for use.
45
46 \sa setPath(), isReady(), isValid()
47*/
48QStorageInfo::QStorageInfo()
49 : d(new QStorageInfoPrivate)
50{
51}
52
53/*!
54 Constructs a new QStorageInfo object that gives information about the volume
55 mounted at \a path.
56
57 If you pass a directory or file, the QStorageInfo object will refer to the
58 volume where this directory or file is located.
59 You can check if the created object is correct using the isValid() method.
60
61 The following example shows how to get the volume on which the application is
62 located. It is recommended to always check that the volume is ready and valid.
63
64 \snippet code/src_corelib_io_qstorageinfo.cpp 0
65
66 \sa setPath()
67*/
68QStorageInfo::QStorageInfo(const QString &path)
69 : d(new QStorageInfoPrivate)
70{
71 setPath(path);
72}
73
74/*!
75 Constructs a new QStorageInfo object that gives information about the volume
76 containing the \a dir folder.
77*/
78QStorageInfo::QStorageInfo(const QDir &dir)
79 : d(new QStorageInfoPrivate)
80{
81 setPath(dir.absolutePath());
82}
83
84/*!
85 Constructs a new QStorageInfo object that is a copy of the \a other QStorageInfo object.
86*/
87QStorageInfo::QStorageInfo(const QStorageInfo &other)
88 : d(other.d)
89{
90}
91
92/*!
93 Destroys the QStorageInfo object and frees its resources.
94*/
95QStorageInfo::~QStorageInfo()
96{
97}
98
99/*!
100 Makes a copy of the QStorageInfo object \a other and assigns it to this QStorageInfo object.
101*/
102QStorageInfo &QStorageInfo::operator=(const QStorageInfo &other)
103{
104 d = other.d;
105 return *this;
106}
107
108/*!
109 \fn QStorageInfo &QStorageInfo::operator=(QStorageInfo &&other)
110
111 Assigns \a other to this QStorageInfo instance.
112*/
113
114/*!
115 \fn void QStorageInfo::swap(QStorageInfo &other)
116
117 Swaps this volume info with \a other. This function is very fast and
118 never fails.
119*/
120
121/*!
122 Sets this QStorageInfo object to the filesystem mounted where \a path is located.
123
124 \a path can either be a root path of the filesystem, a directory, or a file
125 within that filesystem.
126
127 \sa rootPath()
128*/
129void QStorageInfo::setPath(const QString &path)
130{
131 if (d->rootPath == path)
132 return;
133 d.detach();
134 d->rootPath = path;
135 d->doStat();
136}
137
138/*!
139 Returns the mount point of the filesystem this QStorageInfo object
140 represents.
141
142 On Windows, it returns the volume letter in case the volume is not mounted to
143 a directory.
144
145 Note that the value returned by rootPath() is the real mount point of a
146 volume, and may not be equal to the value passed to the constructor or setPath()
147 method. For example, if you have only the root volume in the system, and
148 pass '/directory' to setPath(), then this method will return '/'.
149
150 \sa setPath(), device()
151*/
152QString QStorageInfo::rootPath() const
153{
154 return d->rootPath;
155}
156
157/*!
158 Returns the size (in bytes) available for the current user. It returns
159 the total size available if the user is the root user or a system administrator.
160
161 This size can be less than or equal to the free size returned by
162 bytesFree() function.
163
164 Returns -1 if QStorageInfo object is not valid.
165
166 \sa bytesTotal(), bytesFree()
167*/
168qint64 QStorageInfo::bytesAvailable() const
169{
170 return d->bytesAvailable;
171}
172
173/*!
174 Returns the number of free bytes in a volume. Note that if there are
175 quotas on the filesystem, this value can be larger than the value
176 returned by bytesAvailable().
177
178 Returns -1 if QStorageInfo object is not valid.
179
180 \sa bytesTotal(), bytesAvailable()
181*/
182qint64 QStorageInfo::bytesFree() const
183{
184 return d->bytesFree;
185}
186
187/*!
188 Returns the total volume size in bytes.
189
190 Returns -1 if QStorageInfo object is not valid.
191
192 \sa bytesFree(), bytesAvailable()
193*/
194qint64 QStorageInfo::bytesTotal() const
195{
196 return d->bytesTotal;
197}
198
199/*!
200 \since 5.6
201 Returns the optimal transfer block size for this filesystem.
202
203 Returns -1 if QStorageInfo could not determine the size or if the QStorageInfo
204 object is not valid.
205 */
206int QStorageInfo::blockSize() const
207{
208 return d->blockSize;
209}
210
211/*!
212 Returns the type name of the filesystem.
213
214 This is a platform-dependent function, and filesystem names can vary
215 between different operating systems. For example, on Windows filesystems
216 they can be named \c NTFS, and on Linux they can be named \c ntfs-3g or \c fuseblk.
217
218 \sa name()
219*/
220QByteArray QStorageInfo::fileSystemType() const
221{
222 return d->fileSystemType;
223}
224
225/*!
226 Returns the device for this volume.
227
228 For example, on Unix filesystems (including \macos), this returns the
229 devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
230 path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
231
232 \sa rootPath(), subvolume()
233*/
234QByteArray QStorageInfo::device() const
235{
236 return d->device;
237}
238
239/*!
240 \since 5.9
241 Returns the subvolume name for this volume.
242
243 Some filesystem types allow multiple subvolumes inside one device, which
244 may be mounted in different paths (e.g. 'bind' mounts on Unix, or Btrfs
245 filesystem subvolumes). If the subvolume could be detected, its name is
246 returned by this function. The format of the subvolume name is specific
247 to each filesystem type.
248
249 If this volume was not mounted from a subvolume of a larger filesystem or
250 if the subvolume could not be detected, this function returns an empty byte
251 array.
252
253 \sa device()
254*/
255QByteArray QStorageInfo::subvolume() const
256{
257 return d->subvolume;
258}
259
260/*!
261 Returns the human-readable name of a filesystem, usually called \c label.
262
263 Not all filesystems support this feature. In this case, the value returned by
264 this method could be empty. An empty string is returned if the file system
265 does not support labels, or if no label is set.
266
267 On Linux, retrieving the volume's label requires \c udev to be present in the
268 system.
269
270 \sa fileSystemType()
271*/
272QString QStorageInfo::name() const
273{
274 return d->name;
275}
276
277/*!
278 Returns the volume's name, if available, or the root path if not.
279*/
280QString QStorageInfo::displayName() const
281{
282 if (!d->name.isEmpty())
283 return d->name;
284 return d->rootPath;
285}
286
287/*!
288 \fn bool QStorageInfo::isRoot() const
289
290 Returns true if this QStorageInfo represents the system root volume; false
291 otherwise.
292
293 On Unix filesystems, the root volume is a volume mounted on \c /. On Windows,
294 the root volume is the volume where the OS is installed.
295
296 \sa root()
297*/
298
299/*!
300 Returns true if the current filesystem is protected from writing; false
301 otherwise.
302*/
303bool QStorageInfo::isReadOnly() const
304{
305 return d->readOnly;
306}
307
308/*!
309 Returns true if the current filesystem is ready to work; false otherwise. For
310 example, false is returned if the CD volume is not inserted.
311
312 Note that fileSystemType(), name(), bytesTotal(), bytesFree(), and
313 bytesAvailable() will return invalid data until the volume is ready.
314
315 \sa isValid()
316*/
317bool QStorageInfo::isReady() const
318{
319 return d->ready;
320}
321
322/*!
323 Returns true if the QStorageInfo specified by rootPath exists and is mounted
324 correctly.
325
326 \sa isReady()
327*/
328bool QStorageInfo::isValid() const
329{
330 return d->valid;
331}
332
333/*!
334 Resets QStorageInfo's internal cache.
335
336 QStorageInfo caches information about storage to speed up performance.
337 QStorageInfo retrieves information during object construction and/or when calling
338 the setPath() method. You have to manually reset the cache by calling this
339 function to update storage information.
340*/
341void QStorageInfo::refresh()
342{
343 d.detach();
344 d->doStat();
345}
346
347/*!
348 Returns the list of QStorageInfo objects that corresponds to the list of currently
349 mounted filesystems.
350
351 On Windows, this returns the drives visible in the \gui{My Computer} folder. On Unix
352 operating systems, it returns the list of all mounted filesystems (except for
353 pseudo filesystems).
354
355 Returns all currently mounted filesystems by default.
356
357 The example shows how to retrieve all available filesystems, skipping read-only ones.
358
359 \snippet code/src_corelib_io_qstorageinfo.cpp 1
360
361 \sa root()
362*/
363QList<QStorageInfo> QStorageInfo::mountedVolumes()
364{
365 return QStorageInfoPrivate::mountedVolumes();
366}
367
368Q_GLOBAL_STATIC(QStorageInfo, getRoot, QStorageInfoPrivate::root())
369
370/*!
371 Returns a QStorageInfo object that represents the system root volume.
372
373 On Unix systems this call returns the root ('/') volume; in Windows the volume where
374 the operating system is installed.
375
376 \sa isRoot()
377*/
378QStorageInfo QStorageInfo::root()
379{
380 return *getRoot();
381}
382
383/*!
384 \fn bool QStorageInfo::operator==(const QStorageInfo &first, const QStorageInfo &second)
385
386 Returns true if the \a first QStorageInfo object refers to the same drive or volume
387 as the \a second; otherwise it returns false.
388
389 Note that the result of comparing two invalid QStorageInfo objects is always
390 positive.
391*/
392
393/*!
394 \fn bool QStorageInfo::operator!=(const QStorageInfo &first, const QStorageInfo &second)
395
396 Returns true if the \a first QStorageInfo object refers to a different drive or
397 volume than the \a second; otherwise returns false.
398*/
399
400#ifndef QT_NO_DEBUG_STREAM
401QDebug operator<<(QDebug debug, const QStorageInfo &s)
402{
403 QDebugStateSaver saver(debug);
404 debug.nospace();
405 debug.noquote();
406 debug << "QStorageInfo(";
407 if (s.isValid()) {
408 const QStorageInfoPrivate *d = s.d.constData();
409 debug << '"' << d->rootPath << '"';
410 if (!d->fileSystemType.isEmpty())
411 debug << ", type=" << d->fileSystemType;
412 if (!d->name.isEmpty())
413 debug << ", name=\"" << d->name << '"';
414 if (!d->device.isEmpty())
415 debug << ", device=\"" << d->device << '"';
416 if (!d->subvolume.isEmpty())
417 debug << ", subvolume=\"" << d->subvolume << '"';
418 if (d->readOnly)
419 debug << " [read only]";
420 debug << (d->ready ? " [ready]" : " [not ready]");
421 if (d->bytesTotal > 0) {
422 debug << ", bytesTotal=" << d->bytesTotal << ", bytesFree=" << d->bytesFree
423 << ", bytesAvailable=" << d->bytesAvailable;
424 }
425 } else {
426 debug << "invalid";
427 }
428 debug << ')';
429 return debug;
430}
431#endif // !QT_NO_DEBUG_STREAM
432
433QT_END_NAMESPACE
434

source code of qtbase/src/corelib/io/qstorageinfo.cpp