89void QFSFileEnginePrivate::init()
95 openMode = QIODevice::NotOpen;
98 lastIOCommand = IOFlushCommand;
99 lastFlushFailed =
false;
100 closeFileHandle =
false;
102 fileAttrib = INVALID_FILE_ATTRIBUTES;
103 fileHandle = INVALID_HANDLE_VALUE;
139 ProcessOpenModeResult result;
141 if ((openMode & QFile::NewOnly) && (openMode & QFile::ExistingOnly)) {
142 qWarning(
"NewOnly and ExistingOnly are mutually exclusive");
143 result.error =
"NewOnly and ExistingOnly are mutually exclusive"_L1;
147 if ((openMode & QFile::ExistingOnly) && !(openMode & (QFile::ReadOnly | QFile::WriteOnly))) {
148 qWarning(
"ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite");
150 "ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"_L1;
155 if (openMode & (QFile::Append | QFile::NewOnly))
156 openMode |= QFile::WriteOnly;
159 if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append | QFile::NewOnly)))
160 openMode |= QFile::Truncate;
163 result.openMode = openMode;
196bool QFSFileEngine::open(QIODevice::OpenMode openMode,
197 std::optional<QFile::Permissions> permissions)
199 Q_ASSERT_X(openMode & QIODevice::Unbuffered,
"QFSFileEngine::open",
200 "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
203 if (d->fileEntry.isEmpty()) {
204 qWarning(
"QFSFileEngine::open: No file name specified");
205 setError(QFile::OpenError,
"No file name specified"_L1);
209 const ProcessOpenModeResult res = processOpenModeFlags(openMode);
211 setError(QFileDevice::OpenError, res.error);
215 d->openMode = res.openMode;
216 d->lastFlushFailed =
false;
221 return d->nativeOpen(d->openMode, permissions);
228bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
230 Q_ASSERT_X(openMode & QIODevice::Unbuffered,
"QFSFileEngine::open",
231 "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
235 const ProcessOpenModeResult res = processOpenModeFlags(openMode);
237 setError(QFileDevice::OpenError, res.error);
241 d->openMode = res.openMode;
242 d->lastFlushFailed =
false;
243 d->closeFileHandle = handleFlags.testAnyFlag(QFile::AutoCloseHandle);
244 d->fileEntry.clear();
248 return d->openFh(d->openMode, fh);
260bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
262 Q_ASSERT_X(openMode & QIODevice::Unbuffered,
"QFSFileEngine::open",
263 "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
270 if (openMode & QIODevice::Append) {
273 ret = QT_FSEEK(fh, 0, SEEK_END);
274 }
while (ret != 0 && errno == EINTR);
277 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
278 QSystemError::stdString(errno));
280 this->openMode = QIODevice::NotOpen;
294bool QFSFileEngine::open(QIODevice::OpenMode openMode,
int fd, QFile::FileHandleFlags handleFlags)
298 const ProcessOpenModeResult res = processOpenModeFlags(openMode);
300 setError(QFileDevice::OpenError, res.error);
304 d->openMode = res.openMode;
305 d->lastFlushFailed =
false;
306 d->closeFileHandle = handleFlags.testAnyFlag(QFile::AutoCloseHandle);
307 d->fileEntry.clear();
312 return d->openFd(d->openMode, fd);
320bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode,
int fd)
327 if (openMode & QFile::Append) {
330 ret = QT_LSEEK(fd, 0, SEEK_END);
331 }
while (ret == -1 && errno == EINTR);
334 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
335 QSystemError::stdString(errno));
337 this->openMode = QIODevice::NotOpen;
430bool QFSFileEnginePrivate::flushFh()
439 int ret = fflush(fh);
441 lastFlushFailed = (ret != 0);
442 lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
445 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
446 QSystemError::stdString(errno));
521QDateTime QFSFileEngine::fileTime(QFile::FileTime time)
const
523 Q_D(
const QFSFileEngine);
525 if (time == QFile::FileAccessTime) {
527 d->metaData.clearFlags(QFileSystemMetaData::AccessTime);
530 if (d->doStat(QFileSystemMetaData::Times))
531 return d->metaData.fileTime(time);
540bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
547 if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
550 if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
557 ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
558 }
while (ret != 0 && errno == EINTR);
561 q->setError(QFile::ReadError, QSystemError::stdString(errno));
566 if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
567 q->setError(QFile::PositionError, QSystemError::stdString(errno));
568 qWarning(
"QFile::at: Cannot set file position %lld", pos);
587qint64 QFSFileEngine::read(
char *data, qint64 maxlen)
594 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
596 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
599 return d->nativeRead(data, maxlen);
605qint64 QFSFileEnginePrivate::readFdFh(
char *data, qint64 len)
609 if (len < 0 || len != qint64(size_t(len))) {
610 q->setError(QFile::ReadError, QSystemError::stdString(EINVAL));
614 qint64 readBytes = 0;
622 result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
624 if (eof && result == 0) {
628 QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET);
632 }
while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
634 }
else if (fd != -1) {
642 quint64 wantedBytes = quint64(len) - quint64(readBytes);
643 UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
644 if (chunkSize > wantedBytes)
645 chunkSize = wantedBytes;
646 result = QT_READ(fd, data + readBytes, chunkSize);
647 }
while (result > 0 && (readBytes += result) < len);
653 if (!eof && readBytes == 0) {
655 q->setError(QFile::ReadError, QSystemError::stdString(errno));
664qint64 QFSFileEngine::readLine(
char *data, qint64 maxlen)
671 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
673 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
676 return d->nativeReadLine(data, maxlen);
682qint64 QFSFileEnginePrivate::readLineFdFh(
char *data, qint64 maxlen)
686 return q->QAbstractFileEngine::readLine(data, maxlen);
690 bool seq = q->isSequential();
693 oldPos = QT_FTELL(fh);
699 if (!fgets(data,
int(maxlen + 1), fh)) {
701 q->setError(QFile::ReadError, QSystemError::stdString(errno));
707 return qstrlen(data);
710 qint64 lineLength = QT_FTELL(fh) - oldPos;
711 return lineLength > 0 ? lineLength : qstrlen(data);
717qint64 QFSFileEngine::write(
const char *data, qint64 len)
720 d->metaData.clearFlags(QFileSystemMetaData::Times);
725 if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
727 d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
730 return d->nativeWrite(data, len);
736qint64 QFSFileEnginePrivate::writeFdFh(
const char *data, qint64 len)
740 if (len < 0 || len != qint64(size_t(len))) {
741 q->setError(QFile::WriteError, QSystemError::stdString(EINVAL));
745 qint64 writtenBytes = 0;
754 result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
755 writtenBytes += result;
756 }
while (result == 0 ? errno == EINTR : writtenBytes < len);
758 }
else if (fd != -1) {
766 quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
767 UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
768 if (chunkSize > wantedBytes)
769 chunkSize = wantedBytes;
770 result = QT_WRITE(fd, data + writtenBytes, chunkSize);
771 }
while (result > 0 && (writtenBytes += result) < len);
776 if (len && writtenBytes == 0) {
778 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
779 QSystemError::stdString(errno));
782 metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
793QFSFileEngine::beginEntryList(
const QString &path, QDirListing::IteratorFlags filters,
794 const QStringList &filterNames)
796 return std::make_unique<QFSFileEngineIterator>(path, filters, filterNames);
826bool QFSFileEngine::extension(Extension extension,
const ExtensionOption *option, ExtensionReturn *output)
829 if (extension == AtEndExtension && d->fh && isSequential())
832 if (extension == MapExtension) {
833 const MapExtensionOption *options = (
const MapExtensionOption*)(option);
834 MapExtensionReturn *returnValue =
static_cast<MapExtensionReturn*>(output);
835 returnValue->address = d->map(options->offset, options->size, options->flags);
836 return (returnValue->address !=
nullptr);
838 if (extension == UnMapExtension) {
839 const UnMapExtensionOption *options = (
const UnMapExtensionOption*)option;
840 return d->unmap(options->address);
849bool QFSFileEngine::supportsExtension(Extension extension)
const
851 Q_D(
const QFSFileEngine);
852 if (extension == AtEndExtension && d->fh && isSequential())
854 if (extension == FastReadLineExtension && d->fh)
856 if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
858 if (extension == UnMapExtension || extension == MapExtension)
961bool QFSFileEngine::rename_helper(
const QString &newName, RenameMode mode)