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 "qdebug.h"
44
#include "qfile.h"
45
#include "qfsfileengine.h"
46
#include "qtemporaryfile.h"
47
#include "qlist.h"
48
#include "qfileinfo.h"
49
#include "private/qiodevice_p.h"
50
#include "private/qfile_p.h"
51
#if defined(QT_BUILD_CORE_LIB)
52
# include "qcoreapplication.h"
53
#endif
54
55
#if !defined(Q_OS_WINCE)
56
#include <errno.h>
57
#endif
58
59
#ifdef QT_NO_QOBJECT
60
#define tr(X) QString::fromLatin1(X)
61
#endif
62
63
QT_BEGIN_NAMESPACE
64
65
static const int QFILE_WRITEBUFFER_SIZE = 16384;
66
67
static QByteArray locale_encode(const QString &f)
68
{
69
#ifndef Q_OS_DARWIN
70
    return f.toLocal8Bit();
71
#else
72
    // Mac always expects UTF-8... and decomposed...
73
    return f.normalized(QString::NormalizationForm_D).toUtf8();
74
#endif
75
}
76
77
static QString locale_decode(const QByteArray &f)
78
{
79
#ifndef Q_OS_DARWIN
80
    return QString::fromLocal8Bit(f);
81
#else
82
    // Mac always gives us UTF-8 and decomposed, we want that composed...
83
    return QString::fromUtf8(f).normalized(QString::NormalizationForm_C);
84
#endif
85
}
86
87
//************* QFilePrivate
88
QFile::EncoderFn QFilePrivate::encoder = locale_encode;
89
QFile::DecoderFn QFilePrivate::decoder = locale_decode;
90
91
QFilePrivate::QFilePrivate()
92
    : fileEngine(0), lastWasWrite(false),
93
      writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError)
