linux_stat 0.2.1 → 0.4.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.
@@ -0,0 +1,31 @@
1
+ #include <sys/statvfs.h>
2
+ #include "ruby.h"
3
+ #pragma GCC optimize ("O3")
4
+ #pragma clang optimize on
5
+
6
+ static VALUE statfs(VALUE obj, VALUE dir) {
7
+ struct statvfs buf ;
8
+ char *d = StringValuePtr(dir) ;
9
+ VALUE hash = rb_hash_new() ;
10
+
11
+ if(statvfs(d, &buf) < 0) return hash ;
12
+
13
+ rb_hash_aset(hash, ID2SYM(rb_intern("block_size")), INT2FIX(buf.f_bsize)) ;
14
+ rb_hash_aset(hash, ID2SYM(rb_intern("fragment_size")), INT2FIX(buf.f_frsize)) ;
15
+ rb_hash_aset(hash, ID2SYM(rb_intern("blocks")), INT2FIX(buf.f_blocks)) ;
16
+ rb_hash_aset(hash, ID2SYM(rb_intern("block_free")), INT2FIX(buf.f_bfree)) ;
17
+ rb_hash_aset(hash, ID2SYM(rb_intern("block_avail_unpriv")), INT2FIX(buf.f_bavail)) ;
18
+ rb_hash_aset(hash, ID2SYM(rb_intern("inodes")), INT2FIX(buf.f_files)) ;
19
+ rb_hash_aset(hash, ID2SYM(rb_intern("free_inodes")), INT2FIX(buf.f_ffree)) ;
20
+ rb_hash_aset(hash, ID2SYM(rb_intern("filesystem_id")), INT2FIX(buf.f_fsid)) ;
21
+ rb_hash_aset(hash, ID2SYM(rb_intern("mount_flags")), INT2FIX(buf.f_flag)) ;
22
+ rb_hash_aset(hash, ID2SYM(rb_intern("max_filename_length")), INT2FIX(buf.f_namemax)) ;
23
+
24
+ return hash ;
25
+ }
26
+
27
+ void Init_fs_stat() {
28
+ VALUE _linux_stat = rb_define_module("LinuxStat") ;
29
+ VALUE fs = rb_define_module_under(_linux_stat, "FS") ;
30
+ rb_define_module_function(fs, "stat", statfs, 1) ;
31
+ }
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ unless (have_header('sys/unistd.h') && have_header('ruby.h'))
4
+ abort('Missing header')
5
+ end
6
+
7
+ create_makefile 'linux_stat/sysconf'
@@ -0,0 +1,53 @@
1
+ #include <unistd.h>
2
+ #include "ruby.h"
3
+
4
+ static VALUE getTick(VALUE obj) {
5
+ return INT2FIX(sysconf(_SC_CLK_TCK)) ;
6
+ }
7
+
8
+ static VALUE getChildMax(VALUE obj) {
9
+ return INT2FIX(sysconf(_SC_CHILD_MAX)) ;
10
+ }
11
+
12
+ static VALUE getHostnameMax(VALUE obj) {
13
+ return INT2FIX(sysconf(_SC_HOST_NAME_MAX)) ;
14
+ }
15
+
16
+ static VALUE getLoginNameMax(VALUE obj) {
17
+ return INT2FIX(sysconf(_SC_LOGIN_NAME_MAX)) ;
18
+ }
19
+
20
+ static VALUE getOpenMax(VALUE obj) {
21
+ return INT2FIX(sysconf(_SC_OPEN_MAX)) ;
22
+ }
23
+
24
+ static VALUE getPageSizeMax(VALUE obj) {
25
+ return INT2FIX(sysconf(_SC_PAGESIZE)) ;
26
+ }
27
+
28
+ static VALUE getStreamMax(VALUE obj) {
29
+ return INT2FIX(sysconf(_SC_STREAM_MAX)) ;
30
+ }
31
+
32
+ static VALUE getTTYNameMax(VALUE obj) {
33
+ return INT2FIX(sysconf(_SC_TTY_NAME_MAX)) ;
34
+ }
35
+
36
+ static VALUE getPosixVersion(VALUE obj) {
37
+ return INT2FIX(sysconf(_SC_VERSION)) ;
38
+ }
39
+
40
+ void Init_sysconf() {
41
+ VALUE _linux_stat = rb_define_module("LinuxStat") ;
42
+ VALUE _sysconf = rb_define_module_under(_linux_stat, "Sysconf") ;
43
+
44
+ rb_define_module_function(_sysconf, "sc_clk_tck", getTick, 0) ;
45
+ rb_define_module_function(_sysconf, "child_max", getChildMax, 0) ;
46
+ rb_define_module_function(_sysconf, "hostname_max", getHostnameMax, 0) ;
47
+ rb_define_module_function(_sysconf, "login_name_max", getLoginNameMax, 0) ;
48
+ rb_define_module_function(_sysconf, "open_max", getOpenMax, 0) ;
49
+ rb_define_module_function(_sysconf, "page_size_max", getPageSizeMax, 0) ;
50
+ rb_define_module_function(_sysconf, "stream_max", getStreamMax, 0) ;
51
+ rb_define_module_function(_sysconf, "tty_name_max", getTTYNameMax, 0) ;
52
+ rb_define_module_function(_sysconf, "posix_version", getPosixVersion, 0) ;
53
+ }
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ unless (have_header('sys/utsname.h') && have_header('ruby.h'))
4
+ abort('Missing header')
5
+ end
6
+
7
+ create_makefile 'linux_stat/utsname'
@@ -0,0 +1,49 @@
1
+ #include <sys/utsname.h>
2
+ #include "ruby.h"
3
+ #pragma GCC optimize ("O3")
4
+ #pragma clang optimize on
5
+
6
+ static struct utsname buf ;
7
+ static short status ;
8
+
9
+ void init_buf() {
10
+ status = uname(&buf) ;
11
+ }
12
+
13
+ static VALUE getSysname(VALUE obj) {
14
+ VALUE sysname = status < 0 ? rb_str_new_cstr("") : rb_str_new_cstr(buf.sysname) ;
15
+ return sysname ;
16
+ }
17
+
18
+ static VALUE getNodename(VALUE obj) {
19
+ VALUE nodename = status < 0 ? rb_str_new_cstr("") : rb_str_new_cstr(buf.nodename) ;
20
+ return nodename ;
21
+ }
22
+
23
+ static VALUE getRelease(VALUE obj) {
24
+ VALUE release = status < 0 ? rb_str_new_cstr("") : rb_str_new_cstr(buf.release) ;
25
+ return release ;
26
+ }
27
+
28
+ static VALUE getVersion(VALUE obj) {
29
+ VALUE version = status < 0 ? rb_str_new_cstr("") : rb_str_new_cstr(buf.version) ;
30
+ return version ;
31
+ }
32
+
33
+ static VALUE getMachine(VALUE obj) {
34
+ VALUE machine = status < 0 ? rb_str_new_cstr("") : rb_str_new_cstr(buf.machine) ;
35
+ return machine ;
36
+ }
37
+
38
+ void Init_utsname() {
39
+ init_buf() ;
40
+
41
+ VALUE _linux_stat = rb_define_module("LinuxStat") ;
42
+ VALUE _uname = rb_define_module_under(_linux_stat, "Uname") ;
43
+
44
+ rb_define_module_function(_uname, "sysname", getSysname, 0) ;
45
+ rb_define_module_function(_uname, "nodename", getNodename, 0) ;
46
+ rb_define_module_function(_uname, "release", getRelease, 0) ;
47
+ rb_define_module_function(_uname, "version", getVersion, 0) ;
48
+ rb_define_module_function(_uname, "machine", getMachine, 0) ;
49
+ }
@@ -1,14 +1,20 @@
1
1
  require "linux_stat/version"
