Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfile.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2017 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include "qplatformdefs.h"
7#include "qdebug.h"
8#include "qfile.h"
9#include "qfileinfo.h"
11#include "qlist.h"
12#include "qsavefile.h"
13#include "qtemporaryfile.h"
14#include "private/qiodevice_p.h"
15#include "private/qfile_p.h"
16#include "private/qfilesystemengine_p.h"
17#include "private/qsavefile_p.h"
18#include "private/qsystemerror_p.h"
19#include "private/qtemporaryfile_p.h"
20#if defined(QT_BUILD_CORE_LIB)
21# include "qcoreapplication.h"
22#endif
23
24#ifdef QT_NO_QOBJECT
25#define tr(X) QString::fromLatin1(X)
26#endif
27
28QT_BEGIN_NAMESPACE
29
30using namespace Qt::StringLiterals;
31
33static bool file_already_open(QFile &file, const char *where = nullptr)
34{
35 qWarning("QFile::%s: File (%ls) already open", where ? where : "open", qUtf16Printable(file.fileName()));
36 return false;
37}
38
39//************* QFilePrivate
40QFilePrivate::QFilePrivate()
41{
42}
43
44QFilePrivate::~QFilePrivate()
45{
46}
47
48bool
49QFilePrivate::openExternalFile(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags)
50{
51#ifdef QT_NO_FSFILEENGINE
52 Q_UNUSED(flags);
53 Q_UNUSED(fd);
54 return false;
55#else
56 auto fs = std::make_unique<QFSFileEngine>();
57 auto fe = fs.get();
58 fileEngine = std::move(fs);
59 return fe->open(flags, fd, handleFlags);
60#endif
61}
62
63bool
64QFilePrivate::openExternalFile(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags)
65{
66#ifdef QT_NO_FSFILEENGINE
67 Q_UNUSED(flags);
68 Q_UNUSED(fh);
69 return false;
70#else
71 auto fs = std::make_unique<QFSFileEngine>();
72 auto fe = fs.get();
73 fileEngine = std::move(fs);
74 return fe->open(flags, fh, handleFlags);
75#endif
76}
77
78QAbstractFileEngine *QFilePrivate::engine() const
79{
80 if (!fileEngine)
81 fileEngine = QAbstractFileEngine::create(fileName);
82 return fileEngine.get();
83}
84
85//************* QFile
86
87/*!
88 \class QFile
89 \inmodule QtCore
90 \brief The QFile class provides an interface for reading from and writing to files.
91
92 \ingroup io
93
94 \reentrant
95
96 QFile is an I/O device for reading and writing text and binary
97 files and \l{The Qt Resource System}{resources}. A QFile may be
98 used by itself or, more conveniently, with a QTextStream or
99 QDataStream.
100
101 The file name is usually passed in the constructor, but it can be
102 set at any time using setFileName(). QFile expects the file
103 separator to be '/' regardless of operating system. The use of
104 other separators (e.g., '\\') is not supported.
105
106 You can check for a file's existence using exists(), and remove a
107 file using remove(). (More advanced file system related operations
108 are provided by QFileInfo and QDir.)
109
110 The file is opened with open(), closed with close(), and flushed
111 with flush(). Data is usually read and written using QDataStream
112 or QTextStream, but you can also call the QIODevice-inherited
113 functions read(), readLine(), readAll(), write(). QFile also
114 inherits getChar(), putChar(), and ungetChar(), which work one
115 character at a time.
116
117 The size of the file is returned by size(). You can get the
118 current file position using pos(), or move to a new file position
119 using seek(). If you've reached the end of the file, atEnd()
120 returns \c true.
121
122 \section1 Reading Files Directly
123
124 The following example reads a text file line by line:
125
126 \snippet file/file.cpp 0
127
128 The \l{QIODeviceBase::}{Text} flag passed to open() tells Qt to convert
129 Windows-style line terminators ("\\r\\n") into C++-style
130 terminators ("\\n"). By default, QFile assumes binary, i.e. it
131 doesn't perform any conversion on the bytes stored in the file.
132
133 \section1 Using Streams to Read Files
134
135 The next example uses QTextStream to read a text file
136 line by line:
137
138 \snippet file/file.cpp 1
139
140 QTextStream takes care of converting the 8-bit data stored on
141 disk into a 16-bit Unicode QString. By default, it assumes that
142 the file is encoded in UTF-8. This can be changed using
143 \l QTextStream::setEncoding().
144
145 To write text, we can use operator<<(), which is overloaded to
146 take a QTextStream on the left and various data types (including
147 QString) on the right:
148
149 \snippet file/file.cpp 2
150
151 QDataStream is similar, in that you can use operator<<() to write
152 data and operator>>() to read it back. See the class
153 documentation for details.
154
155 \section1 Signals
156
157 Unlike other QIODevice implementations, such as QTcpSocket, QFile does not
158 emit the aboutToClose(), bytesWritten(), or readyRead() signals. This
159 implementation detail means that QFile is not suitable for reading and
160 writing certain types of files, such as device files on Unix platforms.
161
162 \section1 Platform Specific Issues
163
164 \l{Input/Output and Networking}{Qt APIs related to I/O} use UTF-16 based
165 QStrings to represent file paths. Standard C++ APIs (\c <cstdio> or
166 \c <iostream>) or platform-specific APIs however often need a 8-bit encoded
167 path. You can use encodeName() and decodeName() to convert between both
168 representations.
169
170 On Unix, there are some special system files (e.g. in \c /proc) for which
171 size() will always return 0, yet you may still be able to read more data
172 from such a file; the data is generated in direct response to you calling
173 read(). In this case, however, you cannot use atEnd() to determine if
174 there is more data to read (since atEnd() will return true for a file that
175 claims to have size 0). Instead, you should either call readAll(), or call
176 read() or readLine() repeatedly until no more data can be read. The next
177 example uses QTextStream to read \c /proc/modules line by line:
178
179 \snippet file/file.cpp 3
180
181 File permissions are handled differently on Unix-like systems and
182 Windows. In a non \l{QIODevice::isWritable()}{writable}
183 directory on Unix-like systems, files cannot be created. This is not always
184 the case on Windows, where, for instance, the 'My Documents'
185 directory usually is not writable, but it is still possible to
186 create files in it.
187
188 Qt's understanding of file permissions is limited, which affects especially
189 the \l QFile::setPermissions() function. On Windows, Qt will set only the
190 legacy read-only flag, and that only when none of the Write* flags are
191 passed. Qt does not manipulate access control lists (ACLs), which makes this
192 function mostly useless for NTFS volumes. It may still be of use for USB
193 sticks that use VFAT file systems. POSIX ACLs are not manipulated, either.
194
195 \include android-content-uri-limitations.qdocinc
196
197 \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
198*/
199
200#ifdef QT_NO_QOBJECT
201QFile::QFile()
202 : QFileDevice(*new QFilePrivate)
203{
204}
205QFile::QFile(const QString &name)
206 : QFileDevice(*new QFilePrivate)
207{
208 d_func()->fileName = name;
209}
210QFile::QFile(QFilePrivate &dd)
211 : QFileDevice(dd)
212{
213}
214#else
215/*!
216 Constructs a QFile object.
217*/
218QFile::QFile()
219 : QFileDevice(*new QFilePrivate, nullptr)
220{
221}
222/*!
223 Constructs a new file object with the given \a parent.
224*/
225QFile::QFile(QObject *parent)
226 : QFileDevice(*new QFilePrivate, parent)
227{
228}
229/*!
230 Constructs a new file object to represent the file with the given \a name.
231
232//! [qfile-explicit-constructor-note]
233 \note In versions up to and including Qt 6.8, this constructor is
234 implicit, for backward compatibility. Starting from Qt 6.9 this
235 constructor is unconditionally \c{explicit}. Users can force this
236 constructor to be \c{explicit} even in earlier versions of Qt by
237 defining the \c{QT_EXPLICIT_QFILE_CONSTRUCTION_FROM_PATH} macro
238 before including any Qt header.
239//! [qfile-explicit-constructor-note]
240*/
241QFile::QFile(const QString &name)
242 : QFileDevice(*new QFilePrivate, nullptr)
243{
244 Q_D(QFile);
245 d->fileName = name;
246}
247/*!
248 Constructs a new file object with the given \a parent to represent the
249 file with the specified \a name.
250*/
251QFile::QFile(const QString &name, QObject *parent)
252 : QFileDevice(*new QFilePrivate, parent)
253{
254 Q_D(QFile);
255 d->fileName = name;
256}
257/*!
258 \internal
259*/
260QFile::QFile(QFilePrivate &dd, QObject *parent)
261 : QFileDevice(dd, parent)
262{
263}
264#endif
265
266/*!
267 Destroys the file object, closing it if necessary.
268*/
269QFile::~QFile()
270{
271}
272
273/*!
274 Returns the name of the file as set by setFileName(), rename(), or
275 by the QFile constructors.
276
277 \sa setFileName(), rename(), QFileInfo::fileName()
278*/
279QString QFile::fileName() const
280{
281 Q_D(const QFile);
282 return d->engine()->fileName(QAbstractFileEngine::DefaultName);
283}
284
285/*!
286 Sets the \a name of the file. The name can have no path, a
287 relative path, or an absolute path.
288
289 Do not call this function if the file has already been opened.
290
291 If the file name has no path or a relative path, the path used
292 will be the application's current directory path
293 \e{at the time of the open()} call.
294
295 Example:
296 \snippet code/src_corelib_io_qfile.cpp 0
297
298 Note that the directory separator "/" works for all operating
299 systems supported by Qt.
300
301 \sa fileName(), QFileInfo, QDir
302*/
303void
304QFile::setFileName(const QString &name)
305{
306 Q_D(QFile);
307 if (isOpen()) {
308 file_already_open(*this, "setFileName");
309 close();
310 }
311 d->fileEngine.reset(); //get a new file engine later
312 d->fileName = name;
313}
314
315/*!
316 \fn QString QFile::decodeName(const char *localFileName)
317
318 \overload
319
320 Returns the Unicode version of the given \a localFileName. See
321 encodeName() for details.
322*/
323
324/*!
325 \fn QByteArray QFile::encodeName(const QString &fileName)
326
327 Converts \a fileName to an 8-bit encoding that you can use in native
328 APIs. On Windows, the encoding is the one from active Windows (ANSI)
329 codepage. On other platforms, this is UTF-8, for \macos in decomposed
330 form (NFD).
331
332 \sa decodeName()
333*/
334
335/*!
336 \fn QString QFile::decodeName(const QByteArray &localFileName)
337
338 This does the reverse of QFile::encodeName() using \a localFileName.
339
340 \sa encodeName()
341*/
342
343/*!
344 \overload
345
346 Returns \c true if the file specified by fileName() exists; otherwise
347 returns \c false.
348
349 \sa fileName(), setFileName()
350*/
351
352bool
353QFile::exists() const
354{
355 Q_D(const QFile);
356 // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
357 return d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
358 | QAbstractFileEngine::Refresh).testAnyFlag(QAbstractFileEngine::ExistsFlag);
359}
360
361/*!
362 Returns \c true if the file specified by \a fileName exists; otherwise
363 returns \c false.
364
365 \note If \a fileName is a symlink that points to a non-existing
366 file, false is returned.
367*/
368
369bool
370QFile::exists(const QString &fileName)
371{
372 return QFileInfo::exists(fileName);
373}
374
375/*!
376 \fn QString QFile::symLinkTarget() const
377 \since 4.2
378 \overload
379
380 Returns the absolute path of the file or directory a symlink (or shortcut
381 on Windows) points to, or a an empty string if the object isn't a symbolic
382 link.
383
384 This name may not represent an existing file; it is only a string.
385 QFile::exists() returns \c true if the symlink points to an existing file.
386
387 \sa fileName(), setFileName()
388*/
389QString QFile::symLinkTarget() const
390{
391 Q_D(const QFile);
392 return d->engine()->fileName(QAbstractFileEngine::AbsoluteLinkTarget);
393}
394
395/*!
396 \fn static QString QFile::symLinkTarget(const QString &fileName)
397 \since 4.2
398
399 Returns the absolute path of the file or directory referred to by the
400 symlink (or shortcut on Windows) specified by \a fileName, or returns an
401 empty string if the \a fileName does not correspond to a symbolic link.
402
403 This name may not represent an existing file; it is only a string.
404 QFile::exists() returns \c true if the symlink points to an existing file.
405*/
406QString QFile::symLinkTarget(const QString &fileName)
407{
408 return QFileInfo(fileName).symLinkTarget();
409}
410
411/*!
412 Removes the file specified by fileName(). Returns \c true if successful;
413 otherwise returns \c false.
414
415 The file is closed before it is removed.
416
417 \sa setFileName()
418*/
419
420bool
421QFile::remove()
422{
423 Q_D(QFile);
424 if (d->fileName.isEmpty() &&
425 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
426 qWarning("QFile::remove: Empty or null file name");
427 return false;
428 }
429 unsetError();
430 close();
431 if (error() == QFile::NoError) {
432 if (d->engine()->remove()) {
433 unsetError();
434 return true;
435 }
436 d->setError(QFile::RemoveError, d->fileEngine->errorString());
437 }
438 return false;
439}
440
441/*!
442 \overload
443
444 Removes the file specified by the \a fileName given.
445
446 Returns \c true if successful; otherwise returns \c false.
447
448 \sa remove()
449*/
450
451bool
452QFile::remove(const QString &fileName)
453{
454 return QFile(fileName).remove();
455}
456
457/*!
458 \since 6.9
459
460 Returns \c true if Qt supports moving files to a trash (recycle bin) in the
461 current operating system using the moveToTrash() function, \c false
462 otherwise. Note that this function returning \c true does not imply
463 moveToTrash() will succeed. In particular, this function does not check if
464 the user has disabled the functionality in their settings.
465
466 \sa moveToTrash()
467*/
468bool QFile::supportsMoveToTrash()
469{
470 return QFileSystemEngine::supportsMoveFileToTrash();
471}
472
473/*!
474 \since 5.15
475
476 Moves the file specified by fileName() to the trash. Returns \c true if successful,
477 and sets the fileName() to the path at which the file can be found within the trash;
478 otherwise returns \c false.
479
480//! [move-to-trash-common]
481 The time for this function to run is independent of the size of the file
482 being trashed. If this function is called on a directory, it may be
483 proportional to the number of files being trashed. If the current
484 fileName() points to a symbolic link, this function will move the link to
485 the trash, possibly breaking it, not the target of the link.
486
487 This function uses the Windows and \macos APIs to perform the trashing on
488 those two operating systems. Elsewhere (Unix systems), this function
489 implements the \l{FreeDesktop.org Trash specification version 1.0}.
490
491 \note When using the FreeDesktop.org Trash implementation, this function
492 will fail if it is unable to move the files to the trash location by way of
493 file renames and hardlinks. This condition arises if the file being trashed
494 resides on a volume (mount point) on which the current user does not have
495 permission to create the \c{.Trash} directory, or with some unusual
496 filesystem types or configurations (such as sub-volumes that aren't
497 themselves mount points).
498//! [move-to-trash-common]
499
500 \note On systems where the system API doesn't report the location of the
501 file in the trash, fileName() will be set to the null string once the file
502 has been moved. On systems that don't have a trash can, this function
503 always returns \c false (see supportsMoveToTrash()).
504
505 \sa supportsMoveToTrash(), remove(), QDir::remove()
506*/
507bool
508QFile::moveToTrash()
509{
510 Q_D(QFile);
511 if (d->fileName.isEmpty() &&
512 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
513 qWarning("QFile::remove: Empty or null file name");
514 return false;
515 }
516 unsetError();
517 close();
518 if (error() == QFile::NoError) {
519 QFileSystemEntry fileEntry(d->fileName);
520 QFileSystemEntry trashEntry;
521 QSystemError error;
522 if (QFileSystemEngine::moveFileToTrash(fileEntry, trashEntry, error)) {
523 setFileName(trashEntry.filePath());
524 unsetError();
525 return true;
526 }
527 d->setError(QFile::RenameError, error.toString());
528 }
529 return false;
530}
531
532/*!
533 \since 5.15
534 \overload
535
536 Moves the file specified by \a fileName to the trash. Returns \c true if successful,
537 and sets \a pathInTrash (if provided) to the path at which the file can be found within
538 the trash; otherwise returns \c false.
539
540 \include qfile.cpp move-to-trash-common
541
542 \note On systems where the system API doesn't report the path of the file in the
543 trash, \a pathInTrash will be set to the null string once the file has been moved.
544 On systems that don't have a trash can, this function always returns false.
545
546*/
547bool
548QFile::moveToTrash(const QString &fileName, QString *pathInTrash)
549{
550 QFile file(fileName);
551 if (file.moveToTrash()) {
552 if (pathInTrash)
553 *pathInTrash = file.fileName();
554 return true;
555 }
556 return false;
557}
558
559/*!
560 Renames the file currently specified by fileName() to \a newName.
561 Returns \c true if successful; otherwise returns \c false.
562
563 If a file with the name \a newName already exists, rename() returns \c false
564 (i.e., QFile will not overwrite it).
565
566 The file is closed before it is renamed.
567
568 If the rename operation fails, Qt will attempt to copy this file's
569 contents to \a newName, and then remove this file, keeping only
570 \a newName. If that copy operation fails or this file can't be removed,
571 the destination file \a newName is removed to restore the old state.
572
573 \sa setFileName()
574*/
575
576bool
577QFile::rename(const QString &newName)
578{
579 Q_D(QFile);
580
581 // if this is a QTemporaryFile, the virtual fileName() call here may do something
582 if (fileName().isEmpty()) {
583 qWarning("QFile::rename: Empty or null file name");
584 return false;
585 }
586 if (d->fileName == newName) {
587 d->setError(QFile::RenameError, tr("Destination file is the same file."));
588 return false;
589 }
590 if (!exists()) {
591 d->setError(QFile::RenameError, tr("Source file does not exist."));
592 return false;
593 }
594
595 // Keep engine for target alive during the operation
596 // FIXME: Involve the target engine in the operation
597 auto targetEngine = QFileSystemEngine::createLegacyEngine(newName);
598
599 // If the file exists and it is a case-changing rename ("foo" -> "Foo"),
600 // compare Ids to make sure it really is a different file.
601 // Note: this does not take file engines into account.
602 bool changingCase = false;
603 QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
604 if (!targetId.isNull()) {
605 QByteArray fileId = d->fileEngine ?
606 d->fileEngine->id() :
607 QFileSystemEngine::id(QFileSystemEntry(d->fileName));
608 changingCase = (fileId == targetId && d->fileName.compare(newName, Qt::CaseInsensitive) == 0);
609 if (!changingCase) {
610 d->setError(QFile::RenameError, tr("Destination file exists"));
611 return false;
612 }
613
614#if defined(Q_OS_LINUX) && QT_CONFIG(temporaryfile)
615 // rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
616 // FS, such as FAT32. Move the file away and rename in 2 steps to work around.
617 QTemporaryFileName tfn(d->fileName);
618 QFileSystemEntry src(d->fileName);
619 QSystemError error;
620 for (int attempt = 0; attempt < 16; ++attempt) {
621 QFileSystemEntry tmp(tfn.generateNext(), QFileSystemEntry::FromNativePath());
622
623 // rename to temporary name
624 if (!QFileSystemEngine::renameFile(src, tmp, error))
625 continue;
626
627 // rename to final name
628 if (QFileSystemEngine::renameFile(tmp, QFileSystemEntry(newName), error)) {
629 d->fileEngine->setFileName(newName);
630 d->fileName = newName;
631 return true;
632 }
633
634 // We need to restore the original file.
635 QSystemError error2;
636 if (QFileSystemEngine::renameFile(tmp, src, error2))
637 break; // report the original error, below
638
639 // report both errors
640 d->setError(QFile::RenameError,
641 tr("Error while renaming: %1").arg(error.toString())
642 + u'\n'
643 + tr("Unable to restore from %1: %2").
644 arg(QDir::toNativeSeparators(tmp.filePath()), error2.toString()));
645 return false;
646 }
647 d->setError(QFile::RenameError,
648 tr("Error while renaming: %1").arg(error.toString()));
649 return false;
650#endif // Q_OS_LINUX
651 }
652 unsetError();
653 close();
654 if (error() == QFile::NoError) {
655 if (changingCase ? d->engine()->renameOverwrite(newName) : d->engine()->rename(newName)) {
656 unsetError();
657 // engine was able to handle the new name so we just reset it
658 d->fileEngine->setFileName(newName);
659 d->fileName = newName;
660 return true;
661 }
662
663 // Engine was unable to rename and the fallback will delete the original file,
664 // so we have to back out here on case-insensitive file systems:
665 if (changingCase) {
666 d->setError(QFile::RenameError, d->fileEngine->errorString());
667 return false;
668 }
669
670 if (isSequential()) {
671 d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
672 return false;
673 }
674
675#if QT_CONFIG(temporaryfile)
676 // copy the file to the destination first
677 if (d->copy(newName)) {
678 // succeeded, remove the original
679 if (!remove()) {
680 d->setError(QFile::RenameError, tr("Cannot remove source file: %1").arg(errorString()));
681 QFile out(newName);
682 // set it back to writable so we can delete it
683 out.setPermissions(ReadUser | WriteUser);
684 out.remove(newName);
685 return false;
686 }
687 d->fileEngine->setFileName(newName);
688 unsetError();
689 setFileName(newName);
690 return true;
691 } else {
692 // change the error type but keep the string
693 d->setError(QFile::RenameError, errorString());
694 }
695#else
696 // copy the error from the engine rename() above
697 d->setError(QFile::RenameError, d->fileEngine->errorString());
698#endif
699 }
700 return false;
701}
702
703/*!
704 \overload
705
706 Renames the file \a oldName to \a newName. Returns \c true if
707 successful; otherwise returns \c false.
708
709 If a file with the name \a newName already exists, rename() returns \c false
710 (i.e., QFile will not overwrite it).
711
712 \sa rename()
713*/
714
715bool
716QFile::rename(const QString &oldName, const QString &newName)
717{
718 return QFile(oldName).rename(newName);
719}
720
721/*!
722
723 Creates a link named \a linkName that points to the file currently specified by
724 fileName(). What a link is depends on the underlying filesystem (be it a
725 shortcut on Windows or a symbolic link on Unix). Returns \c true if successful;
726 otherwise returns \c false.
727
728 This function will not overwrite an already existing entity in the file system;
729 in this case, \c link() will return false and set \l{QFile::}{error()} to
730 return \l{QFile::}{RenameError}.
731
732 \note To create a valid link on Windows, \a linkName must have a \c{.lnk} file extension.
733
734 \sa setFileName()
735*/
736
737bool
738QFile::link(const QString &linkName)
739{
740 Q_D(QFile);
741 if (fileName().isEmpty()) {
742 qWarning("QFile::link: Empty or null file name");
743 return false;
744 }
745
746 // Keep engine for target alive during the operation
747 // FIXME: Involve the target engine in the operation
748 auto targetEngine = QFileSystemEngine::createLegacyEngine(linkName);
749
750 QFileInfo fi(linkName);
751 if (d->engine()->link(fi.absoluteFilePath())) {
752 unsetError();
753 return true;
754 }
755 d->setError(QFile::RenameError, d->fileEngine->errorString());
756 return false;
757}
758
759/*!
760 \overload
761
762 Creates a link named \a linkName that points to the file \a fileName. What a link is
763 depends on the underlying filesystem (be it a shortcut on Windows
764 or a symbolic link on Unix). Returns \c true if successful; otherwise
765 returns \c false.
766
767 \sa link()
768*/
769
770bool
771QFile::link(const QString &fileName, const QString &linkName)
772{
773 return QFile(fileName).link(linkName);
774}
775
776#if QT_CONFIG(temporaryfile) // dangerous without QTemporaryFile
777bool QFilePrivate::copy(const QString &newName)
778{
779 Q_Q(QFile);
780 Q_ASSERT(error == QFile::NoError);
781 Q_ASSERT(!q->isOpen());
782
783 // Keep engine for target alive during the operation
784 // FIXME: Involve the target engine in the operation
785 auto targetEngine = QFileSystemEngine::createLegacyEngine(newName);
786
787 // Some file engines can perform this copy more efficiently (e.g., Windows
788 // calling CopyFile).
789 if (engine()->copy(newName))
790 return true;
791
792 if (!q->open(QFile::ReadOnly | QFile::Unbuffered)) {
793 setError(QFile::CopyError, QFile::tr("Cannot open %1 for input").arg(fileName));
794 return false;
795 }
796
797 QSaveFile out(newName);
798 out.setDirectWriteFallback(true);
799 if (!out.open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
800 q->close();
801 setError(QFile::CopyError, QFile::tr("Cannot open for output: %1").arg(out.errorString()));
802 return false;
803 }
804
805 // Attempt to do an OS-level data copy
806 QAbstractFileEngine::TriStateResult r = engine()->cloneTo(out.d_func()->engine());
807 if (r == QAbstractFileEngine::TriStateResult::Failed) {
808 q->close();
809 setError(QFile::CopyError, QFile::tr("Could not copy to %1: %2")
810 .arg(newName, engine()->errorString()));
811 return false;
812 }
813
814 while (r == QAbstractFileEngine::TriStateResult::NotSupported) {
815 // OS couldn't do it, so do a block-level copy
816 char block[4096];
817 qint64 in = q->read(block, sizeof(block));
818 if (in == 0)
819 break; // eof
820 if (in < 0) {
821 // Unable to read from the source. Save the error from read() above.
822 QString s = std::move(errorString);
823 q->close();
824 setError(QFile::CopyError, std::move(s));
825 return false;
826 }
827 if (in != out.write(block, in)) {
828 q->close();
829 setError(QFile::CopyError, QFile::tr("Failure to write block: %1")
830 .arg(out.errorString()));
831 return false;
832 }
833 }
834
835 // copy the permissions
836 out.setPermissions(q->permissions());
837 q->close();
838
839 // final step: commit the copy
840 if (out.commit())
841 return true;
842 setError(out.error(), out.errorString());
843 return false;
844}
845
846/*!
847 Copies the file named fileName() to \a newName.
848
849 \include qfile-copy.qdocinc
850
851 \note On Android, this operation is not yet supported for \c content
852 scheme URIs.
853
854 \sa setFileName()
855*/
856
857bool
858QFile::copy(const QString &newName)
859{
860 Q_D(QFile);
861 if (fileName().isEmpty()) {
862 qWarning("QFile::copy: Empty or null file name");
863 return false;
864 }
865 if (QFile::exists(newName)) {
866 // ### Race condition. If a file is moved in after this, it /will/ be
867 // overwritten. On Unix, the proper solution is to use hardlinks:
868 // return ::link(old, new) && ::remove(old); See also rename().
869 d->setError(QFile::CopyError, tr("Destination file exists"));
870 return false;
871 }
872 unsetError();
873 close();
874 if (error() == QFile::NoError)
875 return d->copy(newName);
876 return false;
877}
878
879/*!
880 \overload
881
882 Copies the file named \a fileName to \a newName.
883
884 \include qfile-copy.qdocinc
885
886 \note On Android, this operation is not yet supported for \c content
887 scheme URIs.
888
889 \sa rename()
890*/
891
892bool
893QFile::copy(const QString &fileName, const QString &newName)
894{
895 return QFile(fileName).copy(newName);
896}
897#endif // QT_CONFIG(temporaryfile)
898
899/*!
900 Opens the file using \a mode flags, returning \c true if successful;
901 otherwise returns \c false.
902
903 The flags for \a mode must include \l QIODeviceBase::ReadOnly,
904 \l WriteOnly, or \l ReadWrite. It may also have additional flags,
905 such as \l Text and \l Unbuffered.
906
907 \note In \l{WriteOnly} or \l{ReadWrite}
908 mode, if the relevant file does not already exist, this function
909 will try to create a new file before opening it. The file will be
910 created with mode 0666 masked by the umask on POSIX systems, and
911 with permissions inherited from the parent directory on Windows.
912 On Android, it's expected to have access permission to the parent
913 of the file name, otherwise, it won't be possible to create this
914 non-existing file.
915
916 \sa QT_USE_NODISCARD_FILE_OPEN, setFileName()
917*/
918bool QFile::open(OpenMode mode)
919{
920 Q_D(QFile);
921 if (isOpen())
922 return file_already_open(*this);
923 // Either Append or NewOnly implies WriteOnly
924 if (mode & (Append | NewOnly))
925 mode |= WriteOnly;
926 unsetError();
927 if ((mode & (ReadOnly | WriteOnly)) == 0) {
928 qWarning("QIODevice::open: File access not specified");
929 return false;
930 }
931
932 // QIODevice provides the buffering, so there's no need to request it from the file engine.
933 if (d->engine()->open(mode | QIODevice::Unbuffered)) {
934 QIODevice::open(mode);
935 if (mode & Append)
936 seek(size());
937 return true;
938 }
939 QFile::FileError err = d->fileEngine->error();
940 if (err == QFile::UnspecifiedError)
941 err = QFile::OpenError;
942 d->setError(err, d->fileEngine->errorString());
943 return false;
944}
945
946/*!
947 \overload
948
949 If the file does not exist and \a mode implies creating it, it is created
950 with the specified \a permissions.
951
952 On POSIX systems the actual permissions are influenced by the
953 value of \c umask.
954
955 On Windows the permissions are emulated using ACLs. These ACLs may be in non-canonical
956 order when the group is granted less permissions than others. Files and directories with
957 such permissions will generate warnings when the Security tab of the Properties dialog
958 is opened. Granting the group all permissions granted to others avoids such warnings.
959
960 \sa QIODevice::OpenMode, setFileName(), QT_USE_NODISCARD_FILE_OPEN
961 \since 6.3
962*/
963bool QFile::open(OpenMode mode, QFile::Permissions permissions)
964{
965 Q_D(QFile);
966 if (isOpen())
967 return file_already_open(*this);
968 // Either Append or NewOnly implies WriteOnly
969 if (mode & (Append | NewOnly))
970 mode |= WriteOnly;
971 unsetError();
972 if ((mode & (ReadOnly | WriteOnly)) == 0) {
973 qWarning("QIODevice::open: File access not specified");
974 return false;
975 }
976
977 // QIODevice provides the buffering, so there's no need to request it from the file engine.
978 if (d->engine()->open(mode | QIODevice::Unbuffered, permissions)) {
979 QIODevice::open(mode);
980 if (mode & Append)
981 seek(size());
982 return true;
983 }
984 QFile::FileError err = d->fileEngine->error();
985 if (err == QFile::UnspecifiedError)
986 err = QFile::OpenError;
987 d->setError(err, d->fileEngine->errorString());
988 return false;
989}
990
991/*!
992 \overload
993
994 Opens the existing file handle \a fh in the given \a mode.
995 \a handleFlags may be used to specify additional options.
996 Returns \c true if successful; otherwise returns \c false.
997
998 Example:
999 \snippet code/src_corelib_io_qfile.cpp 3
1000
1001 When a QFile is opened using this function, behaviour of close() is
1002 controlled by the AutoCloseHandle flag.
1003 If AutoCloseHandle is specified, and this function succeeds,
1004 then calling close() closes the adopted handle.
1005 Otherwise, close() does not actually close the file, but only flushes it.
1006
1007 \b{Warning:}
1008 \list 1
1009 \li If \a fh does not refer to a regular file, e.g., it is \c stdin,
1010 \c stdout, or \c stderr, you may not be able to seek(). size()
1011 returns \c 0 in those cases. See QIODevice::isSequential() for
1012 more information.
1013 \li Since this function opens the file without specifying the file name,
1014 you cannot use this QFile with a QFileInfo.
1015 \endlist
1016
1017 \sa close(), QT_USE_NODISCARD_FILE_OPEN
1018
1019 \b{Note for the Windows Platform}
1020
1021 \a fh must be opened in binary mode (i.e., the mode string must contain
1022 'b', as in "rb" or "wb") when accessing files and other random-access
1023 devices. Qt will translate the end-of-line characters if you pass
1024 QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
1025 are unaffected by this limitation.
1026
1027 You need to enable support for console applications in order to use the
1028 stdin, stdout and stderr streams at the console. To do this, add the
1029 following declaration to your application's project file:
1030
1031 \snippet code/src_corelib_io_qfile.cpp 4
1032*/
1033bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
1034{
1035 Q_D(QFile);
1036 if (isOpen())
1037 return file_already_open(*this);
1038 // Either Append or NewOnly implies WriteOnly
1039 if (mode & (Append | NewOnly))
1040 mode |= WriteOnly;
1041 unsetError();
1042 if ((mode & (ReadOnly | WriteOnly)) == 0) {
1043 qWarning("QFile::open: File access not specified");
1044 return false;
1045 }
1046
1047 // QIODevice provides the buffering, so request unbuffered file engines
1048 if (d->openExternalFile(mode | Unbuffered, fh, handleFlags)) {
1049 QIODevice::open(mode);
1050 if (!(mode & Append) && !isSequential()) {
1051 qint64 pos = (qint64)QT_FTELL(fh);
1052 if (pos != -1) {
1053 // Skip redundant checks in QFileDevice::seek().
1054 QIODevice::seek(pos);
1055 }
1056 }
1057 return true;
1058 }
1059 return false;
1060}
1061
1062/*!
1063 \overload
1064
1065 Opens the existing file descriptor \a fd in the given \a mode.
1066 \a handleFlags may be used to specify additional options.
1067 Returns \c true if successful; otherwise returns \c false.
1068
1069 When a QFile is opened using this function, behaviour of close() is
1070 controlled by the AutoCloseHandle flag.
1071 If AutoCloseHandle is specified, and this function succeeds,
1072 then calling close() closes the adopted handle.
1073 Otherwise, close() does not actually close the file, but only flushes it.
1074
1075 \warning If \a fd is not a regular file, e.g, it is 0 (\c stdin),
1076 1 (\c stdout), or 2 (\c stderr), you may not be able to seek(). In
1077 those cases, size() returns \c 0. See QIODevice::isSequential()
1078 for more information.
1079
1080 \warning Since this function opens the file without specifying the file name,
1081 you cannot use this QFile with a QFileInfo.
1082
1083 \sa close(), QT_USE_NODISCARD_FILE_OPEN
1084*/
1085bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
1086{
1087 Q_D(QFile);
1088 if (isOpen())
1089 return file_already_open(*this);
1090 // Either Append or NewOnly implies WriteOnly
1091 if (mode & (Append | NewOnly))
1092 mode |= WriteOnly;
1093 unsetError();
1094 if ((mode & (ReadOnly | WriteOnly)) == 0) {
1095 qWarning("QFile::open: File access not specified");
1096 return false;
1097 }
1098
1099 // QIODevice provides the buffering, so request unbuffered file engines
1100 if (d->openExternalFile(mode | Unbuffered, fd, handleFlags)) {
1101 QIODevice::open(mode);
1102 if (!(mode & Append) && !isSequential()) {
1103 qint64 pos = (qint64)QT_LSEEK(fd, QT_OFF_T(0), SEEK_CUR);
1104 if (pos != -1) {
1105 // Skip redundant checks in QFileDevice::seek().
1106 QIODevice::seek(pos);
1107 }
1108 }
1109 return true;
1110 }
1111 return false;
1112}
1113
1114/*!
1115 \reimp
1116*/
1117bool QFile::resize(qint64 sz)
1118{
1119 return QFileDevice::resize(sz); // for now
1120}
1121
1122/*!
1123 \overload
1124
1125 Sets \a fileName to size (in bytes) \a sz. Returns \c true if
1126 the resize succeeds; false otherwise. If \a sz is larger than \a
1127 fileName currently is the new bytes will be set to 0, if \a sz is
1128 smaller the file is simply truncated.
1129
1130 \warning This function can fail if the file doesn't exist.
1131
1132 \sa resize()
1133*/
1134
1135bool
1136QFile::resize(const QString &fileName, qint64 sz)
1137{
1138 return QFile(fileName).resize(sz);
1139}
1140
1141/*!
1142 \reimp
1143*/
1144QFile::Permissions QFile::permissions() const
1145{
1146 return QFileDevice::permissions(); // for now
1147}
1148
1149/*!
1150 \overload
1151
1152 Returns the complete OR-ed together combination of
1153 QFile::Permission for \a fileName.
1154*/
1155
1156QFile::Permissions
1157QFile::permissions(const QString &fileName)
1158{
1159 return QFile(fileName).permissions();
1160}
1161
1162/*!
1163 Sets the permissions for the file to the \a permissions specified.
1164 Returns \c true if successful, or \c false if the permissions cannot be
1165 modified.
1166
1167 \warning This function does not manipulate ACLs, which may limit its
1168 effectiveness.
1169
1170 \sa permissions(), setFileName()
1171*/
1172
1173bool QFile::setPermissions(Permissions permissions)
1174{
1175 return QFileDevice::setPermissions(permissions); // for now
1176}
1177
1178/*!
1179 \overload
1180
1181 Sets the permissions for \a fileName file to \a permissions.
1182*/
1183
1184bool
1185QFile::setPermissions(const QString &fileName, Permissions permissions)
1186{
1187 return QFile(fileName).setPermissions(permissions);
1188}
1189
1190/*!
1191 \reimp
1192*/
1193qint64 QFile::size() const
1194{
1195 return QFileDevice::size(); // for now
1196}
1197
1198/*!
1199 \fn QFile::QFile(const std::filesystem::path &name)
1200 \since 6.0
1201
1202 Constructs a new file object to represent the file with the given \a name.
1203
1204 \include qfile.cpp qfile-explicit-constructor-note
1205*/
1206/*!
1207 \fn QFile::QFile(const std::filesystem::path &name, QObject *parent)
1208 \since 6.0
1209
1210 Constructs a new file object with the given \a parent to represent the
1211 file with the specified \a name.
1212*/
1213/*!
1214 \fn std::filesystem::path QFile::filesystemFileName() const
1215 \since 6.0
1216 Returns fileName() as \c{std::filesystem::path}.
1217*/
1218/*!
1219 \fn void QFile::setFileName(const std::filesystem::path &name)
1220 \since 6.0
1221 \overload
1222*/
1223/*!
1224 \fn bool QFile::rename(const std::filesystem::path &newName)
1225 \since 6.0
1226 \overload
1227*/
1228/*!
1229 \fn bool QFile::link(const std::filesystem::path &newName)
1230 \since 6.0
1231 \overload
1232*/
1233/*!
1234 \fn bool QFile::copy(const std::filesystem::path &newName)
1235 \since 6.0
1236 \overload
1237*/
1238/*!
1239 \fn QFile::Permissions QFile::permissions(const std::filesystem::path &filename)
1240 \since 6.0
1241 \overload
1242*/
1243/*!
1244 \fn bool QFile::setPermissions(const std::filesystem::path &filename, Permissions permissionSpec)
1245 \since 6.0
1246 \overload
1247*/
1248/*!
1249 \fn bool exists(const std::filesystem::path &fileName)
1250 \since 6.3
1251 \overload
1252*/
1253/*!
1254 \fn std::filesystem::path QFile::filesystemSymLinkTarget() const
1255 \since 6.3
1256 Returns symLinkTarget() as \c{std::filesystem::path}.
1257*/
1258/*!
1259 \fn std::filesystem::path QFile::filesystemSymLinkTarget(const std::filesystem::path &fileName)
1260 \since 6.3
1261 Returns symLinkTarget() as \c{std::filesystem::path} of \a fileName.
1262*/
1263/*!
1264 \fn bool remove(const std::filesystem::path &fileName)
1265 \since 6.3
1266 \overload
1267*/
1268/*!
1269 \fn bool moveToTrash(const std::filesystem::path &fileName, QString *pathInTrash)
1270 \since 6.3
1271 \overload
1272*/
1273/*!
1274 \fn bool rename(const std::filesystem::path &oldName, const std::filesystem::path &newName)
1275 \since 6.3
1276 \overload
1277*/
1278/*!
1279 \fn bool link(const std::filesystem::path &fileName, const std::filesystem::path &newName);
1280 \since 6.3
1281 \overload
1282*/
1283/*!
1284 \fn bool copy(const std::filesystem::path &fileName, const std::filesystem::path &newName);
1285 \since 6.3
1286 \overload
1287*/
1288
1289
1290/*!
1291 \class QNtfsPermissionCheckGuard
1292 \since 6.6
1293 \inmodule QtCore
1294 \brief The QNtfsPermissionCheckGuard class is a RAII class to manage NTFS
1295 permission checking.
1296
1297 \ingroup io
1298
1299 For performance reasons, QFile, QFileInfo, and related classes do not
1300 perform full ownership and permission (ACL) checking on NTFS file systems
1301 by default. During the lifetime of any instance of this class, that
1302 default is overridden and advanced checking is performed. This provides
1303 a safe and easy way to manage enabling and disabling this change to the
1304 default behavior.
1305
1306 Example:
1307
1308 \snippet ntfsp.cpp raii
1309
1310 This class is available only on Windows.
1311
1312 \section1 qt_ntfs_permission_lookup
1313
1314 Prior to Qt 6.6, the user had to directly manipulate the global variable
1315 \c qt_ntfs_permission_lookup. However, this was a non-atomic global
1316 variable and as such it was prone to data races.
1317
1318 The variable \c qt_ntfs_permission_lookup is therefore deprecated since Qt
1319 6.6.
1320*/
1321
1322/*!
1323 \fn QNtfsPermissionCheckGuard::QNtfsPermissionCheckGuard()
1324
1325 Creates a guard and calls the function qEnableNtfsPermissionChecks().
1326*/
1327
1328/*!
1329 \fn QNtfsPermissionCheckGuard::~QNtfsPermissionCheckGuard()
1330
1331 Destroys the guard and calls the function qDisableNtfsPermissionChecks().
1332*/
1333
1334
1335/*!
1336 \fn bool qEnableNtfsPermissionChecks()
1337 \since 6.6
1338 \threadsafe
1339 \relates QNtfsPermissionCheckGuard
1340
1341 Enables permission checking on NTFS file systems. Returns \c true if the check
1342 was already enabled before the call to this function, meaning that there
1343 are other users.
1344
1345 This function is only available on Windows and makes the direct
1346 manipulation of \l qt_ntfs_permission_lookup obsolete.
1347
1348 This is a low-level function, please consider the RAII class
1349 \l QNtfsPermissionCheckGuard instead.
1350
1351 \note The thread-safety of this function holds only as long as there are no
1352 concurrent updates to \l qt_ntfs_permission_lookup.
1353*/
1354
1355/*!
1356 \fn bool qDisableNtfsPermissionChecks()
1357 \since 6.6
1358 \threadsafe
1359 \relates QNtfsPermissionCheckGuard
1360
1361 Disables permission checking on NTFS file systems. Returns \c true if the
1362 check is disabled, meaning that there are no more users.
1363
1364 This function is only available on Windows and makes the direct
1365 manipulation of \l qt_ntfs_permission_lookup obsolete.
1366
1367 This is a low-level function and must (only) be called to match one earlier
1368 call to qEnableNtfsPermissionChecks(). Please consider the RAII class
1369 \l QNtfsPermissionCheckGuard instead.
1370
1371 \note The thread-safety of this function holds only as long as there are no
1372 concurrent updates to \l qt_ntfs_permission_lookup.
1373*/
1374
1375/*!
1376 \fn bool qAreNtfsPermissionChecksEnabled()
1377 \since 6.6
1378 \threadsafe
1379 \relates QNtfsPermissionCheckGuard
1380
1381 Checks the status of the permission checks on NTFS file systems. Returns
1382 \c true if the check is enabled.
1383
1384 This function is only available on Windows and makes the direct
1385 manipulation of \l qt_ntfs_permission_lookup obsolete.
1386
1387 \note The thread-safety of this function holds only as long as there are no
1388 concurrent updates to \l qt_ntfs_permission_lookup.
1389*/
1390
1391#ifndef QT_NO_DEBUG_STREAM
1392void QFilePrivate::writeToDebugStream(QDebug &dbg) const
1393{
1394 Q_Q(const QFile);
1395 dbg.nospace();
1396 dbg << "QFile(" << q->fileName() << ')';
1397}
1398#endif
1399
1400QT_END_NAMESPACE
1401
1402#ifndef QT_NO_QOBJECT
1403#include "moc_qfile.cpp"
1404#endif
static Q_DECL_COLD_FUNCTION bool file_already_open(QFile &file, const char *where=nullptr)
Definition qfile.cpp:33