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 named fileName() to \a newName.
833
834 \include qfile-copy.qdocinc
835
836 \sa setFileName()
837*/
838
839bool
840QFile::copy(const QString &newName)
841{
842 Q_D(QFile);
843 if (fileName().isEmpty()) {
844 qWarning(msg: "QFile::copy: Empty or null file name");
845 return false;
846 }
847 if (QFile::exists(fileName: newName)) {
848 // ### Race condition. If a file is moved in after this, it /will/ be
849 // overwritten. On Unix, the proper solution is to use hardlinks:
850 // return ::link(old, new) && ::remove(old); See also rename().
851 d->setError(err: QFile::CopyError, errorString: tr(s: "Destination file exists"));
852 return false;
853 }
854 unsetError();
855 close();
856 if(error() == QFile::NoError) {
857 if (d->engine()->copy(newName)) {
858 unsetError();
859 return true;
860 } else {
861 bool error = false;
862 if(!open(flags: QFile::ReadOnly)) {
863 error = true;
864 d->setError(err: QFile::CopyError, errorString: tr(s: "Cannot open %1 for input").arg(a: d->fileName));
865 } else {
866 const auto fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
867#ifdef QT_NO_TEMPORARYFILE
868 QFile out(fileTemplate.arg(QFileInfo(newName).path()));
869 if (!out.open(QIODevice::ReadWrite))
870 error = true;
871#else
872 QTemporaryFile out(fileTemplate.arg(args: QFileInfo(newName).path()));
873 if (!out.open()) {
874 out.setFileTemplate(fileTemplate.arg(args: QDir::tempPath()));
875 if (!out.open())
876 error = true;
877 }
878#endif
879 if (error) {
880 out.close();
881 close();
882 d->setError(err: QFile::CopyError, errorString: tr(s: "Cannot open for output: %1").arg(a: out.errorString()));
883 } else {
884 if (!d->engine()->cloneTo(target: out.d_func()->engine())) {
885 char block[4096];
886 qint64 totalRead = 0;
887 while (!atEnd()) {
888 qint64 in = read(data: block, maxlen: sizeof(block));
889 if (in <= 0)
890 break;
891 totalRead += in;
892 if (in != out.write(data: block, len: in)) {
893 close();
894 d->setError(err: QFile::CopyError, errorString: tr(s: "Failure to write block"));
895 error = true;
896 break;
897 }
898 }
899
900 if (totalRead != size()) {
901 // Unable to read from the source. The error string is
902 // already set from read().
903 error = true;
904 }
905 }
906
907 if (!error) {
908 // Sync to disk if possible. Ignore errors (e.g. not supported).
909 out.d_func()->fileEngine->syncToDisk();
910
911 if (!out.rename(newName)) {
912 error = true;
913 close();
914 d->setError(err: QFile::CopyError, errorString: tr(s: "Cannot create %1 for output").arg(a: newName));
915 }
916 }
917#ifdef QT_NO_TEMPORARYFILE
918 if (error)
919 out.remove();
920#else
921 if (!error)
922 out.setAutoRemove(false);
923#endif
924 }
925 }
926 if(!error) {
927 QFile::setPermissions(filename: newName, permissionSpec: permissions());
928 close();
929 unsetError();
930 return true;
931 }
932 }
933 }
934 return false;
935}
936
937/*!
938 \overload
939
940 Copies the file named \a fileName to \a newName.
941
942 \include qfile-copy.qdocinc
943
944 \sa rename()
945*/
946
947bool
948QFile::copy(const QString &fileName, const QString &newName)
949{
950 return QFile(fileName).copy(newName);
951}
952
953/*!
954 Opens the file using OpenMode \a mode, returning true if successful;
955 otherwise false.
956
957 The \a mode must be QIODevice::ReadOnly, QIODevice::WriteOnly, or
958 QIODevice::ReadWrite. It may also have additional flags, such as
959 QIODevice::Text and QIODevice::Unbuffered.
960
961 \note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite}
962 mode, if the relevant file does not already exist, this function
963 will try to create a new file before opening it.
964
965 \sa QIODevice::OpenMode, setFileName()
966*/
967bool QFile::open(OpenMode mode)
968{
969 Q_D(QFile);
970 if (isOpen())
971 return file_already_open(file&: *this);
972 // Either Append or NewOnly implies WriteOnly
973 if (mode & (Append | NewOnly))
974 mode |= WriteOnly;
975 unsetError();
976 if ((mode & (ReadOnly | WriteOnly)) == 0) {
977 qWarning(msg: "QIODevice::open: File access not specified");
978 return false;
979 }
980
981 // QIODevice provides the buffering, so there's no need to request it from the file engine.
982 if (d->engine()->open(openMode: mode | QIODevice::Unbuffered)) {
983 QIODevice::open(mode);
984 if (mode & Append)
985 seek(offset: size());
986 return true;
987 }
988 QFile::FileError err = d->fileEngine->error();
989 if(err == QFile::UnspecifiedError)
990 err = QFile::OpenError;
991 d->setError(err, errorString: d->fileEngine->errorString());
992 return false;
993}
994
995/*!
996 \overload
997
998 Opens the existing file handle \a fh in the given \a mode.
999 \a handleFlags may be used to specify additional options.
1000 Returns \c true if successful; otherwise returns \c false.
1001
1002 Example:
1003 \snippet code/src_corelib_io_qfile.cpp 3
1004
1005 When a QFile is opened using this function, behaviour of close() is
1006 controlled by the AutoCloseHandle flag.
1007 If AutoCloseHandle is specified, and this function succeeds,
1008 then calling close() closes the adopted handle.
1009 Otherwise, close() does not actually close the file, but only flushes it.
1010
1011 \b{Warning:}
1012 \list 1
1013 \li If \a fh does not refer to a regular file, e.g., it is \c stdin,
1014 \c stdout, or \c stderr, you may not be able to seek(). size()
1015 returns \c 0 in those cases. See QIODevice::isSequential() for
1016 more information.
1017 \li Since this function opens the file without specifying the file name,
1018 you cannot use this QFile with a QFileInfo.
1019 \endlist
1020
1021 \sa close()
1022
1023 \b{Note for the Windows Platform}
1024
1025 \a fh must be opened in binary mode (i.e., the mode string must contain
1026 'b', as in "rb" or "wb") when accessing files and other random-access
1027 devices. Qt will translate the end-of-line characters if you pass
1028 QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
1029 are unaffected by this limitation.
1030
1031 You need to enable support for console applications in order to use the
1032 stdin, stdout and stderr streams at the console. To do this, add the
1033 following declaration to your application's project file:
1034
1035 \snippet code/src_corelib_io_qfile.cpp 4
1036*/
1037bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
1038{
1039 Q_D(QFile);
1040 if (isOpen())
1041 return file_already_open(file&: *this);
1042 // Either Append or NewOnly implies WriteOnly
1043 if (mode & (Append | NewOnly))
1044 mode |= WriteOnly;
1045 unsetError();
1046 if ((mode & (ReadOnly | WriteOnly)) == 0) {
1047 qWarning(msg: "QFile::open: File access not specified");
1048 return false;
1049 }
1050
1051 // QIODevice provides the buffering, so request unbuffered file engines
1052 if (d->openExternalFile(flags: mode | Unbuffered, fh, handleFlags)) {
1053 QIODevice::open(mode);
1054 if (!(mode & Append) && !isSequential()) {
1055 qint64 pos = (qint64)QT_FTELL(stream: fh);
1056 if (pos != -1) {
1057 // Skip redundant checks in QFileDevice::seek().
1058 QIODevice::seek(pos);
1059 }
1060 }
1061 return true;
1062 }
1063 return false;
1064}
1065
1066/*!
1067 \overload
1068
1069 Opens the existing file descriptor \a fd in the given \a mode.
1070 \a handleFlags may be used to specify additional options.
1071 Returns \c true if successful; otherwise returns \c false.
1072
1073 When a QFile is opened using this function, behaviour of close() is
1074 controlled by the AutoCloseHandle flag.
1075 If AutoCloseHandle is specified, and this function succeeds,
1076 then calling close() closes the adopted handle.
1077 Otherwise, close() does not actually close the file, but only flushes it.
1078
1079 \warning If \a fd is not a regular file, e.g, it is 0 (\c stdin),
1080 1 (\c stdout), or 2 (\c stderr), you may not be able to seek(). In
1081 those cases, size() returns \c 0. See QIODevice::isSequential()
1082 for more information.
1083
1084 \warning Since this function opens the file without specifying the file name,
1085 you cannot use this QFile with a QFileInfo.
1086
1087 \sa close()
1088*/
1089bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
1090{
1091 Q_D(QFile);
1092 if (isOpen())
1093 return file_already_open(file&: *this);
1094 // Either Append or NewOnly implies WriteOnly
1095 if (mode & (Append | NewOnly))
1096 mode |= WriteOnly;
1097 unsetError();
1098 if ((mode & (ReadOnly | WriteOnly)) == 0) {
1099 qWarning(msg: "QFile::open: File access not specified");
1100 return false;
1101 }
1102
1103 // QIODevice provides the buffering, so request unbuffered file engines
1104 if (d->openExternalFile(flags: mode | Unbuffered, fd, handleFlags)) {
1105 QIODevice::open(mode);
1106 if (!(mode & Append) && !isSequential()) {
1107 qint64 pos = (qint64)QT_LSEEK(fd: fd, QT_OFF_T(0), SEEK_CUR);
1108 if (pos != -1) {
1109 // Skip redundant checks in QFileDevice::seek().
1110 QIODevice::seek(pos);
1111 }
1112 }
1113 return true;
1114 }
1115 return false;
1116}
1117
1118/*!
1119 \reimp
1120*/
1121bool QFile::resize(qint64 sz)
1122{
1123 return QFileDevice::resize(sz); // for now
1124}
1125
1126/*!
1127 \overload
1128
1129 Sets \a fileName to size (in bytes) \a sz. Returns \c true if
1130 the resize succeeds; false otherwise. If \a sz is larger than \a
1131 fileName currently is the new bytes will be set to 0, if \a sz is
1132 smaller the file is simply truncated.
1133
1134 \warning This function can fail if the file doesn't exist.
1135
1136 \sa resize()
1137*/
1138
1139bool
1140QFile::resize(const QString &fileName, qint64 sz)
1141{
1142 return QFile(fileName).resize(sz);
1143}
1144
1145/*!
1146 \reimp
1147*/
1148QFile::Permissions QFile::permissions() const
1149{
1150 return QFileDevice::permissions(); // for now
1151}
1152
1153/*!
1154 \overload
1155
1156 Returns the complete OR-ed together combination of
1157 QFile::Permission for \a fileName.
1158*/
1159
1160QFile::Permissions
1161QFile::permissions(const QString &fileName)
1162{
1163 return QFile(fileName).permissions();
1164}
1165
1166/*!
1167 Sets the permissions for the file to the \a permissions specified.
1168 Returns \c true if successful, or \c false if the permissions cannot be
1169 modified.
1170
1171 \warning This function does not manipulate ACLs, which may limit its
1172 effectiveness.
1173
1174 \sa permissions(), setFileName()
1175*/
1176
1177bool QFile::setPermissions(Permissions permissions)
1178{
1179 return QFileDevice::setPermissions(permissions); // for now
1180}
1181
1182/*!
1183 \overload
1184
1185 Sets the permissions for \a fileName file to \a permissions.
1186*/
1187
1188bool
1189QFile::setPermissions(const QString &fileName, Permissions permissions)
1190{
1191 return QFile(fileName).setPermissions(permissions);
1192}
1193
1194/*!
1195 \reimp
1196*/
1197qint64 QFile::size() const
1198{
1199 return QFileDevice::size(); // for now
1200}
1201
1202QT_END_NAMESPACE
1203
1204#ifndef QT_NO_QOBJECT
1205#include "moc_qfile.cpp"
1206#endif
1207

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