1
/****************************************************************************
2
**
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
14
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file.  Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
**
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27
**
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
**
31
**
32
**
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include "qplatformdefs.h"
43
#include "qfileinfo.h"
44
#include "qdatetime.h"
45
#include "qabstractfileengine.h"
46
#include "qfsfileengine_p.h"
47
#include "qglobal.h"
48
#include "qatomic.h"
49
#include "qhash.h"
50
#include "qdir.h"
51
52
QT_BEGIN_NAMESPACE
53
54
class QFileInfoPrivate
55
{
56
public:
57
    QFileInfoPrivate(const QFileInfo *copy=0);
58
    ~QFileInfoPrivate();
59
60
    void initFileEngine(const QString &);
61
62
    enum Access {
63
        ReadAccess,
64
        WriteAccess,
65
        ExecuteAccess
66
    };
67
    bool hasAccess(Access access) const;
68
69
    uint getFileFlags(QAbstractFileEngine::FileFlags) const;
70
    QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
71
    QString getFileName(QAbstractFileEngine::FileName) const;
72
73
    enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
74
           CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
75
           CachedSize =0x08 };
76
    struct Data {
77
        inline Data()
78
            : ref(1), fileEngine(0), cache_enabled(1)
79
        { clear(); }
80
        inline Data(const Data &copy)
81
            : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
82
              fileName(copy.fileName), cache_enabled(copy.cache_enabled)
83
        { clear(); }
84
        inline ~Data() { delete fileEngine; }
85
        inline void clearFlags() {
86
            fileFlags = 0;
87
            cachedFlags = 0;
88
            if (fileEngine)
89
                (void)fileEngine->fileFlags(QFSFileEngine::Refresh);
90
        }
91
        inline void clear() {
92
            fileNames.clear();
93
            clearFlags();
94
        }
95
        mutable QAtomicInt ref;
96
97
        QAbstractFileEngine *fileEngine;
98
        mutable QString fileName;
99
        mutable QHash<int, QString> fileNames;
100
101
        mutable uint cachedFlags : 31;
102
        mutable uint cache_enabled : 1;
103
        mutable uint fileFlags;
104
        mutable qint64 fileSize;
105
        mutable QDateTime fileTimes[3];
106
        inline bool getCachedFlag(uint c) const
107
        { return cache_enabled ? (cachedFlags & c) : 0; }
108
        inline void setCachedFlag(uint c)
109
        { if (cache_enabled) cachedFlags |= c; }
110
    } *data;
111
    inline void reset() {
112
        detach();
113
        data->clear();
114
    }
115
    void detach();
116
};
117
118
QFileInfoPrivate::QFileInfoPrivate(const QFileInfo *copy)
119
{
120
    if(copy) {
121
        copy->d_func()->data->ref.ref();
122
        data = copy->d_func()->data;
123
    } else {
124
        data = new QFileInfoPrivate::Data;
125
        data->clear();
126
    }
127
}
128
129
QFileInfoPrivate::~QFileInfoPrivate()
130
{
131
    if (!data->ref.deref())
132
        delete data;
133
    data = 0;
134
}
135
136
void QFileInfoPrivate::initFileEngine(const QString &file)
137
{
138
    detach();
139
    delete data->fileEngine;
140
    data->fileEngine = 0;
141
    data->clear();
142
    data->fileEngine = QAbstractFileEngine::create(file);
143
    data->fileName = file;
144
}
145
146
bool QFileInfoPrivate::hasAccess(Access access) const
147
{
148
    if (!(getFileFlags(QAbstractFileEngine::FileInfoAll) & QAbstractFileEngine::LocalDiskFlag)) {
149
        switch (access) {
150
        case ReadAccess:
151
            return getFileFlags(QAbstractFileEngine::ReadUserPerm);
152
        case WriteAccess:
153
            return getFileFlags(QAbstractFileEngine::WriteUserPerm);
154
        case ExecuteAccess:
155
            return getFileFlags(QAbstractFileEngine::ExeUserPerm);
156
        default:
157
            return false;
158
        }
159
    }
160
161
    int mode = 0;
162
    switch (access) {
163
    case ReadAccess:
164
        mode = R_OK;
165
        break;
166
    case WriteAccess:
167
        mode = W_OK;
168
        break;
169
    case ExecuteAccess:
170
        mode = X_OK;
171
        break;
172
    };
173
#ifdef Q_OS_UNIX
174
    return QT_ACCESS(QFile::encodeName(data->fileName).data(), mode) == 0;
175
#endif
176
#ifdef Q_OS_WIN
177
    if ((access == ReadAccess && !getFileFlags(QAbstractFileEngine::ReadUserPerm))
178
        || (access == WriteAccess && !getFileFlags(QAbstractFileEngine::WriteUserPerm))) {
179
        return false;
180
    }
181
    if (access == ExecuteAccess)
182
        return getFileFlags(QAbstractFileEngine::ExeUserPerm);
183
184
    QT_WA( {
185
        return ::_waccess((TCHAR *)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0;
186
    } , {
187
        return QT_ACCESS(QFSFileEnginePrivate::win95Name(data->fileName), mode) == 0;
188
    } );
189
#endif
190
    return false;
191
}
192
193
void QFileInfoPrivate::detach()
194
{
195
    qAtomicDetach(data);
196
}
197
198
QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
199
{
200
    if(data->cache_enabled && data->fileNames.contains((int)name))
201
        return data->fileNames.value(name);
202
    QString ret = data->fileEngine->fileName(name);
203
    if(data->cache_enabled)
204
        data->fileNames.insert((int)name, ret);
205
    return ret;
206
}
207
208
uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) const
209
{
210
    // We split the testing into tests for for LinkType, BundleType and the rest.
211
    // In order to determine if a file is a symlink or not, we have to lstat().
212
    // If we're not interested in that information, we might as well avoid one
213
    // extra syscall. Bundle detecton on Mac can be slow, expecially on network
214
    // paths, so we separate out that as well.
215
216
    QAbstractFileEngine::FileFlags flags;
217
    if (!data->getCachedFlag(CachedFileFlags)) {
218
        QAbstractFileEngine::FileFlags req = QAbstractFileEngine::FileInfoAll;
219
        req &= (~QAbstractFileEngine::LinkType);
220
        req &= (~QAbstractFileEngine::BundleType);
221
222
        flags = data->fileEngine->fileFlags(req);
223
        data->setCachedFlag(CachedFileFlags);
224
        data->fileFlags |= uint(flags);
225
    } else {
226
        flags = QAbstractFileEngine::FileFlags(data->fileFlags & request);
227
    }
228
229
    if (request & QAbstractFileEngine::LinkType) {
230
        if (!data->getCachedFlag(CachedLinkTypeFlag)) {
231
            QAbstractFileEngine::FileFlags linkflag;
232
            linkflag = data->fileEngine->fileFlags(QAbstractFileEngine::LinkType);
233
234
            data->setCachedFlag(CachedLinkTypeFlag);
235
            data->fileFlags |= uint(linkflag);
236
            flags |= linkflag;
237
        }
238
    }
239
240
    if (request & QAbstractFileEngine::BundleType) {
241
        if (!data->getCachedFlag(CachedBundleTypeFlag)) {
242
            QAbstractFileEngine::FileFlags bundleflag;
243
            bundleflag = data->fileEngine->fileFlags(QAbstractFileEngine::BundleType);
244
245
            data->setCachedFlag(CachedBundleTypeFlag);
246
            data->fileFlags |= uint(bundleflag);
247
            flags |= bundleflag;
248
        }
249
    }
250
251
    // no else branch
252
    // if we had it cached, it was caught in the previous else branch
253
254
    return flags & request;
255
}
256
257
QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) const
258
{
259
    if (!data->cache_enabled)
260
        data->clearFlags();
261
    if(request == QAbstractFileEngine::CreationTime) {
262
        if(data->getCachedFlag(CachedCTime))
263
            return data->fileTimes[request];
264
        data->setCachedFlag(CachedCTime);
265
        return (data->fileTimes[request] = data->fileEngine->fileTime(request));
266
    }
267
    if(request == QAbstractFileEngine::ModificationTime) {
268
        if(data->getCachedFlag(CachedMTime))
269
            return data->fileTimes[request];
270
        data->setCachedFlag(CachedMTime);
271
        return (data->fileTimes[request] = data->fileEngine->fileTime(request));
272
    }
273
    if(request == QAbstractFileEngine::AccessTime) {
274
        if(data->getCachedFlag(CachedATime))
275
            return data->fileTimes[request];
276
        data->setCachedFlag(CachedATime);
277
        return (data->fileTimes[request] = data->fileEngine->fileTime(request));
278
    }
279
    return data->fileTimes[0]; //cannot really happen
280
}
281
282
//************* QFileInfo
283
284
/*!
285
    \class QFileInfo
286
    \reentrant
287
    \brief The QFileInfo class provides system-independent file information.
288
289
    \ingroup io
290
    \ingroup shared
291
292
    QFileInfo provides information about a file's name and position
293
    (path) in the file system, its access rights and whether it is a
294
    directory or symbolic link, etc. The file's size and last
295
    modified/read times are also available. QFileInfo can also be
296
    used to obtain information about a Qt \l{resource
297
    system}{resource}.
298
299
    A QFileInfo can point to a file with either a relative or an
300
    absolute file path. Absolute file paths begin with the directory
301
    separator "/" (or with a drive specification on Windows). Relative
302
    file names begin with a directory name or a file name and specify
303
    a path relative to the current working directory. An example of an
304
    absolute path is the string "/tmp/quartz". A relative path might
305
    look like "src/fatlib". You can use the function isRelative() to
306
    check whether a QFileInfo is using a relative or an absolute file
307
    path. You can call the function makeAbsolute() to convert a
308
    relative QFileInfo's path to an absolute path.
309
310
    The file that the QFileInfo works on is set in the constructor or
311
    later with setFile(). Use exists() to see if the file exists and
312
    size() to get its size.
313
314
    The file's type is obtained with isFile(), isDir() and
315
    isSymLink(). The symLinkTarget() function provides the name of the file
316
    the symlink points to.
317
318
    On Unix (including Mac OS X), the symlink has the same size() has
319
    the file it points to, because Unix handles symlinks
320
    transparently; similarly, opening a symlink using QFile
321
    effectively opens the link's target. For example:
322
323
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 0
324
325
    On Windows, symlinks (shortcuts) are \c .lnk files. The reported
326
    size() is that of the symlink (not the link's target), and
327
    opening a symlink using QFile opens the \c .lnk file. For
328
    example:
329
330
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 1
331
332
    Elements of the file's name can be extracted with path() and
333
    fileName(). The fileName()'s parts can be extracted with
334
    baseName(), suffix() or completeSuffix(). QFileInfo objects to
335
    directories created by Qt classes will not have a trailing file
336
    separator. If you wish to use trailing separators in your own file
337
    info objects, just append one to the file name given to the constructors
338
    or setFile().
339
340
    The file's dates are returned by created(), lastModified() and
341
    lastRead(). Information about the file's access permissions is
342
    obtained with isReadable(), isWritable() and isExecutable(). The
343
    file's ownership is available from owner(), ownerId(), group() and
344
    groupId(). You can examine a file's permissions and ownership in a
345
    single statement using the permission() function.
346
347
    \section1 Performance Issues
348
349
    Some of QFileInfo's functions query the file system, but for
350
    performance reasons, some functions only operate on the
351
    file name itself. For example: To return the absolute path of
352
    a relative file name, absolutePath() has to query the file system.
353
    The path() function, however, can work on the file name directly,
354
    and so it is faster.
355
356
    \note To speed up performance, QFileInfo caches information about
357
    the file.
358
359
    To speed up performance, QFileInfo caches information about the
360
    file. Because files can be changed by other users or programs, or
361
    even by other parts of the same program, there is a function that
362
    refreshes the file information: refresh(). If you want to switch
363
    off a QFileInfo's caching and force it to access the file system
364
    every time you request information from it call setCaching(false).
365
366
    \sa QDir, QFile
367
*/
368
369
/*!
370
    Constructs an empty QFileInfo object.
371
372
    Note that an empty QFileInfo object contain no file reference.
373
374
    \sa setFile()
375
*/
376
377
QFileInfo::QFileInfo() : d_ptr(new QFileInfoPrivate())
378
{
379
}
380
381
/*!
382
    Constructs a new QFileInfo that gives information about the given
383
    file. The \a file can also include an absolute or relative path.
384
385
    \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
386
*/
387
388
QFileInfo::QFileInfo(const QString &file) : d_ptr(new QFileInfoPrivate())
389
{
390
    d_ptr->initFileEngine(file);
391
}
392
393
/*!
394
    Constructs a new QFileInfo that gives information about file \a
395
    file.
396
397
    If the \a file has a relative path, the QFileInfo will also have a
398
    relative path.
399
400
    \sa isRelative()
401
*/
402
403
QFileInfo::QFileInfo(const QFile &file) : d_ptr(new QFileInfoPrivate())
404
{
405
    d_ptr->initFileEngine(file.fileName());
406
}
407
408
/*!
409
    Constructs a new QFileInfo that gives information about the given
410
    \a file in the directory \a dir.
411
412
    If \a dir has a relative path, the QFileInfo will also have a
413
    relative path.
414
415
    If \a file is an absolute path, then the directory specified
416
    by \a dir will be disregarded.
417
418
    \sa isRelative()
419
*/
420
421
QFileInfo::QFileInfo(const QDir &dir, const QString &file) : d_ptr(new QFileInfoPrivate())
422
{
423
    d_ptr->initFileEngine(dir.filePath(file));
424
}
425
426
/*!
427
    Constructs a new QFileInfo that is a copy of the given \a fileinfo.
428
*/
429
430
QFileInfo::QFileInfo(const QFileInfo &fileinfo) : d_ptr(new QFileInfoPrivate(&fileinfo))
431
{
432
433
}
434
435
/*!
436
    Destroys the QFileInfo and frees its resources.
437
*/
438
439
440
QFileInfo::~QFileInfo()
441
{
442
    delete d_ptr;
443
    d_ptr = 0;
444
}
445
446
/*!
447
    \fn bool QFileInfo::operator!=(const QFileInfo &fileinfo)
448
449
    Returns true if this QFileInfo object refers to a different file
450
    than the one specified by \a fileinfo; otherwise returns false.
451
452
    \sa operator==()
453
*/
454
455
/*!
456
    \overload
457
    \fn bool QFileInfo::operator!=(const QFileInfo &fileinfo) const
458
*/
459
460
/*!
461
    \overload
462
*/
463
bool QFileInfo::operator==(const QFileInfo &fileinfo) const
464
{
465
    Q_D(const QFileInfo);
466
    // ### Qt 5: understand long and short file names on Windows
467
    // ### (GetFullPathName()).
468
    if(fileinfo.d_func()->data == d->data)
469
        return true;
470
    if(!d->data->fileEngine || !fileinfo.d_func()->data->fileEngine)
471
        return false;
472
    if(d->data->fileEngine->caseSensitive() != fileinfo.d_func()->data->fileEngine->caseSensitive())
473
        return false;
474
    if(fileinfo.size() == size()) { //if the size isn't the same...
475
        QString file1 = canonicalFilePath(),
476
                file2 = fileinfo.canonicalFilePath();
477
        if(file1.length() == file2.length()) {
478
            if(!fileinfo.d_func()->data->fileEngine->caseSensitive()) {
479
                for(int i = 0; i < file1.length(); i++) {
480
                    if(file1.at(i).toLower() != file2.at(i).toLower())
481
                        return false;
482
                }
483
                return true;
484
            }
485
            return (file1 == file2);
486
        }
487
    }
488
    return false;
489
}
490
491
/*!
492
    Returns true if this QFileInfo object refers to a file in the same
493
    location as \a fileinfo; otherwise returns false.
494
495
    Note that the result of comparing two empty QFileInfo objects,
496
    containing no file references, is undefined.
497
498
    \warning This will not compare two different symbolic links
499
    pointing to the same file.
500
501
    \warning Long and short file names that refer to the same file on Windows
502
    are treated as if they referred to different files.
503
504
    \sa operator!=()
505
*/
506
bool QFileInfo::operator==(const QFileInfo &fileinfo)
507
{
508
    return const_cast<const QFileInfo *>(this)->operator==(fileinfo);
509
}
510
511
/*!
512
    Makes a copy of the given \a fileinfo and assigns it to this QFileInfo.
513
*/
514
515
QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
516
{
517
    Q_D(QFileInfo);
518
    qAtomicAssign(d->data, fileinfo.d_func()->data);
519
    return *this;
520
}
521
522
/*!
523
    Sets the file that the QFileInfo provides information about to \a
524
    file.
525
526
    The \a file can also include an absolute or relative file path.
527
    Absolute paths begin with the directory separator (e.g. "/" under
528
    Unix) or a drive specification (under Windows). Relative file
529
    names begin with a directory name or a file name and specify a
530
    path relative to the current directory.
531
532
    Example:
533
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 2
534
535
    \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath()
536
*/
537
538
void QFileInfo::setFile(const QString &file)
539
{
540
    Q_D(QFileInfo);
541
    d->initFileEngine(file);
542
}
543
544
/*!
545
    \overload
546
547
    Sets the file that the QFileInfo provides information about to \a
548
    file.
549
550
    If \a file includes a relative path, the QFileInfo will also have
551
    a relative path.
552
553
    \sa isRelative()
554
*/
555
556
void QFileInfo::setFile(const QFile &file)
557
{
558
    Q_D(QFileInfo);
559
    d->initFileEngine(file.fileName());
560
}
561
562
/*!
563
    \overload
564
565
    Sets the file that the QFileInfo provides information about to \a
566
    file in directory \a dir.
567
568
    If \a file includes a relative path, the QFileInfo will also
569
    have a relative path.
570
571
    \sa isRelative()
572
*/
573
574
void QFileInfo::setFile(const QDir &dir, const QString &file)
575
{
576
    Q_D(QFileInfo);
577
    d->initFileEngine(dir.filePath(file));
578
}
579
580
/*!
581
    Returns an absolute path including the file name.
582
583
    The absolute path name consists of the full path and the file
584
    name. On Unix this will always begin with the root, '/',
585
    directory. On Windows this will always begin 'D:/' where D is a
586
    drive letter, except for network shares that are not mapped to a
587
    drive letter, in which case the path will begin '//sharename/'.
588
    QFileInfo will uppercase drive letters. Note that QDir does not do
589
    this. The code snippet below shows this.
590
591
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp newstuff
592
593
    This function returns the same as filePath(), unless isRelative()
594
    is true. In contrast to canonicalFilePath(), symbolic links or
595
    redundant "." or ".." elements are not necessarily removed.
596
597
    If the QFileInfo is empty it returns QDir::currentPath().
598
599
    \sa filePath(), canonicalFilePath(), isRelative()
600
*/
601
QString QFileInfo::absoluteFilePath() const
602
{
603
    Q_D(const QFileInfo);
604
    if(!d->data->fileEngine)
605
        return QLatin1String("");
606
    return d->getFileName(QAbstractFileEngine::AbsoluteName);
607
}
608
609
/*!
610
  Returns the canonical path including the file name, i.e. an absolute
611
  path without symbolic links or redundant "." or ".." elements.
612
613
  If the file does not exist, canonicalFilePath() returns an empty
614
  string.
615
616
  \sa filePath(), absoluteFilePath(), dir()
617
*/
618
619
QString QFileInfo::canonicalFilePath() const
620
{
621
    Q_D(const QFileInfo);
622
    if(!d->data->fileEngine)
623
        return QLatin1String("");
624
    return d->getFileName(QAbstractFileEngine::CanonicalName);
625
}
626
627
628
/*!
629
    Returns a file's path absolute path. This doesn't include the
630
    file name.
631
632
    On Unix the absolute path will always begin with the root, '/',
633
    directory. On Windows this will always begin 'D:/' where D is a
634
    drive letter, except for network shares that are not mapped to a
635
    drive letter, in which case the path will begin '//sharename/'.
636
637
    In contrast to canonicalPath() symbolic links or redundant "." or
638
    ".." elements are not necessarily removed.
639
640
    \warning If the QFileInfo object was created with an empty QString,
641
              the behavior of this function is undefined.
642
643
    \sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative()
644
*/
645
646
QString QFileInfo::absolutePath() const
647
{
648
    Q_D(const QFileInfo);
649
    if(!d->data->fileEngine)
650
        return QLatin1String("");
651
    return d->getFileName(QAbstractFileEngine::AbsolutePathName);
652
}
653
654
/*!
655
    Returns the file's path canonical path (excluding the file name),
656
    i.e. an absolute path without symbolic links or redundant "." or ".." elements.
657
658
    If the file does not exist, canonicalPath() returns an empty string.
659
660
    \sa path(), absolutePath()
661
*/
662
663
QString QFileInfo::canonicalPath() const
664
{
665
    Q_D(const QFileInfo);
666
    if(!d->data->fileEngine)
667
        return QLatin1String("");
668
    return d->getFileName(QAbstractFileEngine::CanonicalPathName);
669
}
670
671
672
/*!
673
    Returns the file's path. This doesn't include the file name.
674
675
    Note that, if this QFileInfo object is given a path ending in a
676
    slash, the name of the file is considered empty and this function
677
    will return the entire path.
678
679
    \sa filePath(), absolutePath(), canonicalPath(), dir(), fileName(), isRelative()
680
*/
681
682
QString QFileInfo::path() const
683
{
684
    Q_D(const QFileInfo);
685
    if(!d->data->fileEngine)
686
        return QLatin1String("");
687
    return d->getFileName(QAbstractFileEngine::PathName);
688
}
689
690
/*!
691
    \fn bool QFileInfo::isAbsolute() const
692
693
    Returns true if the file path name is absolute, otherwise returns
694
    false if the path is relative.
695
696
    \sa isRelative()
697
*/
698
699
/*!
700
    Returns true if the file path name is relative, otherwise returns
701
    false if the path is absolute (e.g. under Unix a path is absolute
702
    if it begins with a "/").
703
704
    \sa isAbsolute()
705
*/
706
707
bool QFileInfo::isRelative() const
708
{
709
    Q_D(const QFileInfo);
710
    if(!d->data->fileEngine)
711
        return true;
712
    return d->data->fileEngine->isRelativePath();
713
}
714
715
716
/*!
717
    Converts the file's path to an absolute path if it is not already in that form.
718
    Returns true to indicate that the path was converted; otherwise returns false
719
    to indicate that the path was already absolute.
720
721
    \sa filePath(), isRelative()
722
*/
723
724
bool QFileInfo::makeAbsolute()
725
{
726
    Q_D(QFileInfo);
727
    if(!d->data->fileEngine || !d->data->fileEngine->isRelativePath())
728
        return false;
729
    QString absFileName = d->getFileName(QAbstractFileEngine::AbsoluteName);
730
    d->initFileEngine(absFileName);
731
    return true;
732
}
733
734
/*!
735
    Returns true if the file exists; otherwise returns false.
736
737
    \note If the file is a symlink that points to a non existing
738
     file, false is returned.
739
*/
740
741
bool QFileInfo::exists() const
742
{
743
    Q_D(const QFileInfo);
744
    if(!d->data->fileEngine)
745
        return false;
746
    return d->getFileFlags(QAbstractFileEngine::ExistsFlag);
747
}
748
749
/*!
750
    Refreshes the information about the file, i.e. reads in information
751
    from the file system the next time a cached property is fetched.
752
753
   \note On Windows CE, there might be a delay for the file system driver
754
    to detect changes on the file.
755
*/
756
757
void QFileInfo::refresh()
758
{
759
    Q_D(QFileInfo);
760
    d->reset();
761
}
762
763
/*!
764
    Returns the file name, including the path (which may be absolute
765
    or relative).
766
767
    \sa absoluteFilePath(), canonicalFilePath(), isRelative()
768
*/
769
770
QString QFileInfo::filePath() const
771
{
772
    Q_D(const QFileInfo);
773
    if(!d->data->fileEngine)
774
        return QLatin1String("");
775
    return d->getFileName(QAbstractFileEngine::DefaultName);
776
}
777
778
/*!
779
    Returns the name of the file, excluding the path.
780
781
    Example:
782
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 3
783
784
    Note that, if this QFileInfo object is given a path ending in a
785
    slash, the name of the file is considered empty.
786
787
    \sa isRelative(), filePath(), baseName(), extension()
788
*/
789
790
QString QFileInfo::fileName() const
791
{
792
    Q_D(const QFileInfo);
793
    if(!d->data->fileEngine)
794
        return QLatin1String("");
795
    return d->getFileName(QAbstractFileEngine::BaseName);
796
}
797
798
/*!
799
    \since 4.3
800
    Returns the name of the bundle.
801
802
    On Mac OS X this returns the proper localized name for a bundle if the
803
    path isBundle(). On all other platforms an empty QString is returned.
804
805
    Example:
806
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 4
807
808
    \sa isBundle(), filePath(), baseName(), extension()
809
*/
810
811
QString QFileInfo::bundleName() const
812
{
813
    Q_D(const QFileInfo);
814
    if(!d->data->fileEngine)
815
        return QLatin1String("");
816
    return d->getFileName(QAbstractFileEngine::BundleName);
817
}
818
819
/*!
820
    Returns the base name of the file without the path.
821
822
    The base name consists of all characters in the file up to (but
823
    not including) the \e first '.' character.
824
825
    Example:
826
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 5
827
828
829
    The base name of a file is computed equally on all platforms, independent
830
    of file naming conventions (e.g., ".bashrc" on Unix has an empty base
831
    name, and the suffix is "bashrc").
832
833
    \sa fileName(), suffix(), completeSuffix(), completeBaseName()
834
*/
835
836
QString QFileInfo::baseName() const
837
{
838
    Q_D(const QFileInfo);
839
    if(!d->data->fileEngine)
840
        return QLatin1String("");
841
    return d->getFileName(QAbstractFileEngine::BaseName).section(QLatin1Char('.'), 0, 0);
842
}
843
844
/*!
845
    Returns the complete base name of the file without the path.
846
847
    The complete base name consists of all characters in the file up
848
    to (but not including) the \e last '.' character.
849
850
    Example:
851
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 6
852
853
    \sa fileName(), suffix(), completeSuffix(), baseName()
854
*/
855
856
QString QFileInfo::completeBaseName() const
857
{
858
    Q_D(const QFileInfo);
859
    if(!d->data->fileEngine)
860
        return QLatin1String("");
861
    QString name = d->getFileName(QAbstractFileEngine::BaseName);
862
    int index = name.lastIndexOf(QLatin1Char('.'));
863
    return (index == -1) ? name : name.left(index);
864
}
865
866
/*!
867
    Returns the complete suffix of the file.
868
869
    The complete suffix consists of all characters in the file after
870
    (but not including) the first '.'.
871
872
    Example:
873
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 7
874
875
    \sa fileName(), suffix(), baseName(), completeBaseName()
876
*/
877
878
QString QFileInfo::completeSuffix() const
879
{
880
    Q_D(const QFileInfo);
881
    if(!d->data->fileEngine)
882
        return QLatin1String("");
883
    QString fileName = d->getFileName(QAbstractFileEngine::BaseName);
884
    int firstDot = fileName.indexOf(QLatin1Char('.'));
885
    if (firstDot == -1)
886
        return QLatin1String("");
887
    return fileName.mid(firstDot + 1);
888
}
889
890
/*!
891
    Returns the suffix of the file.
892
893
    The suffix consists of all characters in the file after (but not
894
    including) the last '.'.
895
896
    Example:
897
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 8
898
899
    The suffix of a file is computed equally on all platforms, independent of
900
    file naming conventions (e.g., ".bashrc" on Unix has an empty base name,
901
    and the suffix is "bashrc").
902
903
    \sa fileName(), completeSuffix(), baseName(), completeBaseName()
904
*/
905
906
QString QFileInfo::suffix() const
907
{
908
    Q_D(const QFileInfo);
909
    if(!d->data->fileEngine)
910
        return QLatin1String("");
911
    QString fileName = d->getFileName(QAbstractFileEngine::BaseName);
912
    int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
913
    if (lastDot == -1)
914
        return QLatin1String("");
915
    return fileName.mid(lastDot + 1);
916
}
917
918
919
/*!
920
  Returns the path of the object's parent directory as a QDir object.
921
922
  \bold{Note:} The QDir returned always corresponds to the object's
923
  parent directory, even if the QFileInfo represents a directory.
924
  
925
  For each of the follwing, dir() returns a QDir for
926
  \c{"~/examples/191697"}.
927
928
  \snippet doc/src/snippets/fileinfo/main.cpp 0
929
930
  For each of the follwing, dir() returns a QDir for
931
  \c{"."}.
932
933
  \snippet doc/src/snippets/fileinfo/main.cpp 1
934
935
  \sa absolutePath(), filePath(), fileName(), isRelative(), absoluteDir()
936
*/
937
938
QDir QFileInfo::dir() const
939
{
940
    // ### Qt5: Maybe rename this to parentDirectory(), considering what it actually do?
941
    return QDir(path());
942
}
943
944
/*!
945
    Returns the file's absolute path as a QDir object.
946
947
    \sa dir(), filePath(), fileName(), isRelative()
948
*/
949
950
QDir QFileInfo::absoluteDir() const
951
{
952
    return QDir(absolutePath());
953
}
954
955
#ifdef QT3_SUPPORT
956
/*!
957
    Use absoluteDir() or the dir() overload that takes no parameters
958
    instead.
959
*/
960
QDir QFileInfo::dir(bool absPath) const
961
{
962
    if(absPath)
963
        return absoluteDir();
964
    return dir();
965
}
966
#endif //QT3_SUPPORT
967
968
/*!
969
    Returns true if the user can read the file; otherwise returns false.
970
971
    \sa isWritable(), isExecutable(), permission()
972
*/
973
974
bool QFileInfo::isReadable() const
975
{
976
    Q_D(const QFileInfo);
977
    if(!d->data->fileEngine)
978
        return false;
979
    return d->hasAccess(QFileInfoPrivate::ReadAccess);
980
}
981
982
/*!
983
    Returns true if the user can write to the file; otherwise returns false.
984
985
    \sa isReadable(), isExecutable(), permission()
986
*/
987
988
bool QFileInfo::isWritable() const
989
{
990
    Q_D(const QFileInfo);
991
    if(!d->data->fileEngine)
992
        return false;
993
    return d->hasAccess(QFileInfoPrivate::WriteAccess);
994
}
995
996
/*!
997
    Returns true if the file is executable; otherwise returns false.
998
999
    \sa isReadable(), isWritable(), permission()
1000
*/
1001
1002
bool QFileInfo::isExecutable() const
1003
{
1004
    Q_D(const QFileInfo);
1005
    if(!d->data->fileEngine)
1006
        return false;
1007
    return d->hasAccess(QFileInfoPrivate::ExecuteAccess);
1008
}
1009
1010
/*!
1011
    Returns true if this is a `hidden' file; otherwise returns false.
1012
1013
    \bold{Note:} This function returns true for the special entries
1014
    "." and ".." on Unix, even though QDir::entryList threats them as shown.
1015
*/
1016
bool QFileInfo::isHidden() const
1017
{
1018
    Q_D(const QFileInfo);
1019
    if(!d->data->fileEngine)
1020
        return false;
1021
    return d->getFileFlags(QAbstractFileEngine::HiddenFlag);
1022
}
1023
1024
/*!
1025
    Returns true if this object points to a file or to a symbolic
1026
    link to a file. Returns false if the
1027
    object points to something which isn't a file, such as a directory.
1028
1029
    \sa isDir(), isSymLink(), isBundle()
1030
*/
1031
1032
bool QFileInfo::isFile() const
1033
{
1034
    Q_D(const QFileInfo);
1035
    if(!d->data->fileEngine)
1036
        return false;
1037
    return d->getFileFlags(QAbstractFileEngine::FileType);
1038
}
1039
1040
/*!
1041
    Returns true if this object points to a directory or to a symbolic
1042
    link to a directory; otherwise returns false.
1043
1044
    \sa isFile(), isSymLink(), isBundle()
1045
*/
1046
1047
bool QFileInfo::isDir() const
1048
{
1049
    Q_D(const QFileInfo);
1050
    if(!d->data->fileEngine)
1051
        return false;
1052
    return d->getFileFlags(QAbstractFileEngine::DirectoryType);
1053
}
1054
1055
1056
/*!
1057
    \since 4.3
1058
    Returns true if this object points to a bundle or to a symbolic
1059
    link to a bundle on Mac OS X; otherwise returns false.
1060
1061
    \sa isDir(), isSymLink(), isFile()
1062
*/
1063
1064
bool QFileInfo::isBundle() const
1065
{
1066
    Q_D(const QFileInfo);
1067
    if(!d->data->fileEngine)
1068
        return false;
1069
    return d->getFileFlags(QAbstractFileEngine::BundleType);
1070
}
1071
1072
/*!
1073
    Returns true if this object points to a symbolic link (or to a
1074
    shortcut on Windows); otherwise returns false.
1075
1076
    On Unix (including Mac OS X), opening a symlink effectively opens
1077
    the \l{symLinkTarget()}{link's target}. On Windows, it opens the \c
1078
    .lnk file itself.
1079
1080
    Example:
1081
1082
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 9
1083
1084
    \note If the symlink points to a non existing file, exists() returns
1085
     false.
1086
1087
    \sa isFile(), isDir(), symLinkTarget()
1088
*/
1089
1090
bool QFileInfo::isSymLink() const
1091
{
1092
    Q_D(const QFileInfo);
1093
    if(!d->data->fileEngine)
1094
        return false;
1095
    return d->getFileFlags(QAbstractFileEngine::LinkType);
1096
}
1097
1098
/*!
1099
  Returns true if the object points to a directory or to a symbolic
1100
  link to a directory, and that directory is the root directory; otherwise
1101
  returns false.
1102
*/
1103
1104
bool QFileInfo::isRoot() const
1105
{
1106
    Q_D(const QFileInfo);
1107
    if (!d->data->fileEngine)
1108
        return true;
1109
    return d->getFileFlags(QAbstractFileEngine::RootFlag);
1110
}
1111
1112
/*!
1113
    \fn QString QFileInfo::symLinkTarget() const
1114
    \since 4.2
1115
1116
    Returns the absolute path to the file or directory a symlink (or shortcut
1117
    on Windows) points to, or a an empty string if the object isn't a symbolic
1118
    link.
1119
1120
    This name may not represent an existing file; it is only a string.
1121
    QFileInfo::exists() returns true if the symlink points to an
1122
    existing file.
1123
1124
    \sa exists(), isSymLink(), isDir(), isFile()
1125
*/
1126
1127
/*!
1128
    \obsolete
1129
1130
    Use symLinkTarget() instead.
1131
*/
1132
QString QFileInfo::readLink() const
1133
{
1134
    Q_D(const QFileInfo);
1135
    if(!d->data->fileEngine)
1136
        return QLatin1String("");
1137
    return d->getFileName(QAbstractFileEngine::LinkName);
1138
}
1139
1140
/*!
1141
    Returns the owner of the file. On systems where files
1142
    do not have owners, or if an error occurs, an empty string is
1143
    returned.
1144
1145
    This function can be time consuming under Unix (in the order of
1146
    milliseconds).
1147
1148
    \sa ownerId(), group(), groupId()
1149
*/
1150
1151
QString QFileInfo::owner() const
1152
{
1153
    Q_D(const QFileInfo);
1154
    if(!d->data->fileEngine)
1155
        return QLatin1String("");
1156
    return d->data->fileEngine->owner(QAbstractFileEngine::OwnerUser);
1157
}
1158
1159
/*!
1160
    Returns the id of the owner of the file.
1161
1162
    On Windows and on systems where files do not have owners this
1163
    function returns ((uint) -2).
1164
1165
    \sa owner(), group(), groupId()
1166
*/
1167
1168
uint QFileInfo::ownerId() const
1169
{
1170
    Q_D(const QFileInfo);
1171
    if(!d->data->fileEngine)
1172
        return 0;
1173
    return d->data->fileEngine->ownerId(QAbstractFileEngine::OwnerUser);
1174
}
1175
1176
/*!
1177
    Returns the group of the file. On Windows, on systems where files
1178
    do not have groups, or if an error occurs, an empty string is
1179
    returned.
1180
1181
    This function can be time consuming under Unix (in the order of
1182
    milliseconds).
1183
1184
    \sa groupId(), owner(), ownerId()
1185
*/
1186
1187
QString QFileInfo::group() const
1188
{
1189
    Q_D(const QFileInfo);
1190
    if(!d->data->fileEngine)
1191
        return QLatin1String("");
1192
    return d->data->fileEngine->owner(QAbstractFileEngine::OwnerGroup);
1193
}
1194
1195
/*!
1196
    Returns the id of the group the file belongs to.
1197
1198
    On Windows and on systems where files do not have groups this
1199
    function always returns (uint) -2.
1200
1201
    \sa group(), owner(), ownerId()
1202
*/
1203
1204
uint QFileInfo::groupId() const
1205
{
1206
    Q_D(const QFileInfo);
1207
    if(!d->data->fileEngine)
1208
        return 0;
1209
    return d->data->fileEngine->ownerId(QAbstractFileEngine::OwnerGroup);
1210
}
1211
1212
/*!
1213
    Tests for file permissions. The \a permissions argument can be
1214
    several flags of type QFile::Permissions OR-ed together to check
1215
    for permission combinations.
1216
1217
    On systems where files do not have permissions this function
1218
    always returns true.
1219
1220
    Example:
1221
    \snippet doc/src/snippets/code/src_corelib_io_qfileinfo.cpp 10
1222
1223
    \sa isReadable(), isWritable(), isExecutable()
1224
*/
1225
1226
bool QFileInfo::permission(QFile::Permissions permissions) const
1227
{
1228
    Q_D(const QFileInfo);
1229
    if(!d->data->fileEngine)
1230
        return false;
1231
    return d->getFileFlags(QAbstractFileEngine::FileFlags((int)permissions)) == (uint)permissions;
1232
}
1233
1234
/*!
1235
    Returns the complete OR-ed together combination of
1236
    QFile::Permissions for the file.
1237
*/
1238
1239
QFile::Permissions QFileInfo::permissions() const
1240
{
1241
    Q_D(const QFileInfo);
1242
    if(!d->data->fileEngine)
1243
        return 0;
1244
    return QFile::Permissions(d->getFileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask);
1245
}
1246
1247
1248
/*!
1249
    Returns the file size in bytes. If the file does not exist or cannot be
1250
    fetched, 0 is returned.
1251
1252
    \sa exists()
1253
*/
1254
1255
qint64 QFileInfo::size() const
1256
{
1257
    Q_D(const QFileInfo);
1258
    if(!d->data->fileEngine)
1259
        return 0;
1260
    if(!d->data->getCachedFlag(QFileInfoPrivate::CachedSize)) {
1261
        d->data->setCachedFlag(QFileInfoPrivate::CachedSize);
1262
        d->data->fileSize = d->data->fileEngine->size();
1263
    }
1264
    return d->data->fileSize;
1265
}
1266
1267
/*!
1268
    Returns the date and time when the file was created.
1269
1270
    On most Unix systems, this function returns the time of the last
1271
    status change. A status change occurs when the file is created,
1272
    but it also occurs whenever the user writes or sets inode
1273
    information (for example, changing the file permissions).
1274
1275
    If neither creation time nor "last status change" time are not
1276
    available, returns the same as lastModified().
1277
1278
    \sa lastModified() lastRead()
1279
*/
1280
1281
QDateTime QFileInfo::created() const
1282
{
1283
    Q_D(const QFileInfo);
1284
    if(!d->data->fileEngine)
1285
        return QDateTime();
1286
    return d->getFileTime(QAbstractFileEngine::CreationTime);
1287
}
1288
1289
/*!
1290
    Returns the date and time when the file was last modified.
1291
1292
    \sa created() lastRead()
1293
*/
1294
1295
QDateTime QFileInfo::lastModified() const
1296
{
1297
    Q_D(const QFileInfo);
1298
    if(!d->data->fileEngine)
1299
        return QDateTime();
1300
    return d->getFileTime(QAbstractFileEngine::ModificationTime);
1301
}
1302
1303
/*!
1304
    Returns the date and time when the file was last read (accessed).
1305
1306
    On platforms where this information is not available, returns the
1307
    same as lastModified().
1308
1309
    \sa created() lastModified()
1310
*/
1311
1312
QDateTime QFileInfo::lastRead() const
1313
{
1314
    Q_D(const QFileInfo);
1315
    if(!d->data->fileEngine)
1316
        return QDateTime();
1317
    return d->getFileTime(QAbstractFileEngine::AccessTime);
1318
}
1319
1320
/*! \internal
1321
    Detaches all internal data.
1322
*/
1323
1324
void QFileInfo::detach()
1325
{
1326
    Q_D(QFileInfo);
1327
    d->detach();
1328
}
1329
1330
/*!
1331
    Returns true if caching is enabled; otherwise returns false.
1332
1333
    \sa setCaching(), refresh()
1334
*/
1335
1336
bool QFileInfo::caching() const
1337
{
1338
    Q_D(const QFileInfo);
1339
    return d->data->cache_enabled;
1340
}
1341
1342
/*!
1343
    If \a enable is true, enables caching of file information. If \a
1344
    enable is false caching is disabled.
1345
1346
    When caching is enabled, QFileInfo reads the file information from
1347
    the file system the first time it's needed, but generally not
1348
    later.
1349
1350
    Caching is enabled by default.
1351
1352
    \sa refresh(), caching()
1353
*/
1354
1355
void QFileInfo::setCaching(bool enable)
1356
{
1357
    Q_D(QFileInfo);
1358
    detach();
1359
    d->data->cache_enabled = enable;
1360
}
1361
1362
/*!
1363
    \fn QString QFileInfo::baseName(bool complete)
1364
1365
    Use completeBaseName() or the baseName() overload that takes no
1366
    parameters instead.
1367
*/
1368
1369
/*!
1370
    \fn QString QFileInfo::extension(bool complete = true) const
1371
1372
    Use completeSuffix() or suffix() instead.
1373
*/
1374
1375
/*!
1376
    \fn QString QFileInfo::absFilePath() const
1377
1378
    Use absoluteFilePath() instead.
1379
*/
1380
1381
/*!
1382
    \fn QString QFileInfo::dirPath(bool absPath) const
1383
1384
    Use absolutePath() if the absolute path is wanted (\a absPath
1385
    is true) or path() if it's not necessary (\a absPath is false).
1386
*/
1387
1388
/*!
1389
    \fn bool QFileInfo::convertToAbs()
1390
1391
    Use makeAbsolute() instead.
1392
*/
1393
1394
/*!
1395
    \enum QFileInfo::Permission
1396
1397
    \compat
1398
1399
    \value ReadOwner
1400
    \value WriteOwner
1401
    \value ExeOwner
1402
    \value ReadUser
1403
    \value WriteUser
1404
    \value ExeUser
1405
    \value ReadGroup
1406
    \value WriteGroup
1407
    \value ExeGroup
1408
    \value ReadOther
1409
    \value WriteOther
1410
    \value ExeOther
1411
*/
1412
1413
/*!
1414
    \fn bool QFileInfo::permission(PermissionSpec permissions) const
1415
    \compat
1416
1417
    Use permission() instead.
1418
*/
1419
1420
/*!
1421
    \typedef QFileInfoList
1422
    \relates QFileInfo
1423
1424
    Synonym for QList<QFileInfo>.
1425
*/
1426
1427
QT_END_NAMESPACE