source: src-qt4/pc-mounttray/devCheck.cpp @ 03aedf0

9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 03aedf0 was 03aedf0, checked in by Ken Moore <ken@…>, 8 months ago

Setup the pc-mounttray to allow for mounting a *.iso file via memory disk. This option is available under the "Load ISO File" option in the menu. Once the ISO file is unmounted, the memory disk is also detached from the system.

  • Property mode set to 100644
File size: 8.2 KB
Line 
1#include <pcbsd-utils.h>
2#include "devCheck.h"
3
4
5DevCheck::DevCheck(){
6  //Initialize the lists of valid device types
7  validDevs << "da" << "ad" << "mmcsd" << "cd" << "acd" << "md";
8  validDevTypes << "USB" << "SATA" << "SD" << "CD9660" << "CD9660" << "ISO";
9  for(int i=0; i<validDevs.length(); i++){
10    devFilter << validDevs[i]+"*";
11  }
12  //Initialize lists of filesystems and detection strings
13  fsDetection.clear();
14  fsMatch.clear();
15  fsDetection << "FAT" << "NTFS" << "EXT" << "ISO 9660" << "Unix Fast File system" << "Reiser" << "XFS"; //string to match for a particular filesystem
16  fsMatch << "FAT" << "NTFS" << "EXT" << "CD9660" << "UFS" << "REISERFS" << "XFS"; //internal labels for the filesystems
17  fsFilter << "fat" << "ntfs" << "ext" << "cdrom" << "ufs" << "reiser" << "xfs"; //label categories in /dev/
18  //Initialize the device directory
19  devDir = QDir(DEVICEDIR);
20}
21
22DevCheck::~DevCheck(){
23}
24
25/*
26  PUBLIC FUNCTIONS
27*/
28
29bool DevCheck::isValid(QString node){
30  bool ok = FALSE;
31  for(int i=0; i<validDevs.length(); i++){
32    if(node.startsWith(validDevs[i]) && node!="mdctl"){ 
33        ok = TRUE; 
34        break; 
35    }
36  }
37  return ok;
38}
39
40QStringList DevCheck::devChildren(QString node){
41  devDir.cd(DEVICEDIR);
42  QStringList subdevs;
43  if(node.isEmpty()){
44    subdevs = devDir.entryList(devFilter, QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::System, QDir::NoSort);
45  }else{
46    subdevs = devDir.entryList(QStringList(node+"*"), QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::System, QDir::NoSort);
47  }
48  //Clean up the list of children
49  for(int i=0; i<subdevs.length(); i++){
50    if( (subdevs[i] == node) || subdevs[i].isEmpty() ){
51      subdevs.removeAt(i);
52      i--;
53    }
54  }
55  return subdevs;
56}
57
58QString DevCheck::devLabel(QString node, QString filesystem){
59  QString dlabel;
60  QStringList glout = pcbsd::Utils::runShellCommand("glabel list");
61  int index = glout.indexOf("Geom name: "+node);
62  while(index != -1){
63    for(int i=index; i<glout.length(); i++){ 
64      if(glout[i].contains("Name: ")){ index = i; break;} //should only be 1 or 2 lines to find this
65    }
66    if(index == -1){ break; } //quick check to make sure we don't error out
67    QString path = glout[index].section("Name:",1,10,QString::SectionSkipEmpty).simplified(); 
68    int fschk = fsMatch.indexOf(filesystem);
69    if(fschk != -1){
70      if(fsFilter[fschk] == path.section("/",0,0).simplified() ){
71        //good label
72        dlabel = path.section("/",-1).simplified();
73        break;
74      }
75    }
76    index = glout.indexOf("Geom name: "+node, index); //move to the next index if there is one
77  }
78  return dlabel;
79}
80
81bool DevCheck::devInfo(QString dev, QString* type, QString* label, QString* filesystem, QString* maxsize){
82  //OUTPUT: bool isGoodDevice
83  //INPUTS/OUTPUTS: type, label, filesystem, maxsize
84  //INPUT: dev = device node (da0, not /dev/da0)
85       
86  //Clear the output variables
87  type->clear(); label->clear(); filesystem->clear(); maxsize->clear();
88  //make sure to have both the full path and just node
89  QString node;
90  QString fullDev;
91  if(dev.startsWith(DEVICEDIR)){ fullDev = dev; node = dev.section("/",-1); }
92  else{ node = dev; fullDev = DEVICEDIR + dev; }
93  //Do not allow sym-links
94  if(!QFile::symLinkTarget(fullDev).isEmpty()){ return FALSE; }
95 
96  //Double check for valid device types (just in case)
97  QString detType;
98  for(int i=0; i<validDevs.length(); i++){
99    if(node.startsWith(validDevs[i]) && node != "mdctl"){ 
100        detType = validDevTypes[i]; 
101        break; 
102    }
103  }
104 
105  //Make sure we quit before running commands on any invalid device nodes
106  if(detType.isEmpty() || !QFile::exists(fullDev) ){return FALSE;}
107  else{type->append(detType);}
108  bool isCD=FALSE;
109  if(detType == "CD9660" || detType == "ISO"){ isCD=TRUE; }
110 
111  //Read the Device Info using "file -s <device>"
112  QString cmd = "file -s "+fullDev;
113  QString output = pcbsd::Utils::runShellCommand(cmd).join(" ");
114  //if(isCD){ qDebug() << "File -s output:" << output; }
115 
116  // ** Get the max storage size **
117  int kb = 0;
118  bool hasPartitions = FALSE; 
119  bool isMounted = FALSE;
120  if( !isCD ){
121    QStringList tmp = output.split(",");
122    if( !tmp.filter("partition ").isEmpty() ){
123      //Check for actual sub-devices (*s[#][a/b/c/....])
124      if( devChildren(node).length() > 1 ){ hasPartitions = TRUE; } //the main device will always make it length 1
125    }
126    if( !tmp.filter("last mounted on /").isEmpty() && (detType == "SATA")){
127      isMounted = TRUE;
128    }
129    //Now try to get the size of the disk
130    if( !tmp.filter("number of data blocks").isEmpty() ){
131      tmp = tmp.filter("number of data blocks");
132      kb = tmp[0].remove("number of data blocks").simplified().toInt();
133    }else if( !tmp.filter("number of blocks").isEmpty() ){
134      tmp = tmp.filter("number of blocks");
135      kb = tmp[0].remove("number of blocks").simplified().toInt();
136    }else if( !tmp.filter("hidden sectors").isEmpty()){
137      tmp = tmp.filter("hidden sectors");
138      kb = tmp[0].remove("hidden sectors").simplified().toInt();
139    }else if( !tmp.filter("sectors").isEmpty()){
140      tmp = tmp.filter("sectors");
141      //qDebug() << "Det Sectors line:"<<tmp;
142      int num=0;
143      for(int i=0; i<tmp.length(); i++){
144        int n = tmp[i].remove("sectors").section("(",0,0).simplified().toInt();
145        if(n > num){ num = n; }
146      }
147      kb = num;
148    }else{ kb = -1; }
149  } //end non-CD size and isMounted detection
150  bool oksize = (kb > 0);
151  //First try to get the device label using the "file -s" output
152  QString dlabel;
153  if(isCD){
154    if( !output.contains("ERROR:") ){
155      dlabel = output.section("'",-2).remove("'").simplified();
156      if(dlabel.contains("(")){ dlabel = dlabel.left(dlabel.indexOf("(")+1).trimmed();}
157    }
158  }else{
159   dlabel = output.section("label: \"",1,1).section("\"",0,0).simplified(); //device name
160  }
161  // - trim the label out of the output line for filesystem type detection
162  QString devFSsec, devFSsec2;
163  if(!isCD){
164    devFSsec = output.section("label:",0,0);
165    devFSsec2 = output.section("label:",1,3).section(",",1,1,QString::SectionSkipEmpty);
166  }else{
167    devFSsec = output.simplified();       
168  }
169  // ** Find the filesystem type for the device **
170  QString filesys;
171  for(int i=0; i<fsDetection.length(); i++){
172    if(devFSsec.contains(fsDetection[i]) || devFSsec2.contains(fsDetection[i]) ){
173      filesys = fsMatch[i]; 
174    }
175  }
176  //If the filesystem could not be detected or is not supported
177  bool hasFS = TRUE;
178  if(filesys.isEmpty()){ filesys = "UNKNOWN"; hasFS=FALSE; }
179 
180  //Now get the device label (if there is one) using glabel
181  bool hasLabel = FALSE;
182  QString glabel;
183  if(!isCD){ glabel = devLabel(node, filesys); }
184  //Check to see if we have a label, otherwise assign one
185  if( !glabel.isEmpty() ){ dlabel = glabel; hasLabel = TRUE; } //glabel
186  else if(!dlabel.isEmpty()){ hasLabel = TRUE; } //file -s label
187  else{
188    //Assign a device label
189    if(isCD){
190      if(detType == "ISO"){
191        dlabel = "ISO_File";
192      }else{
193        dlabel = "Optical_Disk";
194      }
195    }else{
196      dlabel = detType+"-Device"; //this is not a "detected" label
197    }
198  }
199  //make sure that a device label does not contain "(" or ")"
200  if(dlabel.contains("(")){ dlabel.remove("(").simplified(); }
201  if(dlabel.contains(")")){ dlabel.remove(")").simplified(); }
202  dlabel = dlabel.simplified();
203  //Now perform the final checks to see if it is a good device
204  bool good = FALSE;
205  if( isMounted ){}//Always ignore this device (local FreeBSD installation that is being used)
206  else if( hasPartitions ){} //Ignore devices that have partitions accessible as seperate devices
207  else if( hasFS && isCD ){ good = TRUE; } //CD/DVD data disks don't have as much info
208  //Allow devices that match 2 of the 3 criteria
209  else if( hasFS && oksize ){ good = TRUE; } //This will catch most good devices
210  else if( hasLabel && oksize ){ good = TRUE; } //allow unknown filesystems if there is a good size reading
211  else if( hasFS && hasLabel ){ good = TRUE; } // allow device if it has a known label and filesystem
212 
213  //Now setup the outputs as appropriate
214  maxsize->append( QString::number(kb) );
215  label->append(dlabel);
216  filesystem->append(filesys);
217 
218  if(!good){
219    qDebug() << "Invalid Device:" << node << detType << dlabel << filesys << kb; 
220    if(DEBUG_MODE){qDebug() << " -Detected Flags:" << isMounted << hasPartitions << hasLabel << hasFS << oksize;} 
221  }
222  return good;
223}
224
225/*
226  PRIVATE FUNCTIONS
227*/
228
229
Note: See TracBrowser for help on using the repository browser.