diff options
-rw-r--r-- | src-qt5/core/libLumina/LFileInfo.cpp | 118 | ||||
-rw-r--r-- | src-qt5/core/libLumina/LFileInfo.h | 21 |
2 files changed, 134 insertions, 5 deletions
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 <LUtils.h> +#include <QRegExp> +#include <unistd.h> 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; i<gplist.length(); i++){ + QStringList tmp = perms.filter(QRegExp("[user|group] "+gplist[i])); + if(tmp.isEmpty()){ continue; } + zfs_perms << tmp.first().section(" ",2,2,QString::SectionSkipEmpty).split(",",QString::SkipEmptyParts); + } + zfs_perms.removeDuplicates(); + //qDebug() << "Got ZFS Permissions:" << zfs_ds << zfs_perms; + } + } + } } @@ -138,7 +166,11 @@ bool LFileInfo::isAVFile(){ return (mime.startsWith("audio/") || mime.startsWith("video/") ); } -bool LFileInfo::isZfsDataset(){ +bool LFileInfo::isZfsDataset(QString path){ + if(!path.isEmpty() && zfsAvailable() ){ + //manual check of a dir + return (0 == LUtils::runCmd("zfs", QStringList() << "get" << "-H" << "atime" << path) ); + } if(!goodZfsDataset()){ return false; } return ( ("/"+zfs_ds.section("/",1,-1)) == this->canonicalFilePath()); } @@ -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<LFileInfo> LFileInfoList; |