94
{
95
}
96
97
QFilePrivate::~QFilePrivate()
98
{
99
    delete fileEngine;
100
    fileEngine = 0;
101
}
102
103
bool
104
QFilePrivate::openExternalFile(int flags, int fd)
105
{
106
#ifdef QT_NO_FSFILEENGINE
107
    Q_UNUSED(flags);
108
    Q_UNUSED(fd);
109
    return false;
110
#else
111
    delete fileEngine;
112
    QFSFileEngine *fe = new QFSFileEngine;
113
    fe->setFileName(fileName);
114
    fileEngine = fe;
115
    return fe->open(QIODevice::OpenMode(flags), fd);
116
#endif
117
}
118
119
bool
120
QFilePrivate::openExternalFile(int flags, FILE *fh)
121
{
122
#ifdef QT_NO_FSFILEENGINE
123
    Q_UNUSED(flags);
124
    Q_UNUSED(fh);
125
    return false;
126
#else
127
    delete fileEngine;
128
    QFSFileEngine *fe = new QFSFileEngine;
129
    fe->setFileName(fileName);
130
    fileEngine = fe;
131
    return fe->open(QIODevice::OpenMode(flags), fh);
132
#endif
133
}
134
135
inline bool QFilePrivate::ensureFlushed() const
136
{
137
    // This function ensures that the write buffer has been flushed (const
138
    // because certain const functions need to call it.
139
    if (lastWasWrite) {
140
        const_cast<QFilePrivate *>(this)->lastWasWrite = false;
141
        if (!const_cast<QFile *>(q_func())->flush())
142
            return false;
143
    }
144
    return true;
145
}
146
147
void
148
QFilePrivate::setError(QFile::FileError err)
149
{
150
    error = err;
151
    errorString.clear();
152
}
153
154
void
155
QFilePrivate::setError(QFile::FileError err, const QString &errStr)
156
{
157
    Q_Q(QFile);
158
    error = err;
159
    q->setErrorString(errStr);
160
}
161
162
void
163
QFilePrivate::setError(QFile::FileError err, int errNum)
164
{
165
    Q_Q(QFile);
166
    error = err;
167
    q->setErrorString(qt_error_string(errNum));
168
}
169
170
//************* QFile
171
172
/*!
173
    \class QFile
174
    \brief The QFile class provides an interface for reading from and writing to files.
175
176
    \ingroup io
177
    \mainclass
178
    \reentrant
179
180
    QFile is an I/O device for reading and writing text and binary
181
    files and \l{The Qt Resource System}{resources}. A QFile may be
182
    used by itself or, more conveniently, with a QTextStream or
183
    QDataStream.
184
185
    The file name is usually passed in the constructor, but it can be
186
    set at any time using setFileName(). QFile expects the file
187
    separator to be '/' regardless of operating system. The use of
188
    other separators (e.g., '\\') is not supported.
189
190
    You can check for a file's existence using exists(), and remove a
191
    file using remove(). (More advanced file system related operations
192
    are provided by QFileInfo and QDir.)
193
194
    The file is opened with open(), closed with close(), and flushed
195
    with flush(). Data is usually read and written using QDataStream
196
    or QTextStream, but you can also call the QIODevice-inherited
197
    functions read(), readLine(), readAll(), write(). QFile also
198
    inherits getChar(), putChar(), and ungetChar(), which work one
199
    character at a time.
200
201
    The size of the file is returned by size(). You can get the
202
    current file position using pos(), or move to a new file position
203
    using seek(). If you've reached the end of the file, atEnd()
204
    returns true.
205
206
    \section1 Reading Files Directly
207
208
    The following example reads a text file line by line:
209
210
    \snippet doc/src/snippets/file/file.cpp 0
211
212
    The QIODevice::Text flag passed to open() tells Qt to convert
213
    Windows-style line terminators ("\\r\\n") into C++-style
214
    terminators ("\\n"). By default, QFile assumes binary, i.e. it
215
    doesn't perform any conversion on the bytes stored in the file.
216
217
    \section1 Using Streams to Read Files
218
219
    The next example uses QTextStream to read a text file
220
    line by line:
221
222
    \snippet doc/src/snippets/file/file.cpp 1
223
224
    QTextStream takes care of converting the 8-bit data stored on
225
    disk into a 16-bit Unicode QString. By default, it assumes that
226
    the user system's local 8-bit encoding is used (e.g., ISO 8859-1
227
    for most of Europe; see QTextCodec::codecForLocale() for
228
    details). This can be changed using setCodec().
229
230
    To write text, we can use operator<<(), which is overloaded to
231
    take a QTextStream on the left and various data types (including
232
    QString) on the right:
233
234
    \snippet doc/src/snippets/file/file.cpp 2
235
236
    QDataStream is similar, in that you can use operator<<() to write
237
    data and operator>>() to read it back. See the class
238
    documentation for details.
239
240
    When you use QFile, QFileInfo, and QDir to access the file system
241
    with Qt, you can use Unicode file names. On Unix, these file
242
    names are converted to an 8-bit encoding. If you want to use
243
    standard C++ APIs (\c <cstdio> or \c <iostream>) or
244
    platform-specific APIs to access files instead of QFile, you can
245
    use the encodeName() and decodeName() functions to convert
246
    between Unicode file names and 8-bit file names.
247
248
    On Unix, there are some special system files (e.g. in \c /proc) for which
249
    size() will always return 0, yet you may still be able to read more data
250
    from such a file; the data is generated in direct response to you calling
251
    read(). In this case, however, you cannot use atEnd() to determine if
252
    there is more data to read (since atEnd() will return true for a file that
253
    claims to have size 0). Instead, you should either call readAll(), or call
254
    read() or readLine() repeatedly until no more data can be read. The next
255
    example uses QTextStream to read \c /proc/modules line by line:
256
257
    \snippet doc/src/snippets/file/file.cpp 3
258
259
    \section1 Signals
260
261
    Unlike other QIODevice implementations, such as QTcpSocket, QFile does not
262
    emit the aboutToClose(), bytesWritten(), or readyRead() signals. This
263
    implementation detail means that QFile is not suitable for reading and
264
    writing certain types of files, such as device files on Unix platforms.
265
266
    \section1 Platform Specific Issues
267
268
    File permissions are handled differently on Linux/Mac OS X and
269
    Windows.  In a non \l{QIODevice::isWritable()}{writable}
270
    directory on Linux, files cannot be created. This is not always
271
    the case on Windows, where, for instance, the 'My Documents'
272
    directory usually is not writable, but it is still possible to
273
    create files in it.
274
275
    \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
276
*/
277
278
/*!
279
    \enum QFile::FileError
280
281
    This enum describes the errors that may be returned by the error()
282
    function.
283
284
    \value NoError          No error occurred.
285
    \value ReadError        An error occurred when reading from the file.
286
    \value WriteError       An error occurred when writing to the file.
287
    \value FatalError       A fatal error occurred.
288
    \value ResourceError
289
    \value OpenError        The file could not be opened.
290
    \value AbortError       The operation was aborted.
291
    \value TimeOutError     A timeout occurred.
292
    \value UnspecifiedError An unspecified error occurred.
293
    \value RemoveError      The file could not be removed.
294
    \value RenameError      The file could not be renamed.
295
    \value PositionError    The position in the file could not be changed.
296
    \value ResizeError      The file could not be resized.
297
    \value PermissionsError The file could not be accessed.
298
    \value CopyError        The file could not be copied.
299
300
    \omitvalue ConnectError
301
*/
302
303
/*!
304
    \enum QFile::Permission
305
306
    This enum is used by the permission() function to report the
307
    permissions and ownership of a file. The values may be OR-ed
308
    together to test multiple permissions and ownership values.
309
310
    \value ReadOwner The file is readable by the owner of the file.
311
    \value WriteOwner The file is writable by the owner of the file.
312
    \value ExeOwner The file is executable by the owner of the file.
313
    \value ReadUser The file is readable by the user.
314
    \value WriteUser The file is writable by the user.
315
    \value ExeUser The file is executable by the user.
316
    \value ReadGroup The file is readable by the group.
317
    \value WriteGroup The file is writable by the group.
318
    \value ExeGroup The file is executable by the group.
319
    \value ReadOther The file is readable by anyone.
320
    \value WriteOther The file is writable by anyone.
321
    \value ExeOther The file is executable by anyone.
322
323
    \warning Because of differences in the platforms supported by Qt,
324
    the semantics of ReadUser, WriteUser and ExeUser are
325
    platform-dependent: On Unix, the rights of the owner of the file
326
    are returned and on Windows the rights of the current user are
327
    returned. This behavior might change in a future Qt version.
328
329
    Note that Qt does not by default check for permissions on NTFS
330
    file systems, as this may decrease the performance of file
331
    handling considerably. It is possible to force permission checking
332
    on NTFS by including the following code in your source:
333
334
    \snippet doc/src/snippets/ntfsp.cpp 0
335
336
    Permission checking is then turned on and off by incrementing and
337
    decrementing \c qt_ntfs_permission_lookup by 1.
338
339
    \snippet doc/src/snippets/ntfsp.cpp 1
340
*/
341
342
#ifdef QT3_SUPPORT
343
/*!
344
    \typedef QFile::PermissionSpec
345
346
    Use QFile::Permission instead.
347
*/
348
#endif
349
350
#ifdef QT_NO_QOBJECT
351
QFile::QFile()
352
    : QIODevice(*new QFilePrivate)
353
{
354
}
355
QFile::QFile(const QString &name)
356
    : QIODevice(*new QFilePrivate)
357
{
358
    d_func()->fileName = name;
359
}
360
QFile::QFile(QFilePrivate &dd)
361
    : QIODevice(dd)
362
{
363
}
364
#else
365
/*!
366
    \internal
367
*/
368
QFile::QFile()
369
    : QIODevice(*new QFilePrivate, 0)
370
{
371
}
372
/*!
373
    Constructs a new file object with the given \a parent.
374
*/
375
QFile::QFile(QObject *parent)
376
    : QIODevice(*new QFilePrivate, parent)
377
{
378
}
379
/*!
380
    Constructs a new file object to represent the file with the given \a name.
381
*/
382
QFile::QFile(const QString &name)
383
    : QIODevice(*new QFilePrivate, 0)
384
{
385
    Q_D(QFile);
386
    d->fileName = name;
387
}
388
/*!
389
    Constructs a new file object with the given \a parent to represent the
390
    file with the specified \a name.
391
*/
392
QFile::QFile(const QString &name, QObject *parent)
393
    : QIODevice(*new QFilePrivate, parent)
