QStringList Backend::findActiveDevices(){ QStringList activeDevs; //Now find any active partitions and ignore it and any children of it //NOTE: gpart does not work for root on ZFS, especially with boot blocks on every device for BE-support /*QStringList info = runShellCommand("gpart show -p"); info = info.filter("freebsd").filter("[active]"); for(int i=0; i<info.length(); i++){ info[i].remove("=>"); info[i] = info[i].replace("\t"," ").simplified(); QString dev = info[i].section(" ",2,2,QString::SectionSkipEmpty); activeDevs << dev; //Now get any child devices activeDevs << devChildren(dev); }*/ //Use "zpool status" to get the active ZFS devices/partitions QStringList info = runShellCommand("zpool status"); int start = info.indexOf("config:"); //qDebug() << "Zpool info start:" << start; for(int i = start+1; i<info.length(); i++){ //qDebug() << "Check Line:" << info[i] << i; if(info[i].isEmpty() || (info[i].contains("NAME") && info[i].contains("STATE")) ){ continue; } else if(info[i].startsWith("errors:")){ break; } //start of the next section info[i].replace("\t"," "); QString dev = info[i].section(" ",0,0,QString::SectionSkipEmpty).simplified(); //qDebug() << "Device:" << dev << info[i]; if(QFile::exists("/dev/"+dev)){ activeDevs << dev; } } activeDevs.removeDuplicates(); //qDebug() << "Active Devices:" << activeDevs; return activeDevs; }
QString Backend::getDeviceSizeInfo(QString nodedir){ //can use node *or* mntdir updateIntMountPoints(); QStringList found = IntMountPoints.filter(nodedir+DELIM); QString out = "%1/%2 (%3)"; //<used>/<total> (<percent>) if(found.length()>0){ QString dir = found[0].section(DELIM,2,2); //This might not work properly for ZFS file systems (FIX LATER) QStringList info = runShellCommand("df -h \""+dir+"\""); if(info.length()>1){ //first line is the labels (Filesystem, Size, Used, Avail, Capacity, Mounted On) info[1] = info[1].replace("\t"," "); QStringList stats = info[1].split(" ", QString::SkipEmptyParts); if(stats.length() >= 5){ out = out.arg(stats[2], stats[1], stats[4]); }else{ out = out.arg("??","??","??"); } }else{ out = out.arg("??","??","??"); } }else{ out = out.arg("??","??","??"); } return out; }
QStringList Backend::getPersonaCryptDevices(){ QStringList info = runShellCommand("personacrypt list"); QStringList devs; for(int i=0; i<info.length(); i++){ if(info[i].contains(":") && QFile::exists("/dev/"+info[i].section(":",0,0)) ){ devs << info[i].section(":",0,0); } } return devs; }
QStringList Backend::getSwapDevices(){ //Use "mdconfig" to filter out any SWAP devices QStringList info = runShellCommand("mdconfig -l -v").filter("/swap"); QStringList devs; for(int i=0; i<info.length(); i++){ info[i].replace("\t", " "); devs << info[i].section(" ",0,0).simplified(); } //Also check for EFI/SWAP partitions with glabel info = runShellCommand("glabel status"); for(int i=1; i<info.length(); i++){ info[i].replace("\t"," "); QString lab = info[i].section(" ",0,0); if(lab.contains("label/efi") || lab.contains("/swap") ){ devs << info[i].section(" ",2,2,QString::SectionSkipEmpty); } } devs.removeDuplicates(); return devs; }
QStringList Backend::disktypeInfo(QString node){ //Run disktype on the device and return any info QStringList info = runShellCommand("disktype /dev/"+node); //In case there are multiple partitions on the device, remove all the invalid ones (EFI boot partitions for instance) QStringList parts = info.join("\n").split("\nPartition "); //qDebug() << "DiskType Partitions:" << node << parts; if(parts.filter("Volume name ").length()>0){ parts = parts.filter("Volume name "); if(parts.length()>1 && parts.filter("file system").isEmpty()){ parts = parts.filter("file system"); } } for(int i=0; i<parts.length(); i++){ if(parts[i].contains("Partition GUID ") ){ parts.removeAt(i); i--; } //EFI boot partition } if(!parts.isEmpty()){ info = parts[0].split("\n"); //only use the first partition with both a label and a file system } //qDebug() << " - Filtered:" << info; //qDebug() << "Disktype Detection:" << node; QStringList dsDetection = DEVDB::disktypeDetectionStrings(); QString bytes, fs, type, label; bool blankDisk=false; for(int i=0; i<info.length(); i++){ //qDebug() << "Line:" << info[i]; if(info[i].isEmpty() || info[i].startsWith("---")){ continue; } //skip this line else if( info[i].startsWith("Character device,") && !info[i].contains("unknown size") ){ //Get the size if possible QString tmp = info[i].section("(",1,1).section(")",0,0); if(tmp.contains("bytes")){ bytes = tmp.section(" ",0,0,QString::SectionSkipEmpty); } //qDebug() << " - bytes:" << bytes; }else if( info[i].contains("Blank disk/medium") ){ blankDisk = true; //qDebug() << " - Blank disk"; }else if( info[i].contains("file system") ){ if(fs.isEmpty() || !fs.contains("(hints")){ QString tmp = info[i].section("file system",0,0); for(int j=0; j<dsDetection.length(); j++){ if(tmp.contains(dsDetection[j].section("::::",0,0))){ fs = dsDetection[j].section("::::",1,1); break; } } } //qDebug() << " - File System:" << fs; }else if( info[i].contains("Volume name") ){ label = info[i].section("\"",1,1).section("\"",0,0).simplified(); //name is within quotes //qDebug() << " - Label:" << label; } //stop if all info found (size is always the first to be found in info) if(!fs.isEmpty() && !label.isEmpty()){ break; } } if( (blankDisk || (bytes.toInt()<2049) ) && (node.startsWith("cd") || node.startsWith("acd")) && label.isEmpty() && fs.isEmpty() ){ type = "CD-BLANK"; } if( (node.startsWith("cd")||node.startsWith("acd")) && (bytes.isEmpty()) ){ type = "CD-NONE"; } //Format the outputs //qDebug() << "Results:" << fs << label << type; return (QStringList() << fs << label << type); }
void MainWindow::getUsers() { QStringList users = runShellCommand("getent passwd"); mvUsers.clear(); exUserMenu->clear(); for(int i=0; i<users.length(); i++){ QString line = users[i]; if ((line.trimmed().indexOf("#") != 0) && (! line.isEmpty())) { //Make sure it isn't a comment or blank QString username = line.section(":",0,0); QString homedir = line.section(":",5,5); QString shell = line.section(":",6,6); //Ignore invalid users if(shell.contains("nologin") || homedir.contains("nonexistent") || homedir.endsWith("/empty") ){ continue; } // Ignore PEFS encrypted users if ( QFile::exists(homedir + "/.pefs.db") ) continue; int uid = line.section(":",2,2).toInt(); if(uid==0){ continue; } if ((uid>1000)&&(uid<65534)){ mvUsers.push_back(username); }else if(QFile::exists(homedir) && QFile::exists(shell)){ exUserMenu->addAction(username); } } } /*QFile userFile("/etc/passwd"); if ( userFile.open(QIODevice::ReadOnly) ) { QTextStream stream(&userFile); stream.setCodec("UTF-8"); QString line; while ( !stream.atEnd() ) { line = stream.readLine(); if ((line.trimmed().indexOf("#") != 0) && (! line.isEmpty())) { //Make sure it isn't a comment or blank QString username = line.section(":",0,0); QString homedir = line.section(":",5,5); // Ignore PEFS encrypted users if ( QFile::exists(homedir + "/.pefs.db") ) continue; int uid = line.section(":",2,2).toInt(); if ((uid>1000)&&(uid<65534)) mvUsers.push_back(username); }//if gout user }//for all lines }//if can open file*/ }
/** * Evaluates each command stored in the parser struct and exeutes either the runShellCommand * function or the runCommand function. * @param parser A constructed LashParser struct with fully populated commands * @return 0 if a command was "exit", 1 otherwise */ int executeCommand(struct LashParser *parser){ int i; int nextinput = -1; for(i = 0; i < parser->commandNum; i++){ struct Command *command = parser->commands[i]; int shellCommand = inArray(command->args[0], inbuiltCommands, NUMINBUILTCOMMANDS); if(shellCommand){ return runShellCommand(parser, command); } else if(strcmp(command->args[0], "") != 0){ nextinput = runCommand(command, nextinput); } } return 1; }
bool Backend::VerifyDevice(QString fulldev, QString type){ QString info = runShellCommand("file -s "+fulldev).join(""); if(info.contains( fulldev+": symbolic link to ")){ return false; } //do not allow symbolic links through if(type.startsWith("CD") || type=="USB" || type=="SATA" || type=="SD"){ bool good = info.simplified()!=(fulldev + ": data"); if(good){ good = !info.contains("(Device not configured)"); } //special output when nothing actually in the tray if(good && !type.startsWith("CD")){ good = !info.contains("(Invalid argument)"); } //other output when nothing actually in the tray return good; }else if(type=="ISO"){ return info.simplified()!=(fulldev+": data"); }else{ return true; //assume valid for other types of devices //(need to add parsing for new types here at a later date) } }
void MixerTray::slotFillOutputDevices() { soundOutput->clear(); QStringList outdevs = runShellCommand("cat /dev/sndstat"); for(int i=0; i<outdevs.length(); i++){ if(outdevs[i].startsWith("pcm")){ QAction* action = new QAction(soundOutput); action->setCheckable(true); action->setChecked(outdevs[i].contains(" default")); QString name = outdevs[i].trimmed(); name = name.mid(name.indexOf("<")+1, name.indexOf(">") - name.indexOf("<")-1); //name = name.left(name.lastIndexOf("(")); action->setText(name); action->setData(QVariant(outdevs[i].section(":",0,0))); //Select icon QString icon_path="output-unknown.png"; if (outdevs[i].toLower().indexOf("internal")>0) { icon_path="output-internal_speaker.png"; }else if ((outdevs[i].toLower().indexOf("rear")>0)) { icon_path="output-internal_speaker.png"; }else if ((outdevs[i].toLower().indexOf("headphones")>0)) { icon_path="output-headphones.png"; }else if ((outdevs[i].toLower().indexOf("hdmi")>0)) { icon_path="output-hdmi.png"; }else if ((outdevs[i].toLower().indexOf("usb")>0)) { icon_path="output-usb.png"; } icon_path = QString(":/icons/")+icon_path; action->setIcon(QIcon(icon_path)); if (outdevs[i].contains(" default")) soundOutput->setIcon(QIcon(icon_path)); connect(action, SIGNAL(triggered()), this, SLOT(slotOutputSelected())); soundOutput->addAction(action); }//if pcm device }// for all sound outputs); }
int main() { int SOCKET_FLAG = 0; char s[100]; printf("$ "); fflush(stdout); while(fgets ( s, sizeof(s), stdin ) != NULL) { // Call function and pass input command s with SOCKET_FLAG as argument runShellCommand(s, SOCKET_FLAG, 0); printf("$ "); fflush(stdout); } printf("\n"); return 0; }
QStringList Backend::getCurrentZFSDevices(QString pool){ //This lists all the raw devices associated with mounted zpools //Seperate them by different pools QStringList info = runShellCommand("zpool status "+pool).join("<br>").replace("\t"," ").split(" pool: "); QStringList output; for(int i=0; i<info.length(); i++){ //Now look at the info for this particular pool QStringList pinfo = info[i].split("<br>"); if(pinfo.length() < 5){ continue; } //not a full pool info (at least 5 lines - [pool:, id:, state:, action:, config:], usually more) QString pool = pinfo[0].simplified(); //this is how we divided it up earlier, with "pool:" as the first line pinfo = pinfo.filter("ONLINE"); //only look for available (ONLINE) pools to import for(int j=0; j<pinfo.length(); j++){ if(pinfo[j].contains("state: ONLINE")){ continue; } //skip this line QString dev = pinfo[j].section("ONLINE",0,0).simplified(); if(dev!=pool && QFile::exists("/dev/"+dev) ){ output << dev; } } } return output; }
void * shell(void *arg) { int connfd, n, n1, fdin; char command[MAXLINE], out_buf[MAXLINE]; pthread_t tid; char *output_file = malloc( sizeof(char) * 64 ); char *remove_file_cmd = malloc( sizeof(char) * 64 ); printf("SERVER: thread %u created for dealing with client requests\n", (unsigned int)tid,command); sprintf(output_file, "output_%u",(unsigned int)tid); tid = pthread_self(); connfd = *((int *) arg); free(arg); while ( (n = recv(connfd, command, MAXLINE,0)) > 0) { printf("client<%u>$ %s",(unsigned int)tid,command); if (strcmp(command, "\n")) { if (!strcmp(removeNewlineString(command), "exit")) { break; } runShellCommand(command, 1, connfd); memset(&command[0], 0, sizeof(command)); } else { write(connfd, "", 1); } } if (n < 0) printf("Command read error thread_id: %u\n", (unsigned int)tid); close(connfd); return((void *)0); }
bool MainWindow::setConfFileValue( QString oFile, QString oldKey, QString newKey, int occur ) { // Lets the dev save a value into a specified config file. // The occur value tells which occurance of "oldKey" to replace // If occur is set to -1, it will remove any duplicates of "oldKey" //copy the original file to create a temporary file for editing QString oFileTmp = oFile + ".tmp"; QString cmd = "cp "+oFile+" "+oFileTmp; runShellCommand(cmd); //Continue evaluating the temporary file QStringList SavedFile; int found = 1; // Load the old file, find the oldKey, remove it and replace with newKey QFile file( oFileTmp ); if ( ! file.open( QIODevice::ReadOnly ) ) return false; QTextStream stream( &file ); QString line; while ( !stream.atEnd() ) { line = stream.readLine(); // line of text excluding '\n' // Key is not found at all if ( line.indexOf(oldKey, 0) == -1 ) { SavedFile << line ; continue; } // Found the key, but it is commented out, so don't worry about this line if ( line.trimmed().indexOf("#", 0) == 0 ) { SavedFile << line ; continue; } // If the KEY is found, and we are just on wrong occurance, save it and continue to search if ( occur != -1 && found != occur ) { SavedFile << line ; found++; continue; } // If the KEY is found in the line and this matches the occurance that must be processed if ( ! newKey.isEmpty() && found == occur ) { SavedFile << newKey ; newKey.clear(); found++; continue; } // If the KEY is found and we just want one occurance of the key if ( occur == -1 && ! newKey.isEmpty() ) { SavedFile << newKey ; newKey.clear(); found++; continue; } } file.close(); // Didn't find the key? Write it! if ( ! newKey.isEmpty() ) SavedFile << newKey; // Save the new file QFile fileout( oFileTmp ); if ( ! fileout.open( QIODevice::WriteOnly ) ) return false; QTextStream streamout( &fileout ); for (int i = 0; i < SavedFile.size(); ++i) streamout << SavedFile.at(i) << "\n"; fileout.close(); //Have the temporary file with new changes overwrite the original file cmd = "mv "+oFileTmp+" "+oFile; runShellCommand(cmd); return true; }
void runShellCommand(const __FlashStringHelper* command, char * retbuffer, uint8_t size) { strlcpy_P(commonlyUsedBuffer,(prog_char *)command,commonlyUsedBuffersize); runShellCommand((char*) commonlyUsedBuffer, retbuffer, size); }
QString Backend::unmountRemDev(QString nodedir, bool force, bool internal){ //can use node *or* mntdir if(nodedir.startsWith("/dev/")){ nodedir = nodedir.section("/dev/",-1); } if(!internal){ updateIntMountPoints(); } QStringList found = IntMountPoints.filter(nodedir+DELIM); if(QFile::exists("/dev/"+nodedir)){ //node given if(nodedir.startsWith("md")){ //memory disk, might have a different node in the mounting log (get all entries) found.clear(); //going to rebuild this list with a different criteria QString shortnode = nodedir.section("p",0,0).section("s",0,0).simplified(); for(int i=0; i<IntMountPoints.length(); i++){ if(IntMountPoints[i].startsWith(nodedir+DELIM)){ found.prepend(IntMountPoints[i]); //exact match, put it at the top }else if(IntMountPoints[i].startsWith(shortnode)){ found << IntMountPoints[i]; //partial match (other partition/slice is mounted) } } } } QString mntdir, fs, user, dev; bool rmdir = false; if(found.length()>0){ dev=found[0].section(DELIM,0,0); mntdir=found[0].section(DELIM,2,2); rmdir = (found[0].section(DELIM,4,4)=="canremove"); fs = found[0].section(DELIM,1,1); user = found[0].section(DELIM, 3,3); }else if(QFile::exists(nodedir)){ mntdir = nodedir; rmdir = false; //not internally managed } if(mntdir.isEmpty()){ return ("[ERROR] Inputs Invalid: "+nodedir); } //Unmount the device QStringList cmds = DEVDB::UnmountCmdsForFS(fs, force); bool ok = true; QString errline; QString basedir = mntdir.section("/",0,-2); for(int i=0; i<cmds.length() && ok; i++){ cmds[i].replace("%1", "/dev/"+dev).replace("%2a", "\""+basedir+"\"").replace("%2b","\""+mntdir.section("/",-1)+"\"").replace("%2", "\""+mntdir+"\"").replace("%3", CLOCALE); if(cmds[i].contains("%4")){ cmds[i].replace("%4", runShellCommand("id -u "+CUSER).join("").simplified() ); } if(cmds[i].contains("%5")){ cmds[i].replace("%5", runShellCommand("id -g operator").join("").simplified() ); } ok = ( 0==QProcess::execute(cmds[i]) ); //return code of 0 means success if(!ok){ errline = "[ERROR] Command Run: "+cmds[i]; } } if(!ok && internal){ //force it anyway return unmountRemDev(nodedir, true, internal); } if( !ok ){ //Error unmounting the device if(!errline.isEmpty()){ return errline; } else{ return "[ERROR]"; } } //Remove the mount point (if necessary) if(rmdir){ QDir dir; dir.rmdir(mntdir); if(DEVDB::deviceTypeByNode(dev)=="ISO" && found.length()==1){ //Also unload the memory disk if the last partition/slice was just unmounted // NOTE: this only works with the main md device number (not partitions/slices) QProcess::execute("mdconfig -d -u "+dev.section("md",-1).section("p",0,0).section("s",0,0).simplified() ); } } //Now remove that entry from the internal list IntMountPoints.removeAll(found[0]); return "[SUCCESS]"; }
QString Backend::mountRemDev(QString node, QString mntdir, QString fs){ //See if we need to probe the device here and adjust inputs if(fs.toLower()=="none" || fs.toLower()=="auto"){ fs.clear(); } //special input flags if(mntdir.isEmpty() || fs.isEmpty()){ QStringList info = getRemDevInfo(node,!mntdir.isEmpty()); //<fs>,<label>,<type> //qDebug() << "Detected Info:" << info; if(info.length() > 2){ if(fs.isEmpty()){ fs = info[0]; } if(fs.isEmpty() && info[2].startsWith("CD-")){ fs = "CD9660"; } if(mntdir.isEmpty()){ if(info[1].isEmpty()){ //no label either, give it a generic label based on it's type info[1] = generateGenericLabel(info[2]); } //Assign a mountpoint for the device based on it's label QString tmp = "/media/"+info[1]; //put it in this base directory //Make sure to verify that the mountpoint does not already exist if(QFile::exists(tmp)){ int i=2; //this would technically be the second device with this label while( QFile::exists(tmp+"-"+QString::number(i)) ){ i++; } tmp = tmp+"-"+QString::number(i); } mntdir = tmp; } } //info length check } //Final check for valid inputs/detections if(!node.startsWith("/dev/") && fs.toLower()!="zfs"){ node.prepend("/dev/"); } if(fs.isEmpty() || fs.toLower()=="none"){ return ("[ERROR-0] No filesystem detected -- "+node); } if(!mntdir.startsWith("/")){ mntdir.prepend("/media/"); } // - mntdir will always be auto-created as necessary QDir dir(mntdir); //Verify Inputs if(!QFile::exists(node) && fs.toLower()!="zfs"){ return ("[ERROR-1] Invalid device node -- "+node); } else if(!DEVDB::isFSSupported(fs)){ return ("[ERROR-2] Filesystem not supported -- "+fs); } else if(dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).length() > 0){ return ("[ERROR-3] Mount point already in use -- "+mntdir); } //Create the directory if necessary bool dircreated = false; if(fs.toLower()=="zfs"){ dircreated = false; } //ZFS automatically handles the dir creation else if(!dir.exists()){ dircreated = dir.mkpath(mntdir); if(!dircreated){ return ("[ERROR-4] Mount point could not be created -- "+mntdir); } } //Now get the mounting commands for the device QStringList cmds = DEVDB::MountCmdsForFS(fs, CLOCALE!="en_US"); bool usedlocale = cmds.join(" ").contains("%3"); //Mount the device bool ok = true; bool done = false; QString errline; QString basedir = mntdir.section("/",0,-2); while(!done){ for(int i=0; i<cmds.length() && ok; i++){ //qDebug() << "Mountpoint:" << mntdir << basedir << mntdir.section("/",-1); cmds[i].replace("%1", node).replace("%2a", "\""+basedir+"\"").replace("%2b","\""+mntdir.section("/",-1)+"\"").replace("%2", "\""+mntdir+"\"").replace("%3", CLOCALE+".UTF-8"); if(cmds[i].contains("%4")){ cmds[i].replace("%4", runShellCommand("id -u "+CUSER).join("").simplified() ); } if(cmds[i].contains("%5")){ cmds[i].replace("%5", runShellCommand("id -g operator").join("").simplified() ); } ok = ( 0==QProcess::execute(cmds[i]) ); //look for a return code of 0 for success for the command if(!ok){ errline = " -- on command: "+cmds[i]; } } //Check for success and use any fallback methods if(!ok && usedlocale){ //Failure with custom locale - try it without the localization flags ok = true; usedlocale = false; //reset flags for next run cmds = DEVDB::MountCmdsForFS(fs, false); errline.clear(); }else{ done = true; } } //end with "done" loop if( !ok ){ //Error mounting the device dir.rmpath(mntdir); //clean up the unused mountpoint that was just created return ("[ERROR-5] Device could not be mounted -- "+node+" -- "+fs+" -- "+mntdir+errline); } //Now set permissions on the mount point (if just created) // NOTE: this chown usage is *NOT* recursive if(dircreated){ //Set 777 permissions QFile::setPermissions(mntdir, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser | QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther ); //Set the given user as the owner if(!CUSER.isEmpty()){ runShellCommand("chown "+CUSER+":operator \""+mntdir+"\""); } } //Now save this entry internally [node, filesystem, mntdir, user, (canremove/noremove), internal] node.remove("/dev/"); //only save the node IntMountPoints << node+DELIM+fs+DELIM+mntdir+DELIM+CUSER+DELIM+(dircreated ? "canremove": "noremove")+DELIM+"internal"; return ("[SUCCESS] "+mntdir); }
QStringList Backend::getCurrentZFSPools(){ //This just returns the names of all the currently used ZFS pools QStringList pools = runShellCommand("zpool list -H -o name"); return pools; }
unsigned int ApiClient::request() { return runShellCommand(request_buffer); }
QStringList Backend::getRemDevInfo(QString node, bool skiplabel){ //Overarching device info retrieval //Output: [FILESYSTEM, LABEL, TYPE] QStringList out; QString fs, label, type; if(node.startsWith("/dev/")){ node.remove("/dev/"); } if(!QFile::exists("/dev/"+node)){ // - Check if this is an available ZFS pool first (instead of a device node) QStringList zinfo = getAvailableZFSPools(); //qDebug() << " - Available ZFS Pools:" << zinfo; for(int i=0; i<zinfo.length(); i++){ if(zinfo[i].startsWith(node+"::::") ){ //First exact match for the pool - use this device for determining type fs = "ZFS"; label = node; type = DEVDB::deviceTypeByNode(zinfo[i].section("::::",1,1) ); return (QStringList() << fs << label << type); //already have everything necessary }else if(zinfo[i].endsWith("::::"+node)){ //First exact match for a device node - use this pool for output fs = "ZFS"; label = zinfo[i].section("::::",0,0); type = DEVDB::deviceTypeByNode(node); return (QStringList() << fs << label << type); //already have everything necessary } } } // - Quick finish if the device is already mounted // (same info - no need to re-probe the device and cause activity on it) updateIntMountPoints(); QStringList info = IntMountPoints.filter(node); for(int i=0; i<info.length(); i++){ if(info[i].startsWith(node+DELIM)){ //Already mounted - return the info from the internal database fs = info[i].section(DELIM,1,1).toUpper(); label = info[i].section(DELIM,2,2).section("/",-1); //mountpoint directory name if(fs.toUpper()=="ZFS"){ type = DEVDB::deviceTypeByNode( getCurrentZFSDevices(node).first() ); } else{ type = DEVDB::deviceTypeByNode(node); } return (QStringList() << fs << label << type); } } //Non-ZFS device given - try to figure it out // - Now determine the type by the name of the node (simple/fast) type = DEVDB::deviceTypeByNode(node); //qDebug() << "Device Type By Node:" << node << type; // - Run Disktype QStringList dtype = disktypeInfo(node); fs = dtype[0]; label = dtype[1]; if(!dtype[2].isEmpty()){ type = dtype[2]; } //replace type if necessary // - If CD/DVD, try to determine the full type (empty/audio/video/data) if(type=="CD"){ if(fs=="CD9660"){ type = "CD-DATA"; //data CD }else if(fs=="UDF"){ //Could be VIDEO (DVD/BlueRay) or DATA QStringList cdinfo = runShellCommand("cd-info --no-cddb --no-device-info --no-disc-mode --dvd --no-header -q /dev/"+node); if(cdinfo.filter("Track List").isEmpty()){ type = "CD-DATA"; } else{ type = "CD-VIDEO"; } //either dvd or blueray, no distinction at the moment }else{ //No filesystem, so it must be either nothing or an audio CD /*if( QFile::exists("/usr/local/bin/cdparanoia") ){ //cdparanoia is much better about not disturbing the cd if it is running than cd-info QStringList cdinfo = runShellCommand("cdparanoia -Q -d /dev/"+node); if( !cdinfo.filter("(audio tracks only)").isEmpty() ){ type = "CD-AUDIO"; } else{ type = "CD-NONE"; } }else{*/ QStringList cdinfo = runShellCommand("cdcontrol -f "+node+" status audio"); if( !cdinfo.filter("Audio status =").isEmpty() ){ type = "CD-AUDIO"; } else{ type = "CD-NONE"; } //The cd-info method is rather invasive, and takes a while to read the disk (causing delays in any app currently using it) /*QStringList cdinfo = runShellCommand("cd-info -T --no-cddb --no-device-info --no-disc-mode --dvd --no-header -q /dev/"+node); if( !cdinfo.filter("TRACK").filter("1").isEmpty() ){type = "CD-AUDIO"; } else{ type = "CD-NONE"; }*/ //} } } // - Determine the label using other tools if necessary //qDebug() << "End of disktype:" << node << dtype << fs << label << type; if(!skiplabel && label.isEmpty()){ //Run glabel/ntfslabel/other as needed if(fs=="NTFS"){ QStringList lab = runShellCommand("ntfslabel /dev/"+node); //qDebug() << "ntfslabel:" << node << lab; if(lab.length()==2 && lab[0].startsWith("Failed ") ){ label = lab[2]; } //special catch for Windows 8 else if(!lab.isEmpty()){ label = lab[0]; } //qDebug() << "label:" << label; }else{ QStringList labs = runShellCommand("glabel list "+node).filter("Name: "); if(labs.length() > 0){ labs[0] = labs[0].section(":",-1).section("/",-1).simplified(); if(!labs[0].isEmpty()){ label = labs[0]; } } } //Final check for getting a device label: camctl (based on type of device) if(label.isEmpty()){ QString camctl; if(type=="SATA"){ camctl = runShellCommand("camcontrol identify "+node.section("s",0,0) ).join(" "); }else if(type=="USB"){ camctl = runShellCommand("camcontrol inquiry "+node.section("s",0,0) ).join(" "); } if(camctl.contains("camcontrol")){ camctl.clear(); } //error reported if(!camctl.isEmpty()){ label = camctl.section(">",0,0).section("<",-1).section(" ",0,0).simplified(); if(!label.isEmpty() && node.contains("s")){ label.append("-"+node.section("s",-1)); } } } } if(label.isEmpty()){ label = generateGenericLabel(type); //final option - just create a generic name } label.replace("%20", " "); //this field code is often not replaced properly in glabel output if(fs.isEmpty()){ fs = "NONE"; } //Format the output out << fs << label << type; //qDebug() << " - done:" << out; return out; }
//REMOVABLE DEVICES (remdev) void Backend::updateIntMountPoints(){ //Format: //First run "mount" to make sure and get the complete list of mounted devices QStringList info = runShellCommand("mount"); QStringList zinfo = runShellCommand("zpool list -H -o name,altroot"); //qDebug() << "zpool list:" << zinfo; //Verify that the current entries are still valid for(int i=0; i<IntMountPoints.length(); i++){ QString node = IntMountPoints[i].section(DELIM,0,0); QString fs = IntMountPoints[i].section(DELIM,1,1).toLower(); if(!node.isEmpty() && !node.startsWith("/dev/") && fs!="zfs"){ node.prepend("/dev/"); } QString mntdir = IntMountPoints[i].section(DELIM,2,2); bool invalid = false; if(!node.isEmpty() && ( (!QFile::exists(node) && fs!="zfs") || (fs=="zfs" && zinfo.filter(node).isEmpty()) )){ invalid = true; if( info.filter(mntdir).length()==1 ){ //This is the only entry for this mounttpoint (don't have multiple things mounted on the same dir) qDebug() << "Unmounting directory:" << mntdir; //Device unplugged while it was mounted, unmount it unmountRemDev(mntdir, false, true); //this is an internal change (no user interaction) //Need to be careful about the internal list, since the unmount routine can modify it // better to just restart at the beginning again and stop here updateIntMountPoints(); return; } } else if(mntdir.isEmpty()){ invalid = true; } //required for unmounting else if( info.filter(mntdir).isEmpty() ){ //not currently listed by "mount" qDebug() << "Mount Dir not listed as active - checking for removal:" << mntdir; QDir dir(mntdir); if(!dir.exists()){ invalid = true; } else if( dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).length() < 1 && info.filter(mntdir).isEmpty() ){ invalid = true; if( IntMountPoints[i].section(DELIM,4,4)=="canremove" ){ //Unmounted some other way - still clean up the old mountpoint dir.rmdir(mntdir); } } } if(invalid){ //Remove this entry from the list qDebug() << "Removing Internal Mount Info:" << IntMountPoints[i]; IntMountPoints.removeAt(i); i--; } } //Parse the mount info and find anything that was mounted externally QStringList fsfilter = DEVDB::knownFilesystems(); for(int i=0; i<info.length(); i++){ //filter out unknown filesystems QString fs = info[i].section("(",1,1).section(",",0,0); if(fs=="msdosfs"){ fs="fat"; } //special catch for an alternate display if( !fsfilter.contains(fs.toUpper()) || fs=="zfs" ){ continue; } else if( info[i].contains(" /boot/") || info[i].contains("personahome.eli") ){ continue; } //skip any boot devices or home dirs QString mpoint = info[i].section(" on ",1,50).section(" (",0,0); if(!mpoint.isEmpty() && IntMountPoints.filter(DELIM+mpoint+DELIM).isEmpty()){ //Externally Mounted device: add it to the internal list QString node = info[i].section(" on ",0,0); if(!node.startsWith("/dev/")){ node.clear(); } //not a valid device node: just skip this else{ node.remove("/dev/"); //Make sure this is not an active device node (for the currently running OS partition) if(CPART.contains(node)){ continue; } } IntMountPoints << node+DELIM+fs+DELIM+mpoint+DELIM+""+DELIM+"noremove"+DELIM+"external"; qDebug() << "New Internal Mount Info:" << IntMountPoints.last(); } } }