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
4#include "private/qabstractfileengine_p.h"
5#include "private/qfsfileengine_p.h"
6#ifdef QT_BUILD_CORE_LIB
7#include "private/qresource_p.h"
8#endif
9#include "qdatetime.h"
10#include "qreadwritelock.h"
11#include "qvariant.h"
12// built-in handlers
13#include "qdirlisting.h"
14#include "qstringbuilder.h"
15
16#include <QtCore/private/qfilesystementry_p.h>
17#include <QtCore/private/qfilesystemmetadata_p.h>
18#include <QtCore/private/qfilesystemengine_p.h>
19
20QT_BEGIN_NAMESPACE
21
22using namespace Qt::StringLiterals;
23
24static QString appendSlashIfNeeded(const QString &path)
25{
26 if (!path.isEmpty() && !path.endsWith(c: u'/')
27#ifdef Q_OS_ANDROID
28 && !path.startsWith("content:/"_L1)
29#endif
30 )
31 return QString{path + u'/'};
32 return path;
33}
34
35QAbstractFileEnginePrivate::~QAbstractFileEnginePrivate()
36 = default;
37
38/*!
39 \class QAbstractFileEngineHandler
40 \inmodule QtCore
41 \reentrant
42 \internal
43
44 \brief The QAbstractFileEngineHandler class provides a way to register
45 custom file engines with your application.
46
47 \ingroup io
48 \since 4.1
49
50 QAbstractFileEngineHandler is a factory for creating QAbstractFileEngine
51 objects (file engines), which are used internally by QFile, QFileInfo, and
52 QDir when working with files and directories.
53
54 When you open a file, Qt chooses a suitable file engine by passing the
55 file name from QFile or QDir through an internal list of registered file
56 engine handlers. The first handler to recognize the file name is used to
57 create the engine. Qt provides internal file engines for working with
58 regular files and resources, but you can also register your own
59 QAbstractFileEngine subclasses.
60
61 To install an application-specific file engine, you subclass
62 QAbstractFileEngineHandler and reimplement create(). When you instantiate
63 the handler (e.g. by creating an instance on the stack or on the heap), it
64 will automatically register with Qt. (The latest registered handler takes
65 precedence over existing handlers.)
66
67 For example:
68
69 \snippet code/src_corelib_io_qabstractfileengine.cpp 0
70
71 When the handler is destroyed, it is automatically removed from Qt.
72
73 The most common approach to registering a handler is to create an instance
74 as part of the start-up phase of your application. It is also possible to
75 limit the scope of the file engine handler to a particular area of
76 interest (e.g. a special file dialog that needs a custom file engine). By
77 creating the handler inside a local scope, you can precisely control the
78 area in which your engine will be applied without disturbing file
79 operations in other parts of your application.
80
81 \sa QAbstractFileEngine, QAbstractFileEngine::create()
82*/
83
84Q_CONSTINIT static QBasicAtomicInt qt_file_engine_handlers_in_use = Q_BASIC_ATOMIC_INITIALIZER(false);
85
86/*
87 All application-wide handlers are stored in this list. The mutex must be
88 acquired to ensure thread safety.
89 */
90Q_GLOBAL_STATIC(QReadWriteLock, fileEngineHandlerMutex, QReadWriteLock::Recursive)
91Q_CONSTINIT static bool qt_abstractfileenginehandlerlist_shutDown = false;
92class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
93{
94 Q_DISABLE_COPY_MOVE(QAbstractFileEngineHandlerList)
95public:
96 QAbstractFileEngineHandlerList() = default;
97
98 ~QAbstractFileEngineHandlerList()
99 {
100 QWriteLocker locker(fileEngineHandlerMutex());
101 qt_abstractfileenginehandlerlist_shutDown = true;
102 }
103};
104Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
105
106/*!
107 Constructs a file handler and registers it with Qt. Once created this
108 handler's create() function will be called (along with all the other
109 handlers) for any paths used. The most recently created handler that
110 recognizes the given path (i.e. that returns a QAbstractFileEngine) is
111 used for the new path.
112
113 \sa create()
114 */
115QAbstractFileEngineHandler::QAbstractFileEngineHandler()
116{
117 QWriteLocker locker(fileEngineHandlerMutex());
118 qt_file_engine_handlers_in_use.storeRelaxed(newValue: true);
119 fileEngineHandlers()->prepend(t: this);
120}
121
122/*!
123 Destroys the file handler. This will automatically unregister the handler
124 from Qt.
125 */
126QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
127{
128 QWriteLocker locker(fileEngineHandlerMutex());
129 // Remove this handler from the handler list only if the list is valid.
130 if (!qt_abstractfileenginehandlerlist_shutDown) {
131 QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
132 handlers->removeOne(t: this);
133 if (handlers->isEmpty())
134 qt_file_engine_handlers_in_use.storeRelaxed(newValue: false);
135 }
136}
137
138/*
139 \internal
140
141 Handles calls to custom file engine handlers.
142*/
143std::unique_ptr<QAbstractFileEngine> qt_custom_file_engine_handler_create(const QString &path)
144{
145 if (qt_file_engine_handlers_in_use.loadRelaxed()) {
146 QReadLocker locker(fileEngineHandlerMutex());
147
148 // check for registered handlers that can load the file
149 for (QAbstractFileEngineHandler *handler : std::as_const(t&: *fileEngineHandlers())) {
150 if (auto engine = handler->create(fileName: path))
151 return engine;
152 }
153 }
154
155 return nullptr;
156}
157
158/*!
159 \fn std::unique_ptr<QAbstractFileEngine> QAbstractFileEngineHandler::create(const QString &fileName) const
160
161 If this file handler can handle \a fileName, this method creates a file
162 engine and returns it wrapped in a std::unique_ptr; otherwise returns
163 nullptr.
164
165 Example:
166
167 \snippet code/src_corelib_io_qabstractfileengine.cpp 1
168
169 \sa QAbstractFileEngine::create()
170*/
171
172/*!
173 Creates and returns a QAbstractFileEngine suitable for processing \a
174 fileName.
175
176 You should not need to call this function; use QFile, QFileInfo or
177 QDir directly instead.
178
179 If you reimplemnt this function, it should only return file
180 engines that knows how to handle \a fileName; otherwise, it should
181 return 0.
182
183 \sa QAbstractFileEngineHandler
184*/
185std::unique_ptr<QAbstractFileEngine> QAbstractFileEngine::create(const QString &fileName)
186{
187 QFileSystemEntry entry(fileName);
188 QFileSystemMetaData metaData;
189 auto engine = QFileSystemEngine::createLegacyEngine(entry, data&: metaData);
190
191#ifndef QT_NO_FSFILEENGINE
192 if (!engine) // fall back to regular file engine
193 engine = std::make_unique<QFSFileEngine>(args: entry.filePath());
194#endif
195
196 return engine;
197}
198
199/*!
200 \class QAbstractFileEngine
201 \inmodule QtCore
202 \reentrant
203 \internal
204
205 \brief The QAbstractFileEngine class provides an abstraction for accessing
206 the filesystem.
207
208 \ingroup io
209 \since 4.1
210
211 The QDir, QFile, and QFileInfo classes all make use of a
212 QAbstractFileEngine internally. If you create your own QAbstractFileEngine
213 subclass (and register it with Qt by creating a QAbstractFileEngineHandler
214 subclass), your file engine will be used when the path is one that your
215 file engine handles.
216
217 A QAbstractFileEngine refers to one file or one directory. If the referent
218 is a file, the setFileName(), rename(), and remove() functions are
219 applicable. If the referent is a directory the mkdir(), rmdir(), and
220 entryList() functions are applicable. In all cases the caseSensitive(),
221 isRelativePath(), fileFlags(), ownerId(), owner(), and fileTime()
222 functions are applicable.
223
224 A QAbstractFileEngine subclass can be created to do synchronous network I/O
225 based file system operations, local file system operations, or to operate
226 as a resource system to access file based resources.
227
228 \sa QAbstractFileEngineHandler
229*/
230
231/*!
232 \enum QAbstractFileEngine::FileName
233
234 These values are used to request a file name in a particular
235 format.
236
237 \value DefaultName The same filename that was passed to the
238 QAbstractFileEngine.
239 \value BaseName The name of the file excluding the path.
240 \value PathName The path to the file excluding the base name.
241 \value AbsoluteName The absolute path to the file (including
242 the base name).
243 \value AbsolutePathName The absolute path to the file (excluding
244 the base name).
245 \value AbsoluteLinkTarget The full file name of the file that this file is a
246 link to. (This will be empty if this file is not a link.)
247 \value RawLinkPath The raw link path of the file that this file is a
248 link to. (This will be empty if this file is not a link.)
249 \value CanonicalName Often very similar to AbsoluteLinkTarget. Will return the true path to the file.
250 \value CanonicalPathName Same as CanonicalName, excluding the base name.
251 \value BundleName Returns the name of the bundle implies BundleType is set.
252 \value JunctionName The full name of the directory that this NTFS junction
253 is linked to. (This will be empty if this file is not an NTFS junction.)
254
255 \omitvalue NFileNames
256
257 \sa fileName(), setFileName()
258*/
259
260/*!
261 \enum QAbstractFileEngine::FileFlag
262
263 The permissions and types of a file, suitable for OR'ing together.
264
265 \value ReadOwnerPerm The owner of the file has permission to read
266 it.
267 \value WriteOwnerPerm The owner of the file has permission to
268 write to it.
269 \value ExeOwnerPerm The owner of the file has permission to
270 execute it.
271 \value ReadUserPerm The current user has permission to read the
272 file.
273 \value WriteUserPerm The current user has permission to write to
274 the file.
275 \value ExeUserPerm The current user has permission to execute the
276 file.
277 \value ReadGroupPerm Members of the current user's group have
278 permission to read the file.
279 \value WriteGroupPerm Members of the current user's group have
280 permission to write to the file.
281 \value ExeGroupPerm Members of the current user's group have
282 permission to execute the file.
283 \value ReadOtherPerm All users have permission to read the file.
284 \value WriteOtherPerm All users have permission to write to the
285 file.
286 \value ExeOtherPerm All users have permission to execute the file.
287
288 \value LinkType The file is a link to another file (or link) in
289 the file system (i.e. not a file or directory).
290 \value FileType The file is a regular file to the file system
291 (i.e. not a link or directory)
292 \value BundleType \macos and iOS: the file is a bundle; implies DirectoryType
293 \value DirectoryType The file is a directory in the file system
294 (i.e. not a link or file).
295
296 \value HiddenFlag The file is hidden.
297 \value ExistsFlag The file actually exists in the file system.
298 \value RootFlag The file or the file pointed to is the root of the filesystem.
299 \value LocalDiskFlag The file resides on the local disk and can be passed to standard file functions.
300 \value Refresh Passing this flag will force the file engine to refresh all flags.
301
302 \omitvalue PermsMask
303 \omitvalue TypesMask
304 \omitvalue FlagsMask
305 \omitvalue FileInfoAll
306
307 \sa fileFlags(), setFileName()
308*/
309
310/*!
311 \enum QAbstractFileEngine::FileOwner
312
313 \value OwnerUser The user who owns the file.
314 \value OwnerGroup The group who owns the file.
315
316 \sa owner(), ownerId(), setFileName()
317*/
318
319/*!
320 Constructs a new QAbstractFileEngine that does not refer to any file or directory.
321
322 \sa setFileName()
323 */
324QAbstractFileEngine::QAbstractFileEngine() : d_ptr(new QAbstractFileEnginePrivate)
325{
326 d_ptr->q_ptr = this;
327}
328
329/*!
330 \internal
331
332 Constructs a QAbstractFileEngine.
333 */
334QAbstractFileEngine::QAbstractFileEngine(QAbstractFileEnginePrivate &dd) : d_ptr(&dd)
335{
336 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 */
833bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
834{
835 Q_UNUSED(target);
836 return false;
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