394
{
395
    Q_D(QFile);
396
    d->fileName = name;
397
}
398
/*!
399
    \internal
400
*/
401
QFile::QFile(QFilePrivate &dd, QObject *parent)
402
    : QIODevice(dd, parent)
403
{
404
}
405
#endif
406
407
/*!
408
    Destroys the file object, closing it if necessary.
409
*/
410
QFile::~QFile()
411
{
412
    close();
413
#ifdef QT_NO_QOBJECT
414
    delete d_ptr;
415
#endif
416
}
417
418
/*!
419
    Returns the name set by setFileName() or to the QFile
420
    constructors.
421
422
    \sa setFileName(), QFileInfo::fileName()
423
*/
424
QString QFile::fileName() const
425
{
426
    return fileEngine()->fileName(QAbstractFileEngine::DefaultName);
427
}
428
429
/*!
430
    Sets the \a name of the file. The name can have no path, a
431
    relative path, or an absolute path.
432
433
    Do not call this function if the file has already been opened.
434
435
    If the file name has no path or a relative path, the path used
436
    will be the application's current directory path
437
    \e{at the time of the open()} call.
438
439
    Example:
440
    \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 0
441
442
    Note that the directory separator "/" works for all operating
443
    systems supported by Qt.
444
445
    \sa fileName(), QFileInfo, QDir
446
*/
447
void
448
QFile::setFileName(const QString &name)
449
{
450
    Q_D(QFile);
451
    if (isOpen()) {
452
        qWarning("QFile::setFileName: File (%s) is already opened",
453
                 qPrintable(fileName()));
454
        close();
455
    }
456
    if(d->fileEngine) { //get a new file engine later
457
        delete d->fileEngine;
458
        d->fileEngine = 0;
459
    }
460
    d->fileName = name;
461
}
462
463
/*!
464
    \fn QString QFile::decodeName(const char *localFileName)
465
466
    \overload
467
468
    Returns the Unicode version of the given \a localFileName. See
469
    encodeName() for details.
470
*/
471
472
/*!
473
    By default, this function converts \a fileName to the local 8-bit
474
    encoding determined by the user's locale. This is sufficient for
475
    file names that the user chooses. File names hard-coded into the
476
    application should only use 7-bit ASCII filename characters.
477
478
    \sa decodeName() setEncodingFunction()
479
*/
480
481
QByteArray
482
QFile::encodeName(const QString &fileName)
483
{
484
    return (*QFilePrivate::encoder)(fileName);
485
}
486
487
/*!
488
    \typedef QFile::EncoderFn
489
490
    This is a typedef for a pointer to a function with the following
491
    signature:
492
493
    \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 1
494
495
    \sa setEncodingFunction(), encodeName()
496
*/
497
498
/*!
499
    This does the reverse of QFile::encodeName() using \a localFileName.
500
501
    \sa setDecodingFunction(), encodeName()
502
*/
503
504
QString
505
QFile::decodeName(const QByteArray &localFileName)
506
{
507
    return (*QFilePrivate::decoder)(localFileName);
508
}
509
510
/*!
511
    \fn void QFile::setEncodingFunction(EncoderFn function)
512
513
    \nonreentrant
514
515
    Sets the \a function for encoding Unicode file names. The
516
    default encodes in the locale-specific 8-bit encoding.
517
518
    \sa encodeName(), setDecodingFunction()
519
*/
520
521
void
522
QFile::setEncodingFunction(EncoderFn f)
523
{
524
    if (!f)
525
        f = locale_encode;
526
    QFilePrivate::encoder = f;
527
}
528
529
/*!
530
    \typedef QFile::DecoderFn
531
532
    This is a typedef for a pointer to a function with the following
533
    signature:
534
535
    \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 2
536
537
    \sa setDecodingFunction()
538
*/
539
540
/*!
541
    \fn void QFile::setDecodingFunction(DecoderFn function)
542
543
    \nonreentrant
544
545
    Sets the \a function for decoding 8-bit file names. The
546
    default uses the locale-specific 8-bit encoding.
547
548
    \sa setEncodingFunction(), decodeName()
549
*/
550
551
void
552
QFile::setDecodingFunction(DecoderFn f)
553
{
554
    if (!f)
555
        f = locale_decode;
556
    QFilePrivate::decoder = f;
557
}
558
559
/*!
560
    \overload
561
562
    Returns true if the file specified by fileName() exists; otherwise
563
    returns false.
564
565
    \sa fileName(), setFileName()
566
*/
567
568
bool
569
QFile::exists() const
570
{
571
    // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
572
    return (fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask
573
                                    | QAbstractFileEngine::FileFlag(0x1000000)) & QAbstractFileEngine::ExistsFlag);
