1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Copyright (C) 2017 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qplatformdefs.h"
42#include "qdebug.h"
43#include "qfile.h"
44#include "qfsfileengine_p.h"
45#include "qtemporaryfile.h"
46#include "qtemporaryfile_p.h"
47#include "qlist.h"
48#include "qfileinfo.h"
49#include "private/qiodevice_p.h"
50#include "private/qfile_p.h"
51#include "private/qfilesystemengine_p.h"
52#include "private/qsystemerror_p.h"
53#include "private/qtemporaryfile_p.h"
54#if defined(QT_BUILD_CORE_LIB)
55# include "qcoreapplication.h"
56#endif
57
58#include <private/qmemory_p.h>
59
60#ifdef QT_NO_QOBJECT
61#define tr(X) QString::fromLatin1(X)
62#endif
63
64QT_BEGIN_NAMESPACE
65
66Q_DECL_COLD_FUNCTION
67static bool file_already_open(QFile &file, const char *where = nullptr)
68{
69 qWarning("QFile::%s: File (%ls) already open", where ? where : "open", qUtf16Printable(file.fileName()));
70 return false;
71}
72
73//************* QFilePrivate
74QFilePrivate::QFilePrivate()
75{
76}
77
78QFilePrivate::~QFilePrivate()
79{
80}
81
82bool
83QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
84{
85#ifdef QT_NO_FSFILEENGINE
86 Q_UNUSED(flags);
87 Q_UNUSED(fd);
88 return false;
89#else
90 auto fs = qt_make_unique<QFSFileEngine>();
91 auto fe = fs.get();
92 fileEngine = std::move(fs);
93 return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
94#endif
95}
96
97bool
98QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags)
99{
100#ifdef QT_NO_FSFILEENGINE
101 Q_UNUSED(flags);
102 Q_UNUSED(fh);
103 return false;
104#else
105 auto fs = qt_make_unique<QFSFileEngine>();
106 auto fe = fs.get();
107 fileEngine = std::move(fs);
108 return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
109#endif
110}
111
112QAbstractFileEngine *QFilePrivate::engine() const
113{
114 if (!fileEngine)
115 fileEngine.reset(QAbstractFileEngine::create(fileName));
116 return fileEngine.get();
117}
118
119//************* QFile
120
121/*!
122 \class QFile
123 \inmodule QtCore
124 \brief The QFile class provides an interface for reading from and writing to files.
125
126 \ingroup io
127
128 \reentrant
129
130 QFile is an I/O device for reading and writing text and binary
131 files and \l{The Qt Resource System}{resources}. A QFile may be
132 used by itself or, more conveniently, with a QTextStream or
133 QDataStream.
134
135 The file name is usually passed in the constructor, but it can be
136 set at any time using setFileName(). QFile expects the file
137 separator to be '/' regardless of operating system. The use of
138 other separators (e.g., '\\') is not supported.
139
140 You can check for a file's existence using exists(), and remove a
141 file using remove(). (More advanced file system related operations
142 are provided by QFileInfo and QDir.)
143
144 The file is opened with open(), closed with close(), and flushed
145 with flush(). Data is usually read and written using QDataStream
146 or QTextStream, but you can also call the QIODevice-inherited
147 functions read(), readLine(), readAll(), write(). QFile also
148 inherits getChar(), putChar(), and ungetChar(), which work one
149 character at a time.
150
151 The size of the file is returned by size(). You can get the
152 current file position using pos(), or move to a new file position
153 using seek(). If you've reached the end of the file, atEnd()
154 returns \c true.
155
156 \section1 Reading Files Directly
157
158 The following example reads a text file line by line:
159
160 \snippet file/file.cpp 0
161
162 The QIODevice::Text flag passed to open() tells Qt to convert
163 Windows-style line terminators ("\\r\\n") into C++-style
164 terminators ("\\n"). By default, QFile assumes binary, i.e. it
165 doesn't perform any conversion on the bytes stored in the file.
166
167 \section1 Using Streams to Read Files
168
169 The next example uses QTextStream to read a text file
170 line by line:
171
172 \snippet file/file.cpp 1
173
174 QTextStream takes care of converting the 8-bit data stored on
175 disk into a 16-bit Unicode QString. By default, it assumes that
176 the file is encoded in UTF-8. This can be changed using
177 \l QTextStream::setEncoding().
178
179 To write text, we can use operator<<(), which is overloaded to
180 take a QTextStream on the left and various data types (including
181 QString) on the right:
182
183 \snippet file/file.cpp 2
184
185 QDataStream is similar, in that you can use operator<<() to write
186 data and operator>>() to read it back. See the class
187 documentation for details.
188
189 When you use QFile, QFileInfo, and QDir to access the file system
190 with Qt, you can use Unicode file names. On Unix, these file
191 names are converted to an 8-bit encoding. If you want to use
192 standard C++ APIs (\c <cstdio> or \c <iostream>) or
193 platform-specific APIs to access files instead of QFile, you can
194 use the encodeName() and decodeName() functions to convert
195 between Unicode file names and 8-bit file names.
196
197 On Unix, there are some special system files (e.g. in \c /proc) for which
198 size() will always return 0, yet you may still be able to read more data
199 from such a file; the data is generated in direct response to you calling
200 read(). In this case, however, you cannot use atEnd() to determine if
201 there is more data to read (since atEnd() will return true for a file that
202 claims to have size 0). Instead, you should either call readAll(), or call
203 read() or readLine() repeatedly until no more data can be read. The next
204 example uses QTextStream to read \c /proc/modules line by line:
205
206 \snippet file/file.cpp 3
207
208 \section1 Signals
209
210 Unlike other QIODevice implementations, such as QTcpSocket, QFile does not
211 emit the aboutToClose(), bytesWritten(), or readyRead() signals. This
212 implementation detail means that QFile is not suitable for reading and
213 writing certain types of files, such as device files on Unix platforms.
214
215 \section1 Platform Specific Issues
216
217 File permissions are handled differently on Unix-like systems and
218 Windows. In a non \l{QIODevice::isWritable()}{writable}
219 directory on Unix-like systems, files cannot be created. This is not always
220 the case on Windows, where, for instance, the 'My Documents'
221 directory usually is not writable, but it is still possible to
222 create files in it.
223
224 Qt's understanding of file permissions is limited, which affects especially
225 the \l QFile::setPermissions() function. On Windows, Qt will set only the
226 legacy read-only flag, and that only when none of the Write* flags are
227 passed. Qt does not manipulate access control lists (ACLs), which makes this
228 function mostly useless for NTFS volumes. It may still be of use for USB
229 sticks that use VFAT file systems. POSIX ACLs are not manipulated, either.
230
231 \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
232*/
233
234#ifdef QT_NO_QOBJECT
235QFile::QFile()
236 : QFileDevice(*new QFilePrivate)
237{
238}
239QFile::QFile(const QString &name)
240 : QFileDevice(*new QFilePrivate)
241{
242 d_func()->fileName = name;
243}
244QFile::QFile(QFilePrivate &dd)
245 : QFileDevice(dd)
246{
247}
248#else
249/*!
250 Constructs a QFile object.
251*/
252QFile::QFile()
253 : QFileDevice(*new QFilePrivate, nullptr)
254{
255}
256/*!
257 Constructs a new file object with the given \a parent.
258*/
259QFile::QFile(QObject *parent)
260 : QFileDevice(*new QFilePrivate, parent)
261{
262}
263/*!
264 Constructs a new file object to represent the file with the given \a name.
265*/
266QFile::QFile(const QString &name)
267 : QFileDevice(*new QFilePrivate, nullptr)
268{
269 Q_D(QFile);
270 d->fileName = name;
271}
272/*!
273 Constructs a new file object with the given \a parent to represent the
274 file with the specified \a name.
275*/
276QFile::QFile(const QString &name, QObject *parent)
277 : QFileDevice(*new QFilePrivate, parent)
278{
279 Q_D(QFile);
280 d->fileName = name;
281}
282/*!
283 \internal
284*/
285QFile::QFile(QFilePrivate &dd, QObject *parent)
286 : QFileDevice(dd, parent)
287{
288}
289#endif
290
291/*!
292 Destroys the file object, closing it if necessary.
293*/
294QFile::~QFile()
295{
296}
297
298/*!
299 Returns the name set by setFileName() or to the QFile
300 constructors.
301
302 \sa setFileName(), QFileInfo::fileName()
303*/
304QString QFile::fileName() const
305{
306 Q_D(const QFile);
307 return d->engine()->fileName(QAbstractFileEngine::DefaultName);
308}
309
310/*!
311 Sets the \a name of the file. The name can have no path, a
312 relative path, or an absolute path.
313
314 Do not call this function if the file has already been opened.
315
316 If the file name has no path or a relative path, the path used
317 will be the application's current directory path
318 \e{at the time of the open()} call.
319
320 Example:
321 \snippet code/src_corelib_io_qfile.cpp 0
322
323 Note that the directory separator "/" works for all operating
324 systems supported by Qt.
325
326 \sa fileName(), QFileInfo, QDir
327*/
328void
329QFile::setFileName(const QString &name)
330{
331 Q_D(QFile);
332 if (isOpen()) {
333 file_already_open(*this, "setFileName");
334 close();
335 }
336 d->fileEngine.reset(); //get a new file engine later
337 d->fileName = name;
338}
339
340/*!
341 \fn QString QFile::decodeName(const char *localFileName)
342
343 \overload
344
345 Returns the Unicode version of the given \a localFileName. See
346 encodeName() for details.
347*/
348
349/*!
350 \fn QByteArray QFile::encodeName(const QString &fileName)
351
352 Converts \a fileName to the local 8-bit
353 encoding determined by the user's locale. This is sufficient for
354 file names that the user chooses. File names hard-coded into the
355 application should only use 7-bit ASCII filename characters.
356
357 \sa decodeName()
358*/
359
360/*!
361 \fn QString QFile::decodeName(const QByteArray &localFileName)
362
363 This does the reverse of QFile::encodeName() using \a localFileName.
364
365 \sa encodeName()
366*/
367
368/*!
369 \overload
370
371 Returns \c true if the file specified by fileName() exists; otherwise
372 returns \c false.
373
374 \sa fileName(), setFileName()
375*/
376
377bool
378QFile::exists() const
379{
380 Q_D(const QFile);
381 // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
382 return (d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
383 | QAbstractFileEngine::Refresh) & QAbstractFileEngine::ExistsFlag);
384}
385
386/*!
387 Returns \c true if the file specified by \a fileName exists; otherwise
388 returns \c false.
389
390 \note If \a fileName is a symlink that points to a non-existing
391 file, false is returned.
392*/
393
394bool
395QFile::exists(const QString &fileName)
396{
397 return QFileInfo::exists(fileName);
398}
399
400/*!
401 \fn QString QFile::symLinkTarget() const
402 \since 4.2
403 \overload
404
405 Returns the absolute path of the file or directory a symlink (or shortcut
406 on Windows) points to, or a an empty string if the object isn't a symbolic
407 link.
408
409 This name may not represent an existing file; it is only a string.
410 QFile::exists() returns \c true if the symlink points to an existing file.
411
412 \sa fileName(), setFileName()
413*/
414QString QFile::symLinkTarget() const
415{
416 Q_D(const QFile);
417 return d->engine()->fileName(QAbstractFileEngine::LinkName);
418}
419
420/*!
421 \fn static QString QFile::symLinkTarget(const QString &fileName)
422 \since 4.2
423
424 Returns the absolute path of the file or directory referred to by the
425 symlink (or shortcut on Windows) specified by \a fileName, or returns an
426 empty string if the \a fileName does not correspond to a symbolic link.
427
428 This name may not represent an existing file; it is only a string.
429 QFile::exists() returns \c true if the symlink points to an existing file.
430*/
431QString QFile::symLinkTarget(const QString &fileName)
432{
433 return QFileInfo(fileName).symLinkTarget();
434}
435
436/*!
437 Removes the file specified by fileName(). Returns \c true if successful;
438 otherwise returns \c false.
439
440 The file is closed before it is removed.
441
442 \sa setFileName()
443*/
444
445bool
446QFile::remove()
447{
448 Q_D(QFile);
449 if (d->fileName.isEmpty() &&
450 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
451 qWarning("QFile::remove: Empty or null file name");
452 return false;
453 }
454 unsetError();
455 close();
456 if(error() == QFile::NoError) {
457 if (d->engine()->remove()) {
458 unsetError();
459 return true;
460 }
461 d->setError(QFile::RemoveError, d->fileEngine->errorString());
462 }
463 return false;
464}
465
466/*!
467 \overload
468
469 Removes the file specified by the \a fileName given.
470
471 Returns \c true if successful; otherwise returns \c false.
472
473 \sa remove()
474*/
475
476bool
477QFile::remove(const QString &fileName)
478{
479 return QFile(fileName).remove();
480}
481
482/*!
483 \since 5.15
484
485 Moves the file specified by fileName() to the trash. Returns \c true if successful,
486 and sets the fileName() to the path at which the file can be found within the trash;
487 otherwise returns \c false.
488
489 \note On systems where the system API doesn't report the location of the file in the
490 trash, fileName() will be set to the null string once the file has been moved. On
491 systems that don't have a trash can, this function always returns false.
492*/
493bool
494QFile::moveToTrash()
495{
496 Q_D(QFile);
497 if (d->fileName.isEmpty() &&
498 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
499 qWarning("QFile::remove: Empty or null file name");
500 return false;
501 }
502 unsetError();
503 close();
504 if (error() == QFile::NoError) {
505 QFileSystemEntry fileEntry(d->fileName);
506 QFileSystemEntry trashEntry;
507 QSystemError error;
508 if (QFileSystemEngine::moveFileToTrash(fileEntry, trashEntry, error)) {
509 setFileName(trashEntry.filePath());
510 unsetError();
511 return true;
512 }
513 d->setError(QFile::RenameError, error.toString());
514 }
515 return false;
516}
517
518/*!
519 \since 5.15
520 \overload
521
522 Moves the file specified by fileName() to the trash. Returns \c true if successful,
523 and sets \a pathInTrash (if provided) to the path at which the file can be found within
524 the trash; otherwise returns \c false.
525
526 \note On systems where the system API doesn't report the path of the file in the
527 trash, \a pathInTrash will be set to the null string once the file has been moved.
528 On systems that don't have a trash can, this function always returns false.
529*/
530bool
531QFile::moveToTrash(const QString &fileName, QString *pathInTrash)
532{
533 QFile file(fileName);
534 if (file.moveToTrash()) {
535 if (pathInTrash)
536 *pathInTrash = file.fileName();
537 return true;
538 }
539 return false;
540}
541
542/*!
543 Renames the file currently specified by fileName() to \a newName.
544 Returns \c true if successful; otherwise returns \c false.
545
546 If a file with the name \a newName already exists, rename() returns \c false
547 (i.e., QFile will not overwrite it).
548
549 The file is closed before it is renamed.
550
551 If the rename operation fails, Qt will attempt to copy this file's
552 contents to \a newName, and then remove this file, keeping only
553 \a newName. If that copy operation fails or this file can't be removed,
554 the destination file \a newName is removed to restore the old state.
555
556 \sa setFileName()
557*/
558
559bool
560QFile::rename(const QString &newName)
561{
562 Q_D(QFile);
563
564 // if this is a QTemporaryFile, the virtual fileName() call here may do something
565 if (fileName().isEmpty()) {
566 qWarning("QFile::rename: Empty or null file name");
567 return false;
568 }
569 if (d->fileName == newName) {
570 d->setError(QFile::RenameError, tr("Destination file is the same file."));
571 return false;
572 }
573 if (!exists()) {
574 d->setError(QFile::RenameError, tr("Source file does not exist."));
575 return false;
576 }
577
578 // If the file exists and it is a case-changing rename ("foo" -> "Foo"),
579 // compare Ids to make sure it really is a different file.
580 // Note: this does not take file engines into account.
581 bool changingCase = false;
582 QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
583 if (!targetId.isNull()) {
584 QByteArray fileId = d->fileEngine ?
585 d->fileEngine->id() :
586 QFileSystemEngine::id(QFileSystemEntry(d->fileName));
587 changingCase = (fileId == targetId && d->fileName.compare(newName, Qt::CaseInsensitive) == 0);
588 if (!changingCase) {
589 d->setError(QFile::RenameError, tr("Destination file exists"));
590 return false;
591 }
592
593#ifdef Q_OS_LINUX
594 // rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
595 // FS, such as FAT32. Move the file away and rename in 2 steps to work around.
596 QTemporaryFileName tfn(d->fileName);
597 QFileSystemEntry src(d->fileName);
598 QSystemError error;
599 for (int attempt = 0; attempt < 16; ++attempt) {
600 QFileSystemEntry tmp(tfn.generateNext(), QFileSystemEntry::FromNativePath());
601
602 // rename to temporary name
603 if (!QFileSystemEngine::renameFile(src, tmp, error))
604 continue;
605
606 // rename to final name
607 if (QFileSystemEngine::renameFile(tmp, QFileSystemEntry(newName), error)) {
608 d->fileEngine->setFileName(newName);
609 d->fileName = newName;
610 return true;
611 }
612
613 // We need to restore the original file.
614 QSystemError error2;
615 if (QFileSystemEngine::renameFile(tmp, src, error2))
616 break; // report the original error, below
617
618 // report both errors
619 d->setError(QFile::RenameError,
620 tr("Error while renaming: %1").arg(error.toString())
621 + QLatin1Char('\n')
622 + tr("Unable to restore from %1: %2").
623 arg(QDir::toNativeSeparators(tmp.filePath()), error2.toString()));
624 return false;
625 }
626 d->setError(QFile::RenameError,
627 tr("Error while renaming: %1").arg(error.toString()));
628 return false;
629#endif // Q_OS_LINUX
630 }
631 unsetError();
632 close();
633 if(error() == QFile::NoError) {
634 if (changingCase ? d->engine()->renameOverwrite(newName) : d->engine()->rename(newName)) {
635 unsetError();
636 // engine was able to handle the new name so we just reset it
637 d->fileEngine->setFileName(newName);
638 d->fileName = newName;
639 return true;
640 }
641
642 if (isSequential()) {
643 d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
644 return false;
645 }
646
647 QFile out(newName);
648 if (open(QIODevice::ReadOnly)) {
649 if (out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
650 bool error = false;
651 char block[4096];
652 qint64 bytes;
653 while ((bytes = read(block, sizeof(block))) > 0) {
654 if (bytes != out.write(block, bytes)) {
655 d->setError(QFile::RenameError, out.errorString());
656 error = true;
657 break;
658 }
659 }
660 if (bytes == -1) {
661 d->setError(QFile::RenameError, errorString());
662 error = true;
663 }
664 if(!error) {
665 if (!remove()) {
666 d->setError(QFile::RenameError, tr("Cannot remove source file"));
667 error = true;
668 }
669 }
670 if (error) {
671 out.remove();
672 } else {
673 d->fileEngine->setFileName(newName);
674 setPermissions(permissions());
675 unsetError();
676 setFileName(newName);
677 }
678 close();
679 return !error;
680 }
681 close();
682 d->setError(QFile::RenameError,
683 tr("Cannot open destination file: %1").arg(out.errorString()));
684 } else {
685 d->setError(QFile::RenameError, errorString());
686 }
687 }
688 return false;
689}
690
691/*!
692 \overload
693
694 Renames the file \a oldName to \a newName. Returns \c true if
695 successful; otherwise returns \c false.
696
697 If a file with the name \a newName already exists, rename() returns \c false
698 (i.e., QFile will not overwrite it).
699
700 \sa rename()
701*/
702
703bool
704QFile::rename(const QString &oldName, const QString &newName)
705{
706 return QFile(oldName).rename(newName);
707}
708
709/*!
710
711 Creates a link named \a linkName that points to the file currently specified by
712 fileName(). What a link is depends on the underlying filesystem (be it a
713 shortcut on Windows or a symbolic link on Unix). Returns \c true if successful;
714 otherwise returns \c false.
715
716 This function will not overwrite an already existing entity in the file system;
717 in this case, \c link() will return false and set \l{QFile::}{error()} to
718 return \l{QFile::}{RenameError}.
719
720 \note To create a valid link on Windows, \a linkName must have a \c{.lnk} file extension.
721
722 \sa setFileName()
723*/
724
725bool
726QFile::link(const QString &linkName)
727{
728 Q_D(QFile);
729 if (fileName().isEmpty()) {
730 qWarning("QFile::link: Empty or null file name");
731 return false;
732 }
733 QFileInfo fi(linkName);
734 if (d->engine()->link(fi.absoluteFilePath())) {
735 unsetError();
736 return true;
737 }
738 d->setError(QFile::RenameError, d->fileEngine->errorString());
739 return false;
740}
741
742/*!
743 \overload
744
745 Creates a link named \a linkName that points to the file \a fileName. What a link is
746 depends on the underlying filesystem (be it a shortcut on Windows
747 or a symbolic link on Unix). Returns \c true if successful; otherwise
748 returns \c false.
749
750 \sa link()
751*/
752
753bool
754QFile::link(const QString &fileName, const QString &linkName)
755{
756 return QFile(fileName).link(linkName);
757}
758
759/*!
760 Copies the file currently specified by fileName() to a file called
761 \a newName. Returns \c true if successful; otherwise returns \c false.
762
763 Note that if a file with the name \a newName already exists,
764 copy() returns \c false (i.e. QFile will not overwrite it).
765
766 The source file is closed before it is copied.
767
768 \sa setFileName()
769*/
770
771bool
772QFile::copy(const QString &newName)
773{
774 Q_D(QFile);
775 if (fileName().isEmpty()) {
776 qWarning("QFile::copy: Empty or null file name");
777 return false;
778 }
779 if (QFile::exists(newName)) {
780 // ### Race condition. If a file is moved in after this, it /will/ be
781 // overwritten. On Unix, the proper solution is to use hardlinks:
782 // return ::link(old, new) && ::remove(old); See also rename().
783 d->setError(QFile::CopyError, tr("Destination file exists"));
784 return false;
785 }
786 unsetError();
787 close();
788 if(error() == QFile::NoError) {
789 if (d->engine()->copy(newName)) {
790 unsetError();
791 return true;
792 } else {
793 bool error = false;
794 if(!open(QFile::ReadOnly)) {
795 error = true;
796 d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
797 } else {
798 const auto fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
799#ifdef QT_NO_TEMPORARYFILE
800 QFile out(fileTemplate.arg(QFileInfo(newName).path()));
801 if (!out.open(QIODevice::ReadWrite))
802 error = true;
803#else
804 QTemporaryFile out(fileTemplate.arg(QFileInfo(newName).path()));
805 if (!out.open()) {
806 out.setFileTemplate(fileTemplate.arg(QDir::tempPath()));
807 if (!out.open())
808 error = true;
809 }
810#endif
811 if (error) {
812 out.close();
813 close();
814 d->setError(QFile::CopyError, tr("Cannot open for output: %1").arg(out.errorString()));
815 } else {
816 if (!d->engine()->cloneTo(out.d_func()->engine())) {
817 char block[4096];
818 qint64 totalRead = 0;
819 while (!atEnd()) {
820 qint64 in = read(block, sizeof(block));
821 if (in <= 0)
822 break;
823 totalRead += in;
824 if (in != out.write(block, in)) {
825 close();
826 d->setError(QFile::CopyError, tr("Failure to write block"));
827 error = true;
828 break;
829 }
830 }
831
832 if (totalRead != size()) {
833 // Unable to read from the source. The error string is
834 // already set from read().
835 error = true;
836 }
837 }
838
839 if (!error) {
840 // Sync to disk if possible. Ignore errors (e.g. not supported).
841 out.d_func()->fileEngine->syncToDisk();
842
843 if (!out.rename(newName)) {
844 error = true;
845 close();
846 d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
847 }
848 }
849#ifdef QT_NO_TEMPORARYFILE
850 if (error)
851 out.remove();
852#else
853 if (!error)
854 out.setAutoRemove(false);
855#endif
856 }
857 }
858 if(!error) {
859 QFile::setPermissions(newName, permissions());
860 close();
861 unsetError();
862 return true;
863 }
864 }
865 }
866 return false;
867}
868
869/*!
870 \overload
871
872 Copies the file \a fileName to \a newName. Returns \c true if successful;
873 otherwise returns \c false.
874
875 If a file with the name \a newName already exists, copy() returns \c false
876 (i.e., QFile will not overwrite it).
877
878 \sa rename()
879*/
880
881bool
882QFile::copy(const QString &fileName, const QString &newName)
883{
884 return QFile(fileName).copy(newName);
885}
886
887/*!
888 Opens the file using OpenMode \a mode, returning true if successful;
889 otherwise false.
890
891 The \a mode must be QIODevice::ReadOnly, QIODevice::WriteOnly, or
892 QIODevice::ReadWrite. It may also have additional flags, such as
893 QIODevice::Text and QIODevice::Unbuffered.
894
895 \note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite}
896 mode, if the relevant file does not already exist, this function
897 will try to create a new file before opening it.
898
899 \sa QIODevice::OpenMode, setFileName()
900*/
901bool QFile::open(OpenMode mode)
902{
903 Q_D(QFile);
904 if (isOpen())
905 return file_already_open(*this);
906 // Either Append or NewOnly implies WriteOnly
907 if (mode & (Append | NewOnly))
908 mode |= WriteOnly;
909 unsetError();
910 if ((mode & (ReadOnly | WriteOnly)) == 0) {
911 qWarning("QIODevice::open: File access not specified");
912 return false;
913 }
914
915 // QIODevice provides the buffering, so there's no need to request it from the file engine.
916 if (d->engine()->open(mode | QIODevice::Unbuffered)) {
917 QIODevice::open(mode);
918 if (mode & Append)
919 seek(size());
920 return true;
921 }
922 QFile::FileError err = d->fileEngine->error();
923 if(err == QFile::UnspecifiedError)
924 err = QFile::OpenError;
925 d->setError(err, d->fileEngine->errorString());
926 return false;
927}
928
929/*!
930 \overload
931
932 Opens the existing file handle \a fh in the given \a mode.
933 \a handleFlags may be used to specify additional options.
934 Returns \c true if successful; otherwise returns \c false.
935
936 Example:
937 \snippet code/src_corelib_io_qfile.cpp 3
938
939 When a QFile is opened using this function, behaviour of close() is
940 controlled by the AutoCloseHandle flag.
941 If AutoCloseHandle is specified, and this function succeeds,
942 then calling close() closes the adopted handle.
943 Otherwise, close() does not actually close the file, but only flushes it.
944
945 \b{Warning:}
946 \list 1
947 \li If \a fh does not refer to a regular file, e.g., it is \c stdin,
948 \c stdout, or \c stderr, you may not be able to seek(). size()
949 returns \c 0 in those cases. See QIODevice::isSequential() for
950 more information.
951 \li Since this function opens the file without specifying the file name,
952 you cannot use this QFile with a QFileInfo.
953 \endlist
954
955 \sa close()
956
957 \b{Note for the Windows Platform}
958
959 \a fh must be opened in binary mode (i.e., the mode string must contain
960 'b', as in "rb" or "wb") when accessing files and other random-access
961 devices. Qt will translate the end-of-line characters if you pass
962 QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
963 are unaffected by this limitation.
964
965 You need to enable support for console applications in order to use the
966 stdin, stdout and stderr streams at the console. To do this, add the
967 following declaration to your application's project file:
968
969 \snippet code/src_corelib_io_qfile.cpp 4
970*/
971bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
972{
973 Q_D(QFile);
974 if (isOpen())
975 return file_already_open(*this);
976 // Either Append or NewOnly implies WriteOnly
977 if (mode & (Append | NewOnly))
978 mode |= WriteOnly;
979 unsetError();
980 if ((mode & (ReadOnly | WriteOnly)) == 0) {
981 qWarning("QFile::open: File access not specified");
982 return false;
983 }
984
985 // QIODevice provides the buffering, so request unbuffered file engines
986 if (d->openExternalFile(mode | Unbuffered, fh, handleFlags)) {
987 QIODevice::open(mode);
988 if (!(mode & Append) && !isSequential()) {
989 qint64 pos = (qint64)QT_FTELL(fh);
990 if (pos != -1) {
991 // Skip redundant checks in QFileDevice::seek().
992 QIODevice::seek(pos);
993 }
994 }
995 return true;
996 }
997 return false;
998}
999
1000/*!
1001 \overload
1002
1003 Opens the existing file descriptor \a fd in the given \a mode.
1004 \a handleFlags may be used to specify additional options.
1005 Returns \c true if successful; otherwise returns \c false.
1006
1007 When a QFile is opened using this function, behaviour of close() is
1008 controlled by the AutoCloseHandle flag.
1009 If AutoCloseHandle is specified, and this function succeeds,
1010 then calling close() closes the adopted handle.
1011 Otherwise, close() does not actually close the file, but only flushes it.
1012
1013 \warning If \a fd is not a regular file, e.g, it is 0 (\c stdin),
1014 1 (\c stdout), or 2 (\c stderr), you may not be able to seek(). In
1015 those cases, size() returns \c 0. See QIODevice::isSequential()
1016 for more information.
1017
1018 \warning Since this function opens the file without specifying the file name,
1019 you cannot use this QFile with a QFileInfo.
1020
1021 \sa close()
1022*/
1023bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
1024{
1025 Q_D(QFile);
1026 if (isOpen())
1027 return file_already_open(*this);
1028 // Either Append or NewOnly implies WriteOnly
1029 if (mode & (Append | NewOnly))
1030 mode |= WriteOnly;
1031 unsetError();
1032 if ((mode & (ReadOnly | WriteOnly)) == 0) {
1033 qWarning("QFile::open: File access not specified");
1034 return false;
1035 }
1036
1037 // QIODevice provides the buffering, so request unbuffered file engines
1038 if (d->openExternalFile(mode | Unbuffered, fd, handleFlags)) {
1039 QIODevice::open(mode);
1040 if (!(mode & Append) && !isSequential()) {
1041 qint64 pos = (qint64)QT_LSEEK(fd, QT_OFF_T(0), SEEK_CUR);
1042 if (pos != -1) {
1043 // Skip redundant checks in QFileDevice::seek().
1044 QIODevice::seek(pos);
1045 }
1046 }
1047 return true;
1048 }
1049 return false;
1050}
1051
1052/*!
1053 \reimp
1054*/
1055bool QFile::resize(qint64 sz)
1056{
1057 return QFileDevice::resize(sz); // for now
1058}
1059
1060/*!
1061 \overload
1062
1063 Sets \a fileName to size (in bytes) \a sz. Returns \c true if
1064 the resize succeeds; false otherwise. If \a sz is larger than \a
1065 fileName currently is the new bytes will be set to 0, if \a sz is
1066 smaller the file is simply truncated.
1067
1068 \warning This function can fail if the file doesn't exist.
1069
1070 \sa resize()
1071*/
1072
1073bool
1074QFile::resize(const QString &fileName, qint64 sz)
1075{
1076 return QFile(fileName).resize(sz);
1077}
1078
1079/*!
1080 \reimp
1081*/
1082QFile::Permissions QFile::permissions() const
1083{
1084 return QFileDevice::permissions(); // for now
1085}
1086
1087/*!
1088 \overload
1089
1090 Returns the complete OR-ed together combination of
1091 QFile::Permission for \a fileName.
1092*/
1093
1094QFile::Permissions
1095QFile::permissions(const QString &fileName)
1096{
1097 return QFile(fileName).permissions();
1098}
1099
1100/*!
1101 Sets the permissions for the file to the \a permissions specified.
1102 Returns \c true if successful, or \c false if the permissions cannot be
1103 modified.
1104
1105 \warning This function does not manipulate ACLs, which may limit its
1106 effectiveness.
1107
1108 \sa permissions(), setFileName()
1109*/
1110
1111bool QFile::setPermissions(Permissions permissions)
1112{
1113 return QFileDevice::setPermissions(permissions); // for now
1114}
1115
1116/*!
1117 \overload
1118
1119 Sets the permissions for \a fileName file to \a permissions.
1120*/
1121
1122bool
1123QFile::setPermissions(const QString &fileName, Permissions permissions)
1124{
1125 return QFile(fileName).setPermissions(permissions);
1126}
1127
1128/*!
1129 \reimp
1130*/
1131qint64 QFile::size() const
1132{
1133 return QFileDevice::size(); // for now
1134}
1135
1136/*!
1137 \fn QFile::QFile(const std::filesystem::path &name)
1138 \since 6.0
1139
1140 Constructs a new file object to represent the file with the given \a name.
1141*/
1142/*!
1143 \fn QFile::QFile(const std::filesystem::path &name, QObject *parent)
1144 \since 6.0
1145
1146 Constructs a new file object with the given \a parent to represent the
1147 file with the specified \a name.
1148*/
1149/*!
1150 \fn std::filesystem::path QFile::filesystemFileName() const
1151 \since 6.0
1152 Returns fileName() as \c{std::filesystem::path}.
1153*/
1154/*!
1155 \fn void QFile::setFileName(const std::filesystem::path &name)
1156 \since 6.0
1157 \overload
1158*/
1159/*!
1160 \fn bool QFile::rename(const std::filesystem::path &newName)
1161 \since 6.0
1162 \overload
1163*/
1164/*!
1165 \fn bool QFile::link(const std::filesystem::path &newName)
1166 \since 6.0
1167 \overload
1168*/
1169/*!
1170 \fn bool QFile::copy(const std::filesystem::path &newName)
1171 \since 6.0
1172 \overload
1173*/
1174/*!
1175 \fn QFile::Permissions QFile::permissions(const std::filesystem::path &filename)
1176 \since 6.0
1177 \overload
1178*/
1179/*!
1180 \fn bool QFile::setPermissions(const std::filesystem::path &filename, Permissions permissionSpec)
1181 \since 6.0
1182 \overload
1183*/
1184
1185
1186QT_END_NAMESPACE
1187
1188#ifndef QT_NO_QOBJECT
1189#include "moc_qfile.cpp"
1190#endif
1191