146 lines
3.9 KiB
C++
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
|