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