2
-
3
- module LinuxStat
4
- end
5
-
6
2
  require "linux_stat/battery"
7
3
  require "linux_stat/bios"
8
4
  require "linux_stat/cpu"
9
- require "linux_stat/kernel"
10
5
  require "linux_stat/memory"
11
6
  require "linux_stat/net"
7
+
8
+ require 'linux_stat/utsname'
12
9
  require "linux_stat/os"
10
+
13
11
  require "linux_stat/process"
14
12
  require "linux_stat/swap"
13
+ require "linux_stat/mounts"
14
+
15
+ require "linux_stat/fs_stat"
16
+ require "linux_stat/filesystem"
17
+
18
+ require "linux_stat/sysconf"
19
+ require "linux_stat/kernel"
20
+ require "linux_stat/process_info"
@@ -9,7 +9,7 @@ module LinuxStat
9
9
  end
10
10
 
11
11
  # Returns the details of the battery.
12
- #If the battery is not present it will return an empty Hash.
12
+ # If the battery is not present it will return an empty Hash.
13
13
  def stat
14
14
  st = status.downcase
15
15
  return {} unless present?
@@ -27,7 +27,7 @@ module LinuxStat
27
27
  end
28
28
 
29
29
  # Returns the model of the battery.
30
- #If the battery is not present or the information isn't available it will return an empty String.
30
+ # If the battery is not present or the information isn't available it will return an empty String.
31
31
  def model
