38 int oflags = QT_OPEN_RDONLY;
39#ifdef QT_LARGEFILE_SUPPORT
40 oflags |= QT_OPEN_LARGEFILE;
43 if ((mode & QFile::ReadWrite) == QFile::ReadWrite)
44 oflags = QT_OPEN_RDWR;
45 else if (mode & QFile::WriteOnly)
46 oflags = QT_OPEN_WRONLY;
48 if (QFSFileEnginePrivate::openModeCanCreate(mode))
49 oflags |= QT_OPEN_CREAT;
51 if (mode & QFile::Truncate)
52 oflags |= QT_OPEN_TRUNC;
54 if (mode & QFile::Append)
55 oflags |= QT_OPEN_APPEND;
57 if (mode & QFile::NewOnly)
58 oflags |= QT_OPEN_EXCL;
159bool QFSFileEnginePrivate::nativeSyncToDisk()
163#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
164 QT_EINTR_LOOP(ret, fdatasync(nativeHandle()));
166 QT_EINTR_LOOP(ret, fsync(nativeHandle()));
169 q->setError(QFile::WriteError, qt_error_string(errno));
176qint64 QFSFileEnginePrivate::nativeRead(
char *data, qint64 len)
180 if (fh && nativeIsSequential()) {
181 size_t readBytes = 0;
182 int oldFlags = fcntl(QT_FILENO(fh), F_GETFL);
183 for (
int i = 0; i < 2; ++i) {
185 if ((oldFlags & O_NONBLOCK) == 0)
186 fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK);
191 read = fread(data + readBytes, 1, size_t(len - readBytes), fh);
192 }
while (read == 0 && !feof(fh) && errno == EINTR);
203 if ((oldFlags & O_NONBLOCK) == 0) {
204 fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
205 if (readBytes == 0) {
208 readByte = fgetc(fh);
209 }
while (readByte == -1 && errno == EINTR);
210 if (readByte != -1) {
211 *data = uchar(readByte);
220 if ((oldFlags & O_NONBLOCK) == 0) {
221 fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
223 if (readBytes == 0 && !feof(fh)) {
225 q->setError(QFile::ReadError, qt_error_string(errno));
231 return readFdFh(data, len);
311bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags)
const
313 if (!tried_stat || !metaData.hasFlags(flags)) {
317 if (fh && fileEntry.isEmpty())
318 localFd = QT_FILENO(fh);
320 QFileSystemEngine::fillMetaData(localFd, metaData);
322 if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
323 QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags));
326 return metaData.exists();
340QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type)
const
342 Q_D(
const QFSFileEngine);
347 QAbstractFileEngine::FileFlags ret = { };
349 if (type & FlagsMask)
350 ret |= LocalDiskFlag;
354 QFileSystemMetaData::MetaDataFlags queryFlags = { };
356 queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type.toInt()))
357 & QFileSystemMetaData::Permissions;
359 if (type & TypesMask)
360 queryFlags |= QFileSystemMetaData::AliasType
361 | QFileSystemMetaData::LinkType
362 | QFileSystemMetaData::FileType
363 | QFileSystemMetaData::DirectoryType
364 | QFileSystemMetaData::BundleType
365 | QFileSystemMetaData::WasDeletedAttribute;
367 if (type & FlagsMask)
368 queryFlags |= QFileSystemMetaData::HiddenAttribute
369 | QFileSystemMetaData::ExistsAttribute;
370 else if (type & ExistsFlag)
371 queryFlags |= QFileSystemMetaData::WasDeletedAttribute;
373 queryFlags |= QFileSystemMetaData::LinkType;
375 exists = d->doStat(queryFlags);
378 if (!exists && !d->metaData.isLink())
381 if (exists && (type & PermsMask))
382 ret |= FileFlags(uint(d->metaData.permissions().toInt()));
384 if (type & TypesMask) {
385 if (d->metaData.isAlias()) {
388 if ((type & LinkType) && d->metaData.isLink())
391 if (d->metaData.isFile()) {
393 }
else if (d->metaData.isDirectory()) {
394 ret |= DirectoryType;
395 if ((type & BundleType) && d->metaData.isBundle())
402 if (type & FlagsMask) {
404 if (!d->metaData.wasDeleted())
406 if (d->fileEntry.isRoot())
408 else if (d->metaData.isHidden())
423QString QFSFileEngine::fileName(FileName file)
const
425 Q_D(
const QFSFileEngine);
428 return QFileSystemEngine::bundleName(d->fileEntry);
430 return d->fileEntry.fileName();
432 return d->fileEntry.path();
434 case AbsolutePathName: {
435 QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry));
436 return file == AbsolutePathName ? entry.path() : entry.filePath();
439 case CanonicalPathName: {
440 QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
441 return file == CanonicalPathName ? entry.path() : entry.filePath();
443 case AbsoluteLinkTarget:
444 if (d->isSymlink()) {
445 QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
446 return entry.filePath();
450 if (d->isSymlink()) {
451 QFileSystemEntry entry = QFileSystemEngine::getRawLinkPath(d->fileEntry, d->metaData);
452 return entry.filePath();
461 return d->fileEntry.filePath();
489bool QFSFileEngine::setPermissions(uint perms)
496 d->metaData.clearFlags(QFileSystemMetaData::Permissions);
499 ok = QFileSystemEngine::setPermissions(d->fd, QFile::Permissions(perms), error);
501 ok = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
503 setError(QFile::PermissionsError, error.toString());
509bool QFSFileEngine::setSize(qint64 size)
514 ret = QT_FTRUNCATE(d->fd, size) == 0;
516 ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0;
518 ret = QT_TRUNCATE(d->fileEntry.nativeFilePath().constData(), size) == 0;
520 setError(QFile::ResizeError, qt_error_string(errno));
524bool QFSFileEngine::setFileTime(
const QDateTime &newDate, QFile::FileTime time)
528 if (d->openMode == QIODevice::NotOpen) {
529 setError(QFile::PermissionsError, qt_error_string(EACCES));
534 if (!QFileSystemEngine::setFileTime(d->nativeHandle(), newDate, time, error)) {
535 setError(QFile::PermissionsError, error.toString());
539 d->metaData.clearFlags(QFileSystemMetaData::Times);
543uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
545 qint64 maxFileOffset = std::numeric_limits<QT_OFF_T>::max();
546#if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
554 maxFileOffset = qMin((Q_INT64_C(1) << (32+12)) - 1, maxFileOffset);
558 if (openMode == QIODevice::NotOpen) {
559 q->setError(QFile::PermissionsError, qt_error_string(EACCES));
563 if (offset < 0 || offset > maxFileOffset
565 || quint64(size) > quint64(size_t(-1))) {
566 q->setError(QFile::UnspecifiedError, qt_error_string(EINVAL));
571 if (doStat(QFileSystemMetaData::SizeAttribute)
572 && (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset)))
573 qWarning(
"QFSFileEngine::map: Mapping a file beyond its size is not portable");
576 if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
577 if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
579 int sharemode = MAP_SHARED;
580 if (flags & QFileDevice::MapPrivateOption) {
581 sharemode = MAP_PRIVATE;
582 access |= PROT_WRITE;
585#if defined(Q_OS_INTEGRITY)
586 int pageSize = sysconf(_SC_PAGESIZE);
588 int pageSize = getpagesize();
590 int extra = offset % pageSize;
592 if (quint64(size + extra) > quint64((size_t)-1)) {
593 q->setError(QFile::UnspecifiedError, qt_error_string(EINVAL));
597 size_t realSize = (size_t)size + extra;
598 QT_OFF_T realOffset = QT_OFF_T(offset);
599 realOffset &= ~(QT_OFF_T(pageSize - 1));
601 void *mapAddress = QT_MMAP((
void*)
nullptr, realSize,
602 access, sharemode, nativeHandle(), realOffset);
604 uchar *address = extra +
static_cast<uchar*>(mapAddress);
605 maps[address] = {extra, realSize};
611 q->setError(QFile::PermissionsError, qt_error_string(EACCES));
615 q->setError(QFile::ResourceError, qt_error_string(errno));
620 q->setError(QFile::UnspecifiedError, qt_error_string(errno));
626bool QFSFileEnginePrivate::unmap(uchar *ptr)
628#if !defined(Q_OS_INTEGRITY)
630 const auto it = std::as_const(maps).find(ptr);
631 if (it == maps.cend()) {
632 q->setError(QFile::PermissionsError, qt_error_string(EACCES));
636 uchar *start = ptr - it->start;
637 size_t len = it->length;
638 if (-1 == munmap(start, len)) {
639 q->setError(QFile::UnspecifiedError, qt_error_string(errno));
652QAbstractFileEngine::TriStateResult QFSFileEngine::cloneTo(QAbstractFileEngine *target)
655 if ((target->fileFlags(LocalDiskFlag) & LocalDiskFlag) == 0)
656 return TriStateResult::NotSupported;
658 int srcfd = d->nativeHandle();
659 int dstfd = target->handle();
660 TriStateResult r = QFileSystemEngine::cloneFile(srcfd, dstfd, d->metaData);
661 if (r == TriStateResult::Failed)
662 setError(QFile::CopyError, qt_error_string(errno));