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