180 | | Originally I thought to just used lshw to gather most of the information, but this doesn't really gain us any thing since I would have to resort to the other tools (lsusb and lspci) to find the relevant entries in lshw output (and would require a huge rewrite of the gatherer). Lshw can output in a few diffrent ways. I'm currently using the direct line by line approach to search for the uuid. I did however experiment with the -xml output. When combined with XmlSimple.xml_in() |
181 | | |
| 180 | Originally I thought to just used lshw to gather most of the information, but this doesn't really gain us any thing since I would have to resort to the other tools (lsusb and lspci) to find the relevant entries in lshw output (and would require a huge rewrite of the gatherer). Lshw can output in a few diffrent ways. I'm currently using the direct line by line approach to search for the uuid. I did however experiment with the -xml output. When imported with !XmlSimple.xml_in(), we get a massive hash/array structure that contains all the data elements as either a value in a hash or a item in an array. To find what we're looking for we need a recursive tool to extract the relevant data structures. An example was written in titled ''lshw_recursion_example.rb'' |
| 181 | the main recursive tool keeps calling the each method of every sub-element (hashes and arrays both have an each method, they behave differently, thus a check for class is needed first). |
| 182 | |
| 183 | One snag that was "hacked" in was that if we find the keyword in an array if we push the containing data type, all we get is an array with that keyword. I resolved this by passing the previous data structure as a parameter. If the keyword is found in a hash I store the hash, if it's found in an array, I store the previous hash. I opted to hunt for an list of words instead of a single one. Its more efficient than iterating across the entire structure multiple times for each word. We don't iterate through the words for every element, just the ones that are the termination of a branch. This saves a lot of computation and prevents a few type errors. Its assumed that the word list is significantly smaller than the size of the hash. Some example code: |
| 184 | |
| 185 | {{{ |
| 186 | found = Hash.new() |
| 187 | def hunt (dat,words,found,prev=nil) |
| 188 | #check the type |
| 189 | if dat.kind_of?(Array): |
| 190 | dat.each do |v| |
| 191 | #iterate over the current type and check for an instance the words |
| 192 | words.each {|w| found.store(w,prev) if /#{w}/.match(v)} if v.kind_of?(String) |
| 193 | |
| 194 | #recursively call the function on the children of this data structre |
| 195 | #note the parent is passed as a parameter as the array branch needs to store the container |
| 196 | hunt(v,words,found,dat) |
| 197 | end |
| 198 | elsif dat.kind_of?(Hash) |
| 199 | dat.each do |k,v| |
| 200 | #same deal as the array cept we have a key,value combo, and we can store the current data |
| 201 | #data structure. We still need to pass the parent as a parameter since we don't know |
| 202 | #what type the child is |
| 203 | words.each {|w| found.store(w,dat) if /#{w}/.match(v)} if v.kind_of?(String) |
| 204 | hunt(v,words,found,dat) |
| 205 | end |
| 206 | end |
| 207 | }}} |
| 208 | |