quickmod/FuseMounter/fusearchive.h

146 lines
3.9 KiB
C++

#ifndef FUSEARCHIVE_H
#define FUSEARCHIVE_H
#include <QCache>
#include <QMutex>
#include <QObject>
#include <QSqlDatabase>
extern "C" {
#include <fcntl.h>
#include <unarr.h>
#include <unistd.h>
}
#include "fusebase.h"
class ModLibrary;
class ModEntry;
class FuseArchiveEntry : public QObject {
public:
FuseArchiveEntry(QObject *parent=nullptr)
: QObject(parent)
{
memset(&m_stat, 0, sizeof(struct stat));
}
FuseArchiveEntry(const FuseArchiveEntry& other)
: QObject()
{
m_path = other.m_path;
m_actual = other.m_actual;
m_offset = other.m_offset;
memcpy( &m_stat, &other.m_stat, sizeof(struct stat));
}
FuseArchiveEntry& operator=(const FuseArchiveEntry& other) {
if (this != &other) {
m_path = other.m_path;
m_actual = other.m_actual;
m_offset = other.m_offset;
memcpy( &m_stat, &other.m_stat, sizeof(struct stat));
}
return *this;
}
FuseArchiveEntry &findChild(const QStringList &path);
QString m_path;
QString m_actual;
quint64 m_offset;
struct stat m_stat;
};
class FuseArchiveMapping : public QObject {
public:
FuseArchiveMapping(QObject *parent=nullptr)
: QObject(parent)
{
}
FuseArchiveMapping(const FuseArchiveMapping& other)
: QObject(),
m_path{other.m_path},
m_actual{other.m_actual},
m_entry{other.m_entry}
{
}
FuseArchiveMapping& operator=(const FuseArchiveMapping& other) {
if (this != &other) {
m_path = other.m_path;
m_actual = other.m_actual;
m_entry = other.m_entry;
}
return *this;
}
QString m_path;
QString m_actual;
FuseArchiveEntry m_entry;
};
class FuseAccessorArchive : public FuseAccessorBase
{
Q_OBJECT
protected:
friend class FuseFHArchive;
bool m_valid;
ar_stream *m_stream;
ar_archive *m_archive;
QMutex m_mutex;
QSqlDatabase &m_database;
int m_id;
QMap< QString, QStringList > m_dirCache;
QMap< QString, struct stat * > m_statCache;
QMap< QString, FuseArchiveEntry > m_entries;
QList< FuseArchiveMapping > m_manifest;
QMap< QString, FuseArchiveEntry > readEntries();
QList< FuseArchiveMapping > readManifest();
public:
explicit FuseAccessorArchive(FuseInterface *parent, QSqlDatabase &database, int modId, const QString &modPath );
virtual ~FuseAccessorArchive();
int getattr(const QString &path, struct stat *stbuf) override;
QStringList readdir(const QString &path) override;
FuseFHBase *open(const QString &path, QIODeviceBase::OpenMode mode) override;
static QList< QPair<int, QString> > activeArchives(QSqlDatabase &database, int profileId);
// This expects the new entry to be created, then return "write" on the opened handle, otherwise return the appropriate "write" error code.
int makeWritable(struct fuse_file_info *fi, const QString &origsource, const QString &path, const QByteArray &fullData, QIODeviceBase::OpenMode mode, const QByteArray &data, off_t offset);
bool slurpData(const QString &path, const QString &origpath);
QSharedPointer<QByteArray> cacheGrab(const QString &path);
};
class FuseFHArchive : public FuseFHBase
{
Q_OBJECT
FuseAccessorArchive *m_archive;
int m_accessCount;
time_t m_lastAccess;
QString m_newpath;
public:
explicit FuseFHArchive(FuseAccessorBase *parent, const QString &path, const QString &newpath);
virtual ~FuseFHArchive();
bool open(QIODeviceBase::OpenMode mode) override;
QByteArray read(size_t size, off_t offset) override;
int write(const QByteArray &data, off_t offset, fuse_file_info *fi) override;
off_t lseek(off_t off, int whence) override;
void release() override;
};
#endif // FUSEARCHIVE_H