1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "private/qabstractfileengine_p.h"
6#include "private/qfsfileengine_p.h"
7#ifdef QT_BUILD_CORE_LIB
8#include "private/qresource_p.h"
9#endif
10#include "qdatetime.h"
11#include "qreadwritelock.h"
12#include "qvariant.h"
13// built-in handlers
14#include "qdirlisting.h"
15#include "qstringbuilder.h"
16
17#include <QtCore/private/qfilesystementry_p.h>
18#include <QtCore/private/qfilesystemmetadata_p.h>
19#include <QtCore/private/qfilesystemengine_p.h>
20
21QT_BEGIN_NAMESPACE
22
23using namespace Qt::StringLiterals;
24
25static QString appendSlashIfNeeded(const QString &path)
26{
27 if (!path.isEmpty() && !path.endsWith(c: u'/')
28#ifdef Q_OS_ANDROID
29 && !path.startsWith("content:/"_L1)
30#endif
31 )
32 return QString{path + u'/'};
33 return path;
34}
35
36QAbstractFileEnginePrivate::~QAbstractFileEnginePrivate()
37 = default;
38
39/*!
40 \class QAbstractFileEngineHandler
41 \inmodule QtCore
42 \reentrant
43 \internal
44
45 \brief The QAbstractFileEngineHandler class provides a way to register
46 custom file engines with your application.
47
48 \ingroup io
49 \since 4.1
50
51 QAbstractFileEngineHandler is a factory for creating QAbstractFileEngine
52 objects (file engines), which are used internally by QFile, QFileInfo, and
53 QDir when working with files and directories.
54
55 When you open a file, Qt chooses a suitable file engine by passing the
56 file name from QFile or QDir through an internal list of registered file
57 engine handlers. The first handler to recognize the file name is used to
58 create the engine. Qt provides internal file engines for working with
59 regular files and resources, but you can also register your own
60 QAbstractFileEngine subclasses.
61
62 To install an application-specific file engine, you subclass
63 QAbstractFileEngineHandler and reimplement create(). When you instantiate
64 the handler (e.g. by creating an instance on the stack or on the heap), it
65 will automatically register with Qt. (The latest registered handler takes
66 precedence over existing handlers.)
67
68 For example:
69
70 \snippet code/src_corelib_io_qabstractfileengine.cpp 0
71
72 When the handler is destroyed, it is automatically removed from Qt.
73
74 The most common approach to registering a handler is to create an instance
75 as part of the start-up phase of your application. It is also possible to
76 limit the scope of the file engine handler to a particular area of
77 interest (e.g. a special file dialog that needs a custom file engine). By
78 creating the handler inside a local scope, you can precisely control the
79 area in which your engine will be applied without disturbing file
80 operations in other parts of your application.
81
82 \sa QAbstractFileEngine, QAbstractFileEngine::create()
83*/
84
85Q_CONSTINIT static QBasicAtomicInt qt_file_engine_handlers_in_use = Q_BASIC_ATOMIC_INITIALIZER(false);
86
87/*
88 All application-wide handlers are stored in this list. The mutex must be
89 acquired to ensure thread safety.
90 */
91Q_GLOBAL_STATIC(QReadWriteLock, fileEngineHandlerMutex, QReadWriteLock::Recursive)
92Q_CONSTINIT static bool qt_abstractfileenginehandlerlist_shutDown = false;
93class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
94{
95 Q_DISABLE_COPY_MOVE(QAbstractFileEngineHandlerList)
96public:
97 QAbstractFileEngineHandlerList() = default;
98
99 ~QAbstractFileEngineHandlerList()
100 {
101 QWriteLocker locker(fileEngineHandlerMutex());
102 qt_abstractfileenginehandlerlist_shutDown = true;
103 }
104};
105Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
106
107/*!
108 Constructs a file handler and registers it with Qt. Once created this
109 handler's create() function will be called (along with all the other
110 handlers) for any paths used. The most recently created handler that
111 recognizes the given path (i.e. that returns a QAbstractFileEngine) is
112 used for the new path.
113
114 \sa create()
115 */
116QAbstractFileEngineHandler::QAbstractFileEngineHandler()
117{
118 QWriteLocker locker(fileEngineHandlerMutex());
119 qt_file_engine_handlers_in_use.storeRelaxed(newValue: true);
120 fileEngineHandlers()->prepend(t: this);
121}
122
123/*!
124 Destroys the file handler. This will automatically unregister the handler
125 from Qt.
126 */
127QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
128{
129 QWriteLocker locker(fileEngineHandlerMutex());
130 // Remove this handler from the handler list only if the list is valid.
131 if (!qt_abstractfileenginehandlerlist_shutDown) {
132 QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
133 handlers->removeOne(t: this);
134 if (handlers->isEmpty())
135 qt_file_engine_handlers_in_use.storeRelaxed(newValue: false);
136 }
137}
138
139/*
140 \internal
141
142 Handles calls to custom file engine handlers.
143*/
144std::unique_ptr<QAbstractFileEngine> qt_custom_file_engine_handler_create(const QString &path)
145{
146 if (qt_file_engine_handlers_in_use.loadRelaxed()) {
147 QReadLocker locker(fileEngineHandlerMutex());
148
149 // check for registered handlers that can load the file
150 for (QAbstractFileEngineHandler *handler : std::as_const(t&: *fileEngineHandlers())) {
151 if (auto engine = handler->create(fileName: path))
152 return engine;
153 }
154 }
155
156 return nullptr;
157}
158
159/*!
160 \fn std::unique_ptr<QAbstractFileEngine> QAbstractFileEngineHandler::create(const QString &fileName) const
161
162 If this file handler can handle \a fileName, this method creates a file
163 engine and returns it wrapped in a std::unique_ptr; otherwise returns
164 nullptr.
165
166 Example:
167
168 \snippet code/src_corelib_io_qabstractfileengine.cpp 1
169
170 \sa QAbstractFileEngine::create()
171*/
172
173/*!
174 Creates and returns a QAbstractFileEngine suitable for processing \a
175 fileName.
176
177 You should not need to call this function; use QFile, QFileInfo or
178 QDir directly instead.
179
180 If you reimplemnt this function, it should only return file
181 engines that knows how to handle \a fileName; otherwise, it should
182 return 0.
183
184 \sa QAbstractFileEngineHandler
185*/
186std::unique_ptr<QAbstractFileEngine> QAbstractFileEngine::create(const QString &fileName)
187{
188 QFileSystemEntry entry(fileName);
189 QFileSystemMetaData metaData;
190 auto engine = QFileSystemEngine::createLegacyEngine(entry, data&: metaData);
191
192#ifndef QT_NO_FSFILEENGINE
193 if (!engine) // fall back to regular file engine
194 engine = std::make_unique<QFSFileEngine>(args: entry.filePath());
195#endif
196
197 return engine;
198}
199
200/*!
201 \class QAbstractFileEngine
202 \inmodule QtCore
203 \reentrant
204 \internal
205
206 \brief The QAbstractFileEngine class provides an abstraction for accessing
207 the filesystem.
208
209 \ingroup io
210 \since 4.1
211
212 The QDir, QFile, and QFileInfo classes all make use of a
213 QAbstractFileEngine internally. If you create your own QAbstractFileEngine
214 subclass (and register it with Qt by creating a QAbstractFileEngineHandler
215 subclass), your file engine will be used when the path is one that your
216 file engine handles.
217
218 A QAbstractFileEngine refers to one file or one directory. If the referent
219 is a file, the setFileName(), rename(), and remove() functions are
220 applicable. If the referent is a directory the mkdir(), rmdir(), and
221 entryList() functions are applicable. In all cases the caseSensitive(),
222 isRelativePath(), fileFlags(), ownerId(), owner(), and fileTime()
223 functions are applicable.
224
225 A QAbstractFileEngine subclass can be created to do synchronous network I/O
226 based file system operations, local file system operations, or to operate
227 as a resource system to access file based resources.
228
229 \sa QAbstractFileEngineHandler
230*/
231
232/*!
233 \enum QAbstractFileEngine::FileName
234
235 These values are used to request a file name in a particular
236 format.
237
238 \value DefaultName The same filename that was passed to the
239 QAbstractFileEngine.
240 \value BaseName The name of the file excluding the path.
241 \value PathName The path to the file excluding the base name.
242 \value AbsoluteName The absolute path to the file (including
243 the base name).
244 \value AbsolutePathName The absolute path to the file (excluding
245 the base name).
246 \value AbsoluteLinkTarget The full file name of the file that this file is a
247 link to. (This will be empty if this file is not a link.)
248 \value RawLinkPath The raw link path of the file that this file is a
249 link to. (This will be empty if this file is not a link.)
250 \value CanonicalName Often very similar to AbsoluteLinkTarget. Will return the true path to the file.
251 \value CanonicalPathName Same as CanonicalName, excluding the base name.
252 \value BundleName Returns the name of the bundle implies BundleType is set.
253 \value JunctionName The full name of the directory that this NTFS junction
254 is linked to. (This will be empty if this file is not an NTFS junction.)
255
256 \omitvalue NFileNames
257
258 \sa fileName(), setFileName()
259*/
260
261/*!
262 \enum QAbstractFileEngine::FileFlag
263
264 The permissions and types of a file, suitable for OR'ing together.
265
266 \value ReadOwnerPerm The owner of the file has permission to read
267 it.
268 \value WriteOwnerPerm The owner of the file has permission to
269 write to it.
270 \value ExeOwnerPerm The owner of the file has permission to
271 execute it.
272 \value ReadUserPerm The current user has permission to read the
273 file.
274 \value WriteUserPerm The current user has permission to write to
275 the file.
276 \value ExeUserPerm The current user has permission to execute the
277 file.
278 \value ReadGroupPerm Members of the current user's group have
279 permission to read the file.
280 \value WriteGroupPerm Members of the current user's group have
281 permission to write to the file.
282 \value ExeGroupPerm Members of the current user's group have
283 permission to execute the file.
284 \value ReadOtherPerm All users have permission to read the file.
285 \value WriteOtherPerm All users have permission to write to the
286 file.
287 \value ExeOtherPerm All users have permission to execute the file.
288
289 \value LinkType The file is a link to another file (or link) in
290 the file system (i.e. not a file or directory).
291 \value FileType The file is a regular file to the file system
292 (i.e. not a link or directory)
293 \value BundleType \macos and iOS: the file is a bundle; implies DirectoryType
294 \value DirectoryType The file is a directory in the file system
295 (i.e. not a link or file).
296
297 \value HiddenFlag The file is hidden.
298 \value ExistsFlag The file actually exists in the file system.
299 \value RootFlag The file or the file pointed to is the root of the filesystem.
300 \value LocalDiskFlag The file resides on the local disk and can be passed to standard file functions.
301 \value Refresh Passing this flag will force the file engine to refresh all flags.
302
303 \omitvalue PermsMask
304 \omitvalue TypesMask
305 \omitvalue FlagsMask
306 \omitvalue FileInfoAll
307
308 \sa fileFlags(), setFileName()
309*/
310
311/*!
312 \enum QAbstractFileEngine::FileOwner
313
314 \value OwnerUser The user who owns the file.
315 \value OwnerGroup The group who owns the file.
316
317 \sa owner(), ownerId(), setFileName()
318*/
319
320/*!
321 Constructs a new QAbstractFileEngine that does not refer to any file or directory.
322
323 \sa setFileName()
324 */
325QAbstractFileEngine::QAbstractFileEngine() : d_ptr(new QAbstractFileEnginePrivate(this))
326{
327}
328
329/*!
330 \internal
331
332 Constructs a QAbstractFileEngine.
333 */
334QAbstractFileEngine::QAbstractFileEngine(QAbstractFileEnginePrivate &dd) : d_ptr(&dd)
335{
336 Q_ASSERT(d_ptr->q_ptr == this);
337}
338
339/*!
340 Destroys the QAbstractFileEngine.
341 */
342QAbstractFileEngine::~QAbstractFileEngine()
343{
344}
345
346/*!
347 \fn bool QAbstractFileEngine::open(QIODevice::OpenMode mode)
348
349 Opens the file in the specified \a mode. Returns \c true if the file
350 was successfully opened; otherwise returns \c false.
351
352 The \a mode is an OR combination of QIODevice::OpenMode and
353 QIODevice::HandlingMode values.
354
355 If the file is created as a result of this call, its permissions are
356 set according to \a permissision. Null value means an implementation-
357 specific default.
358*/
359bool QAbstractFileEngine::open(QIODevice::OpenMode openMode,
360 std::optional<QFile::Permissions> permissions)
361{
362 Q_UNUSED(openMode);
363 Q_UNUSED(permissions);
364 return false;
365}
366
367/*!
368 Closes the file, returning true if successful; otherwise returns \c false.
369
370 The default implementation always returns \c false.
371*/
372bool QAbstractFileEngine::close()
373{
374 return false;
375}
376
377/*!
378 \since 5.1
379
380 Flushes and syncs the file to disk.
381
382 Returns \c true if successful; otherwise returns \c false.
383 The default implementation always returns \c false.
384*/
385bool QAbstractFileEngine::syncToDisk()
386{
387 return false;
388}
389
390/*!
391 Flushes the open file, returning true if successful; otherwise returns
392 false.
393
394 The default implementation always returns \c false.
395*/
396bool QAbstractFileEngine::flush()
397{
398 return false;
399}
400
401/*!
402 Returns the size of the file.
403*/
404qint64 QAbstractFileEngine::size() const
405{
406 return 0;
407}
408
409/*!
410 Returns the current file position.
411
412 This is the position of the data read/write head of the file.
413*/
414qint64 QAbstractFileEngine::pos() const
415{
416 return 0;
417}
418
419/*!
420 \fn bool QAbstractFileEngine::seek(qint64 offset)
421
422 Sets the file position to the given \a offset. Returns \c true if
423 the position was successfully set; otherwise returns \c false.
424
425 The offset is from the beginning of the file, unless the
426 file is sequential.
427
428 \sa isSequential()
429*/
430bool QAbstractFileEngine::seek(qint64 pos)
431{
432 Q_UNUSED(pos);
433 return false;
434}
435
436/*!
437 Returns \c true if the file is a sequential access device; returns
438 false if the file is a direct access device.
439
440 Operations involving size() and seek(qint64) are not valid on
441 sequential devices.
442*/
443bool QAbstractFileEngine::isSequential() const
444{
445 return false;
446}
447
448/*!
449 Requests that the file is deleted from the file system. If the
450 operation succeeds return true; otherwise return false.
451
452 \sa setFileName(), rmdir()
453 */
454bool QAbstractFileEngine::remove()
455{
456 return false;
457}
458
459/*!
460 Copies the contents of this file to a file with the name \a newName.
461 Returns \c true on success; otherwise, false is returned.
462*/
463bool QAbstractFileEngine::copy(const QString &newName)
464{
465 Q_UNUSED(newName);
466 return false;
467}
468
469/*!
470 Requests that the file be renamed to \a newName in the file
471 system. If the operation succeeds return true; otherwise return
472 false.
473
474 \sa setFileName()
475 */
476bool QAbstractFileEngine::rename(const QString &newName)
477{
478 Q_UNUSED(newName);
479 return false;
480}
481
482/*!
483 \since 5.1
484
485 Requests that the file be renamed to \a newName in the file
486 system. If the new name already exists, it must be overwritten.
487 If the operation succeeds, returns \c true; otherwise returns
488 false.
489
490 \sa setFileName()
491 */
492bool QAbstractFileEngine::renameOverwrite(const QString &newName)
493{
494 Q_UNUSED(newName);
495 return false;
496}
497
498/*!
499 Creates a link from the file currently specified by fileName() to
500 \a newName. What a link is depends on the underlying filesystem
501 (be it a shortcut on Windows or a symbolic link on Unix). Returns
502 true if successful; otherwise returns \c false.
503*/
504bool QAbstractFileEngine::link(const QString &newName)
505{
506 Q_UNUSED(newName);
507 return false;
508}
509
510/*!
511 Requests that the directory \a dirName be created with the specified \a permissions.
512 If \a createParentDirectories is true, then any sub-directories in \a dirName
513 that don't exist must be created. If \a createParentDirectories is false then
514 any sub-directories in \a dirName must already exist for the function to
515 succeed. If the operation succeeds return true; otherwise return
516 false.
517
518 If \a permissions is null then implementation-specific default permissions are
519 used.
520
521 \sa setFileName(), rmdir(), isRelativePath()
522 */
523bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
524 std::optional<QFile::Permissions> permissions) const
525{
526 Q_UNUSED(dirName);
527 Q_UNUSED(createParentDirectories);
528 Q_UNUSED(permissions);
529 return false;
530}
531
532/*!
533 Requests that the directory \a dirName is deleted from the file
534 system. When \a recurseParentDirectories is true, then any empty
535 parent-directories in \a dirName must also be deleted. If
536 \a recurseParentDirectories is false, only the \a dirName leaf-node
537 should be deleted. In most file systems a directory cannot be deleted
538 using this function if it is non-empty. If the operation succeeds
539 return true; otherwise return false.
540
541 \sa setFileName(), remove(), mkdir(), isRelativePath()
542 */
543bool QAbstractFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
544{
545 Q_UNUSED(dirName);
546 Q_UNUSED(recurseParentDirectories);
547 return false;
548}
549
550/*!
551 Requests that the file be set to size \a size. If \a size is larger
552 than the current file then it is filled with 0's, if smaller it is
553 simply truncated. If the operations succceeds return true; otherwise
554 return false;
555
556 \sa size()
557*/
558bool QAbstractFileEngine::setSize(qint64 size)
559{
560 Q_UNUSED(size);
561 return false;
562}
563
564/*!
565 Should return true if the underlying file system is case-sensitive;
566 otherwise return false.
567 */
568bool QAbstractFileEngine::caseSensitive() const
569{
570 return false;
571}
572
573/*!
574 Return true if the file referred to by this file engine has a
575 relative path; otherwise return false.
576
577 \sa setFileName()
578 */
579bool QAbstractFileEngine::isRelativePath() const
580{
581 return false;
582}
583
584/*!
585 Requests that a list of all the files matching the \a filters
586 list based on the \a filterNames in the file engine's directory
587 are returned.
588
589 Should return an empty list if the file engine refers to a file
590 rather than a directory, or if the directory is unreadable or does
591 not exist or if nothing matches the specifications.
592
593 \sa setFileName()
594 */
595QStringList QAbstractFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
596{
597 QStringList ret;
598#ifdef QT_BOOTSTRAPPED
599 Q_UNUSED(filters);
600 Q_UNUSED(filterNames);
601 Q_UNREACHABLE_RETURN(ret);
602#else
603 for (const auto &dirEntry : QDirListing(fileName(), filterNames, filters.toInt()))
604 ret.emplace_back(args: dirEntry.fileName());
605 return ret;
606#endif
607}
608
609QStringList QAbstractFileEngine::entryList(QDirListing::IteratorFlags filters,
610 const QStringList &filterNames) const
611{
612 QStringList ret;
613#ifdef QT_BOOTSTRAPPED
614 Q_UNUSED(filters);
615 Q_UNUSED(filterNames);
616 Q_UNREACHABLE_RETURN(ret);
617#else
618 for (const auto &dirEntry : QDirListing(fileName(), filterNames, filters))
619 ret.emplace_back(args: dirEntry.fileName());
620 return ret;
621#endif
622}
623
624/*!
625 This function should return the set of OR'd flags that are true
626 for the file engine's file, and that are in the \a type's OR'd
627 members.
628
629 In your reimplementation you can use the \a type argument as an
630 optimization hint and only return the OR'd set of members that are
631 true and that match those in \a type; in other words you can
632 ignore any members not mentioned in \a type, thus avoiding some
633 potentially expensive lookups or system calls.
634
635 \sa setFileName()
636*/
637QAbstractFileEngine::FileFlags QAbstractFileEngine::fileFlags(FileFlags type) const
638{
639 Q_UNUSED(type);
640 return {};
641}
642
643/*!
644 Requests that the file's permissions be set to \a perms. The argument
645 perms will be set to the OR-ed together combination of
646 QAbstractFileEngine::FileInfo, with only the QAbstractFileEngine::PermsMask being
647 honored. If the operations succceeds return true; otherwise return
648 false;
649
650 \sa size()
651*/
652bool QAbstractFileEngine::setPermissions(uint perms)
653{
654 Q_UNUSED(perms);
655 return false;
656}
657
658/*!
659 \since 5.9
660
661 Return an identifier that (hopefully) uniquely identifies this file in the
662 system. Returns an invalid QByteArray() if that cannot be calculated.
663*/
664QByteArray QAbstractFileEngine::id() const
665{
666 return QByteArray();
667}
668
669/*!
670 Return the file engine's current file name in the format
671 specified by \a file.
672
673 If you don't handle some \c FileName possibilities, return the
674 file name set in setFileName() when an unhandled format is
675 requested.
676
677 \sa setFileName(), FileName
678 */
679QString QAbstractFileEngine::fileName(FileName file) const
680{
681 Q_UNUSED(file);
682 return QString();
683}
684
685/*!
686 If \a owner is \c OwnerUser return the ID of the user who owns
687 the file. If \a owner is \c OwnerGroup return the ID of the group
688 that own the file. If you can't determine the owner return -2.
689
690 \sa owner(), setFileName(), FileOwner
691 */
692uint QAbstractFileEngine::ownerId(FileOwner owner) const
693{
694 Q_UNUSED(owner);
695 return 0;
696}
697
698/*!
699 If \a owner is \c OwnerUser return the name of the user who owns
700 the file. If \a owner is \c OwnerGroup return the name of the group
701 that own the file. If you can't determine the owner return
702 QString().
703
704 \sa ownerId(), setFileName(), FileOwner
705 */
706QString QAbstractFileEngine::owner(FileOwner owner) const
707{
708 Q_UNUSED(owner);
709 return QString();
710}
711
712
713/*!
714 \since 5.10
715
716 Sets the file \a time to \a newDate, returning true if successful;
717 otherwise returns false.
718
719 \sa fileTime()
720*/
721bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
722{
723 Q_UNUSED(newDate);
724 Q_UNUSED(time);
725 return false;
726}
727
728/*!
729 If \a time is \c BirthTime, return when the file was born (created). If \a
730 time is \c MetadataChangeTime, return when the file's metadata was last
731 changed. If \a time is \c ModificationTime, return when the file was most
732 recently modified. If \a time is \c AccessTime, return when the file was
733 most recently accessed (e.g. read or written). If the time cannot be
734 determined return QDateTime() (an invalid date time).
735
736 \sa setFileName(), QDateTime, QDateTime::isValid(), FileTime
737 */
738QDateTime QAbstractFileEngine::fileTime(QFile::FileTime time) const
739{
740 Q_UNUSED(time);
741 return QDateTime();
742}
743
744/*!
745 Sets the file engine's file name to \a file. This file name is the
746 file that the rest of the virtual functions will operate on.
747
748 \sa rename()
749 */
750void QAbstractFileEngine::setFileName(const QString &file)
751{
752 Q_UNUSED(file);
753}
754
755/*!
756 Returns the native file handle for this file engine. This handle must be
757 used with care; its value and type are platform specific, and using it
758 will most likely lead to non-portable code.
759*/
760int QAbstractFileEngine::handle() const
761{
762 return -1;
763}
764
765/*!
766 \since 4.3
767
768 Returns \c true if the current position is at the end of the file; otherwise,
769 returns \c false.
770
771 This function bases its behavior on calling extension() with
772 AtEndExtension. If the engine does not support this extension, false is
773 returned.
774
775 \sa extension(), supportsExtension(), QFile::atEnd()
776*/
777bool QAbstractFileEngine::atEnd() const
778{
779 return const_cast<QAbstractFileEngine *>(this)->extension(extension: AtEndExtension);
780}
781
782/*!
783 \since 4.4
784
785 Maps \a size bytes of the file into memory starting at \a offset.
786 Returns a pointer to the memory if successful; otherwise returns \c false
787 if, for example, an error occurs.
788
789 This function bases its behavior on calling extension() with
790 MapExtensionOption. If the engine does not support this extension, 0 is
791 returned.
792
793 \a flags is currently not used, but could be used in the future.
794
795 \sa unmap(), supportsExtension()
796 */
797
798uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
799{
800 const MapExtensionOption option(offset, size, flags);
801 MapExtensionReturn r;
802 if (!extension(extension: MapExtension, option: &option, output: &r))
803 return nullptr;
804 return r.address;
805}
806
807/*!
808 \since 4.4
809
810 Unmaps the memory \a address. Returns \c true if the unmap succeeds; otherwise
811 returns \c false.
812
813 This function bases its behavior on calling extension() with
814 UnMapExtensionOption. If the engine does not support this extension, false is
815 returned.
816
817 \sa map(), supportsExtension()
818 */
819bool QAbstractFileEngine::unmap(uchar *address)
820{
821 const UnMapExtensionOption options(address);
822 return extension(extension: UnMapExtension, option: &options);
823}
824
825/*!
826 \since 5.10
827
828 Duplicates the contents of this file (starting from the current position)
829 to the file specified by the engine \a target.
830
831 Returns \c true on success; otherwise, \c false is returned.
832 */
833QAbstractFileEngine::TriStateResult QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
834{
835 Q_UNUSED(target);
836 return TriStateResult::NotSupported;
837}
838
839/*!
840 \since 4.3
841 \class QAbstractFileEngineIterator
842 \inmodule QtCore
843 \brief The QAbstractFileEngineIterator class provides an iterator
844 interface for custom file engines.
845 \internal
846
847 If all you want is to iterate over entries in a directory, see
848 QDirListing instead. This class is useful only for custom file engine
849 authors.
850
851 QAbstractFileEngineIterator is a unidirectional single-use virtual
852 iterator that plugs into QDirListing, providing transparent proxy
853 iteration for custom file engines (for example, QResourceFileEngine).
854
855 You can subclass QAbstractFileEngineIterator to provide an iterator when
856 writing your own file engine. To plug the iterator into your file system,
857 you simply return an instance of this subclass from a reimplementation of
858 QAbstractFileEngine::beginEntryList().
859
860 Example:
861
862 \snippet code/src_corelib_io_qabstractfileengine.cpp 2
863
864 QAbstractFileEngineIterator is associated with a path, name filters, and
865 entry filters. The path is the directory that the iterator lists entries
866 in. The name filters and entry filters are provided for file engines that
867 can optimize directory listing at the iterator level (e.g., network file
868 systems that need to minimize network traffic), but they can also be
869 ignored by the iterator subclass; QAbstractFileEngineIterator already
870 provides the required filtering logics in the matchesFilters() function.
871 You can call dirName() to get the directory name, nameFilters() to get a
872 stringlist of name filters, and filters() to get the entry filters.
873
874 The pure virtual function advance(), as its name implies, advances the
875 iterator to the next entry in the current directory; if the operation
876 was successful this method returns \c true, otherwise it returns \c
877 false. You have to reimplement this function in your sub-class to work
878 with your file engine implementation.
879
880 The pure virtual function currentFileName() returns the name of the
881 current entry without advancing the iterator. The currentFilePath()
882 function is provided for convenience; it returns the full path of the
883 current entry.
884
885 Here is an example of how to implement an iterator that returns each of
886 three fixed entries in sequence.
887
888 \snippet code/src_corelib_io_qabstractfileengine.cpp 3
889
890 Note: QAbstractFileEngineIterator does not deal with QDir::IteratorFlags;
891 it simply returns entries for a single directory.
892
893 \sa QDirListing
894*/
895
896/*!
897 \typedef QAbstractFileEngine::Iterator
898 \since 4.3
899
900 Synonym for QAbstractFileEngineIterator.
901*/
902
903/*!
904 \typedef QAbstractFileEngine::IteratorUniquePtr
905 \since 6.8
906
907 Synonym for std::unique_ptr<Iterator> (that is a
908 std::unique_ptr<QAbstractFileEngineIterator>).
909*/
910
911/*!
912 Constructs a QAbstractFileEngineIterator, using the entry filters \a
913 filters, and wildcard name filters \a nameFilters.
914*/
915QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path, QDir::Filters filters,
916 const QStringList &nameFilters)
917 : m_filters(filters),
918 m_nameFilters(nameFilters),
919 m_path(appendSlashIfNeeded(path))
920{
921}
922
923QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path,
924 QDirListing::IteratorFlags filters,
925 const QStringList &nameFilters)
926 : m_listingFilters(filters),
927 m_nameFilters(nameFilters),
928 m_path(appendSlashIfNeeded(path))
929{
930}
931
932/*!
933 Destroys the QAbstractFileEngineIterator.
934
935 \sa QDirListing
936*/
937QAbstractFileEngineIterator::~QAbstractFileEngineIterator()
938{
939}
940
941/*!
942
943 Returns the path for this iterator. The path is set by beginEntryList().
944 The path should't be changed once iteration begins.
945
946 \sa nameFilters(), filters()
947*/
948QString QAbstractFileEngineIterator::path() const
949{
950 return m_path;
951}
952
953/*!
954 Returns the name filters for this iterator.
955
956 \sa QDir::nameFilters(), filters(), path()
957*/
958QStringList QAbstractFileEngineIterator::nameFilters() const
959{
960 return m_nameFilters;
961}
962
963/*!
964 Returns the entry filters for this iterator.
965
966 \sa QDir::filter(), nameFilters(), path()
967*/
968QDir::Filters QAbstractFileEngineIterator::filters() const
969{
970 return m_filters;
971}
972
973/*!
974 \fn QString QAbstractFileEngineIterator::currentFileName() const = 0
975
976 This pure virtual function returns the name of the current directory
977 entry, excluding the path.
978
979 \sa currentFilePath()
980*/
981
982/*!
983 Returns the path to the current directory entry. It's the same as
984 prepending path() to the return value of currentFileName().
985
986 \sa currentFileName()
987*/
988QString QAbstractFileEngineIterator::currentFilePath() const
989{
990 QString name = currentFileName();
991 if (name.isNull())
992 return name;
993
994 return path() + name;
995}
996
997/*!
998 The virtual function returns a QFileInfo for the current directory
999 entry. This function is provided for convenience. It can also be slightly
1000 faster than creating a QFileInfo object yourself, as the object returned
1001 by this function might contain cached information that QFileInfo otherwise
1002 would have to access through the file engine.
1003
1004 \sa currentFileName()
1005*/
1006QFileInfo QAbstractFileEngineIterator::currentFileInfo() const
1007{
1008 QString path = currentFilePath();
1009 if (m_fileInfo.filePath() != path)
1010 m_fileInfo.setFile(path);
1011
1012 // return a shallow copy
1013 return m_fileInfo;
1014}
1015
1016/*!
1017 \fn virtual bool QAbstractFileEngineIterator::advance() = 0
1018
1019 This pure virtual function advances the iterator to the next directory
1020 entry; if the operation was successful this method returns \c true,
1021 otherwise it returs \c false.
1022
1023 This function can optionally make use of nameFilters() and filters() to
1024 optimize its performance.
1025
1026 Reimplement this function in a subclass to advance the iterator.
1027*/
1028
1029/*!
1030 Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used
1031 to iterate over the entries in \a path, using \a filters for entry
1032 filtering and \a filterNames for name filtering. This function is called
1033 by QDirListing to initiate directory iteration.
1034
1035 \sa QDirListing
1036*/
1037QAbstractFileEngine::IteratorUniquePtr
1038QAbstractFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
1039 const QStringList &filterNames)
1040{
1041 Q_UNUSED(path);
1042 Q_UNUSED(filters);
1043 Q_UNUSED(filterNames);
1044 return {};
1045}
1046
1047/*!
1048 Reads a number of characters from the file into \a data. At most
1049 \a maxlen characters will be read.
1050
1051 Returns -1 if a fatal error occurs, or 0 if there are no bytes to
1052 read.
1053*/
1054qint64 QAbstractFileEngine::read(char *data, qint64 maxlen)
1055{
1056 Q_UNUSED(data);
1057 Q_UNUSED(maxlen);
1058 return -1;
1059}
1060
1061/*!
1062 Writes \a len bytes from \a data to the file. Returns the number
1063 of characters written on success; otherwise returns -1.
1064*/
1065qint64 QAbstractFileEngine::write(const char *data, qint64 len)
1066{
1067 Q_UNUSED(data);
1068 Q_UNUSED(len);
1069 return -1;
1070}
1071
1072/*!
1073 This function reads one line, terminated by a '\\n' character, from the
1074 file info \a data. At most \a maxlen characters will be read. The
1075 end-of-line character is included.
1076*/
1077qint64 QAbstractFileEngine::readLine(char *data, qint64 maxlen)
1078{
1079 qint64 readSoFar = 0;
1080 while (readSoFar < maxlen) {
1081 char c;
1082 qint64 readResult = read(data: &c, maxlen: 1);
1083 if (readResult <= 0)
1084 return (readSoFar > 0) ? readSoFar : -1;
1085 ++readSoFar;
1086 *data++ = c;
1087 if (c == '\n')
1088 return readSoFar;
1089 }
1090 return readSoFar;
1091}
1092
1093/*!
1094 \enum QAbstractFileEngine::Extension
1095 \since 4.3
1096
1097 This enum describes the types of extensions that the file engine can
1098 support. Before using these extensions, you must verify that the extension
1099 is supported (i.e., call supportsExtension()).
1100
1101 \value AtEndExtension Whether the current file position is at the end of
1102 the file or not. This extension allows file engines that implement local
1103 buffering to report end-of-file status without having to check the size of
1104 the file. It is also useful for sequential files, where the size of the
1105 file cannot be used to determine whether or not you have reached the end.
1106 This extension returns \c true if the file is at the end; otherwise it returns
1107 false. The input and output arguments to extension() are ignored.
1108
1109 \value FastReadLineExtension Whether the file engine provides a
1110 fast implementation for readLine() or not. If readLine() remains
1111 unimplemented in the file engine, QAbstractFileEngine will provide
1112 an implementation based on calling read() repeatedly. If
1113 supportsExtension() returns \c false for this extension, however,
1114 QIODevice can provide a faster implementation by making use of its
1115 internal buffer. For engines that already provide a fast readLine()
1116 implementation, returning false for this extension can avoid
1117 unnecessary double-buffering in QIODevice.
1118
1119 \value MapExtension Whether the file engine provides the ability to map
1120 a file to memory.
1121
1122 \value UnMapExtension Whether the file engine provides the ability to
1123 unmap memory that was previously mapped.
1124*/
1125
1126/*!
1127 \class QAbstractFileEngine::ExtensionOption
1128 \inmodule QtCore
1129 \since 4.3
1130 \brief provides an extended input argument to QAbstractFileEngine's
1131 extension support.
1132
1133 \sa QAbstractFileEngine::extension()
1134*/
1135
1136/*!
1137 \class QAbstractFileEngine::ExtensionReturn
1138 \inmodule QtCore
1139 \since 4.3
1140 \brief provides an extended output argument to QAbstractFileEngine's
1141 extension support.
1142
1143 \sa QAbstractFileEngine::extension()
1144*/
1145
1146/*!
1147 \since 4.3
1148
1149 This virtual function can be reimplemented in a QAbstractFileEngine
1150 subclass to provide support for extensions. The \a option argument is
1151 provided as input to the extension, and this function can store output
1152 results in \a output.
1153
1154 The behavior of this function is determined by \a extension; see the
1155 Extension documentation for details.
1156
1157 You can call supportsExtension() to check if an extension is supported by
1158 the file engine.
1159
1160 By default, no extensions are supported, and this function returns \c false.
1161
1162 \sa supportsExtension(), Extension
1163*/
1164bool QAbstractFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
1165{
1166 Q_UNUSED(extension);
1167 Q_UNUSED(option);
1168 Q_UNUSED(output);
1169 return false;
1170}
1171
1172/*!
1173 \since 4.3
1174
1175 This virtual function returns \c true if the file engine supports \a
1176 extension; otherwise, false is returned. By default, no extensions are
1177 supported.
1178
1179 \sa extension()
1180*/
1181bool QAbstractFileEngine::supportsExtension(Extension extension) const
1182{
1183 Q_UNUSED(extension);
1184 return false;
1185}
1186
1187/*!
1188 Returns the QFile::FileError that resulted from the last failed
1189 operation. If QFile::UnspecifiedError is returned, QFile will
1190 use its own idea of the error status.
1191
1192 \sa QFile::FileError, errorString()
1193 */
1194QFile::FileError QAbstractFileEngine::error() const
1195{
1196 Q_D(const QAbstractFileEngine);
1197 return d->fileError;
1198}
1199
1200/*!
1201 Returns the human-readable message appropriate to the current error
1202 reported by error(). If no suitable string is available, an
1203 empty string is returned.
1204
1205 \sa error()
1206 */
1207QString QAbstractFileEngine::errorString() const
1208{
1209 Q_D(const QAbstractFileEngine);
1210 return d->errorString;
1211}
1212
1213/*!
1214 Sets the error type to \a error, and the error string to \a errorString.
1215 Call this function to set the error values returned by the higher-level
1216 classes.
1217
1218 \sa QFile::error(), QIODevice::errorString(), QIODevice::setErrorString()
1219*/
1220void QAbstractFileEngine::setError(QFile::FileError error, const QString &errorString)
1221{
1222 Q_D(QAbstractFileEngine);
1223 d->fileError = error;
1224 d->errorString = errorString;
1225}
1226
1227QT_END_NAMESPACE
1228

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