574
}
575
576
/*!
577
    Returns true if the file specified by \a fileName exists; otherwise
578
    returns false.
579
*/
580
581
bool
582
QFile::exists(const QString &fileName)
583
{
584
    return QFileInfo(fileName).exists();
585
}
586
587
/*!
588
    \fn QString QFile::symLinkTarget() const
589
    \since 4.2
590
    \overload
591
592
    Returns the absolute path of the file or directory a symlink (or shortcut
593
    on Windows) points to, or a an empty string if the object isn't a symbolic
594
    link.
595
596
    This name may not represent an existing file; it is only a string.
597
    QFile::exists() returns true if the symlink points to an existing file.
598
599
    \sa fileName() setFileName()
600
*/
601
602
/*!
603
    \obsolete
604
605
    Use symLinkTarget() instead.
606
*/
607
QString
608
QFile::readLink() const
609
{
610
    return fileEngine()->fileName(QAbstractFileEngine::LinkName);
611
}
612
613
/*!
614
    \fn static QString QFile::symLinkTarget(const QString &fileName)
615
    \since 4.2
616
617
    Returns the absolute path of the file or directory referred to by the
618
    symlink (or shortcut on Windows) specified by \a fileName, or returns an
619
    empty string if the \a fileName does not correspond to a symbolic link.
620
621
    This name may not represent an existing file; it is only a string.
622
    QFile::exists() returns true if the symlink points to an existing file.
623
*/
624
625
/*!
626
    \obsolete
627
628
    Use symLinkTarget() instead.
629
*/
630
QString
631
QFile::readLink(const QString &fileName)
632
{
633
    return QFileInfo(fileName).readLink();
634
}
635
636
/*!
637
    Removes the file specified by fileName(). Returns true if successful;
638
    otherwise returns false.
639
640
    The file is closed before it is removed.
641
642
    \sa setFileName()
643
*/
644
645
bool
646
QFile::remove()
647
{
648
    Q_D(QFile);
649
    if (d->fileName.isEmpty()) {
650
        qWarning("QFile::remove: Empty or null file name");
651
        return false;
652
    }
653
    close();
654
    if(error() == QFile::NoError) {
655
        if(fileEngine()->remove()) {
656
            unsetError();
657
            return true;
658
        }
659
#if defined(Q_OS_WIN)
660
        d->setError(QFile::RemoveError, GetLastError());
661
#else
662
        d->setError(QFile::RemoveError, errno);
663
#endif
664
    }
665
    return false;
666
}
667
668
/*!
669
    \overload
670
671
    Removes the file specified by the \a fileName given.
672
673
    Returns true if successful; otherwise returns false.
674
675
    \sa remove()
676
*/
677
678
bool
679
QFile::remove(const QString &fileName)
680
{
681
    return QFile(fileName).remove();
682
}
683
684
/*!
685
    Renames the file currently specified by fileName() to \a newName.
686
    Returns true if successful; otherwise returns false.
687
688
    If a file with the name \a newName already exists, rename() returns false
689
    (i.e., QFile will not overwrite it).
690
691
    The file is closed before it is renamed.
692
693
    \sa setFileName()
694
*/
695
696
bool
697
QFile::rename(const QString &newName)
698
{
699
    Q_D(QFile);
700
    if (d->fileName.isEmpty()) {
701
        qWarning("QFile::rename: Empty or null file name");
702
        return false;
703
    }
704
    if (QFile(newName).exists()) {
705
        // ### Race condition. If a file is moved in after this, it /will/ be
706
        // overwritten. On Unix, the proper solution is to use hardlinks:
707
        // return ::link(old, new) && ::remove(old);
708
        d->setError(QFile::RenameError, tr("Destination file exists"));
709
        return false;
710
    }
711
    close();
712
    if(error() == QFile::NoError) {
713
        if (fileEngine()->rename(newName)) {
714
            unsetError();
715
            // engine was able to handle the new name so we just reset it
716
            fileEngine()->setFileName(newName);
717
            d->fileName = newName;
718
            return true;
719
        }
720
721
        if (isSequential()) {
722
            d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
723
            return false;
724
        }
725
726
        QFile out(newName);
727
        if (open(QIODevice::ReadOnly)) {
728
            if (out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
729
                bool error = false;
730
                char block[4096];
731
                qint64 bytes;
732
                while ((bytes = read(block, sizeof(block))) > 0) {
733
                    if (bytes != out.write(block, bytes)) {
734
                        d->setError(QFile::RenameError, out.errorString());
735
                        error = true;
736
                        break;
737
                    }
738
                }
739
                if (bytes == -1) {
740
                    d->setError(QFile::RenameError, errorString());
741
                    error = true;
742
                }
743
                if(!error) {
744
                    if (!remove()) {
745
                        d->setError(QFile::RenameError, tr("Cannot remove source file"));
746
                        error = true;
747
                    }
748
                }
749
                if (error)
750
                    out.remove();
751
                else {
752
                    setPermissions(permissions());
753
                    unsetError();
754
                    setFileName(newName);
755
                }
756
                close();
757
                return !error;
758
            }
759
            close();
760
        }
761
        d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString());
762
    }
763
    return false;
