From 0c4f3e425346da4272f75c0b30e573e653916574 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 23 Apr 2018 08:43:39 -0400 Subject: Add a bunch more ZFS integrations into LFileInfo: 1. ZFS permissions detection and UID check. 2. ZFS create 3. ZFS destroy 4. ZFS snapshot 5. ZFS rollback 6. ZFS clone (not finished yet) --- src-qt5/core/libLumina/LFileInfo.cpp | 118 ++++++++++++++++++++++++++++++++++- src-qt5/core/libLumina/LFileInfo.h | 21 ++++++- 2 files changed, 134 insertions(+), 5 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LFileInfo.cpp b/src-qt5/core/libLumina/LFileInfo.cpp index 3b659c75..9fdbfcb5 100644 --- a/src-qt5/core/libLumina/LFileInfo.cpp +++ b/src-qt5/core/libLumina/LFileInfo.cpp @@ -6,9 +6,12 @@ //=========================================== #include "LFileInfo.h" #include +#include +#include LFileInfo::LFileInfo() : QFileInfo(){ desk = 0; + c_uid = -1; } LFileInfo::LFileInfo(QString filepath) : QFileInfo(){ //overloaded contructor @@ -30,6 +33,7 @@ LFileInfo::~LFileInfo(){ void LFileInfo::loadExtraInfo(){ if(desk!=0){ desk->deleteLater(); } desk = 0; + c_uid = geteuid(); //Now load the extra information if(this->absoluteFilePath().startsWith("/net/") || this->isDir() ){ mime = "inode/directory"; @@ -81,8 +85,32 @@ void LFileInfo::getZfsDataset(){ //Use the "atime" property for this check - been around since the earliest versions of ZFS and should take no time to probe QString out = LUtils::runCommand(ok, "zfs", QStringList() << "get" << "-H" << "atime" << this->canonicalFilePath() ); if(!ok){ zfs_ds = "."; } //just something that is not empty - but is clearly not a valid dataset - else{ zfs_ds = out.section("\n",0,0).section("\t",0,0).simplified(); } + else{ + zfs_ds = out.section("\n",0,0).section("\t",0,0).simplified(); + zfs_dspath = this->canonicalFilePath().section(zfs_ds.section("/",1,-1), 1,-1); //relative path + if(!zfs_dspath.isEmpty()){ zfs_dspath.prepend(zfs_ds); } + else{ zfs_dspath = zfs_ds; } //on the current dataset "root" + //qDebug() << "Got ZFS dataset:" << zfs_ds << zfs_dspath; + } //qDebug() << "Found Dataset:" << zfs_ds << out << ok; + if(ok){ + //Also get the list of permissions this user has for modifying the ZFS dataset + QStringList perms = LUtils::runCommand(ok, "zfs", QStringList() << "allow" << zfs_ds ).split("\n"); + //qDebug() << "Permissions:" << perms; + if(!perms.isEmpty() && ok){ + //Now need to filter/combine the permissions for all the groups this user is a part of + QStringList gplist = LUtils::runCommand(ok, "id", QStringList() << "-np").split("\n").filter("groups"); + if(!gplist.isEmpty()){ gplist = gplist.first().replace("\t", " ").split(" ",QString::SkipEmptyParts); gplist.removeAll("groups"); } + for(int i=0; icanonicalFilePath()); } @@ -185,3 +217,85 @@ bool LFileInfo::zfsSetProperty(QString property, QString value){ if(!ok){ qDebug() << "Error Setting ZFS Property:" << property+"="+value << info; } return ok; } + +//ZFS Permissions/Modifications +bool LFileInfo::canZFScreate(){ + if(!goodZfsDataset()){ return false; } + return (zfs_perms.contains("create") || (c_uid==0) ); +} + +bool LFileInfo::zfsCreateDataset(QString subdir){ + if(!canZFScreate()){ return false; } + if(subdir.startsWith("/")){ qDebug() << "Not a relative path!!"; return false; } + if( QFile::exists(this->canonicalFilePath()+"/"+subdir) ){ + return false; + } + bool ok = false; + QString info = LUtils::runCommand(ok, "zfs", QStringList() << "create" << zfs_dspath+"/"+subdir ); + if(!ok){ qDebug() << "Error Creating ZFS Dataset:" << subdir << info; } + return ok; +} + +bool LFileInfo::canZFSdestroy(){ + if(!goodZfsDataset()){ return false; } + return (zfs_perms.contains("destroy") || (c_uid==0) ); +} + +bool LFileInfo::zfsDestroyDataset(QString subdir){ + if(!canZFSdestroy()){ return false; } + if(!subdir.isEmpty() && !subdir.startsWith("/")){ + if( isZfsDataset(this->canonicalFilePath()+"/"+subdir) ){ subdir = zfs_dspath+"/"+subdir; } + } + else if(subdir.isEmpty() && (zfs_ds == zfs_dspath) ){ subdir = zfs_ds; } + else{ qDebug() << "Invalid subdir:" << subdir; return false; } + bool ok = false; + QString info = LUtils::runCommand(ok, "zfs", QStringList() << "destroy" << subdir); + if(!ok){ qDebug() << "Error Destroying ZFS Dataset:" << subdir << info; } + return ok; +} + +bool LFileInfo::zfsDestroySnapshot(QString snapshot){ + if(!canZFSdestroy()){ return false; } + bool ok = false; + QString info = LUtils::runCommand(ok, "zfs", QStringList() << "destroy" << zfs_ds+"@"+snapshot); + if(!ok){ qDebug() << "Error Destroying ZFS Snapshot:" << snapshot << info; } + return ok; +} + +bool LFileInfo::canZFSclone(){ + if(!goodZfsDataset()){ return false; } + return (zfs_perms.contains("clone") || (c_uid==0) ); +} + +bool LFileInfo::zfsCloneDataset(QString subdir, QString newsubdir){ + if(!canZFSclone()){ return false; } + + return false; +} + +bool LFileInfo::canZFSsnapshot(){ + if(!goodZfsDataset()){ return false; } + return (zfs_perms.contains("snapshot") || (c_uid==0) ); +} + +bool LFileInfo::zfsSnapshot(QString snapname){ + if(!canZFSsnapshot()){ return false; } + bool ok = false; + QString info = LUtils::runCommand(ok, "zfs", QStringList() << "snapshot" << zfs_ds+"@"+snapname); + if(!ok){ qDebug() << "Error Creating ZFS Snapshot:" << snapname << info; } + return ok; +} + +bool LFileInfo::canZFSrollback(){ + if(!goodZfsDataset()){ return false; } + return (zfs_perms.contains("rollback") || (c_uid==0) ); +} + +bool LFileInfo::zfsRollback(QString snapname){ + if(!canZFSrollback()){ return false; } + bool ok = false; + QString info = LUtils::runCommand(ok, "zfs", QStringList() << "rollback" << zfs_ds+"@"+snapname); + if(!ok){ qDebug() << "Error Rolling back to ZFS Snapshot:" << snapname << info; } + return ok; +} + diff --git a/src-qt5/core/libLumina/LFileInfo.h b/src-qt5/core/libLumina/LFileInfo.h index f72c8649..21aae19d 100644 --- a/src-qt5/core/libLumina/LFileInfo.h +++ b/src-qt5/core/libLumina/LFileInfo.h @@ -17,8 +17,9 @@ class LFileInfo : public QFileInfo{ private: - QString mime, zfs_ds; - QStringList iconList; + QString mime, zfs_ds, zfs_dspath; + QStringList iconList, zfs_perms; + int c_uid; XDGDesktop *desk; void loadExtraInfo(); @@ -51,12 +52,26 @@ public: bool isVideo(); //Is a readable video file (for thumbnail support) bool isAVFile(); //Is an audio/video file - bool isZfsDataset(); + //ZFS Information + bool isZfsDataset(QString path = ""); QString zfsPool(); QStringList zfsSnapshots(); //Format: "snapshot name::::path/to/snapshot" QJsonObject zfsProperties(); bool zfsSetProperty(QString property, QString value); + //ZFS Permissions/Modifications + bool canZFScreate(); + bool zfsCreateDataset(QString subdir); + bool canZFSdestroy(); + bool zfsDestroyDataset(QString subdir); + bool zfsDestroySnapshot(QString snapshot); + bool canZFSclone(); + bool zfsCloneDataset(QString subdir, QString newsubdir); + bool canZFSsnapshot(); + bool zfsSnapshot(QString snapname); + bool canZFSrollback(); + bool zfsRollback(QString snapname); + }; typedef QList LFileInfoList; -- cgit