bool DevCheck::devInfo(QString dev, QString* type, QString* label, QString* filesystem, QString* maxsize){ //OUTPUT: bool isGoodDevice //INPUTS/OUTPUTS: type, label, filesystem, maxsize //INPUT: dev = device node (da0, not /dev/da0) //Clear the output variables type->clear(); label->clear(); filesystem->clear(); maxsize->clear(); //make sure to have both the full path and just node QString node; QString fullDev; if(dev.startsWith(DEVICEDIR)){ fullDev = dev; node = dev.section("/",-1); } else{ node = dev; fullDev = DEVICEDIR + dev; } //Do not allow sym-links if(!QFile::symLinkTarget(fullDev).isEmpty()){ return FALSE; } //Do not allow currently active devices if(activeDevs.contains(node)){ return FALSE; } //Double check for valid device types (just in case) QString detType; for(int i=0; i<validDevs.length(); i++){ if(node.startsWith(validDevs[i]) && node != "mdctl"){ detType = validDevTypes[i]; break; } } //Make sure it is a no-child device (except memory disks or CD's, those need to be the parent) int children = devChildren(node).length(); if( !node.startsWith("md") && detType!="CD9660" && detType!="ISO" && children>0 ){ return FALSE; } //Make sure we quit before running commands on any invalid device nodes if(detType.isEmpty() || !QFile::exists(fullDev) ){return FALSE;} //Get the camctl info and refine the device type if possible QString camctl; if(detType == "USB" && QFile::exists(fullDev)){ //make sure that it is not a SCSI device camctl = pcbsd::Utils::runShellCommand( QString("camcontrol inquiry ")+node.section("s",0,0) ).join(" "); if(camctl.contains(" Fixed Direct Access SCSI")){ detType = "SCSI"; } if(camctl.contains("camcontrol")){ camctl.clear(); } //error or invalid device type }else if(detType == "SATA" && QFile::exists(fullDev)){ camctl = pcbsd::Utils::runShellCommand( QString("camcontrol identify ")+node.section("s",0,0) ).join(" "); if(camctl.contains("camcontrol")){ camctl.clear(); } //error or invalid device type } if(!camctl.isEmpty()){ //Alternate Device name for label later (if needed) camctl = camctl.section(">",0,0).section("<",-1).section(" ",0,0).simplified(); QString partition = node.section("s",1,1); if(!partition.isEmpty()){ camctl.append("-"+partition); } } //Save the device type type->append(detType); bool isCD= (detType == "CD9660" || detType == "ISO"); //simplification for later //Run either "file -s" or "disktype" to get device info bool valid = false; QString fs, dlabel; if(QFile::exists("/usr/local/bin/disktype")){ valid = getDiskInfo(fullDev, &fs, &dlabel); }else{ // "file -s" should always work - use it as the backup method valid = getSpecialFileInfo(fullDev, &fs, &dlabel); } if(detType=="ISO" && fs.isEmpty() ){ valid = false; } //skip ISO's with unknown filesystems (swap, etc) else if(detType=="CD9660" && fs.isEmpty() ){ //Try to determine which type of cd/dvd this is since it is not a data disk (which can be mounted) fs = "AVDISK"; //audio/video disk (not mountable) } if(!valid){ //don't bother continuing - already invalid if(DEBUG_MODE){ qDebug() << "Invalid Device:" << node << detType << dlabel << fs; } return FALSE; } //If the filesystem could not be detected or is not supported if(fs.isEmpty()){ fs = "UNKNOWN"; } //Now get the device label (if there is one) using glabel QString glabel; //Don't use glabel for SATA devices right now because it is inconsistent if(!isCD){ glabel = devLabel(node, fs); } //Check to see if we have a label, otherwise assign one if( !glabel.isEmpty() ){ dlabel = glabel; } //glabel else if(!dlabel.isEmpty()){ } //device info label else if( !camctl.isEmpty() ){ dlabel = camctl; } //camcontrol device ID else{ //Assign a device label if(isCD){ if(detType == "ISO"){ dlabel = "ISO_File"; }else{ dlabel = "Optical_Disk"; } }else{ dlabel = detType+"-Device"; //this is not a "detected" label } } //make sure that a device label does not contain "(" or ")" if(dlabel.contains("(")){ dlabel = dlabel.remove("(").simplified(); } if(dlabel.contains(")")){ dlabel = dlabel.remove(")").simplified(); } dlabel = dlabel.simplified(); //Setup the outputs label->append(dlabel); filesystem->append(fs); return valid; }
bool DevCheck::devInfo(QString dev, QString* type, QString* label, QString* filesystem, QString* maxsize){ //OUTPUT: bool isGoodDevice //INPUTS/OUTPUTS: type, label, filesystem, maxsize //INPUT: dev = device node (da0, not /dev/da0) //Clear the output variables type->clear(); label->clear(); filesystem->clear(); maxsize->clear(); //make sure to have both the full path and just node QString node; QString fullDev; if(dev.startsWith(DEVICEDIR)){ fullDev = dev; node = dev.section("/",-1); } else{ node = dev; fullDev = DEVICEDIR + dev; } //Do not allow sym-links if(!QFile::symLinkTarget(fullDev).isEmpty()){ return FALSE; } //Double check for valid device types (just in case) QString detType; for(int i=0; i<validDevs.length(); i++){ if(node.startsWith(validDevs[i]) && node != "mdctl"){ detType = validDevTypes[i]; break; } } QString camctl; if(detType == "USB" && QFile::exists(fullDev)){ //make sure that it is not a SCSI device camctl = pcbsd::Utils::runShellCommand( QString("camcontrol inquiry ")+node ).join(" "); if(camctl.contains(" Fixed Direct Access SCSI")){ detType = "SCSI"; } //USB devices do not have any output if(camctl.contains("camcontrol")){ camctl.clear(); } //error or invalid device type } //Make sure we quit before running commands on any invalid device nodes if(detType.isEmpty() || !QFile::exists(fullDev) ){return FALSE;} else{type->append(detType);} bool isCD=FALSE; if(detType == "CD9660" || detType == "ISO"){ isCD=TRUE; } //Read the Device Info using "file -s <device>" QString cmd = "file -s "+fullDev; QString output = pcbsd::Utils::runShellCommand(cmd).join(" "); //if(isCD){ qDebug() << "File -s output:" << output; } // ** Get the max storage size ** int kb = 0; bool hasPartitions = FALSE; bool isMounted = FALSE; if( !isCD ){ QStringList tmp = output.split(","); if( !tmp.filter("partition ").isEmpty() ){ //Check for actual sub-devices (*s[#][a/b/c/....]) if( devChildren(node).length() > 0 ){ hasPartitions = TRUE; } } if( !tmp.filter("last mounted on /").isEmpty() && (detType == "SATA")){ isMounted = TRUE; } //Now try to get the size of the disk if( !tmp.filter("number of data blocks").isEmpty() ){ tmp = tmp.filter("number of data blocks"); kb = tmp[0].remove("number of data blocks").simplified().toInt(); }else if( !tmp.filter("number of blocks").isEmpty() ){ tmp = tmp.filter("number of blocks"); kb = tmp[0].remove("number of blocks").simplified().toInt(); }else if( !tmp.filter("hidden sectors").isEmpty()){ tmp = tmp.filter("hidden sectors"); kb = tmp[0].remove("hidden sectors").simplified().toInt(); }else if( !tmp.filter("sectors").isEmpty()){ tmp = tmp.filter("sectors"); //qDebug() << "Det Sectors line:"<<tmp; int num=0; for(int i=0; i<tmp.length(); i++){ int n = tmp[i].remove("sectors").section("(",0,0).simplified().toInt(); if(n > num){ num = n; } } kb = num; }else{ kb = -1; } } //end non-CD size and isMounted detection bool oksize = (kb > 0); //First try to get the device label using the "file -s" output QString dlabel; if(isCD){ if( !output.contains("ERROR:") ){ dlabel = output.section("'",-2).remove("'").simplified(); if(dlabel.contains("(")){ dlabel = dlabel.left(dlabel.indexOf("(")+1).trimmed();} } }else{ dlabel = output.section("label: \"",1,1).section("\"",0,0).simplified(); //device name } // - trim the label out of the output line for filesystem type detection QString devFSsec, devFSsec2; if(!isCD){ devFSsec = output.section("label:",0,0); devFSsec2 = output.section("label:",1,3).section(",",1,1,QString::SectionSkipEmpty); }else{ devFSsec = output.simplified(); } // ** Find the filesystem type for the device ** QString filesys; for(int i=0; i<fsDetection.length(); i++){ if(devFSsec.contains(fsDetection[i]) || devFSsec2.contains(fsDetection[i]) ){ filesys = fsMatch[i]; } } //If the filesystem could not be detected or is not supported bool hasFS = TRUE; if(filesys.isEmpty()){ filesys = "UNKNOWN"; hasFS=FALSE; } //Now get the device label (if there is one) using glabel bool hasLabel = FALSE; QString glabel; if(!isCD){ glabel = devLabel(node, filesys); } //Check to see if we have a label, otherwise assign one if( !glabel.isEmpty() ){ dlabel = glabel; hasLabel = TRUE; } //glabel else if(!dlabel.isEmpty()){ hasLabel = TRUE; } //file -s label else if( !camctl.isEmpty() ){ //not necessarily a "detected" label, but just an alternate fallback name dlabel = camctl.section(">",0,0).section("<",-1).section(" ",0,0).simplified(); }else{ //Assign a device label if(isCD){ if(detType == "ISO"){ dlabel = "ISO_File"; }else{ dlabel = "Optical_Disk"; } }else{ dlabel = detType+"-Device"; //this is not a "detected" label } } //make sure that a device label does not contain "(" or ")" if(dlabel.contains("(")){ dlabel.remove("(").simplified(); } if(dlabel.contains(")")){ dlabel.remove(")").simplified(); } dlabel = dlabel.simplified(); //Now perform the final checks to see if it is a good device bool good = FALSE; if( isMounted ){}//Always ignore this device (local FreeBSD installation that is being used) else if( hasPartitions ){} //Ignore devices that have partitions accessible as seperate devices else if( hasFS && isCD ){ good = TRUE; } //CD/DVD data disks don't have as much info //Allow devices that match 2 of the 3 criteria else if( hasFS && oksize ){ good = TRUE; } //This will catch most good devices else if( hasLabel && oksize ){ good = TRUE; } //allow unknown filesystems if there is a good size reading else if( hasFS && hasLabel ){ good = TRUE; } // allow device if it has a known label and filesystem //Now setup the outputs as appropriate maxsize->append( QString::number(kb) ); label->append(dlabel); filesystem->append(filesys); if(!good){ qDebug() << "Invalid Device:" << node << detType << dlabel << filesys << kb; if(DEBUG_MODE){qDebug() << " -Detected Flags:" << isMounted << hasPartitions << hasLabel << hasFS << oksize;} } return good; }