764
}
765
766
/*!
767
    \overload
768
769
    Renames the file \a oldName to \a newName. Returns true if
770
    successful; otherwise returns false.
771
772
    If a file with the name \a newName already exists, rename() returns false
773
    (i.e., QFile will not overwrite it).
774
775
    \sa rename()
776
*/
777
778
bool
779
QFile::rename(const QString &oldName, const QString &newName)
780
{
781
    return QFile(oldName).rename(newName);
782
}
783
784
/*!
785
786
    Creates a link named \a linkName that points to the file currently specified by
787
    fileName().  What a link is depends on the underlying filesystem (be it a
788
    shortcut on Windows or a symbolic link on Unix). Returns true if successful;
789
    otherwise returns false.
790
791
    This function will not overwrite an already existing entity in the file system;
792
    in this case, \c link() will return false and set \l{QFile::}{error()} to
793
    return \l{QFile::}{RenameError}.
794
795
    \note To create a valid link on Windows, \a linkName must have a \c{.lnk} file extension.
796
797
    \sa setFileName()
798
*/
799
800
bool
801
QFile::link(const QString &linkName)
802
{
803
    Q_D(QFile);
804
    if (d->fileName.isEmpty()) {
805
        qWarning("QFile::link: Empty or null file name");
806
        return false;
807
    }
808
    QFileInfo fi(linkName);
809
    if(fileEngine()->link(fi.absoluteFilePath())) {
810
        unsetError();
811
        return true;
812
    }
813
    d->setError(QFile::RenameError, errno);
814
    return false;
815
}
816
817
/*!
818
    \overload
819
820
    Creates a link named \a linkName that points to the file \a fileName. What a link is
821
    depends on the underlying filesystem (be it a shortcut on Windows
822
    or a symbolic link on Unix). Returns true if successful; otherwise
823
    returns false.
824
825
    \sa link()
826
*/
827
828
bool
829
QFile::link(const QString &fileName, const QString &linkName)
830
{
831
    return QFile(fileName).link(linkName);
832
}
833
834
/*!
835
    Copies the file currently specified by fileName() to a file called
836
    \a newName.  Returns true if successful; otherwise returns false.
837
838
    Note that if a file with the name \a newName already exists,
839
    copy() returns false (i.e. QFile will not overwrite it).
840
841
    The source file is closed before it is copied.
842
843
    \sa setFileName()
844
*/
845
846
bool
847
QFile::copy(const QString &newName)
848
{
849
    Q_D(QFile);
850
    if (d->fileName.isEmpty()) {
851
        qWarning("QFile::copy: Empty or null file name");
852
        return false;
853
    }
854
    if (QFile(newName).exists()) {
855
        // ### Race condition. If a file is moved in after this, it /will/ be
856
        // overwritten. On Unix, the proper solution is to use hardlinks:
857
        // return ::link(old, new) && ::remove(old); See also rename().
858
        d->setError(QFile::CopyError, tr("Destination file exists"));
859
        return false;
860
    }
861
    close();
862
    if(error() == QFile::NoError) {
863
        if(fileEngine()->copy(newName)) {
864
            unsetError();
865
            return true;
866
        } else {
867
            bool error = false;
868
            if(!open(QFile::ReadOnly)) {
869
                error = true;
870
                d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
871
            } else {
872
                QString fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
873
#ifdef QT_NO_TEMPORARYFILE
874
                QFile out(fileTemplate.arg(QFileInfo(newName).path()));
875
                if (!out.open(QIODevice::ReadWrite))
876
                    error = true;
877
#else
878
                QTemporaryFile out(fileTemplate.arg(QFileInfo(newName).path()));
879
                if (!out.open()) {
880
                    out.setFileTemplate(fileTemplate.arg(QDir::tempPath()));
881
                    if (!out.open())
882
                        error = true;
883
                }
884
#endif
885
                if (error) {
886
                    out.close();
887
                    d->setError(QFile::CopyError, tr("Cannot open for output"));
888
                } else {
889
                    char block[4096];
890
                    qint64 totalRead = 0;
891
                    while(!atEnd()) {
892
                        qint64 in = read(block, sizeof(block));
893
                        if (in <= 0)
894
                            break;
895
                        totalRead += in;
896
                        if(in != out.write(block, in)) {
897
                            d->setError(QFile::CopyError, tr("Failure to write block"));
898
                            error = true;
899
                            break;
900
                        }
901
                    }
902
903
                    if (totalRead != size()) {
904
                        // Unable to read from the source. The error string is
905
                        // already set from read().
906
                        error = true;
907
                    }
908
                    if (!error && !out.rename(newName)) {
909
                        error = true;
910
                        d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
911
                    }
912
#ifdef QT_NO_TEMPORARYFILE
913
                    if (error)
914
                        out.remove();
915
#else
916
                    if (!error)
917
                        out.setAutoRemove(false);
918
#endif
919
                }
920
                close();
921
            }
922
            if(!error) {
923
                QFile::setPermissions(newName, permissions());
924
                unsetError();
925
                return true;
926
            }
927
        }
928
    }
929
    return false;
930
}
931
932
/*!
933
    \overload
934
935
    Copies the file \a fileName to \a newName. Returns true if successful;
936
    otherwise returns false.
937
938
    If a file with the name \a newName already exists, copy() returns false
939
    (i.e., QFile will not overwrite it).
940
941
    \sa rename()
942
*/
943
944
bool
945
QFile::copy(const QString &fileName, const QString &newName)
946
{
947
    return QFile(fileName).copy(newName);
948
}
949
950
/*!
951
    Returns true if the file can only be manipulated sequentially;
952
    otherwise returns false.
953
954
    Most files support random-access, but some special files may not.
955
956
    \sa QIODevice::isSequential()
957
*/
958
bool QFile::isSequential() const
959
{
960
    Q_D(const QFile);
961
    return d->fileEngine && d->fileEngine->isSequential();
962
}
963
964
/*!
965
    Opens the file using OpenMode \a mode, returning true if successful;
966
    otherwise false.
967
968
    The \a mode must be QIODevice::ReadOnly, QIODevice::WriteOnly, or
969
    QIODevice::ReadWrite. It may also have additional flags, such as
970
    QIODevice::Text and QIODevice::Unbuffered.
971
972
    \note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite}
973
    mode, if the relevant file does not already exist, this function
974
    will try to create a new file before opening it.
975
976
    \note Because of limitations in the native API, QFile ignores the
977
    Unbuffered flag on Windows.
978
979
    \sa QIODevice::OpenMode, setFileName()
980
*/
981
bool QFile::open(OpenMode mode)
982
{
983
    Q_D(QFile);
984
    if (isOpen()) {
985
        qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
986
        return false;
987
    }
988
    if (mode & Append)
989
        mode |= WriteOnly;
990
991
    unsetError();
992
    if ((mode & (ReadOnly | WriteOnly)) == 0) {
993
        qWarning("QIODevice::open: File access not specified");
994
        return false;
995
    }
996
    if (fileEngine()->open(mode)) {
997
        QIODevice::open(mode);
998
        if (mode & Append)
999
            seek(size());
1000
        return true;
1001
    }
1002
    QFile::FileError err = fileEngine()->error();
1003
    if(err == QFile::UnspecifiedError)
1004
        err = QFile::OpenError;
1005
    d->setError(err, fileEngine()->errorString());
1006
    return false;
1007
}
1008
1009
/*! \fn QFile::open(OpenMode, FILE*)
1010
1011
    Use open(FILE *, OpenMode) instead.
1012
*/
1013
1014
/*!
1015
    \overload
1016
1017
    Opens the existing file handle \a fh in the given \a mode.
1018
    Returns true if successful; otherwise returns false.
1019
1020
    Example:
1021
    \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 3
1022
1023
    When a QFile is opened using this function, close() does not actually
1024
    close the file, but only flushes it.
1025
1026
    \bold{Warning:}
1027
    \list 1
1028
        \o If \a fh is \c stdin, \c stdout, or \c stderr, you may not be able
1029
           to seek(). See QIODevice::isSequential() for more information.
1030
        \o Since this function opens the file without specifying the file name,
1031
           you cannot use this QFile with a QFileInfo.
1032
    \endlist
1033
1034
    \note For Windows CE you may not be able to call seek() and resize().
1035
    Also, size() is set to \c 0.
1036
1037
    \sa close(), {qmake Variable Reference#CONFIG}{qmake Variable Reference}
1038
1039
    \bold{Note for the Windows Platform}
1040
1041
    \a fh must be opened in binary mode (i.e., the mode string must contain
1042
    'b', as in "rb" or "wb") when accessing files and other random-access
1043
    devices. Qt will translate the end-of-line characters if you pass
1044
    QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
1045
    are unaffected by this limitation.
1046
1047
    You need to enable support for console applications in order to use the
1048
    stdin, stdout and stderr streams at the console. To do this, add the
1049
    following declaration to your application's project file:
1050
1051
    \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 4
1052
*/
1053
bool QFile::open(FILE *fh, OpenMode mode)
1054
{
1055
    Q_D(QFile);
1056
    if (isOpen()) {
1057
        qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1058
        return false;
1059
    }
1060
    if (mode & Append)
1061
        mode |= WriteOnly;
1062
    unsetError();
1063
    if ((mode & (ReadOnly | WriteOnly)) == 0) {
1064
        qWarning("QFile::open: File access not specified");
1065
        return false;
1066
    }
1067
    if(d->openExternalFile(mode, fh)) {
1068
        QIODevice::open(mode);
1069
        if (mode & Append) {
1070
            seek(size());
1071
        } else {
1072
            long pos = ftell(fh);
1073
            if (pos != -1)
1074
                seek(pos);
1075
        }
1076
        return true;
1077
    }
1078
    return false;
1079
}
1080
1081
/*! \fn QFile::open(OpenMode, int)
1082
1083
    Use open(int, OpenMode) instead.
1084
*/
1085
1086
/*!
1087
    \overload
1088
1089
    Opens the existing file descripter \a fd in the given \a mode.
1090
    Returns true if successful; otherwise returns false.
1091
1092
    When a QFile is opened using this function, close() does not
1093
    actually close the file.
1094
1095
    The QFile that is opened using this function is automatically set
1096
    to be in raw mode; this means that the file input/output functions
1097
    are slow. If you run into performance issues, you should try to
1098
    use one of the other open functions.
1099
1100
    \warning If \a fd is 0 (\c stdin), 1 (\c stdout), or 2 (\c
1101
    stderr), you may not be able to seek(). size() is set to \c
1102
    LLONG_MAX (in \c <climits>).
1103
1104
    \warning For Windows CE you may not be able to call seek(), setSize(),
1105
    fileTime(). size() is set to \c 0.
1106
1107
    \warning Since this function opens the file without specifying the file name,
1108
             you cannot use this QFile with a QFileInfo.
1109
1110
    \sa close()
1111
*/
1112
bool QFile::open(int fd, OpenMode mode)
1113
{
1114
    Q_D(QFile);
1115
    if (isOpen()) {
1116
        qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1117
        return false;
1118
    }
1119
    if (mode & Append)
1120
        mode |= WriteOnly;
1121
    unsetError();
1122
    if ((mode & (ReadOnly | WriteOnly)) == 0) {
1123
        qWarning("QFile::open: File access not specified");
1124
        return false;
1125
    }
1126
    if(d->openExternalFile(mode, fd)) {
1127
        QIODevice::open(mode);
1128
        if (mode & Append)
1129
            seek(size());
1130
        return true;
1131
    }
1132
    return false;
1133
}
1134
1135
/*!
1136
  Returns the file handle of the file.
1137
1138
  This is a small positive integer, suitable for use with C library
1139
  functions such as fdopen() and fcntl(). On systems that use file
1140
  descriptors for sockets (i.e. Unix systems, but not Windows) the handle
1141
  can be used with QSocketNotifier as well.
1142
1143
  If the file is not open, or there is an error, handle() returns -1.
1144
1145
  This function is not supported on Windows CE.
1146
1147
  \sa QSocketNotifier
1148
*/
1149
1150
int
1151
QFile::handle() const
1152
{
1153
    if (!isOpen())
1154
        return -1;
1155
1156
    if (QAbstractFileEngine *engine = fileEngine())
1157
        return engine->handle();
1158
    return -1;
1159
}
1160
1161
/*!
1162
    \enum QFile::MemoryMapFlags
1163
    \since 4.4
1164
1165
    This enum describes special options that may be used by the map()
1166
    function.
1167
1168
    \value NoOptions        No options.
1169
*/
1170
1171
/*!
1172
    \since 4.4
1173
    Maps \a size bytes of the file into memory starting at \a offset.  A file
1174
    should be open for a map to succeed but the file does not need to stay
1175
    open after the memory has been mapped.  When the QFile is destroyed
1176
    or a new file is opened with this object, any maps that have not been
1177
    unmapped will automatically be unmapped.
1178
1179
    Any mapping options can be passed through \a flags.
1180
1181
    Returns a pointer to the memory or 0 if there is an error.
1182
1183
    \note On Windows CE 5.0 the file will be closed before mapping occurs.
1184
1185
    \sa unmap(), QAbstractFileEngine::supportsExtension()
1186
 */
