Back to index

lshw  02.16
mounts.cc
Go to the documentation of this file.
00001 /*
00002  * mounts.cc
00003  *
00004  *
00005  */
00006 
00007 #include "version.h"
00008 #include "mounts.h"
00009 #include "osutils.h"
00010 #include <vector>
00011 #include <iostream>
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <unistd.h>
00017 
00018 
00019 __ID("@(#) $Id: mounts.cc 2433 2012-01-10 22:01:30Z lyonel $");
00020 
00021 #define MOUNTS "/proc/mounts"
00022 
00023 static bool has_device(const string & dev, hwNode & n)
00024 {
00025   string devid = get_devid(dev);
00026   vector <string> lnames;
00027   size_t i;
00028 
00029   if(devid == "")
00030     return false;
00031 
00032   if(get_devid(dev) == n.getDev())
00033     return true;
00034 
00035   lnames = n.getLogicalNames();
00036   for(i=0; i<lnames.size(); i++)
00037   {
00038     if(get_devid(lnames[i]) == devid)
00039       return true;
00040   }
00041   return false;
00042 }
00043 
00044 // unescape octal-encoded "special" characters:
00045 //  "/this\040is\040a\040test" --> "/this is a test"
00046 
00047 static string unescape(string s)
00048 {
00049   size_t backslash = 0;
00050   string result = s;
00051   
00052   while((backslash=result.find('\\', backslash)) != string::npos)
00053   {
00054     string code = result.substr(backslash+1,3);
00055     if(matches(code, "^[0-9][0-9][0-9]$"))
00056     {
00057       result[backslash] = (char)strtol(code.c_str(), NULL, 8); // value is octal
00058       result.erase(backslash+1,3);
00059     }
00060     backslash++;
00061   }
00062 
00063   return result;
00064 }
00065 
00066 static void update_mount_status(hwNode & n, const vector <string> & mount)
00067 {
00068   unsigned i;
00069 
00070   if(has_device(mount[0], n))
00071   {
00072     n.setConfig("state", "mounted");
00073     n.setLogicalName(mount[1]);           // mountpoint
00074     n.setConfig("mount.fstype", mount[2]);
00075     n.setConfig("mount.options", mount[3]);
00076   }
00077 
00078   for(i=0; i<n.countChildren(); i++)
00079     update_mount_status(*n.getChild(i), mount);
00080 }
00081 
00082 static bool process_mount(const string & s, hwNode & n)
00083 {
00084   vector <string> mount;
00085   struct stat buf;
00086 
00087   // entries' format is
00088   // devicenode mountpoint fstype mountoptions dumpfrequency pass
00089   if(splitlines(s, mount, ' ') != 6)
00090   {
00091     mount.clear();
00092     if(splitlines(s, mount, '\t') != 6)
00093       return false;
00094   }
00095 
00096   mount[0] = unescape(mount[0]);
00097   mount[1] = unescape(mount[1]);
00098 
00099   if(mount[0][0] != '/')    // devicenode isn't a full path
00100     return false;
00101 
00102   if(stat(mount[0].c_str(), &buf) != 0)
00103     return false;
00104 
00105   if(!S_ISBLK(buf.st_mode)) // we're only interested in block devices
00106     return false;
00107 
00108   update_mount_status(n, mount);
00109 
00110   return true;
00111 }
00112 
00113 bool scan_mounts(hwNode & n)
00114 {
00115   vector <string> mounts;
00116   size_t i;
00117 
00118   if(!loadfile(MOUNTS, mounts))
00119     return false;
00120 
00121   for(i=0; i<mounts.size(); i++)
00122     process_mount(mounts[i], n);
00123 
00124   return true;
00125 }