linux_stat 0.7.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +542 -312
- data/exe/linuxstat.rb +34 -13
- data/ext/fs_stat/fs_stat.c +9 -2
- data/ext/nproc/extconf.rb +11 -0
- data/ext/nproc/nproc.c +31 -0
- data/ext/sysconf/sysconf.c +78 -11
- data/ext/utsname/utsname.c +26 -14
- data/lib/linux_stat.rb +8 -1
- data/lib/linux_stat/battery.rb +183 -20
- data/lib/linux_stat/cpu.rb +222 -41
- data/lib/linux_stat/filesystem.rb +12 -12
- data/lib/linux_stat/kernel.rb +1 -1
- data/lib/linux_stat/mounts.rb +4 -4
- data/lib/linux_stat/os.rb +2 -2
- data/lib/linux_stat/prettify_bytes.rb +1 -4
- data/lib/linux_stat/process.rb +1 -1
- data/lib/linux_stat/process_info.rb +124 -18
- data/lib/linux_stat/swap.rb +1 -1
- data/lib/linux_stat/usb.rb +192 -0
- data/lib/linux_stat/version.rb +1 -1
- metadata +6 -2
data/lib/linux_stat/os.rb
CHANGED
@@ -121,7 +121,7 @@ module LinuxStat
|
|
121
121
|
hour: h,
|
122
122
|
minute: m,
|
123
123
|
second: s
|
124
|
-
}
|
124
|
+
}.freeze
|
125
125
|
end
|
126
126
|
|
127
127
|
private
|
@@ -143,7 +143,7 @@ module LinuxStat
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def uptime_readable?
|
146
|
-
@@uptime_readable
|
146
|
+
@@uptime_readable ||= File.readable?('/proc/uptime')
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
@@ -100,10 +100,7 @@ module LinuxStat
|
|
100
100
|
|
101
101
|
private
|
102
102
|
def pad_left(n, mantissa_length = 2)
|
103
|
-
|
104
|
-
exp, mant = n.to_s.split(?..freeze)
|
105
|
-
m = mant.length < mantissa_length ? mant + ?0.freeze * (mantissa_length - mant.length) : mant
|
106
|
-
exp + ?..freeze + m
|
103
|
+
sprintf("%.#{mantissa_length}f".freeze, n)
|
107
104
|
end
|
108
105
|
end
|
109
106
|
end
|
data/lib/linux_stat/process.rb
CHANGED
@@ -203,13 +203,13 @@ module LinuxStat
|
|
203
203
|
end
|
204
204
|
|
205
205
|
##
|
206
|
-
# = cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
206
|
+
# = cpu_stat(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
|
207
207
|
#
|
208
208
|
# Where pid is the process ID and sleep time is the interval between measurements.
|
209
209
|
#
|
210
210
|
# By default it is the id of the current process ($$), and sleep is LinuxStat::Sysconf.sc_clk_tck
|
211
211
|
#
|
212
|
-
# The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck.
|
212
|
+
# The smallest amount of available sleep time is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5.
|
213
213
|
#
|
214
214
|
# * Note 1:
|
215
215
|
# 1. Do note that the sleep time can slow down your application.
|
@@ -244,20 +244,22 @@ module LinuxStat
|
|
244
244
|
# Only use this method if you need all of the data at once, in such case, it's more efficient to use this method.
|
245
245
|
#
|
246
246
|
# The :last_executed_cpu also returns an Integer indicating the last executed cpu of the process.
|
247
|
-
def cpu_stat(pid: $$, sleep:
|
247
|
+
def cpu_stat(pid: $$, sleep: ticks_to_ms_t5)
|
248
248
|
file = "/proc/#{pid}/stat"
|
249
|
-
return {} unless File.readable?(file)
|
250
|
-
|
251
249
|
ticks = get_ticks
|
252
250
|
|
251
|
+
return {} unless File.readable?(file)
|
253
252
|
utime, stime, starttime = IO.read(file)
|
254
253
|
.split.values_at(13, 14, 21).map(&:to_f)
|
254
|
+
|
255
255
|
uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
|
256
256
|
|
257
257
|
total_time = utime + stime
|
258
258
|
idle1 = uptime - starttime - total_time
|
259
259
|
|
260
260
|
sleep(sleep)
|
261
|
+
|
262
|
+
return {} unless File.readable?(file)
|
261
263
|
stat = IO.read(file).split
|
262
264
|
|
263
265
|
utime2, stime2, starttime2 = stat.values_at(13, 14, 21).map(&:to_f)
|
@@ -267,25 +269,25 @@ module LinuxStat
|
|
267
269
|
idle2 = uptime - starttime2 - total_time2
|
268
270
|
|
269
271
|
totald = idle2.+(total_time2).-(idle1 + total_time)
|
270
|
-
|
272
|
+
cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
|
271
273
|
|
272
274
|
{
|
273
|
-
cpu_usage:
|
275
|
+
cpu_usage: cpu_u > 100 ? 100.0 : cpu_u.round(2),
|
274
276
|
threads: stat[19].to_i,
|
275
277
|
last_executed_cpu: stat[38].to_i
|
276
278
|
}
|
277
279
|
end
|
278
280
|
|
279
281
|
##
|
280
|
-
# = cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
282
|
+
# = cpu_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
|
281
283
|
#
|
282
284
|
# Where pid is the process ID and sleep time is the interval between measurements.
|
283
285
|
#
|
284
|
-
# By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck
|
286
|
+
# By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
|
285
287
|
#
|
286
288
|
# The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
|
287
289
|
#
|
288
|
-
# It retuns the CPU usage
|
290
|
+
# It retuns the CPU usage as Float.
|
289
291
|
#
|
290
292
|
# For example:
|
291
293
|
#
|
@@ -293,19 +295,75 @@ module LinuxStat
|
|
293
295
|
#
|
294
296
|
# => 10.0
|
295
297
|
#
|
298
|
+
# 10.0 means it's using 10% of the total processing power of the system.
|
299
|
+
#
|
300
|
+
# The value is divided with the configured number of CPU and not online CPU.
|
301
|
+
#
|
296
302
|
# A value of 100.0 indicates it is using 100% processing power available to the system.
|
297
303
|
#
|
298
304
|
# But if the info isn't available, it will return nil.
|
299
305
|
#
|
300
306
|
# This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
|
301
|
-
def cpu_usage(pid: $$, sleep:
|
307
|
+
def cpu_usage(pid: $$, sleep: ticks_to_ms_t5)
|
302
308
|
file = "/proc/#{pid}/stat"
|
309
|
+
ticks = get_ticks
|
310
|
+
|
303
311
|
return nil unless File.readable?(file)
|
312
|
+
utime, stime, starttime = IO.read(file)
|
313
|
+
.split.values_at(13, 14, 21).map(&:to_f)
|
314
|
+
|
315
|
+
uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
|
316
|
+
|
317
|
+
total_time = utime + stime
|
318
|
+
idle1 = uptime - starttime - total_time
|
319
|
+
|
320
|
+
sleep(sleep)
|
304
321
|
|
322
|
+
return nil unless File.readable?(file)
|
323
|
+
utime2, stime2, starttime2 = IO.read(file)
|
324
|
+
.split.values_at(13, 14, 21).map(&:to_f)
|
325
|
+
|
326
|
+
uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
|
327
|
+
|
328
|
+
total_time2 = utime2 + stime2
|
329
|
+
idle2 = uptime - starttime2 - total_time2
|
330
|
+
|
331
|
+
totald = idle2.+(total_time2).-(idle1 + total_time)
|
332
|
+
|
333
|
+
u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
|
334
|
+
u > 100 ? 100.0 : u.round(2)
|
335
|
+
end
|
336
|
+
|
337
|
+
##
|
338
|
+
# = thread_usage(pid: $$, sleep: 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
|
339
|
+
#
|
340
|
+
# Where pid is the process ID and sleep time is the interval between measurements.
|
341
|
+
#
|
342
|
+
# By default it is the id of the current process ($$), and sleep is 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
|
343
|
+
#
|
344
|
+
# The smallest amount of available sleep time is LinuxStat::Sysconf.sc_clk_tck.
|
345
|
+
#
|
346
|
+
# It retuns the per core CPU usage as Float.
|
347
|
+
#
|
348
|
+
# For example:
|
349
|
+
#
|
350
|
+
# LinuxStat::ProcessInfo.core_usage
|
351
|
+
#
|
352
|
+
# => 200.0
|
353
|
+
#
|
354
|
+
# A value of 100.0 indicates it is using 100% processing power of a core.
|
355
|
+
#
|
356
|
+
# The value could be 0 to (100 * the number of CPU threads (including hyperthreading) in the system)
|
357
|
+
#
|
358
|
+
# But if the info isn't available, it will return nil.
|
359
|
+
def thread_usage(pid: $$, sleep: ticks_to_ms_t5)
|
360
|
+
file = "/proc/#{pid}/stat"
|
305
361
|
ticks = get_ticks
|
306
362
|
|
363
|
+
return nil unless File.readable?(file)
|
307
364
|
utime, stime, starttime = IO.read(file)
|
308
365
|
.split.values_at(13, 14, 21).map(&:to_f)
|
366
|
+
|
309
367
|
uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
|
310
368
|
|
311
369
|
total_time = utime + stime
|
@@ -313,15 +371,21 @@ module LinuxStat
|
|
313
371
|
|
314
372
|
sleep(sleep)
|
315
373
|
|
374
|
+
return nil unless File.readable?(file)
|
316
375
|
utime2, stime2, starttime2 = IO.read(file)
|
317
376
|
.split.values_at(13, 14, 21).map(&:to_f)
|
377
|
+
|
318
378
|
uptime = IO.read('/proc/uptime'.freeze).to_f * ticks
|
319
379
|
|
320
380
|
total_time2 = utime2 + stime2
|
321
381
|
idle2 = uptime - starttime2 - total_time2
|
322
382
|
|
323
383
|
totald = idle2.+(total_time2).-(idle1 + total_time)
|
324
|
-
|
384
|
+
|
385
|
+
u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
|
386
|
+
|
387
|
+
cpu_count_t100 = cpu_count * 100
|
388
|
+
u > cpu_count_t100 ? cpu_count_t100 : u.round(2)
|
325
389
|
end
|
326
390
|
|
327
391
|
##
|
@@ -491,7 +555,9 @@ module LinuxStat
|
|
491
555
|
# For example:
|
492
556
|
# LinuxStat::ProcessInfo.running_time 14183
|
493
557
|
#
|
494
|
-
# => 1947.
|
558
|
+
# => 1947.61
|
559
|
+
#
|
560
|
+
# It always rounds the float number upto 2 decimal places
|
495
561
|
#
|
496
562
|
# If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
|
497
563
|
def running_time(pid = $$)
|
@@ -501,7 +567,8 @@ module LinuxStat
|
|
501
567
|
@@u_readable ||= File.readable?(uptime)
|
502
568
|
return nil unless @@u_readable && File.readable?(stat_file)
|
503
569
|
|
504
|
-
IO.foreach(uptime, ' '.freeze).next.to_f
|
570
|
+
IO.foreach(uptime, ' '.freeze).next.to_f
|
571
|
+
.-(IO.read(stat_file).split[21].to_f / get_ticks).round(2)
|
505
572
|
end
|
506
573
|
|
507
574
|
##
|
@@ -544,18 +611,57 @@ module LinuxStat
|
|
544
611
|
IO.foreach(file, ' ').first(19)[-1].to_i
|
545
612
|
end
|
546
613
|
|
614
|
+
##
|
615
|
+
# = nproc(pid = $$)
|
616
|
+
# Returns the cpu allocated to the process.
|
617
|
+
#
|
618
|
+
# The output value is an Integer.
|
619
|
+
#
|
620
|
+
# For example:
|
621
|
+
# $ taskset -c 0 irb
|
622
|
+
#
|
623
|
+
# irb(main):001:0> require 'linux_stat'
|
624
|
+
#
|
625
|
+
# => true
|
626
|
+
#
|
627
|
+
# irb(main):002:0> LinuxStat::ProcessInfo.nproc
|
628
|
+
#
|
629
|
+
# => 1
|
630
|
+
#
|
631
|
+
# irb(main):003:0> LinuxStat::ProcessInfo.nproc 11562
|
632
|
+
#
|
633
|
+
# => 3
|
634
|
+
#
|
635
|
+
# irb(main):004:0> LinuxStat::ProcessInfo.nproc 12513
|
636
|
+
#
|
637
|
+
# => 4
|
638
|
+
#
|
639
|
+
# If the info isn't available or the argument passed doesn't exist as a process ID, it will return nil.
|
640
|
+
def nproc(pid = $$)
|
641
|
+
LinuxStat::Nproc.count_cpu_for_pid(pid)
|
642
|
+
end
|
643
|
+
|
644
|
+
alias count_cpu nproc
|
645
|
+
|
547
646
|
private
|
548
647
|
def get_ticks
|
549
|
-
@@
|
648
|
+
@@sc_clk_tck ||= LinuxStat::Sysconf.sc_clk_tck
|
649
|
+
@@ticks ||= @@sc_clk_tck < 1 ? 100 : @@sc_clk_tck
|
550
650
|
end
|
551
651
|
|
552
652
|
# Just to avoid multiple calculations!...
|
553
|
-
|
554
|
-
|
653
|
+
# ticks to ms * 5
|
654
|
+
# If ticks is 100, it will return 0.05
|
655
|
+
def ticks_to_ms_t5
|
656
|
+
@@ms_t5 ||= 1.0 / get_ticks * 5
|
555
657
|
end
|
556
658
|
|
557
659
|
def pagesize
|
558
|
-
@@pagesize ||= LinuxStat::Sysconf.pagesize
|
660
|
+
@@pagesize ||= LinuxStat::Sysconf.pagesize.to_i
|
661
|
+
end
|
662
|
+
|
663
|
+
def cpu_count
|
664
|
+
@@nprocessors_conf ||= LinuxStat::CPU.count
|
559
665
|
end
|
560
666
|
end
|
561
667
|
end
|
data/lib/linux_stat/swap.rb
CHANGED
@@ -0,0 +1,192 @@
|
|
1
|
+
module LinuxStat
|
2
|
+
module USB
|
3
|
+
class << self
|
4
|
+
##
|
5
|
+
# = devices_stat(hwdata: true)
|
6
|
+
#
|
7
|
+
# Returns details about the devices found in /sys/bus/usb/devices/
|
8
|
+
#
|
9
|
+
# The return value is an Array of multiple Hashes. If there's no info available,
|
10
|
+
# it will rather return an empty Array.
|
11
|
+
#
|
12
|
+
# On Android Termux for example, it can not list the directories because they are
|
13
|
+
# not readable the the regular user.
|
14
|
+
#
|
15
|
+
# It can have information like:
|
16
|
+
#
|
17
|
+
# id, vendor id, product id, manufacturer, serial, bus number, dev number,
|
18
|
+
# b_max_power, b_max_packet_size, etc.
|
19
|
+
#
|
20
|
+
# An example of the returned sample from a test machine is:
|
21
|
+
# LinuxStat::USB.devices_stat
|
22
|
+
#
|
23
|
+
# [{:path=>"/sys/bus/usb/devices/1-1.2/", :id=>"04d9:1203", :vendor_id=>"04d9", :product_id=>"1203", :bus_num=>1, :dev_num=>4, :hwdata=>{:vendor=>"Holtek Semiconductor, Inc.", :product=>"Keyboard"}, :authorized=>true, :b_max_power=>"100mA", :b_max_packet_size0=>8}
|
24
|
+
#
|
25
|
+
# Right, it's an array of Hashes.
|
26
|
+
#
|
27
|
+
# It also takes one option. The hwdata, which is true by default.
|
28
|
+
#
|
29
|
+
# Information about usb devices is found inside /usr/share/hwdata/usb.ids
|
30
|
+
#
|
31
|
+
# The data contains the vendor and the product.
|
32
|
+
#
|
33
|
+
# If the option is enabled, it will try look at /usr/share/hwdata/usb.ids
|
34
|
+
#
|
35
|
+
# But the file will be read only once. The consecutive calls to this method
|
36
|
+
# won't open the hwdata all the times.
|
37
|
+
#
|
38
|
+
# But if there's no hwdata, the Hash returned by this method will not contain
|
39
|
+
# hwdata key.
|
40
|
+
#
|
41
|
+
# The data is only populated if it's available. For example, if there's no
|
42
|
+
# manufacturer available for the product, the returned Hash will not contain the
|
43
|
+
# information about the manufacturer.
|
44
|
+
#
|
45
|
+
# Also note that if there's no info available or no USB devices, it will return an empty
|
46
|
+
# Hash.
|
47
|
+
def devices_stat(hwdata: true)
|
48
|
+
@@sys_usb_readable ||= File.readable?('/sys/bus/usb/devices/')
|
49
|
+
return [] unless @@sys_usb_readable
|
50
|
+
|
51
|
+
Dir['/sys/bus/usb/devices/*/'.freeze].sort!.map! { |x|
|
52
|
+
id_vendor_file = File.join(x, 'idVendor'.freeze)
|
53
|
+
next unless File.readable?(id_vendor_file)
|
54
|
+
id_vendor = IO.read(id_vendor_file).strip
|
55
|
+
|
56
|
+
id_product_file = File.join(x, 'idProduct'.freeze)
|
57
|
+
next unless File.readable?(id_vendor_file)
|
58
|
+
id_product = IO.read(id_product_file).strip
|
59
|
+
|
60
|
+
bus_num_file = File.join(x, 'busnum'.freeze)
|
61
|
+
bus_num = File.readable?(bus_num_file) ? IO.read(bus_num_file).strip : ''.freeze
|
62
|
+
|
63
|
+
dev_num_file = File.join(x, 'devnum'.freeze)
|
64
|
+
dev_num = File.readable?(dev_num_file) ? IO.read(dev_num_file).strip : ''.freeze
|
65
|
+
|
66
|
+
serial_file = File.join(x, 'serial'.freeze)
|
67
|
+
serial = File.readable?(serial_file) ? IO.read(serial_file).strip : ''.freeze
|
68
|
+
|
69
|
+
product_file = File.join(x, 'product'.freeze)
|
70
|
+
product = File.readable?(product_file) ? IO.read(product_file).strip : ''.freeze
|
71
|
+
|
72
|
+
manufacturer_file = File.join(x, 'manufacturer'.freeze)
|
73
|
+
manufacturer = File.readable?(manufacturer_file) ? IO.read(manufacturer_file).strip : ''.freeze
|
74
|
+
|
75
|
+
removable_file = File.join(x, 'removable'.freeze)
|
76
|
+
removable = File.readable?(removable_file) ? IO.read(removable_file).strip : ''.freeze
|
77
|
+
|
78
|
+
authorized_file = File.join(x, 'authorized'.freeze)
|
79
|
+
authorized = File.readable?(authorized_file) ? IO.read(authorized_file).to_i : ''.freeze
|
80
|
+
|
81
|
+
b_max_power_file = File.join(x, 'bMaxPower'.freeze)
|
82
|
+
b_max_power = File.readable?(b_max_power_file) ? IO.read(b_max_power_file).strip : ''.freeze
|
83
|
+
|
84
|
+
b_max_packet_size0_file = File.join(x, 'bMaxPacketSize0'.freeze)
|
85
|
+
b_max_packet_size0 = File.readable?(b_max_packet_size0_file) ? IO.read(b_max_packet_size0_file).to_i : ''.freeze
|
86
|
+
|
87
|
+
query = hwdata ? query_hwdata(id_vendor, id_product) : {}
|
88
|
+
|
89
|
+
removable.downcase!
|
90
|
+
is_removable = if removable == 'removable'.freeze
|
91
|
+
true
|
92
|
+
elsif removable == 'unknown'.freeze
|
93
|
+
nil
|
94
|
+
else
|
95
|
+
false
|
96
|
+
end
|
97
|
+
|
98
|
+
ret = {
|
99
|
+
path: x, id: "#{id_vendor}:#{id_product}",
|
100
|
+
vendor_id: id_vendor, product_id: id_product
|
101
|
+
}
|
102
|
+
|
103
|
+
ret.merge!(bus_num: bus_num.to_i) unless bus_num.empty?
|
104
|
+
ret.merge!(dev_num: dev_num.to_i) unless dev_num.empty?
|
105
|
+
|
106
|
+
ret.merge!(serial: serial) unless serial.empty?
|
107
|
+
|
108
|
+
ret.merge!(hwdata: query) unless query.empty?
|
109
|
+
ret.merge!(product: product) unless product.empty?
|
110
|
+
ret.merge!(manufacturer: manufacturer) unless manufacturer.empty?
|
111
|
+
|
112
|
+
ret.merge!(removable: is_removable) unless is_removable.nil?
|
113
|
+
ret.merge!(authorized: authorized == 1)
|
114
|
+
|
115
|
+
ret.merge!(b_max_power: b_max_power) unless b_max_power.empty?
|
116
|
+
ret.merge!(b_max_packet_size0: b_max_packet_size0) if b_max_packet_size0
|
117
|
+
}.tap(&:compact!)
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Opens /sys/bus/usb/devices, and counts the total number of
|
122
|
+
# devices connected to the USB interface.
|
123
|
+
# The return type is an integer.
|
124
|
+
#
|
125
|
+
# It checks for devices with vendor and product id file.
|
126
|
+
# If there's no such file, it will not count them as a USB device.
|
127
|
+
#
|
128
|
+
# It could be also an integrated hub or a webcam, as well as
|
129
|
+
# external hotpluggable devices like printer, USB storage devices,
|
130
|
+
# USB mouse, USB keyboard, USB joypad etc.
|
131
|
+
#
|
132
|
+
# But if the information isn't available, it will return nil.
|
133
|
+
def count
|
134
|
+
@@sys_usb_readable ||= File.readable?('/sys/bus/usb/devices/')
|
135
|
+
return [] unless @@sys_usb_readable
|
136
|
+
|
137
|
+
Dir['/sys/bus/usb/devices/*/'.freeze].count { |x|
|
138
|
+
id_vendor_file = File.join(x, 'idVendor'.freeze)
|
139
|
+
id_product_file = File.join(x, 'idProduct'.freeze)
|
140
|
+
File.readable?(id_vendor_file) && File.readable?(id_product_file)
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
alias count_devices count
|
145
|
+
|
146
|
+
private
|
147
|
+
def hwdata
|
148
|
+
@@hwdata_file ||= "/usr/share/hwdata/usb.ids"
|
149
|
+
|
150
|
+
@@hwdata ||= if File.readable?(@@hwdata_file)
|
151
|
+
file_data = IO.readlines(@@hwdata_file, encoding: 'ASCII-8BIT')
|
152
|
+
ret, vendor_id = {}, nil
|
153
|
+
|
154
|
+
i = -1
|
155
|
+
file_data_size = file_data.size
|
156
|
+
|
157
|
+
while (i += 1) < file_data_size
|
158
|
+
x = file_data[i]
|
159
|
+
|
160
|
+
_lstripped = x.lstrip
|
161
|
+
next if _lstripped == ?#.freeze || _lstripped.empty?
|
162
|
+
|
163
|
+
if x.start_with?(?\t.freeze)
|
164
|
+
data = x.tap(&:strip!)
|
165
|
+
device_id = data[/\A.*?\s/].to_s.strip
|
166
|
+
device = data[device_id.length..-1].to_s.strip
|
167
|
+
ret[vendor_id][1][device_id] = device
|
168
|
+
else
|
169
|
+
data = x
|
170
|
+
vendor_id = data[/\A.*?\s/].to_s.strip
|
171
|
+
vendor = data[vendor_id.length..-1].to_s.strip
|
172
|
+
ret[vendor_id] = [vendor, {}]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
ret.freeze
|
177
|
+
else
|
178
|
+
{}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def query_hwdata(vendor_id, product_id)
|
183
|
+
vendor = hwdata[vendor_id]
|
184
|
+
if vendor
|
185
|
+
{vendor: vendor[0], product: vendor[1][product_id]}
|
186
|
+
else
|
187
|
+
{}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|