32
32
  return ''.freeze unless model_readable?
33
33
  IO.read(File.join(PATH, 'model_name')).tap(&:strip!)
@@ -3,9 +3,10 @@ module LinuxStat
3
3
  class << self
4
4
  # Returns the model of the BIOS.
5
5
  # If the information is not available it will return a frozen empty string.
6
- # The output is also cached ; as changing the value in runtime is unexpected.
6
+ #
7
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
7
8
  def model
8
- # Cached ; as changing the value in runtime is unexpected
9
+ # cached (memoized) ; as changing the value in runtime is unexpected
9
10
  @@model ||= if File.readable?('/sys/devices/virtual/dmi/id/product_name')
10
11
  IO.read('/sys/devices/virtual/dmi/id/product_name').tap(&:strip!)
11
12
  elsif File.readable?('/sys/firmware/devicetree/base/model')
@@ -17,9 +18,10 @@ module LinuxStat
17
18
 
18
19
  # Returns the vendor of the BIOS.
19
20
  # If the information is not available it will return a frozen empty string.
20
- # The output is also cached ; as changing the value in runtime is unexpected.
21
+ #
22
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
21
23
  def vendor
22
- # Cached ; as changing the value in runtime is unexpected
24
+ # cached (memoized) ; as changing the value in runtime is unexpected
23
25
  @@vendor ||= if File.readable?('/sys/devices/virtual/dmi/id/bios_vendor')
24
26
  IO.read('/sys/devices/virtual/dmi/id/bios_vendor').tap(&:strip!)
25
27
  else
@@ -29,7 +31,8 @@ module LinuxStat
29
31
 
30
32
  # Returns the version of the BIOS.
31
33
  # If the information is not available it will return a frozen empty string.
32
- # The output is also cached ; as changing the value in runtime is unexpected.
34
+ #
35
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
33
36
  def version
34
37
  @@version ||= if File.readable?('/sys/devices/virtual/dmi/id/bios_version')
35
38
  IO.read('/sys/devices/virtual/dmi/id/bios_version').tap(&:strip!)
@@ -40,7 +43,8 @@ module LinuxStat
40
43
 
41
44
  # Returns the date of the BIOS.
42
45
  # If the information is not available it will return a frozen empty string.
43
- # The output is also cached ; as changing the value in runtime is unexpected.
46
+ #
47
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
44
48
  def date
45
49
  @@date ||= if File.readable?('/sys/devices/virtual/dmi/id/bios_date')
46
50
  IO.read('/sys/devices/virtual/dmi/id/bios_date').tap(&:strip!)
@@ -1,7 +1,9 @@
1
1
  module LinuxStat
2
2
  module CPU
3
3
  class << self
4
- # Returns the cpu usage of all threads.
4
+ # stat(sleep = 0.075)
5
+ # Where sleep is the delay to gather the data.
6
+ # This method returns the cpu usage of all threads.
5
7
  #
6
8
  # The first one is aggregated CPU usage reported by the Linux kernel.
7
9
  # And the consecutive ones are the real core usages.
@@ -17,7 +19,14 @@ module LinuxStat
17
19
  sleep(sleep)
