reusable non-VFS (QRC) QFileInfo/QFileSystemWatcherEngineUnix::FileInfo alternative

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-11-15 09:23:41 +02:00
parent c372e5af3a
commit ec45dcff28
4 changed files with 152 additions and 50 deletions

View file

@ -43,12 +43,12 @@ QStringList QFileSystemWatcherEngineUnix::addPaths(const QStringList &paths,
{
QStringList p = paths;
foreach (const QString &path, p) {
QFileInfo fi(path);
QStatInfo fi(path);
if (fi.isDir() || path.endsWith(QLatin1Char('/'))) {
if (!directories->contains(path))
directories->append(path);
if (!path.endsWith(QLatin1Char('/')))
fi = QFileInfo(path + QLatin1Char('/'));
fi = QStatInfo(path + QLatin1Char('/'));
this->directories.insert(path, fi);
} else {
if (!files->contains(path))
@ -88,11 +88,11 @@ QStringList QFileSystemWatcherEngineUnix::removePaths(const QStringList &paths,
void QFileSystemWatcherEngineUnix::timeout()
{
QMutableHashIterator<QString, FileInfo> fit(files);
QMutableHashIterator<QString, QStatInfo> fit(files);
while (fit.hasNext()) {
QHash<QString, FileInfo>::iterator x = fit.next();
QHash<QString, QStatInfo>::iterator x = fit.next();
QString path = x.key();
QFileInfo fi(path);
QStatInfo fi(path);
if (x.value() != fi) {
if (!fi.exists()) {
fit.remove();
@ -103,14 +103,14 @@ void QFileSystemWatcherEngineUnix::timeout()
}
}
}
QMutableHashIterator<QString, FileInfo> dit(directories);
QMutableHashIterator<QString, QStatInfo> dit(directories);
while (dit.hasNext()) {
QHash<QString, FileInfo>::iterator x = dit.next();
QHash<QString, QStatInfo>::iterator x = dit.next();
QString path = x.key();
QFileInfo fi(path);
QStatInfo fi(path);
if (!path.endsWith(QLatin1Char('/')))
fi = QFileInfo(path + QLatin1Char('/'));
if (x.value() != fi) {
fi = QStatInfo(path + QLatin1Char('/'));
if (!fi.dirEquals(x.value())) {
if (!fi.exists()) {
dit.remove();
emit directoryChanged(path, true);

View file

@ -43,6 +43,7 @@
#include "qfileinfo.h"
#include "qdatetime.h"
#include "qtimer.h"
#include "qcore_unix_p.h"
QT_BEGIN_NAMESPACE
@ -51,46 +52,7 @@ class QFileSystemWatcherEngineUnix : public QFileSystemWatcherEngine
{
Q_OBJECT
class FileInfo
{
uint ownerId;
uint groupId;
QFile::Permissions permissions;
QDateTime lastModified;
QStringList entries;
public:
FileInfo(const QFileInfo &fileInfo)
: ownerId(fileInfo.ownerId()),
groupId(fileInfo.groupId()),
permissions(fileInfo.permissions()),
lastModified(fileInfo.lastModified())
{
if (fileInfo.isDir()) {
entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
}
}
FileInfo &operator=(const QFileInfo &fileInfo)
{
*this = FileInfo(fileInfo);
return *this;
}
bool operator!=(const QFileInfo &fileInfo) const
{
if (ownerId != fileInfo.ownerId()
|| groupId != fileInfo.groupId()
|| permissions != fileInfo.permissions()
|| lastModified != fileInfo.lastModified()) {
return true;
}
if (fileInfo.isDir() && entries != fileInfo.absoluteDir().entryList(QDir::AllEntries))
return true;
return false;
}
};
QHash<QString, FileInfo> files, directories;
QHash<QString, QStatInfo> files, directories;
public:
QFileSystemWatcherEngineUnix();

View file

@ -21,6 +21,8 @@
#include "qcore_unix_p.h"
#include "qelapsedtimer.h"
#include "qbytearray.h"
#include "qdebug.h"
#include <sys/select.h>
#include <sys/time.h>
@ -28,6 +30,115 @@
QT_BEGIN_NAMESPACE
QStatInfo::QStatInfo(const QString &path, const bool listdir)
: m_mode(0),
m_uid(-2),
m_gid(-2),
m_mtime(0),
m_path(path.toLocal8Bit())
{
QT_STATBUF statbuf;
if (QT_STAT(m_path.constData(), &statbuf) == 0) {
m_mode = statbuf.st_mode;
m_uid = statbuf.st_uid;
m_gid = statbuf.st_gid;
m_mtime = statbuf.st_mtime;
if (listdir && S_ISDIR(statbuf.st_mode)) {
m_entries = dirInfos(m_path, path);
}
}
}
QStatInfo::QStatInfo(const QStatInfo &other)
: m_mode(other.m_mode),
m_uid(other.m_uid),
m_gid(other.m_gid),
m_mtime(other.m_mtime),
m_entries(other.m_entries),
m_path(other.m_path)
{
}
QStatInfo& QStatInfo::operator=(const QStatInfo &other)
{
m_mode = other.m_mode;
m_uid = other.m_uid;
m_gid = other.m_gid;
m_mtime = other.m_mtime;
m_entries = other.m_entries;
m_path = other.m_path;
return *this;
}
bool QStatInfo::operator==(const QStatInfo &other) const
{
if (m_mode != other.m_mode || m_uid != other.m_uid
|| m_gid != other.m_gid || m_mtime != other.m_mtime) {
return false;
}
return (m_path == other.m_path);
}
bool QStatInfo::dirEquals(const QStatInfo &other) const
{
if (*this != other) {
return false;
}
if (isDir() && other.isDir()) {
const QString localpath = QString::fromLocal8Bit(other.m_path);
if (m_entries != dirInfos(other.m_path, localpath)) {
return false;
}
}
return true;
}
QList<QStatInfo> QStatInfo::dirInfos(const QByteArray &nativepath, const QString &localpath)
{
QList<QStatInfo> result;
QT_DIR *dir = QT_OPENDIR(nativepath.constData());
QT_DIRENT *dirent = QT_READDIR(dir);
while (dirent) {
if (qstrcmp(".", dirent->d_name) == 0 || qstrcmp("..", dirent->d_name) == 0) {
dirent = QT_READDIR(dir);
continue;
}
#ifdef QT_HAVE_DIRENT_D_TYPE
const QString dirlocal = QString::fromLocal8Bit(dirent->d_name);
switch (dirent->d_type) {
case DT_BLK:
case DT_CHR:
case DT_FIFO:
case DT_SOCK:
case DT_LNK:
case DT_REG: {
const QString fulllocal = QString::fromLatin1("%1/%2").arg(localpath, dirlocal);
result.append(QStatInfo(fulllocal));
break;
}
case DT_DIR:
case DT_UNKNOWN:
default: {
break;
}
}
#else
const QString fulllocal = QString::fromLatin1("%1/%2").arg(localpath, dirlocal);
const QByteArray fullnative = fulllocal.toLocal8Bit();
QT_STATBUF statbuf;
if (QT_STAT(fullnative.constData(), &statbuf) == 0) {
if (!S_ISDIR(statbuf.st_mode)) {
result.append(QStatInfo(fulllocal));
}
}
#endif
dirent = QT_READDIR(dir);
}
QT_CLOSEDIR(dir);
return result;
}
static inline bool time_update(struct timeval *tv, const struct timeval &start,
const struct timeval &timeout)
{

View file

@ -35,6 +35,8 @@
#include "qplatformdefs.h"
#include "qatomic.h"
#include "qlist.h"
#include "qstring.h"
#include <poll.h>
#include <string.h>
@ -58,6 +60,33 @@
QT_BEGIN_NAMESPACE
class QStatInfo {
public:
QStatInfo(const QString &path, const bool listdir = true);
QStatInfo(const QStatInfo &other);
QStatInfo& operator=(const QStatInfo &other);
bool operator==(const QStatInfo &other) const;
inline bool operator!=(const QStatInfo &other) const
{ return !operator==(other); }
inline bool isDir() const
{ return S_ISDIR(m_mode); }
inline bool exists() const
{ return (m_mode != 0); }
bool dirEquals(const QStatInfo &other) const;
static QList<QStatInfo> dirInfos(const QByteArray &nativepath, const QString &localpath);
private:
mode_t m_mode;
uid_t m_uid;
gid_t m_gid;
time_t m_mtime;
QList<QStatInfo> m_entries;
QByteArray m_path;
};
// Internal operator functions for timevals
inline timeval &normalizedTimeval(timeval &t)
{