1187
uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags)
1188
{
1189
    Q_D(QFile);
1190
    QAbstractFileEngine *engine = fileEngine();
1191
    if (engine
1192
        && engine->supportsExtension(QAbstractFileEngine::MapExtension)) {
1193
        unsetError();
1194
        uchar *address = engine->map(offset, size, flags);
1195
        if (address == 0)
1196
            d->setError(engine->error(), engine->errorString());
1197
        return address;
1198
    }
1199
    return 0;
1200
}
1201
1202
/*!
1203
    \since 4.4
1204
    Unmaps the memory \a address.
1205
1206
    Returns true if the unmap succeeds; false otherwise.
1207
1208
    \sa map(), QAbstractFileEngine::supportsExtension()
1209
 */
1210
bool QFile::unmap(uchar *address)
1211
{
1212
    Q_D(QFile);
1213
    QAbstractFileEngine *engine = fileEngine();
1214
    if (engine
1215
        && engine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
1216
        unsetError();
1217
        bool success = engine->unmap(address);
1218
        if (!success)
1219
            d->setError(engine->error(), engine->errorString());
1220
        return success;
1221
    }
1222
    return false;
1223
}
1224
1225
/*!
1226
    \fn QString QFile::name() const
1227
1228
    Use fileName() instead.
1229
*/
1230
1231
/*!
1232
    \fn void QFile::setName(const QString &name)
1233
1234
    Use setFileName() instead.
1235
*/
1236
1237
/*!
1238
    Sets the file size (in bytes) \a sz. Returns true if the file if the
1239
    resize succeeds; false otherwise. If \a sz is larger than the file
1240
    currently is the new bytes will be set to 0, if \a sz is smaller the
1241
    file is simply truncated.
1242
1243
    \sa size(), setFileName()
1244
*/
1245
1246
bool
1247
QFile::resize(qint64 sz)
1248
{
1249
    Q_D(QFile);
1250
    if (!d->ensureFlushed())
1251
        return false;
1252
    if (isOpen() && fileEngine()->pos() > sz)
1253
        seek(sz);
1254
    if(fileEngine()->setSize(sz)) {
1255
        unsetError();
1256
        return true;
1257
    }
1258
    d->setError(QFile::ResizeError, errno);
1259
    return false;
1260
}
1261
1262
/*!
1263
    \overload
1264
1265
    Sets \a fileName to size (in bytes) \a sz. Returns true if the file if
1266
    the resize succeeds; false otherwise. If \a sz is larger than \a
1267
    fileName currently is the new bytes will be set to 0, if \a sz is
1268
    smaller the file is simply truncated.
1269
1270
    \sa resize()
1271
*/
1272
1273
bool
1274
QFile::resize(const QString &fileName, qint64 sz)
1275
{
1276
    return QFile(fileName).resize(sz);
1277
}
1278
1279
/*!
1280
    Returns the complete OR-ed together combination of
1281
    QFile::Permission for the file.
1282
1283
    \sa setPermissions(), setFileName()
1284
*/
1285
1286
QFile::Permissions
1287
QFile::permissions() const
1288
{
1289
    QAbstractFileEngine::FileFlags perms = fileEngine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
1290
    return QFile::Permissions((int)perms); //ewww
1291
}
1292
1293
/*!
1294
    \overload
1295
1296
    Returns the complete OR-ed together combination of
1297
    QFile::Permission for \a fileName.
1298
*/
1299
1300
QFile::Permissions
1301
QFile::permissions(const QString &fileName)
1302
{
1303
    return QFile(fileName).permissions();
1304
}
1305
1306
/*!
1307
    Sets the permissions for the file to the \a permissions specified.
1308
    Returns true if successful, or false if the permissions cannot be
1309
    modified.
1310
1311
    \sa permissions(), setFileName()
1312
*/
1313
1314
bool
1315
QFile::setPermissions(Permissions permissions)
1316
{
1317
    Q_D(QFile);
1318
    if(fileEngine()->setPermissions(permissions)) {
1319
        unsetError();
1320
        return true;
1321
    }
1322
    d->setError(QFile::PermissionsError, errno);
1323
    return false;
1324
}
1325
1326
/*!
1327
    \overload
1328
1329
    Sets the permissions for \a fileName file to \a permissions.
1330
*/
1331
1332
bool
1333
QFile::setPermissions(const QString &fileName, Permissions permissions)
1334
{
1335
    return QFile(fileName).setPermissions(permissions);
1336
}
1337
1338
static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
1339
{
1340
    qint64 ret = engine->write(buffer->readPointer(), buffer->size());
1341
    if (ret > 0)
1342
        buffer->free(ret);
1343
    return ret;
1344
}
1345
1346
/*!
1347
    Flushes any buffered data to the file. Returns true if successful;
1348
    otherwise returns false.
1349
*/
1350
1351
bool
1352
QFile::flush()
1353
{
1354
    Q_D(QFile);
1355
    if (!d->writeBuffer.isEmpty()) {
1356
        qint64 size = d->writeBuffer.size();
1357
        if (_qfile_writeData(d->fileEngine ? d->fileEngine : fileEngine(),
1358
                             &d->writeBuffer) != size) {
1359
            QFile::FileError err = fileEngine()->error();
1360
            if(err == QFile::UnspecifiedError)
1361
                err = QFile::WriteError;
1362
            d->setError(err, fileEngine()->errorString());
1363
            return false;
1364
        }
1365
    }
1366
1367
    if (!fileEngine()->flush()) {
1368
        QFile::FileError err = fileEngine()->error();
1369
        if(err == QFile::UnspecifiedError)
1370
            err = QFile::WriteError;
1371
        d->setError(err, fileEngine()->errorString());
1372
        return false;
1373
    }
1374
    return true;
1375
}
1376
1377
/*!
1378
  Flushes the file and then closes it.
1379
1380
  \sa QIODevice::close()
1381
*/
1382
void
1383
QFile::close()
1384
{
1385
    Q_D(QFile);
1386
    if(!isOpen())
1387
        return;
1388
    flush();
1389
    QIODevice::close();
1390
1391
    unsetError();
1392
    if(!fileEngine()->close())
1393
        d->setError(fileEngine()->error(), fileEngine()->errorString());
1394
}
1395
1396
/*!
1397
  Returns the size of the file.
1398
1399
  For regular empty files on Unix (e.g. those in \c /proc), this function
1400
  returns 0; the contents of such a file are generated on demand in response
1401
  to you calling read().
1402
*/
1403
1404
qint64 QFile::size() const
1405
{
1406
    Q_D(const QFile);
1407
    if (!d->ensureFlushed())
1408
        return 0;
1409
    return fileEngine()->size();
1410
}
1411
1412
/*!
1413
  \reimp
1414
*/
1415
1416
qint64 QFile::pos() const
1417
{
1418
    return QIODevice::pos();
1419
}
1420
1421
/*!
1422
  Returns true if the end of the file has been reached; otherwise returns
1423
  false.
1424
1425
  For regular empty files on Unix (e.g. those in \c /proc), this function
1426
  returns true, since the file system reports that the size of such a file is
1427
  0. Therefore, you should not depend on atEnd() when reading data from such a
1428
  file, but rather call read() until no more data can be read.
1429
*/
1430
1431
bool QFile::atEnd() const
1432
{
1433
    Q_D(const QFile);
1434
1435
    if (!isOpen())
1436
        return true;
1437
1438
    if (!d->ensureFlushed())
1439
        return false;
1440
1441
    // If there's buffered data left, we're not at the end.
1442
    if (!d->buffer.isEmpty())
1443
        return false;
1444
1445
    // If the file engine knows best, say what it says.
1446
    if (fileEngine()->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
1447
        // Check if the file engine supports AtEndExtension, and if it does,
1448
        // check if the file engine claims to be at the end.
1449
        return fileEngine()->atEnd();
1450
    }
1451
1452
    // Fall back to checking how much is available (will stat files).
1453
    return bytesAvailable() == 0;
1454
}
1455
1456
/*!
1457
  \reimp
1458
*/
1459
1460
bool QFile::seek(qint64 off)
1461
{
1462
    Q_D(QFile);
1463
    if (!isOpen()) {
1464
        qWarning("QFile::seek: IODevice is not open");
1465
        return false;
1466
    }
1467
1468
    if (!d->ensureFlushed())
1469
        return false;
1470
1471
    if (!fileEngine()->seek(off) || !QIODevice::seek(off)) {
1472
        QFile::FileError err = fileEngine()->error();
1473
        if(err == QFile::UnspecifiedError)
1474
            err = QFile::PositionError;
1475
        d->setError(err, fileEngine()->errorString());
1476
        return false;
1477
    }
1478
    d->error = NoError;
1479
    return true;
1480
}
1481
1482
/*!
1483
  \reimp
1484
*/
1485
qint64 QFile::readLineData(char *data, qint64 maxlen)
1486
{
1487
    Q_D(QFile);
1488
    if (!d->ensureFlushed())
1489
        return -1;
1490
1491
    if (fileEngine()->supportsExtension(QAbstractFileEngine::FastReadLineExtension))
1492
        return fileEngine()->readLine(data, maxlen);
1493
1494
    // Fall back to QIODevice's readLine implementation if the engine
1495
    // cannot do it faster.
1496
    return QIODevice::readLineData(data, maxlen);
1497
}
1498
1499
/*!
1500
  \reimp
1501
*/
1502
1503
qint64 QFile::readData(char *data, qint64 len)
1504
{
1505
    Q_D(QFile);
1506
    d->error = NoError;
1507
    if (!d->ensureFlushed())
1508
        return -1;
1509
1510
    qint64 ret = -1;
1511
    qint64 read = fileEngine()->read(data, len);
1512
    if (read != -1)
1513
        ret = read;
1514
1515
    if(ret < 0) {
1516
        QFile::FileError err = fileEngine()->error();
1517
        if(err == QFile::UnspecifiedError)
1518
            err = QFile::ReadError;
1519
        d->setError(err, fileEngine()->errorString());
1520
    }
1521
    return ret;
1522
}
1523
1524
/*!
1525
    \internal
1526
*/
1527
bool QFilePrivate::putCharHelper(char c)
1528
{
1529
#ifdef QT_NO_QOBJECT
1530
    return QIODevicePrivate::putCharHelper(c);
1531
#else
1532
1533
    // Cutoff for code that doesn't only touch the buffer.
1534
    int writeBufferSize = writeBuffer.size();
1535
    if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
1536
#ifdef Q_OS_WIN
1537
        || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
1538
#endif
1539
        ) {
1540
        return QIODevicePrivate::putCharHelper(c);
1541
    }
