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);
254bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
256 Q_ASSERT_X(openMode & QIODevice::Unbuffered,
"QFSFileEngine::open",
257 "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
264 if (openMode & QIODevice::Append) {
267 ret = QT_FSEEK(fh, 0, SEEK_END);
268 }
while (ret != 0 && errno == EINTR);
271 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
272 QSystemError::stdString(errno));
274 this->openMode = QIODevice::NotOpen;
288bool QFSFileEngine::open(QIODevice::OpenMode openMode,
int fd, QFile::FileHandleFlags handleFlags)
292 const ProcessOpenModeResult res = processOpenModeFlags(openMode);
294 setError(QFileDevice::OpenError, res.error);
298 d->openMode = res.openMode;
299 d->lastFlushFailed =
false;
300 d->closeFileHandle = handleFlags.testAnyFlag(QFile::AutoCloseHandle);
301 d->fileEntry.clear();
306 return d->openFd(d->openMode, fd);
314bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode,
int fd)
321 if (openMode & QFile::Append) {
324 ret = QT_LSEEK(fd, 0, SEEK_END);
325 }
while (ret == -1 && errno == EINTR);
328 q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
329 QSystemError::stdString(errno));
331 this->openMode = QIODevice::NotOpen;
424bool QFSFileEnginePrivate::flushFh()
433 int ret = fflush(fh);
435 lastFlushFailed = (ret != 0);
436 lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
439 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
440 QSystemError::stdString(errno));
515QDateTime QFSFileEngine::fileTime(QFile::FileTime time)
const
517 Q_D(
const QFSFileEngine);
519 if (time == QFile::FileAccessTime) {
521 d->metaData.clearFlags(QFileSystemMetaData::AccessTime);
524 if (d->doStat(QFileSystemMetaData::Times))
525 return d->metaData.fileTime(time);
534bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
541 if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
544 if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
551 ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
552 }
while (ret != 0 && errno == EINTR);
555 q->setError(QFile::ReadError, QSystemError::stdString(errno));
560 if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
561 q->setError(QFile::PositionError, QSystemError::stdString(errno));
562 qWarning(
"QFile::at: Cannot set file position %lld", pos);
581qint64 QFSFileEngine::read(
char *data, qint64 maxlen)
588 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
590 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
593 return d->nativeRead(data, maxlen);
599qint64 QFSFileEnginePrivate::readFdFh(
char *data, qint64 len)
603 if (len < 0 || len != qint64(size_t(len))) {
604 q->setError(QFile::ReadError, QSystemError::stdString(EINVAL));
608 qint64 readBytes = 0;
616 result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
618 if (eof && result == 0) {
622 QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET);
626 }
while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
628 }
else if (fd != -1) {
636 quint64 wantedBytes = quint64(len) - quint64(readBytes);
637 UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
638 if (chunkSize > wantedBytes)
639 chunkSize = wantedBytes;
640 result = QT_READ(fd, data + readBytes, chunkSize);
641 }
while (result > 0 && (readBytes += result) < len);
647 if (!eof && readBytes == 0) {
649 q->setError(QFile::ReadError, QSystemError::stdString(errno));
658qint64 QFSFileEngine::readLine(
char *data, qint64 maxlen)
665 if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
667 d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
670 return d->nativeReadLine(data, maxlen);
676qint64 QFSFileEnginePrivate::readLineFdFh(
char *data, qint64 maxlen)
680 return q->QAbstractFileEngine::readLine(data, maxlen);
684 bool seq = q->isSequential();
687 oldPos = QT_FTELL(fh);
693 if (!fgets(data,
int(maxlen + 1), fh)) {
695 q->setError(QFile::ReadError, QSystemError::stdString(errno));
701 return qstrlen(data);
704 qint64 lineLength = QT_FTELL(fh) - oldPos;
705 return lineLength > 0 ? lineLength : qstrlen(data);
711qint64 QFSFileEngine::write(
const char *data, qint64 len)
714 d->metaData.clearFlags(QFileSystemMetaData::Times);
719 if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
721 d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
724 return d->nativeWrite(data, len);
730qint64 QFSFileEnginePrivate::writeFdFh(
const char *data, qint64 len)
734 if (len < 0 || len != qint64(size_t(len))) {
735 q->setError(QFile::WriteError, QSystemError::stdString(EINVAL));
739 qint64 writtenBytes = 0;
748 result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
749 writtenBytes += result;
750 }
while (result == 0 ? errno == EINTR : writtenBytes < len);
752 }
else if (fd != -1) {
760 quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
761 UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
762 if (chunkSize > wantedBytes)
763 chunkSize = wantedBytes;
764 result = QT_WRITE(fd, data + writtenBytes, chunkSize);
765 }
while (result > 0 && (writtenBytes += result) < len);
770 if (len && writtenBytes == 0) {
772 q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
773 QSystemError::stdString(errno));
776 metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
787QFSFileEngine::beginEntryList(
const QString &path, QDirListing::IteratorFlags filters,
788 const QStringList &filterNames)
790 return std::make_unique<QFSFileEngineIterator>(path, filters, filterNames);
820bool QFSFileEngine::extension(Extension extension,
const ExtensionOption *option, ExtensionReturn *output)
823 if (extension == AtEndExtension && d->fh && isSequential())
826 if (extension == MapExtension) {
827 const MapExtensionOption *options = (
const MapExtensionOption*)(option);
828 MapExtensionReturn *returnValue =
static_cast<MapExtensionReturn*>(output);
829 returnValue->address = d->map(options->offset, options->size, options->flags);
830 return (returnValue->address !=
nullptr);
832 if (extension == UnMapExtension) {
833 const UnMapExtensionOption *options = (
const UnMapExtensionOption*)option;
834 return d->unmap(options->address);
843bool QFSFileEngine::supportsExtension(Extension extension)
const
845 Q_D(
const QFSFileEngine);
846 if (extension == AtEndExtension && d->fh && isSequential())
848 if (extension == FastReadLineExtension && d->fh)
850 if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
852 if (extension == UnMapExtension || extension == MapExtension)
955bool QFSFileEngine::rename_helper(
const QString &newName, RenameMode mode)