18
20
  data2 = IO.readlines('/proc/stat').select! { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
19
21
 
20
- data.size.times.reduce({}) do |h, x|
22
+ # On devices like android, the core count can change anytime.
23
+ # I had crashes on Termux.
24
+ # So better just count the min number of CPU and iterate over that
25
+ # If data.length is smaller than data2.length, we don't have enough data to compare.
26
+ dl, d2l = data.length, data2.length
27
+ min = dl > d2l ? d2l : dl
28
+
29
+ min.times.reduce({}) do |h, x|
21
30
  user, nice, sys, idle, iowait, irq, softirq, steal = *data[x].drop(1)
22
31
  user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2[x].drop(1)
23
32
 
@@ -30,7 +39,10 @@ module LinuxStat
30
39
  end
31
40
  end
32
41
 
33
- # Returns the total cpu usage.
42
+ # total_usage(sleep = 0.075)
43
+ # Where sleep is the delay to gather the data.
44
+ # This method returns the cpu usage of all threads.
45
+ #
34
46
  # It's like running LinuxStat::CPU.stat[0] but it's much more efficient and calculates just the aggregated usage which is available at the top of the /proc/stat file.
35
47
  #
36
48
  # If the information is not available, it will return nil.
@@ -58,7 +70,8 @@ module LinuxStat
58
70
 
59
71
  # Returns the model of processor.
60
72
  # If the information isn't available, it will return en empty string.
61
- # The output is also cached ; as changing the value in runtime is unexpected.
73
+ #
74
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
62
75
  def model
63
76
  @@name ||= cpuinfo.find { |x| x.start_with?('model name') }.to_s.split(?:)[-1].to_s.strip
64
77
  end
@@ -67,14 +80,26 @@ module LinuxStat
67
80
  # If the information isn't available, it will return an empty array.
68
81
  def cur_freq
69
82
  @@cpu_freqs ||= Dir["/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_cur_freq"]
70
- @@cpu_freqs.map { |x| IO.read(x).to_i }
83
+ @@cur_freqs_readable ||= @@cpu_freqs.all?(&File.method(:readable?))
84
+
85
+ if @@cur_freqs_readable
86
+ @@cpu_freqs.map { |x| IO.read(x).to_i }
87
+ else
88
+ []
89
+ end
71
90
  end
72
91
 
73
92
  # Returns an array with max core frequencies corresponding to the usages.
74
93
  # If the information isn't available, it will return an empty array.
75
94
  def max_freq
76
95
  @@max_freqs ||= Dir["/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_max_freq"]
77
- @@max_freqs.map { |x| IO.read(x).to_i }
96
+ @@max_freqs_readable ||= @@max_freqs.all?(&File.method(:readable?))
97
+
98
+ if @@max_freqs_readable
99
+ @@max_freqs.map { |x| IO.read(x).to_i }
100
+ else
101
+ []
102
+ end
78
103
  end
79
104
 
80
105
  alias usages stat
@@ -0,0 +1,92 @@
1
+ module LinuxStat
2
+ module Filesystem
3
+ class << self
4
+ # stat(fs = '/')
5
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
6
+ #
7
+ # It returns a Hash with the following info:
8
+ # 1. total size of the device (in bytes)
9
+ # 2. free space (in kilobytes)
10
+ # 3. used space (in kilobytes)
11
+ #
12
+ # In a hash format:
13
+ # {:total=>119981191168, :free=>43155574784, :used=>76825616384, :available=>43155574784}
14
+ #
15
+ # If the stat can't be acquired, this method will return an empty Hash.
16
+ def stat(fs = ?/.freeze)
17
+ s = stat_raw(fs)
18
+ return {} if s.empty?
19
+ s.default = 0
20
+
21
+ {
22
+ total: s[:block_size] * s[:blocks],
23
+ free: s[:block_size] * s[:block_free],
24
+ used: s[:blocks].-(s[:block_free]) * s[:block_size]
25
+ }
26
+ end
27
+
28
+ # total(fs = '/')
29
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
30
+ # It returns the total size of a given disk in bytes.
31
+ #
32
+ # If the stat can't be acquired, this method will return nil.
33
+ def total(fs = ?/.freeze)
34
+ s = stat_raw(fs)
35
+ return nil if s.empty?
36
+ s.default = 0
37
+ s[:block_size] * s[:blocks]
38
+ end
39
+
40
+ # free(fs = '/')
41
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
42
+ # It returns the total free space in a disk in bytes.
43
+ # It is to be noted that free is not same as available.
44
+ # Free returns the size of free blocks.
45
+ #
46
+ # If the stat can't be acquired, this method will return an empty Hash.
47
+ def free(fs = ?/.freeze)
48
+ s = stat_raw(fs)
49
+ return nil if s.empty?
50
+ s.default = 0
51
+ s[:block_size] * s[:block_free]
52
+ end
53
+
54
+ # used(fs = '/')
55
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
56
+ # It returns the used space of a given disk in bytes.
57
+ #
58
+ # If the stat can't be acquired, this method will return nil.
59
+ def used(fs = ?/.freeze)
60
+ s = stat_raw(fs)
61
+ return nil if s.empty?
62
+ s.default = 0
63
+ s[:blocks].-(s[:block_free]) * s[:block_size]
64
+ end
65
+
66
+ # available(fs = '/')
67
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
68
+ # It returns the total free space in a disk in bytes.
69
+ # It is to be noted that free is not same as available.
70
+ # Available returns the size of free blocks for unpriviledged users.
71
+ #
72
+ # If the stat can't be acquired, this method will return an empty Hash.
73
+ def available(fs = ?/.freeze)
74
+ s = stat_raw(fs)
75
+ return nil if s.empty?
76
+ s.default = 0
77
+ s[:block_size] * s[:block_avail_unpriv]
78
+ end
79
+
80
+ # stat_raw(fs = '/')
81
+ # Where fs is the directory of the file system (like / or /tmp/ or /run/media/thumbdrive).
82
+ #
83
+ # It returns a Hash with the following data (for example):
84
+ # {:block_size=>4096, :fragment_size=>4096, :blocks=>29292283, :block_free=>10535967, :block_avail_unpriv=>10535967, :inodes=>58612160, :free_inodes=>56718550, :filesystem_id=>2050, :mount_flags=>1024, :max_filename_length=>255}
85
+ #
86
+ # If the stat can't be acquired, this method will return an empty Hash.
87
+ def stat_raw(fs = ?/.freeze)
88
+ LinuxStat::FS.stat(fs)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -3,7 +3,7 @@ module LinuxStat
3
3
  class << self
4
4
  # Returns the Linux Kernel version.
5
5
  # If the information isn't available, it will return a frozen empty string.
6
- # The output is also cached ; as changing the value in runtime is unexpected.
6
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
7
7
  def version
8
8
  return ''.freeze if string.empty?
9
9
  @@version ||= splitted[2]
@@ -11,7 +11,7 @@ module LinuxStat
11
11
 
12
12
  # Returns the name of the user who built the kernel using KBUILD_FLAGS.
13
13
  # If the information isn't available, it will return a frozen empty string.
14
- # The output is also cached ; as changing the value in runtime is unexpected.
14
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
15
15
  def build_user
16
16
  @@build_user ||= string.split(/(\(.+\))/).each(&:strip!)
17
17
  .reject(&:empty?).find { |x| x[/^\(.+\)$/] }.to_s
@@ -20,7 +20,7 @@ module LinuxStat
20
20
 
21
21
  # Returns the compiler used to compile the Linux Kernel.
22
22
  # If the information isn't available, it will return a frozen empty string.
23
- # The output is also cached ; as changing the value in runtime is unexpected.
23
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
24
24
  def compiler
25
25
  return ''.freeze if string.empty?
26
26
 
@@ -39,7 +39,7 @@ module LinuxStat
39
39
 
40
40
  # Returns the compiler version used to compile the Linux Kernel.
41
41
  # If the information isn't available, it will return a frozen empty string.
42
- # The output is also cached ; as changing the value in runtime is unexpected.
42
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
43
43
  def compiler_version
44
44
  @@compiler_version ||= string.split(/(\(.+?\))/).each(&:strip!)
45
45
  .reject(&:empty?)[2..4].to_a
@@ -62,7 +62,7 @@ module LinuxStat
62
62
  # You have to use regexp yourself to get the proper zone.
63
63
  # Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
64
64
  #
65
- # The output is also cached ; as changing the value in runtime is unexpected.
65
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
66
66
  def build_date
67
67
  return nil if splitted.empty?
68
68
 
@@ -107,7 +107,7 @@ module LinuxStat
107
107
  # You have to use regexp yourself to get the proper zone.
108
108
  # Use LinuxStat::Kernel.build_date_string to get the original string if you need that.
109
109
  #
110
- # The output is also cached ; as changing the value in runtime is unexpected.
110
+ # The output is also cached (memoized) ; as changing the value in runtime is unexpected.
111
111
  def build_date_string
112
112
  return nil if splitted.empty?
113
113
 
@@ -133,12 +133,23 @@ module LinuxStat
133
133
  end
134
134
  end
135
135
 
136
+ alias release version
137
+
136
138
  # Reads maximum 1024 bytes from /proc/version and returns the string.
137
139
  # The output is also cached ; as changing the value in runtime is unexpected.
138
140
  def string
139
141
  @@string ||= File.readable?('/proc/version') ? IO.read('/proc/version', 1024).tap(&:strip!) : ''
140
142
  end
141
143
 
144
+ # Returns the sc_clk_tck or the same output from command `getconf CLK_TCK`.
145
+ # Also, clk_tck is an alias of this method.
146
+ # The output is also cached ; as changing the value in runtime is unexpected.
147
+ def ticks
148
+ @@tick ||= LinuxStat::Sysconf.sc_clk_tck
149
+ end
150
+
151
+ alias clk_tck ticks
152
+
142
153
  private
143
154
  def splitted
144
155
  @@string_splitted ||= string.split