1542
1543
    if (!(openMode & QIODevice::WriteOnly)) {
1544
        if (openMode == QIODevice::NotOpen)
1545
            qWarning("QIODevice::putChar: Closed device");
1546
        else
1547
            qWarning("QIODevice::putChar: ReadOnly device");
1548
        return false;
1549
    }
1550
1551
    // Make sure the device is positioned correctly.
1552
    const bool sequential = isSequential();
1553
    if (pos != devicePos && !sequential && !q_func()->seek(pos))
1554
        return false;
1555
1556
    lastWasWrite = true;
1557
1558
    int len = 1;
1559
#ifdef Q_OS_WIN
1560
    if ((openMode & QIODevice::Text) && c == '\n') {
1561
        ++len;
1562
        *writeBuffer.reserve(1) = '\r';
1563
    }
1564
#endif
1565
1566
    // Write to buffer.
1567
    *writeBuffer.reserve(1) = c;
1568
1569
    if (!sequential) {
1570
        pos += len;
1571
        devicePos += len;
1572
        if (!buffer.isEmpty())
1573
            buffer.skip(len);
1574
    }
1575
1576
    return true;
1577
#endif
1578
}
1579
1580
/*!
1581
  \reimp
1582
*/
1583
1584
qint64
1585
QFile::writeData(const char *data, qint64 len)
1586
{
1587
    Q_D(QFile);
1588
    d->error = NoError;
1589
    d->lastWasWrite = true;
1590
    bool buffered = !(d->openMode & Unbuffered);
1591
1592
    // Flush buffered data if this read will overflow.
1593
    if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
1594
        if (!flush())
1595
            return -1;
1596
    }
