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
64QT_BEGIN_NAMESPACE
65
66Q_DECL_COLD_FUNCTION
67static bool file_already_open(QFile &file, const char *where = nullptr)
68{
69 qWarning(msg: "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(flags: 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(flags: QIODevice::OpenMode(flags), fh, handleFlags);
109#endif
110}
111
112QAbstractFileEngine *QFilePrivate::engine() const
113{
114 if (!fileEngine)
115 fileEngine.reset(p: 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
236QFile::QFile()
237 : QFileDevice(*new QFilePrivate)
238{
239}
240QFile::QFile(const QString &name)
241 : QFileDevice(*new QFilePrivate)
242{
243 d_func()->fileName = name;
244}
245QFile::QFile(QFilePrivate &dd)
246 : QFileDevice(dd)
247{
248}
249#else
250/*!
251 Constructs a QFile object.
252*/
253QFile::QFile()
254 : QFileDevice(*new QFilePrivate, nullptr)
255{
256}
257/*!
258 Constructs a new file object with the given \a parent.
259*/
260QFile::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*/
267QFile::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*/
277QFile::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*/
286QFile::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*/
295QFile::~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*/
305QString QFile::fileName() const
306{
307 Q_D(const QFile);
308 return d->engine()->fileName(file: 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*/
329void
330QFile::setFileName(const QString &name)
331{
332 Q_D(QFile);
333 if (isOpen()) {
334 file_already_open(file&: *this, where: "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
423bool
424QFile::exists() const
425{
426 Q_D(const QFile);
427 // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
428 return (d->engine()->fileFlags(type: 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
440bool
441QFile::exists(const QString &fileName)
442{
443 return QFileInfo::exists(file: 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*/
460QString QFile::symLinkTarget() const
461{
462 Q_D(const QFile);
463 return d->engine()->fileName(file: QAbstractFileEngine::LinkName);
464}
465
466#if QT_DEPRECATED_SINCE(5, 13)
467/*!
468 \obsolete
469
470 Use symLinkTarget() instead.
471*/
472QString
473QFile::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*/
490QString 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*/
501QString
502QFile::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
517bool
518QFile::remove()
519{
520 Q_D(QFile);
521 if (d->fileName.isEmpty() &&
522 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
523 qWarning(msg: "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(err: QFile::RemoveError, errorString: 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
548bool
549QFile::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*/
565bool
566QFile::moveToTrash()
567{
568 Q_D(QFile);
569 if (d->fileName.isEmpty() &&
570 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
571 qWarning(msg: "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(source: fileEntry, newLocation&: trashEntry, error)) {
581 setFileName(trashEntry.filePath());
582 unsetError();
583 return true;
584 }
585 d->setError(err: QFile::RenameError, errorString: 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*/
602bool
603QFile::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
631bool
632QFile::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(msg: "QFile::rename: Empty or null file name");
639 return false;
640 }
641 if (d->fileName == newName) {
642 d->setError(err: QFile::RenameError, errorString: tr(s: "Destination file is the same file."));
643 return false;
644 }
645 if (!exists()) {
646 d->setError(err: QFile::RenameError, errorString: tr(s: "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(entry: QFileSystemEntry(newName));
655 if (!targetId.isNull()) {
656 QByteArray fileId = d->fileEngine ?
657 d->fileEngine->id() :
658 QFileSystemEngine::id(entry: QFileSystemEntry(d->fileName));
659 changingCase = (fileId == targetId && d->fileName.compare(s: newName, cs: Qt::CaseInsensitive) == 0);
660 if (!changingCase) {
661 d->setError(err: QFile::RenameError, errorString: tr(s: "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(source: src, target: tmp, error))
676 continue;
677
678 // rename to final name
679 if (QFileSystemEngine::renameFile(source: tmp, target: 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(source: tmp, target: src, error&: error2))
688 break; // report the original error, below
689
690 // report both errors
691 d->setError(err: QFile::RenameError,
692 errorString: tr(s: "Error while renaming: %1").arg(a: error.toString())
693 + QLatin1Char('\n')
694 + tr(s: "Unable to restore from %1: %2").
695 arg(args: QDir::toNativeSeparators(pathName: tmp.filePath()), args: error2.toString()));
696 return false;
697 }
698 d->setError(err: QFile::RenameError,
699 errorString: tr(s: "Error while renaming: %1").arg(a: 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(err: QFile::RenameError, errorString: tr(s: "Will not rename sequential file using block copy"));
716 return false;
717 }
718
719 QFile out(newName);
720 if (open(flags: QIODevice::ReadOnly)) {
721 if (out.open(flags: QIODevice::WriteOnly | QIODevice::Truncate)) {
722 bool error = false;
723 char block[4096];
724 qint64 bytes;
725 while ((bytes = read(data: block, maxlen: sizeof(block))) > 0) {
726 if (bytes != out.write(data: block, len: bytes)) {
727 d->setError(err: QFile::RenameError, errorString: out.errorString());
728 error = true;
729 break;
730 }
731 }
732 if (bytes == -1) {
733 d->setError(err: QFile::RenameError, errorString: errorString());
734 error = true;
735 }
736 if(!error) {
737 if (!remove()) {
738 d->setError(err: QFile::RenameError, errorString: tr(s: "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(err: QFile::RenameError,
755 errorString: tr(s: "Cannot open destination file: %1").arg(a: out.errorString()));
756 } else {
757 d->setError(err: QFile::RenameError, errorString: 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
775bool
776QFile::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
797bool
798QFile::link(const QString &linkName)
799{
800 Q_D(QFile);
801 if (fileName().isEmpty()) {
802 qWarning(msg: "QFile::link: Empty or null file name");
803 return false;
804 }
805 QFileInfo fi(linkName);
806 if (d->engine()->link(newName: fi.absoluteFilePath())) {
807 unsetError();
808 return true;
809 }
810 d->setError(err: QFile::RenameError, errorString: 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
825bool
826QFile::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
843bool
844QFile::copy(const QString &newName)
845{
846 Q_D(QFile);
847 if (fileName().isEmpty()) {
848 qWarning(msg: "QFile::copy: Empty or null file name");
849 return false;
850 }
851 if (QFile::exists(fileName: 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(err: QFile::CopyError, errorString: tr(s: "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(flags: QFile::ReadOnly)) {
867 error = true;
868 d->setError(err: QFile::CopyError, errorString: tr(s: "Cannot open %1 for input").arg(a: 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(args: QFileInfo(newName).path()));
877 if (!out.open()) {
878 out.setFileTemplate(fileTemplate.arg(args: QDir::tempPath()));
879 if (!out.open())
880 error = true;
881 }
882#endif
883 if (error) {
884 out.close();
885 close();
886 d->setError(err: QFile::CopyError, errorString: tr(s: "Cannot open for output: %1").arg(a: out.errorString()));
887 } else {
888 if (!d->engine()->cloneTo(target: out.d_func()->engine())) {
889 char block[4096];
890 qint64 totalRead = 0;
891 while (!atEnd()) {
892 qint64 in = read(data: block, maxlen: sizeof(block));
893 if (in <= 0)
894 break;
895 totalRead += in;
896 if (in != out.write(data: block, len: in)) {
897 close();
898 d->setError(err: QFile::CopyError, errorString: tr(s: "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(err: QFile::CopyError, errorString: tr(s: "Cannot create %1 for output").arg(a: 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(filename: newName, permissionSpec: 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
953bool
954QFile::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*/
973bool QFile::open(OpenMode mode)
974{
975 Q_D(QFile);
976 if (isOpen())
977 return file_already_open(file&: *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(msg: "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(openMode: mode | QIODevice::Unbuffered)) {
989 QIODevice::open(mode);
990 if (mode & Append)
991 seek(offset: 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, errorString: 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*/
1043bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
1044{
1045 Q_D(QFile);
1046 if (isOpen())
1047 return file_already_open(file&: *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(msg: "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(flags: mode | Unbuffered, fh, handleFlags)) {
1059 QIODevice::open(mode);
1060 if (!(mode & Append) && !isSequential()) {
1061 qint64 pos = (qint64)QT_FTELL(stream: 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*/
1095bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
1096{
1097 Q_D(QFile);
1098 if (isOpen())
1099 return file_already_open(file&: *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(msg: "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(flags: mode | Unbuffered, fd, handleFlags)) {
1111 QIODevice::open(mode);
1112 if (!(mode & Append) && !isSequential()) {
1113 qint64 pos = (qint64)QT_LSEEK(fd: 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*/
1127bool 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
1145bool
1146QFile::resize(const QString &fileName, qint64 sz)
1147{
1148 return QFile(fileName).resize(sz);
1149}
1150
1151/*!
1152 \reimp
1153*/
1154QFile::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
1166QFile::Permissions
1167QFile::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
1183bool 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
1194bool
1195QFile::setPermissions(const QString &fileName, Permissions permissions)
1196{
1197 return QFile(fileName).setPermissions(permissions);
1198}
1199
1200/*!
1201 \reimp
1202*/
1203qint64 QFile::size() const
1204{
1205 return QFileDevice::size(); // for now
1206}
1207
1208QT_END_NAMESPACE
1209
1210#ifndef QT_NO_QOBJECT
1211#include "moc_qfile.cpp"
1212#endif
1213

source code of qtbase/src/corelib/io/qfile.cpp