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{
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().
413
414 Returns \c true if the file was successfully removed; otherwise returns \c
415 false.
416
417 The file is closed before it is removed, if it was open.
418
419 \sa setFileName()
420*/
421
422bool
423QFile::remove()
424{
425 Q_D(QFile);
426 if (d->fileName.isEmpty() &&
427 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
428 qWarning("QFile::remove: Empty or null file name");
429 return false;
430 }
431 unsetError();
432 close();
433 if (error() == QFile::NoError) {
434 if (d->engine()->remove()) {
435 unsetError();
436 return true;
437 }
438 d->setError(QFile::RemoveError, d->fileEngine->errorString());
439 }
440 return false;
441}
442
443/*!
444 \overload
445
446 Removes the file specified by the \a fileName given.
447
448 Returns \c true if the file was successfully removed; otherwise returns
449 \c false.
450
451 \sa remove()
452*/
453
454bool
455QFile::remove(const QString &fileName)
456{
457 return QFile(fileName).remove();
458}
459
460/*!
461 \since 6.9
462
463 Returns \c true if Qt supports moving files to a trash (recycle bin) in the
464 current operating system using the moveToTrash() function, \c false
465 otherwise. Note that this function returning \c true does not imply
466 moveToTrash() will succeed. In particular, this function does not check if
467 the user has disabled the functionality in their settings.
468
469 \sa moveToTrash()
470*/
471bool QFile::supportsMoveToTrash()
472{
473 return QFileSystemEngine::supportsMoveFileToTrash();
474}
475
476/*!
477 \since 5.15
478
479 Moves the file specified by fileName() to the trash. Returns \c true if successful,
480 and sets the fileName() to the path at which the file can be found within the trash;
481 otherwise returns \c false.
482
483//! [move-to-trash-common]
484 The time for this function to run is independent of the size of the file
485 being trashed. If this function is called on a directory, it may be
486 proportional to the number of files being trashed. If the current
487 fileName() points to a symbolic link, this function will move the link to
488 the trash, possibly breaking it, not the target of the link.
489
490 This function uses the Windows and \macos APIs to perform the trashing on
491 those two operating systems. Elsewhere (Unix systems), this function
492 implements the \l{FreeDesktop.org Trash specification version 1.0}.
493
494 \note When using the FreeDesktop.org Trash implementation, this function
495 will fail if it is unable to move the files to the trash location by way of
496 file renames and hardlinks. This condition arises if the file being trashed
497 resides on a volume (mount point) on which the current user does not have
498 permission to create the \c{.Trash} directory, or with some unusual
499 filesystem types or configurations (such as sub-volumes that aren't
500 themselves mount points).
501//! [move-to-trash-common]
502
503 \note On systems where the system API doesn't report the location of the
504 file in the trash, fileName() will be set to the null string once the file
505 has been moved. On systems that don't have a trash can, this function
506 always returns \c false (see supportsMoveToTrash()).
507
508 \sa supportsMoveToTrash(), remove(), QDir::remove()
509*/
510bool
511QFile::moveToTrash()
512{
513 Q_D(QFile);
514 if (d->fileName.isEmpty() &&
515 !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
516 qWarning("QFile::remove: Empty or null file name");
517 return false;
518 }
519 unsetError();
520 close();
521 if (error() == QFile::NoError) {
522 QFileSystemEntry fileEntry(d->fileName);
523 QFileSystemEntry trashEntry;
524 QSystemError error;
525 if (QFileSystemEngine::moveFileToTrash(fileEntry, trashEntry, error)) {
526 setFileName(trashEntry.filePath());
527 unsetError();
528 return true;
529 }
530 d->setError(QFile::RenameError, error.toString());
531 }
532 return false;
533}
534
535/*!
536 \since 5.15
537 \overload
538
539 Moves the file specified by \a fileName to the trash. Returns \c true if successful,
540 and sets \a pathInTrash (if provided) to the path at which the file can be found within
541 the trash; otherwise returns \c false.
542
543 \include qfile.cpp move-to-trash-common
544
545 \note On systems where the system API doesn't report the path of the file in the
546 trash, \a pathInTrash will be set to the null string once the file has been moved.
547 On systems that don't have a trash can, this function always returns false.
548
549*/
550bool
551QFile::moveToTrash(const QString &fileName, QString *pathInTrash)
552{
553 QFile file(fileName);
554 if (file.moveToTrash()) {
555 if (pathInTrash)
556 *pathInTrash = file.fileName();
557 return true;
558 }
559 return false;
560}
561
562/*!
563 Renames the file currently specified by fileName() to \a newName.
564 Returns \c true if successful; otherwise returns \c false.
565
566 If a file with the name \a newName already exists, rename() returns \c false
567 (i.e., QFile will not overwrite it).
568
569 The file is closed before it is renamed.
570
571 If the rename operation fails, Qt will attempt to copy this file's
572 contents to \a newName, and then remove this file, keeping only
573 \a newName. If that copy operation fails or this file can't be removed,
574 the destination file \a newName is removed to restore the old state.
575
576 \sa setFileName()
577*/
578
579bool
580QFile::rename(const QString &newName)
581{
582 Q_D(QFile);
583
584 // if this is a QTemporaryFile, the virtual fileName() call here may do something
585 if (fileName().isEmpty()) {
586 qWarning("QFile::rename: Empty or null file name");
587 return false;
588 }
589 if (d->fileName == newName) {
590 d->setError(QFile::RenameError, tr("Destination file is the same file."));
591 return false;
592 }
593 if (!exists()) {
594 d->setError(QFile::RenameError, tr("Source file does not exist."));
595 return false;
596 }
597
598 // Keep engine for target alive during the operation
599 // FIXME: Involve the target engine in the operation
600 auto targetEngine = QFileSystemEngine::createLegacyEngine(newName);
601
602 // If the file exists and it is a case-changing rename ("foo" -> "Foo"),
603 // compare Ids to make sure it really is a different file.
604 // Note: this does not take file engines into account.
605 bool changingCase = false;
606 QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
607 if (!targetId.isNull()) {
608 QByteArray fileId = d->fileEngine ?
609 d->fileEngine->id() :
610 QFileSystemEngine::id(QFileSystemEntry(d->fileName));
611 changingCase = (fileId == targetId && d->fileName.compare(newName, Qt::CaseInsensitive) == 0);
612 if (!changingCase) {
613 d->setError(QFile::RenameError, tr("Destination file exists"));
614 return false;
615 }
616
617#if defined(Q_OS_LINUX) && QT_CONFIG(temporaryfile)
618 // rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
619 // FS, such as FAT32. Move the file away and rename in 2 steps to work around.
620 QTemporaryFileName tfn(d->fileName);
621 QFileSystemEntry src(d->fileName);
622 QSystemError error;
623 for (int attempt = 0; attempt < 16; ++attempt) {
624 QFileSystemEntry tmp(tfn.generateNext(), QFileSystemEntry::FromNativePath());
625
626 // rename to temporary name
627 if (!QFileSystemEngine::renameFile(src, tmp, error))
628 continue;
629
630 // rename to final name
631 if (QFileSystemEngine::renameFile(tmp, QFileSystemEntry(newName), error)) {
632 d->fileEngine->setFileName(newName);
633 d->fileName = newName;
634 return true;
635 }
636
637 // We need to restore the original file.
638 QSystemError error2;
639 if (QFileSystemEngine::renameFile(tmp, src, error2))
640 break; // report the original error, below
641
642 // report both errors
643 d->setError(QFile::RenameError,
644 tr("Error while renaming: %1").arg(error.toString())
645 + u'\n'
646 + tr("Unable to restore from %1: %2").
647 arg(QDir::toNativeSeparators(tmp.filePath()), error2.toString()));
648 return false;
649 }
650 d->setError(QFile::RenameError,
651 tr("Error while renaming: %1").arg(error.toString()));
652 return false;
653#endif // Q_OS_LINUX
654 }
655 unsetError();
656 close();
657 if (error() == QFile::NoError) {
658 if (changingCase ? d->engine()->renameOverwrite(newName) : d->engine()->rename(newName)) {
659 unsetError();
660 // engine was able to handle the new name so we just reset it
661 d->fileEngine->setFileName(newName);
662 d->fileName = newName;
663 return true;
664 }
665
666 // Engine was unable to rename and the fallback will delete the original file,
667 // so we have to back out here on case-insensitive file systems:
668 if (changingCase) {
669 d->setError(QFile::RenameError, d->fileEngine->errorString());
670 return false;
671 }
672
673 if (isSequential()) {
674 d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
675 return false;
676 }
677
678#if QT_CONFIG(temporaryfile)
679 // copy the file to the destination first
680 if (d->copy(newName, permissions())) {
681 // succeeded, remove the original
682 if (!remove()) {
683 d->setError(QFile::RenameError, tr("Cannot remove source file: %1").arg(errorString()));
684 QFile out(newName);
685 // set it back to writable so we can delete it
686 out.setPermissions(ReadUser | WriteUser);
687 out.remove(newName);
688 return false;
689 }
690 d->fileEngine->setFileName(newName);
691 unsetError();
692 setFileName(newName);
693 return true;
694 } else {
695 // change the error type but keep the string
696 d->setError(QFile::RenameError, errorString());
697 }
698#else
699 // copy the error from the engine rename() above
700 d->setError(QFile::RenameError, d->fileEngine->errorString());
701#endif
702 }
703 return false;
704}
705
706/*!
707 \overload
708
709 Renames the file \a oldName to \a newName. Returns \c true if
710 successful; otherwise returns \c false.
711
712 If a file with the name \a newName already exists, rename() returns \c false
713 (i.e., QFile will not overwrite it).
714
715 \sa rename()
716*/
717
718bool
719QFile::rename(const QString &oldName, const QString &newName)
720{
721 return QFile(oldName).rename(newName);
722}
723
724/*!
725
726 Creates a link named \a linkName that points to the file currently specified by
727 fileName(). What a link is depends on the underlying filesystem (be it a
728 shortcut on Windows or a symbolic link on Unix). Returns \c true if successful;
729 otherwise returns \c false.
730
731 This function will not overwrite an already existing entity in the file system;
732 in this case, \c link() will return false and set \l{QFile::}{error()} to
733 return \l{QFile::}{RenameError}.
734
735 \note To create a valid link on Windows, \a linkName must have a \c{.lnk} file extension.
736
737 \sa setFileName()
738*/
739
740bool
741QFile::link(const QString &linkName)
742{
743 Q_D(QFile);
744 if (fileName().isEmpty()) {
745 qWarning("QFile::link: Empty or null file name");
746 return false;
747 }
748
749 // Keep engine for target alive during the operation
750 // FIXME: Involve the target engine in the operation
751 auto targetEngine = QFileSystemEngine::createLegacyEngine(linkName);
752
753 QFileInfo fi(linkName);
754 if (d->engine()->link(fi.absoluteFilePath())) {
755 unsetError();
756 return true;
757 }
758 d->setError(QFile::RenameError, d->fileEngine->errorString());
759 return false;
760}
761
762/*!
763 \overload
764
765 Creates a link named \a linkName that points to the file \a fileName. What a link is
766 depends on the underlying filesystem (be it a shortcut on Windows
767 or a symbolic link on Unix). Returns \c true if successful; otherwise
768 returns \c false.
769
770 \sa link()
771*/
772
773bool
774QFile::link(const QString &fileName, const QString &linkName)
775{
776 return QFile(fileName).link(linkName);
777}
778
779#if QT_CONFIG(temporaryfile) // dangerous without QTemporaryFile
780bool QFilePrivate::copy(const QString &newName, QFileDevice::Permissions permissions)
781{
782 Q_Q(QFile);
783 Q_ASSERT(error == QFile::NoError);
784 Q_ASSERT(!q->isOpen());
785
786 // Keep engine for target alive during the operation
787 // FIXME: Involve the target engine in the operation
788 auto targetEngine = QFileSystemEngine::createLegacyEngine(newName);
789
790 // Some file engines can perform this copy more efficiently (e.g., Windows
791 // calling CopyFile).
792 if (engine()->copy(newName))
793 return true;
794
795 if (!q->open(QFile::ReadOnly | QFile::Unbuffered)) {
796 setError(QFile::CopyError, QFile::tr("Cannot open %1 for input").arg(fileName));
797 return false;
798 }
799
800 QSaveFile out(newName);
801 out.setDirectWriteFallback(true);
802 if (!out.open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
803 q->close();
804 setError(QFile::CopyError, QFile::tr("Cannot open for output: %1").arg(out.errorString()));
805 return false;
806 }
807
808 // Attempt to do an OS-level data copy
809 QAbstractFileEngine::TriStateResult r = engine()->cloneTo(out.d_func()->engine());
810 if (r == QAbstractFileEngine::TriStateResult::Failed) {
811 q->close();
812 setError(QFile::CopyError, QFile::tr("Could not copy to %1: %2")
813 .arg(newName, engine()->errorString()));
814 return false;
815 }
816
817 while (r == QAbstractFileEngine::TriStateResult::NotSupported) {
818 // OS couldn't do it, so do a block-level copy
819 char block[4096];
820 qint64 in = q->read(block, sizeof(block));
821 if (in == 0)
822 break; // eof
823 if (in < 0) {
824 // Unable to read from the source. Save the error from read() above.
825 QString s = std::move(errorString);
826 q->close();
827 setError(QFile::CopyError, std::move(s));
828 return false;
829 }
830 if (in != out.write(block, in)) {
831 q->close();
832 setError(QFile::CopyError, QFile::tr("Failure to write block: %1")
833 .arg(out.errorString()));
834 return false;
835 }
836 }
837
838 // copy the permissions
839 out.setPermissions(permissions);
840 q->close();
841
842 // final step: commit the copy
843 if (out.commit())
844 return true;
845 setError(out.error(), out.errorString());
846 return false;
847}
848
849/*!
850 Copies the file named fileName() to \a newName.
851
852 This file is closed before it is copied.
853
854 \include qfile-copy.qdocinc
855
856 \sa setFileName()
857*/
858
859bool
860QFile::copy(const QString &newName, std::optional<QFileDevice::Permissions> perm)
861{
862 Q_D(QFile);
863 if (fileName().isEmpty()) {
864 qWarning("QFile::copy: Empty or null file name");
865 return false;
866 }
867 if (QFile::exists(newName)) {
868 // ### Race condition. If a file is moved in after this, it /will/ be
869 // overwritten. On Unix, the proper solution is to use hardlinks:
870 // return ::link(old, new) && ::remove(old); See also rename().
871 d->setError(QFile::CopyError, tr("Destination file exists"));
872 return false;
873 }
874 unsetError();
875 close();
876 if (error() == QFile::NoError)
877 return d->copy(newName, perm ? *perm : permissions());
878 return false;
879}
880
881/*!
882 \overload
883
884 Copies the file named \a fileName to \a newName.
885
886 \include qfile-copy.qdocinc
887
888 \sa rename()
889*/
890
891bool
892QFile::copy(const QString &fileName, const QString &newName,
893 std::optional<QFileDevice::Permissions> perm)
894{
895 return QFile(fileName).copy(newName, perm);
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