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 
45 QT_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 */
QStorageInfo()81 QStorageInfo::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 */
QStorageInfo(const QString & path)101 QStorageInfo::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 */
QStorageInfo(const QDir & dir)111 QStorageInfo::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 */
QStorageInfo(const QStorageInfo & other)120 QStorageInfo::QStorageInfo(const QStorageInfo &other)
121     : d(other.d)
122 {
123 }
124 
125 /*!
126     Destroys the QStorageInfo object and frees its resources.
127 */
~QStorageInfo()128 QStorageInfo::~QStorageInfo()
129 {
130 }
131 
132 /*!
133     Makes a copy of the QStorageInfo object \a other and assigns it to this QStorageInfo object.
134 */
operator =(const QStorageInfo & other)135 QStorageInfo &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 */
setPath(const QString & path)162 void 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 */
rootPath() const185 QString 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 */
bytesAvailable() const201 qint64 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 */
bytesFree() const215 qint64 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 */
bytesTotal() const227 qint64 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  */
blockSize() const239 int 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 */
fileSystemType() const253 QByteArray 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 */
device() const267 QByteArray 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 */
subvolume() const287 QByteArray 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 */
name() const304 QString 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 */
displayName() const312 QString 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 */
isReadOnly() const335 bool 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 */
isReady() const349 bool 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 */
isValid() const360 bool 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 */
refresh()373 void 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 */
mountedVolumes()395 QList<QStorageInfo> QStorageInfo::mountedVolumes()
396 {
397     return QStorageInfoPrivate::mountedVolumes();
398 }
399 
400 Q_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 */
root()410 QStorageInfo 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
operator <<(QDebug debug,const QStorageInfo & s)437 QDebug 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 
469 QT_END_NAMESPACE
470