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

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