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

releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since e417b8a was e417b8a, checked in by Ken Moore <ken@…>, 11 months ago

Clean up the device naming scheme in the mount tray:
1) Do not use glabel for NTFS devices (when mounted through fuse glabel is not consistent in giving the label)
2) Use device's camcontrol identifyier for SATA devices as well as USB devices. This should provide a more specific name than "SATA-Device".
3) For a camcontrol name, append "-" followed by the partition number (so ada0s1a will have a "-1a" appended to the end. Again, this should help devices have unique names.

  • Property mode set to 100644
File size: 9.4 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" << "da";
8  validDevTypes << "USB" << "SATA" << "SD" << "CD9660" << "CD9660" << "ISO" << "SCSI";
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 = devDir.entryList(devFilter, QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::System, QDir::NoSort);
43  //Clean up the list of children
44  for(int i=0; i<subdevs.length(); i++){
45    if( (subdevs[i] == node) || subdevs[i].isEmpty() || !subdevs[i].startsWith(node) ){
46      subdevs.removeAt(i);
47      i--;
48    }
49  }
50  //qDebug() << "[DEBUG] " <<node << "Device Children:" << subdevs;
51  return subdevs;
52}
53
54QString DevCheck::devLabel(QString node, QString filesystem){
55  QString dlabel;
56  QStringList glout = pcbsd::Utils::runShellCommand("glabel list");
57  int index = glout.indexOf("Geom name: "+node);
58  while(index != -1){
59    for(int i=index; i<glout.length(); i++){ 
60      if(glout[i].contains("Name: ")){ index = i; break;} //should only be 1 or 2 lines to find this
61    }
62    if(index == -1){ break; } //quick check to make sure we don't error out
63    QString path = glout[index].section("Name:",1,10,QString::SectionSkipEmpty).simplified(); 
64    int fschk = fsMatch.indexOf(filesystem);
65    if(fschk != -1){
66      if(fsFilter[fschk] == path.section("/",0,0).simplified() ){
67        //good label
68        dlabel = path.section("/",-1).simplified();
69        break;
70      }
71    }
72    index = glout.indexOf("Geom name: "+node, index); //move to the next index if there is one
73  }
74  dlabel.replace("%20", " "); //quick check to make sure it does not have that special character
75  return dlabel;
76}
77
78bool DevCheck::devInfo(QString dev, QString* type, QString* label, QString* filesystem, QString* maxsize){
79  //OUTPUT: bool isGoodDevice
80  //INPUTS/OUTPUTS: type, label, filesystem, maxsize
81  //INPUT: dev = device node (da0, not /dev/da0)
82       
83  //Clear the output variables
84  type->clear(); label->clear(); filesystem->clear(); maxsize->clear();
85  //make sure to have both the full path and just node
86  QString node;
87  QString fullDev;
88  if(dev.startsWith(DEVICEDIR)){ fullDev = dev; node = dev.section("/",-1); }
89  else{ node = dev; fullDev = DEVICEDIR + dev; }
90  //Do not allow sym-links
91  if(!QFile::symLinkTarget(fullDev).isEmpty()){ return FALSE; }
92 
93  //Double check for valid device types (just in case)
94  QString detType;
95  for(int i=0; i<validDevs.length(); i++){
96    if(node.startsWith(validDevs[i]) && node != "mdctl"){ 
97        detType = validDevTypes[i]; 
98        break; 
99    }
100  }
101  QString camctl;
102  if(detType == "USB" && QFile::exists(fullDev)){
103    //make sure that it is not a SCSI device
104    camctl = pcbsd::Utils::runShellCommand( QString("camcontrol inquiry ")+node.section("s",0,0) ).join(" ");
105    if(camctl.contains(" Fixed Direct Access SCSI")){ detType = "SCSI"; }
106    if(camctl.contains("camcontrol")){ camctl.clear(); } //error or invalid device type
107  }else if(detType == "SATA" && QFile::exists(fullDev)){
108    camctl = pcbsd::Utils::runShellCommand( QString("camcontrol identify ")+node.section("s",0,0) ).join(" ");
109    if(camctl.contains("camcontrol")){ camctl.clear(); } //error or invalid device type
110  }
111  if(!camctl.isEmpty()){
112    //Alternate Device name for label later
113    camctl = camctl.section(">",0,0).section("<",-1).section(" ",0,0).simplified();
114    QString partition = node.section("s",1,1);
115    if(!partition.isEmpty()){ camctl.append("-"+partition); }
116  }
117  //Make sure we quit before running commands on any invalid device nodes
118  if(detType.isEmpty() || !QFile::exists(fullDev) ){return FALSE;}
119  else{type->append(detType);}
120  bool isCD=FALSE;
121  if(detType == "CD9660" || detType == "ISO"){ isCD=TRUE; }
122 
123  //Read the Device Info using "file -s <device>"
124  QString cmd = "file -s "+fullDev;
125  QString output = pcbsd::Utils::runShellCommand(cmd).join(" ");
126  //if(isCD){ qDebug() << "File -s output:" << output; }
127 
128  // ** Get the max storage size **
129  int kb = 0;
130  bool hasPartitions = FALSE; 
131  bool isMounted = FALSE;
132  if( !isCD ){
133    QStringList tmp = output.split(",");
134    //if( !tmp.filter("partition ").isEmpty() ){
135      //Check for actual sub-devices (*s[#][a/b/c/....])
136      if( devChildren(node).length() > 0 ){ hasPartitions = TRUE; }
137    //}
138    if( !tmp.filter("last mounted on /").isEmpty() && (detType == "SATA")){
139      isMounted = TRUE;
140    }
141    //Now try to get the size of the disk
142    if( !tmp.filter("number of data blocks").isEmpty() ){
143      tmp = tmp.filter("number of data blocks");
144      kb = tmp[0].remove("number of data blocks").simplified().toInt();
145    }else if( !tmp.filter("number of blocks").isEmpty() ){
146      tmp = tmp.filter("number of blocks");
147      kb = tmp[0].remove("number of blocks").simplified().toInt();
148    }else if( !tmp.filter("hidden sectors").isEmpty()){
149      tmp = tmp.filter("hidden sectors");
150      kb = tmp[0].remove("hidden sectors").simplified().toInt();
151    }else if( !tmp.filter("sectors").isEmpty()){
152      tmp = tmp.filter("sectors");
153      //qDebug() << "Det Sectors line:"<<tmp;
154      int num=0;
155      for(int i=0; i<tmp.length(); i++){
156        int n = tmp[i].remove("sectors").section("(",0,0).simplified().toInt();
157        if(n > num){ num = n; }
158      }
159      kb = num;
160    }else{ kb = -1; }
161  } //end non-CD size and isMounted detection
162  bool oksize = (kb > 0);
163  //First try to get the device label using the "file -s" output
164  QString dlabel;
165  if(isCD){
166    if( !output.contains("ERROR:") ){
167      dlabel = output.section("'",-2).remove("'").simplified();
168      if(dlabel.contains("(")){ dlabel = dlabel.left(dlabel.indexOf("(")+1).trimmed();}
169    }
170  }else{
171   dlabel = output.section("label: \"",1,1).section("\"",0,0).simplified(); //device name
172  }
173  // - trim the label out of the output line for filesystem type detection
174  QString devFSsec, devFSsec2;
175  if(!isCD){
176    devFSsec = output.section("label:",0,0);
177    devFSsec2 = output.section("label:",1,3).section(",",1,1,QString::SectionSkipEmpty);
178  }else{
179    devFSsec = output.simplified();       
180  }
181  // ** Find the filesystem type for the device **
182  QString filesys;
183  for(int i=0; i<fsDetection.length(); i++){
184    if(devFSsec.contains(fsDetection[i]) || devFSsec2.contains(fsDetection[i]) ){
185      filesys = fsMatch[i]; 
186    }
187  }
188  //If the filesystem could not be detected or is not supported
189  bool hasFS = TRUE;
190  if(filesys.isEmpty()){ filesys = "UNKNOWN"; hasFS=FALSE; }
191 
192  //Now get the device label (if there is one) using glabel
193  bool hasLabel = FALSE;
194  QString glabel;
195  //Don't use glabel for SATA devices right now because it is inconsistent
196  if(!isCD && filesys!="NTFS"){ glabel = devLabel(node, filesys); }
197  //Check to see if we have a label, otherwise assign one
198  if( !glabel.isEmpty() ){ dlabel = glabel; hasLabel = TRUE; } //glabel
199  else if(!dlabel.isEmpty()){ hasLabel = TRUE; } //file -s label
200  else if( !camctl.isEmpty() ){ 
201    //not necessarily a "detected" label, but just an alternate fallback name
202    dlabel = camctl;
203  }else{
204    //Assign a device label
205    if(isCD){
206      if(detType == "ISO"){
207        dlabel = "ISO_File";
208      }else{
209        dlabel = "Optical_Disk";
210      }
211    }else{
212      dlabel = detType+"-Device"; //this is not a "detected" label
213    }
214  }
215  //make sure that a device label does not contain "(" or ")"
216  if(dlabel.contains("(")){ dlabel = dlabel.remove("(").simplified(); }
217  if(dlabel.contains(")")){ dlabel = dlabel.remove(")").simplified(); }
218  dlabel = dlabel.simplified();
219  //Now perform the final checks to see if it is a good device
220  bool good = FALSE;
221  if( isMounted ){}//Always ignore this device (local FreeBSD installation that is being used)
222  else if( hasPartitions ){} //Ignore devices that have partitions accessible as seperate devices
223  else if( hasFS && isCD ){ good = TRUE; } //CD/DVD data disks don't have as much info
224  //Allow devices that match 2 of the 3 criteria
225  else if( hasFS && oksize ){ good = TRUE; } //This will catch most good devices
226  else if( hasLabel && oksize ){ good = TRUE; } //allow unknown filesystems if there is a good size reading
227  else if( hasFS && hasLabel ){ good = TRUE; } // allow device if it has a known label and filesystem
228 
229  //Now setup the outputs as appropriate
230  maxsize->append( QString::number(kb) );
231  label->append(dlabel);
232  filesystem->append(filesys);
233 
234  if(!good){
235    qDebug() << "Invalid Device:" << node << detType << dlabel << filesys << kb; 
236    if(DEBUG_MODE){qDebug() << " -Detected Flags:" << isMounted << hasPartitions << hasLabel << hasFS << oksize;} 
237  }
238  return good;
239}
240
241/*
242  PRIVATE FUNCTIONS
243*/
244
245
Note: See TracBrowser for help on using the repository browser.