source: trunk/src/corelib/io/qfsfileengine.cpp@ 73

Last change on this file since 73 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 22.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qfsfileengine_p.h"
43#include "qfsfileengine_iterator_p.h"
44#include "qdatetime.h"
45#include "qdiriterator.h"
46#include "qset.h"
47
48#ifndef QT_NO_FSFILEENGINE
49
50#if !defined(Q_OS_WINCE)
51#include <errno.h>
52#endif
53#include <stdio.h>
54
55QT_BEGIN_NAMESPACE
56
57#ifdef Q_OS_WIN
58# ifndef S_ISREG
59# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
60# endif
61# ifndef S_ISCHR
62# define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
63# endif
64# ifndef S_ISFIFO
65# define S_ISFIFO(x) false
66# endif
67# ifndef S_ISSOCK
68# define S_ISSOCK(x) false
69# endif
70# ifndef INVALID_FILE_ATTRIBUTES
71# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
72# endif
73#endif
74
75
76/*! \class QFSFileEngine
77 \brief The QFSFileEngine class implements Qt's default file engine.
78 \since 4.1
79
80 This class is part of the file engine framework in Qt. If you only want to
81 access files or directories, use QFile, QFileInfo or QDir instead.
82
83 QFSFileEngine is the default file engine for accessing regular files. It
84 is provided for convenience; by subclassing this class, you can alter its
85 behavior slightly, without having to write a complete QAbstractFileEngine
86 subclass. To install your custom file engine, you must also subclass
87 QAbstractFileEngineHandler and create an instance of your handler.
88
89 It can also be useful to create a QFSFileEngine object directly if you
90 need to use the local file system inside QAbstractFileEngine::create(), in
91 order to avoid recursion (as higher-level classes tend to call
92 QAbstractFileEngine::create()).
93*/
94
95//**************** QFSFileEnginePrivate
96QFSFileEnginePrivate::QFSFileEnginePrivate() : QAbstractFileEnginePrivate()
97{
98 init();
99}
100
101/*!
102 \internal
103*/
104void QFSFileEnginePrivate::init()
105{
106 is_sequential = 0;
107 tried_stat = 0;
108#ifdef Q_OS_UNIX
109 need_lstat = 1;
110 is_link = 0;
111#endif
112 openMode = QIODevice::NotOpen;
113 fd = -1;
114 fh = 0;
115 lastIOCommand = IOFlushCommand;
116 lastFlushFailed = false;
117 closeFileHandle = false;
118#ifdef Q_OS_WIN
119 fileAttrib = INVALID_FILE_ATTRIBUTES;
120 fileHandle = INVALID_HANDLE_VALUE;
121 cachedFd = -1;
122#endif
123#ifdef Q_USE_DEPRECATED_MAP_API
124 fileMapHandle = INVALID_HANDLE_VALUE;
125#endif
126}
127
128/*!
129 \internal
130
131 Returns the canonicalized form of \a path (i.e., with all symlinks
132 resolved, and all redundant path elements removed.
133*/
134QString QFSFileEnginePrivate::canonicalized(const QString &path)
135{
136 if (path.isEmpty())
137 return path;
138
139 QFileInfo fi;
140 const QChar slash(QLatin1Char('/'));
141 QString tmpPath = path;
142 int separatorPos = 0;
143 QSet<QString> nonSymlinks;
144 QSet<QString> known;
145
146 known.insert(path);
147 do {
148#ifdef Q_OS_WIN
149 // UNC, skip past the first two elements
150 if (separatorPos == 0 && tmpPath.startsWith(QLatin1String("//")))
151 separatorPos = tmpPath.indexOf(slash, 2);
152 if (separatorPos != -1)
153#endif
154 separatorPos = tmpPath.indexOf(slash, separatorPos + 1);
155 QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos);
156 if (!nonSymlinks.contains(prefix)) {
157 fi.setFile(prefix);
158 if (fi.isSymLink()) {
159 QString target = fi.symLinkTarget();
160 if (separatorPos != -1) {
161 if (fi.isDir() && !target.endsWith(slash))
162 target.append(slash);
163 target.append(tmpPath.mid(separatorPos));
164 }
165 tmpPath = QDir::cleanPath(target);
166 separatorPos = 0;
167
168 if (known.contains(tmpPath))
169 return QString();
170 known.insert(tmpPath);
171 } else {
172 nonSymlinks.insert(prefix);
173 }
174 }
175 } while (separatorPos != -1);
176
177 return QDir::cleanPath(tmpPath);
178}
179
180/*!
181 Constructs a QFSFileEngine for the file name \a file.
182*/
183QFSFileEngine::QFSFileEngine(const QString &file) : QAbstractFileEngine(*new QFSFileEnginePrivate)
184{
185 Q_D(QFSFileEngine);
186 d->filePath = QDir::fromNativeSeparators(file);
187 d->nativeInitFileName();
188}
189
190/*!
191 Constructs a QFSFileEngine.
192*/
193QFSFileEngine::QFSFileEngine() : QAbstractFileEngine(*new QFSFileEnginePrivate)
194{
195}
196
197/*!
198 \internal
199*/
200QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd)
201 : QAbstractFileEngine(dd)
202{
203}
204
205/*!
206 Destructs the QFSFileEngine.
207*/
208QFSFileEngine::~QFSFileEngine()
209{
210 Q_D(QFSFileEngine);
211 if (d->closeFileHandle) {
212 if (d->fh) {
213 int ret;
214 do {
215 ret = fclose(d->fh);
216 } while (ret == EOF && errno == EINTR);
217 } else if (d->fd != -1) {
218 int ret;
219 do {
220 ret = QT_CLOSE(d->fd);
221 } while (ret == -1 && errno == EINTR);
222 }
223 }
224 QList<uchar*> keys = d->maps.keys();
225 for (int i = 0; i < keys.count(); ++i)
226 unmap(keys.at(i));
227}
228
229/*!
230 \reimp
231*/
232void QFSFileEngine::setFileName(const QString &file)
233{
234 Q_D(QFSFileEngine);
235 d->init();
236 d->filePath = QDir::fromNativeSeparators(file);
237 d->nativeInitFileName();
238}
239
240/*!
241 \reimp
242*/
243bool QFSFileEngine::open(QIODevice::OpenMode openMode)
244{
245 Q_D(QFSFileEngine);
246 if (d->filePath.isEmpty()) {
247 qWarning("QFSFileEngine::open: No file name specified");
248 setError(QFile::OpenError, QLatin1String("No file name specified"));
249 return false;
250 }
251
252 // Append implies WriteOnly.
253 if (openMode & QFile::Append)
254 openMode |= QFile::WriteOnly;
255
256 // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
257 if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
258 openMode |= QFile::Truncate;
259
260 d->openMode = openMode;
261 d->lastFlushFailed = false;
262 d->tried_stat = 0;
263 d->fh = 0;
264 d->fd = -1;
265
266 return d->nativeOpen(openMode);
267}
268
269/*!
270 Opens the file handle \a fh in \a openMode mode. Returns true on
271 success; otherwise returns false.
272*/
273bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
274{
275 Q_D(QFSFileEngine);
276
277 // Append implies WriteOnly.
278 if (openMode & QFile::Append)
279 openMode |= QFile::WriteOnly;
280
281 // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
282 if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
283 openMode |= QFile::Truncate;
284
285 d->openMode = openMode;
286 d->lastFlushFailed = false;
287 d->closeFileHandle = false;
288 d->nativeFilePath.clear();
289 d->filePath.clear();
290 d->tried_stat = 0;
291 d->fd = -1;
292
293 return d->openFh(openMode, fh);
294}
295
296/*!
297 Opens the file handle \a fh using the open mode \a flags.
298*/
299bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
300{
301 Q_Q(QFSFileEngine);
302 this->fh = fh;
303 fd = -1;
304
305 // Seek to the end when in Append mode.
306 if (openMode & QIODevice::Append) {
307 int ret;
308 do {
309 ret = QT_FSEEK(fh, 0, SEEK_END);
310 } while (ret == -1 && errno == EINTR);
311
312 if (ret == -1) {
313 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
314 qt_error_string(int(errno)));
315 return false;
316 }
317 }
318
319 return true;
320}
321
322/*!
323 Opens the file descriptor \a fd in \a openMode mode. Returns true
324 on success; otherwise returns false.
325*/
326bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
327{
328 Q_D(QFSFileEngine);
329
330 // Append implies WriteOnly.
331 if (openMode & QFile::Append)
332 openMode |= QFile::WriteOnly;
333
334 // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
335 if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
336 openMode |= QFile::Truncate;
337
338 d->lastFlushFailed = false;
339 d->closeFileHandle = false;
340 d->nativeFilePath.clear();
341 d->filePath.clear();
342 d->fh = 0;
343 d->fd = -1;
344 d->tried_stat = 0;
345
346 return d->openFd(openMode, fd);
347}
348
349
350/*!
351 Opens the file descriptor \a fd to the file engine, using the open mode \a
352 flags.
353*/
354bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
355{
356 Q_Q(QFSFileEngine);
357 this->fd = fd;
358 fh = 0;
359
360 // Seek to the end when in Append mode.
361 if (openMode & QFile::Append) {
362 int ret;
363 do {
364 ret = QT_LSEEK(fd, 0, SEEK_END);
365 } while (ret == -1 && errno == EINTR);
366
367 if (ret == -1) {
368 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
369 qt_error_string(int(errno)));
370 return false;
371 }
372 }
373
374 return true;
375}
376
377/*!
378 \reimp
379*/
380bool QFSFileEngine::close()
381{
382 Q_D(QFSFileEngine);
383 d->openMode = QIODevice::NotOpen;
384 return d->nativeClose();
385}
386
387/*!
388 \internal
389*/
390bool QFSFileEnginePrivate::closeFdFh()
391{
392 Q_Q(QFSFileEngine);
393 if (fd == -1 && !fh)
394 return false;
395
396 // Flush the file if it's buffered, and if the last flush didn't fail.
397 bool flushed = !fh || (!lastFlushFailed && q->flush());
398 bool closed = true;
399 tried_stat = 0;
400
401 // Close the file if we created the handle.
402 if (closeFileHandle) {
403 int ret;
404 do {
405 if (fh) {
406 // Close buffered file.
407 ret = fclose(fh) != 0 ? -1 : 0;
408 } else {
409 // Close unbuffered file.
410 ret = QT_CLOSE(fd);
411 }
412 } while (ret == -1 && errno == EINTR);
413
414 // We must reset these guys regardless; calling close again after a
415 // failed close causes crashes on some systems.
416 fh = 0;
417 fd = -1;
418 closed = (ret == 0);
419 }
420
421 // Report errors.
422 if (!flushed || !closed) {
423 if (flushed) {
424 // If not flushed, we want the flush error to fall through.
425 q->setError(QFile::UnspecifiedError, qt_error_string(errno));
426 }
427 return false;
428 }
429
430 return true;
431}
432
433/*!
434 \reimp
435*/
436bool QFSFileEngine::flush()
437{
438 Q_D(QFSFileEngine);
439 if ((d->openMode & QIODevice::WriteOnly) == 0) {
440 // Nothing in the write buffers, so flush succeeds in doing
441 // nothing.
442 return true;
443 }
444 return d->nativeFlush();
445}
446
447/*!
448 \internal
449*/
450bool QFSFileEnginePrivate::flushFh()
451{
452 Q_Q(QFSFileEngine);
453
454 // Never try to flush again if the last flush failed. Otherwise you can
455 // get crashes on some systems (AIX).
456 if (lastFlushFailed)
457 return false;
458
459 int ret = fflush(fh);
460
461 lastFlushFailed = (ret != 0);
462 lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
463
464 if (ret != 0) {
465 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
466 qt_error_string(errno));
467 return false;
468 }
469 return true;
470}
471
472/*!
473 \reimp
474*/
475qint64 QFSFileEngine::size() const
476{
477 Q_D(const QFSFileEngine);
478 return d->nativeSize();
479}
480
481/*!
482 \internal
483*/
484qint64 QFSFileEnginePrivate::sizeFdFh() const
485{
486 Q_Q(const QFSFileEngine);
487 // ### Fix this function, it should not stat unless the file is closed.
488 QT_STATBUF st;
489 int ret = 0;
490 const_cast<QFSFileEngine *>(q)->flush();
491 if (fh && nativeFilePath.isEmpty()) {
492 // Buffered stdlib mode.
493 // ### This should really be an ftell
494 ret = QT_FSTAT(QT_FILENO(fh), &st);
495 } else if (fd == -1) {
496 // Stateless stat.
497 ret = QT_STAT(nativeFilePath.constData(), &st);
498 } else {
499 // Unbuffered stdio mode.
500 ret = QT_FSTAT(fd, &st);
501 }
502 if (ret == -1)
503 return 0;
504 return st.st_size;
505}
506
507/*!
508 \reimp
509*/
510qint64 QFSFileEngine::pos() const
511{
512 Q_D(const QFSFileEngine);
513 return d->nativePos();
514}
515
516/*!
517 \internal
518*/
519qint64 QFSFileEnginePrivate::posFdFh() const
520{
521 if (fh)
522 return qint64(QT_FTELL(fh));
523 return QT_LSEEK(fd, 0, SEEK_CUR);
524}
525
526/*!
527 \reimp
528*/
529bool QFSFileEngine::seek(qint64 pos)
530{
531 Q_D(QFSFileEngine);
532 return d->nativeSeek(pos);
533}
534
535/*!
536 \internal
537*/
538bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
539{
540 Q_Q(QFSFileEngine);
541
542 // On Windows' stdlib implementation, the results of calling fread and
543 // fwrite are undefined if not called either in sequence, or if preceded
544 // with a call to fflush().
545 if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
546 return false;
547
548 if (fh) {
549 // Buffered stdlib mode.
550 int ret;
551 do {
552 ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
553 } while (ret == -1 && errno == EINTR);
554
555 if (ret == -1) {
556 q->setError(QFile::ReadError, qt_error_string(int(errno)));
557 return false;
558 }
559 } else {
560 // Unbuffered stdio mode.
561 if (QT_LSEEK(fd, pos, SEEK_SET) == -1) {
562 qWarning("QFile::at: Cannot set file position %lld", pos);
563 q->setError(QFile::PositionError, qt_error_string(errno));
564 return false;
565 }
566 }
567 return true;
568}
569
570/*!
571 \reimp
572*/
573int QFSFileEngine::handle() const
574{
575 Q_D(const QFSFileEngine);
576 return d->nativeHandle();
577}
578
579/*!
580 \reimp
581*/
582qint64 QFSFileEngine::read(char *data, qint64 maxlen)
583{
584 Q_D(QFSFileEngine);
585
586 // On Windows' stdlib implementation, the results of calling fread and
587 // fwrite are undefined if not called either in sequence, or if preceded
588 // with a call to fflush().
589 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
590 flush();
591 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
592 }
593
594 return d->nativeRead(data, maxlen);
595}
596
597/*!
598 \internal
599*/
600qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
601{
602 Q_Q(QFSFileEngine);
603
604 // Buffered stdlib mode.
605 if (fh) {
606 qint64 readBytes = 0;
607 qint64 read = 0;
608 int retry = 0;
609
610 // Read in blocks of 4k to avoid platform limitations (Windows
611 // commonly bails out if you read or write too large blocks at once).
612 qint64 bytesToRead;
613 do {
614 if (retry == 1)
615 retry = 2;
616
617 bytesToRead = qMin<qint64>(4096, len - read);
618 do {
619 readBytes = fread(data + read, 1, size_t(bytesToRead), fh);
620 } while (readBytes == 0 && !feof(fh) && errno == EINTR);
621
622 if (readBytes > 0) {
623 read += readBytes;
624 } else if (!retry && feof(fh)) {
625 // Synchronize and try again (just once though).
626 if (++retry == 1)
627 QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET);
628 }
629 } while (retry == 1 || (readBytes == bytesToRead && read < len));
630
631 // Return the number of bytes read, or if nothing was read, return -1
632 // if an error occurred, or 0 if we detected EOF.
633 if (read == 0) {
634 q->setError(QFile::ReadError, qt_error_string(int(errno)));
635 if (!feof(fh))
636 read = -1;
637 }
638 return read;
639 }
640
641 // Unbuffered stdio mode.
642 qint64 ret = 0;
643 if (len) {
644 int result;
645 qint64 read = 0;
646 errno = 0;
647
648 // Read in blocks of 4k to avoid platform limitations (Windows
649 // commonly bails out if you read or write too large blocks at once).
650 do {
651 qint64 bytesToRead = qMin<qint64>(4096, len - read);
652 do {
653 result = QT_READ(fd, data + read, int(bytesToRead));
654 } while (result == -1 && errno == EINTR);
655 if (result > 0)
656 read += result;
657 } while (result > 0 && read < len);
658
659 // Return the number of bytes read, or if nothing was read, return -1
660 // if an error occurred.
661 if (read > 0) {
662 ret += read;
663 } else if (read == 0 && result < 0) {
664 ret = -1;
665 q->setError(QFile::ReadError, qt_error_string(errno));
666 }
667 }
668 return ret;
669}
670
671/*!
672 \reimp
673*/
674qint64 QFSFileEngine::readLine(char *data, qint64 maxlen)
675{
676 Q_D(QFSFileEngine);
677
678 // On Windows' stdlib implementation, the results of calling fread and
679 // fwrite are undefined if not called either in sequence, or if preceded
680 // with a call to fflush().
681 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
682 flush();
683 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
684 }
685
686 return d->nativeReadLine(data, maxlen);
687}
688
689/*!
690 \internal
691*/
692qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
693{
694 Q_Q(QFSFileEngine);
695 if (!fh)
696 return q->QAbstractFileEngine::readLine(data, maxlen);
697
698 QT_OFF_T oldPos = 0;
699#ifdef Q_OS_WIN
700 bool seq = q->isSequential();
701 if (!seq)
702#endif
703 oldPos = QT_FTELL(fh);
704
705 // QIODevice::readLine() passes maxlen - 1 to QFile::readLineData()
706 // because it has made space for the '\0' at the end of data. But fgets
707 // does the same, so we'd get two '\0' at the end - passing maxlen + 1
708 // solves this.
709 if (!fgets(data, int(maxlen + 1), fh)) {
710 if (!feof(fh))
711 q->setError(QFile::ReadError, qt_error_string(int(errno)));
712 return -1; // error
713 }
714
715#ifdef Q_OS_WIN
716 if (seq)
717 return qstrlen(data);
718#endif
719
720 qint64 lineLength = QT_FTELL(fh) - oldPos;
721 return lineLength > 0 ? lineLength : qstrlen(data);
722}
723
724/*!
725 \reimp
726*/
727qint64 QFSFileEngine::write(const char *data, qint64 len)
728{
729 Q_D(QFSFileEngine);
730
731 // On Windows' stdlib implementation, the results of calling fread and
732 // fwrite are undefined if not called either in sequence, or if preceded
733 // with a call to fflush().
734 if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
735 flush();
736 d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
737 }
738
739 return d->nativeWrite(data, len);
740}
741
742/*!
743 \internal
744*/
745qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
746{
747 Q_Q(QFSFileEngine);
748 qint64 result;
749 qint64 written = 0;
750
751 do {
752 // Write blocks of 4k to avoid platform limitations (Windows commonly
753 // bails out if you read or write too large blocks at once).
754 qint64 bytesToWrite = qMin<qint64>(4096, len - written);
755 if (fh) {
756 do {
757 // Buffered stdlib mode.
758 result = qint64(fwrite(data + written, 1, size_t(bytesToWrite), fh));
759 } while (result == 0 && errno == EINTR);
760 if (bytesToWrite > 0 && result == 0)
761 result = -1;
762 } else {
763 do {
764 // Unbuffered stdio mode.
765 result = QT_WRITE(fd, data + written, bytesToWrite);
766 } while (result == -1 && errno == EINTR);
767 }
768 if (result > 0)
769 written += qint64(result);
770 } while (written < len && result > 0);
771
772 // If we read anything, return that with success. Otherwise, set an error,
773 // and return the last return value.
774 if (result > 0)
775 return written;
776 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
777 return result;
778}
779
780/*!
781 \internal
782*/
783QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
784{
785 return new QFSFileEngineIterator(filters, filterNames);
786}
787
788/*!
789 \internal
790*/
791QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
792{
793 return 0;
794}
795
796/*!
797 \internal
798*/
799QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
800{
801 return QAbstractFileEngine::entryList(filters, filterNames);
802}
803
804/*!
805 \reimp
806*/
807bool QFSFileEngine::isSequential() const
808{
809 Q_D(const QFSFileEngine);
810 if (d->is_sequential == 0)
811 d->is_sequential = d->nativeIsSequential() ? 1 : 2;
812 return d->is_sequential == 1;
813}
814
815/*!
816 \internal
817*/
818bool QFSFileEnginePrivate::isSequentialFdFh() const
819{
820 if (!tried_stat)
821 doStat();
822 if (could_stat) {
823#ifdef Q_OS_UNIX
824 return (st.st_mode & S_IFMT) != S_IFREG;
825 // ### WINDOWS!
826#endif
827 }
828 return true;
829}
830
831/*!
832 \reimp
833*/
834bool QFSFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
835{
836 Q_D(QFSFileEngine);
837 if (extension == AtEndExtension && d->fh && isSequential())
838 return feof(d->fh);
839
840 if (extension == MapExtension) {
841 const MapExtensionOption *options = (MapExtensionOption*)(option);
842 MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
843 returnValue->address = d->map(options->offset, options->size, options->flags);
844 return (returnValue->address != 0);
845 }
846 if (extension == UnMapExtension) {
847 UnMapExtensionOption *options = (UnMapExtensionOption*)option;
848 return d->unmap(options->address);
849 }
850
851 return false;
852}
853
854/*!
855 \reimp
856*/
857bool QFSFileEngine::supportsExtension(Extension extension) const
858{
859 Q_D(const QFSFileEngine);
860 if (extension == AtEndExtension && d->fh && isSequential())
861 return true;
862 if (extension == FastReadLineExtension && d->fh)
863 return true;
864 if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
865 return true;
866 if (extension == UnMapExtension || extension == MapExtension)
867 return true;
868 return false;
869}
870
871QT_END_NAMESPACE
872
873#endif // QT_NO_FSFILEENGINE
Note: See TracBrowser for help on using the repository browser.