/ src / core / mounts.cc
mounts.cc
  1  /*
  2   * mounts.cc
  3   *
  4   *
  5   */
  6  
  7  #include "version.h"
  8  #include "mounts.h"
  9  #include "osutils.h"
 10  #include <vector>
 11  #include <iostream>
 12  #include <sys/types.h>
 13  #include <sys/stat.h>
 14  #include <stdlib.h>
 15  #include <string.h>
 16  #include <unistd.h>
 17  #include <cstdlib>
 18  
 19  __ID("@(#) $Id$");
 20  
 21  #define MOUNTS "/proc/mounts"
 22  
 23  static bool has_device(const string & dev, hwNode & n)
 24  {
 25    string devid = get_devid(dev);
 26    vector <string> lnames;
 27    size_t i;
 28  
 29    if(devid == "")
 30      return false;
 31  
 32    if(get_devid(dev) == n.getDev())
 33      return true;
 34  
 35    lnames = n.getLogicalNames();
 36    for(i=0; i<lnames.size(); i++)
 37    {
 38      if(get_devid(lnames[i]) == devid)
 39        return true;
 40    }
 41    return false;
 42  }
 43  
 44  // unescape octal-encoded "special" characters:
 45  //  "/this\040is\040a\040test" --> "/this is a test"
 46  
 47  static string unescape(string s)
 48  {
 49    size_t backslash = 0;
 50    string result = s;
 51    
 52    while((backslash=result.find('\\', backslash)) != string::npos)
 53    {
 54      string code = result.substr(backslash+1,3);
 55      if(matches(code, "^[0-9][0-9][0-9]$"))
 56      {
 57        result[backslash] = (char)strtol(code.c_str(), NULL, 8); // value is octal
 58        result.erase(backslash+1,3);
 59      }
 60      backslash++;
 61    }
 62  
 63    return result;
 64  }
 65  
 66  static void update_mount_status(hwNode & n, const vector <string> & mount)
 67  {
 68    unsigned i;
 69  
 70    if(has_device(mount[0], n))
 71    {
 72      n.setConfig("state", "mounted");
 73      n.setLogicalName(mount[1]);		// mountpoint
 74      n.setConfig("mount.fstype", mount[2]);
 75      n.setConfig("mount.options", mount[3]);
 76    }
 77  
 78    for(i=0; i<n.countChildren(); i++)
 79      update_mount_status(*n.getChild(i), mount);
 80  }
 81  
 82  static bool process_mount(const string & s, hwNode & n)
 83  {
 84    vector <string> mount;
 85    struct stat buf;
 86  
 87    // entries' format is
 88    // devicenode mountpoint fstype mountoptions dumpfrequency pass
 89    if(splitlines(s, mount, ' ') != 6)
 90    {
 91      mount.clear();
 92      if(splitlines(s, mount, '\t') != 6)
 93        return false;
 94    }
 95  
 96    mount[0] = unescape(mount[0]);
 97    mount[1] = unescape(mount[1]);
 98  
 99    if(mount[0][0] != '/')	// devicenode isn't a full path
100      return false;
101  
102    if(stat(mount[0].c_str(), &buf) != 0)
103      return false;
104  
105    if(!S_ISBLK(buf.st_mode))	// we're only interested in block devices
106      return false;
107  
108    update_mount_status(n, mount);
109  
110    return true;
111  }
112  
113  bool scan_mounts(hwNode & n)
114  {
115    vector <string> mounts;
116    size_t i;
117  
118    if(!loadfile(MOUNTS, mounts))
119      return false;
120  
121    for(i=0; i<mounts.size(); i++)
122      process_mount(mounts[i], n);
123  
124    return true;
125  }