Update mime database from Qt

qtbase/047d8f36de45ebb318726167f941b0dbc64754ba
  QMimeDatabase::mimeTypeForFile: don't create QFileInfo on UNIX

Change-Id: Ia51923681fa8a759202eaf2542b81733bfbf5745
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Eike Ziller
2024-08-08 16:07:07 +02:00
parent 4790b09bee
commit e148be365e
2 changed files with 88 additions and 70 deletions

View File

@@ -468,6 +468,82 @@ MimeType MimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName
return matchOnContent(&fallbackFile); return matchOnContent(&fallbackFile);
} }
MimeType MimeDatabasePrivate::mimeTypeForFileExtension(const QString &fileName)
{
const QStringList matches = mimeTypeForFileName(fileName);
const int matchCount = matches.count();
if (matchCount == 0) {
return mimeTypeForName(defaultMimeType());
} else if (matchCount == 1) {
return mimeTypeForName(matches.first());
} else {
// We have to pick one.
return mimeTypeForName(matches.first());
}
}
MimeType MimeDatabasePrivate::mimeTypeForData(QIODevice *device)
{
int accuracy = 0;
const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
if (device->isOpen()) {
// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
// This is much faster than seeking back and forth into QIODevice.
const QByteArray data = device->peek(16384);
const MimeType result = findByData(data, &accuracy);
if (openedByUs)
device->close();
return result;
}
return mimeTypeForName(defaultMimeType());
}
MimeType MimeDatabasePrivate::mimeTypeForFile(const QString &fileName,
[[maybe_unused]] const QFileInfo *fileInfo,
MimeDatabase::MatchMode mode)
{
#ifdef Q_OS_UNIX
// Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
// In addition we want to follow symlinks.
const QByteArray nativeFilePath = QFile::encodeName(fileName);
QT_STATBUF statBuffer;
if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
if (S_ISDIR(statBuffer.st_mode))
return mimeTypeForName(QLatin1String("inode/directory"));
if (S_ISCHR(statBuffer.st_mode))
return mimeTypeForName(QLatin1String("inode/chardevice"));
if (S_ISBLK(statBuffer.st_mode))
return mimeTypeForName(QLatin1String("inode/blockdevice"));
if (S_ISFIFO(statBuffer.st_mode))
return mimeTypeForName(QLatin1String("inode/fifo"));
if (S_ISSOCK(statBuffer.st_mode))
return mimeTypeForName(QLatin1String("inode/socket"));
}
#else
const bool isDirectory = fileInfo ? fileInfo->isDir() : QFileInfo(fileName).isDir();
if (isDirectory)
return mimeTypeForName(QLatin1String("inode/directory"));
#endif
int priority = 0;
switch (mode) {
case MimeDatabase::MatchDefault:
return mimeTypeForFileNameAndData(fileName, nullptr, &priority);
case MimeDatabase::MatchExtension:
return mimeTypeForFileExtension(fileName);
case MimeDatabase::MatchContent: {
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
return mimeTypeForData(&file);
} else {
return mimeTypeForName(defaultMimeType());
}
}
default:
Q_ASSERT(false);
}
return mimeTypeForName(defaultMimeType());
}
QList<MimeType> MimeDatabasePrivate::allMimeTypes() QList<MimeType> MimeDatabasePrivate::allMimeTypes()
{ {
QList<MimeType> result; QList<MimeType> result;
@@ -601,48 +677,7 @@ MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode
d->checkInitPhase(fileInfo.filePath()); d->checkInitPhase(fileInfo.filePath());
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
if (fileInfo.isDir()) return d->mimeTypeForFile(fileInfo.filePath(), &fileInfo, mode);
return d->mimeTypeForName(QLatin1String("inode/directory"));
const QString filePath = fileInfo.filePath();
#ifdef Q_OS_UNIX
// Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
// In addition we want to follow symlinks.
const QByteArray nativeFilePath = QFile::encodeName(filePath);
QT_STATBUF statBuffer;
if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
if (S_ISCHR(statBuffer.st_mode))
return d->mimeTypeForName(QLatin1String("inode/chardevice"));
if (S_ISBLK(statBuffer.st_mode))
return d->mimeTypeForName(QLatin1String("inode/blockdevice"));
if (S_ISFIFO(statBuffer.st_mode))
return d->mimeTypeForName(QLatin1String("inode/fifo"));
if (S_ISSOCK(statBuffer.st_mode))
return d->mimeTypeForName(QLatin1String("inode/socket"));
}
#endif
int priority = 0;
switch (mode) {
case MatchDefault:
return d->mimeTypeForFileNameAndData(filePath, nullptr, &priority);
case MatchExtension:
locker.unlock();
return mimeTypeForFile(filePath, mode);
case MatchContent: {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
locker.unlock();
return mimeTypeForData(&file);
} else {
return d->mimeTypeForName(d->defaultMimeType());
}
}
default:
Q_ASSERT(false);
}
return d->mimeTypeForName(d->defaultMimeType());
} }
/*! /*!
@@ -652,24 +687,13 @@ MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode
*/ */
MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
{ {
if (mode == MatchExtension) {
d->checkInitPhase(fileName); d->checkInitPhase(fileName);
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
const QStringList matches = d->mimeTypeForFileName(fileName); if (mode == MatchExtension) {
const int matchCount = matches.count(); return d->mimeTypeForFileExtension(fileName);
if (matchCount == 0) {
return d->mimeTypeForName(d->defaultMimeType());
} else if (matchCount == 1) {
return d->mimeTypeForName(matches.first());
} else { } else {
// We have to pick one. return d->mimeTypeForFile(fileName, nullptr, mode);
return d->mimeTypeForName(matches.first());
}
} else {
// Implemented as a wrapper around mimeTypeForFile(QFileInfo), so no mutex.
QFileInfo fileInfo(fileName);
return mimeTypeForFile(fileInfo, mode);
} }
} }
@@ -737,18 +761,7 @@ MimeType MimeDatabase::mimeTypeForData(QIODevice *device) const
{ {
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
int accuracy = 0; return d->mimeTypeForData(device);
const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
if (device->isOpen()) {
// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
// This is much faster than seeking back and forth into QIODevice.
const QByteArray data = device->peek(16384);
const MimeType result = d->findByData(data, &accuracy);
if (openedByUs)
device->close();
return result;
}
return d->mimeTypeForName(d->defaultMimeType());
} }
/*! /*!

View File

@@ -15,6 +15,7 @@
// We mean it. // We mean it.
// //
#include "mimedatabase.h"
#include "mimetype.h" #include "mimetype.h"
#include "mimeglobpattern_p.h" #include "mimeglobpattern_p.h"
@@ -32,6 +33,7 @@
#include <vector> #include <vector>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QFileInfo;
class QIODevice; class QIODevice;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -60,6 +62,9 @@ public:
QStringList parents(const QString &mimeName); QStringList parents(const QString &mimeName);
MimeType mimeTypeForName(const QString &nameOrAlias); MimeType mimeTypeForName(const QString &nameOrAlias);
MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr); MimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
MimeType mimeTypeForFileExtension(const QString &fileName);
MimeType mimeTypeForData(QIODevice *device);
MimeType mimeTypeForFile(const QString &fileName, const QFileInfo *fileInfo, MimeDatabase::MatchMode mode);
MimeType findByData(const QByteArray &data, int *priorityPtr); MimeType findByData(const QByteArray &data, int *priorityPtr);
QStringList mimeTypeForFileName(const QString &fileName); QStringList mimeTypeForFileName(const QString &fileName);
MimeGlobMatchResult findByFileName(const QString &fileName); MimeGlobMatchResult findByFileName(const QString &fileName);