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

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

Use ntfslabel instead of glabel for NTFS formatted devices when looking for a device label in the mounttray.

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