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 }