1597
1598
    // Write directly to the engine if the block size is larger than
1599
    // the write buffer size.
1600
    if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
1601
        QAbstractFileEngine *fe = d->fileEngine ? d->fileEngine : fileEngine();
1602
        qint64 ret = fe->write(data, len);
1603
        if(ret < 0) {
1604
            QFile::FileError err = fileEngine()->error();
1605
            if(err == QFile::UnspecifiedError)
1606
                err = QFile::WriteError;
1607
            d->setError(err, fileEngine()->errorString());
1608
        }
1609
        return ret;
1610
    }
1611
1612
    // Write to the buffer.
1613
    char *writePointer = d->writeBuffer.reserve(len);
1614
    if (len == 1)
1615
        *writePointer = *data;
1616
    else
1617
        ::memcpy(writePointer, data, len);
1618
    return len;
1619
}
1620
1621
/*!
1622
    \internal
1623
    Returns the QIOEngine for this QFile object.
1624
*/
1625
QAbstractFileEngine *QFile::fileEngine() const
1626
{
1627
    Q_D(const QFile);
1628
    if(!d->fileEngine)
1629
        d->fileEngine = QAbstractFileEngine::create(d->fileName);
1630
    return d->fileEngine;
1631
}
1632
1633
/*!
1634
    Returns the file error status.
1635
1636
    The I/O device status returns an error code. For example, if open()
1637
    returns false, or a read/write operation returns -1, this function can
1638
    be called to find out the reason why the operation failed.
1639
1640
    \sa unsetError()
1641
*/
1642
1643
QFile::FileError
1644
QFile::error() const
1645
{
1646
    Q_D(const QFile);
1647
    return d->error;
1648
}
1649
1650
/*!
1651
    Sets the file's error to QFile::NoError.
1652
1653
    \sa error()
1654
*/
1655
void
1656
QFile::unsetError()
1657
{
1658
    Q_D(QFile);
1659
    d->setError(QFile::NoError);
1660
}
1661
1662
QT_END_NAMESPACE