diff --git a/inxi b/inxi index 3fcd4aa..d6f7066 100755 --- a/inxi +++ b/inxi @@ -20,15 +20,16 @@ use warnings; use 5.008; ## Perl 7 things for testing: depend on Perl 5.032 -# use 5.032 +#use 5.032; # use compat::perl5; # act like Perl 5's defaults -# no feature qw(indirect); -# no multidimensional; -# no bareword::filehandle; +#no feature qw(indirect); +#no multidimensional; +#no bareword::filehandles; use Cwd qw(abs_path); # #abs_path realpath getcwd use Data::Dumper qw(Dumper); # print_r -use File::Find; +# NOTE: load in SystemDebugger unless encounter issues with require/import +#use File::Find; use File::stat; # needed for Xorg.0.log file mtime comparisons use Getopt::Long qw(GetOptions); # Note: default auto_abbrev is enabled @@ -39,8 +40,8 @@ use POSIX qw(uname strftime ttyname); ## INXI INFO ## my $self_name='inxi'; -my $self_version='3.1.09'; -my $self_date='2020-11-11'; +my $self_version='3.2.00'; +my $self_date='2020-12-15'; my $self_patch='00'; ## END INXI INFO ## @@ -60,8 +61,8 @@ if (eval {require Time::HiRes}){ } @t0 = eval 'Time::HiRes::gettimeofday()' if $b_hires; # let's start it right away ## Hashes -my (%alerts,%build_prop,%client,%colors,%debugger,%dl,%files,%program_values, -%rows,%sensors_raw,%system_files); +my (%alerts,%build_prop,%client,%colors,%debugger,%dl,%files, +%dmmapper,%mapper,%program_values,%rows,%sensors_raw,%system_files); ## Arrays # ps_aux is full output, ps_cmd is only the last 10 columns to last @@ -70,18 +71,20 @@ my (@app,@dmesg_boot,@devices_audio,@devices_graphics,@devices_network, @paths,@proc_partitions,@ps_aux,@ps_cmd,@ps_gui,@sensors_exclude,@sensors_use, @sysctl,@sysctl_battery,@sysctl_sensors,@sysctl_machine,@uname,@usb); ## Disk arrays -my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@hardware_raid,@labels, -@lsblk,@partitions,@raid,@sysctl_disks,@swaps,@uuids); +my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@labels,@lsblk,@lvm, +@lvm_raid,@md_raid,@partitions,@raw_logical,@sysctl_disks,@swaps,@uuids,@zfs_raid); my @test = (0,0,0,0,0); ## Booleans -my ($b_admin,$b_arm,$b_bb_ps,$b_block_tool,$b_build_prop, +my ($b_active_general,$b_active_lvm, +$b_admin,$b_android,$b_arm,$b_bb_ps,$b_block_tool,$b_build_prop, $b_display,$b_dmesg_boot_check,$b_dmi,$b_dmidecode_force, -$b_fake_bsd,$b_fake_dboot,$b_fake_dmidecode,$b_fake_pciconf,$b_fake_sysctl, -$b_fake_usbdevs,$b_force_display,$b_gpudata,$b_irc, -$b_log,$b_log_colors,$b_log_full,$b_man,$b_mem,$b_no_html_wan,$b_mips,$b_no_sudo, -$b_pci,$b_pci_tool,$b_pkg,$b_ppc,$b_proc_partitions,$b_ps_gui, -$b_root,$b_running_in_display,$b_sensors,$b_skip_dig, +$b_fake_bsd,$b_fake_cpu,$b_fake_dboot,$b_fake_dmidecode,$b_fake_logical,$b_fake_pciconf, +$b_fake_raid,$b_fake_sensors,$b_fake_sysctl,$b_fake_usbdevs,$b_force_display, +$b_gpudata,$b_hddtemp_force,$b_irc,$b_log,$b_log_colors,$b_log_full,$b_lvm,$b_lvm_data, +$b_man,$b_mapper,$b_mdadm,$b_mem,$b_mips, +$b_no_html_wan,$b_no_sudo,$b_pci,$b_pci_tool,$b_pkg,$b_ppc,$b_proc_partitions, +$b_ps_gui,$b_root,$b_running_in_display,$b_sensors,$b_skip_dig, $b_slot_tool,$b_soc_audio,$b_soc_gfx,$b_soc_net,$b_soc_timer,$b_sparc, $b_swaps,$b_sysctl,$b_usb,$b_usb_check,$b_usb_sys,$b_usb_tool, $b_wmctrl); @@ -192,8 +195,8 @@ sub initialize { } sub check_tools { - my ($action,$program,$message,@data,%commands,%hash); - if ( $b_dmi ){ + my ($action,$program,$message,@data,%commands); + if ($b_dmi){ $action = 'use'; if ($program = check_program('dmidecode')) { @data = grabber("$program -t chassis -t baseboard -t processor 2>&1"); @@ -227,36 +230,36 @@ sub check_tools { else { $action = 'missing'; } - %hash = ( - 'dmidecode' => { + $alerts{'dmidecode'} = { 'action' => $action, 'missing' => row_defaults('tool-missing-required','dmidecode'), 'permissions' => row_defaults('tool-permissions','dmidecode'), + 'path' => $program, 'smbios' => row_defaults('dmidecode-smbios'), 'no-data' => row_defaults('dmidecode-dev-mem'), 'unknown-error' => row_defaults('tool-unknown-error','dmidecode'), - }, - ); - %alerts = (%alerts, %hash); + }; } # note: gnu/linux has sysctl so it may be used that for something if present # there is lspci for bsds so doesn't hurt to check it - if ($b_pci || $b_sysctl){ + if ($b_lvm || $b_pci || $b_sysctl){ if (!$bsd_type){ if ($b_pci ){ - %hash = ('lspci' => '-n',); - %commands = (%commands,%hash); + $commands{'lspci'} = '-n'; + } + if ($b_lvm){ + $commands{'lvs'} = ''; } } else { if ($b_pci ){ - %hash = ('pciconf' => '-l','pcictl' => 'list', 'pcidump' => ''); - %commands = (%commands,%hash); + $commands{'pciconf'} = '-l'; + $commands{'pcictl'} = 'list'; + $commands{'pcidump'} = ''; } if ($b_sysctl ){ # note: there is a case of kernel.osrelease but it's a linux distro - %hash = ('sysctl' => 'kern.osrelease',); - %commands = (%commands,%hash); + $commands{'sysctl'} = 'kern.osrelease'; } } foreach ( keys %commands ){ @@ -271,70 +274,59 @@ sub check_tools { else { $action = 'missing'; } - %hash = ( - $_ => { + $alerts{$_} = { 'action' => $action, 'missing' => row_defaults('tool-missing-incomplete',"$_"), + 'path' => $program, 'permissions' => row_defaults('tool-permissions',"$_"), - }, - ); - %alerts = (%alerts, %hash); + }; } } %commands = (); - if ( $show{'sensor'} ){ - %commands = ('sensors' => 'linux',); + if ($show{'sensor'}){ + $commands{'sensors'} = 'linux'; } # note: lsusb ships in FreeBSD ports sysutils/usbutils - if ( $b_usb ){ - %hash = ('lsusb' => 'all',); - %commands = (%commands,%hash); - %hash = ('usbdevs' => 'bsd',); - %commands = (%commands,%hash); + if ($b_usb){ + $commands{'lsusb'} = 'all'; + $commands{'usbdevs'} = 'bsd'; } if ($show{'ip'} || ($bsd_type && $show{'network-advanced'})){ - %hash = ( - 'ip' => 'linux', - 'ifconfig' => 'all', - ); - %commands = (%commands,%hash); + $commands{'ip'} = 'linux'; + $commands{'ifconfig'} = 'all'; } # can't check permissions since we need to know the partition/disc if ($b_block_tool){ - %hash = ( - 'blockdev' => 'linux', - 'lsblk' => 'linux', - ); - %commands = (%commands,%hash); + $commands{'blockdev'} = 'linux'; + $commands{'lsblk'} = 'linux'; + } + if ($b_mdadm){ + $commands{'mdadm'} = 'linux'; } if ($b_smartctl){ - %hash = ( - 'smartctl' => 'all', - ); - %commands = (%commands,%hash); + $commands{'smartctl'} = 'all'; } foreach ( keys %commands ){ $action = 'use'; + $program = ''; $message = row_defaults('tool-present'); if ( ($commands{$_} eq 'linux' && $os ne 'linux' ) || ($commands{$_} eq 'bsd' && $os eq 'linux' ) ){ $message = row_defaults('tool-missing-os', ucfirst($os) . " $_"); $action = 'platform'; } - elsif (!check_program($_)){ + elsif (!($program = check_program($_))){ $message = row_defaults('tool-missing-recommends',"$_"); $action = 'missing'; } - %hash = ( - $_ => { + $alerts{$_} = { 'action' => $action, 'missing' => $message, + 'path' => $program, 'platform' => $message, - }, - ); - %alerts = (%alerts, %hash); + }; } # print Dumper \%alerts; - set_fake_tools() if $b_fake_bsd; + set_fake_bsd_tools() if $b_fake_bsd; } # args: 1 - desktop/app command for --version; 2 - search string; # 3 - space print number; 4 - [optional] version arg: -v, version, etc @@ -366,6 +358,7 @@ sub set_basics { $client{'version'} = ''; $colors{'default'} = 2; $show{'partition-sort'} = 'id'; # sort order for partitions + @raw_logical = (0,0,0); } # args: $1 - default OR override default cols max integer count. $_[0] @@ -416,16 +409,16 @@ sub set_display_width { } # only for dev/debugging BSD -sub set_fake_tools { +sub set_fake_bsd_tools { $system_files{'dmesg-boot'} = '/var/run/dmesg.boot' if $b_fake_dboot; - $alerts{'pciconf'} = ({'action' => 'use'}) if $b_fake_pciconf; - $alerts{'sysctl'} = ({'action' => 'use'}) if $b_fake_sysctl; - if ($b_fake_usbdevs ){ - $alerts{'usbdevs'} = ({'action' => 'use'}); - $alerts{'lsusb'} = ({ + $alerts{'pciconf'}->{'action'} = 'use' if $b_fake_pciconf; + $alerts{'sysctl'}->{'action'} = 'use' if $b_fake_sysctl; + if ($b_fake_usbdevs){ + $alerts{'usbdevs'}->{'action'} = 'use'; + $alerts{'lsusb'} = { 'action' => 'missing', 'missing' => 'Required program lsusb not available', - }); + }; } } @@ -434,7 +427,7 @@ sub set_os { @uname = uname(); $os = lc($uname[0]); $cpu_arch = lc($uname[-1]); - if ($cpu_arch =~ /arm|aarch/){$b_arm = 1} + if ($cpu_arch =~ /arm|aarch/){$b_arm = 1;} elsif ($cpu_arch =~ /mips/) {$b_mips = 1} elsif ($cpu_arch =~ /power|ppc/) {$b_ppc = 1} elsif ($cpu_arch =~ /sparc/) {$b_sparc = 1} @@ -445,6 +438,7 @@ sub set_os { elsif ($cpu_arch =~ /(alpha|64|e2k)/){ $bits_sys = 64; } + $b_android = 1 if -e '/system/build.prop'; if ( $os =~ /(aix|bsd|cosix|dragonfly|darwin|hp-?ux|indiana|irix|sunos|solaris|ultrix|unix)/ ){ if ( $os =~ /openbsd/ ){ $os = 'openbsd'; @@ -470,12 +464,12 @@ sub set_path { # NOTE: recent Xorg's show error if you try /usr/bin/Xorg -version but work # if you use the /usr/lib/xorg-server/Xorg path. @paths = qw(/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin); - @path = split /:/, $ENV{'PATH'} if $ENV{'PATH'}; + @path = split(':', $ENV{'PATH'}) if $ENV{'PATH'}; # print "paths: @paths\nPATH: $ENV{'PATH'}\n"; # Create a difference of $PATH and $extra_paths and add that to $PATH: foreach my $id (@path) { if ( !(grep { /^$id$/ } @paths) && $id !~ /(game)/ ){ - push @paths, $id; + push(@paths, $id); } } # print "paths: @paths\n"; @@ -601,16 +595,16 @@ sub set_xorg_log { # we are just going to get all the Xorg logs we can find, and not worry about # which is 'right'. @temp = globber('/var/log/Xorg.*.log'); - push @x_logs, @temp if @temp; + push(@x_logs, @temp) if @temp; @temp = globber('/var/lib/gdm/.local/share/xorg/Xorg.*.log'); - push @x_logs, @temp if @temp; + push(@x_logs, @temp) if @temp; @temp = globber($ENV{'HOME'} . '/.local/share/xorg/Xorg.*.log',); - push @x_logs, @temp if @temp; + push(@x_logs, @temp) if @temp; # root will not have a /root/.local/share/xorg directory so need to use a # user one if we can find one. if ($b_root){ @temp = globber('/home/*/.local/share/xorg/Xorg.*.log'); - push @x_logs, @temp if @temp; + push(@x_logs, @temp) if @temp; } foreach (@x_logs){ if (-r $_){ @@ -628,7 +622,7 @@ sub set_xorg_log { } if ( !$file_holder && check_program('xset') ){ my $data = qx(xset q 2>/dev/null); - foreach ( split /\n/, $data){ + foreach (split('\n', $data)){ if ($_ =~ /Log file/i){ $file_holder = get_piece($_,3); last; @@ -755,7 +749,7 @@ sub set_color_scheme { sub set_colors { eval $start if $b_log; # it's already been set with -c 0-43 - if ( exists $colors{'c1'} ){ + if (exists $colors{'c1'}){ return 1; } # This let's user pick their color scheme. For IRC, only shows the color schemes, @@ -810,7 +804,7 @@ package SelectColors; # use diagnostics; # use 5.008; -my (@data,@rows,%configs,%status); +my (@data,%configs,%status); my ($type,$w_fh); my $safe_color_count = 12; # null/normal + default color group my $count = 0; @@ -882,7 +876,7 @@ sub start_selector { $configs{'selection'} color scheme."], ); } - @rows = ( + push(@data, [ 0, '', '', "Because there is no way to know your $configs{'selection'} foreground/background colors, you can set your color preferences from color scheme option list below:"], @@ -892,19 +886,16 @@ sub start_selector { 3-dark^backgrounds; 4-miscellaneous"], [ 0, '', '', ""], ); - push @data, @rows; if ( ! $b_irc ){ - @rows = ( + push(@data, [ 0, '', '', "Please note that this will set the $configs{'selection'} preferences only for user: $whoami"], ); - push @data, @rows; } - @rows = ( + push(@data, [ 0, '', '', "$line1"], ); - push @data, @rows; - main::print_basic(@data); + main::print_basic(\@data); @data = (); } sub create_color_selections { @@ -918,13 +909,12 @@ sub create_color_selections { last; } main::set_color_scheme($i); - @rows = ( + push(@data, [0, '', '', "$i)$spacer$colors{'c1'}Card:$colors{'c2'}^nVidia^GT218 $colors{'c1'}Display^Server$colors{'c2'}^x11^(X.Org^1.7.7)$colors{'cn'}"], ); - push @data, @rows; } - main::print_basic(@data); + main::print_basic(\@data); @data = (); main::set_color_scheme(0); } @@ -950,16 +940,16 @@ sub get_selection { schemes remove the global setting."], [0, '', '', "$line1"], ); - main::print_basic(@data); + main::print_basic(\@data); @data = (); my $response = ; - chomp $response; + chomp($response); if (!main::is_int($response) || $response > ($count + 3) ){ @data = ( [0, '', '', "Error - Invalid Selection. You entered this: $response. Hit to continue."], [0, '', '', "$line1"], ); - main::print_basic(@data); + main::print_basic(\@data); my $response = ; start_selector(); create_color_selections(); @@ -973,7 +963,7 @@ sub process_selection { my $response = shift; if ($response == ($count + 3) ){ @data = ([0, '', '', "Ok, exiting $self_name now. You can set the colors later."],); - main::print_basic(@data); + main::print_basic(\@data); exit 0; } elsif ($response == ($count + 2)){ @@ -981,7 +971,7 @@ sub process_selection { [0, '', '', "Ok, continuing $self_name unchanged."], [0, '', '', "$line1"], ); - main::print_basic(@data); + main::print_basic(\@data); if ( defined $colors{'console'} && !$b_display ){ main::set_color_scheme($colors{'console'}); } @@ -997,7 +987,7 @@ sub process_selection { [0, '', '', "Removing all color settings from config file now..."], [0, '', '', "$line1"], ); - main::print_basic(@data); + main::print_basic(\@data); delete_all_config_colors(); main::set_color_scheme($colors{'default'}); } @@ -1007,7 +997,7 @@ sub process_selection { [0, '', '', "Updating config file for $configs{'selection'} color scheme now..."], [0, '', '', "$line1"], ); - main::print_basic(@data); + main::print_basic(\@data); if ($configs{'selection'} eq 'global'){ delete_all_colors(); } @@ -1018,7 +1008,7 @@ sub process_selection { } } sub delete_all_colors { - my @file_lines = main::reader( $user_config_file ); + my @file_lines = main::reader($user_config_file); open( $w_fh, '>', $user_config_file ) or main::error_handler('open', $user_config_file, $!); foreach ( @file_lines ) { if ( $_ !~ /^(CONSOLE_COLOR_SCHEME|GLOBAL_COLOR_SCHEME|IRC_COLOR_SCHEME|IRC_CONS_COLOR_SCHEME|IRC_X_TERM_COLOR_SCHEME|VIRT_TERM_COLOR_SCHEME)/){ @@ -1028,7 +1018,7 @@ sub delete_all_colors { close $w_fh; } sub delete_global_color { - my @file_lines = main::reader( $user_config_file ); + my @file_lines = main::reader($user_config_file); open( $w_fh, '>', $user_config_file ) or main::error_handler('open', $user_config_file, $!); foreach ( @file_lines ) { if ( $_ !~ /^GLOBAL_COLOR_SCHEME/){ @@ -1039,7 +1029,7 @@ sub delete_global_color { } sub set_config_color_scheme { my $value = shift; - my @file_lines = main::reader( $user_config_file ); + my @file_lines = main::reader($user_config_file); my $b_found = 0; open( $w_fh, '>', $user_config_file ) or main::error_handler('open', $user_config_file, $!); foreach ( @file_lines ) { @@ -1068,7 +1058,7 @@ sub print_irc_message { [ 0, '', '', "98 (irc,^not^in^desktop^-^$status{'irc-console'})"], [ 0, '', '', "99 (global^-^$status{'global'})"] ); - main::print_basic(@data); + main::print_basic(\@data); exit 0; } @@ -1086,21 +1076,21 @@ sub check_config_file { } sub get_configs { - my (@configs) = @_; + my ($configs) = @_; my ($key, $val,@config_files); - if (!@configs){ + if (!$configs){ @config_files = ( qq(/etc/$self_name.conf), qq($user_config_dir/$self_name.conf) ); } else { - @config_files = (@configs); + @config_files = @$configs; } # Config files should be passed in an array as a param to this function. # Default intended use: global @CONFIGS; foreach (@config_files) { - next unless open (my $fh, '<', "$_"); + next unless open(my $fh, '<', "$_"); while (<$fh>) { chomp; s/#.*//; @@ -1145,8 +1135,8 @@ sub get_config_item { elsif ($key eq 'PARTITION_SORT') {$show{'partition-sort'} = $val if ($val =~ /^(dev-base|fs|id|label|percent-used|size|uuid|used)$/) } elsif ($key eq 'PS_COUNT') {$ps_count = $val if is_int($val) } elsif ($key eq 'SENSORS_CPU_NO') {$sensors_cpu_nu = $val if is_int($val)} - elsif ($key eq 'SENSORS_EXCLUDE') {@sensors_exclude = split /\s*,\s*/, $val if $val} - elsif ($key eq 'SENSORS_USE') {@sensors_use = split /\s*,\s*/, $val if $val} + elsif ($key eq 'SENSORS_EXCLUDE') {@sensors_exclude = split(/\s*,\s*/, $val) if $val} + elsif ($key eq 'SENSORS_USE') {@sensors_use = split(/\s*,\s*/, $val) if $val} elsif ($key eq 'SHOW_HOST' || $key eq 'B_SHOW_HOST') { if (is_int($val)){ $show{'host'} = $val; @@ -1221,7 +1211,7 @@ sub begin_logging { } # now create the logfile # print "Opening log file for reading: $log_file\n"; - open $fh_l, '>', $log_file or error_handler(4, $log_file, "$!"); + open($fh_l, '>', $log_file) or error_handler(4, $log_file, "$!"); # and echo the start data $data = $line2; $data .= "START $self_name LOGGING:\n"; @@ -1250,8 +1240,7 @@ sub log_data { # print "1: $one 2: $two 3: $three\n"; if ($one eq 'fs') { if (ref $three eq 'ARRAY'){ - # my @temp = @$three; - # print Data::Dumper::Dumper \@$three; + # print Data::Dumper::Dumper $three; $args = "\n${spacer}Args: " . joiner($three, '; ', 'unset'); } else { @@ -1293,11 +1282,11 @@ sub log_data { elsif ( $one eq 'dump') { $data = "$two:\n"; if (ref $three eq 'HASH'){ - $data .= Data::Dumper::Dumper \%$three; + $data .= Data::Dumper::Dumper $three; } elsif (ref $three eq 'ARRAY'){ - # print Data::Dumper::Dumper \@$three; - $data .= Data::Dumper::Dumper \@$three; + # print Data::Dumper::Dumper $three; + $data .= Data::Dumper::Dumper $three; } else { $data .= Data::Dumper::Dumper $three; @@ -1356,17 +1345,10 @@ sub set_debugger { } } } - ## SystemDebugger { package SystemDebugger; -# use File::Find q(find); -#no warnings 'File::Find'; -# use File::Spec::Functions; -#use File::Copy; -#use POSIX qw(strftime); - my $option = 'main'; my ($data_dir,$debug_dir,$debug_gz,$parse_src,$upload) = ('','','','',''); my @content = (); @@ -1384,16 +1366,30 @@ sub new { } sub run_debugger { - #require File::Find; - #File::Find::Functions->import; - require File::Copy; - File::Copy->import; - require File::Spec::Functions; - File::Spec::Functions->import; - print "Starting $self_name debugging data collector...\n"; + print "Loading required debugger Perl File:: modules... \n"; + # Fedora/Redhat doesn't include File::Find File::Copy in + # core modules!! why? Or rather, they deliberately removed them!! + if (main::check_module('File::Find')){ + File::Find->import('find'); + } + else { + main::error_handler('required-module', 'File', 'File::Find'); + } + if (main::check_module('File::Copy')){ + File::Copy->import; + } + else { + main::error_handler('required-module', 'File', 'File::Copy'); + } + if (main::check_module('File::Spec::Functions')){ + File::Spec::Functions->import; + } + else { + main::error_handler('required-module', 'File', 'File::Spec::Functions'); + } create_debug_directory(); - print "Note: for dmidecode data you must be root.\n" if !$b_root; + print "Note: for dmidecode, smartctl, lvm data you must be root.\n" if !$b_root; print $line3; if (!$b_debug){ audio_data(); @@ -1458,7 +1454,7 @@ sub create_debug_directory { elsif ($b_mips) {$alt_string = '-MIPS'} elsif ($b_ppc) {$alt_string = '-PPC'} elsif ($b_sparc) {$alt_string = '-SPARC'} - $debug_dir = "$self_name$alt_string$bsd_string-$host-$today$root_string-$self_version"; + $debug_dir = "$self_name$alt_string$bsd_string-$host-$today$root_string-$self_version-$self_patch"; $debug_gz = "$debug_dir.tar.gz"; $data_dir = "$user_data_dir/$debug_dir"; if ( -d $data_dir ){ @@ -1469,7 +1465,7 @@ sub create_debug_directory { #rmdir "$user_data_dir$debug_gz" or main::error_handler('remove', "$user_data_dir/$debug_gz", "$!"); print "Failed removing leftover directory:\n$user_data_dir$debug_gz error: $?" if system('rm','-rf',"$user_data_dir$debug_gz"); } - print "Data going into:\n$data_dir\n"; + print "Debugger data going into:\n$data_dir\n"; } sub compress_dir { print "Creating tar.gz compressed file of this material...\n"; @@ -1509,7 +1505,7 @@ sub audio_data { '/proc/asound/version', ); @files2 = main::globber('/proc/asound/*/usbid'); - @files = (@files,@files2) if @files2; + push(@files,@files2) if @files2; copy_files(\@files,'audio'); } ## NOTE: >/dev/null 2>&1 is sh, and &>/dev/null is bash, fix this @@ -1529,10 +1525,10 @@ sub disk_data { # very old systems if (-d '/proc/ide/'){ my @ides = main::globber('/proc/ide/*/*'); - @files = (@files, @ides) if @ides; + push(@files, @ides) if @ides; } else { - push (@files, '/proc-ide-directory'); + push(@files, '/proc-ide-directory'); } copy_files(\@files, 'disk'); my @cmds = ( @@ -1547,23 +1543,10 @@ sub disk_data { ['df', '-k -T -P'], ['df', '-k -T -P -a'], ['df', '-P'], + ['dmsetup', 'ls --tree'], ['findmnt', ''], ['findmnt', '--df --no-truncate'], ['findmnt', '--list --no-truncate'], - ['lsblk', '-fs'], - ['lsblk', '-fsr'], - ['lsblk', '-fsP'], - ['lsblk', '-a'], - ['lsblk', '-aP'], - ['lsblk', '-ar'], - ['lsblk', '-p'], - ['lsblk', '-pr'], - ['lsblk', '-pP'], - ['lsblk', '-r'], - ['lsblk', '-r --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], - ['lsblk', '-rb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], - ['lsblk', '-Pb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE'], - ['lsblk', '-Pb --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], ['gpart', 'list'], ['gpart', 'show'], ['gpart', 'status'], @@ -1582,6 +1565,31 @@ sub disk_data { # http://comments.gmane.org/gmane.linux.file-systems.zfs.user/2032 ['ls', '-l /dev/disk/by-wwn'], ['ls', '-l /dev/mapper'], + ['lsblk', '-fs'], + ['lsblk', '-fsr'], + ['lsblk', '-fsP'], + ['lsblk', '-a'], + ['lsblk', '-aP'], + ['lsblk', '-ar'], + ['lsblk', '-p'], + ['lsblk', '-pr'], + ['lsblk', '-pP'], + ['lsblk', '-r'], + ['lsblk', '-r --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], + ['lsblk', '-rb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], + ['lsblk', '-Pb --output NAME,PKNAME,TYPE,RM,FSTYPE,SIZE'], + ['lsblk', '-Pb --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS'], + ['lvdisplay', '-c'], + ['lvdisplay', '-cv'], + ['lvdisplay', '-cv --segments'], + ['lvdisplay', '-m --segments'], + ['lvdisplay', '-ma --segments'], + ['lvs', '--separator :'], + ['lvs', '--separator : --segments'], + ['lvs', '-o +devices --separator : --segments'], + ['lvs', '-o +devices -v --separator : --segments'], + ['lvs', '-o +devices -av --separator : --segments'], + ['lvs', '-o +devices -aPv --separator : --segments'], # LSI raid https://hwraid.le-vert.net/wiki/LSIMegaRAIDSAS ['megacli', '-AdpAllInfo -aAll'], ['megacli', '-LDInfo -L0 -a0'], @@ -1591,10 +1599,31 @@ sub disk_data { ['megasasctl', ''], ['mount', ''], ['nvme', 'present'], + ['pvdisplay', '-c'], + ['pvdisplay', '-cv'], + ['pvdisplay', '-m'], + ['pvdisplay', '-ma'], + ['pvs', '--separator :'], + ['pvs', '--separator : --segments'], + ['pvs', '-a --separator : --segments'], + ['pvs', '-av --separator : --segments'], + ['pvs', '-aPv --separator : --segments -o +pv_major,pv_minor'], + ['pvs', '-v --separator : --segments'], + ['pvs', '-Pv --separator : --segments'], + ['pvs', '--segments -o pv_name,pv_size,seg_size,vg_name,lv_name,lv_size,seg_pe_ranges'], ['readlink', '/dev/root'], ['swapon', '-s'], # 3ware-raid ['tw-cli', 'info'], + ['vgdisplay', ''], + ['vgdisplay', '-v'], + ['vgdisplay', '-c'], + ['vgdisplay', '-vc'], + ['vgs', '--separator :'], + ['vgs', '-av --separator :'], + ['vgs', '-aPv --separator :'], + ['vgs', '-v --separator :'], + ['vgs', '-o +pv_name --separator :'], ['zfs', 'list'], ['zpool', 'list'], ['zpool', 'list -v'], @@ -1631,11 +1660,11 @@ sub display_data { # keep this updated to handle all possible locations we know about for Xorg.0.log # not using $system_files{'xorg-log'} for now though it would be best to know what file is used main::set_xorg_log(); - push (@files, '/var/log/Xorg.0.log'); - push (@files, '/var/lib/gdm/.local/share/xorg/Xorg.0.log'); - push (@files, $ENV{'HOME'} . '/.local/share/xorg/Xorg.0.log'); - push (@files, $system_files{'xorg-log'}) if $system_files{'xorg-log'}; - push (@files, '/etc/X11/xorg.conf'); + push(@files, '/var/log/Xorg.0.log'); + push(@files, '/var/lib/gdm/.local/share/xorg/Xorg.0.log'); + push(@files, $ENV{'HOME'} . '/.local/share/xorg/Xorg.0.log'); + push(@files, $system_files{'xorg-log'}) if $system_files{'xorg-log'}; + push(@files, '/etc/X11/xorg.conf'); copy_files(\@files,'display-xorg'); print "Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, wayland, weston...\n"; %data = ( @@ -1719,17 +1748,17 @@ sub perl_modules { if (-d $_ && $_ ne '.'){ $_ =~ s/\/$//; # just in case, trim off trailing slash $value .= "EXISTS: $_\n"; - push @inc, $_; + push(@inc, $_); } else { $value .= "ABSENT: $_\n"; } } main::writer("$data_dir/perl-inc-data.txt",$value); - File::Find::find { wanted => sub { - push @modules, File::Spec->canonpath($_) if /\.pm\z/ - }, no_chdir => 1 }, @inc; - @modules = sort(@modules); + File::Find::find({ wanted => sub { + push(@modules, File::Spec->canonpath($_)) if /\.pm\z/ + }, no_chdir => 1 }, @inc); + @modules = sort @modules; foreach (@modules){ my $dir = $_; $dir =~ s/[^\/]+$//; @@ -1746,16 +1775,18 @@ sub perl_modules { } $mods .= $value; } - open (my $fh, '>', "$data_dir/$filename"); + open(my $fh, '>', "$data_dir/$filename"); print $fh $mods; close $fh; } sub system_data { print "Collecting system data...\n"; + # has to run here because if null, error, list constructor throws fatal error + my $ksh = qx(ksh -c 'printf \%s "\$KSH_VERSION"' 2>/dev/null); my %data = ( 'cc' => $ENV{'CC'}, # @(#)MIRBSD KSH R56 2018/03/09: ksh and mksh - 'ksh-version' => system('ksh -c \'printf %s "$KSH_VERSION"\''), # shell, not env, variable + 'ksh-version' => $ksh, # shell, not env, variable 'manpath' => $ENV{'MANPATH'}, 'path' => $ENV{'PATH'}, 'xdg-config-home' => $ENV{'XDG_CONFIG_HOME'}, @@ -1765,14 +1796,14 @@ sub system_data { ); my @files = main::globber('/usr/bin/gcc*'); if (@files){ - $data{'gcc-versions'} = join "\n",@files; + $data{'gcc-versions'} = join("\n", @files); } else { $data{'gcc-versions'} = undef; } @files = main::globber('/sys/*'); if (@files){ - $data{'sys-tree-ls-1-basic'} = join "\n", @files; + $data{'sys-tree-ls-1-basic'} = join("\n", @files); } else { $data{'sys-tree-ls-1-basic'} = undef; @@ -1864,11 +1895,11 @@ sub system_files { copy_files(\@files, 'repo'); # chdir "/etc"; @files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); - push (@files, '/etc/issue'); - push (@files, '/etc/lsb-release'); - push (@files, '/etc/os-release'); - push (@files, '/system/build.prop');# android data file, requires rooted - push (@files, '/var/log/installer/oem-id'); # ubuntu only for oem installs? + push(@files, '/etc/issue'); + push(@files, '/etc/lsb-release'); + push(@files, '/etc/os-release'); + push(@files, '/system/build.prop');# android data file, requires rooted + push(@files, '/var/log/installer/oem-id'); # ubuntu only for oem installs? copy_files(\@files,'system-distro'); @files = main::globber('/etc/upstream[-_]{[rR]elease,[vV]ersion}/*'); copy_files(\@files,'system-distro'); @@ -1885,10 +1916,10 @@ sub system_files { ); @files2=main::globber('/sys/class/power_supply/*/uevent'); if (@files2){ - @files = (@files,@files2); + push(@files,@files2); } else { - push (@files, '/sys-class-power-supply-empty'); + push(@files, '/sys-class-power-supply-empty'); } copy_files(\@files, 'system'); @files = ( @@ -1906,9 +1937,10 @@ sub run_self { print "Starting $self_name from: $self_path\n"; my $i = ($option eq 'main-full')? ' -i' : ''; my $z = ($debugger{'filter'}) ? ' -z' : ''; + my $w = ($debugger{'width'}) ? $debugger{'width'} : 120; my $iz = "$i$z"; $iz =~ s/[\s-]//g; - my $cmd = "$self_path/$self_name -FRfJrploudmaxxx$i$z --slots --debug 10 -y 120 > $data_dir/$self_name-FRfJrploudmaxxx$iz-slots-y120.txt 2>&1"; + my $cmd = "$self_path/$self_name -FRfJLrploudma$i$z --slots --debug 10 -y $w > $data_dir/$self_name-FRfJLrploudma$iz-slots-y$w.txt 2>&1"; system($cmd); copy($log_file, "$data_dir") or main::error_handler('copy-failed', "$log_file", "$!"); system("$self_path/$self_name --recommends -y 120 > $data_dir/$self_name-recommends-120.txt 2>&1"); @@ -1949,29 +1981,28 @@ sub run_commands { my ($cmds,$type) = @_; my $holder = ''; my ($name,$cmd,$args); - foreach (@$cmds){ - my @rows = @$_; - if (my $program = main::check_program($rows[0])){ - if ($rows[1] eq 'present'){ - $name = "$data_dir/$type-cmd-$rows[0]-present"; + foreach my $rows (@$cmds){ + if (my $program = main::check_program($rows->[0])){ + if ($rows->[1] eq 'present'){ + $name = "$data_dir/$type-cmd-$rows->[0]-present"; main::toucher($name); } else { - $args = $rows[1]; + $args = $rows->[1]; $args =~ s/\s|--|\/|=/-/g; # for: $args =~ s/--/-/g;# strip out -- that result from the above $args =~ s/^-//g; $args = "-$args" if $args; - $name = "$data_dir/$type-cmd-$rows[0]$args.txt"; - $cmd = "$program $rows[1] >$name 2>&1"; + $name = "$data_dir/$type-cmd-$rows->[0]$args.txt"; + $cmd = "$program $rows->[1] >$name 2>&1"; system($cmd); } } else { - if ($holder ne $rows[0]){ - $name = "$data_dir/$type-cmd-$rows[0]-absent"; + if ($holder ne $rows->[0]){ + $name = "$data_dir/$type-cmd-$rows->[0]-absent"; main::toucher($name); - $holder = $rows[0]; + $holder = $rows->[0]; } } } @@ -1980,7 +2011,7 @@ sub write_data { my ($data_ref, $type) = @_; my ($empty,$error,$fh,$good,$name,$undefined,$value); foreach (keys %$data_ref) { - $value = $$data_ref{$_}; + $value = $data_ref->{$_}; $name = "$data_dir/$type-data-$_"; $good = $name . '.txt'; $empty = $name . '-empty'; @@ -2008,8 +2039,8 @@ sub build_tree { my $dirname = '/sys'; my $cmd; system("tree -a -L 10 /sys > $data_dir/sys-data-tree-full-10.txt"); - opendir my($dh), $dirname or main::error_handler('open-dir',"$dirname", "$!"); - my @files = readdir $dh; + opendir(my $dh, $dirname) or main::error_handler('open-dir',"$dirname", "$!"); + my @files = readdir($dh); closedir $dh; foreach (@files){ next if /^\./; @@ -2054,11 +2085,11 @@ sub directory_ls { my $output = ''; my ($type); my $result = qx($cmd); - open my $ch, '<', \$result or main::error_handler('open-data',"$cmd", "$!"); + open(my $ch, '<', \$result) or main::error_handler('open-data',"$cmd", "$!"); while ( my $line = <$ch> ){ chomp($line); $line =~ s/^\s+|\s+$//g; - @working = split /\s+/, $line; + @working = split(/\s+/, $line); $working[0] ||= ''; if ( scalar @working > 7 ){ if ($working[0] =~ /^d/ ){ @@ -2080,7 +2111,7 @@ sub directory_ls { } close $ch; my $file = "$data_dir/$dir-data-ls-$depth.txt"; - open my $fh, '>', $file or main::error_handler('create',"$file", "$!"); + open(my $fh, '>', $file) or main::error_handler('create',"$file", "$!"); print $fh $output; close $fh; # print "$output\n"; @@ -2088,34 +2119,34 @@ sub directory_ls { sub proc_traverse_data { print "Building /proc file list...\n"; # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied - no warnings 'File::Find'; + #no warnings 'File::Find'; + no warnings; $parse_src = 'proc'; - File::Find::find( \&wanted, "/proc"); - proc_traverse_processor(); + File::Find::find(\&wanted, "/proc"); + process_proc_traverse(); @content = (); } -sub proc_traverse_processor { +sub process_proc_traverse { my ($data,$fh,$result,$row,$sep); my $proc_dir = "$data_dir/proc"; print "Adding /proc files...\n"; mkdir $proc_dir or main::error_handler('mkdir', "$proc_dir", "$!"); # @content = sort @content; copy_files(\@content,'proc',$proc_dir); -# foreach (@content){ -# print "$_\n"; -# } +# foreach (@content){print "$_\n";} } sub sys_traverse_data { print "Building /sys file list...\n"; # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied - no warnings 'File::Find'; + #no warnings 'File::Find'; + no warnings; $parse_src = 'sys'; - File::Find::find( \&wanted, "/sys"); - sys_traverse_processsor(); + File::Find::find(\&wanted, "/sys"); + process_sys_traverse(); @content = (); } -sub sys_traverse_processsor { +sub process_sys_traverse { my ($data,$fh,$result,$row,$sep); my $filename = "sys-data-parse.txt"; print "Parsing /sys files...\n"; @@ -2130,7 +2161,7 @@ sub sys_traverse_processsor { # needed for removing -T test and root if ($b_fh){ while ($row = <$fh>) { - chomp $row; + chomp($row); $data .= $sep . '"' . $row . '"'; $sep=', '; } @@ -2142,7 +2173,7 @@ sub sys_traverse_processsor { # print "$_:[$data]\n" } # print scalar @content . "\n"; - open ($fh, '>', "$data_dir/$filename"); + open($fh, '>', "$data_dir/$filename"); print $fh $result; close $fh; # print $fh "$result"; @@ -2182,7 +2213,7 @@ sub wanted { return if $File::Find::name =~ /(\/mb_groups|debug)$/; } # print $File::Find::name . "\n"; - push (@content, $File::Find::name); + push(@content, $File::Find::name); return; } # args: 1 - path to file to be uploaded @@ -2195,7 +2226,7 @@ sub upload_file { my ($ftp, $domain, $host, $user, $pass, $dir, $error); $ftp_url ||= main::get_defaults('ftp-upload'); $ftp_url =~ s/\/$//g; # trim off trailing slash if present - my @url = split(/\//, $ftp_url); + my @url = split('/', $ftp_url); my $file_path = "$user_data_dir/$debug_gz"; $host = $url[0]; $dir = $url[1]; @@ -2244,7 +2275,7 @@ sub user_debug_test_1 { # print "With binmode: ", $item,"\n"; # print "Perl IO data:\n"; # print(join(', ', PerlIO::get_layers(STDOUT)), "\n"); -# close($duped); +# close $duped; } #### ------------------------------------------------------------------- @@ -2314,10 +2345,10 @@ sub get_file { my $debug = 0; my $fh; $file ||= 'N/A'; - log_data('dump','%{$response}',\%{$response}) if $b_log; - # print Dumper \%{$response}; - if ( ! $response->{success} ){ - my $content = $response->{content}; + log_data('dump','%{$response}',$response) if $b_log; + # print Dumper $response; + if ( ! $response->{'success'} ){ + my $content = $response->{'content'}; $content ||= "N/A\n"; my $msg = "Failed to connect to server/file!\n"; $msg .= "Response: ${content}Downloader: HTTP::Tiny URL: $url\nFile: $file"; @@ -2329,21 +2360,21 @@ sub get_file { if ( $debug ){ print "$response->{success}\n"; print "$response->{status} $response->{reason}\n"; - while (my ($key, $value) = each %{$response->{headers}}) { + while (my ($key, $value) = each %{$response->{'headers'}}) { for (ref $value eq "ARRAY" ? @$value : $value) { print "$key: $_\n"; } } } if ( $type eq "stdout" || $type eq "ua-stdout" ){ - $return = $response->{content}; + $return = $response->{'content'}; } elsif ($type eq "spider"){ # do nothing, just use the return value } elsif ($type eq "file"){ open($fh, ">", $file); - print $fh $response->{content}; # or die "can't write to file!\n"; + print $fh $response->{'content'}; # or die "can't write to file!\n"; close $fh; } } @@ -2535,31 +2566,31 @@ sub run { my $line = make_line(); my $pm = get_pm(); @data = basic_data($line,$pm); - push @rows,@data; + push(@rows, @data); if (!$bsd_type){ @data = check_items('required system directories',$line,$pm); - push @rows,@data; + push(@rows, @data); } @data = check_items('recommended system programs',$line,$pm); - push @rows,@data; + push(@rows, @data); @data = check_items('recommended display information programs',$line,$pm); - push @rows,@data; + push(@rows, @data); @data = check_items('recommended downloader programs',$line,$pm); - push @rows,@data; + push(@rows, @data); @data = check_items('recommended Perl modules',$line,$pm); - push @rows,@data; + push(@rows, @data); @data = check_items('recommended directories',$line,''); - push @rows,@data; + push(@rows, @data); @data = check_items('recommended files',$line,''); - push @rows,@data; + push(@rows, @data); @data = ( ['0', '', '', "$line"], ['0', '', '', "Ok, all done with the checks. Have a nice day."], ['0', '', '', " "], ); - push @rows,@data; + push(@rows, @data); #print Data::Dumper::Dumper \@rows; - main::print_basic(@rows); + main::print_basic(\@rows); exit 0; # shell true } @@ -2649,14 +2680,17 @@ sub check_items { $item = 'Program'; } elsif ($type eq 'recommended Perl modules'){ - @data = qw(HTTP::Tiny IO::Socket::SSL Time::HiRes Cpanel::JSON::XS JSON::XS XML::Dumper Net::FTP); + @data = qw(File::Copy File::Find File::Spec::Functions HTTP::Tiny IO::Socket::SSL + Time::HiRes Cpanel::JSON::XS JSON::XS XML::Dumper Net::FTP); $b_module = 1; $item = 'Perl Module'; $extra = ' (Optional)'; - $extra2 = "None of these are strictly required, but if you have them all, you can eliminate - some recommended non Perl programs from the install. "; + $extra2 = "None of these are strictly required, but if you have them all, you can + eliminate some recommended non Perl programs from the install. "; $extra3 = "HTTP::Tiny and IO::Socket::SSL must both be present to use as a downloader option. - For json export Cpanel::JSON::XS is preferred over JSON::XS."; + For json export Cpanel::JSON::XS is preferred over JSON::XS. To run --debug 20-22 File::Copy, + File::Find, and File::Spec::Functions must be present (most distros have these in Core Modules). + "; } elsif ($type eq 'recommended directories'){ if ($bsd_type){ @@ -2707,7 +2741,7 @@ sub check_items { } elsif ($b_file && -f $_){ $result = 'Unreadable'; - push @unreadable, "$_"; + push(@unreadable, "$_"); } else { $result = 'Missing'; @@ -2715,7 +2749,7 @@ sub check_items { $info{$pm} ||= 'N/A'; $install = " ~ Install package: $info{$pm}"; } - push @missing, "$_$install"; + push(@missing, "$_$install"); } $row = make_row($_,$about,$result); $rows[scalar @rows] = (['0', '', '', $row]); @@ -2892,7 +2926,7 @@ sub item_data { 'rpm' => 'bluez-utils', }), 'hddtemp' => ({ - 'info' => '-Dx show hdd temp', + 'info' => '-Dx show hdd temp, if no /sys drive temp', 'info-bsd' => '-Dx show hdd temp', 'apt' => 'hddtemp', 'pacman' => 'hddtemp', @@ -3068,6 +3102,27 @@ sub item_data { 'pacman' => 'perl-cpanel-json-xs', 'rpm' => 'perl-Cpanel-JSON-XS', }), + 'File::Copy' => ({ + 'info' => '--debug 20-22 - required to run debugger.', + 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'apt' => 'Core Modules', + 'pacman' => 'Core Modules', + 'rpm' => 'perl-File-Copy', + }), + 'File::Find' => ({ + 'info' => '--debug 20-22 - required to run debugger.', + 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'apt' => 'Core Modules', + 'pacman' => 'Core Modules', + 'rpm' => 'perl-File-Find', + }), + 'File::Spec::Functions' => ({ + 'info' => '--debug 20-22 - required to run debugger.', + 'info-bsd' => '--debug 20-22 - required to run debugger.', + 'apt' => 'Core Modules', + 'pacman' => 'Core Modules', + 'rpm' => 'Core Modules', + }), 'HTTP::Tiny' => ({ 'info' => '-U; -w,-W; -i (if dig not installed).', 'info-bsd' => '-U; -w,-W; -i (if dig not installed)', @@ -3112,8 +3167,7 @@ sub item_data { }), ## END PACKAGE MANAGER BLOCK ## ); - my $ref = $data{$type}; - my %values = %$ref; + my %values = %{$data{$type}}; return %values; } sub get_pm { @@ -3177,7 +3231,7 @@ sub awk { if ($result && defined $num){ $sep ||= '\s+'; $num-- if $num > 0; # retain the negative values as is - $result = (split /$sep/, $result)[$num]; + $result = (split(/$sep/, $result))[$num]; $result =~ s/^\s+|,|\s+$//g if $result; } eval $end if $b_log; @@ -3217,12 +3271,12 @@ sub compare_versions { elsif ($two && !$one){return $two;} elsif (!$one && !$two){return} my ($pad1,$pad2) = ('',''); - my (@temp1) = split /[._-]/, $one; - my (@temp2) = split /[._-]/, $two; + my (@temp1) = split(/[._-]/, $one); + my (@temp2) = split(/[._-]/, $two); @temp1 = map {$_ = sprintf("%04s", $_);$_ } @temp1; @temp2 = map {$_ = sprintf("%04s", $_);$_ } @temp2; - $pad1 = join '', @temp1; - $pad2 = join '', @temp2; + $pad1 = join('', @temp1); + $pad2 = join('', @temp2); # print "p1:$pad1 p2:$pad2\n"; if ($pad1 ge $pad2){return $one} elsif ($pad2 gt $pad1){return $two} @@ -3238,8 +3292,9 @@ sub convert_hex { # returns count of files in directory, if 0, dir is empty sub count_dir_files { return unless -d $_[0]; - opendir my $dh, $_[0] or error_handler('open-dir-failed', "$_[0]", $!); - my $count = grep { ! /^\.{1,2}/ } readdir $dh; # strips out . and .. + opendir(my $dh, $_[0]) or error_handler('open-dir-failed', "$_[0]", $!); + my $count = grep { ! /^\.{1,2}/ } readdir($dh); # strips out . and .. + closedir $dh; return $count; } @@ -3268,7 +3323,7 @@ sub grabber { eval $start if $b_log; my ($cmd,$split,$strip) = @_; $split ||= "\n"; - my @rows = split /$split/, qx($cmd); + my @rows = split(/$split/, qx($cmd)); if ($strip && @rows){ @rows = grep {/^\s*[^#]/} @rows; @rows = map {s/^\s+|\s+$//g; $_} @rows if @rows; @@ -3306,11 +3361,10 @@ sub is_numeric { # which we don't know are defined or not null. # args: 1 - array ref; 2 - join string; 3 - default value, optional sub joiner { - my ($ref,$join,$default) = @_; - my @arr = @$ref; + my ($arr,$join,$default) = @_; $default ||= ''; my $string = ''; - foreach (@arr){ + foreach (@$arr){ if (defined $_){ $string .= $_ . $join; } @@ -3628,7 +3682,7 @@ sub program_version { return 0 unless $extra && -r $extra; my @data = reader($extra,'strip'); @data = map {s/$stderr/ /;$_} @data if $stderr; # $stderr is the splitter - $output = join "\n",@data; + $output = join("\n", @data); $cmd = ''; } # These will mostly be shells that require running the shell command -c to get info data @@ -3658,7 +3712,7 @@ sub program_version { # sample: dwm-5.8.2, ©.. etc, why no space? who knows. Also get rid of v in number string # xfce, and other, output has , in it, so dump all commas and parentheses if ($output){ - open my $ch, '<', \$output or error_handler('open-data',"$cmd", "$!"); + open(my $ch, '<', \$output) or error_handler('open-data',"$cmd", "$!"); while (<$ch>){ #chomp; last if $count > $exit; @@ -3667,7 +3721,7 @@ sub program_version { # print "loop: $_ :: num: $num\n"; $_ =~ s/$replace//i if $replace; $_ =~ s/\s/_/g if $b_no_space; # needed for some items with version > 1 word - my @data = split /\s+/, $_; + my @data = split(/\s+/, $_); $version_nu = $data[$num]; last if ! defined $version_nu; # some distros add their distro name before the version data, which @@ -3734,19 +3788,22 @@ sub program_version_pkg { # arg: 1 - full file path, returns array of file lines. # 2 - optionsl, strip and clean data +# 3 - optional, return specific index, if it exists, else undef # note: chomp has to chomp the entire action, not just <$fh> sub reader { eval $start if $b_log; - my ($file,$strip) = @_; + my ($file,$strip,$index) = @_; return if ! $file; - open( my $fh, '<', $file ) or error_handler('open', $file, $!); + open(my $fh, '<', $file ) or error_handler('open', $file, $!); chomp(my @rows = <$fh>); - if ($strip && @rows){ + close $fh if $fh; + if (@rows && $strip){ @rows = grep {/^\s*[^#]/} @rows; @rows = map {s/^\s+|\s+$//g; $_} @rows if @rows; } eval $end if $b_log; - return @rows; + # note: returns undef scalar value if $rows[index] does not exist + return (defined $index) ? $rows[$index] : @rows; } # args: 1 - the file to create if not exists @@ -3768,28 +3825,28 @@ sub trimmer { return $str; } -# args: 1 - hash -# send array, assign to hash, return array, uniq values only. +# args: 1 - array, by ref, modifying by ref +# send array, assign to hash, changed array by reference, uniq values only. sub uniq { my %seen; - grep !$seen{$_}++, @_; + @{$_[0]} = grep !$seen{$_}++, @{$_[0]}; } -# arg: 1 file full path to write to; 2 - arrayof data to write. +# arg: 1 file full path to write to; 2 - array ref or scalar of data to write. # note: turning off strict refs so we can pass it a scalar or an array reference. sub writer { - my ($path, $ref_content) = @_; - my ($content); + my ($path, $content) = @_; + my ($contents); no strict 'refs'; - # print Dumper $ref_content, "\n"; - if (ref $ref_content eq 'ARRAY'){ - $content = join "\n", @$ref_content or die "failed with error $!"; + # print Dumper $content, "\n"; + if (ref $content eq 'ARRAY'){ + $contents = join("\n", @$content); # or die "failed with error $!"; } else { - $content = scalar $ref_content; + $contents = $content; } open(my $fh, ">", $path) or error_handler('open',"$path", "$!"); - print $fh $content; + print $fh $contents; close $fh; } @@ -3976,21 +4033,21 @@ sub set_man_location { # note, this is only now used for self updater function so it can get # the values from the UPDATED file, NOT the running program! sub set_version_data { - open (my $fh, '<', "$self_path/$self_name"); + open(my $fh, '<', "$self_path/$self_name"); while( my $row = <$fh>){ - chomp $row; + chomp($row); $row =~ s/'|;//g; if ($row =~ /^my \$self_name/ ){ - $self_name = (split /=/, $row)[1]; + $self_name = (split('=', $row))[1]; } elsif ($row =~ /^my \$self_version/ ){ - $self_version = (split /=/, $row)[1]; + $self_version = (split('=', $row))[1]; } elsif ($row =~ /^my \$self_date/ ){ - $self_date = (split /=/, $row)[1]; + $self_date = (split('=', $row))[1]; } elsif ($row =~ /^my \$self_patch/ ){ - $self_patch = (split /=/, $row)[1]; + $self_patch = (split('=', $row))[1]; } elsif ($row =~ /^## END INXI INFO/){ last; @@ -4003,9 +4060,8 @@ sub set_version_data { #### OPTIONS HANDLER / VERSION ######################################################################## -sub get_options{ +sub get_options { eval $start if $b_log; - my (@args) = @_; $show{'short'} = 1; my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_sensors_default, $b_recommends,$b_updater,$b_version,$b_use_man,$self_download, $download_id); @@ -4106,6 +4162,9 @@ sub get_options{ else { error_handler('bad-arg',$opt,$arg); } }, + 'L|lvm' => sub { + $show{'short'} = 0; + $show{'logical'} = 1; }, 'm|memory' => sub { $show{'short'} = 0; $show{'ram'} = 1; }, @@ -4252,11 +4311,12 @@ sub get_options{ if ($arg >= 8 ){ $b_admin = 1; $b_downloader = 1; - $show{'slot'} = 1; + $show{'logical'} = 1; $show{'process'} = 1; $show{'ps-cpu'} = 1; $show{'ps-mem'} = 1; $show{'repo'} = 1; + $show{'slot'} = 1; #$show{'weather'} = 1; } } @@ -4431,6 +4491,14 @@ sub get_options{ $debugger{'sys-print'} = 1; }, 'debug-test-1' => sub { $debugger{'test-1'} = 1; }, + 'debug-width:i' => sub { + my ($opt,$arg) = @_; + if ($arg =~ /^[0-9]+$/ && $arg >= 80){ + $debugger{'width'} = $arg; + } + else { + error_handler('bad-arg', $opt, $arg); + } }, 'dig' => sub { $b_skip_dig = 0; }, 'display:s' => sub { @@ -4469,8 +4537,16 @@ sub get_options{ else { error_handler('bad-arg', $opt, $arg); } }, + 'fake-cpu' => sub { + $b_fake_cpu = 1 }, 'fake-dmi' => sub { $b_fake_dmidecode = 1 }, + 'fake-logical' => sub { + $b_fake_logical = 1 }, + 'fake-raid' => sub { + $b_fake_raid = 1 }, + 'fake-sensors' => sub { + $b_fake_sensors = 1 }, 'ftp:s' => sub { my ($opt,$arg) = @_; # pattern: ftp.x.x/x @@ -4480,6 +4556,8 @@ sub get_options{ else { error_handler('bad-arg', $opt, $arg); }}, + 'hddtemp' => sub { + $b_hddtemp_force = 1 }, 'host|hostname' => sub { $show{'host'} = 1; $show{'no-host'} = 0}, @@ -4547,7 +4625,7 @@ sub get_options{ 'sensors-exclude:s' => sub { my ($opt,$arg) = @_; if ($arg){ - @sensors_exclude = split /\s*,\s*/, $arg; + @sensors_exclude = split(/\s*,\s*/, $arg); } else { error_handler('bad-arg',$opt,$arg); @@ -4555,7 +4633,7 @@ sub get_options{ 'sensors-use:s' => sub { my ($opt,$arg) = @_; if ($arg){ - @sensors_use = split /\s*,\s*/, $arg; + @sensors_use = split(/\s*,\s*/, $arg); } else { error_handler('bad-arg',$opt,$arg); @@ -4642,7 +4720,29 @@ sub get_options{ @sensors_exclude = (); @sensors_use = (); } - $b_block_tool = 1 if ( $b_admin && ($show{'partition'} || $show{'partition-full'} )); + if ($show{'short'} || $show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} || + $show{'logical'} || $show{'partition'} || $show{'partition-full'} || $show{'raid'} || + $show{'unmounted'}){ + $b_block_tool = 1; + } + if ($show{'raid'} || $show{'disk'} || $show{'disk-total'} || $show{'disk-basic'} + || $show{'unmounted'}){ + $b_mdadm = 1; + } + if ($bsd_type && ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'disk'})){ + $b_dm_boot_disk = 1; + } + if ($bsd_type && ($show{'optical-basic'} || $show{'optical'})){ + $b_dm_boot_optical = 1 + } + if ($b_admin && $show{'disk'}){ + $b_smartctl = 1; + } + # triggers may extend to -D, -pP + if ($show{'short'} || $show{'logical'} || $show{'raid'} || $show{'disk'} || + $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){ + $b_lvm = 1; + } set_sudo() if ( $show{'unmounted'} || ($extra > 0 && $show{'disk'}) ); $extra = 3 if $b_admin; $use{'filter'} = 0 if $use{'filter-override'}; @@ -4670,20 +4770,11 @@ sub get_options{ $show{'info'} || $show{'machine'} || $show{'process'} || $show{'ram'} || $show{'sensor'} ) ){ $b_sysctl = 1; } - if ($bsd_type && ($show{'short'} || $show{'disk-basic'} || $show{'disk-total'} || $show{'disk'})){ - $b_dm_boot_disk = 1; - } - if ($bsd_type && ($show{'optical-basic'} || $show{'optical'})){ - $b_dm_boot_optical = 1 - } - if ($b_admin && $show{'disk'}){ - $b_smartctl = 1; - } } sub show_options { error_handler('not-in-irc', 'help') if $b_irc; - my (@row,@rows,@data); + my (@data); my $line = ''; my $color_scheme_count = get_color_scheme('count') - 1; my $partition_string='partition'; @@ -4697,14 +4788,14 @@ sub show_options { for my $i ( 0 .. ( ( $size{'max'} / 2 ) - 2 ) ){ $line = $line . '- '; } - @rows = ( + push(@data, ['0', '', '', "$self_name supports the following options. For more detailed information, see man^$self_name. If you start $self_name with no arguments, it will display a short system summary." ], ['0', '', '', '' ], ['0', '', '', "You can use these options alone or together, to show or add the item(s) you want to see: A, B, C, D, G, I, J, M, N, P, - R, S, W, d, f, i, j, l, m, n, o, p, r, s, t, u, w, --slots. + R, S, W, d, f, i, j, l, L, m, n, o, p, r, s, t, u, w, --slots. If you use them with -v [level], -b or -F, $self_name will add the requested lines to the output." ], ['0', '', '', '' ], @@ -4722,7 +4813,7 @@ sub show_options { family, model-id, stepping - format: hex (decimal) if greater than 9, otherwise hex; microcode - format: hex." ], ['2', '-d,-D', '', "If available: logical and physical block sizes; drive family; - USB drive specifics; SMART report." ], + maj:min, USB drive specifics; SMART report." ], ['2', '-G', '', "If available: Xorg Display ID, Screens total, default Screen, current Screen; per X Screen: resolution, dpi, size, diagonal; per Monitor: resolution; hz; dpi; size; diagonal; list of alternate kernel modules/drivers @@ -4731,11 +4822,17 @@ sub show_options { number of lib files found for each package manager if not -r." ], ['2', '-j,-p,-P', '', "For swap (if available): swappiness and vfs cache pressure, and if values are default or not." ], + ['2', '-L', '', "LV, Crypto, devices, components: add maj:min; show + full device/components report (speed, mapped names)." ], ['2', '-n,-N', '', "If available: list of alternate kernel modules/drivers for device(s)." ], - ['2', '-p,-P', '', "If available: raw size of ${partition_string}s, + ['2', '-o', '', "If available: maj:min of device." ], + ['2', '-p,-P', '', "If available: raw size of ${partition_string}s, maj:min, percent available for user, block size of file system (root required)." ], ['2', '-r', '', "Packages, see -Ia." ], + ['2', '-L', '', "Show maj:min, component devices; per component/device: + size, maj:min." ], + ['2', '-R', '', "mdraid: device maj:min; per component: size, maj:min, state." ], ['2', '-S', '', "If available: kernel boot parameters." ], ['1', '-A', '--audio', "Audio/sound card(s), driver, sound server." ], ['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ], @@ -4776,6 +4873,8 @@ sub show_options { ['1', '-J', '--usb', "Show USB data: Hubs and Devices." ], ['1', '-l', '--label', "$partition_string_u labels. Triggers -P. For full -p output, use -pl." ], + ['1', '-L', '--logical', "Logical devices, LVM (VG, LV), + LUKS, Crypto, bcache, MultiPath. Shows compenents/devices, sizes, etc." ], ['1', '-m', '--memory', "Memory (RAM) data. Requires root. Numbers of devices (slots) supported and individual memory devices (sticks of memory etc). For devices, shows device locator, size, speed, type (e.g. DDR3). @@ -4804,7 +4903,7 @@ sub show_options { ['1', '-r', '--repos', "Distro repository data. Supported repo types: APK, APT, CARDS, EOPKG, PACMAN, PACMAN-G2, PISI, PORTAGE, PORTS (BSDs), SLACKPKG, TCE, URPMQ, XBPS, YUM/ZYPP." ], - ['1', '-R', '--raid', "RAID data. Shows RAID devices, states, levels, + ['1', '-R', '--raid', "RAID data. Shows RAID devices, states, levels, array sizes, and components. md-raid: If device is resyncing, also shows resync progress line." ], ['1', '-s', '--sensors', "Sensors output (if sensors installed/configured): mobo/CPU/GPU temp; detected fan speeds. GPU temp only for Fglrx/Nvidia drivers. @@ -4837,13 +4936,12 @@ sub show_options { unmounted $partition_string (-o), optical drive (-d), USB (-J), full RAID; triggers -xx." ], ['2', '7', '', "Network IP data (-i); triggers -xxx."], - ['2', '8', '', "Everything available, including repos (-r), processes - (-tcm), PCI slots (--slots)."], + ['2', '8', '', "Everything available, including logical (-L), + repos (-r), processes (-tcm), PCI slots (--slots)."], ); - push @data, @rows; # if distro maintainers don't want the weather feature disable it if ( $use{'weather'} ){ - @rows = ( + push(@data, ['1', '-w', '--weather', "Local weather data/time. To check an alternate location, see -W. NO AUTOMATED QUERIES ALLOWED!"], ['1', '-W', '--weather-location', "[location] Supported options for @@ -4857,9 +4955,8 @@ sub show_options { ['1', '', '--weather-unit', "Set weather units to metric (m), imperial (i), metric/imperial (mi), or imperial/metric (im)."], ); - push @data, @rows; } - @rows = ( + push(@data, ['1', '-x', '--extra', "Adds the following extra data (only works with verbose or line output, not short form):" ], ['2', '-A', '', "Specific vendor/product information (if relevant); @@ -4884,10 +4981,13 @@ sub show_options { GCC versions. If running in shell, not in IRC client, shows shell version number, if detected. Init/RC type and runlevel (if available). Total count of all packages discovered in system and not -r." ], + ['2', '-j', '', "Add mapped: name if partition mapped." ], ['2', '-J', '', "For Device: driver." ], + ['2', '-L', '', "For VG > LV, and other Devices, dm:" ], ['2', '-m,--memory-modules', '', "Max memory module size (if available), device type." ], ['2', '-N', '', "Specific vendor/product information (if relevant); PCI Bus ID/USB ID number of card; Version/port(s)/driver version (if available)." ], + ['2', '-o,-p,-P', '', "Add mapped: name if partition mapped." ], ['2', '-r', '', "Packages, see -Ix." ], ['2', '-R', '', "md-raid: second RAID Info line with extra data: blocks, chunk size, bitmap (if present). Resync line, shows blocks @@ -4898,19 +4998,19 @@ sub show_options { ['2', '-t', '', "Adds memory use output to CPU (-xt c), and CPU use to memory (-xt m)." ], ); - push @data, @rows; if ( $use{'weather'} ){ - @rows = (['2', '-w -W', '', "Wind speed and direction, humidity, pressure, + push(@data, + ['2', '-w -W', '', "Wind speed and direction, humidity, pressure, and time zone, if available." ]); - push @data, @rows; } - @rows = ( + push(@data, ['1', '-xx', '--extra 2', "Show extra, extra data (only works with verbose or line output, not short form):" ], ['2', '-A', '', "Chip vendor:product ID for each audio device." ], ['2', '-B', '', "Serial number, voltage now/minimum (if available)." ], ['2', '-C', '', "L1/L3 cache (if root and dmidecode installed)." ], - ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number." ], + ['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number; LVM + volume group free space (if available)." ], ['2', '-G', '', "Chip vendor:product ID for each video card; OpenGL compatibility version, if free drivers and available; Xorg compositor; alternate Xorg drivers (if available). Alternate means driver is on automatic @@ -4922,6 +5022,9 @@ sub show_options { package counts if not -r." ], ['2', '-j,-p,-P', '', "Swap priority." ], ['2', '-J', '', "Vendor:chip ID." ], + ['2', '-L', '', "Show internal LVM volumes, like raid image/meta volumes; + for LVM RAID, adds RAID report line (if not -R); show all components > + devices, number of 'c' or 'p' indicate depth of device." ], ['2', '-m,--memory-modules', '', "Manufacturer, part number; single/double bank (if found)." ], ['2', '-M', '', "Chassis info, BIOS ROM size (dmidecode only), if available." ], ['2', '-N', '', "Chip vendor:product ID." ], @@ -4934,13 +5037,13 @@ sub show_options { if available (Xfce/KDE/Trinity only)." ], ['2', '--slots', '', "Slot length." ], ); - push @data, @rows; if ( $use{'weather'} ){ - @rows = (['2', '-w -W', '', "Snow, rain, precipitation, (last observed hour), - cloud cover, wind chill, dew point, heat index, if available." ]); - push @data, @rows; + push(@data, + ['2', '-w -W', '', "Snow, rain, precipitation, (last observed hour), + cloud cover, wind chill, dew point, heat index, if available." ] + ); } - @rows = ( + push(@data, ['1', '-xxx', '--extra 3', "Show extra, extra, extra data (only works with verbose or line output, not short form):" ], ['2', '-A', '', "Serial number." ], @@ -4961,15 +5064,15 @@ sub show_options { Hardware RAID rev, ports, specific vendor/product information." ], ['2', '-S', '', "Panel/tray/bar/dock info in desktop output, if in X (like lxpanel, xfce4-panel, mate-panel); (if available) dm version number, window manager - version number." ], + version number."], ); - push @data, @rows; if ( $use{'weather'} ){ - @rows = (['2', '-w -W', '', "Location (uses -z/irc filter), weather observation - time, altitude, sunrise/sunset, if available." ] ); - push @data, @rows; + push(@data, + ['2', '-w -W', '', "Location (uses -z/irc filter), weather observation + time, altitude, sunrise/sunset, if available." ] + ); } - @rows = ( + push(@data, ['1', '-y', '--width', "Output line width max (integer >= 80). Overrides IRC/Terminal settings or actual widths. If no integer give, defaults to 80. -1 removes line lengths. 1 switches output to 1 key/value pair per line. Example:^inxi^-y^130" ], @@ -4986,11 +5089,10 @@ sub show_options { ['1', '-h', '--help', "This help menu." ], ['1', '', '--recommends', "Checks $self_name application dependencies + recommends, and directories, then shows what package(s) you need to install to add support - for that feature." ] + for that feature." ], ); - push @data, @rows; if ( $use{'update'} ){ - @rows = ( + push(@data, ['1', '-U', '--update', "Auto-update $self_name. Will also install/update man page. Note: if you installed as root, you must be root to update, otherwise user is fine. Man page installs require root. No arguments downloads from @@ -5000,11 +5102,10 @@ sub show_options { ['2', '2', '', "Get the git branch two version." ], ['3', '3', '', "Get the dev server (smxi.org) version." ], ['2', '', '', "Get a version of $self_name from your own server. - Use the full download path, e.g.^$self_name^-U^https://myserver.com/inxi" ] + Use the full download path, e.g.^$self_name^-U^https://myserver.com/inxi" ], ); - push @data, @rows; } - @rows = ( + push(@data, ['1', '-V', '--version', "Prints $self_name version info then exits." ], ['0', '', '', "$line" ], ['0', '', '', "Advanced Options:" ], @@ -5020,33 +5121,30 @@ sub show_options { ['1', '', '--dmidecode', "Force use of dmidecode data instead of /sys where relevant (e.g. -M, -B)." ], ['1', '', '--downloader', "Force $self_name to use [curl|fetch|perl|wget] for downloads." ], + ['1', '', '--hddtemp', "Force use of hddtemp for disk temps." ], ['1', '', '--host', "Turn on hostname for -S." ], ['1', '', '--html-wan', "Overrides configuration item NO_HTML_WAN (resets to default)." ], ['1', '', '--indent-min', "Set point where $self_name autowraps line starters." ], ['1', '', '--limit', "[-1; 1-x] Set max output limit of IP addresses for -i (default 10; -1 removes limit)." ], ); - push @data, @rows; if ( $use{'update'} ){ - @rows = ( + push(@data, ['1', '', '--man', "Install correct man version for dev branch (-U 3) or pinxi using -U." ], ); - push @data, @rows; } - @rows = ( + push(@data, ['1', '', '--no-dig', "Skip dig for WAN IP checks, use downloader program." ], ['1', '', '--no-host', "Turn off hostname for -S. Useful if showing output from servers etc." ], ['1', '', '--no-html-wan', "Skip HTML IP sources for WAN IP checks, use dig only, or nothing if --no-dig." ], ); - push @data, @rows; if ( $use{'update'} ){ - @rows = ( + push(@data, ['1', '', '--no-man', "Disable man install for all -U update actions." ], ); - push @data, @rows; } - @rows = ( + push(@data, ['1', '', '--no-ssl', "Skip SSL certificate checks for all downloader actions (Wget/Fetch/Curl/Perl-HTTP::Tiny)." ], ['1', '', '--no-sudo', "Skip internal program use of sudo features (not related @@ -5106,15 +5204,14 @@ sub show_options { Example:^$self_name^--debug^21^--ftp^ftp.myserver.com/incoming" ], ['0', '', '', "$line" ], ); - push @data, @rows; - print_basic(@data); + print_basic(\@data); exit 0; # shell true } sub show_version { # if not in PATH could be either . or directory name, no slash starting my $working_path=$self_path; - my (@data, @row, @rows, $link, $self_string); + my (@data,$link,$self_string); Cwd->import('getcwd'); # no point loading this on top use, we only use getcwd here if ( $working_path eq '.' ){ $working_path = getcwd(); @@ -5133,40 +5230,32 @@ sub show_version { } # strange output /./ ending, but just trim it off, I don't know how it happens $working_path =~ s%/\./%/%; - @row = ( - [ 0, '', '', "$self_name $self_version-$self_patch ($self_date)"], - ); - push @data, @row; + push(@data, [ 0, '', '', "$self_name $self_version-$self_patch ($self_date)"]); if ( ! $b_irc ){ - @row = ([ 0, '', '', ''],); - push @data, @row; + push(@data, [ 0, '', '', '']); my $year = (split/-/, $self_date)[0]; - @row = ( + push(@data, [ 0, '', '', "Copyright^(C)^2008-$year^Harald^Hope^aka^h2"], [ 0, '', '', "Forked from Infobash 3.02: Copyright^(C)^2005-2007^Michiel^de^Boer^aka^locsmif." ], [ 0, '', '', "Using Perl version: $]"], [ 0, '', '', "Program Location: $working_path" ], ); - push @data, @row; if ( $link ){ - @row = [ 0, '', '', "Started via symbolic link: $link" ]; - push @data, @row; + push(@data, [ 0, '', '', "Started via symbolic link: $link" ]); } - @rows = ( + push(@data, [ 0, '', '', '' ], [ 0, '', '', "Website:^https://github.com/smxi/inxi^or^https://smxi.org/" ], [ 0, '', '', "IRC:^irc.oftc.net channel:^#smxi" ], [ 0, '', '', "Forums:^https://techpatterns.com/forums/forum-33.html" ], - [ 0, '', '', '' ], [ 0, '', '', "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. (https://www.gnu.org/licenses/gpl.html)" ] ); - push @data, @rows; } - print_basic(@data); + print_basic(\@data); exit 0; # shell true } @@ -5240,7 +5329,7 @@ sub get_client_name { $ppid = getppid(); $client_name = (main::grabber("ps -p $ppid"))[1]; if ($client_name){ - my @data = split /\s+/, $client_name if $client_name; + my @data = split(/\s+/, $client_name) if $client_name; if ($bsd_type){ $client_name = lc($data[5]); } @@ -5284,7 +5373,7 @@ sub get_client_version { $string = awk(\@data,'Version'); if ($string){ $string =~ s/[()]|bitchx-//g; - @data = split /\s+/, $string; + @data = split(/\s+/, $string); $_=lc for @data; $client{'version'} = ($data[1] eq 'version') ? $data[2] : $data[1]; } @@ -5319,11 +5408,11 @@ sub get_client_version { @data = main::grabber("$client{'name'} -v 2>/dev/null"); foreach (@data){ if ($_ =~ /^Quassel IRC:/){ - $client{'version'} = (split /\s+/, $_ )[2]; + $client{'version'} = (split(/\s+/, $_))[2]; last; } elsif ($_ =~ /quassel\s[v]?[0-9]/){ - $client{'version'} = (split /\s+/, $_ )[1]; + $client{'version'} = (split(/\s+/, $_))[1]; last; } } @@ -5391,7 +5480,7 @@ sub get_cmdline { my @rows = <$fh>; close $fh; foreach (@rows){ - push @cmdline, $_; + push(@cmdline, $_); $i++; last if $i > 31; } @@ -5476,7 +5565,7 @@ sub check_modern_konvi { if ($konvi){ @app = main::program_values('konversation'); $konvi_version = main::program_version($konvi,$app[0],$app[1],$app[2],$app[5],$app[6]); - @temp = split /\./, $konvi_version; + @temp = split('\.', $konvi_version); $client{'console-irc'} = $app[4]; $client{'konvi'} = 3; $client{'name'} = 'konversation'; @@ -5531,7 +5620,7 @@ sub set_konvi_data { # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf if ($config_tool){ my @data = main::grabber("$config_tool --path data 2>/dev/null",':'); - main::get_configs(@data); + main::get_configs(\@data); } eval $end if $b_log; } @@ -5624,11 +5713,15 @@ sub dmi_cleaner { return $string; } -# args: $1 - size in KB, return KB, MB, GB, TB, PB, EB +# args: $1 - size in KB, return KB, MB, GB, TB, PB, EB; $2 - 'string'; +# $3 - default value if null +# returns string with units or array or size unmodified if not numeric sub get_size { - my ($size,$b_int) = @_; + my ($size,$type,$empty) = @_; my (@data); - return ('','') if ! defined $size; + $type ||= ''; + $empty ||= ''; + return $empty if !defined $size; if (!is_numeric($size)){ $data[0] = $size; $data[1] = ''; @@ -5657,17 +5750,24 @@ sub get_size { $data[0] = sprintf("%.0f",$size); $data[1] = 'KiB'; } - $data[0] = int($data[0]) if $b_int && $data[0]; - return @data; + $data[0] += 0 if $data[1]; # trim trailing 0s + # note: perl throws strict error if you try to convert string to int + # $data[0] = int($data[0]) if $b_int && $data[0]; + if ($type eq 'string'){ + return ($data[1]) ? join(' ', @data) : $size; + } + else { + return @data; + } } # not used, but keeping logic for now sub increment_starters { my ($key,$indexes) = @_; my $result = $key; - if (defined $$indexes{$key} ){ - $$indexes{$key}++; - $result = "$key-$$indexes{$key}"; + if (defined $indexes->{$key} ){ + $indexes->{$key}++; + $result = "$key-$indexes->{$key}"; } return $result; } @@ -5724,14 +5824,13 @@ sub remove_duplicates { return if ! $string; my $holder = ''; my (@temp); - my @data = split /\s+/, $string; - foreach (@data){ + foreach (split(/\s+/, $string)){ if ($holder ne $_){ - push @temp, $_; + push(@temp, $_); } $holder = $_; } - $string = join ' ', @temp; + $string = join(' ', @temp); return $string; } @@ -5751,7 +5850,7 @@ sub row_defaults { 'disk-data-bsd' => 'No Disk data found for this BSD system.', 'disk-size-0' => 'Total N/A', 'display-console' => 'No advanced graphics data found on this system in console.', - 'display-driver-na' => 'display driver n/a', + 'display-driver-na' => 'n/a (using device driver)', 'display-null' => 'No advanced graphics data found on this system.', 'display-root' => 'Advanced graphics data unavailable in console for root.', 'display-root-x' => 'Advanced graphics data unavailable for root.', @@ -5767,11 +5866,15 @@ sub row_defaults { 'dmidecode-smbios' => 'No SMBIOS data for dmidecode to process', 'IP-dig' => "No $id found. Connected to web? SSL issues? Try --no-dig", 'IP-no-dig' => "No $id found. Connected to web? SSL issues? Try enabling dig", + 'lvm-data' => 'No LVM data was found.', + 'lvm-data-bsd' => 'No BSD support for LVM data.', 'machine-data' => 'No Machine data: try newer kernel.', 'machine-data-bsd' => 'No Machine data: Is dmidecode installed? Try -M --dmidecode.', 'machine-data-dmidecode' => 'No Machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', 'machine-data-force-dmidecode' => 'No Machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.', 'mips-pci' => 'No MIPS data found for this feature.', + 'note-check' => 'check', + 'note-est' => 'est.', 'optical-data' => 'No Optical or Floppy data was found.', 'optical-data-bsd' => 'No Optical or Floppy data found for this BSD system.', 'output-limit' => "Output throttled. IPs: $id; Limit: $limit; Override: --limit [1-x;-1 all]", @@ -5785,7 +5888,7 @@ sub row_defaults { 'ps-data-null' => 'No Process data available.', 'raid-data' => 'No RAID data was found.', 'ram-data' => 'No RAM data was found.', - 'root-required' => '', + 'root-required' => '', 'root-suggested' => 'try sudo/root', 'sensors-data-ipmi' => 'No ipmi sensors data was found.', 'sensors-data-linux' => 'No sensors data was found. Is sensors configured?', @@ -5860,37 +5963,37 @@ sub check_output_path { $b_good = 1 if (-d $dir && -w $dir && $dir =~ /^\// && $file); return $b_good; } - +# passing along hash ref sub output_handler { - my (%data) = @_; + my ($data) = @_; # print Dumper \%data; if ($output_type eq 'screen'){ - print_data(%data); + print_data($data); } elsif ($output_type eq 'json'){ - generate_json(%data); + generate_json($data); } elsif ($output_type eq 'xml'){ - generate_xml(%data); + generate_xml($data); } } - +# passing along hash ref # NOTE: file has already been set and directory verified sub generate_json { eval $start if $b_log; - my (%data) = @_; + my ($data) = @_; my ($json); my $b_debug = 1; my ($b_cpanel,$b_valid); error_handler('not-in-irc', 'help') if $b_irc; - #print Dumper \%data if $b_debug; + print Dumper $data if $b_debug; if (check_module('Cpanel::JSON::XS')){ Cpanel::JSON::XS->import; - $json = Cpanel::JSON::XS::encode_json(\%data); + $json = Cpanel::JSON::XS::encode_json($data); } elsif (check_module('JSON::XS')){ JSON::XS->import; - $json = JSON::XS::encode_json(\%data); + $json = JSON::XS::encode_json($data); } else { error_handler('required-module', 'json', 'Cpanel::JSON::XS OR JSON::XS'); @@ -5917,14 +6020,14 @@ sub generate_json { # least xml has some output now. sub generate_xml { eval $start if $b_log; - my (%data) = @_; + my ($data) = @_; my ($xml); my $b_debug = 0; error_handler('not-in-irc', 'help') if $b_irc; - #print Dumper \%data if $b_debug; + #print Dumper $data if $b_debug; if (check_module('XML::Dumper')){ XML::Dumper->import; - $xml = XML::Dumper::pl2xml(\%data); + $xml = XML::Dumper::pl2xml($data); #$xml =~ s/"[0-9]+#/"/g; if ($output_file eq 'print'){ print "$xml"; @@ -5948,15 +6051,15 @@ sub key { } sub print_basic { - my (@data) = @_; + my ($data) = @_; my $indent = 18; my $indent_static = 18; my $indent1_static = 5; my $indent2_static = 8; my $indent1 = 5; my $indent2 = 8; - my $length = @data; - my ($start,$aref,$i,$j,$line); + my $length = @$data; + my ($start,$i,$j,$line); if ( $size{'max'} > 110 ){ $indent_static = 22; @@ -5965,46 +6068,47 @@ sub print_basic { $indent_static = 15; } # print $length . "\n"; - for my $i (0 .. $#data){ - $aref = $data[$i]; - #print "0: $data[$i][0]\n"; - if ($data[$i][0] == 0 ){ + for my $i (0 .. $#$data){ + #print "0: $data->[$i][0]\n"; + if ($data->[$i][0] == 0 ){ $indent = 0; $indent1 = 0; $indent2 = 0; } - elsif ($data[$i][0] == 1 ){ + elsif ($data->[$i][0] == 1 ){ $indent = $indent_static; $indent1 = $indent1_static; $indent2= $indent2_static; } - elsif ($data[$i][0] == 2 ){ + elsif ($data->[$i][0] == 2 ){ $indent = ( $indent_static + 7 ); $indent1 = ( $indent_static + 5 ); $indent2 = 0; } - $data[$i][3] =~ s/\n/ /g; - $data[$i][3] =~ s/\s+/ /g; - if ($data[$i][1] && $data[$i][2]){ - $data[$i][1] = $data[$i][1] . ', '; + $data->[$i][3] =~ s/\n/ /g; + $data->[$i][3] =~ s/\s+/ /g; + if ($data->[$i][1] && $data->[$i][2]){ + $data->[$i][1] = $data->[$i][1] . ', '; } - $start = sprintf("%${indent1}s%-${indent2}s",$data[$i][1],$data[$i][2]); + $start = sprintf("%${indent1}s%-${indent2}s",$data->[$i][1],$data->[$i][2]); if ($indent > 1 && ( length($start) > ( $indent - 1) ) ){ $line = sprintf("%-${indent}s\n", "$start"); print_line($line); $start = ''; #print "1-print.\n"; } - if ( ( $indent + length($data[$i][3]) ) < $size{'max'} ){ - $data[$i][3] =~ s/\^/ /g; - $line = sprintf("%-${indent}s%s\n", "$start", $data[$i][3]); + if ( ( $indent + length($data->[$i][3]) ) < $size{'max'} ){ + $data->[$i][3] =~ s/\^/ /g; + $line = sprintf("%-${indent}s%s\n", "$start", $data->[$i][3]); print_line($line); #print "2-print.\n"; } else { my $holder = ''; my $sep = ' '; - foreach my $word (split / /, $data[$i][3]){ + # note: special case, split ' ' trims leading, trailing spaces, + # then splits like awk, on one or more white spaces. + foreach my $word (split(' ', $data->[$i][3])){ #print "$word\n"; if ( ( $indent + length($holder) + length($word) ) < $size{'max'} ) { $word =~ s/\^/ /g; @@ -6034,7 +6138,7 @@ sub print_basic { # because perl does not retain insertion order, I use a prefix for each # hash key to force sorts. sub print_data { - my (%data) = @_; + my ($data) = @_; my ($array,$counter,$length,$split_count) = (0,0,0,0); my ($hash_id,$holder,$start,$start2,$start_holder) = ('','','','',''); my $indent = $size{'indent'}; @@ -6048,10 +6152,10 @@ sub print_data { if ($size{'max'} < $size{'indent-min'} || $size{'indent'} < 11 ){ $indent = 2; } - #foreach my $key1 (sort { (split/#/, $a)[0] <=> (split/#/, $b)[0] } keys %data) { - foreach my $key1 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %data) { - #foreach my $key1 (sort { $a cmp $b } keys %data) { - $key = (split/#/, $key1)[3]; + #foreach my $key1 (sort { (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$data) { + foreach my $key1 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %$data) { + #foreach my $key1 (sort { $a cmp $b } keys %$data) { + $key = (split('#', $key1))[3]; if ($key ne 'SHORT' ) { $start = sprintf("$colors{'c1'}%-${indent}s$colors{'cn'}","$key$sep{'s1'}"); $start_holder = $key; @@ -6065,8 +6169,8 @@ sub print_data { else { $indent = 0; } - next if ref($data{$key1}) ne 'ARRAY'; - # @working = @{$data{$key1}}; + next if ref($data->{$key1}) ne 'ARRAY'; + # @working = @{$data->{$key1}}; # Line starters that will be -x incremented always # It's a tiny bit faster manually resetting rather than using for loop %ids = ( @@ -6078,20 +6182,21 @@ sub print_data { 'Hardware' => 1, # hardware raid report 'ID' => 1, 'IF-ID' => 1, + 'LV' => 1, 'Monitor' => 1, 'Optical' => 1, 'Screen' => 1, 'variant' => 1, # arm > 1 cpu type ); - foreach my $val1 (@{$data{$key1}}){ + foreach my $val1 (@{$data->{$key1}}){ $indent_use = $length = $indent; if (ref($val1) eq 'HASH'){ #%row = %$val1; ($counter,$split_count) = (0,0); - #foreach my $key2 (sort { (split/#/, $a)[0] <=> (split/#/, $b)[0] } keys %$val1){ + #foreach my $key2 (sor ({ (split('#', $a))[0] <=> (split('#', $b))[0] } keys %$val1){ foreach my $key2 (sort { substr($a,0,3) <=> substr($b,0,3) } keys %$val1){ #foreach my $key2 (sort { $a cmp $b } keys %$val1){ - ($hash_id,$b_container,$indentx,$key) = (split/#/, $key2); + ($hash_id,$b_container,$indentx,$key) = (split('#', $key2)); if ($start_holder eq 'Graphics' && $key eq 'Screen'){ $ids{'Monitor'} = 1; } @@ -6104,17 +6209,20 @@ sub print_data { elsif ($start_holder eq 'USB' && $key eq 'Hub'){ $ids{'Device'} = 1; } + elsif ($start_holder eq 'Logical' && $key eq 'Device'){ + $ids{'LV'} = 1; + } if ($counter == 0 && defined $ids{$key}){ $key .= '-' . $ids{$key}++; } - $val2 = $$val1{$key2}; + $val2 = $val1->{$key2}; # we have to handle cases where $val2 is 0 if (!$b_single && $val2 || $val2 eq '0'){ $val2 .= " "; } # see: Use of implicit split to @_ is deprecated. Only get this warning # in Perl 5.08 oddly enough. - @temp = split/\s+/, $val2; + @temp = split(/\s+/, $val2); $split_count = scalar @temp; if ( !$b_single && ( length( "$key$sep{'s2'} $val2" ) + $length ) < $size{'max'} ) { #print "one\n"; @@ -6127,7 +6235,7 @@ sub print_data { elsif ( !$b_single && ( length( "$key$sep{'s2'} $val2" ) + $indent ) > $size{'max'} && !defined $ids{$key} && $split_count > 2 ) { #print "two\n"; - @values = split/\s+/, $val2; + @values = split(/\s+/, $val2); $val3 = shift @values; # $length += length("$key$sep{'s2'} $val3 ") + $indent; $start2 = "$colors{'c1'}$key$sep{'s2'}$colors{'c2'} $val3 "; @@ -6273,91 +6381,85 @@ sub get { if (($b_arm || $b_mips) && !$b_soc_audio && !$b_pci_tool){ my $type = ($b_arm) ? 'arm' : 'mips'; my $key = 'Message'; - @data = ({ + push(@rows,{ main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), },); - @rows = (@rows,@data); } else { @data = card_data(); - @rows = (@rows,@data); + push(@rows,@data); } if ( ( (($b_arm || $b_mips) && !$b_soc_audio && !$b_pci_tool) || !@rows ) && (my $file = main::system_files('asound-cards') ) ){ @data = asound_data($file); - @rows = (@rows,@data); + push(@rows,@data); } @data = usb_data(); - @rows = (@rows,@data); + push(@rows,@data); if (!@rows){ my $key = 'Message'; my $type = 'pci-card-data'; - if ($pci_tool && ${$alerts{$pci_tool}}{'action'} eq 'permissions'){ + if ($pci_tool && $alerts{$pci_tool}->{'action'} eq 'permissions'){ $type = 'pci-card-data-root'; } - @data = ({ + push(@rows,{ main::key($num++,0,1,$key) => main::row_defaults($type,''), },); - @rows = (@rows,@data); } @data = sound_server_data(); - @rows = (@rows,@data); + push(@rows,@data); eval $end if $b_log; return @rows; } sub card_data { eval $start if $b_log; - my (@rows,@data); + my (@rows); my ($j,$num) = (0,1); - foreach (@devices_audio){ + foreach my $row (@devices_audio){ $num = 1; - my @row = @$_; $j = scalar @rows; - my $driver = $row[9]; + my $driver = $row->[9]; $driver ||= 'N/A'; - my $card = $row[4]; + my $card = $row->[4]; $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; # have seen absurdly verbose card descriptions, with non related data etc if (length($card) > 85 || $size{'max'} < 110){ $card = main::pci_long_filter($card); } - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $card, },); - @rows = (@rows,@data); - if ($extra > 0 && $b_pci_tool && $row[12]){ - my $item = main::get_pci_vendor($row[4],$row[12]); + if ($extra > 0 && $b_pci_tool && $row->[12]){ + my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]{main::key($num++,0,2,'vendor')} = $item if $item; } $rows[$j]{main::key($num++,1,2,'driver')} = $driver; if ($extra > 0 && !$bsd_type){ - if ($row[9] ){ - my $version = main::get_module_version($row[9]); + if ($row->[9] ){ + my $version = main::get_module_version($row->[9]); $rows[$j]{main::key($num++,0,3,'v')} = $version if $version; } } - if ($b_admin && $row[10]){ - $row[10] = main::get_driver_modules($row[9],$row[10]); - $rows[$j]{main::key($num++,0,3,'alternate')} = $row[10] if $row[10]; + if ($b_admin && $row->[10]){ + $row->[10] = main::get_driver_modules($row->[9],$row->[10]); + $rows[$j]{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10]; } if ($extra > 0){ - $rows[$j]{main::key($num++,0,2,'bus ID')} = (!$row[2] && !$row[3]) ? 'N/A' : "$row[2].$row[3]"; + $rows[$j]{main::key($num++,0,2,'bus ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; } if ($extra > 1){ my $chip_id = 'N/A'; - if ($row[5] && $row[6]){ - $chip_id = "$row[5]:$row[6]"; + if ($row->[5] && $row->[6]){ + $chip_id = "$row->[5]:$row->[6]"; } - elsif ($row[6]){ - $chip_id = $row[6]; + elsif ($row->[6]){ + $chip_id = $row->[6]; } $rows[$j]{main::key($num++,0,2,'chip ID')} = $chip_id; } - #print "$row[0]\n"; + #print "$row->[0]\n"; } - #my $ref = $pci[-1]; - #print $$ref[0],"\n"; eval $end if $b_log; return @rows; } @@ -6367,7 +6469,7 @@ sub card_data { sub asound_data { eval $start if $b_log; my ($file) = @_; - my (@asound,@rows,@data); + my (@asound,@rows); my ($card,$driver,$j,$num) = ('','',0,1); @asound = main::reader($file); foreach (@asound){ @@ -6375,7 +6477,7 @@ sub asound_data { # usb audio card as well, this will take some trial and error if ( !/modem|usb/i && /^\s*[0-9]/ ) { $num = 1; - my @working = split /:\s*/, $_; + my @working = split(/:\s*/, $_); # now let's get 1 2 $working[1] =~ /(.*)\s+-\s+(.*)/; $card = $2; @@ -6383,11 +6485,10 @@ sub asound_data { if ( $card ){ $j = scalar @rows; $driver ||= 'N/A'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $card, main::key($num++,1,2,'driver') => $driver, },); - @rows = (@rows,@data); if ($extra > 0){ my $version = main::get_module_version($driver); $rows[$j]{main::key($num++,0,3,'v')} = $version if $version; @@ -6402,15 +6503,15 @@ sub asound_data { } sub usb_data { eval $start if $b_log; - my (@rows,@data,@ids,$driver,$path_id,$product,@temp2); + my (@rows,@ids,$driver,$path_id,$product,@temp2); my ($j,$num) = (0,1); if (-d '/proc/asound') { # note: this will double the data, but it's easier this way. # inxi tested for -L in the /proc/asound files, and used only those. my @files = main::globber('/proc/asound/*/usbid'); foreach (@files){ - my $id = (main::reader($_))[0]; - push @ids, $id if ($id && ! grep {/$id/} @ids); + my $id = main::reader($_,'',0); + push(@ids, $id) if ($id && ! grep {/$id/} @ids); } # lsusb is a very expensive operation if (@ids){ @@ -6422,33 +6523,31 @@ sub usb_data { return if !@usb; foreach my $id (@ids){ $j = scalar @rows; - foreach my $ref (@usb){ - my @row = @$ref; + foreach my $row (@usb){ # a device will always be the second or > device on the bus - if ($row[1] > 1 && $row[7] eq $id){ + if ($row->[1] > 1 && $row->[7] eq $id){ $num = 1; # makre sure to reset, or second device trips last flag ($driver,$path_id,$product) = ('','',''); - $product = main::cleaner($row[13]) if $row[13]; - $driver = $row[15] if $row[15]; - $path_id = $row[2] if $row[2]; + $product = main::cleaner($row->[13]) if $row->[13]; + $driver = $row->[15] if $row->[15]; + $path_id = $row->[2] if $row->[2]; $product ||= 'N/A'; $driver ||= 'snd-usb-audio'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $product, main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $driver, },); - @rows = (@rows,@data); if ($extra > 0){ - $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row[1]"; + $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row->[1]"; } if ($extra > 1){ - $row[7] ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'chip ID')} = $row[7]; + $row->[7] ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'chip ID')} = $row->[7]; } - if ($extra > 2 && $row[16]){ - $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row[16]); + if ($extra > 2 && $row->[16]){ + $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row->[16]); } } } @@ -6463,13 +6562,13 @@ sub sound_server_data { my (@data,$server,$version); my $num = 0; if (my $file = main::system_files('asound-version') ){ - my $content = (main::reader($file))[0]; + my $content = main::reader($file,'',0); # some alsa strings have the build date in (...) # remove trailing . and remove possible second line if compiled by user # foreach (@content){ # if (!/compile/i){ #$_ =~ s/Advanced Linux Sound Architecture/ALSA/; - $version = (split /\s+/, $content)[-1]; + $version = (split(/\s+/, $content))[-1]; $version =~ s/\.$//; # trim off period $server = 'ALSA'; # } @@ -6500,10 +6599,9 @@ sub get { my (@rows,%battery,$key1,$val1); my $num = 0; if ($bsd_type || $b_dmidecode_force){ - my $ref = $alerts{'dmidecode'}; - if ( $$ref{'action'} ne 'use'){ - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; + if ($alerts{'dmidecode'}->{'action'} ne 'use'){ + $key1 = $alerts{'dmidecode'}->{'action'}; + $val1 = $alerts{'dmidecode'}->{$key1}; $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } @@ -6517,7 +6615,7 @@ sub get { } } else { - @rows = create_output(%battery); + @rows = create_output(\%battery); } } } @@ -6531,7 +6629,7 @@ sub get { } } else { - @rows = create_output(%battery); + @rows = create_output(\%battery); } } else { @@ -6568,63 +6666,62 @@ sub get { # 17 location sub create_output { eval $start if $b_log; - my (%battery) = @_; - my ($key,@data,@rows); + my ($battery) = @_; + my ($key,@rows); my $num = 0; my $j = 0; - # print Data::Dumper::Dumper \%battery; - foreach $key (sort keys %battery){ + # print Data::Dumper::Dumper $battery; + foreach $key (sort keys %$battery){ $num = 0; my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','',''); my ($chemistry,$cycles,$location) = ('','',''); - next if !$battery{$key}{'purpose'} || $battery{$key}{'purpose'} ne 'primary'; - # $battery{$key}{''}; + next if !$battery->{$key}{'purpose'} || $battery->{$key}{'purpose'} ne 'primary'; + # $battery->{$key}{''}; # we need to handle cases where charge or energy full is 0 - if (defined $battery{$key}{'energy_now'} && $battery{$key}{'energy_now'} ne ''){ - $charge = "$battery{$key}{'energy_now'} Wh"; + if (defined $battery->{$key}{'energy_now'} && $battery->{$key}{'energy_now'} ne ''){ + $charge = "$battery->{$key}{'energy_now'} Wh"; } # better than nothing, shows the charged percent - elsif (defined $battery{$key}{'capacity'} && $battery{$key}{'capacity'} ne ''){ - $charge = $battery{$key}{'capacity'} . '%' + elsif (defined $battery->{$key}{'capacity'} && $battery->{$key}{'capacity'} ne ''){ + $charge = $battery->{$key}{'capacity'} . '%' } else { $charge = 'N/A'; } - if ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full_design'}){ - $battery{$key}{'energy_full_design'} ||= 'N/A'; - $battery{$key}{'energy_full'}= (defined $battery{$key}{'energy_full'} && $battery{$key}{'energy_full'} ne '') ? $battery{$key}{'energy_full'} : 'N/A'; - $condition = "$battery{$key}{'energy_full'}/$battery{$key}{'energy_full_design'} Wh"; - if ($battery{$key}{'of_orig'}){ - $condition .= " ($battery{$key}{'of_orig'}%)"; + if ($battery->{$key}{'energy_full'} || $battery->{$key}{'energy_full_design'}){ + $battery->{$key}{'energy_full_design'} ||= 'N/A'; + $battery->{$key}{'energy_full'}= (defined $battery->{$key}{'energy_full'} && $battery->{$key}{'energy_full'} ne '') ? $battery->{$key}{'energy_full'} : 'N/A'; + $condition = "$battery->{$key}{'energy_full'}/$battery->{$key}{'energy_full_design'} Wh"; + if ($battery->{$key}{'of_orig'}){ + $condition .= " ($battery->{$key}{'of_orig'}%)"; } } $condition ||= 'N/A'; $j = scalar @rows; - @data = ({ + push(@rows, { main::key($num++,1,1,'ID') => $key, main::key($num++,0,2,'charge') => $charge, main::key($num++,0,2,'condition') => $condition, },); - @rows = (@rows,@data); if ($extra > 0){ if ($extra > 1){ - if ($battery{$key}{'voltage_min_design'} || $battery{$key}{'voltage_now'}){ - $battery{$key}{'voltage_min_design'} ||= 'N/A'; - $battery{$key}{'voltage_now'} ||= 'N/A'; - $volts = "$battery{$key}{'voltage_now'}/$battery{$key}{'voltage_min_design'}"; + if ($battery->{$key}{'voltage_min_design'} || $battery->{$key}{'voltage_now'}){ + $battery->{$key}{'voltage_min_design'} ||= 'N/A'; + $battery->{$key}{'voltage_now'} ||= 'N/A'; + $volts = "$battery->{$key}{'voltage_now'}/$battery->{$key}{'voltage_min_design'}"; } $volts ||= 'N/A'; $rows[$j]{main::key($num++,0,2,'volts')} = $volts; } - if ($battery{$key}{'manufacturer'} || $battery{$key}{'model_name'}) { - if ($battery{$key}{'manufacturer'} && $battery{$key}{'model_name'}){ - $model = "$battery{$key}{'manufacturer'} $battery{$key}{'model_name'}"; + if ($battery->{$key}{'manufacturer'} || $battery->{$key}{'model_name'}) { + if ($battery->{$key}{'manufacturer'} && $battery->{$key}{'model_name'}){ + $model = "$battery->{$key}{'manufacturer'} $battery->{$key}{'model_name'}"; } - elsif ($battery{$key}{'manufacturer'}){ - $model = $battery{$key}{'manufacturer'}; + elsif ($battery->{$key}{'manufacturer'}){ + $model = $battery->{$key}{'manufacturer'}; } - elsif ($battery{$key}{'model_name'}){ - $model = $battery{$key}{'model_name'}; + elsif ($battery->{$key}{'model_name'}){ + $model = $battery->{$key}{'model_name'}; } } else { @@ -6632,33 +6729,33 @@ sub create_output { } $rows[$j]{main::key($num++,0,2,'model')} = $model; if ($extra > 2){ - $chemistry = ( $battery{$key}{'technology'} ) ? $battery{$key}{'technology'}: 'N/A'; + $chemistry = ( $battery->{$key}{'technology'} ) ? $battery->{$key}{'technology'}: 'N/A'; $rows[$j]{main::key($num++,0,2,'type')} = $chemistry; } if ($extra > 1){ - $serial = main::apply_filter($battery{$key}{'serial_number'}); + $serial = main::apply_filter($battery->{$key}{'serial_number'}); $rows[$j]{main::key($num++,0,2,'serial')} = $serial; } - $status = ($battery{$key}{'status'}) ? $battery{$key}{'status'}: 'N/A'; + $status = ($battery->{$key}{'status'}) ? $battery->{$key}{'status'}: 'N/A'; $rows[$j]{main::key($num++,0,2,'status')} = $status; if ($extra > 2){ - if ($battery{$key}{'cycle_count'}){ - $rows[$j]{main::key($num++,0,2,'cycles')} = $battery{$key}{'cycle_count'}; + if ($battery->{$key}{'cycle_count'}){ + $rows[$j]{main::key($num++,0,2,'cycles')} = $battery->{$key}{'cycle_count'}; } - if ($battery{$key}{'location'}){ - $rows[$j]{main::key($num++,0,2,'location')} = $battery{$key}{'location'}; + if ($battery->{$key}{'location'}){ + $rows[$j]{main::key($num++,0,2,'location')} = $battery->{$key}{'location'}; } } } - $battery{$key} = undef; + $battery->{$key} = undef; } - # print Data::Dumper::Dumper \%battery; + # print Data::Dumper::Dumper \%$battery; # now if there are any devices left, print them out, excluding Mains if ($extra > 0){ $upower = main::check_program('upower'); - foreach $key (sort keys %battery){ + foreach $key (sort keys %$battery){ $num = 0; - next if !defined $battery{$key} || $battery{$key}{'purpose'} eq 'mains'; + next if !defined $battery->{$key} || $battery->{$key}{'purpose'} eq 'mains'; my ($charge,$model,$serial,$percent,$status,$vendor) = ('','','','','',''); my (%upower_data); $j = scalar @rows; @@ -6666,15 +6763,15 @@ sub create_output { if ($upower_data{'percent'}){ $charge = $upower_data{'percent'}; } - elsif ($battery{$key}{'capacity_level'} && lc($battery{$key}{'capacity_level'}) ne 'unknown'){ - $charge = $battery{$key}{'capacity_level'}; + elsif ($battery->{$key}{'capacity_level'} && lc($battery->{$key}{'capacity_level'}) ne 'unknown'){ + $charge = $battery->{$key}{'capacity_level'}; } else { $charge = 'N/A'; } - $model = $battery{$key}{'model_name'} if $battery{$key}{'model_name'}; - $status = ($battery{$key}{'status'} && lc($battery{$key}{'status'}) ne 'unknown') ? $battery{$key}{'status'}: 'N/A' ; - $vendor = $battery{$key}{'manufacturer'} if $battery{$key}{'manufacturer'}; + $model = $battery->{$key}{'model_name'} if $battery->{$key}{'model_name'}; + $status = ($battery->{$key}{'status'} && lc($battery->{$key}{'status'}) ne 'unknown') ? $battery->{$key}{'status'}: 'N/A' ; + $vendor = $battery->{$key}{'manufacturer'} if $battery->{$key}{'manufacturer'}; if ($vendor || $model){ if ($vendor && $model){ $model = "$vendor $model"; @@ -6686,13 +6783,12 @@ sub create_output { else { $model = 'N/A'; } - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $key, main::key($num++,0,2,'model') => $model, },); - @rows = (@rows,@data); if ($extra > 1){ - $serial = main::apply_filter($battery{$key}{'serial_number'}); + $serial = main::apply_filter($battery->{$key}{'serial_number'}); $rows[$j]{main::key($num++,0,2,'serial')} = $serial; } $rows[$j]{main::key($num++,0,2,'charge')} = $charge; @@ -6723,14 +6819,13 @@ sub battery_data_sys { $b_ma = 0; $id = $item; $id =~ s%/sys/class/power_supply/%%g; - $battery{$id} = ({}); foreach $file (@items){ $path = "$item/$file"; # android shows some files only root readable - $value = (-r $path) ? (main::reader($path))[0]: ''; + $value = (-r $path) ? main::reader($path,'',0): ''; # mains, plus in psu if ($file eq 'type' && $value && lc($value) ne 'battery' ){ - $battery{$id}{'purpose'} = 'mains'; + $battery{$id}->{'purpose'} = 'mains'; } if ($value){ $value = main::trimmer($value); @@ -6776,56 +6871,56 @@ sub battery_data_sys { elsif ($b_root && -e $path && ! -r $path ){ $value = main::row_defaults('root-required'); } - $battery{$id}{$file} = $value; - # print "$battery{$id}{$file}\n"; + $battery{$id}->{$file} = $value; + # print "$battery{$id}->{$file}\n"; } # note, too few data sets, there could be sbs-charger but not sure - if (!$battery{$id}{'purpose'}){ + if (!$battery{$id}->{'purpose'}){ # NOTE: known ids: BAT[0-9] CMB[0-9]. arm may be like: sbs- sbm- but just check # if the energy/charge values exist for this item, if so, it's a battery, if not, # it's a device. if ($id =~ /^(BAT|CMB).*$/i || - ( $battery{$id}{'energy_full'} || $battery{$id}{'charge_full'} || - $battery{$id}{'energy_now'} || $battery{$id}{'charge_now'} || - $battery{$id}{'energy_full_design'} || $battery{$id}{'charge_full_design'} ) || - $battery{$id}{'voltage_min_design'} || $battery{$id}{'voltage_now'} ){ - $battery{$id}{'purpose'} = 'primary'; + ( $battery{$id}->{'energy_full'} || $battery{$id}->{'charge_full'} || + $battery{$id}->{'energy_now'} || $battery{$id}->{'charge_now'} || + $battery{$id}->{'energy_full_design'} || $battery{$id}->{'charge_full_design'} ) || + $battery{$id}->{'voltage_min_design'} || $battery{$id}->{'voltage_now'} ){ + $battery{$id}->{'purpose'} = 'primary'; } else { - $battery{$id}{'purpose'} = 'device'; + $battery{$id}->{'purpose'} = 'device'; } } # note:voltage_now fluctuates, which will make capacity numbers change a bit # if any of these values failed, the math will be wrong, but no way to fix that # tests show more systems give right capacity/charge with voltage_min_design # than with voltage_now - if ($b_ma && $battery{$id}{'voltage_min_design'}){ - if ($battery{$id}{'charge_now'}){ - $battery{$id}{'energy_now'} = $battery{$id}{'charge_now'} * $battery{$id}{'voltage_min_design'}; + if ($b_ma && $battery{$id}->{'voltage_min_design'}){ + if ($battery{$id}->{'charge_now'}){ + $battery{$id}->{'energy_now'} = $battery{$id}->{'charge_now'} * $battery{$id}->{'voltage_min_design'}; } - if ($battery{$id}{'charge_full'}){ - $battery{$id}{'energy_full'} = $battery{$id}{'charge_full'}*$battery{$id}{'voltage_min_design'}; + if ($battery{$id}->{'charge_full'}){ + $battery{$id}->{'energy_full'} = $battery{$id}->{'charge_full'}*$battery{$id}->{'voltage_min_design'}; } - if ($battery{$id}{'charge_full_design'}){ - $battery{$id}{'energy_full_design'} = $battery{$id}{'charge_full_design'} * $battery{$id}{'voltage_min_design'}; + if ($battery{$id}->{'charge_full_design'}){ + $battery{$id}->{'energy_full_design'} = $battery{$id}->{'charge_full_design'} * $battery{$id}->{'voltage_min_design'}; } } - if ( $battery{$id}{'energy_now'} && $battery{$id}{'energy_full'} ){ - $battery{$id}{'capacity'} = 100 * $battery{$id}{'energy_now'}/$battery{$id}{'energy_full'}; - $battery{$id}{'capacity'} = sprintf( "%.1f", $battery{$id}{'capacity'} ); + if ( $battery{$id}->{'energy_now'} && $battery{$id}->{'energy_full'} ){ + $battery{$id}->{'capacity'} = 100 * $battery{$id}->{'energy_now'}/$battery{$id}->{'energy_full'}; + $battery{$id}->{'capacity'} = sprintf("%.1f", $battery{$id}->{'capacity'}); } - if ( $battery{$id}{'energy_full_design'} && $battery{$id}{'energy_full'} ){ - $battery{$id}{'of_orig'} = 100 * $battery{$id}{'energy_full'}/$battery{$id}{'energy_full_design'}; - $battery{$id}{'of_orig'} = sprintf( "%.0f", $battery{$id}{'of_orig'} ); + if ( $battery{$id}->{'energy_full_design'} && $battery{$id}->{'energy_full'} ){ + $battery{$id}->{'of_orig'} = 100 * $battery{$id}->{'energy_full'}/$battery{$id}->{'energy_full_design'}; + $battery{$id}->{'of_orig'} = sprintf("%.0f", $battery{$id}->{'of_orig'}); } - if ( $battery{$id}{'energy_now'} ){ - $battery{$id}{'energy_now'} = sprintf( "%.1f", $battery{$id}{'energy_now'} ); + if ( $battery{$id}->{'energy_now'} ){ + $battery{$id}->{'energy_now'} = sprintf("%.1f", $battery{$id}->{'energy_now'}); } - if ( $battery{$id}{'energy_full_design'} ){ - $battery{$id}{'energy_full_design'} = sprintf( "%.1f",$battery{$id}{'energy_full_design'} ); + if ( $battery{$id}->{'energy_full_design'} ){ + $battery{$id}->{'energy_full_design'} = sprintf("%.1f",$battery{$id}->{'energy_full_design'}); } - if ( $battery{$id}{'energy_full'} ){ - $battery{$id}{'energy_full'} = sprintf( "%.1f", $battery{$id}{'energy_full'} ); + if ( $battery{$id}->{'energy_full'} ){ + $battery{$id}->{'energy_full'} = sprintf("%.1f", $battery{$id}->{'energy_full'}); } } main::log_data('dump','sys: %battery',\%battery) if $b_log; @@ -6837,43 +6932,42 @@ sub battery_data_dmi { eval $start if $b_log; my (%battery,$id); my $i = 0; - foreach (@dmi){ - my @ref = @$_; + foreach my $row (@dmi){ # Portable Battery - if ($ref[0] == 22){ + if ($row->[0] == 22){ $id = "BAT$i"; $i++; $battery{$id} = ({}); - $battery{$id}{'purpose'} = 'primary'; + $battery{$id}->{'purpose'} = 'primary'; # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; - foreach my $item (@ref){ - my @value = split /:\s+/, $item; + splice @$row, 0, 3 if @$row; + foreach my $item (@$row){ + my @value = split(/:\s+/, $item); next if !$value[0]; - if ($value[0] eq 'Location') {$battery{$id}{'location'} = $value[1] } - elsif ($value[0] eq 'Manufacturer') {$battery{$id}{'manufacturer'} = main::dmi_cleaner($value[1]) } - elsif ($value[0] =~ /Chemistry/) {$battery{$id}{'technology'} = $value[1] } - elsif ($value[0] =~ /Serial Number/) {$battery{$id}{'serial_number'} = $value[1] } - elsif ($value[0] =~ /^Name/) {$battery{$id}{'model_name'} = main::dmi_cleaner($value[1]) } + if ($value[0] eq 'Location') {$battery{$id}->{'location'} = $value[1] } + elsif ($value[0] eq 'Manufacturer') {$battery{$id}->{'manufacturer'} = main::dmi_cleaner($value[1]) } + elsif ($value[0] =~ /Chemistry/) {$battery{$id}->{'technology'} = $value[1] } + elsif ($value[0] =~ /Serial Number/) {$battery{$id}->{'serial_number'} = $value[1] } + elsif ($value[0] =~ /^Name/) {$battery{$id}->{'model_name'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Design Capacity') { $value[1] =~ s/\s*mwh$//i; - $battery{$id}{'energy_full_design'} = sprintf( "%.1f", $value[1]/1000); + $battery{$id}->{'energy_full_design'} = sprintf("%.1f", $value[1]/1000); } elsif ($value[0] eq 'Design Voltage') { $value[1] =~ s/\s*mv$//i; - $battery{$id}{'voltage_min_design'} = sprintf( "%.1f", $value[1]/1000); + $battery{$id}->{'voltage_min_design'} = sprintf("%.1f", $value[1]/1000); } } - if ($battery{$id}{'energy_now'} && $battery{$id}{'energy_full'} ){ - $battery{$id}{'capacity'} = 100 * $battery{$id}{'energy_now'} / $battery{$id}{'energy_full'}; - $battery{$id}{'capacity'} = sprintf( "%.1f%", $battery{$id}{'capacity'} ); + if ($battery{$id}->{'energy_now'} && $battery{$id}->{'energy_full'} ){ + $battery{$id}->{'capacity'} = 100 * $battery{$id}->{'energy_now'} / $battery{$id}->{'energy_full'}; + $battery{$id}->{'capacity'} = sprintf("%.1f%", $battery{$id}->{'capacity'}); } - if ($battery{$id}{'energy_full_design'} && $battery{$id}{'energy_full'} ){ - $battery{$id}{'of_orig'} = 100 * $battery{$id}{'energy_full'} / $battery{$id}{'energy_full_design'}; - $battery{$id}{'of_orig'} = sprintf( "%.0f%", $battery{$id}{'of_orig'} ); + if ($battery{$id}->{'energy_full_design'} && $battery{$id}->{'energy_full'} ){ + $battery{$id}->{'of_orig'} = 100 * $battery{$id}->{'energy_full'} / $battery{$id}->{'energy_full_design'}; + $battery{$id}->{'of_orig'} = sprintf("%.0f%", $battery{$id}->{'of_orig'}); } } - elsif ($ref[0] > 22){ + elsif ($row->[0] > 22){ last; } } @@ -6895,7 +6989,7 @@ sub upower_data { if ($_ =~ /$id/){ my @working = main::grabber("$upower -i $_",'','strip'); foreach my $row (@working){ - my @temp = split /\s*:\s*/, $row; + my @temp = split(/\s*:\s*/, $row); if ($temp[0] eq 'percentage'){ $data{'percent'} = $temp[1]; } @@ -6935,7 +7029,7 @@ sub get { sub create_output_full { eval $start if $b_log; my $num = 0; - my ($b_flags,$b_speeds,$core_speeds_value,$flag_key,@flags,%cpu,@data,@rows); + my ($b_flags,$b_speeds,$core_speeds_value,$flag_key,@flags,%cpu,@rows); my $sleep = $cpu_sleep * 1000000; if ($b_hires){ eval 'Time::HiRes::usleep( $sleep )'; @@ -6949,34 +7043,31 @@ sub create_output_full { elsif ($bsd_type ){ my ($key1,$val1) = ('',''); if ( $alerts{'sysctl'} ){ - if ( $alerts{'sysctl'}{'action'} eq 'use' ){ + if ( $alerts{'sysctl'}->{'action'} eq 'use' ){ # $key1 = 'Status'; # $val1 = main::row_defaults('dev'); %cpu = data_sysctl('full'); } else { - $key1 = ucfirst($alerts{'sysctl'}{'action'}); - $val1 = $alerts{'sysctl'}{$alerts{'sysctl'}{'action'}}; - @data = ({main::key($num++,0,1,$key1) => $val1,}); - return @data; + $key1 = ucfirst($alerts{'sysctl'}->{'action'}); + $val1 = $alerts{'sysctl'}->{$alerts{'sysctl'}->{'action'}}; + @rows = ({main::key($num++,0,1,$key1) => $val1,}); + return @rows; } } } - my %properties = cpu_properties(%cpu); + my %properties = cpu_properties(\%cpu); my $type = ($properties{'cpu-type'}) ? $properties{'cpu-type'}: ''; - my $ref = $cpu{'processors'}; - my @processors = @$ref; - my @speeds = cpu_speeds(@processors); + my @processors = @{$cpu{'processors'}}; + my @speeds = cpu_speeds(\@processors); my $j = scalar @rows; $cpu{'model_name'} ||= 'N/A'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Info') => $properties{'cpu-layout'}, main::key($num++,0,2,'model') => $cpu{'model_name'}, },); - @rows = (@rows,@data); if ($cpu{'system-cpus'}){ - my $ref = $cpu{'system-cpus'}; - my %system_cpus = %$ref; + my %system_cpus = %{$cpu{'system-cpus'}}; my $i = 1; my $counter = ( %system_cpus && scalar keys %system_cpus > 1 ) ? '-' : ''; foreach my $key (keys %system_cpus){ @@ -6987,7 +7078,7 @@ sub create_output_full { if ($b_admin && $properties{'socket'}){ if ($properties{'upgrade'}){ $rows[$j]{main::key($num++,1,2,'socket')} = $properties{'socket'} . ' (' . $properties{'upgrade'} . ')'; - $rows[$j]{main::key($num++,0,3,'note')} = 'check'; + $rows[$j]{main::key($num++,0,3,'note')} = main::row_defaults('note-check'); } else { $rows[$j]{main::key($num++,0,2,'socket')} = $properties{'socket'}; @@ -7000,48 +7091,52 @@ sub create_output_full { } if ($extra > 0){ $cpu{'arch'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'arch')} = $cpu{'arch'}; - if ( !$b_admin && $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){ - $rows[$j]{main::key($num++,0,2,'rev')} = $cpu{'rev'}; + $rows[$j]{main::key($num++,1,2,'arch')} = $cpu{'arch'}; + if ($cpu{'arch-note'}){ + $rows[$j]{main::key($num++,0,3,'note')} = $cpu{'arch-note'}; + } + # ntoe: had if arch, but stepping can be defined where arch failed, stepping can be 0 + if ( !$b_admin && defined $cpu{'stepping'} ){ + $rows[$j]{main::key($num++,0,2,'rev')} = $cpu{'stepping'}; } } if ($b_admin){ $rows[$j]{main::key($num++,0,2,'family')} = hex_and_decimal($cpu{'family'}); $rows[$j]{main::key($num++,0,2,'model-id')} = hex_and_decimal($cpu{'model_id'}); - $rows[$j]{main::key($num++,0,2,'stepping')} = hex_and_decimal($cpu{'rev'}); - $cpu{'microcode'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'microcode')} = $cpu{'microcode'}; + $rows[$j]{main::key($num++,0,2,'stepping')} = hex_and_decimal($cpu{'stepping'}); + if (!$b_arm && !$b_mips && !$b_ppc && $cpu{'type'} ne 'elbrus'){ + $cpu{'microcode'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'microcode')} = $cpu{'microcode'}; + } } if ($extra > 1 && $properties{'l1-cache'}){ - $rows[$j]{main::key($num++,0,2,'L1 cache')} = $properties{'l1-cache'}; + $rows[$j]{main::key($num++,0,2,'L1 cache')} = main::get_size($properties{'l1-cache'},'string'); } - $properties{'l2-cache'} ||= 'N/A'; - if (!$b_arm || ($b_arm && $properties{'l2-cache'} ne 'N/A')){ + if (!$b_arm || ($b_arm && $properties{'l2-cache'})){ + $properties{'l2-cache'} = ($properties{'l2-cache'}) ? main::get_size($properties{'l2-cache'},'string') : 'N/A'; $rows[$j]{main::key($num++,0,2,'L2 cache')} = $properties{'l2-cache'}; } if ($extra > 1 && $properties{'l3-cache'}){ - $rows[$j]{main::key($num++,0,2,'L3 cache')} = $properties{'l3-cache'}; + $rows[$j]{main::key($num++,0,2,'L3 cache')} = main::get_size($properties{'l3-cache'},'string'); } - if ($extra > 0 && !$show{'cpu-flag'}){ $j = scalar @rows; - @flags = split /\s+/, $cpu{'flags'} if $cpu{'flags'}; + @flags = split(/\s+/, $cpu{'flags'}) if $cpu{'flags'}; $flag_key = ($b_arm || $bsd_type) ? 'features': 'flags'; my $flag = 'N/A'; if (@flags){ # failure to read dmesg.boot: dmesg.boot permissions; then short -Cx list flags @flags = grep {/^(dmesg.boot|permissions|avx[2-9]?|lm|nx|pae|pni|(sss|ss)e([2-9])?([a-z])?(_[0-9])?|svm|vmx)$/} @flags; @flags = map {s/pni/sse3/; $_} @flags; - @flags = sort(@flags); - $flag = join ' ', @flags if @flags; + @flags = sort @flags; + $flag = join(' ', @flags) if @flags; } if ($b_arm && $flag eq 'N/A'){ $flag = main::row_defaults('arm-cpu-f'); } - @data = ({ + push(@rows, { main::key($num++,0,2,$flag_key) => $flag, - },); - @rows = (@rows,@data); + }); $b_flags = 1; } if ($extra > 0 && !$bsd_type){ @@ -7068,11 +7163,10 @@ sub create_output_full { $core_speeds_value = 'N/A'; } $j = scalar @rows; - @data = ({ + push(@rows, { main::key($num++,1,1,$speed_key) => $speed, main::key($num++,0,2,$min_max_key) => $min_max, }); - @rows = (@rows,@data); if ($b_admin && $properties{'dmi-speed'} && $properties{'dmi-max-speed'}){ $rows[$j]{main::key($num++,0,2,'base/boost')} = $properties{'dmi-speed'} . '/' . $properties{'dmi-max-speed'}; } @@ -7098,40 +7192,37 @@ sub create_output_full { } if ($show{'cpu-flag'} && !$b_flags){ $flag_key = ($b_arm || $bsd_type) ? 'Features': 'Flags'; - @flags = split /\s+/, $cpu{'flags'} if $cpu{'flags'}; + @flags = split(/\s+/, $cpu{'flags'}) if $cpu{'flags'}; my $flag = 'N/A'; if (@flags){ - @flags = sort(@flags); - $flag = join ' ', @flags if @flags; + @flags = sort @flags; + $flag = join(' ', @flags) if @flags; } - @data = ({ + push(@rows, { main::key($num++,0,1,$flag_key) => $flag, },); - @rows = (@rows,@data); } if ($b_admin){ my @bugs = cpu_bugs_sys(); my $value = ''; if (!@bugs){ if ( $cpu{'bugs'}){ - my @proc_bugs = split /\s+/, $cpu{'bugs'}; - @proc_bugs = sort(@proc_bugs); - $value = join ' ', @proc_bugs; + my @proc_bugs = split(/\s+/, $cpu{'bugs'}); + @proc_bugs = sort @proc_bugs; + $value = join(' ', @proc_bugs); } else { $value = main::row_defaults('cpu-bugs-null'); } } - @data = ({ + push(@rows, { main::key($num++,1,1,'Vulnerabilities') => $value, },); - @rows = (@rows,@data); if (@bugs){ $j = $#rows; - foreach my $ref (@bugs){ - my @bug = @$ref; - $rows[$j]{main::key($num++,1,2,'Type')} = $bug[0]; - $rows[$j]{main::key($num++,0,3,$bug[1])} = $bug[2]; + foreach my $bug (@bugs){ + $rows[$j]{main::key($num++,1,2,'Type')} = $bug->[0]; + $rows[$j]{main::key($num++,0,3,$bug->[1])} = $bug->[2]; $j++; } } @@ -7141,21 +7232,24 @@ sub create_output_full { } sub create_output_short { eval $start if $b_log; - my (@cpu) = @_; + my ($cpu) = @_; my @data; my $num = 0; - $cpu[1] ||= main::row_defaults('cpu-model-null'); - $cpu[2] ||= 'N/A'; + $cpu->[1] ||= main::row_defaults('cpu-model-null'); + $cpu->[2] ||= 'N/A'; @data = ({ - main::key($num++,1,1,'Info') => $cpu[0] . ' ' . $cpu[1] . ' [' . $cpu[2] . ']', - #main::key($num++,0,2,'type') => $cpu[2], + main::key($num++,1,1,'Info') => $cpu->[0] . ' ' . $cpu->[1] . ' [' . $cpu->[2] . ']', + #main::key($num++,0,2,'type') => $cpu->[2], },); if ($extra > 0){ - $data[0]{main::key($num++,0,2,'arch')} = $cpu[7]; + $data[0]{main::key($num++,1,2,'arch')} = $cpu->[7]; + if ($cpu->[8]){ + $data[0]{main::key($num++,0,3,'note')} = $cpu->[8]; + } } - $data[0]{main::key($num++,0,2,$cpu[3])} = $cpu[4]; - if ($cpu[6]){ - $data[0]{main::key($num++,0,2,$cpu[5])} = $cpu[6]; + $data[0]{main::key($num++,0,2,$cpu->[3])} = $cpu->[4]; + if ($cpu->[6]){ + $data[0]{main::key($num++,0,2,$cpu->[5])} = $cpu->[6]; } eval $end if $b_log; return @data; @@ -7181,14 +7275,14 @@ sub data_short { elsif ($bsd_type ){ my ($key1,$val1) = ('',''); if ( $alerts{'sysctl'} ){ - if ( $alerts{'sysctl'}{'action'} eq 'use' ){ + if ( $alerts{'sysctl'}->{'action'} eq 'use' ){ # $key1 = 'Status'; # $val1 = main::row_defaults('dev'); %cpu = data_sysctl($type); } else { - $key1 = ucfirst($alerts{'sysctl'}{'action'}); - $val1 = $alerts{'sysctl'}{$alerts{'sysctl'}{'action'}}; + $key1 = ucfirst($alerts{'sysctl'}->{'action'}); + $val1 = $alerts{'sysctl'}->{$alerts{'sysctl'}->{'action'}}; @data = ({main::key($num++,0,1,$key1) => $val1,}); return @data; } @@ -7196,10 +7290,10 @@ sub data_short { } # $cpu{'cur-freq'} = $cpu[0]{'core-id'}[0]{'speed'}; if ($type eq 'short' || $type eq 'basic'){ - @data = prep_short_data(%cpu); + @data = prep_short_data(\%cpu); } if ($type eq 'basic'){ - @data = create_output_short(@data); + @data = create_output_short(\@data); } eval $end if $b_log; return @data; @@ -7207,10 +7301,10 @@ sub data_short { sub prep_short_data { eval $start if $b_log; - my (%cpu) = @_; - my %properties = cpu_properties(%cpu); + my ($cpu_data) = @_; + my %properties = cpu_properties($cpu_data); my ($cpu,$speed_key,$speed,$type) = ('','speed',0,''); - $cpu = $cpu{'model_name'} if $cpu{'model_name'}; + $cpu = $cpu_data->{'model_name'} if $cpu_data->{'model_name'}; $type = $properties{'cpu-type'} if $properties{'cpu-type'}; $speed_key = $properties{'speed-key'} if $properties{'speed-key'}; $speed = $properties{'speed'} if $properties{'speed'}; @@ -7224,8 +7318,9 @@ sub prep_short_data { $properties{'min-max'}, ); if ($extra > 0){ - $cpu{'arch'} ||= 'N/A'; - $result[7] = $cpu{'arch'}; + $cpu_data->{'arch'} ||= 'N/A'; + $result[7] = $cpu_data->{'arch'}; + $result[8] = $cpu_data->{'arch-note'}; } eval $end if $b_log; return @result; @@ -7234,40 +7329,47 @@ sub prep_short_data { sub data_cpuinfo { eval $start if $b_log; my ($file,$type)= @_; - my ($arch,@ids,@line,$b_first,$b_proc_int,$starter); - # use --arm flag when testing arm cpus - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-4-core-pinebook-1.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv6-single-core-1.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-dual-core-1.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-new-format-model-name-single-core.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-2-die-96-core-rk01.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/16-core-32-mt-ryzen.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-16-core-epyc-abucodonosor.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-core-probook-antix.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-jean-antix.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-althlon-mjro.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-apu-vc-box.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-a10-5800k-1.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-ht-atom-bruh.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/core-2-i3.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/8-core-i7-damentz64.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-10-core-xeon-ht.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-core-xeon-fake-dual-die-zyanya.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-i5-fake-dual-die-hek.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-1-core-xeon-vm-vs2017.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-1-core-xeon-vps-frodo1.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-6-core-xeon-no-mt-lathander.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/mips/mips-mainusg-cpuinfo.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/ppc/ppc-debian-ppc64-cpuinfo.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE1C-8.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2CDSP-4.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2S4-3-monocub.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xMBE8C-7.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xEL2S4-3.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xE8C-7.txt"; - # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xE2CDSP-4.txt"; - my %speeds = set_cpu_speeds_sys(); + my ($arch,@ids,@line,$b_first,$b_proc_int,$note,$starter); + # has to be set above fake cpu section + my %cpu = set_cpu_data(); + $cpu{'type'} = cpu_vendor($cpu_arch) if $cpu_arch =~ /e2k/; # already set to lower + # use --arm flag when testing arm cpus, and --fake-cpu to trigger fake data + if ($b_fake_cpu){ + # $cpu{'type'} = 'elbrus'; # uncomment to test elbrus + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-4-core-pinebook-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv6-single-core-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-dual-core-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/armv7-new-format-model-name-single-core.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/arm/arm-2-die-96-core-rk01.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/16-core-32-mt-ryzen.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-16-core-epyc-abucodonosor.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/2-core-probook-antix.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-jean-antix.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-althlon-mjro.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-apu-vc-box.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/amd/4-core-a10-5800k-1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-ht-atom-bruh.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/core-2-i3.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/8-core-i7-damentz64.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-10-core-xeon-ht.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-core-xeon-fake-dual-die-zyanya.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-core-i5-fake-dual-die-hek.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/2-1-core-xeon-vm-vs2017.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-1-core-xeon-vps-frodo1.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/intel/4-6-core-xeon-no-mt-lathander.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/mips/mips-mainusg-cpuinfo.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/ppc/ppc-debian-ppc64-cpuinfo.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE1C-8.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2CDSP-4.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xE2S4-3-monocub.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/1xMBE8C-7.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xEL2S4-3.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xE8C-7.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/4xE2CDSP-4.txt"; + # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/cpu/elbrus/cpuinfo.e8c2.txt"; + } my @cpuinfo = main::reader($file); + my %speeds = set_cpu_speeds_sys(); my @phys_cpus = (0);# start with 1 always my ($core_count,$die_holder,$die_id,$phys_id,$proc_count,$speed) = (0,0,0,0,0,0,0); my ($phys_holder) = (undef); @@ -7276,13 +7378,11 @@ sub data_cpuinfo { #$ids[0] = ([(0)]); $ids[0] = ([]); $ids[0][0] = ([]); - my %cpu = set_cpu_data(); - $cpu{'type'} = cpu_vendor($cpu_arch) if $cpu_arch =~ /e2k/; # already set to lower - #$cpu{'type'} = 'elbrus'; + # note, there con be a lot of processors, 32 core HT would have 64, for example. foreach (@cpuinfo){ next if /^\s*$/; - @line = split /\s*:\s*/, $_; + @line = split(/\s*:\s*/, $_, 2); next if !$line[0]; $starter = $line[0]; # preserve case for one specific ARM issue $line[0] = lc($line[0]); @@ -7295,7 +7395,7 @@ sub data_cpuinfo { # Processor : Feroceon 88FR131 rev 1 (v5l) if ($cpu{'model_name'} && $cpu{'model_name'} =~ /(.*)\srev\s([\S]+)\s(\(([\S]+)\))?/){ $cpu{'model_name'} = $1; - $cpu{'rev'} = $2; + $cpu{'stepping'} = $2; if ($4){ $cpu{'arch'} = $4; $cpu{'model_name'} .= ' ' . $cpu{'arch'} if $cpu{'model_name'} !~ /$cpu{'arch'}/i; @@ -7346,12 +7446,12 @@ sub data_cpuinfo { $cpu{'arch'} = $line[1]; } } - elsif (!$cpu{'rev'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision')){ - $cpu{'rev'} = uc(sprintf("%x", $line[1])); + elsif (!defined $cpu{'stepping'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision')){ + $cpu{'stepping'} = uc(sprintf("%x", $line[1])); } # ppc - elsif (!$cpu{'rev'} && $line[0] eq 'revision'){ - $cpu{'rev'} = $line[1]; + elsif (!defined $cpu{'stepping'} && $line[0] eq 'revision'){ + $cpu{'stepping'} = $line[1]; } # this is hex so uc for cpu arch id. raspi 4 has Model rather than Hard elsif (!$cpu{'model_id'} && (!$b_ppc && !$b_arm && $line[0] eq 'model') ){ @@ -7370,7 +7470,7 @@ sub data_cpuinfo { $cpu{'type'} = 'arm'; if ($cpu{'model_name'} && $cpu{'model_name'} =~ /(.*)\srev\s([\S]+)\s(\(([\S]+)\))?/){ $cpu{'model_name'} = $1; - $cpu{'rev'} = $2; + $cpu{'stepping'} = $2; if ($4){ $cpu{'arch'} = $4; $cpu{'model_name'} .= ' ' . $cpu{'arch'} if $cpu{'model_name'} !~ /$cpu{'arch'}/i; @@ -7399,7 +7499,7 @@ sub data_cpuinfo { elsif ( $line[0] eq 'physical id' ){ if ( !defined $phys_holder || $phys_holder != $line[1] ){ # only increment if not in array counter - push @phys_cpus, $line[1] if ! grep {/$line[1]/} @phys_cpus; + push(@phys_cpus, $line[1]) if ! grep {/$line[1]/} @phys_cpus; $phys_holder = $line[1]; $ids[$phys_holder] = ([]) if ! exists $ids[$phys_holder]; $ids[$phys_holder][$die_id] = ([]) if ! exists $ids[$phys_holder][$die_id]; @@ -7433,24 +7533,42 @@ sub data_cpuinfo { ## this is only for -C full cpu output if ( $type eq 'full' ){ if (!$cpu{'l2-cache'} && ($line[0] eq 'cache size' || $line[0] eq 'l2 cache size' )){ - if ($line[1] =~ /(\d+)\sKB$/){ - $cpu{'l2-cache'} = $1; - } - elsif ($line[1] =~ /(\d+)\sMB$/){ - $cpu{'l2-cache'} = ($1*1024); + if ($line[1] =~ /(\d+)\s(K|M)B$/){ + $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; } } elsif (!$cpu{'l1-cache'} && $line[0] eq 'l1 cache size'){ if ($line[1] =~ /(\d+)\sKB$/){ - $cpu{'l1-cache'} = ($1); + $cpu{'l1-cache'} = $1; } } elsif (!$cpu{'l3-cache'} && $line[0] eq 'l3 cache size'){ - if ($line[1] =~ /(\d+)\sKB$/){ - $cpu{'l3-cache'} = $1; + if ($line[1] =~ /(\d+)\s(K|M)B$/){ + $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; } - elsif ($line[1] =~ /(\d+)\sMB$/){ - $cpu{'l3-cache'} = ($1*1024); + } + if ($cpu{'type'} eq 'elbrus'){ + # note: cache0 is L1i and cache1 L1d, but add both for L1 + if (!$cpu{'l0-cache'} && $line[0] eq 'cache0'){ + if ($line[1] =~ /size=(\d+)K\s/){ + $cpu{'l0-cache'} = $1; + } + } + elsif (!$cpu{'l1-cache'} && $line[0] eq 'cache1'){ + if ($line[1] =~ /size=(\d+)K\s/){ + $cpu{'l1-cache'} = $1; + $cpu{'l1-cache'} += $cpu{'l0-cache'} if $cpu{'l0-cache'}; + } + } + elsif (!$cpu{'l2-cache'} && $line[0] eq 'cache2'){ + if ($line[1] =~ /size=(\d+)(K|M)\s/){ + $cpu{'l2-cache'} = ($2 eq 'M') ? ($1*1024) : $1; + } + } + elsif (!$cpu{'l3-cache'} && $line[0] eq 'cache3'){ + if ($line[1] =~ /size=(\d+)(K|M)\s/){ + $cpu{'l3-cache'} = ($2 eq 'M') ? ($1*1024) : $1; + } } } if (!$cpu{'flags'} && ($line[0] eq 'flags' || $line[0] eq 'features' )){ @@ -7496,7 +7614,7 @@ sub data_cpuinfo { } $cpu{'ids'} = (\@ids); if ( $extra > 0 && !$cpu{'arch'} && $type ne 'short' ){ - $cpu{'arch'} = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'rev'}); + ($cpu{'arch'},$cpu{'arch-note'}) = cpu_arch($cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'stepping'}); # cpu_arch comes from set_os() $cpu{'arch'} = $cpu_arch if (!$cpu{'arch'} && $cpu_arch && ($b_mips || $b_arm || $b_ppc)); #print "$cpu{'type'},$cpu{'family'},$cpu{'model_id'},$cpu{'arch'}\n"; @@ -7525,11 +7643,12 @@ sub data_sysctl { my ($sep) = (''); my ($die_holder,$die_id,$phys_holder,$phys_id,$proc_count,$speed) = (0,0,0,0,0,0,0); foreach (@sysctl){ - @line = split /\s*:\s*/, $_; + @line = split(/\s*:\s*/, $_); next if ! $line[0]; # darwin shows machine, like MacBook7,1, not cpu # machdep.cpu.brand_string: Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz - if ( ($bsd_type ne 'darwin' && $line[0] eq 'hw.model' ) || $line[0] eq 'machdep.cpu.brand_string' ){ + if ( ($bsd_type ne 'darwin' && $line[0] eq 'hw.model' ) || + $line[0] eq 'machdep.cpu.brand_string' ){ # cut L2 cache/cpu max speed out of model string, if available # openbsd 5.6: AMD Sempron(tm) Processor 3400+ ("AuthenticAMD" 686-class, 256KB L2 cache) # freebsd 10: hw.model: AMD Athlon(tm) II X2 245 Processor @@ -7596,7 +7715,7 @@ sub data_sysctl { elsif ($line[0] eq 'dev.cpu.0.freq_levels') { $line[1] =~ s/^\s+|\/[0-9]+|\s+$//g; if ( $line[1] =~ /[0-9]+\s+[0-9]+/ ) { - my @temp = split /\s+/, $line[1]; + my @temp = split(/\s+/, $line[1]); $cpu{'max-freq'} = $temp[0]; $cpu{'min-freq'} = $temp[-1]; $cpu{'scalings'} = \@temp; @@ -7607,7 +7726,7 @@ sub data_sysctl { } # the following have only been seen in DragonflyBSD data but thumbs up! elsif ($line[0] eq 'hw.cpu_topology.members' ) { - my @temp = split /\s+/, $line[1]; + my @temp = split(/\s+/, $line[1]); my $count = scalar @temp; $count-- if $count > 0; $cpu{'processors'}[$count] = 0; @@ -7618,7 +7737,7 @@ sub data_sysctl { } elsif ($line[0] eq 'hw.cpu_topology.cpu1.physical_siblings' ) { # string, like: cpu0 cpu1 - my @temp = split /\s+/, $line[1]; + my @temp = split(/\s+/, $line[1]); $cpu{'siblings'} = scalar @temp; } # increment by 1 for every new physical id we see. These are in almost all cases @@ -7654,33 +7773,32 @@ sub data_sysctl { } sub cpu_properties { - my (%cpu) = @_; + my ($cpu) = @_; my ($b_amd_zen,$b_epyc,$b_ht,$b_elbrus,$b_intel,$b_ryzen,$b_xeon); - if ($cpu{'type'} ){ - if ($cpu{'type'} eq 'intel'){ + if ($cpu->{'type'} ){ + if ($cpu->{'type'} eq 'intel'){ $b_intel = 1; - $b_xeon = 1 if $cpu{'model_name'} =~ /Xeon/i; + $b_xeon = 1 if $cpu->{'model_name'} =~ /Xeon/i; } - elsif ($cpu{'type'} eq 'amd' ){ - if ( $cpu{'family'} && $cpu{'family'} eq '17' ) { + elsif ($cpu->{'type'} eq 'amd' ){ + if ( $cpu->{'family'} && $cpu->{'family'} eq '17' ) { $b_amd_zen = 1; - if ($cpu{'model_name'} ){ - if ($cpu{'model_name'} =~ /Ryzen/i ){ + if ($cpu->{'model_name'} ){ + if ($cpu->{'model_name'} =~ /Ryzen/i ){ $b_ryzen = 1; } - elsif ($cpu{'model_name'} =~ /EPYC/i){ + elsif ($cpu->{'model_name'} =~ /EPYC/i){ $b_epyc = 1; } } } } - elsif ($cpu{'type'} eq 'elbrus') { + elsif ($cpu->{'type'} eq 'elbrus') { $b_elbrus = 1; } } #my @dies = $phys[0][0]; - my $ref = $cpu{'ids'}; - my @phys = @$ref; + my @phys = @{$cpu->{'ids'}}; my $phyical_count = 0; #my $phyical_count = scalar @phys; my @processors; @@ -7691,9 +7809,8 @@ sub cpu_properties { } # count unique processors ## # note, this fails for intel cpus at times - $ref = $cpu{'processors'}; - @processors = @$ref; - #print ref $cpu{'processors'}, "\n"; + @processors = @{$cpu->{'processors'}}; + #print ref $cpu->{'processors'}, "\n"; my $processors_count = scalar @processors; #print "p count:$processors_count\n"; #print Data::Dumper::Dumper \@processors; @@ -7703,11 +7820,11 @@ sub cpu_properties { my ($l1_cache,$l2_cache,$l3_cache,$core_count,$cpu_cores,$die_count) = (0,0,0,0,0,0); # note: elbrus supports turning off cores, so we need to add one for cases where rounds to 0 or 1 less if ($b_elbrus && $processors_count){ - my @elbrus = elbrus_data($cpu{'model_id'},$processors_count,$cpu{'arch'}); + my @elbrus = elbrus_data($cpu->{'model_id'},$processors_count,$cpu->{'arch'}); $cpu_cores = $elbrus[0]; $phyical_count = $elbrus[1]; - $cpu{'arch'} = $elbrus[2]; - # print 'model id: ' . $cpu{'model_id'} . ' arch: ' . $cpu{'arch'} . " cpc: $cpu_cores phyc: $phyical_count proc: $processors_count \n"; + $cpu->{'arch'} = $elbrus[2]; + # print 'model id: ' . $cpu->{'model_id'} . ' arch: ' . $cpu->{'arch'} . " cpc: $cpu_cores phyc: $phyical_count proc: $processors_count \n"; } $phyical_count ||= 1; # assume 1 if no id found, as with ARM if ($extra > 1){ @@ -7717,8 +7834,8 @@ sub cpu_properties { $l1_cache = $cpu_dmi{'L1'} if $cpu_dmi{'L1'}; $l3_cache = $cpu_dmi{'L3'} if $cpu_dmi{'L3'}; # bsd sysctl can have these values so let's check just in case - $l1_cache = $cpu{'l1-cache'} * $phyical_count if !$l1_cache && $cpu{'l1-cache'}; - $l3_cache = $cpu{'l3-cache'} * $phyical_count if !$l3_cache && $cpu{'l3-cache'}; + $l1_cache = $cpu->{'l1-cache'} * $phyical_count if !$l1_cache && $cpu->{'l1-cache'}; + $l3_cache = $cpu->{'l3-cache'} * $phyical_count if !$l3_cache && $cpu->{'l3-cache'}; $dmi_max_speed = $cpu_dmi{'max-speed'} if $cpu_dmi{'max-speed'}; $socket = $cpu_dmi{'socket'} if $cpu_dmi{'socket'}; $upgrade = $cpu_dmi{'upgrade'} if $cpu_dmi{'upgrade'}; @@ -7727,76 +7844,73 @@ sub cpu_properties { $volts = $cpu_dmi{'volts'} if $cpu_dmi{'volts'}; } foreach my $die_ref ( @phys ){ - next if ! $die_ref; - my @dies = @$die_ref; + next if ref $die_ref ne 'ARRAY'; $core_count = 0; - $die_count = scalar @dies; - #$cpu{'dies'} = $die_count; - foreach my $core_ref (@dies){ + $die_count = scalar @$die_ref; + #$cpu->{'dies'} = $die_count; + foreach my $core_ref (@$die_ref){ next if ref $core_ref ne 'ARRAY'; - my @cores = @$core_ref; $core_count = 0;# reset for each die!! # NOTE: the counters can be undefined because the index comes from # core id: which can be 0 skip 1 then 2, which leaves index 1 undefined # arm cpus do not actually show core id so ignore that counter - foreach my $id (@cores){ + foreach my $id (@$core_ref){ $core_count++ if defined $id && !$b_arm; } #print 'cores: ' . $core_count, "\n"; } } - # this covers potentially cases where ARM cpus have > 1 die - $cpu{'dies'} = ($b_arm && $die_count <= 1 && $cpu{'dies'} > 1) ? $cpu{'dies'}: $die_count; + $cpu->{'dies'} = ($b_arm && $die_count <= 1 && $cpu->{'dies'} > 1) ? $cpu->{'dies'}: $die_count; # this is an attempt to fix the amd family 15 bug with reported cores vs actual cores # NOTE: amd A6-4400M APU 2 core reports: cores: 1 siblings: 2 # NOTE: AMD A10-5800K APU 4 core reports: cores: 2 siblings: 4 if (!$cpu_cores){ - if ($cpu{'cores'} && ! $core_count || $cpu{'cores'} >= $core_count){ - $cpu_cores = $cpu{'cores'}; + if ($cpu->{'cores'} && ! $core_count || $cpu->{'cores'} >= $core_count){ + $cpu_cores = $cpu->{'cores'}; } - elsif ($core_count > $cpu{'cores'}){ + elsif ($core_count > $cpu->{'cores'}){ $cpu_cores = $core_count; } } #print "cpu-c:$cpu_cores\n"; - #$cpu_cores = $cpu{'cores'}; + #$cpu_cores = $cpu->{'cores'}; # like, intel core duo # NOTE: sadly, not all core intel are HT/MT, oh well... # xeon may show wrong core / physical id count, if it does, fix it. A xeon # may show a repeated core id : 0 which gives a fake num_of_cores=1 if ($b_intel){ - if ($cpu{'siblings'} && $cpu{'siblings'} > 1 && $cpu{'cores'} && $cpu{'cores'} > 1 ){ - if ( $cpu{'siblings'}/$cpu{'cores'} == 1 ){ + if ($cpu->{'siblings'} && $cpu->{'siblings'} > 1 && $cpu->{'cores'} && $cpu->{'cores'} > 1 ){ + if ( $cpu->{'siblings'}/$cpu->{'cores'} == 1 ){ $b_intel = 0; $b_ht = 0; } else { - $cpu_cores = ($cpu{'siblings'}/2); + $cpu_cores = ($cpu->{'siblings'}/2); $b_ht = 1; } } } # ryzen is made out of blocks of 8 core dies elsif ($b_ryzen){ - $cpu_cores = $cpu{'cores'}; + $cpu_cores = $cpu->{'cores'}; # note: posix ceil isn't present in Perl for some reason, deprecated? my $working = $cpu_cores / 8; - my @temp = split /\./, $working; - $cpu{'dies'} = ($temp[1] && $temp[1] > 0) ? $temp[0]++ : $temp[0]; + my @temp = split('\.', $working); + $cpu->{'dies'} = ($temp[1] && $temp[1] > 0) ? $temp[0]++ : $temp[0]; } # these always have 4 dies elsif ($b_epyc) { - $cpu_cores = $cpu{'cores'}; - $cpu{'dies'} = 4; + $cpu_cores = $cpu->{'cores'}; + $cpu->{'dies'} = 4; } # elsif ($b_elbrus){ # $cpu_cores = # } # final check, override the num of cores value if it clearly is wrong # and use the raw core count and synthesize the total instead of real count - if ( $cpu_cores == 0 && ($cpu{'cores'} * $phyical_count > 1)){ - $cpu_cores = ($cpu{'cores'} * $phyical_count); + if ( $cpu_cores == 0 && ($cpu->{'cores'} * $phyical_count > 1)){ + $cpu_cores = ($cpu->{'cores'} * $phyical_count); } # last check, seeing some intel cpus and vms with intel cpus that do not show any # core id data at all, or siblings. @@ -7811,12 +7925,12 @@ sub cpu_properties { } my $count = $processors_count; $count-- if $count > 0; - $cpu{'processors'}[$count] = 0; + $cpu->{'processors'}[$count] = 0; # no way to get per processor speeds yet, so assign 0 to each # must be a numeric value. Could use raw speed from core 0, but # that would just be a hack. foreach (0 .. $count){ - $cpu{'processors'}[$_] = 0; + $cpu->{'processors'}[$_] = 0; } } # last test to catch some corner cases @@ -7829,26 +7943,26 @@ sub cpu_properties { $b_intel = 0; $cpu_cores = 1; $core_count = 1; - $cpu{'siblings'} = 1; + $cpu->{'siblings'} = 1; } - #print "pc: $processors_count s: $cpu{'siblings'} cpuc: $cpu_cores corec: $core_count\n"; + #print "pc: $processors_count s: $cpu->{'siblings'} cpuc: $cpu_cores corec: $core_count\n"; # Algorithm: # if > 1 processor && processor id (physical id) == core id then Multi threaded (MT) - # if siblings > 1 && siblings == 2 * num_of_cores ($cpu{'cores'}) then Multi threaded (MT) + # if siblings > 1 && siblings == 2 * num_of_cores ($cpu->{'cores'}) then Multi threaded (MT) # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP) # if > 1 processor && processor ids (physical id) > 1 then Symmetric Multi Processing (SMP) # if = 1 processor then single core/processor Uni-Processor (UP) - if ( $processors_count > 1 || ( $b_intel && $cpu{'siblings'} > 0 ) ) { + if ( $processors_count > 1 || ( $b_intel && $cpu->{'siblings'} > 0 ) ) { # non-multicore MT if ($processors_count == ($phyical_count * $cpu_cores * 2)){ #print "mt:1\n"; $cpu_type .= 'MT'; } -# elsif ($b_xeon && $cpu{'siblings'} > 1){ +# elsif ($b_xeon && $cpu->{'siblings'} > 1){ # #print "mt:2\n"; # $cpu_type .= 'MT'; # } - elsif ($cpu{'siblings'} > 1 && ($cpu{'siblings'} == 2 * $cpu_cores )){ + elsif ($cpu->{'siblings'} > 1 && ($cpu->{'siblings'} == 2 * $cpu_cores )){ #print "mt:3\n"; $cpu_type .= 'MT'; } @@ -7858,7 +7972,7 @@ sub cpu_properties { $cpu_type .= $sep . 'MCP'; } # only solidly known > 1 die cpus will use this, ryzen and arm for now - if ( $cpu{'dies'} > 1 ){ + if ( $cpu->{'dies'} > 1 ){ my $sep = ($cpu_type) ? ' ' : '' ; $cpu_type .= $sep . 'MCM'; } @@ -7875,67 +7989,52 @@ sub cpu_properties { $cpu_layout = $phyical_count . 'x '; } $cpu_layout .= count_alpha($cpu_cores) . 'Core'; - $cpu_layout .= ' (' . $cpu{'dies'}. '-Die)' if !$bsd_type && $cpu{'dies'} > 1; + $cpu_layout .= ' (' . $cpu->{'dies'}. '-Die)' if !$bsd_type && $cpu->{'dies'} > 1; # the only possible change for bsds is if we can get phys counts in the future if ($bsd_type){ - $l2_cache = $cpu{'l2-cache'} * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $phyical_count; } # AMD SOS chips appear to report full L2 cache per core - elsif ($cpu{'type'} eq 'amd' && ($cpu{'family'} eq '14' || $cpu{'family'} eq '15' || $cpu{'family'} eq '16')){ - $l2_cache = $cpu{'l2-cache'} * $phyical_count; + elsif ($cpu->{'type'} eq 'amd' && ($cpu->{'family'} eq '14' || $cpu->{'family'} eq '15' || $cpu->{'family'} eq '16')){ + $l2_cache = $cpu->{'l2-cache'} * $phyical_count; } - elsif ($cpu{'type'} ne 'intel'){ - $l2_cache = $cpu{'l2-cache'} * $cpu_cores * $phyical_count; + elsif ($cpu->{'type'} ne 'intel'){ + $l2_cache = $cpu->{'l2-cache'} * $cpu_cores * $phyical_count; } ## note: this handles how intel reports L2, total instead of per core like AMD does # note that we need to multiply by number of actual cpus here to get true cache size else { - $l2_cache = $cpu{'l2-cache'} * $phyical_count; + $l2_cache = $cpu->{'l2-cache'} * $phyical_count; } - if ($l1_cache > 0){ - $l1_cache = "$l1_cache KiB"; - } - if ($l2_cache > 10000){ - $l2_cache = sprintf("%.01f MiB",$l2_cache/1024); # trim to no decimals? - } - elsif ($l2_cache > 0){ - $l2_cache = "$l2_cache KiB"; - } - if ($l3_cache > 10000){ - $l3_cache = sprintf("%.01f MiB",$l3_cache/1024); # trim to no decimals? - } - elsif ($l3_cache > 0){ - $l3_cache = "$l3_cache KiB"; - } - if ($cpu{'cur-freq'} && $cpu{'min-freq'} && $cpu{'max-freq'} ){ - $min_max = "$cpu{'min-freq'}/$cpu{'max-freq'} MHz"; + if ($cpu->{'cur-freq'} && $cpu->{'min-freq'} && $cpu->{'max-freq'} ){ + $min_max = "$cpu->{'min-freq'}/$cpu->{'max-freq'} MHz"; $min_max_key = "min/max"; $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed'; - $speed = "$cpu{'cur-freq'} MHz"; + $speed = "$cpu->{'cur-freq'} MHz"; } - elsif ($cpu{'cur-freq'} && $cpu{'max-freq'}){ - $min_max = "$cpu{'max-freq'} MHz"; + elsif ($cpu->{'cur-freq'} && $cpu->{'max-freq'}){ + $min_max = "$cpu->{'max-freq'} MHz"; $min_max_key = "max"; $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed'; - $speed = "$cpu{'cur-freq'} MHz"; + $speed = "$cpu->{'cur-freq'} MHz"; } -# elsif ($cpu{'cur-freq'} && $cpu{'max-freq'} && $cpu{'cur-freq'} == $cpu{'max-freq'}){ +# elsif ($cpu->{'cur-freq'} && $cpu->{'max-freq'} && $cpu->{'cur-freq'} == $cpu->{'max-freq'}){ # $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed'; -# $speed = "$cpu{'cur-freq'} MHz (max)"; +# $speed = "$cpu->{'cur-freq'} MHz (max)"; # } - elsif ($cpu{'cur-freq'} && $cpu{'min-freq'}){ - $min_max = "$cpu{'min-freq'} MHz"; + elsif ($cpu->{'cur-freq'} && $cpu->{'min-freq'}){ + $min_max = "$cpu->{'min-freq'} MHz"; $min_max_key = "min"; $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed'; - $speed = "$cpu{'cur-freq'} MHz"; + $speed = "$cpu->{'cur-freq'} MHz"; } - elsif ($cpu{'cur-freq'} && !$cpu{'max-freq'}){ + elsif ($cpu->{'cur-freq'} && !$cpu->{'max-freq'}){ $speed_key = ($show{'short'} || $show{'cpu-basic'}) ? 'speed' : 'Speed'; - $speed = "$cpu{'cur-freq'} MHz"; + $speed = "$cpu->{'cur-freq'} MHz"; } - if ( !$bits_sys && !$b_arm && $cpu{'flags'} ){ - $bits_sys = ($cpu{'flags'} =~ /\blm\b/) ? 64 : 32; + if ( !$bits_sys && !$b_arm && $cpu->{'flags'} ){ + $bits_sys = ($cpu->{'flags'} =~ /\blm\b/) ? 64 : 32; } my %cpu_properties = ( 'bits-sys' => $bits_sys, @@ -7956,7 +8055,7 @@ sub cpu_properties { 'l3-cache' => $l3_cache, ); main::log_data('dump','%cpu_properties',\%cpu_properties) if $b_log; - #print Data::Dumper::Dumper \%cpu; + #print Data::Dumper::Dumper $cpu; #print Data::Dumper::Dumper \%cpu_properties; #my $dc = scalar @dies; #print 'phys: ' . $pc . ' dies: ' . $dc, "\n"; @@ -7969,16 +8068,15 @@ sub cpu_dmi_data { my %dmi_data = ('L1' => 0, 'L2' => 0,'L3' => 0, 'ext-clock' => undef, 'socket' => undef, 'speed' => undef, 'max-speed' => undef, 'upgrade' => undef, 'volts' => undef); my ($id,$amount,$socket,$upgrade); - foreach my $ref (@dmi){ - next if ref $ref ne 'ARRAY'; - my @item = @$ref; - next if ($item[0] < 4 || $item[0] == 5 || $item[0] == 6); - last if $item[0] > 7; - if ($item[0] == 7){ + foreach my $item (@dmi){ + next if ref $item ne 'ARRAY'; + next if ($item->[0] < 4 || $item->[0] == 5 || $item->[0] == 6); + last if $item->[0] > 7; + if ($item->[0] == 7){ # skip first three row, we don't need that data - splice @item, 0, 3; + splice @$item, 0, 3; ($id,$amount) = ('',0); - foreach my $value (@item){ + foreach my $value (@$item){ next if $value =~ /~/; # variants: L3 - Cache; L3 Cache; L3-cache; CPU Internal L1 if ($value =~ /^Socket Designation:.* (L[1-3])\b/){ @@ -8001,11 +8099,11 @@ sub cpu_dmi_data { # the same for each cpu, which in most pc situations they will be, # and ARM etc won't be using dmi data here anyway. # Older dmidecode appear to have unreliable Upgrade outputs - elsif ($item[0] == 4){ + elsif ($item->[0] == 4){ # skip first three row, we don't need that data - splice @item, 0, 3; + splice @$item, 0, 3; ($socket,$upgrade) = (undef); - foreach my $value (@item){ + foreach my $value (@$item){ next if $value =~ /~/; # note: on single cpu systems, Socket Designation shows socket type, # but on multi, shows like, CPU1; CPU Socket #2; Socket 0; so check values a bit. @@ -8061,11 +8159,11 @@ sub cpu_bugs_sys { my @items = main::globber('/sys/devices/system/cpu/vulnerabilities/*'); if (@items){ foreach (@items){ - $value = ( -r $_) ? (main::reader($_))[0] : main::row_defaults('root-required'); + $value = ( -r $_) ? main::reader($_,'',0) : main::row_defaults('root-required'); $type = ($value =~ /^Mitigation:/) ? 'mitigation': 'status'; $_ =~ s/.*\/([^\/]+)$/$1/; $value =~ s/Mitigation: //; - @bugs = (@bugs,[($_,$type,$value)]); + push(@bugs,[($_,$type,$value)]); } } main::log_data('dump','@bugs',\@bugs) if $b_log; @@ -8076,25 +8174,25 @@ sub cpu_bugs_sys { sub cpu_speeds { eval $start if $b_log; - my (@processors) = @_; + my ($processors) = @_; my (@speeds); my @files = main::globber('/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq'); foreach (@files){ - my $speed = (main::reader($_))[0]; - if ($speed || $speed eq '0'){ - $speed = sprintf "%.0f", $speed/1000; - push @speeds, $speed; + my $speed = main::reader($_,'',0); + if (defined $speed){ + $speed = sprintf("%.0f", $speed/1000); + push(@speeds, $speed); } } if (!@speeds){ - foreach (@processors){ + foreach (@$processors){ if ($_ || $_ eq '0'){ - $_ = sprintf "%.0f", $_; - push @speeds, $_; + $_ = sprintf("%.0f", $_); + push(@speeds, $_); } } } - #print join '; ', @speeds, "\n"; + #print join('; ', @speeds), "\n"; eval $end if $b_log; return @speeds; } @@ -8111,15 +8209,15 @@ sub set_cpu_speeds_sys { if (-d $sys){ # corner cases, android, will have the files but they may be unreadable if (-r "$sys/$cur"){ - $speeds{'cur-freq'} = (main::reader("$sys/$cur"))[0] ; + $speeds{'cur-freq'} = main::reader("$sys/$cur",'',0); $speeds{'cur-freq'} = speed_cleaner($speeds{'cur-freq'},'khz'); } if (-r "$sys/$min"){ - $speeds{'min-freq'} = (main::reader("$sys/$min"))[0]; + $speeds{'min-freq'} = main::reader("$sys/$min",'',0); $speeds{'min-freq'} = speed_cleaner($speeds{'min-freq'},'khz'); } if (-r "$sys/$max"){ - $speeds{'max-freq'} = (main::reader("$sys/$max"))[0]; + $speeds{'max-freq'} = main::reader("$sys/$max",'',0); $speeds{'max-freq'} = speed_cleaner($speeds{'max-freq'},'khz'); } if ($b_arm || $b_mips){ @@ -8132,31 +8230,31 @@ sub set_cpu_speeds_sys { my ($current,$cur_temp,$max,$max_temp,$min,$min_temp) = (0,0,0,0,0,0); foreach (@policies){ $_ =~ s/\/$//; # strip off last slash in case globs have them - $max_temp = (-r "$_/cpuinfo_max_freq") ? (main::reader("$_/cpuinfo_max_freq"))[0] : 0; + $max_temp = (-r "$_/cpuinfo_max_freq") ? main::reader("$_/cpuinfo_max_freq",'',0) : 0; if ($max_temp){ $max_temp = speed_cleaner($max_temp,'khz'); - push @max_freq, $max_temp; + push(@max_freq, $max_temp); } $max = $max_temp if ($max_temp > $max); - $min_temp = (-r "$_/cpuinfo_min_freq") ? (main::reader("$_/cpuinfo_min_freq"))[0] : 0; + $min_temp = (-r "$_/cpuinfo_min_freq") ? main::reader("$_/cpuinfo_min_freq",'',0) : 0; if ($min_temp){ $min_temp = speed_cleaner($min_temp,'khz'); - push @min_freq, $min_temp; + push(@min_freq, $min_temp); } $min = $min_temp if ($min_temp < $min || $min == 0); - $cur_temp = (-r "$_/scaling_cur_freq") ? (main::reader("$_/scaling_cur_freq"))[0] : 0; + $cur_temp = (-r "$_/scaling_cur_freq") ? main::reader("$_/scaling_cur_freq",'',0) : 0; $cur_temp = speed_cleaner($cur_temp,'khz') if $cur_temp; if ($cur_temp > $current){ $current = $cur_temp; } } if (@max_freq){ - @max_freq = main::uniq(@max_freq); - $max = join ':', @max_freq; + main::uniq(\@max_freq); + $max = join(':', @max_freq); } if (@min_freq){ - @min_freq = main::uniq(@min_freq); - $min = join ':', @min_freq; + main::uniq(\@min_freq); + $min = join(':', @min_freq); } $speeds{'cur-freq'} = $current if $current; $speeds{'max-freq'} = $max if $max; @@ -8182,9 +8280,9 @@ sub cpu_dies_sys { my @data = main::globber('/sys/devices/system/cpu/cpu*/topology/core_siblings_list'); my (@dies); foreach (@data){ - my $siblings = (main::reader($_))[0]; + my $siblings = main::reader($_,'',0); if (! grep {/$siblings/} @dies){ - push @dies, $siblings; + push(@dies, $siblings); } } my $die_count = scalar @dies; @@ -8227,7 +8325,7 @@ sub cpu_flags_bsd { if ( @dmesg_boot){ foreach (@dmesg_boot){ if ( /Features/ || ( $bsd_type eq "openbsd" && /^cpu0:\s*[a-z0-9]{2,3}(\s|,)[a-z0-9]{2,3}(\s|,)/i ) ) { - my @line = split /:\s*/, lc($_); + my @line = split(/:\s*/, lc($_)); # free bsd has to have weird syntax: <....,> # Features2=0x1e98220b $line[1] =~ s/^[^<]*<|>[^>]*$//g; @@ -8256,6 +8354,7 @@ sub cpu_flags_bsd { return $flags; } +# only elbrus ID is actually used live sub cpu_vendor { eval $start if $b_log; my ($string) = @_; @@ -8281,9 +8380,9 @@ sub get_boost_status { eval $start if $b_log; my ($boost); my $path = '/sys/devices/system/cpu/cpufreq/boost'; - if (-f $path){ - $boost = (main::reader($path))[0]; - if (defined $boost && $boost =~/^[01]$/){ + if (-r $path){ + $boost = main::reader($path,'',0); + if (defined $boost && $boost =~ /^[01]$/){ $boost = ($boost) ? 'enabled' : 'disabled'; } } @@ -8295,23 +8394,22 @@ sub system_cpu_name { my (%cpus,$compat,@working); if (@working = main::globber('/sys/firmware/devicetree/base/cpus/cpu@*/compatible')){ foreach my $file (@working){ - $compat = (main::reader($file))[0]; + $compat = main::reader($file,'',0); next if $compat =~ /timer/; # seen on android # these can have non printing ascii... why? As long as we only have the # splits for: null 00/start header 01/start text 02/end text 03 - $compat = (split /\x01|\x02|\x03|\x00/, $compat)[0] if $compat; - $compat = (split /,\s*/, $compat)[-1] if $compat; + $compat = (split(/\x01|\x02|\x03|\x00/, $compat))[0] if $compat; + $compat = (split(/,\s*/, $compat))[-1] if $compat; $cpus{$compat} = ($cpus{$compat}) ? ++$cpus{$compat}: 1; } } # synthesize it, [4] will be like: cortex-a15-timer; sunxi-timer # so far all with this directory show soc name, not cpu name for timer elsif (! -d '/sys/firmware/devicetree/base' && @devices_timer){ - foreach my $ref (@devices_timer){ - @working = @$ref; - next if $working[0] ne 'timer' || !$working[4] || $working[4] =~ /timer-mem$/; - $working[4] =~ s/(-system)?-timer$//; - $compat = $working[4]; + foreach my $working (@devices_timer){ + next if $working->[0] ne 'timer' || !$working->[4] || $working->[4] =~ /timer-mem$/; + $working->[4] =~ s/(-system)?-timer$//; + $compat = $working->[4]; $cpus{$compat} = ($cpus{$compat}) ? ++$cpus{$compat}: 1; } } @@ -8324,9 +8422,10 @@ sub cpu_arch { eval $start if $b_log; my ($type,$family,$model,$stepping) = @_; $stepping = 0 if !main::is_numeric($stepping); - my $arch = ''; + my ($arch,$note) = ('',''); + my $check = main::row_defaults('note-check'); # See: docs/inxi-resources.txt - # print "$type;$family;$model\n"; + # print "type:$type fam:$family model:$model step:$stepping\n"; if ( $type eq 'amd'){ if ($family eq '4'){ if ( $model =~ /^(3|7|8|9|A)$/ ) {$arch = 'Am486'} @@ -8382,21 +8481,29 @@ sub cpu_arch { else {$arch = 'Jaguar'} } elsif ($family eq '17'){ - if ( $model =~ /^(1|11)$/ ) {$arch = 'Zen'} - elsif ( $model =~ /^(8|18)$/ ) {$arch = 'Zen+'} - # not positive about 2x, main resource shows only 31 and 71 hex - elsif ( $model =~ /^(2[0123456789ABCDEF]|31|71)$/ ) {$arch = 'Zen 2'} + if ( $model =~ /^(1|11|20)$/ ) {$arch = 'Zen'} + # Seen: stepping 1 is Zen+ Ryzen 7 3750H. But stepping 1 Zen is: Ryzen 3 3200U + # Unknown if stepping 0 is Zen or either. + elsif ( $model =~ /^(18)$/ ) { + $arch = 'Zen/Zen+'; + $note = $check; + } + elsif ( $model =~ /^(8)$/ ) {$arch = 'Zen+'} + # not positive about 2x, main resource shows only listed hex values + # used this but it didn't age well: ^(2[0123456789ABCDEF]| + elsif ( $model =~ /^(31|60|71|90)$/ ) {$arch = 'Zen 2'} # no info on these yet, but they are coming and are scheduled - # elsif ( $model =~ /^()$/ ) {$arch = 'Zen 3'} # elsif ( $model =~ /^()$/ ) {$arch = 'Zen 4'} - else {$arch = 'Zen'} + else { + $arch = 'Zen'; + $note = $check;} } elsif ($family eq '18'){ # model #s not known yet - $arch = 'Hygon Dhyana'; + $arch = 'Zen (Hygon Dhyana)'; } elsif ($family eq '19'){ - # model #s not known yet + # unconfirmed: model: 0 20 40 50 $arch = 'Zen 3'; } # note: family 20 may be Zen 4 but not known for sure yet @@ -8423,24 +8530,37 @@ sub cpu_arch { elsif ( $model =~ /^(F)$/ ) {$arch = 'Isaiah'} } } + # note, to test uncoment $cpu{'type'} = Elbrus in proc/cpuinfo logic elsif ( $type eq 'elbrus'){ - if ($family eq '4'){ - if ( $model eq '1' ) {$arch = 'Elbrus'} - elsif ( $model eq '2' ) {$arch = 'Elbrus-S'} - elsif ( $model eq '3' ) {$arch = 'Elbrus-4C'} - elsif ( $model eq '4' ) {$arch = 'Elbrus-2C+'} - elsif ( $model eq '6' ) {$arch = 'Elbrus-2CM'} - elsif ( $model eq '7' ) { - if ($stepping >= 2) {$arch = 'Elbrus-8C1';} - else {$arch = 'Elbrus-8C';} - } # note: stepping > 1 may be 8C1 - elsif ( $model eq '8' ) {$arch = 'Elbrus-1C+'} - elsif ( $model eq '9' ) {$arch = 'Elbrus-8CV'} - elsif ( $model eq '10' ) {$arch = 'Elbrus-12C'} - elsif ( $model eq '11' ) {$arch = 'Elbrus-16C'} - elsif ( $model eq '12' ) {$arch = 'Elbrus-2C3'} - else {$arch = 'Elbrus-??';} - } + # E8CB + if ($family eq '4'){ + if ( $model eq '1' ) {$arch = 'Elbrus'} + elsif ( $model eq '2' ) {$arch = 'Elbrus-S'} + elsif ( $model eq '3' ) {$arch = 'Elbrus-4C'} + elsif ( $model eq '4' ) {$arch = 'Elbrus-2C+'} + elsif ( $model eq '6' ) {$arch = 'Elbrus-2CM'} + elsif ( $model eq '7' ) { + if ($stepping >= 2) {$arch = 'Elbrus-8C1';} + else {$arch = 'Elbrus-8C';} + } # note: stepping > 1 may be 8C1 + elsif ( $model eq '8' ) {$arch = 'Elbrus-1C+'} + # 8C2 morphed out of E8CV, but the two were the same die + elsif ( $model eq '9' ) { + $arch = 'Elbrus-8CV/8C2'; + $note = $check;} + elsif ( $model eq '10' ) {$arch = 'Elbrus-12C'} + elsif ( $model eq '11' ) {$arch = 'Elbrus-16C'} + elsif ( $model eq '12' ) {$arch = 'Elbrus-2C3'} + else { + $arch = 'Elbrus-??'; + $note = $check;} + } + elsif ($family eq '5'){ + if ($model eq '9') {$arch = 'Elbrus-8C2'} + else { + $arch = 'Elbrus-??'; + $note = $check;} + } } elsif ( $type eq 'intel'){ if ($family eq '4'){ @@ -8449,11 +8569,10 @@ sub cpu_arch { elsif ($family eq '5'){ if ( $model =~ /^(1|2|3|7)$/ ) {$arch = 'P5'} elsif ( $model =~ /^(4|8)$/ ) {$arch = 'P5'} # MMX - elsif ( $model =~ /^(9)$/ ) {$arch = 'Quark'} + elsif ( $model =~ /^(9|A)$/ ) {$arch = 'Lakemont'} } elsif ($family eq '6'){ if ( $model =~ /^(1)$/ ) {$arch = 'P6 Pro'} - elsif ( $model =~ /^(15)$/ ) {$arch = 'M Tolapai'} # pentium M system on chip elsif ( $model =~ /^(3)$/ ) {$arch = 'P6 II Klamath'} elsif ( $model =~ /^(5)$/ ) {$arch = 'P6 II Deschutes'} elsif ( $model =~ /^(6)$/ ) {$arch = 'P6 II Mendocino'} @@ -8465,9 +8584,10 @@ sub cpu_arch { elsif ( $model =~ /^(D)$/ ) {$arch = 'M Dothan'} # Pentium M elsif ( $model =~ /^(E)$/ ) {$arch = 'M Yonah'} elsif ( $model =~ /^(F|16)$/ ) {$arch = 'Core Merom'} + elsif ( $model =~ /^(15)$/ ) {$arch = 'M Tolapai'} # pentium M system on chip elsif ( $model =~ /^(17|1D)$/ ) {$arch = 'Penryn'} - elsif ( $model =~ /^(1A|1E|1F|2E|25|2C|2F)$/ ) {$arch = 'Nehalem'} - elsif ( $model =~ /^(26|1C)$/ ) {$arch = 'Bonnell'} # atom Bonnell? 27? + elsif ( $model =~ /^(1A|1E|1F|25|2C|2E|2F)$/ ) {$arch = 'Nehalem'} + elsif ( $model =~ /^(1C|26)$/ ) {$arch = 'Bonnell'} # atom Bonnell? 27? elsif ( $model =~ /^(27|35|36)$/ ) {$arch = 'Saltwell'} elsif ( $model =~ /^(25|2C|2F)$/ ) {$arch = 'Westmere'} elsif ( $model =~ /^(2A|2D)$/ ) {$arch = 'Sandy Bridge'} @@ -8475,33 +8595,56 @@ sub cpu_arch { elsif ( $model =~ /^(3A|3E)$/ ) {$arch = 'Ivy Bridge'} elsif ( $model =~ /^(3C|3F|45|46)$/ ) {$arch = 'Haswell'} elsif ( $model =~ /^(3D|47|4F|56)$/ ) {$arch = 'Broadwell'} - elsif ( $model =~ /^(4E)$/ ) {$arch = 'Skylake'} # had 9E, cascade lake also 55 - # need to find stepping for cl, guessing stepping 4 is last for sl + elsif ( $model =~ /^(4C)$/ ) {$arch = 'Airmont'} + elsif ( $model =~ /^(4E)$/ ) {$arch = 'Skylake'} + # need to find stepping for these, guessing stepping 4 is last for SL elsif ( $model =~ /^(55)$/ ) { - if ($stepping > 4){$arch = 'Cascade Lake'} + if ($stepping >= 5 && $stepping <= 7){$arch = 'Cascade Lake'} + elsif ($stepping >= 8){$arch = 'Cooper Lake'} else {$arch = 'Skylake'} } + elsif ( $model =~ /^(57)$/ ) {$arch = 'Knights Landing'} elsif ( $model =~ /^(5C|5F)$/ ) {$arch = 'Goldmont'} elsif ( $model =~ /^(5E)$/ ) {$arch = 'Skylake-S'} - elsif ( $model =~ /^(4C)$/ ) {$arch = 'Airmont'} - elsif ( $model =~ /^(7A)$/ ) {$arch = 'Goldmont Plus'} - elsif ( $model =~ /^(7D|7E)$/ ) {$arch = 'Ice Lake'} - elsif ( $model =~ /^(8C)$/ ) {$arch = 'Tiger Lake'} - elsif ( $model =~ /^(8E|9E)$/ ) { - if ($model eq '9E' && ($stepping == 10 || $stepping == 11 || $stepping == 12 || $stepping == 13)){$arch = 'Coffee Lake'} - elsif ($model eq '8E' && $stepping == 10){$arch = 'Coffee Lake'} - elsif ($model eq '8E' && ($stepping == 11 || $stepping == 12)){$arch = 'Whiskey Lake'} - elsif ($model eq '8E' && $stepping == 9){$arch = 'Amber Lake'} - elsif ($stepping > 13){$arch = 'Comet Lake'} # guess, have not seen docs yet - # elsif ($stepping > 9 && $stepping < 14){$arch = 'Coffee Lake'} - # NOTE: kaby lake is 8E 9 but so is Amber Lake - else {$arch = 'Kaby Lake'} } - #elsif ( $model =~ /^(9E)$/ ) {$arch = 'Coffee Lake'} - elsif ( $model =~ /^(57)$/ ) {$arch = 'Knights Landing'} elsif ( $model =~ /^(66)$/ ) {$arch = 'Cannon Lake'} + # 6 are servers, 7 not + elsif ( $model =~ /^(6A|6C|7D|7E)$/ ) {$arch = 'Ice Lake'} + elsif ( $model =~ /^(7A)$/ ) {$arch = 'Goldmont Plus'} elsif ( $model =~ /^(85)$/ ) {$arch = 'Knights Mill'} elsif ( $model =~ /^(86)$/ ) {$arch = 'Tremont'} + elsif ( $model =~ /^(8C)$/ ) {$arch = 'Tiger Lake'} + elsif ( $model =~ /^(8E)$/ ) { + # can be AmberL or KabyL + if ($stepping == 9){ + $arch = 'Amber/Kaby Lake'; + $note = $check;} + elsif ($stepping == 10){ + $arch = 'Coffee Lake'} + elsif ($stepping == 11){ + $arch = 'Whiskey Lake'} + # can be WhiskeyL or CometL + elsif ($stepping == 12){ + $arch = 'Comet/Whiskey Lake'; + $note = $check;} + # note: had it as > 13, but 0xC seems to be CL + elsif ($stepping >= 13){ + $arch = 'Comet Lake'} # guess, have not seen docs yet + # NOTE: not enough info to lock this down + else { + $arch = 'Kaby Lake'; + $note = $check;} + } + elsif ( $model =~ /^(9E)$/ ) { + if ($stepping == 9){ + $arch = 'Kaby Lake'} + elsif ($stepping >= 10 && $stepping <= 13){ + $arch = 'Coffee Lake'} + else { + $arch = 'Kaby Lake'; + $note = $check;} + } + elsif ( $model =~ /^(A5)$/ ) {$arch = 'Comet Lake'} # steppings 0-5 # More info: comet: shares family/model, need to find stepping numbers - # Coming: meteor lake; alder lake; cooper lake; granite rapids; meteor lake; saphire rapids; + # Coming: meteor lake; alder lake; cooper lake; granite rapids; rocket lake; saphire rapids; } # itanium 1 family 7 all recalled elsif ($family eq 'B'){ @@ -8516,9 +8659,19 @@ sub cpu_arch { elsif ( $model =~ /^(6)$/ ) {$arch = 'Netburst Presler'} else {$arch = 'Netburst'} } + # this is not going to e accurate, WhiskyL or Kaby L can ID as Skylake + # but if it's a new cpu microarch not handled yet, it may give better + # than nothing result. This is intel only + # This is probably the gcc/clang -march/-mtune value, which is not + # necessarily the same as actual microarch, and varies between gcc/clang versions + if (!$model){ + my $file = '/sys/devices/cpu/caps/pmu_name'; + $model = main::reader($file,'strip',0) if -r $file; + $note = $check if $model; + } } eval $end if $b_log; - return $arch; + return ($arch,$note); } sub count_alpha { @@ -8548,7 +8701,7 @@ sub set_cpu_data { 'l3-cache' => 0, # store in KB 'max-freq' => 0, 'min-freq' => 0, - 'model_id' => '', + 'model_id' => undef, 'model_name' => '', 'processors' => [], 'rev' => '', @@ -8564,7 +8717,7 @@ sub speed_cleaner { return if ! $speed || $speed eq '0'; $speed =~ s/[GMK]HZ$//gi; $speed = ($speed/1000) if $opt && $opt eq 'khz'; - $speed = sprintf "%.0f", $speed; + $speed = sprintf("%.0f", $speed); return $speed; } sub cpu_cleaner { @@ -8580,7 +8733,8 @@ sub cpu_cleaner { } sub hex_and_decimal { my ($data) = @_; - if ($data){ + $data ||= ''; + if ($data =~ /\S/){ $data .= ' (' . hex($data) . ')' if hex($data) ne $data; } else { @@ -8597,7 +8751,7 @@ my ($b_hddtemp,$b_nvme,$smartctl_missing); my ($hddtemp,$nvme) = ('',''); my (@by_id,@by_path,@vendors); my ($debugger_dir); -# main::writer("$debugger_dir/system-repo-data-urpmq.txt",@data2) if $debugger_dir; +# main::writer("$debugger_dir/system-repo-data-urpmq.txt",\@data2) if $debugger_dir; sub get { eval $start if $b_log; my (@data,@rows,$key1,$val1); @@ -8608,9 +8762,9 @@ sub get { # NOTE: if (@data){ if ($type eq 'standard'){ - @data = create_output(@data); - @rows = (@rows,@data); - if ( $bsd_type && !@dm_boot_disk && $type eq 'standard' && $show{'disk'} ){ + @data = create_output(\@data); + push(@rows,@data); + if ($bsd_type && !@dm_boot_disk && $type eq 'standard' && $show{'disk'} ){ $key1 = 'Drive Report'; my $file = main::system_files('dmesg-boot'); if ( $file && ! -r $file){ @@ -8623,7 +8777,7 @@ sub get { $val1 = main::row_defaults('disk-data-bsd'); } @data = ({main::key($num++,0,1,$key1) => $val1,}); - @rows = (@rows,@data); + push(@rows,@data); } } else { @@ -8639,13 +8793,13 @@ sub get { if (!@rows){ $key1 = 'Message'; $val1 = main::row_defaults('disk-data'); - @data = ({main::key($num++,0,1,$key1) => $val1,}); + @rows = ({main::key($num++,0,1,$key1) => $val1,}); } - #@rows = (@rows,@data); + #push(@rows,@data); @data = (); if ($show{'optical'} || $show{'optical-basic'}){ @data = OpticalData::get(); - @rows = (@rows,@data); + push(@rows,@data); } ($b_hddtemp,$b_nvme,$hddtemp,$nvme) = (undef,undef,undef,undef); (@by_id,@by_path) = (undef,undef); @@ -8654,12 +8808,12 @@ sub get { } sub create_output { eval $start if $b_log; - my (@disks) = @_; - #print Data::Dumper::Dumper \@disks; - my ($b_oldage,$b_prefail,$b_smart,$b_smart_permissions,@data,@rows); + my ($disks) = @_; + #print Data::Dumper::Dumper $disks; + my ($b_oldage,$b_prefail,$b_smart,$b_smart_permissions,@rows); my ($num,$j) = (0,0); - my ($id,$model,$size,$used,$percent,$size_holder, - $used_holder) = ('','','','','','',''); + my ($id,$logical_total,$logical_used,$model,$size,$size_value,$used,$percent, + $size_holder,$used_holder) = ('','','','','','','','','',''); my @smart_basic =( ['smart','SMART'], ['smart-error','SMART Message'], @@ -8734,156 +8888,144 @@ sub create_output { ['smart-unknown-4-t','threshold'], ['smart-unknown-4-f','alert'], ); - my @sizing = main::get_size($disks[0]{'size'}) if $disks[0]{'size'}; - #print Data::Dumper::Dumper \@disks; - if (@sizing){ - $size = $sizing[0]; - # note: if a string is returned there will be no Size unit so just use string. - if (defined $sizing[0] && $sizing[1]){ - $size .= ' ' . $sizing[1]; - } - } - $size ||= 'N/A'; - @sizing = (); - @sizing = main::get_size($disks[0]{'used'}) if defined $disks[0]{'used'}; - if (@sizing){ - $used = $sizing[0]; - if (defined $sizing[0] && $sizing[1]){ - $used .= ' ' . $sizing[1]; - if (( $disks[0]{'size'} && $disks[0]{'size'} =~ /^[0-9]/ ) && - ( $disks[0]{'used'} =~ /^[0-9]/ ) ){ - $used = $used . ' (' . sprintf("%0.1f", $disks[0]{'used'}/$disks[0]{'size'}*100) . '%)'; - } - } - } - $used ||= 'N/A'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Local Storage') => '', - main::key($num++,0,2,'total') => $size, - main::key($num++,0,2,'used') => $used, }); - @rows = (@rows,@data); - shift @disks; + #print Data::Dumper::Dumper $disks; + $size = main::get_size($disks->[0]{'size'},'string','N/A'); + if ($disks->[0]{'logical-size'}){ + $rows[$j]{main::key($num++,1,2,'total')} = ''; + $rows[$j]{main::key($num++,0,3,'raw')} = $size; + $size = main::get_size($disks->[0]{'logical-size'},'string'); + $size_value = $disks->[0]{'logical-size'}; + #print Data::Dumper::Dumper $disks; + $rows[$j]{main::key($num++,1,3,'usable')} = $size; + } + else { + $size_value = $disks->[0]{'size'} if $disks->[0]{'size'}; + $rows[$j]{main::key($num++,0,2,'total')} = $size; + + } + $used = main::get_size($disks->[0]{'used'},'string','N/A'); + if ($extra > 0 && $disks->[0]{'logical-free'}){ + $size = main::get_size($disks->[0]{'logical-free'},'string'); + $rows[$j]{main::key($num++,0,4,'lvm-free')} = $size; + } + if (($size_value && $size_value =~ /^[0-9]/) && + ($used && $disks->[0]{'used'} =~ /^[0-9]/ )){ + $used = $used . ' (' . sprintf("%0.1f", $disks->[0]{'used'}/$size_value*100) . '%)'; + } + $rows[$j]{main::key($num++,0,2,'used')} = $used; + shift @$disks; if ($smartctl_missing){ $j = scalar @rows; $rows[$j]{main::key($num++,0,1,'SMART Message')} = $smartctl_missing; } - if ( $show{'disk'} && @disks){ - @disks = sort { $a->{'id'} cmp $b->{'id'} } @disks; - foreach my $ref (@disks){ + if ($show{'disk'} && @$disks){ + @$disks = sort { $a->{'id'} cmp $b->{'id'} } @$disks; + foreach my $row (@$disks){ ($b_oldage,$b_prefail,$b_smart,$id,$model,$size) = (0,0,0,'','',''); - my %row = %$ref; $num = 1; - $model = ($row{'model'}) ? $row{'model'}: 'N/A'; - $id = ($row{'id'}) ? "/dev/$row{'id'}":'N/A'; - my @sizing = main::get_size($row{'size'}); - #print Data::Dumper::Dumper \@disks; - if (@sizing){ - $size = $sizing[0]; - # note: if a string is returned there will be no Size unit so just use string. - if (defined $sizing[0] && $sizing[1]){ - $size .= ' ' . $sizing[1]; - $size_holder = $sizing[0]; - } - $size ||= 'N/A'; - } - else { - $size = 'N/A'; - } + $model = ($row->{'model'}) ? $row->{'model'}: 'N/A'; + $id = ($row->{'id'}) ? "/dev/$row->{'id'}":'N/A'; + $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; + #print Data::Dumper::Dumper $disks; $j = scalar @rows; - if (!$b_smart_permissions && $row{'smart-permissions'}){ + if (!$b_smart_permissions && $row->{'smart-permissions'}){ $b_smart_permissions = 1; - $rows[$j]{main::key($num++,0,1,'SMART Message')} = $row{'smart-permissions'}; + $rows[$j]{main::key($num++,0,1,'SMART Message')} = $row->{'smart-permissions'}; $j = scalar @rows; } - @data = ({ + push(@rows, { main::key($num++,1,1,'ID') => $id, }); - @rows = (@rows,@data); - if ($row{'type'}){ - $rows[$j]{main::key($num++,0,2,'type')} = $row{'type'}; + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,2,'maj-min')} = $row->{'maj-min'}; } - if ($row{'vendor'}){ - $rows[$j]{main::key($num++,0,2,'vendor')} = $row{'vendor'}; + if ($row->{'type'}){ + $rows[$j]{main::key($num++,0,2,'type')} = $row->{'type'}; + } + if ($row->{'vendor'}){ + $rows[$j]{main::key($num++,0,2,'vendor')} = $row->{'vendor'}; } $rows[$j]{main::key($num++,0,2,'model')} = $model; - if ($row{'drive-vendor'}){ - $rows[$j]{main::key($num++,0,2,'drive vendor')} = $row{'drive-vendor'}; + if ($row->{'drive-vendor'}){ + $rows[$j]{main::key($num++,0,2,'drive vendor')} = $row->{'drive-vendor'}; } - if ($row{'drive-model'}){ - $rows[$j]{main::key($num++,0,2,'drive model')} = $row{'drive-model'}; + if ($row->{'drive-model'}){ + $rows[$j]{main::key($num++,0,2,'drive model')} = $row->{'drive-model'}; } - if ($row{'family'}){ - $rows[$j]{main::key($num++,0,2,'family')} = $row{'family'}; + if ($row->{'family'}){ + $rows[$j]{main::key($num++,0,2,'family')} = $row->{'family'}; } $rows[$j]{main::key($num++,0,2,'size')} = $size; - if ($b_admin && $row{'block-physical'}){ + if ($b_admin && $row->{'block-physical'}){ $rows[$j]{main::key($num++,1,2,'block size')} = ''; - $rows[$j]{main::key($num++,0,3,'physical')} = $row{'block-physical'} . ' B'; - $rows[$j]{main::key($num++,0,3,'logical')} = ($row{'block-logical'}) ? $row{'block-logical'} . ' B' : 'N/A'; + $rows[$j]{main::key($num++,0,3,'physical')} = $row->{'block-physical'} . ' B'; + $rows[$j]{main::key($num++,0,3,'logical')} = ($row->{'block-logical'}) ? $row->{'block-logical'} . ' B' : 'N/A'; } - if ($extra > 1 && $row{'speed'}){ - if ($row{'sata'}){ - $rows[$j]{main::key($num++,0,2,'sata')} = $row{'sata'}; + if ($extra > 1 && $row->{'speed'}){ + if ($row->{'sata'}){ + $rows[$j]{main::key($num++,0,2,'sata')} = $row->{'sata'}; } - $rows[$j]{main::key($num++,0,2,'speed')} = $row{'speed'}; - $rows[$j]{main::key($num++,0,2,'lanes')} = $row{'lanes'} if $row{'lanes'}; + $rows[$j]{main::key($num++,0,2,'speed')} = $row->{'speed'}; + $rows[$j]{main::key($num++,0,2,'lanes')} = $row->{'lanes'} if $row->{'lanes'}; } - if ($extra > 2 && $row{'rotation'}){ - $rows[$j]{main::key($num++,0,2,'rotation')} = $row{'rotation'}; + if ($extra > 2 && $row->{'rotation'}){ + $rows[$j]{main::key($num++,0,2,'rotation')} = $row->{'rotation'}; } if ($extra > 1){ - my $serial = main::apply_filter($row{'serial'}); + my $serial = main::apply_filter($row->{'serial'}); $rows[$j]{main::key($num++,0,2,'serial')} = $serial; - if ($row{'drive-serial'}){ - $rows[$j]{main::key($num++,0,2,'drive serial')} = main::apply_filter($row{'drive-serial'}); + if ($row->{'drive-serial'}){ + $rows[$j]{main::key($num++,0,2,'drive serial')} = main::apply_filter($row->{'drive-serial'}); } - if ($row{'firmware'}){ - $rows[$j]{main::key($num++,0,2,'rev')} = $row{'firmware'}; + if ($row->{'firmware'}){ + $rows[$j]{main::key($num++,0,2,'rev')} = $row->{'firmware'}; } - if ($row{'drive-firmware'}){ - $rows[$j]{main::key($num++,0,2,'drive rev')} = $row{'drive-firmware'}; + if ($row->{'drive-firmware'}){ + $rows[$j]{main::key($num++,0,2,'drive rev')} = $row->{'drive-firmware'}; } } - if ($extra > 0 && $row{'temp'}){ - $rows[$j]{main::key($num++,0,2,'temp')} = $row{'temp'} . ' C'; + if ($extra > 0 && $row->{'temp'}){ + $rows[$j]{main::key($num++,0,2,'temp')} = $row->{'temp'} . ' C'; } # extra level tests already done - if (defined $row{'partition-table'}){ - $rows[$j]{main::key($num++,0,2,'scheme')} = $row{'partition-table'}; + if (defined $row->{'partition-table'}){ + $rows[$j]{main::key($num++,0,2,'scheme')} = $row->{'partition-table'}; } - if ($row{'smart'} || $row{'smart-error'}){ + if ($row->{'smart'} || $row->{'smart-error'}){ $j = scalar @rows; ## Basic SMART and drive info ## for (my $i = 0; $i < scalar @smart_basic;$i++){ - if ($row{$smart_basic[$i][0]}){ + if ($row->{$smart_basic[$i][0]}){ if (!$b_smart){ - my $support = ($row{'smart'}) ? $row{'smart'}: $row{'smart-error'}; + my $support = ($row->{'smart'}) ? $row->{'smart'}: $row->{'smart-error'}; $rows[$j]{main::key($num++,1,2,$smart_basic[$i][1])} = $support; $b_smart = 1; next; } - $rows[$j]{main::key($num++,0,3,$smart_basic[$i][1])} = $row{$smart_basic[$i][0]}; + $rows[$j]{main::key($num++,0,3,$smart_basic[$i][1])} = $row->{$smart_basic[$i][0]}; } } ## Old-Age errors ## for (my $i = 0; $i < scalar @smart_age;$i++){ - if ($row{$smart_age[$i][0]}){ + if ($row->{$smart_age[$i][0]}){ if (!$b_oldage){ $rows[$j]{main::key($num++,1,3,'Old-Age')} = ''; $b_oldage = 1; } - $rows[$j]{main::key($num++,0,4,$smart_age[$i][1])} = $row{$smart_age[$i][0]}; + $rows[$j]{main::key($num++,0,4,$smart_age[$i][1])} = $row->{$smart_age[$i][0]}; } } ## Pre-Fail errors ## for (my $i = 0; $i < scalar @smart_fail;$i++){ - if ($row{$smart_fail[$i][0]}){ + if ($row->{$smart_fail[$i][0]}){ if (!$b_prefail){ $rows[$j]{main::key($num++,1,3,'Pre-Fail')} = ''; $b_prefail = 1; } - $rows[$j]{main::key($num++,0,4,$smart_fail[$i][1])} = $row{$smart_fail[$i][0]}; + $rows[$j]{main::key($num++,0,4,$smart_fail[$i][1])} = $row->{$smart_fail[$i][0]}; } } } @@ -8899,22 +9041,22 @@ sub disk_data { my $num = 0; my ($used) = (0); PartitionData::partition_data() if !$b_partitions; - foreach my $ref (@partitions){ - my %row = %$ref; + RaidData::raid_data() if !$b_raid; + foreach my $row (@partitions){ # don't count remote used, also, some cases mount # panfs is parallel NAS volume manager, need more data - next if ($row{'fs'} && $row{'fs'} =~ /cifs|iso9660|nfs|panfs|sshfs|smbfs|unionfs/); + next if ($row->{'fs'} && $row->{'fs'} =~ /cifs|iso9660|nfs|panfs|sshfs|smbfs|unionfs/); # don't count zfs or file type swap - next if ($row{'swap-type'} && $row{'swap-type'} ne 'partition'); + next if ($row->{'swap-type'} && $row->{'swap-type'} ne 'partition'); # in some cases, like redhat, mounted cdrom/dvds show up in partition data - next if ($row{'dev-base'} && $row{'dev-base'} =~ /^sr[0-9]+$/); + next if ($row->{'dev-base'} && $row->{'dev-base'} =~ /^sr[0-9]+$/); # this is used for specific cases where bind, or incorrect multiple mounts # to same partitions, or btrfs sub volume mounts, is present. The value is # searched for an earlier appearance of that partition and if it is present, # the data is not added into the partition used size. - if ( $row{'dev-base'} !~ /^(\/\/|:\/)/ && ! (grep {/$row{'dev-base'}/} @devs) ){ - $used += $row{'used'} if $row{'used'}; - push @devs, $row{'dev-base'}; + if ( $row->{'dev-base'} !~ /^(\/\/|:\/)/ && ! (grep {/$row->{'dev-base'}/} @devs) ){ + $used += $row->{'used'} if $row->{'used'}; + push(@devs, $row->{'dev-base'}); } } if (!$bsd_type){ @@ -8924,12 +9066,11 @@ sub disk_data { @data = dmesg_boot_data($used); } if ($b_admin){ - my $ref = $alerts{'smartctl'}; - if ( $ref && $$ref{'action'} eq 'use'){ - @data = smartctl_data(@data); + if ( $alerts{'smartctl'} && $alerts{'smartctl'}->{'action'} eq 'use'){ + @data = smartctl_data(\@data); } else { - $smartctl_missing = $$ref{'missing'}; + $smartctl_missing = $alerts{'smartctl'}->{'missing'}; } } print Data::Dumper::Dumper \@data if $test[13];; @@ -8941,32 +9082,29 @@ sub proc_data { eval $start if $b_log; my ($used) = @_; my (@data,@drives); - my ($b_hdx,$size,$drive_size) = (0,0,0); - set_proc_partitions() if !$b_proc_partitions; - foreach (@proc_partitions){ - next if (/^\s*$/); - my @row = split /\s+/, $_; - if ( $row[-1] =~ /^([hsv]d[a-z]+|(ada|mmcblk|n[b]?d|nvme[0-9]+n)[0-9]+)$/) { - $drive_size = $row[2]; - $b_hdx = 1 if $row[-1] =~ /^hd[a-z]/; - @data = ({ + my ($b_hdx,$logical_size,$size) = (0,0,0); + main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + foreach my $row (@proc_partitions){ + if ( $row->[-1] =~ /^(fio[a-z]+|[hsv]d[a-z]+|(ada|mmcblk|n[b]?d|nvme[0-9]+n)[0-9]+)$/) { + $b_hdx = 1 if $row->[-1] =~ /^hd[a-z]/; + push(@drives, { 'firmware' => '', - 'id' => $row[-1], + 'id' => $row->[-1], + 'maj-min' => $row->[0] . ':' . $row->[1], 'model' => '', 'serial' => '', - 'size' => $drive_size, + 'size' => $row->[2], 'spec' => '', 'speed' => '', 'temp' => '', 'type' => '', 'vendor' => '', }); - @drives = (@drives,@data); } # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below # See https://www.mjmwired.net/kernel/Documentation/devices.txt for kernel 4.x device numbers - # if ( $row[0] =~ /^(3|22|33|8)$/ && $row[1] % 16 == 0 ) { - # $size += $row[2]; + # if ( $row->[0] =~ /^(3|22|33|8)$/ && $row->[1] % 16 == 0 ) { + # $size += $row->[2]; # } # special case from this data: 8 0 156290904 sda # 43 0 48828124 nbd0 @@ -8974,41 +9112,41 @@ sub proc_data { # Note: with > 1 nvme drives, the minor number no longer passes the modulus tests, # It appears to just increase randomly from the first 0 minor of the first nvme to # nvme partitions to next nvme, so it only passes the test for the first nvme drive. - if ( $row[0] =~ /^(3|8|22|33|43|179|202|252|253|254|259)$/ && - $row[-1] =~ /(mmcblk[0-9]+|n[b]?d[0-9]+|nvme[0-9]+n[0-9]+|[hsv]d[a-z]+)$/ && - ( $row[1] % 16 == 0 || $row[1] % 16 == 8 || $row[-1] =~ /(nvme[0-9]+n[0-9]+)$/) ) { - $size += $row[2]; + if ( $row->[0] =~ /^(3|8|22|33|43|179|202|252|253|254|259)$/ && + $row->[-1] =~ /(mmcblk[0-9]+|n[b]?d[0-9]+|nvme[0-9]+n[0-9]+|fio[a-z]+|[hsv]d[a-z]+)$/ && + ( $row->[1] % 16 == 0 || $row->[1] % 16 == 8 || $row->[-1] =~ /(nvme[0-9]+n[0-9]+)$/) ) { + $size += $row->[2]; } } + # raw_logical[0] is total of all logical raid/lvm found + # raw_logical[1] is total of all components found. If this totally fails, + # and we end up with raw logical less than used, give up + if (@raw_logical && $raw_logical[0] && (!$used || $raw_logical[0] > $used)){ + $logical_size = ($size - $raw_logical[1] + $raw_logical[0]); + } # print Data::Dumper::Dumper \@drives; main::log_data('data',"size: $size") if $b_log; @data = ({ + 'logical-size' => $logical_size, + 'logical-free' => $raw_logical[2], 'size' => $size, 'used' => $used, }); #print Data::Dumper::Dumper \@data; - if ( $show{'disk'} ){ - @drives = (@data,@drives); + if ($show{'disk'}){ + unshift(@drives,@data); # print 'drives:', Data::Dumper::Dumper \@drives; - @data = proc_data_advanced($b_hdx,@drives); + @data = proc_data_advanced($b_hdx,\@drives); } main::log_data('dump','@data',\@data) if $b_log; # print Data::Dumper::Dumper \@data; eval $end if $b_log; return @data; } -sub set_proc_partitions { - eval $start if $b_log; - $b_proc_partitions = 1; - if (my $file = main::system_files('partitions')){ - @proc_partitions = main::reader($file,'strip'); - shift @proc_partitions; - } - eval $end if $b_log; -} + sub proc_data_advanced { eval $start if $b_log; - my ($b_hdx,@drives) = @_; + my ($b_hdx,$drives) = @_; my ($i) = (0); my (@data,@disk_data,@rows,@scsi,@temp,@working); my ($pt_cmd) = ('unset'); @@ -9021,17 +9159,17 @@ sub proc_data_advanced { # we also don't need the partition items my $pattern = '^\/dev\/disk\/by-id\/(md-|lvm-|dm-|wwn-|nvme-eui|raid-|scsi-([0-9]ATA|SATA))|-part[0-9]+$'; @by_id = grep {!/$pattern/} @by_id if @by_id; - # print join "\n", @by_id, "\n"; + # print join("\n", @by_id), "\n"; @by_path = main::globber('/dev/disk/by-path/*'); ## check for all ide type drives, non libata, only do it if hdx is in array ## this is now being updated for new /sys type paths, this may handle that ok too ## skip the first rows in the loops since that's the basic size/used data if ($b_hdx){ - for ($i = 1; $i < scalar @drives; $i++){ - $file = "/proc/ide/$drives[$i]{'id'}/model"; - if ( $drives[$i]{'id'} =~ /^hd[a-z]/ && -e $file){ - $model = (main::reader($file,'strip'))[0]; - $drives[$i]{'model'} = $model; + for ($i = 1; $i < scalar @$drives; $i++){ + $file = "/proc/ide/$drives->[$i]{'id'}/model"; + if ( $drives->[$i]{'id'} =~ /^hd[a-z]/ && -e $file){ + $model = main::reader($file,'strip',0); + $drives->[$i]{'model'} = $model; } } } @@ -9039,56 +9177,55 @@ sub proc_data_advanced { if ($file = main::system_files('scsi')){ @scsi = scsi_data($file); } - # print 'drives:', Data::Dumper::Dumper \@drives; - for ($i = 1; $i < scalar @drives; $i++){ - #next if $drives[$i]{'id'} =~ /^hd[a-z]/; + # print 'drives:', Data::Dumper::Dumper $drives; + for ($i = 1; $i < scalar @$drives; $i++){ + #next if $drives->[$i]{'id'} =~ /^hd[a-z]/; ($block_type,$firmware,$model,$partition_scheme, $serial,$vendor,$working_path) = ('','','','','','',''); if ($extra > 2){ - @data = advanced_disk_data($pt_cmd,$drives[$i]{'id'}); + @data = advanced_disk_data($pt_cmd,$drives->[$i]{'id'}); $pt_cmd = $data[0]; - $drives[$i]{'partition-table'} = uc($data[1]) if $data[1]; - $drives[$i]{'rotation'} = "$data[2] rpm" if $data[2]; + $drives->[$i]{'partition-table'} = uc($data[1]) if $data[1]; + $drives->[$i]{'rotation'} = "$data[2] rpm" if $data[2]; } - #print "$drives[$i]{'id'}\n"; - @disk_data = disk_data_by_id("/dev/$drives[$i]{'id'}"); + #print "$drives->[$i]{'id'}\n"; + @disk_data = disk_data_by_id("/dev/$drives->[$i]{'id'}"); main::log_data('dump','@disk_data', \@disk_data) if $b_log; - if ($drives[$i]{'id'} =~ /[sv]d[a-z]/){ + if ($drives->[$i]{'id'} =~ /[sv]d[a-z]/){ $block_type = 'sdx'; - $working_path = "/sys/block/$drives[$i]{'id'}/device/"; + $working_path = "/sys/block/$drives->[$i]{'id'}/device/"; } - elsif ($drives[$i]{'id'} =~ /mmcblk/){ + elsif ($drives->[$i]{'id'} =~ /mmcblk/){ $block_type = 'mmc'; - $working_path = "/sys/block/$drives[$i]{'id'}/device/"; + $working_path = "/sys/block/$drives->[$i]{'id'}/device/"; } - elsif ($drives[$i]{'id'} =~ /nvme/){ + elsif ($drives->[$i]{'id'} =~ /nvme/){ $block_type = 'nvme'; # this results in: # /sys/devices/pci0000:00/0000:00:03.2/0000:06:00.0/nvme/nvme0/nvme0n1 # but we want to go one level down so slice off trailing nvme0n1 - $working_path = Cwd::abs_path("/sys/block/$drives[$i]{'id'}"); + $working_path = Cwd::abs_path("/sys/block/$drives->[$i]{'id'}"); $working_path =~ s/nvme[^\/]*$//; } main::log_data('data',"working path: $working_path") if $b_log; if ($b_admin && -e "/sys/block/"){ - my @working = block_data($drives[$i]{'id'}); - $drives[$i]{'block-logical'} = $working[0]; - $drives[$i]{'block-physical'} = $working[1]; + my @working = block_data($drives->[$i]{'id'}); + $drives->[$i]{'block-logical'} = $working[0]; + $drives->[$i]{'block-physical'} = $working[1]; } if ($block_type && @scsi && @by_id && ! -e "${working_path}model" && ! -e "${working_path}name"){ ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the # discovered disk name AND ends with the correct identifier, sdx # get rid of whitespace for some drive names and ids, and extra data after - in name SCSI: - foreach my $ref (@scsi){ - my %row = %$ref; - if ($row{'model'}){ - $row{'model'} = (split /\s*-\s*/,$row{'model'})[0]; + foreach my $row (@scsi){ + if ($row->{'model'}){ + $row->{'model'} = (split(/\s*-\s*/,$row->{'model'}))[0]; foreach my $id (@by_id){ - if ($id =~ /$row{'model'}/ && "/dev/$drives[$i]{'id'}" eq Cwd::abs_path($id)){ - $drives[$i]{'firmware'} = $row{'firmware'}; - $drives[$i]{'model'} = $row{'model'}; - $drives[$i]{'vendor'} = $row{'vendor'}; + if ($id =~ /$row->{'model'}/ && "/dev/$drives->[$i]{'id'}" eq Cwd::abs_path($id)){ + $drives->[$i]{'firmware'} = $row->{'firmware'}; + $drives->[$i]{'model'} = $row->{'model'}; + $drives->[$i]{'vendor'} = $row->{'vendor'}; last SCSI; } } @@ -9100,61 +9237,57 @@ sub proc_data_advanced { elsif ( (!@disk_data || !$disk_data[0] ) && $block_type){ # NOTE: while path ${working_path}vendor exists, it contains junk value, like: ATA $path = "${working_path}model"; - if ( -e $path){ - $model = (main::reader($path,'strip'))[0]; - if ($model){ - $drives[$i]{'model'} = $model; - } + if ( -r $path){ + $model = main::reader($path,'strip',0); + $drives->[$i]{'model'} = $model if $model; } - elsif ($block_type eq 'mmc' && -e "${working_path}name"){ + elsif ($block_type eq 'mmc' && -r "${working_path}name"){ $path = "${working_path}name"; - $model = (main::reader($path,'strip'))[0]; - if ($model){ - $drives[$i]{'model'} = $model; - } + $model = main::reader($path,'strip',0); + $drives->[$i]{'model'} = $model if $model; } } - if (!$drives[$i]{'model'} && @disk_data){ - $drives[$i]{'model'} = $disk_data[0] if $disk_data[0]; - $drives[$i]{'vendor'} = $disk_data[1] if $disk_data[1]; + if (!$drives->[$i]{'model'} && @disk_data){ + $drives->[$i]{'model'} = $disk_data[0] if $disk_data[0]; + $drives->[$i]{'vendor'} = $disk_data[1] if $disk_data[1]; } # maybe rework logic if find good scsi data example, but for now use this - elsif ($drives[$i]{'model'} && !$drives[$i]{'vendor'}) { - $drives[$i]{'model'} = main::disk_cleaner($drives[$i]{'model'}); - my @device_data = device_vendor($drives[$i]{'model'},''); - $drives[$i]{'model'} = $device_data[1] if $device_data[1]; - $drives[$i]{'vendor'} = $device_data[0] if $device_data[0]; + elsif ($drives->[$i]{'model'} && !$drives->[$i]{'vendor'}) { + $drives->[$i]{'model'} = main::disk_cleaner($drives->[$i]{'model'}); + my @device_data = device_vendor($drives->[$i]{'model'},''); + $drives->[$i]{'model'} = $device_data[1] if $device_data[1]; + $drives->[$i]{'vendor'} = $device_data[0] if $device_data[0]; } if ($working_path){ $path = "${working_path}removable"; - $drives[$i]{'type'} = 'Removable' if -e $path && (main::reader($path,'strip'))[0]; # 0/1 value + $drives->[$i]{'type'} = 'Removable' if -r $path && main::reader($path,'strip',0); # 0/1 value } - my $peripheral = peripheral_data($drives[$i]{'id'}); + my $peripheral = peripheral_data($drives->[$i]{'id'}); # note: we only want to update type if we found a peripheral, otherwise preserve value - $drives[$i]{'type'} = $peripheral if $peripheral; - # print "type:$drives[$i]{'type'}\n"; + $drives->[$i]{'type'} = $peripheral if $peripheral; + # print "type:$drives->[$i]{'type'}\n"; if ($extra > 0){ - $drives[$i]{'temp'} = hdd_temp("/dev/$drives[$i]{'id'}"); + $drives->[$i]{'temp'} = hdd_temp("$drives->[$i]{'id'}"); if ($extra > 1){ - my @speed_data = device_speed($drives[$i]{'id'}); - $drives[$i]{'speed'} = $speed_data[0] if $speed_data[0]; - $drives[$i]{'lanes'} = $speed_data[1] if $speed_data[1]; + my @speed_data = device_speed($drives->[$i]{'id'}); + $drives->[$i]{'speed'} = $speed_data[0] if $speed_data[0]; + $drives->[$i]{'lanes'} = $speed_data[1] if $speed_data[1]; if (@disk_data && $disk_data[2]){ - $drives[$i]{'serial'} = $disk_data[2]; + $drives->[$i]{'serial'} = $disk_data[2]; } else { $path = "${working_path}serial"; - if ( -e $path){ - $serial = (main::reader($path,'strip'))[0]; - $drives[$i]{'serial'} = $serial if $serial; + if ( -r $path){ + $serial = main::reader($path,'strip',0); + $drives->[$i]{'serial'} = $serial if $serial; } } - if ($extra > 2 && !$drives[$i]{'firmware'} ){ + if ($extra > 2 && !$drives->[$i]{'firmware'} ){ my @fm = ('rev','fmrev','firmware_rev'); # 0 ~ default; 1 ~ mmc; 2 ~ nvme foreach my $firmware (@fm){ $path = "${working_path}$firmware"; - if ( -e $path){ - $drives[$i]{'firmware'} = (main::reader($path,'strip'))[0]; + if ( -r $path){ + $drives->[$i]{'firmware'} = main::reader($path,'strip',0); last; } } @@ -9162,9 +9295,9 @@ sub proc_data_advanced { } } } - # print Data::Dumper::Dumper \@drives; + # print Data::Dumper::Dumper $drives; eval $end if $b_log; - return @drives; + return @$drives; } # camcontrol identify |grep ^serial (this might be (S)ATA specific) # smartcl -i |grep ^Serial @@ -9177,7 +9310,7 @@ sub dmesg_boot_data { my $file = main::system_files('dmesg-boot'); if (@dm_boot_disk){ foreach (@dm_boot_disk){ - my @row = split /:\s*/, $_; + my @row = split(/:\s*/, $_); next if ! defined $row[1]; if ($id_holder ne $row[0]){ $i++ if $id_holder; @@ -9206,7 +9339,7 @@ sub dmesg_boot_data { # my $count = ($drives[$i]{'model'} =~ tr/,//); if ($count && $count > 1){ - @temp = split /,\s*/, $drives[$i]{'model'}; + @temp = split(/,\s*/, $drives[$i]{'model'}); $drives[$i]{'model'} = $temp[1]; } } @@ -9253,7 +9386,7 @@ sub dmesg_boot_data { }); #main::log_data('dump','@data',\@data) if $b_log; if ( $show{'disk'} ){ - @data = (@data,@drives); + push(@data,@drives); # print 'drives:', Data::Dumper::Dumper \@drives; } # print Data::Dumper::Dumper \@data; @@ -9263,35 +9396,34 @@ sub dmesg_boot_data { sub smartctl_data { eval $start if $b_log; - my (@data) = @_; + my ($data) = @_; my ($b_attributes,$b_intel,$b_kingston,$cmd,%holder,$id,@working,@result,@split); my ($splitter,$num,$a,$f,$r,$t,$v,$w,$y) = (':\s*',0,0,8,1,5,3,4,6); # $y is type, $t threashold, etc - my $smartctl = main::check_program('smartctl'); - for (my $i = 0; $i < scalar @data; $i++){ - next if !$data[$i]{'id'}; + for (my $i = 0; $i < scalar @$data; $i++){ + next if !$data->[$i]{'id'}; ($b_attributes,$b_intel,$b_kingston,$splitter,$num,$a,$r) = (0,0,0,':\s*',0,0,1); %holder = (); - #print $data[$i]{'id'},"\n"; + #print $data->[$i]{'id'},"\n"; # m2 nvme failed on nvme0n1 drive id: - $id = $data[$i]{'id'}; + $id = $data->[$i]{'id'}; $id =~ s/n[0-9]+$// if $id =~ /^nvme/; - $cmd = "$smartctl -AHi /dev/" . $id . ' 2>/dev/null'; + $cmd = $alerts{'smartctl'}->{'path'} . " -AHi /dev/" . $id . ' 2>/dev/null'; @result = main::grabber("$cmd", '', 'strip'); main::log_data('dump','@result', \@result) if $b_log; # log before cleanup @result = grep {!/^(smartctl|Copyright|==)/} @result; print 'Drive:/dev/' . $id . ":\n", Data::Dumper::Dumper\@result if $test[12]; if (scalar @result < 4 ){ if (grep {/failed: permission denied/i} @result){ - $data[$i]{'smart-permissions'} = main::row_defaults('tool-permissions','smartctl'); + $data->[$i]{'smart-permissions'} = main::row_defaults('tool-permissions','smartctl'); } elsif (grep {/unknown usb bridge/i} @result){ - $data[$i]{'smart-error'} = main::row_defaults('smartctl-usb'); + $data->[$i]{'smart-error'} = main::row_defaults('smartctl-usb'); } elsif (grep {/A mandatory SMART command failed/i} @result){ - $data[$i]{'smart-error'} = main::row_defaults('smartctl-command-failed'); + $data->[$i]{'smart-error'} = main::row_defaults('smartctl-command-failed'); } else { - $data[$i]{'smart-error'} = main::row_defaults('tool-unknown-error','smartctl'); + $data->[$i]{'smart-error'} = main::row_defaults('tool-unknown-error','smartctl'); } next; } @@ -9304,7 +9436,7 @@ sub smartctl_data { $r = 9; next; } - @split = split /$splitter/, $row; + @split = split(/$splitter/, $row); next if !$b_attributes && ! defined $split[$r]; # some cases where drive not in db threshhold will be: --- # value is usually 0 padded which confuses perl. However this will @@ -9318,76 +9450,76 @@ sub smartctl_data { $b_intel = 1 if $split[$r] =~/\bintel\b/i; $b_kingston = 1 if $split[$r] =~/kingston/i; # usb/firewire/thunderbolt - if ($data[$i]{'type'}){ + if ($data->[$i]{'type'}){ @working = device_vendor("$split[$r]"); - $data[$i]{'drive-model'} = $working[1] if $data[$i]{'model'} && $data[$i]{'model'} ne $working[1]; - $data[$i]{'drive-vendor'} = $working[0] if $data[$i]{'vendor'} && $data[$i]{'vendor'} ne $working[0]; + $data->[$i]{'drive-model'} = $working[1] if $data->[$i]{'model'} && $data->[$i]{'model'} ne $working[1]; + $data->[$i]{'drive-vendor'} = $working[0] if $data->[$i]{'vendor'} && $data->[$i]{'vendor'} ne $working[0]; } } elsif ($split[$a] eq 'Model Family'){ @working = device_vendor("$split[$r]"); - $data[$i]{'family'} = $working[1]; - # $data[$i]{'family'} =~ s/$data[$i]{'vendor'}\s*// if $data[$i]{'vendor'}; + $data->[$i]{'family'} = $working[1]; + # $data->[$i]{'family'} =~ s/$data->[$i]{'vendor'}\s*// if $data->[$i]{'vendor'}; } elsif ($split[$a] eq 'Firmware Version'){ # 01.01A01 vs 1A01 - if ($data[$i]{'firmware'} && $split[$r] !~ /$data[$i]{'firmware'}/){ - $data[$i]{'drive-firmware'} = $split[$r]; + if ($data->[$i]{'firmware'} && $split[$r] !~ /$data->[$i]{'firmware'}/){ + $data->[$i]{'drive-firmware'} = $split[$r]; } - elsif (!$data[$i]{'firmware'}){ - $data[$i]{'firmware'} = $split[$r]; + elsif (!$data->[$i]{'firmware'}){ + $data->[$i]{'firmware'} = $split[$r]; } } elsif ($split[$a] eq 'Rotation Rate'){ - $data[$i]{'rotation'} = $split[$r] if $split[$r] !~ /^Solid/; + $data->[$i]{'rotation'} = $split[$r] if $split[$r] !~ /^Solid/; } elsif ($split[$a] eq 'Serial Number'){ - if ( !$data[$i]{'serial'}){ - $data[$i]{'serial'} = $split[$r]; + if ( !$data->[$i]{'serial'}){ + $data->[$i]{'serial'} = $split[$r]; } - elsif ($data[$i]{'type'} && $split[$r] ne $data[$i]{'serial'}){ - $data[$i]{'drive-serial'} = $split[$r]; + elsif ($data->[$i]{'type'} && $split[$r] ne $data->[$i]{'serial'}){ + $data->[$i]{'drive-serial'} = $split[$r]; } } elsif ($split[$a] eq 'SATA Version is'){ if ( $split[$r] =~ /SATA ([0-9.]+), ([0-9.]+ [^\s]+)( \(current: ([1-9.]+ [^\s]+)\))?/){ - $data[$i]{'sata'} = $1; - $data[$i]{'speed'} = $2 if !$data[$i]{'speed'}; + $data->[$i]{'sata'} = $1; + $data->[$i]{'speed'} = $2 if !$data->[$i]{'speed'}; } } elsif ($split[$a] eq 'Sector Sizes'){ - if( $data[$i]{'type'} || !$data[$i]{'block-logical'} || !$data[$i]{'block-physical'} ){ + if( $data->[$i]{'type'} || !$data->[$i]{'block-logical'} || !$data->[$i]{'block-physical'} ){ if ($split[$r] =~ m|^([0-9]+) bytes logical/physical| ){ - $data[$i]{'block-logical'} = $1; - $data[$i]{'block-physical'} = $1; + $data->[$i]{'block-logical'} = $1; + $data->[$i]{'block-physical'} = $1; } # 512 bytes logical, 4096 bytes physical elsif ($split[$r] =~ m|^([0-9]+) bytes logical, ([0-9]+) bytes physical|){ - $data[$i]{'block-logical'} = $1; - $data[$i]{'block-physical'} = $2; + $data->[$i]{'block-logical'} = $1; + $data->[$i]{'block-physical'} = $2; } } } ## SMART STATUS/HEALTH ## elsif ($split[$a] eq 'SMART support is'){ if ($split[$r] =~ /^(Available|Unavailable) /){ - $data[$i]{'smart'} = $1; - $data[$i]{'smart'} = ($data[$i]{'smart'} eq 'Unavailable') ? 'no' : 'yes'; + $data->[$i]{'smart'} = $1; + $data->[$i]{'smart'} = ($data->[$i]{'smart'} eq 'Unavailable') ? 'no' : 'yes'; } elsif ($split[$r] =~ /^(Enabled|Disabled)/ ){ - $data[$i]{'smart-support'} = lc($1); + $data->[$i]{'smart-support'} = lc($1); } } elsif ($split[$a] eq 'SMART overall-health self-assessment test result' ){ - $data[$i]{'smart-status'} = $split[$r]; + $data->[$i]{'smart-status'} = $split[$r]; # seen nvme that only report smart health, not smart support - $data[$i]{'smart'} = 'yes' if !$data[$i]{'smart'}; + $data->[$i]{'smart'} = 'yes' if !$data->[$i]{'smart'}; } ## DEVICE CONDITION: temp/read/write/power on/cycles ## # Attributes data fields, sometimes are same syntax as info block:... elsif ( $split[$a] eq 'Power_Cycle_Count' || $split[$a] eq 'Power Cycles' ){ - $data[$i]{'smart-cycles'} = $split[$r] if $split[$r]; + $data->[$i]{'smart-cycles'} = $split[$r] if $split[$r]; } elsif ($split[$a] eq 'Power_On_Hours' || $split[$a] eq 'Power On Hours' || $split[$a] eq 'Power_On_Hours_and_Msec'){ @@ -9398,17 +9530,17 @@ sub smartctl_data { # $split[$r] = 43; if ($split[$r] =~ /^([0-9]+)$/){ if ($1 > 9000){ - $data[$i]{'smart-power-on-hours'} = int($1/(24*365)) . 'y ' . int($1/24)%365 . 'd ' . $1%24 . 'h'; + $data->[$i]{'smart-power-on-hours'} = int($1/(24*365)) . 'y ' . int($1/24)%365 . 'd ' . $1%24 . 'h'; } elsif ($1 > 100){ - $data[$i]{'smart-power-on-hours'} = int($1/24) . 'd ' . $1%24 . 'h'; + $data->[$i]{'smart-power-on-hours'} = int($1/24) . 'd ' . $1%24 . 'h'; } else { - $data[$i]{'smart-power-on-hours'} = $split[$r] . ' hrs'; + $data->[$i]{'smart-power-on-hours'} = $split[$r] . ' hrs'; } } else { - $data[$i]{'smart-power-on-hours'} = $split[$r]; + $data->[$i]{'smart-power-on-hours'} = $split[$r]; } } } @@ -9416,30 +9548,30 @@ sub smartctl_data { # Temperature like 29 Celsisu elsif ( $split[$a] eq 'Temperature_Celsius' || $split[$a] eq 'Temperature' || $split[$a] eq 'Airflow_Temperature_Cel' ) { - if (!$data[$i]{'temp'} && $split[$r]){ - $data[$i]{'temp'} = $split[$r]; + if (!$data->[$i]{'temp'} && $split[$r]){ + $data->[$i]{'temp'} = $split[$r]; } } ## DEVICE USE: Reads/Writes ## elsif ($split[$a] eq 'Data Units Read'){ - $data[$i]{'smart-units-read'} = $split[$r]; + $data->[$i]{'smart-units-read'} = $split[$r]; } elsif ($split[$a] eq 'Data Units Written'){ - $data[$i]{'smart-units-written'} = $split[$r]; + $data->[$i]{'smart-units-written'} = $split[$r]; } elsif ($split[$a] eq 'Host_Reads_32MiB'){ $split[$r] = $split[$r] * 32 * 1024; - $data[$i]{'smart-read'} = join ' ', main::get_size($split[$r]); + $data->[$i]{'smart-read'} = main::get_size($split[$r],'string'); } elsif ($split[$a] eq 'Host_Writes_32MiB'){ $split[$r] = $split[$r] * 32 * 1024; - $data[$i]{'smart-written'} = join ' ', main::get_size($split[$r]); + $data->[$i]{'smart-written'} = main::get_size($split[$r],'string'); } elsif ($split[$a] eq 'Lifetime_Reads_GiB'){ - $data[$i]{'smart-read'} = $split[$r] . ' GiB'; + $data->[$i]{'smart-read'} = $split[$r] . ' GiB'; } elsif ($split[$a] eq 'Lifetime_Writes_GiB'){ - $data[$i]{'smart-written'} = $split[$r] . ' GiB'; + $data->[$i]{'smart-written'} = $split[$r] . ' GiB'; } elsif ($split[$a] eq 'Total_LBAs_Read'){ if (main::is_numeric($split[$r])){ @@ -9454,9 +9586,9 @@ sub smartctl_data { } # this is what it's supposed to refer to else { - $split[$r] = int($data[$i]{'block-logical'} * $split[$r] / 1024); + $split[$r] = int($data->[$i]{'block-logical'} * $split[$r] / 1024); } - $data[$i]{'smart-read'} = join ' ', main::get_size($split[$r]); + $data->[$i]{'smart-read'} = main::get_size($split[$r],'string'); } } elsif ($split[$a] eq 'Total_LBAs_Written'){ @@ -9472,53 +9604,53 @@ sub smartctl_data { } # this is what it's supposed to refer to, in byte blocks else { - $split[$r] = int($data[$i]{'block-logical'} * $split[$r] / 1024); + $split[$r] = int($data->[$i]{'block-logical'} * $split[$r] / 1024); } - $data[$i]{'smart-written'} = join ' ', main::get_size($split[$r]); + $data->[$i]{'smart-written'} = main::get_size($split[$r],'string'); } } ## DEVICE OLD AGE ## # 191 G-Sense_Error_Rate 0x0032 001 001 000 Old_age Always - 291 elsif ($split[$a] eq 'G-Sense_Error_Rate'){ - # $data[$i]{'smart-media-wearout'} = $split[$r]; + # $data->[$i]{'smart-media-wearout'} = $split[$r]; if ($b_attributes && $split[$r] > 100){ - $data[$i]{'smart-gsense-error-rate-r'} = $split[$r]; + $data->[$i]{'smart-gsense-error-rate-r'} = $split[$r]; } } elsif ($split[$a] eq 'Media_Wearout_Indicator'){ - # $data[$i]{'smart-media-wearout'} = $split[$r]; + # $data->[$i]{'smart-media-wearout'} = $split[$r]; # seen case where they used hex numbers becaause values # were in 47 billion range in hex. You can't hand perl an unquoted # hex number that is > 2^32 without tripping a perl warning if ($b_attributes && $split[$r] && !main::is_hex("$split[$r]") && $split[$r] > 0){ - $data[$i]{'smart-media-wearout-v'} = $split[$v]; - $data[$i]{'smart-media-wearout-t'} = $split[$t]; - $data[$i]{'smart-media-wearout-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-media-wearout-v'} = $split[$v]; + $data->[$i]{'smart-media-wearout-t'} = $split[$t]; + $data->[$i]{'smart-media-wearout-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Multi_Zone_Error_Rate'){ # note: all t values are 0 that I have seen if ( ($split[$v] - $split[$t]) < 50){ - $data[$i]{'smart-multizone-errors-v'} = $split[$v]; - $data[$i]{'smart-multizone-errors-t'} = $split[$v]; + $data->[$i]{'smart-multizone-errors-v'} = $split[$v]; + $data->[$i]{'smart-multizone-errors-t'} = $split[$v]; } } elsif ($split[$a] eq 'UDMA_CRC_Error_Count'){ if (main::is_numeric($split[$r]) && $split[$r] > 50){ - $data[$i]{'smart-udma-crc-errors-r'} = $split[$r]; - $data[$i]{'smart-udma-crc-errors-f'} = main::row_defaults('smartctl-udma-crc') if $split[$r] > 500; + $data->[$i]{'smart-udma-crc-errors-r'} = $split[$r]; + $data->[$i]{'smart-udma-crc-errors-f'} = main::row_defaults('smartctl-udma-crc') if $split[$r] > 500; } } ## DEVICE PRE-FAIL ## elsif ($split[$a] eq 'Available_Reservd_Space'){ - # $data[$i]{'smart-available-reserved-space'} = $split[$r]; + # $data->[$i]{'smart-available-reserved-space'} = $split[$r]; if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92){ - $data[$i]{'smart-available-reserved-space-v'} = $split[$v]; - $data[$i]{'smart-available-reserved-space-t'} = $split[$t]; - $data[$i]{'smart-available-reserved-space-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-available-reserved-space-v'} = $split[$v]; + $data->[$i]{'smart-available-reserved-space-t'} = $split[$t]; + $data->[$i]{'smart-available-reserved-space-f'} = $split[$f] if $split[$f] ne '-'; } } ## nvme splits these into two field/value sets @@ -9529,103 +9661,103 @@ sub smartctl_data { elsif ($split[$a] eq 'Available Spare Threshold'){ $split[$r] =~ s/%$//; if ($holder{'spare'} && main::is_numeric($split[$r]) && $split[$r]/$holder{'spare'} > 0.92 ){ - $data[$i]{'smart-available-reserved-space-v'} = $holder{'spare'}; - $data[$i]{'smart-available-reserved-space-t'} = int($split[$r]); + $data->[$i]{'smart-available-reserved-space-v'} = $holder{'spare'}; + $data->[$i]{'smart-available-reserved-space-t'} = int($split[$r]); } } elsif ($split[$a] eq 'End-to-End_Error'){ if ($b_attributes && int($split[$r]) > 0 && $split[$t]){ - $data[$i]{'smart-end-to-end-v'} = $split[$v]; - $data[$i]{'smart-end-to-end-t'} = $split[$t]; - $data[$i]{'smart-end-to-end-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-end-to-end-v'} = $split[$v]; + $data->[$i]{'smart-end-to-end-t'} = $split[$t]; + $data->[$i]{'smart-end-to-end-f'} = $split[$f] if $split[$f] ne '-'; } } # seen raw value: 0/8415644 elsif ($split[$a] eq 'Raw_Read_Error_Rate'){ if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92){ - $data[$i]{'smart-raw-read-error-rate-v'} = $split[$v]; - $data[$i]{'smart-raw-read-error-rate-t'} = $split[$t]; - $data[$i]{'smart-raw-read-error-rate-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-raw-read-error-rate-v'} = $split[$v]; + $data->[$i]{'smart-raw-read-error-rate-t'} = $split[$t]; + $data->[$i]{'smart-raw-read-error-rate-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Reallocated_Sector_Ct'){ if ($b_attributes && int($split[$r]) > 0 && $split[$t]){ - $data[$i]{'smart-reallocated-sectors-v'} = $split[$v]; - $data[$i]{'smart-reallocated-sectors-t'} = $split[$t]; - $data[$i]{'smart-reallocated-sectors-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-reallocated-sectors-v'} = $split[$v]; + $data->[$i]{'smart-reallocated-sectors-t'} = $split[$t]; + $data->[$i]{'smart-reallocated-sectors-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Retired_Block_Count'){ if ($b_attributes && int($split[$r]) > 0 && $split[$t]){ - $data[$i]{'smart-retired-blocks-v'} = $split[$v]; - $data[$i]{'smart-retired-blocks-t'} = $split[$t]; - $data[$i]{'smart-retired-blocks-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-retired-blocks-v'} = $split[$v]; + $data->[$i]{'smart-retired-blocks-t'} = $split[$t]; + $data->[$i]{'smart-retired-blocks-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Runtime_Bad_Block'){ if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-runtime-bad-block-v'} = $split[$v]; - $data[$i]{'smart-runtime-bad-block-t'} = $split[$t]; - $data[$i]{'smart-runtime-bad-block-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-runtime-bad-block-v'} = $split[$v]; + $data->[$i]{'smart-runtime-bad-block-t'} = $split[$t]; + $data->[$i]{'smart-runtime-bad-block-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Seek_Error_Rate'){ # value 72; threshold either 000 or 30 if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-seek-error-rate-v'} = $split[$v]; - $data[$i]{'smart-seek-error-rate-t'} = $split[$t]; - $data[$i]{'smart-seek-error-rate-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-seek-error-rate-v'} = $split[$v]; + $data->[$i]{'smart-seek-error-rate-t'} = $split[$t]; + $data->[$i]{'smart-seek-error-rate-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Spin_Up_Time'){ # raw will always be > 0 on spinning disks if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-spinup-time-v'} = $split[$v]; - $data[$i]{'smart-spinup-time-t'} = $split[$t]; - $data[$i]{'smart-spinup-time-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-spinup-time-v'} = $split[$v]; + $data->[$i]{'smart-spinup-time-t'} = $split[$t]; + $data->[$i]{'smart-spinup-time-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'SSD_Life_Left'){ # raw will always be > 0 on spinning disks if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-ssd-life-left-v'} = $split[$v]; - $data[$i]{'smart-ssd-life-left-t'} = $split[$t]; - $data[$i]{'smart-ssd-life-left-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-ssd-life-left-v'} = $split[$v]; + $data->[$i]{'smart-ssd-life-left-t'} = $split[$t]; + $data->[$i]{'smart-ssd-life-left-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Unused_Rsvd_Blk_Cnt_Tot'){ # raw will always be > 0 on spinning disks if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-unused-reserve-block-v'} = $split[$v]; - $data[$i]{'smart-unused-reserve-block-t'} = $split[$t]; - $data[$i]{'smart-unused-reserve-block-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-unused-reserve-block-v'} = $split[$v]; + $data->[$i]{'smart-unused-reserve-block-t'} = $split[$t]; + $data->[$i]{'smart-unused-reserve-block-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($split[$a] eq 'Used_Rsvd_Blk_Cnt_Tot'){ # raw will always be > 0 on spinning disks if ($b_attributes && $split[$v] && $split[$t] && $split[$t]/$split[$v] > 0.92 ){ - $data[$i]{'smart-used-reserve-block-v'} = $split[$v]; - $data[$i]{'smart-used-reserve-block-t'} = $split[$t]; - $data[$i]{'smart-used-reserve-block-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-used-reserve-block-v'} = $split[$v]; + $data->[$i]{'smart-used-reserve-block-t'} = $split[$t]; + $data->[$i]{'smart-used-reserve-block-f'} = $split[$f] if $split[$f] ne '-'; } } elsif ($b_attributes ){ if ( $split[$y] eq 'Pre-fail' && ($split[$f] ne '-' || ($split[$t] && $split[$v] && $split[$t]/$split[$v] > 0.92 ))) { $num++; - $data[$i]{'smart-unknown-' . $num . '-a'} = $split[$a]; - $data[$i]{'smart-unknown-' . $num . '-v'} = $split[$v]; - $data[$i]{'smart-unknown-' . $num . '-w'} = $split[$v]; - $data[$i]{'smart-unknown-' . $num . '-t'} = $split[$t]; - $data[$i]{'smart-unknown-' . $num . '-f'} = $split[$f] if $split[$f] ne '-'; + $data->[$i]{'smart-unknown-' . $num . '-a'} = $split[$a]; + $data->[$i]{'smart-unknown-' . $num . '-v'} = $split[$v]; + $data->[$i]{'smart-unknown-' . $num . '-w'} = $split[$v]; + $data->[$i]{'smart-unknown-' . $num . '-t'} = $split[$t]; + $data->[$i]{'smart-unknown-' . $num . '-f'} = $split[$f] if $split[$f] ne '-'; } } } } } - print Data::Dumper::Dumper\@data if $test[19]; + print Data::Dumper::Dumper $data if $test[19]; eval $end if $b_log; - return @data; + return @$data; } # check for usb/firewire/[and thunderwire when data found] @@ -9711,11 +9843,11 @@ sub advanced_disk_data { else { foreach (@data){ if ( /^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)/ ){ - my @working = split /=/, $_; + my @working = split('#', $_); $return[1] = $working[1]; } elsif (/^ID_ATA_ROTATION_RATE_RPM/){ - my @working = split /=/, $_; + my @working = split('#', $_); $return[2] = $working[1]; } last if $return[1] && $return[2]; @@ -9740,12 +9872,11 @@ sub scsi_data { } if (/Type:/i){ if (/Type:\s*Direct-Access/i){ - my @working = ({ + push(@scsi, { 'vendor' => $vendor, 'model' => $model, 'firmware' => $firmware, }); - @scsi = (@scsi,@working); } else { ($firmware,$model,$vendor) = ('','',''); @@ -9764,13 +9895,13 @@ sub disk_data_by_id { my (@disk_data); foreach (@by_id){ if ($device eq Cwd::abs_path($_)){ - my @data = split /_/, $_; + my @data = split('_', $_); my @device_data = (); last if scalar @data < 2; # scsi-3600508e000000000876995df43efa500 $serial = pop @data if @data; # usb-PNY_USB_3.0_FD_3715202280-0:0 $serial =~ s/-[0-9]+:[0-9]+$//; - $model = join ' ', @data; + $model = join(' ', @data); # get rid of the ata-|nvme-|mmc- etc $model =~ s/^\/dev\/disk\/by-id\/([^-]+-)?//; $model = main::disk_cleaner($model); @@ -9789,7 +9920,7 @@ sub disk_data_by_id { sub set_vendors { eval $start if $b_log; @vendors = ( - ## These go first because they are the most likely and common ## + ## MOST LIKELY/COMMON MATCHES ## ['(Crucial|^(FC)?CT|-CT|^M4\b|Gizmo!)','Crucial','Crucial',''], # H10 HBRPEKNX0202A NVMe INTEL 512GB ['(\bINTEL\b|^SSD(PAM|SA2))','\bINTEL\b','Intel',''], @@ -9801,12 +9932,12 @@ sub set_vendors { # HM320II HM320II ['(SAMSUNG|^MCG[0-9]+GC|^MCC|^MCBOE|\bEVO\b|^[GS]2 Portable|^DS20|^[DG]3 Station|^DUO\b|^P3|^BGN|^[CD]JN|^BJ[NT]|^[BC]WB|^(HM|SP)[0-9]{2}|^MZMPC|^HD[0-9]{3}[A-Z]{2}$)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM # Android UMS Composite? - ['(SanDisk|^SDS[S]?[DQ]|^D[AB]4|^SL([0-9]+)G|^AFGCE|^ABLCD|^SDW[1-9]|^U3\b|ULTRA\sFIT|Clip Sport|Cruzer|^Extreme)','SanDisk','SanDisk',''], + ['(SanDisk|^SDS[S]?[DQ]|^D[AB]4|^SL([0-9]+)G|^AFGCE|^ABLCD|^SDW[1-9]|^U3\b|ULTRA\sFIT|Clip Sport|Cruzer|^Extreme|iXpand)','SanDisk','SanDisk',''], ['^STEC\b','^STEC\b','STEC',''], # ssd drive, must come before seagate ST test # real, SSEAGATE Backup+; XP1600HE30002 | 024 HN (spinpoint) ['(^ST[^T]|[S]?SEAGATE|^X[AFP]|^5AS|^BUP|Expansion Desk|^Expansion|FreeAgent|GoFlex|Backup(\+|\s?Plus)\s?(Hub)?|OneTouch)','[S]?SEAGATE','Seagate',''], - ['^(WD|WL[0]9]|Western Digital|My (Book|Passport)|\d*LPCX|Elements|easystore|MD0|M000|EARX|EFRX|\d*EAVS|0JD|JPVX|[0-9]+(BEV|(00)?AAK|AAV|AZL|EA[CD]S)|3200[AB]|2500[BJ]|5000[AB]|6400[AB]|7500[AB]|i HTS)','(^WDC|Western\s?Digital)','Western Digital',''], - ## Then better known ones ## + ['^(WD|WL[0]9]|Western Digital|My (Book|Passport)|\d*LPCX|Elements|easystore|MD0|M000|EARX|EFRX|\d*EAVS|0JD|JPVX|[0-9]+(BEV|(00)?AAK|AAV|AZL|EA[CD]S)|3200[AB]|2500[BJ]|5000[AB]|6400[AB]|7500[AB]|i HTS|00[ABL][A-Z]{2})','(^WDC|Western\s?Digital)','Western Digital',''], + ## THEN BETTER KNOWN ONESs ## ['^(A-DATA|ADATA|AX[MN]|CH11|HV[1-9]|IM2)','^(A-DATA|ADATA)','A-Data',''], ['^ASUS','^ASUS','ASUS',''], # ATCS05 can be hitachi travelstar but not sure @@ -9820,7 +9951,7 @@ sub set_vendors { ['^(Hitachi|HCS|HD[PST]|DK[0-9]|IC|HT|HU|HMS)','^Hitachi','Hitachi',''], # vb: VB0250EAVER but clashes with vbox; HP_SSD_S700_120G ;GB0500EAFYL GB starter too generic? # DX110064A5xnNMRI ids as HP and Sandisc, same ID, made by sandisc for hp? not sure - ['^(HP\b|[MV]B[0-6]|G[BJ][01]|DF|0-9]|FK|0-9]|PSS|v[0-9]{3}[bgorw]$|x[0-9]{3}[w]$)','^HP','HP',''], + ['^(HP\b|[MV]B[0-6]|G[BJ][01]|DF|0-9]|FK|0-9]|PSS|XR[0-9]{4}|v[0-9]{3}[bgorw]$|x[0-9]{3}[w]$)','^HP','HP',''], ['^(Lexar|LSD|JumpDrive|JD\s?Firefly|WorkFlow)','^Lexar','Lexar',''], # mmc-LEXAR_0xb016546c; JD Firefly; # OCZSSD2-2VTXE120G is OCZ-VERTEX2_3.5 ['^(OCZ|APOC|D2|DEN|DEN|DRSAK|EC188|FTNC|GFGC|MANG|MMOC|NIMC|NIMR|PSIR|RALLY2|TALOS2|TMSC|TRSAK)','^OCZ[\s-]','OCZ',''], @@ -9831,12 +9962,13 @@ sub set_vendors { # note: get rid of: M[DGK] becasue mushkin starts with MK # note: seen: KXG50ZNV512G NVMe TOSHIBA 512GB | THNSN51T02DUK NVMe TOSHIBA 1024GB ['(^[S]?TOS|^THN|TOSHIBA|TransMemory|^M[GKQ][0-9]|KBG4)','[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_ - ## These go last because they are short and could lead to false ID, or are unlikely ## + ## LAST: THEY ARE SHORT AND COULD LEAD TO FALSE ID, OR ARE UNLIKELY ## # unknown: AL25744_12345678; ADP may be usb 2.5" adapter; udisk unknown: Z1E6FTKJ 00AAKS # SSD2SC240G726A10 MRS020A128GTS25C EHSAJM0016GB ['^5ACE','^5ACE','5ACE',''], # could be seagate: ST316021 5ACE ['^(AbonMax|ASU[0-9])','^AbonMax','AbonMax',''], ['^Acasis','^Acasis','Acasis (hub)',''], + ['^Acclamator','^Acclamator','Acclamator',''], ['^Addlink','^Addlink','Addlink',''], ['^ADTRON','^(ADTRON)','Adtron',''], ['^(Advantech|SQF)','^Advantech','Advantech',''], @@ -9869,6 +10001,7 @@ sub set_vendors { ['^BUSlink','^BUSlink','BUSlink',''], ['^Centerm','^Centerm','Centerm',''], ['^Centon','^Centon','Centon',''], + ['^(Chipsbank|CHIPSBNK)','^Chipsbank','Chipsbank',''], ['^CHN\b','','Zheino',''], ['^Clover','^Clover','Clover',''], ['^Colorful\b','^Colorful','Colorful',''], @@ -9899,12 +10032,14 @@ sub set_vendors { ['^Eluktro','^Eluktronics','Eluktronics',''], ['^Emperor','^Emperor','Emperor',''], ['^Emtec','^Emtec','Emtec',''], + ['^Energy','^Energy','Energy',''], ['^Epson','^Epson','Epson',''], ['^EXCELSTOR','^EXCELSTOR( TECHNO(LOGY)?)?','ExcelStor',''], ['^EZLINK','^EZLINK','EZLINK',''], ['^Fantom','^Fantom( Drive[s]?)?','Fantom Drives',''], ['^Faspeed','^Faspeed','Faspeed',''], ['^FASTDISK','^FASTDISK','FASTDISK',''], + ['^FiiO','^FiiO','FiiO',''], ['^Fordisk','^Fordisk','Fordisk',''], # FK0032CAAZP/FB160C4081 FK or FV can be HP but can be other things ['^FORESEE','^FORESEE','Foresee',''], @@ -9927,7 +10062,7 @@ sub set_vendors { ['^HDC','^HDC\b','HDC',''], ['^Hectron','^Hectron','Hectron',''], ['^HEMA','^HEMA','HEMA',''], - ['^(Hikvision|HKVSN)','^Hikvision','Hikvision',''], + ['^(Hikvision|HKVSN|HS-SSD)','^Hikvision','Hikvision',''], ['^Hoodisk','^Hoodisk','Hoodisk',''], ['^HUAWEI','^HUAWEI','Huawei',''], ['^HyperX','^HyperX','HyperX',''], @@ -9936,6 +10071,7 @@ sub set_vendors { ['^IEI Tech','^IEI Tech(\.|nology)?( Corp(\.|oration)?)?','IEI Technology',''], ['^(Imation|Nano\s?Pro|HQT)','^Imation(\sImation)?','Imation',''], # Imation_ImationFlashDrive; TF20 is imation/tdk ['^(Inca\b|Npenterprise)','^Inca','Inca',''], + ['^(Indilinx|IND-)','^Indilinx','Indilinx',''], ['^INDMEM','^INDMEM','INDMEM',''], ['^Inland','^Inland','Inland',''], ['^(InnoDisk|Innolite)','^InnoDisk( Corp.)?','InnoDisk',''], @@ -9998,7 +10134,7 @@ sub set_vendors { # Monster MONSTER DIGITAL ['^(Monster\s)+Digital','^(Monster\s)+Digital','Monster Digital',''], ['^Morebeck','^Morebeck','Morebeck',''], - ['^Motorola','^Motorola','Motorola',''], + ['^(Motorola|XT[0-9]{4})','^Motorola','Motorola',''], ['^Moweek','^Moweek','Moweek',''], #MRMAD4B128GC9M2C ['^(MRMA|Memoright)','^Memoright','Memoright',''], @@ -10013,6 +10149,7 @@ sub set_vendors { ['^OWC','^OWC\b','OWC',''], ['^oyunkey','^oyunkey','Oyunkey',''], ['^PALIT','PALIT','Palit',''], # ssd + ['^(Pasoul|OASD)','^Pasoul','Pasoul',''], ['^PERC\b','','Dell PowerEdge RAID Card',''], # ssd ['^(PS[8F]|Patriot)','^Patriot([-\s]?Memory)?','Patriot',''], ['PHISON[\s-]?','PHISON[\s-]?','Phison',''],# E12-256G-PHISON-SSD-B3-BB1 @@ -10069,6 +10206,7 @@ sub set_vendors { ['^TEAC','^TEAC','TEAC',''], ['^TEAM','^TEAM(\s*Group)?','TeamGroup',''], ['^(Teclast|CoolFlash)','^Teclast','Teclast',''], + ['^Teelkoou','^Teelkoou','Teelkoou',''], ['^Teleplan','^Teleplan','Teleplan',''], ['^TEUTONS','^TEUTONS','TEUTONS',''], ['^Tigo','^Tigo','Tigo',''], @@ -10113,7 +10251,6 @@ sub set_vendors { ); eval $end if $b_log; } - # receives space separated string that may or may not contain vendor data sub device_vendor { eval $start if $b_log; @@ -10155,39 +10292,95 @@ sub hdd_temp { my ($device) = @_; my ($path) = (''); my (@data,$hdd_temp); - if ($device =~ /nvme/i){ - if (!$b_nvme){ - $b_nvme = 1; - if ($path = main::check_program('nvme')) { - $nvme = $path; + $hdd_temp = hdd_temp_sys($device) if !$b_hddtemp_force && -e "/sys/block/$device"; + if (!$hdd_temp){ + $device = "/dev/$device"; + if ($device =~ /nvme/i){ + if (!$b_nvme){ + $b_nvme = 1; + if ($path = main::check_program('nvme')) { + $nvme = $path; + } } - } - if ($nvme){ - $device =~ s/n[0-9]//; - @data = main::grabber("$sudo$nvme smart-log $device 2>/dev/null"); - foreach (@data){ - my @row = split /\s*:\s*/, $_; - next if !$row[0]; - # other rows may have: Temperature sensor 1 : - if ( $row[0] eq 'temperature') { - $row[1] =~ s/\s*C//; - $hdd_temp = $row[1]; - last; + if ($nvme){ + $device =~ s/n[0-9]//; + @data = main::grabber("$sudo$nvme smart-log $device 2>/dev/null"); + foreach (@data){ + my @row = split(/\s*:\s*/, $_); + next if !$row[0]; + # other rows may have: Temperature sensor 1 : + if ( $row[0] eq 'temperature') { + $row[1] =~ s/\s*C//; + $hdd_temp = $row[1]; + last; + } } } } - } - else { - if (!$b_hddtemp){ - $b_hddtemp = 1; - if ($path = main::check_program('hddtemp')) { - $hddtemp = $path; + else { + if (!$b_hddtemp){ + $b_hddtemp = 1; + if ($path = main::check_program('hddtemp')) { + $hddtemp = $path; + } + } + if ($hddtemp){ + $hdd_temp = (main::grabber("$sudo$hddtemp -nq -u C $device 2>/dev/null"))[0]; } } - if ($hddtemp){ - $hdd_temp = (main::grabber("$sudo$hddtemp -nq -u C $device 2>/dev/null"))[0]; + $hdd_temp =~ s/\s?(Celsius|C)$// if $hdd_temp; + } + eval $end if $b_log; + return $hdd_temp; +} +sub hdd_temp_sys { + eval $start if $b_log; + my ($device) = @_; + my ($hdd_temp,$hdd_temp_alt,%sensors,@working); + my ($holder,$index) = ('',''); + my $path = Cwd::abs_path("/sys/block/$device"); + return if !$path; + # slice out the part of path that gives us hwmon + $path =~ s%/(block|nvme)/.*$%%; + return if ! -e "$path/hwmon/"; + my @data = main::globber("$path/hwmon/hwmon*/temp*"); + #print "device: $device\n"; + foreach (sort @data){ + #print "file: $_\n"; + #print(main::reader($_,'',0),"\n"); + $path = $_; + # cleanup everything in front of temp, the path + $path =~ s/^.*\///; + @working = split('_', $path); + if ($holder ne $working[0]){ + $holder = $working[0]; + } + $sensors{$holder}->{$working[1]} = main::reader($_,'strip',0); + } + return if !%sensors; + if (keys %sensors == 1){ + if ($sensors{$holder}->{'input'} && main::is_numeric($sensors{$holder}->{'input'})){ + $hdd_temp = $sensors{$holder}->{'input'}; } } + else { + # nvme drives can have > 1 temp types, but composite is the one we want if there + foreach (keys %sensors){ + next if !$sensors{$_}->{'input'} || !main::is_numeric($sensors{$_}->{'input'}); + if ($sensors{$_}->{'label'} && $sensors{$_}->{'label'} eq 'Composite'){ + $hdd_temp = $sensors{$_}->{'input'}; + last; + } + else{ + $hdd_temp_alt = $sensors{$_}->{'input'}; + } + } + $hdd_temp = $hdd_temp_alt if !defined $hdd_temp && defined $hdd_temp_alt; + } + $hdd_temp = sprintf("%.1f", $hdd_temp/1000) if $hdd_temp; + main::log_data('data',"device: $device temp: $hdd_temp") if $b_log; + main::log_data('dump','%sensors',\%sensors) if $b_log; + print Data::Dumper::Dumper \%sensors if $test[21]; eval $end if $b_log; return $hdd_temp; } @@ -10202,13 +10395,11 @@ sub block_data { my $path_log_block = "/sys/block/$id/queue/logical_block_size"; my $path_phy_block = "/sys/block/$id/queue/physical_block_size"; # legacy system path - if (! -e $path_phy_block && -r "/sys/block/$id/queue/hw_sector_size" ){ + if (! -e $path_phy_block && -e "/sys/block/$id/queue/hw_sector_size" ){ $path_phy_block = "/sys/block/$id/queue/hw_sector_size"; } - if ( -r $path_log_block || -r $path_phy_block ){ - $block_log = (main::reader($path_log_block))[0] if -r $path_log_block; - $block_size = (main::reader($path_phy_block))[0] if -r $path_phy_block; - } + $block_log = main::reader($path_log_block,'',0) if -r $path_log_block; + $block_size = main::reader($path_phy_block,'',0) if -r $path_phy_block; # print "l-b: $block_log p-b: $block_size raw: $size_raw\n"; @blocks = ($block_log,$block_size); main::log_data('dump','@blocks',\@blocks) if $b_log; @@ -10246,8 +10437,8 @@ sub device_speed { if (defined $id){ if ($b_nvme){ $working = "/sys/class/nvme/$id/device/max_link_speed"; - $speed = (main::reader($working))[0] if -f $working; - if ($speed =~ /([0-9\.]+)\sGT\/s/){ + $speed = main::reader($working,'',0) if -r $working; + if (defined $speed && $speed =~ /([0-9\.]+)\sGT\/s/){ $speed = $1; # pcie1: 2.5 GT/s; pcie2: 5.0 GT/s; pci3: 8 GT/s # NOTE: PCIe 3 stopped using the 8b/10b encoding but a sample pcie3 nvme has @@ -10255,8 +10446,8 @@ sub device_speed { $speed = ($speed <= 5 ) ? $speed * .8 : $speed * 128/130; $speed = sprintf("%.1f",$speed) if $speed; $working = "/sys/class/nvme/$id/device/max_link_width"; - $lanes = (main::reader($working))[0] if -f $working; - $lanes = 1 if !$lanes; + $lanes = main::reader($working,'',0) if -r $working; + $lanes ||= 1; # https://www.edn.com/electronics-news/4380071/What-does-GT-s-mean-anyway- # https://www.anandtech.com/show/2412/2 # http://www.tested.com/tech/457440-theoretical-vs-actual-bandwidth-pci-express-and-thunderbolt/ @@ -10267,7 +10458,7 @@ sub device_speed { } else { $working = "/sys/class/ata_link/link$id/sata_spd"; - $speed = (main::reader($working))[0] if -f $working; + $speed = main::reader($working,'',0) if -r $working; $speed = main::disk_cleaner($speed) if $speed; $speed =~ s/Gbps/Gb\/s/ if $speed; } @@ -10286,7 +10477,7 @@ sub match_glabel { #$gptid =~ s/s[0-9]+$//; my ($dev_id) = (''); foreach (@glabel){ - my @temp = split /\s+/, $_; + my @temp = split(/\s+/, $_); my $gptid_trimmed = $gptid; # slice off s[0-9] from end in case they use slice syntax $gptid_trimmed =~ s/s[0-9]+$//; @@ -10324,133 +10515,125 @@ sub get { if (($b_arm || $b_mips) && !$b_soc_gfx && !$b_pci_tool){ my $type = ($b_arm) ? 'arm' : 'mips'; my $key = 'Message'; - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), },); - @rows = (@rows,@data); } else { @data = card_data(); - @rows = (@rows,@data); + push(@rows,@data); if (!@rows){ my $key = 'Message'; my $type = 'pci-card-data'; - if ($pci_tool && ${$alerts{$pci_tool}}{'action'} eq 'permissions'){ + if ($pci_tool && $alerts{$pci_tool}->{'action'} eq 'permissions'){ $type = 'pci-card-data-root'; } - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults($type,''), },); - @rows = (@rows,@data); } } # note: not perfect, but we need usb gfx to show for all types, soc, pci, etc @data = usb_data(); - @rows = (@rows,@data); + push(@rows,@data); @data = display_data(); - @rows = (@rows,@data); + push(@rows,@data); @data = gl_data(); - @rows = (@rows,@data); + push(@rows,@data); eval $end if $b_log; return @rows; } sub card_data { eval $start if $b_log; - my (@rows,@data); + my (@rows); my ($j,$num) = (0,1); - foreach (@devices_graphics){ + foreach my $row (@devices_graphics){ $num = 1; - my @row = @$_; - #print "$row[0] $row[3]\n"; + #print "$row->[0] $row->[3]\n"; # not using 3D controller yet, needs research: |3D controller |display controller # note: this is strange, but all of these can be either a separate or the same # card. However, by comparing bus id, say: 00:02.0 we can determine that the # cards are either the same or different. We want only the .0 version as a valid # card. .1 would be for example: Display Adapter with bus id x:xx.1, not the right one - next if $row[3] != 0; - #print "$row[0] $row[3]\n"; + next if $row->[3] != 0; + #print "$row->[0] $row->[3]\n"; $j = scalar @rows; - $driver = $row[9]; + $driver = $row->[9]; $driver ||= 'N/A'; - my $card = main::trimmer($row[4]); + my $card = main::trimmer($row->[4]); $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; # have seen absurdly verbose card descriptions, with non related data etc if (length($card) > 85 || $size{'max'} < 110){ $card = main::pci_long_filter($card); } - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $card, },); - @rows = (@rows,@data); - if ($extra > 0 && $b_pci_tool && $row[12]){ - my $item = main::get_pci_vendor($row[4],$row[12]); + if ($extra > 0 && $b_pci_tool && $row->[12]){ + my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]{main::key($num++,0,2,'vendor')} = $item if $item; } $rows[$j]{main::key($num++,1,2,'driver')} = $driver; - if ($row[9] && !$bsd_type){ - my $version = main::get_module_version($row[9]); + if ($row->[9] && !$bsd_type){ + my $version = main::get_module_version($row->[9]); $version ||= 'N/A'; $rows[$j]{main::key($num++,0,3,'v')} = $version; } - if ($b_admin && $row[10]){ - $row[10] = main::get_driver_modules($row[9],$row[10]); - $rows[$j]{main::key($num++,0,3,'alternate')} = $row[10] if $row[10]; + if ($b_admin && $row->[10]){ + $row->[10] = main::get_driver_modules($row->[9],$row->[10]); + $rows[$j]{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10]; } if ($extra > 0){ - $rows[$j]{main::key($num++,0,2,'bus ID')} = (!$row[2] && !$row[3]) ? 'N/A' : "$row[2].$row[3]"; + $rows[$j]{main::key($num++,0,2,'bus ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]"; } if ($extra > 1){ - $rows[$j]{main::key($num++,0,2,'chip ID')} = ($row[5]) ? "$row[5]:$row[6]" : $row[6]; + $rows[$j]{main::key($num++,0,2,'chip ID')} = ($row->[5]) ? "$row->[5]:$row->[6]" : $row->[6]; } - #print "$row[0]\n"; + #print "$row->[0]\n"; } - #my $ref = $pci[-1]; - #print $$ref[0],"\n"; eval $end if $b_log; return @rows; } sub usb_data { eval $start if $b_log; - my (@rows,@data,@ids,$driver,$path_id,$product,@temp2); + my (@rows,@ids,$driver,$path_id,$product,@temp2); my ($j,$num) = (0,1); return if !@usb; - foreach my $ref (@usb){ - my @row = @$ref; + foreach my $row (@usb){ # these tests only work for /sys based usb data for now - if ($row[14] && ($row[14] eq 'Audio-Video' || $row[14] eq 'Video' ) ){ + if ($row->[14] && ($row->[14] eq 'Audio-Video' || $row->[14] eq 'Video' ) ){ $num = 1; $j = scalar @rows; # makre sure to reset, or second device trips last flag ($driver,$path_id,$product) = ('','',''); - $product = main::cleaner($row[13]) if $row[13]; - $driver = $row[15] if $row[15]; - $path_id = $row[2] if $row[2]; + $product = main::cleaner($row->[13]) if $row->[13]; + $driver = $row->[15] if $row->[15]; + $path_id = $row->[2] if $row->[2]; $product ||= 'N/A'; # note: for real usb video out, no generic drivers? webcams may have one though if (!$driver){ - if ($row[14] eq 'Audio-Video'){ + if ($row->[14] eq 'Audio-Video'){ $driver = 'N/A'; } else { $driver = 'N/A'; } } - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $product, main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $driver, },); - @rows = (@rows,@data); if ($extra > 0){ - $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row[1]"; + $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row->[1]"; } if ($extra > 1){ - $row[7] ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'chip ID')} = $row[7]; + $row->[7] ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'chip ID')} = $row->[7]; } - if ($extra > 2 && $row[16]){ - $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row[16]); + if ($extra > 2 && $row->[16]){ + $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row->[16]); } } } @@ -10579,18 +10762,17 @@ sub display_data(){ my ($diag,$dpi,$hz,$size); my ($m_count,$basic_count,$row_key,$screen_count) = (0,0,0,0); my $s_count = ($graphics{'screens'}) ? scalar @{$graphics{'screens'}}: 0; - foreach (@{$graphics{'screens'}}){ - my %main = %$_; - $m_count = scalar @{$main{'monitors'}} if $main{'monitors'}; + foreach my $main (@{$graphics{'screens'}}){ + $m_count = scalar @{$main->{'monitors'}} if $main->{'monitors'}; $screen_count++; ($diag,$dpi,$hz,$resolution,$size) = (undef); $row_key++ if !$show{'graphic-basic'}; if ( !$show{'graphic-basic'} || $m_count == 0 ){ - if ( !$show{'graphic-basic'} && defined $main{'screen'} ){ - $row[$row_key]{main::key($num++,1,2,'Screen')} = $main{'screen'}; + if ( !$show{'graphic-basic'} && defined $main->{'screen'} ){ + $row[$row_key]{main::key($num++,1,2,'Screen')} = $main->{'screen'}; } - $resolution = $main{'res-x'} . 'x' . $main{'res-y'} if $main{'res-x'} && $main{'res-y'}; - $resolution .= '~' . $main{'hz'} . 'Hz' if $show{'graphic-basic'} && $main{'hz'} && $resolution; + $resolution = $main->{'res-x'} . 'x' . $main->{'res-y'} if $main->{'res-x'} && $main->{'res-y'}; + $resolution .= '~' . $main->{'hz'} . 'Hz' if $show{'graphic-basic'} && $main->{'hz'} && $resolution; $resolution ||= 'N/A'; if ($s_count == 1 || !$show{'graphic-basic'}){ $row[$row_key]{main::key($num++,0,3,'s-res')} = $resolution; @@ -10600,36 +10782,35 @@ sub display_data(){ $row[$row_key]{main::key($num++,0,3,$screen_count)} = $resolution; } $resolution = ''; - if ($main{'s-dpi'} && (!$show{'graphic-basic'} || $extra > 1)){ - $row[$row_key]{main::key($num++,0,3,'s-dpi')} = $main{'s-dpi'}; + if ($main->{'s-dpi'} && (!$show{'graphic-basic'} || $extra > 1)){ + $row[$row_key]{main::key($num++,0,3,'s-dpi')} = $main->{'s-dpi'}; } if ( !$show{'graphic-basic'} ){ - if ($main{'size-x'} && $main{'size-y'}){ - $size = $main{'size-x'} . 'x' . $main{'size-y'} . - 'mm ('. $main{'size-x-i'} . 'x' . $main{'size-y-i'} . '")'; + if ($main->{'size-x'} && $main->{'size-y'}){ + $size = $main->{'size-x'} . 'x' . $main->{'size-y'} . + 'mm ('. $main->{'size-x-i'} . 'x' . $main->{'size-y-i'} . '")'; } $size ||= ''; $row[$row_key]{main::key($num++,0,3,'s-size')} = $size if $size; - if ($main{'diagonal'}){ - $diag = $main{'diagonal-m'} . 'mm ('. $main{'diagonal'} . '")'; + if ($main->{'diagonal'}){ + $diag = $main->{'diagonal-m'} . 'mm ('. $main->{'diagonal'} . '")'; } $diag ||= ''; $row[$row_key]{main::key($num++,0,3,'s-diag')} = $diag if $diag; } } - if ($main{'monitors'}){ + if ($main->{'monitors'}){ #print $basic_count . '::' . $m_count, "\n"; - foreach my $ref2 (@{$main{'monitors'}}){ - my %monitor = %$ref2; + foreach my $monitor (@{$main->{'monitors'}}){ ($diag,$dpi,$hz,$resolution,$size) = (undef); if ($show{'graphic-basic'}){ $basic_count++; - if ($monitor{'res-x'} && $monitor{'res-y'}){ - $resolution = $monitor{'res-x'} . 'x' . $monitor{'res-y'}; + if ($monitor->{'res-x'} && $monitor->{'res-y'}){ + $resolution = $monitor->{'res-x'} . 'x' . $monitor->{'res-y'}; } # using main, noit monitor, dpi because we want xorg dpi, not physical screen dpi - $dpi = $main{'s-dpi'} if $resolution && $extra > 1 && $main{'s-dpi'}; - $resolution .= '~' . $monitor{'hz'} . 'Hz' if $monitor{'hz'} && $resolution; + $dpi = $main->{'s-dpi'} if $resolution && $extra > 1 && $main->{'s-dpi'}; + $resolution .= '~' . $monitor->{'hz'} . 'Hz' if $monitor->{'hz'} && $resolution; $resolution ||= 'N/A'; if ($basic_count == 1 && $m_count == 1){ $row[$row_key]{main::key($num++,0,2,'resolution')} = $resolution; @@ -10644,25 +10825,25 @@ sub display_data(){ next; } $row_key++; - $row[$row_key]{main::key($num++,0,3,'Monitor')} = $monitor{'monitor'}; - if ($monitor{'res-x'} && $monitor{'res-y'}){ - $resolution = $monitor{'res-x'} . 'x' . $monitor{'res-y'}; + $row[$row_key]{main::key($num++,0,3,'Monitor')} = $monitor->{'monitor'}; + if ($monitor->{'res-x'} && $monitor->{'res-y'}){ + $resolution = $monitor->{'res-x'} . 'x' . $monitor->{'res-y'}; } $resolution ||= 'N/A'; $row[$row_key]{main::key($num++,0,4,'res')} = $resolution; - $hz = ($monitor{'hz'}) ? $monitor{'hz'} : ''; + $hz = ($monitor->{'hz'}) ? $monitor->{'hz'} : ''; $row[$row_key]{main::key($num++,0,4,'hz')} = $hz if $hz; - $dpi = ($monitor{'dpi'}) ? $monitor{'dpi'} : ''; + $dpi = ($monitor->{'dpi'}) ? $monitor->{'dpi'} : ''; $row[$row_key]{main::key($num++,0,4,'dpi')} = $dpi if $dpi; - #print "$dpi :: $main{'s-dpi'}\n"; - if ($monitor{'size-x'} && $monitor{'size-y'}){ - $size = $monitor{'size-x'} . 'x' . $monitor{'size-y'} . - 'mm ('. $monitor{'size-x-i'} . 'x' . $monitor{'size-y-i'} . '")'; + #print "$dpi :: $main->{'s-dpi'}\n"; + if ($monitor->{'size-x'} && $monitor->{'size-y'}){ + $size = $monitor->{'size-x'} . 'x' . $monitor->{'size-y'} . + 'mm ('. $monitor->{'size-x-i'} . 'x' . $monitor->{'size-y-i'} . '")'; } $size ||= ''; $row[$row_key]{main::key($num++,0,4,'size')} = $size if $size; - if ($monitor{'diagonal'}){ - $diag = $monitor{'diagonal-m'} . 'mm ('. $monitor{'diagonal'} . '")'; + if ($monitor->{'diagonal'}){ + $diag = $monitor->{'diagonal-m'} . 'mm ('. $monitor->{'diagonal'} . '")'; } $diag ||= ''; $row[$row_key]{main::key($num++,0,4,'diag')} = $diag if $diag; @@ -10692,9 +10873,9 @@ sub x_display_data { my ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i); my @xdpyinfo = main::grabber("$program $display_opt 2>/dev/null","\n",'strip'); #@xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo; - #print join "\n",@xdpyinfo, "\n"; + #print join("\n",@xdpyinfo), "\n"; foreach (@xdpyinfo){ - @working = split /:\s+/, $_; + @working = split(/:\s+/, $_); next if ( ($graphics{'screens'} && $working[0] !~ /^(dimensions$|screen\s#)/ ) || !$working[0] ); #print "$_\n"; if ($working[0] eq 'vendor string'){ @@ -10763,7 +10944,7 @@ sub x_display_data { 'diagonal' => $diagonal, 'diagonal-m' => $diagonal_m, }; - push @{$graphics{'screens'}}, $screen; + push(@{$graphics{'screens'}}, $screen); } } #print Data::Dumper::Dumper $graphics{'screens'}; @@ -10771,7 +10952,7 @@ sub x_display_data { ($diagonal,$diagonal_m,$dpi) = (undef); ($screen_id,$screen,@working) = (undef); ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i) = (undef); - my ($monitor,@monitors,$monitor_id,$screen,$screen_id,@xrandr_screens); + my (@monitors,$monitor_id,$screen,$screen_id,@xrandr_screens); my @xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip'); #$graphics{'dimensions'} = (\@dimensions); # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle @@ -10779,7 +10960,7 @@ sub x_display_data { foreach (@xrandr){ if (/^Screen ([0-9]+):/){ $screen_id = $1; - push @xrandr_screens, \@monitors if @monitors; + push(@xrandr_screens, \@monitors) if @monitors; @monitors = (); } if (/^([^\s]+)\s+connected\s(primary\s)?([0-9]+)\s*x\s*([0-9]+)\+[0-9+]+(\s\([^)]+\))?(\s([0-9]+)mm\sx\s([0-9]+)mm)?/){ @@ -10796,7 +10977,7 @@ sub x_display_data { $diagonal = ($res_x && $size_x) ? sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4 )) : ''; $diagonal += 0 if $diagonal; # trick to get rid of decimal 0 $diagonal_m = ($res_x && $size_x) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : ''; - $monitor = { + push(@monitors, { 'screen' => $screen_id, 'monitor' => $monitor_id, 'res-x' => $res_x, @@ -10810,14 +10991,12 @@ sub x_display_data { 'dpi' => $dpi, 'diagonal' => $diagonal, 'diagonal-m' => $diagonal_m, - }; - push @monitors, $monitor; + }); # print "x:$size_x y:$size_y rx:$res_x ry:$res_y dpi:$dpi\n"; ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i) = (0,0,0,0,0,0,0,0); } - my @working = split /\s+/,$_; - # print join "$_\n"; + my @working = split(/\s+/,$_); if ($working[1] =~ /\*/){ $working[1] =~ s/\*|\+//g; $working[1] = sprintf("%.0f",$working[1]); @@ -10826,18 +11005,16 @@ sub x_display_data { # print Data::Dumper::Dumper \@monitors; } } - push @xrandr_screens, \@monitors if @monitors; + push(@xrandr_screens, \@monitors) if @monitors; #print "xrand: " . Data::Dumper::Dumper \@xrandr_screens; my ($i) = (0); - foreach (@{$graphics{'screens'}}){ - my %main = %$_; - # print "h: " . Data::Dumper::Dumper \%main; - #print $main{'screen'}, "\n"; - foreach my $ref2 (@xrandr_screens){ - my @screens = @$ref2; - # print "d: " . Data::Dumper::Dumper \@screens; - if ($screens[0]{'screen'} eq $main{'screen'}){ - ${$graphics{'screens'}}[$i]{'monitors'} = \@screens; + foreach my $main (@{$graphics{'screens'}}){ + # print "h: " . Data::Dumper::Dumper $main; + #print $main->{'screen'}, "\n"; + foreach my $screens (@xrandr_screens){ + # print "d: " . Data::Dumper::Dumper $screens; + if ($screens->[0]{'screen'} eq $main->{'screen'}){ + ${$graphics{'screens'}}[$i]{'monitors'} = $screens; last; } } @@ -10897,7 +11074,7 @@ sub get_protocol { my @data = main::grabber("$program --no-pager --no-legend 2>/dev/null",'','strip'); foreach (@data){ next if /tty[v]?[0-6]$/; # freebsd: ttyv3 - $id = (split /\s+/, $_)[0]; + $id = (split(/\s+/, $_))[0]; last; # multiuser? too bad, we'll go for the first one } if ($id ){ @@ -10935,14 +11112,14 @@ sub gl_data(){ }); return @row; } - #print join "\n",@glxinfo,"\n"; + #print join("\n", @glxinfo),"\n"; my $compat_version = ''; my ($b_compat,$b_nogl,@core_profile_version,@direct_render,@renderer, @opengl_version,@working); foreach (@glxinfo){ next if /^\s/; if (/^opengl renderer/i){ - @working = split /:\s*/, $_; + @working = split(/:\s*/, $_, 2); if ($working[1]){ $working[1] = main::cleaner($working[1]); # Allow all mesas @@ -10956,31 +11133,31 @@ sub gl_data(){ $b_nogl = 1; $working[1] = main::row_defaults('gl-empty'); } - push @renderer, $working[1]; + push(@renderer, $working[1]); } # dropping all conditions from this test to just show full mesa information # there is a user case where not f and mesa apply, atom mobo # /opengl version/ && ( f || $2 !~ /mesa/ ) { elsif (/^opengl version/i){ - @working = split /:\s*/, $_; + @working = split(/:\s*/, $_, 2); if ($working[1]){ # fglrx started appearing with this extra string, does not appear # to communicate anything of value $working[1] =~ s/(Compatibility Profile Context|\(Compatibility Profile\))//; $working[1] =~ s/\s\s/ /g; $working[1] =~ s/^\s+|\s+$//; - push @opengl_version, $working[1]; + push(@opengl_version, $working[1]); # note: this is going to be off if ever multi opengl versions appear, # never seen one - @working = split /\s+/, $working[1]; + @working = split(/\s+/, $working[1]); $compat_version = $working[0]; } elsif (!$b_nogl) { - push @opengl_version, main::row_defaults('gl-empty'); + push(@opengl_version, main::row_defaults('gl-empty')); } } elsif (/^opengl core profile version/i){ - @working = split /:\s*/, $_; + @working = split(/:\s*/, $_, 2); # note: no need to apply empty message here since we don't have the data # anyway if ($working[1]){ @@ -10989,12 +11166,12 @@ sub gl_data(){ $working[1] =~ s/(Compatibility Profile Context|\((Compatibility|Core) Profile\))//; $working[1] =~ s/\s\s/ /g; $working[1] =~ s/^\s+|\s+$//; - push @core_profile_version, $working[1]; + push(@core_profile_version, $working[1]); } } elsif (/direct rendering/){ - @working = split /:\s*/, $_; - push @direct_render, $working[1]; + @working = split(/:\s*/, $_, 2); + push(@direct_render, $working[1]); } # if -B was always available, we could skip this, but it is not elsif (/GLX Visuals/){ @@ -11002,17 +11179,17 @@ sub gl_data(){ } } my ($direct_render,$renderer,$version) = ('N/A','N/A','N/A'); - $direct_render = join ', ', @direct_render if @direct_render; + $direct_render = join(', ', @direct_render) if @direct_render; # non free drivers once filtered and cleaned show the same for core and compat # but this stopped for some reason at 4.5/4.6 nvidia if (@core_profile_version && @opengl_version && - join ('', @core_profile_version) ne join( '', @opengl_version) && + join('', @core_profile_version) ne join( '', @opengl_version) && !(grep {/nvidia/i} @opengl_version ) ){ @opengl_version = @core_profile_version; $b_compat = 1; } - $version = join ', ', @opengl_version if @opengl_version; - $renderer = join ', ', @renderer if @renderer; + $version = join(', ', @opengl_version) if @opengl_version; + $renderer = join(', ', @renderer) if @renderer; @row = ({ main::key($num++,1,1,'OpenGL') => '', main::key($num++,1,2,'renderer') => ($renderer) ? $renderer : 'N/A', @@ -11063,7 +11240,7 @@ sub tty_data(){ my $tty_arg = ($bsd_type) ? '-f' : '-F'; $tty = (main::grabber("$program $tty_arg /dev/pts/$tty_working size 2>/dev/null"))[0]; if ($tty){ - my @temp = split /\s+/, $tty; + my @temp = split(/\s+/, $tty); $tty = "$temp[1]x$temp[0]"; } } @@ -11083,7 +11260,7 @@ sub x_drivers { # $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/xorg-multi-driver-1.log"; my @xorg = main::reader($log); # list is from sgfxi plus non-free drivers, plus ARM drivers - my $list = join '|',qw(amdgpu apm ark armsoc atimisc ati + my $list = join('|', qw(amdgpu apm ark armsoc atimisc ati chips cirrus cyrix fbdev fbturbo fglrx geode glide glint i128 i740 i810-dec100 i810e i810 i815 i830 i845 i855 i865 i915 i945 i965 iftv imstt intel ivtv mach64 mesa mga modesetting @@ -11091,7 +11268,7 @@ sub x_drivers { rendition s3virge s3 savage siliconmotion sisimedia sisusb sis sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx tdfx tga trident tseng unichrome v4l vboxvideo vesa vga via vmware vmwgfx - voodoo); + voodoo)); # it's much cheaper to grab the simple pattern match then do the expensive one # in the main loop. #@xorg = grep {/Failed|Unload|Loading/} @xorg; @@ -11189,15 +11366,15 @@ sub x_version { if (@data){ foreach (@data){ if (/^X.org X server/i){ - $version = (split /\s+/, $_)[3]; + $version = (split(/\s+/, $_))[3]; last; } elsif (/^X Window System Version/i) { - $version = (split /\s+/, $_)[4]; + $version = (split(/\s+/, $_))[4]; last; } elsif (/^Xvesa from/i) { - $version = (split /\s+/, $_)[3]; + $version = (split(/\s+/, $_))[3]; $version = "Xvesa $version" if $version; last; } @@ -11277,6 +11454,365 @@ sub display_compositor { } } +## LogicalData +{ +package LogicalData; + +sub get { + eval $start if $b_log; + my (@general_data,@rows,$key1,$val1); + my $num = 0; + if ($bsd_type){ + $key1 = 'Message'; + $val1 = main::row_defaults('lvm-data-bsd'); + @rows = ({main::key($num++,0,1,$key1) => $val1,}); + } + else { + main::set_lsblk() if !$b_lsblk; + if ($b_fake_logical || $alerts{'lvs'}->{'action'} eq 'use'){ + lvm_data() if !$b_lvm_data; + if (!@lvm){ + my $key = 'Message'; + push(@rows, { + main::key($num++,0,1,$key) => main::row_defaults('lvm-data',''), + },); + } + else { + my %processed = process_lvm_data(); + @rows = create_output_lvm(\%processed); + } + } + elsif ($b_active_lvm && $alerts{'lvs'}->{'action'} eq 'permissions'){ + my $key = 'Message'; + push(@rows, { + main::key($num++,0,1,$key) => $alerts{'lvs'}->{'permissions'}, + },); + } + elsif (@lsblk && !$b_active_lvm && $alerts{'lvs'}->{'action'} eq 'permissions'){ + my $key = 'Message'; + push(@rows, { + main::key($num++,0,1,$key) => main::row_defaults('lvm-data',''), + },); + } + elsif ($alerts{'lvs'}->{'action'} ne 'use'){ + $key1 = $alerts{'lvs'}->{'action'}; + $val1 = $alerts{'lvs'}->{$key1}; + $key1 = ucfirst($key1); + @rows = ({main::key($num++,0,1,$key1) => $val1,}); + } + if ($b_active_general){ + push(@general_data,general_data()); + } + if (@general_data){ + push(@rows,create_output_general(\@general_data)); + } + } + eval $end if $b_log; + return @rows; +} +sub create_output_general { + eval $start if $b_log; + my ($general_data) = @_; + my ($size,@rows); + my ($j,$num) = (0,0); + # cryptsetup status luks-a00baac5-44ff-4b48-b303-3bedb1f623ce + foreach my $item (sort {$a->{'type'} cmp $b->{'type'}} @$general_data){ + $j = scalar @rows; + $size = ($item->{'size'}) ? main::get_size($item->{'size'}, 'string') : 'N/A'; + push(@rows,{ + main::key($num++,1,1,'Device') => $item->{'name'}, + }); + if ($b_admin){ + $item->{'name'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'maj-min')} = $item->{'maj-min'}; + } + $rows[$j]{main::key($num++,0,2,'type')} = $item->{'type'}; + if ($extra > 0 && $item->{'dm'}){ + $rows[$j]{main::key($num++,0,2,'dm')} = $item->{'dm'}; + } + $rows[$j]{main::key($num++,0,2,'size')} = $size; + my $b_fake; + create_components_output('general',\$j,\$num,\@rows,\@{$item->{'components'}},\$b_fake); + } + eval $end if $b_log; + return @rows; +} +sub create_output_lvm { + eval $start if $b_log; + my ($lvm_data) = @_; + my (@rows); + my ($size); + my ($j,$num) = (0,0); + foreach my $vg (sort keys %$lvm_data){ + $j = scalar @rows; + # print Data::Dumper::Dumper $lvm_data->{$vg}; + $size = main::get_size($lvm_data->{$vg}{'vg-size'},'string','N/A'); + push(@rows,{ + main::key($num++,1,1,'Device') => '', + main::key($num++,0,2,'VG') => $vg, + main::key($num++,0,2,'type') => uc($lvm_data->{$vg}{'vg-format'}), + main::key($num++,0,2,'size') => $size, + },); + $size = main::get_size($lvm_data->{$vg}{'vg-free'},'string','N/A'); + $rows[$j]{main::key($num++,0,2,'free')} = $size; + foreach my $lv (sort keys %{$lvm_data->{$vg}{'lvs'}}){ + next if $extra < 2 && $lv =~ /^\[/; # it's an internal vg lv, raid meta/image + $j = scalar @rows; + my $b_raid; + $size = main::get_size($lvm_data->{$vg}{'lvs'}{$lv}{'lv-size'},'string','N/A'); + $rows[$j]{main::key($num++,1,2,'LV')} = $lv; + if ($b_admin && $lvm_data->{$vg}{'lvs'}{$lv}{'maj-min'}){ + $rows[$j]{main::key($num++,0,3,'maj-min')} = $lvm_data->{$vg}{'lvs'}{$lv}{'maj-min'}; + } + $rows[$j]{main::key($num++,0,3,'type')} = $lvm_data->{$vg}{'lvs'}{$lv}{'lv-type'}; + if ($extra > 0 && $lvm_data->{$vg}{'lvs'}{$lv}{'dm'}){ + $rows[$j]{main::key($num++,0,3,'dm')} = $lvm_data->{$vg}{'lvs'}{$lv}{'dm'}; + } + $rows[$j]{main::key($num++,0,3,'size')} = $size; + if ($extra > 1 && !($show{'raid'} || $show{'raid-basic'}) && $lvm_data->{$vg}{'lvs'}{$lv}{'raid'}){ + $j = scalar @rows; + $rows[$j]{main::key($num++,1,3,'RAID')} = ''; + $rows[$j]{main::key($num++,0,4,'stripes')} = $lvm_data->{$vg}{'lvs'}{$lv}{'raid'}{'stripes'}; + $rows[$j]{main::key($num++,0,4,'sync')} = $lvm_data->{$vg}{'lvs'}{$lv}{'raid'}{'sync'}; + my $copied = $lvm_data->{$vg}{'lvs'}{$lv}{'raid'}{'copied'}; + $copied = (defined $copied) ? ($copied + 0) . '%': 'N/A'; + $rows[$j]{main::key($num++,0,4,'copied')} = $copied; + $rows[$j]{main::key($num++,0,4,'mismatches')} = $lvm_data->{$vg}{'lvs'}{$lv}{'raid'}{'mismatches'}; + $b_raid = 1; + } + create_components_output('lvm',\$j,\$num,\@rows,\@{$lvm_data->{$vg}{'lvs'}{$lv}{'components'}},\$b_raid); + } + } + eval $end if $b_log; + return @rows; +} + +sub create_components_output { + my ($type,$j,$num,$rows,$components,$b_raid) = @_; + my ($l1); + $$j = scalar @$rows if $$b_raid || $extra > 1; + $$b_raid = 0; + if ($type eq 'general'){ + ($l1) = (2); + } + elsif ($type eq 'lvm'){ + ($l1) = (3); + } + my $status = (!@$components) ? 'N/A':'' ; + $$rows[$$j]{main::key($$num++,1,$l1,'Components')} = $status; + create_recursive_components($type,$j,$num,$rows,$components,0,'c','p'); +} +sub create_recursive_components { + my ($type,$j,$num,$rows,$components,$indent,$c,$p) = @_; + my ($l,$m,$size) = (1,1,0); + my ($l2,$l3); + if ($type eq 'general'){ + ($l2,$l3) = (3+$indent,4+$indent) ; + } + elsif ($type eq 'lvm'){ + ($l2,$l3) = (4+$indent,5+$indent); + } + #print 'outside: ', scalar @$component, "\n", Data::Dumper::Dumper $component; + foreach my $component (@$components){ + #print "inside: -n", Data::Dumper::Dumper $component->[$i]; + $$j = scalar @$rows if $b_admin; + my $id; + if ($component->[0][0] =~ /^(bcache|dm-|md)[0-9]/){ + $id = $c .'-' . $m; + $m++; + } + else { + $id = $p . '-' . $l; + $l++; + } + $$rows[$$j]{main::key($$num++,1,$l2,$id)} = $component->[0][0]; + if ($extra > 1){ + if ($b_admin){ + $$rows[$$j]{main::key($$num++,0,$l3,'maj-min')} = $component->[0][1]; + $$rows[$$j]{main::key($$num++,0,$l3,'mapped')} = $component->[0][3] if $component->[0][3]; + $size = main::get_size($component->[0][2],'string','N/A'); + $$rows[$$j]{main::key($$num++,0,$l3,'size')} = $size; + } + #next if !$component->[$i][4]; + for (my $i = 1; $i < scalar @$component; $i++){ + create_recursive_components($type,$j,$num,$rows,$component->[$i],$indent+1,$c.'c',$p.'p'); + } + } + } +} + +# note: type dm is seen in only one dataset, but it's a start +sub general_data { + eval $start if $b_log; + my (@found,@general_data,%parent,$parent_fs); + main::set_mapper() if !$b_mapper; + foreach my $row (@lsblk){ + # bcache doesn't have mapped name: !$mapper{$row->{'name'}} || + next if !$row->{'parent'}; + %parent = main::get_lsblk($row->{'parent'}); + next if !$parent{'fs'}; + if ($row->{'type'} && (($row->{'type'} eq 'crypt' || + $row->{'type'} eq 'mpath' || $row->{'type'} eq 'multipath') || + ($row->{'type'} eq 'dm' && $row->{'name'} =~ /veracrypt/i) || + ($parent{'fs'} eq 'bcache') ) ){ + my (@full_components,$mapped,$type); + $mapped = $mapper{$row->{'name'}} if %mapper; + next if grep(/^$row->{'name'}$/, @found); + push(@found,$row->{'name'}); + if ($parent{'fs'} eq 'crypto_LUKS'){ + $type = 'LUKS'; + } + # note, testing name is random user string, and there is no other + # ID known, the parent FS is '', empty. + elsif ($row->{'type'} eq 'dm' && $row->{'name'} =~ /veracrypt/i){ + $type = 'VeraCrypt'; + } + elsif ($row->{'type'} eq 'crypt'){ + $type = 'Crypto'; + } + elsif ($parent{'fs'} eq 'bcache'){ + $type = 'bcache'; + } + # probably only seen on older Redhat servers, LVM probably replaces + elsif ($row->{'type'} eq 'mpath' || $row->{'type'} eq 'multipath'){ + $type = 'MultiPath'; + } + elsif ($row->{'type'} eq 'crypt'){ + $type = 'Crypt'; + } + #my $name = ($use{'filter-uuid'}) ? "luks-$filter_string" : $row->{'name'}; + component_data($row->{'maj-min'},\@full_components); + # print "$row->{'name'}\n", Data::Dumper::Dumper \@full_components; + push(@general_data, { + 'components' => \@full_components, + 'dm' => $mapped, + 'maj-min' => $row->{'maj-min'}, + 'name' => $row->{'name'}, + 'size' => $row->{'size'}, + 'type' => $type, + }); + } + } + main::log_data('dump','luks @general_data', \@general_data); + print Data::Dumper::Dumper \@general_data if $test[22]; + eval $end if $b_log; + return @general_data; +} + +# note: called for disk totals, raid, and logical +sub lvm_data { + eval $start if $b_log; + $b_lvm_data = 1; + main::set_proc_partitions() if !$b_proc_partitions; + main::set_mapper() if !$b_mapper; + my (@args,@data,%totals); + @args = qw(vg_name vg_fmt vg_size vg_free lv_name lv_layout lv_size + lv_kernel_major lv_kernel_minor segtype seg_count seg_start_pe seg_size_pe + stripes devices raid_mismatch_count raid_sync_action raid_write_behind + copy_percent); + my $num = 0; + if ($b_fake_logical){ + my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lvm/lvs-test-1.txt"; + @data = main::reader($file,'strip'); + } + else { + # lv_full_name: ar0-home; lv_dm_path: /dev/mapper/ar0-home + # seg_size: unit location on volume where segement starts + # 2>/dev/null -unit k ---separator ^: + my $cmd = $alerts{'lvs'}->{'path'}; + $cmd .= ' -aPv --unit k --separator "^:" --segments --noheadings -o '; + # $cmd .= ' -o +lv_size,pv_major,pv_minor 2>/dev/null'; + $cmd .= join(',', @args); + $cmd .= ' 2>/dev/null'; + @data = main::grabber("$cmd",'','strip'); + main::log_data('dump','lvm @data', \@data) if $b_log; + print "command: $cmd\n" if $test[22]; + } + my $j = 0; + foreach (@data){ + my @line = split(/\^:/, $_); + for (my $i = 0; $i < scalar @args; $i++){ + $line[$i] =~ s/k$// if $args[$i] =~ /_(free|size|used)$/; + $lvm[$j]->{$args[$i]} = $line[$i]; + } + if (!$totals{'vgs'}->{$lvm[$j]->{'vg_name'}}){ + $totals{'vgs'}->{$lvm[$j]->{'vg_name'}} = $lvm[$j]->{'vg_size'}; + $raw_logical[2] += $lvm[$j]->{'vg_free'} if $lvm[$j]->{'vg_free'}; + } + $j++; + } + # print Data::Dumper::Dumper \%totals, \@raw_logical; + main::log_data('dump','lvm @lvm', \@lvm) if $b_log; + print Data::Dumper::Dumper \@lvm if $test[22]; + eval $end if $b_log; +} +sub process_lvm_data { + eval $start if $b_log; + my (%processed); + foreach my $item (@lvm){ + my (@components,@devices,$dm,$dm_tmp,$dm_mm,@full_components,$maj_min,%raid,@temp); + if (!$processed{$item->{'vg_name'}}){ + $processed{$item->{'vg_name'}}->{'vg-size'} = $item->{'vg_size'}; + $processed{$item->{'vg_name'}}->{'vg-free'} = $item->{'vg_free'}; + $processed{$item->{'vg_name'}}->{'vg-format'} = $item->{'vg_fmt'}; + } + if (!$processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}){ + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'lv-size'} = $item->{'lv_size'}; + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'lv-type'} = $item->{'segtype'}; + $maj_min = $item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}; + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'maj-min'} = $maj_min; + $dm_tmp = $item->{'vg_name'} . '-' . $item->{'lv_name'}; + $dm_tmp =~ s/\[|\]$//g; + $dm = $mapper{$dm_tmp} if %mapper; + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'dm'} = $dm; + if ($item->{'segtype'} && $item->{'segtype'} ne 'linear' && $item->{'segtype'} =~ /^raid/){ + $raid{'copied'} = $item->{'copy_percent'}; + $raid{'mismatches'} = $item->{'raid_mismatch_count'}; + $raid{'stripes'} = $item->{'stripes'}; + $raid{'sync'} = $item->{'raid_sync_action'}; + $raid{'type'} = $item->{'segtype'}; + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'raid'} = \%raid; + } + component_data($maj_min,\@full_components); + # print "$item->{'lv_name'}\n", Data::Dumper::Dumper \@full_components; + $processed{$item->{'vg_name'}}->{'lvs'}{$item->{'lv_name'}}{'components'} = \@full_components; + } + } + main::log_data('dump','lvm %processed', \%processed) if $b_log; + print Data::Dumper::Dumper \%processed if $test[23]; + eval $end if $b_log; + return %processed; +} +sub component_data { + my ($maj_min,$full_components) = @_; + push(@$full_components, recursive_component_data($maj_min)); +} + +sub recursive_component_data { + eval $start if $b_log; + my ($maj_min) = @_; + my (@components,@devices); + @devices = main::globber("/sys/dev/block/$maj_min/slaves/*") if -e "/sys/dev/block/$maj_min/slaves"; + @devices = map {$_ =~ s|^/.*/||; $_;} @devices if @devices; + # return @devices if !$b_admin; + foreach my $device (@devices){ + my ($mapped,$mm2,@part); + @part = main::get_proc_partition($device) if @proc_partitions; + $mm2 = $part[0] . ':' . $part[1] if @part; + if ($device =~ /^(bcache|dm-|md)[0-9]+$/){ + $mapped = $dmmapper{$device}; + $raw_logical[1] += $part[2] if $mapped && $mapped =~ /_(cdata|cmeta)$/; + push(@components, [[$device,$mm2,$part[2],$mapped],[recursive_component_data($mm2)]]); + } + else { + push(@components,[[$device,$mm2,$part[2]]]); + } + } + eval $end if $b_log; + return @components; +} +} + ## MachineData { package MachineData; @@ -11293,10 +11829,9 @@ sub get { } } elsif ($bsd_type || $b_dmidecode_force){ - my $ref = $alerts{'dmidecode'}; - if ( !$b_fake_dmidecode && $$ref{'action'} ne 'use'){ - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; + if ( !$b_fake_dmidecode && $alerts{'dmidecode'}->{'action'} ne 'use'){ + $key1 = $alerts{'dmidecode'}->{'action'}; + $val1 = $alerts{'dmidecode'}->{$key1}; $key1 = ucfirst($key1); } else { @@ -11341,22 +11876,21 @@ sub get { ## unused: 16-bios_rev 17-bios_romsize 18 - firmware type sub create_output { eval $start if $b_log; - my ($ref) = @_; - my (%data,@row,@rows); - %data = %$ref; + my ($data) = @_; + my (@rows); my $firmware = 'BIOS'; my $num = 0; my $j = 0; my ($b_chassis,$b_skip_chassis,$b_skip_system); my ($bios_date,$bios_rev,$bios_romsize,$bios_vendor,$bios_version,$chassis_serial, - $chassis_type,$chassis_vendor,$chassis_version, $mobo_model,$mobo_serial,$mobo_vendor, + $chassis_type,$chassis_vendor,$chassis_version,$mobo_model,$mobo_serial,$mobo_vendor, $mobo_version,$product_name,$product_serial,$product_version,$system_vendor); # foreach my $key (keys %data){ -# print "$key: $data{$key}\n"; +# print "$key: $data->{$key}\n"; # } - if (!$data{'sys_vendor'} || ($data{'board_vendor'} && - $data{'sys_vendor'} eq $data{'board_vendor'} && !$data{'product_name'} && - !$data{'product_version'} && !$data{'product_serial'})){ + if (!$data->{'sys_vendor'} || ($data->{'board_vendor'} && + $data->{'sys_vendor'} eq $data->{'board_vendor'} && !$data->{'product_name'} && + !$data->{'product_version'} && !$data->{'product_serial'})){ $b_skip_system = 1; } # found a case of battery existing but having nothing in it on desktop mobo @@ -11365,25 +11899,24 @@ sub create_output { # ibm / ibm can be true; dell / quantum is false, so in other words, only do this # in case where the vendor is the same and the version is the same and not null, # otherwise the version information is going to be different in all cases I think - if ( ($data{'sys_vendor'} && $data{'sys_vendor'} eq $data{'board_vendor'} ) && - ( ($data{'product_version'} && $data{'product_version'} eq $data{'board_version'} ) || - (!$data{'product_version'} && $data{'product_name'} && $data{'board_name'} && - $data{'product_name'} eq $data{'board_name'} ) ) ){ + if ( ($data->{'sys_vendor'} && $data->{'sys_vendor'} eq $data->{'board_vendor'} ) && + ( ($data->{'product_version'} && $data->{'product_version'} eq $data->{'board_version'} ) || + (!$data->{'product_version'} && $data->{'product_name'} && $data->{'board_name'} && + $data->{'product_name'} eq $data->{'board_name'} ) ) ){ $b_skip_system = 1; } } - $data{'device'} ||= 'N/A'; + $data->{'device'} ||= 'N/A'; $j = scalar @rows; - @row = ({ - main::key($num++,0,1,'Type') => ucfirst($data{'device'}), + push(@rows, { + main::key($num++,0,1,'Type') => ucfirst($data->{'device'}), },); - @rows = (@rows,@row); if (!$b_skip_system){ # this has already been tested for above so we know it's not null - $system_vendor = main::cleaner($data{'sys_vendor'}); - $product_name = ($data{'product_name'}) ? $data{'product_name'}:'N/A'; - $product_version = ($data{'product_version'}) ? $data{'product_version'}:'N/A'; - $product_serial = main::apply_filter($data{'product_serial'}); + $system_vendor = main::cleaner($data->{'sys_vendor'}); + $product_name = ($data->{'product_name'}) ? $data->{'product_name'}:'N/A'; + $product_version = ($data->{'product_version'}) ? $data->{'product_version'}:'N/A'; + $product_serial = main::apply_filter($data->{'product_serial'}); $rows[$j]{main::key($num++,1,1,'System')} = $system_vendor; $rows[$j]{main::key($num++,0,2,'product')} = $product_name; $rows[$j]{main::key($num++,0,2,'v')} = $product_version; @@ -11391,22 +11924,22 @@ sub create_output { # no point in showing chassis if system isn't there, it's very unlikely that # would be correct if ($extra > 1){ - if ($data{'board_version'} && $data{'chassis_version'} eq $data{'board_version'}){ + if ($data->{'board_version'} && $data->{'chassis_version'} eq $data->{'board_version'}){ $b_skip_chassis = 1; } - if (!$b_skip_chassis && $data{'chassis_vendor'} ){ - if ($data{'chassis_vendor'} ne $data{'sys_vendor'} ){ - $chassis_vendor = $data{'chassis_vendor'}; + if (!$b_skip_chassis && $data->{'chassis_vendor'} ){ + if ($data->{'chassis_vendor'} ne $data->{'sys_vendor'} ){ + $chassis_vendor = $data->{'chassis_vendor'}; } # dmidecode can have these be the same - if ($data{'chassis_type'} && $data{'device'} ne $data{'chassis_type'} ){ - $chassis_type = $data{'chassis_type'}; + if ($data->{'chassis_type'} && $data->{'device'} ne $data->{'chassis_type'} ){ + $chassis_type = $data->{'chassis_type'}; } - if ($data{'chassis_version'}){ - $chassis_version = $data{'chassis_version'}; + if ($data->{'chassis_version'}){ + $chassis_version = $data->{'chassis_version'}; $chassis_version =~ s/^v([0-9])/$1/i; } - $chassis_serial = main::apply_filter($data{'chassis_serial'}); + $chassis_serial = main::apply_filter($data->{'chassis_serial'}); $chassis_vendor ||= ''; $chassis_type ||= ''; $rows[$j]{main::key($num++,1,1,'Chassis')} = $chassis_vendor; @@ -11421,28 +11954,28 @@ sub create_output { } $j++; # start new row } - if ($data{'firmware'}){ - $firmware = $data{'firmware'}; + if ($data->{'firmware'}){ + $firmware = $data->{'firmware'}; } - $mobo_vendor = ($data{'board_vendor'}) ? main::cleaner($data{'board_vendor'}) : 'N/A'; - $mobo_model = ($data{'board_name'}) ? $data{'board_name'}: 'N/A'; - $mobo_version = ($data{'board_version'})? $data{'board_version'} : ''; - $mobo_serial = main::apply_filter($data{'board_serial'}); - $bios_vendor = ($data{'bios_vendor'}) ? main::cleaner($data{'bios_vendor'}) : 'N/A'; - if ($data{'bios_version'}){ - $bios_version = $data{'bios_version'}; + $mobo_vendor = ($data->{'board_vendor'}) ? main::cleaner($data->{'board_vendor'}) : 'N/A'; + $mobo_model = ($data->{'board_name'}) ? $data->{'board_name'}: 'N/A'; + $mobo_version = ($data->{'board_version'})? $data->{'board_version'} : ''; + $mobo_serial = main::apply_filter($data->{'board_serial'}); + $bios_vendor = ($data->{'bios_vendor'}) ? main::cleaner($data->{'bios_vendor'}) : 'N/A'; + if ($data->{'bios_version'}){ + $bios_version = $data->{'bios_version'}; $bios_version =~ s/^v([0-9])/$1/i; - if ($data{'bios_rev'}){ - $bios_rev = $data{'bios_rev'}; + if ($data->{'bios_rev'}){ + $bios_rev = $data->{'bios_rev'}; } } $bios_version ||= 'N/A'; - if ($data{'bios_date'}){ - $bios_date = $data{'bios_date'}; + if ($data->{'bios_date'}){ + $bios_date = $data->{'bios_date'}; } $bios_date ||= 'N/A'; - if ($extra > 1 && $data{'bios_romsize'}){ - $bios_romsize = $data{'bios_romsize'}; + if ($extra > 1 && $data->{'bios_romsize'}){ + $bios_romsize = $data->{'bios_romsize'}; } $rows[$j]{main::key($num++,1,1,'Mobo')} = $mobo_vendor; $rows[$j]{main::key($num++,0,2,'model')} = $mobo_model; @@ -11450,8 +11983,8 @@ sub create_output { $rows[$j]{main::key($num++,0,2,'v')} = $mobo_version; } $rows[$j]{main::key($num++,0,2,'serial')} = $mobo_serial; - if ($extra > 2 && $data{'board_uuid'}){ - $rows[$j]{main::key($num++,0,2,'uuid')} = $data{'board_uuid'}; + if ($extra > 2 && $data->{'board_uuid'}){ + $rows[$j]{main::key($num++,0,2,'uuid')} = $data->{'board_uuid'}; } $rows[$j]{main::key($num++,1,1,$firmware)} = $bios_vendor; $rows[$j]{main::key($num++,0,2,'v')} = $bios_version; @@ -11534,7 +12067,7 @@ sub machine_data_sys { foreach (@sys_files){ $path = "$sys_dir$_"; if (-r $path){ - $data{$_} = (main::reader($path))[0]; + $data{$_} = main::reader($path,'',0); $data{$_} = ($data{$_}) ? main::dmi_cleaner($data{$_}) : ''; } elsif (!$b_root && -e $path && !-r $path ){ @@ -11574,27 +12107,27 @@ sub machine_data_soc { my @data = main::reader($file); foreach (@data){ if (/^(Hardware|machine)\s*:/i){ - @temp = split /\s*:\s*/, $_; + @temp = split(/\s*:\s*/, $_, 2); $temp[1] = main::arm_cleaner($temp[1]); $temp[1] = main::dmi_cleaner($temp[1]); $soc_machine{'device'} = main::cleaner($temp[1]); } elsif (/^(system type|model)\s*:/i){ - @temp = split /\s*:\s*/, $_; + @temp = split(/\s*:\s*/, $_, 2); $temp[1] = main::dmi_cleaner($temp[1]); $soc_machine{'model'} = main::cleaner($temp[1]); } elsif (/^Revision/i){ - @temp = split /\s*:\s*/, $_; + @temp = split(/\s*:\s*/, $_, 2); $soc_machine{'firmware'} = $temp[1]; } elsif (/^Serial/i){ - @temp = split /\s*:\s*/, $_; + @temp = split(/\s*:\s*/, $_, 2); $soc_machine{'serial'} = $temp[1]; } } } - if (!$soc_machine{'model'} && -r '/system/build.prop'){ + if (!$soc_machine{'model'} && $b_android){ main::set_build_prop() if !$b_build_prop; if ($build_prop{'product-manufacturer'} && $build_prop{'product-model'}){ my $brand = ''; @@ -11611,12 +12144,12 @@ sub machine_data_soc { $soc_machine{'model'} = $build_prop{'product-name'}; } } - if (!$soc_machine{'model'} && -f '/proc/device-tree/model'){ - my $model = (main::reader('/proc/device-tree/model'))[0]; + if (!$soc_machine{'model'} && -r '/proc/device-tree/model'){ + my $model = main::reader('/proc/device-tree/model','',0); main::log_data('data',"device-tree-model: $model") if $b_log; - if ( $model ){ + if ($model){ $model = main::dmi_cleaner($model); - $model = (split /\x01|\x02|\x03|\x00/, $model)[0] if $model; + $model = (split(/\x01|\x02|\x03|\x00/, $model))[0] if $model; my $device_temp = main::regex_cleaner($soc_machine{'device'}); if ( !$soc_machine{'device'} || ($model && $model !~ /\Q$device_temp\E/i) ){ $model = main::arm_cleaner($model); @@ -11625,8 +12158,8 @@ sub machine_data_soc { } } if (!$soc_machine{'serial'} && -f '/proc/device-tree/serial-number'){ - my $serial = (main::reader('/proc/device-tree/serial-number'))[0]; - $serial = (split /\x01|\x02|\x03|\x00/, $serial)[0] if $serial; + my $serial = main::reader('/proc/device-tree/serial-number','',0); + $serial = (split(/\x01|\x02|\x03|\x00/, $serial))[0] if $serial; main::log_data('data',"device-tree-serial: $serial") if $b_log; $soc_machine{'serial'} = $serial if $serial; } @@ -11664,15 +12197,14 @@ sub machine_data_dmi { # dmi types: # 0 bios; 1 system info; 2 board|base board info; 3 chassis info; # 4 processor info, use to check for hypervisor - foreach (@dmi){ - my @ref = @$_; + foreach my $row (@dmi){ # bios/firmware - if ($ref[0] == 0){ + if ($row->[0] == 0){ # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; - foreach my $item (@ref){ + splice @$row, 0, 3 if @$row; + foreach my $item (@$row){ if ($item !~ /^~/){ # skip the indented rows - my @value = split /:\s+/, $item; + my @value = split(/:\s+/, $item); if ($value[0] eq 'Release Date') {$data{'bios_date'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Vendor') {$data{'bios_vendor'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Version') {$data{'bios_version'} = main::dmi_cleaner($value[1]) } @@ -11684,12 +12216,12 @@ sub machine_data_dmi { next; } # system information - elsif ($ref[0] == 1){ + elsif ($row->[0] == 1){ # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; - foreach my $item (@ref){ + splice @$row, 0, 3 if @$row; + foreach my $item (@$row){ if ($item !~ /^~/){ # skip the indented rows - my @value = split /:\s+/, $item; + my @value = split(/:\s+/, $item); if ($value[0] eq 'Product Name') {$data{'product_name'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Version') {$data{'product_version'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Serial Number') {$data{'product_serial'} = main::dmi_cleaner($value[1]) } @@ -11700,12 +12232,12 @@ sub machine_data_dmi { next; } # baseboard information - elsif ($ref[0] == 2){ + elsif ($row->[0] == 2){ # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; - foreach my $item (@ref){ + splice @$row, 0, 3 if @$row; + foreach my $item (@$row){ if ($item !~ /^~/){ # skip the indented rows - my @value = split /:\s+/, $item; + my @value = split(/:\s+/, $item); if ($value[0] eq 'Product Name') {$data{'board_name'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Serial Number') {$data{'board_serial'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Manufacturer') {$data{'board_vendor'} = main::dmi_cleaner($value[1]) } @@ -11714,12 +12246,12 @@ sub machine_data_dmi { next; } # chassis information - elsif ($ref[0] == 3){ + elsif ($row->[0] == 3){ # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; - foreach my $item (@ref){ + splice @$row, 0, 3 if @$row; + foreach my $item (@$row){ if ($item !~ /^~/){ # skip the indented rows - my @value = split /:\s+/, $item; + my @value = split(/:\s+/, $item); if ($value[0] eq 'Serial Number') {$data{'chassis_serial'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Type') {$data{'chassis_type'} = main::dmi_cleaner($value[1]) } elsif ($value[0] eq 'Manufacturer') {$data{'chassis_vendor'} = main::dmi_cleaner($value[1]) } @@ -11733,17 +12265,17 @@ sub machine_data_dmi { } # this may catch some BSD and fringe Linux cases # processor information: check for hypervisor - elsif ($ref[0] == 4){ + elsif ($row->[0] == 4){ # skip first three row, we don't need that data - splice @ref, 0, 3 if @ref; + splice @$row, 0, 3 if @$row; if (!$data{'device'}){ - if (grep {/hypervisor/i} @ref){ + if (grep {/hypervisor/i} @$row){ $data{'device'} = 'virtual-machine'; } } last; } - elsif ($ref[0] > 4){ + elsif ($row->[0] > 4){ last; } } @@ -11768,7 +12300,7 @@ sub machine_data_sysctl { # ^hw\.(vendor|product|version|serialno|uuid) foreach (@sysctl_machine){ next if ! $_; - my @item = split /:/, $_; + my @item = split(':', $_); next if ! $item[1]; if ($item[0] eq 'hw.vendor'){ $data{'board_vendor'} = main::dmi_cleaner($item[1]); @@ -11892,7 +12424,7 @@ sub get_device_vm { my @vm_data = (@sysctl,@dmesg_boot,$device_vm); if (-e '/dev/disk/by-id'){ my @dev = glob('/dev/disk/by-id/*'); - @vm_data = (@vm_data,@dev); + push(@vm_data,@dev); } if ( grep {/innotek|vbox|virtualbox/i} @vm_data){ $vm = 'virtualbox'; @@ -11948,18 +12480,17 @@ sub get { } else { @data = card_data(); - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; } @data = usb_data(); - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; # note: rasberry pi uses usb networking only if (!@rows && ($b_arm || $b_mips)){ my $type = ($b_arm) ? 'arm' : 'mips'; my $key = 'Message'; - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults($type . '-pci',''), },); - @rows = (@rows,@data); } if ($show{'network-advanced'}){ # @ifs_found = (); @@ -11967,16 +12498,16 @@ sub get { # pop @ifs_found; if (!$bsd_type){ @data = advanced_data_sys('check','',0,'','',''); - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; } else { @data = advanced_data_bsd('check'); - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; } } if ($show{'ip'}){ @data = wan_ip(); - @rows = (@rows,@data); + push(@rows,@data); } eval $end if $b_log; return @rows; @@ -11984,16 +12515,15 @@ sub get { sub card_data { eval $start if $b_log; - my ($b_wifi,@rows,@data,%holder); + my ($b_wifi,@rows,%holder); my ($j,$num) = (0,1); - foreach (@devices_network){ + foreach my $row (@devices_network){ $num = 1; - my @row = @$_; - #print "$row[0] $row[3]\n"; - #print "$row[0] $row[3]\n"; + #print "$row->[0] $row->[3]\n"; + #print "$row->[0] $row->[3]\n"; $j = scalar @rows; - my $driver = $row[9]; - my $chip_id = "$row[5]:$row[6]"; + my $driver = $row->[9]; + my $chip_id = "$row->[5]:$row->[6]"; # working around a virtuo bug same chip id is used on two nics if (!defined $holder{$chip_id}){ $holder{$chip_id} = 0; @@ -12002,120 +12532,113 @@ sub card_data { $holder{$chip_id}++; } # first check if it's a known wifi id'ed card, if so, no print of duplex/speed - $b_wifi = check_wifi($row[4]); - my $card = $row[4]; + $b_wifi = check_wifi($row->[4]); + my $card = $row->[4]; $card = ($card) ? main::pci_cleaner($card,'output') : 'N/A'; #$card ||= 'N/A'; $driver ||= 'N/A'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $card, },); - @rows = (@rows,@data); - if ($extra > 0 && $b_pci_tool && $row[12]){ - my $item = main::get_pci_vendor($row[4],$row[12]); + if ($extra > 0 && $b_pci_tool && $row->[12]){ + my $item = main::get_pci_vendor($row->[4],$row->[12]); $rows[$j]{main::key($num++,0,2,'vendor')} = $item if $item; } - if ($row[1] eq '0680'){ + if ($row->[1] eq '0680'){ $rows[$j]{main::key($num++,0,2,'type')} = 'network bridge'; } $rows[$j]{main::key($num++,1,2,'driver')} = $driver; my $bus_id = 'N/A'; # note: for arm/mips we want to see the single item bus id, why not? # note: we can have bus id: 0002 / 0 which is valid, but 0 / 0 is invalid - if (defined $row[2] && $row[2] ne '0' && defined $row[3]){$bus_id = "$row[2].$row[3]"} - elsif (defined $row[2] && $row[2] ne '0'){$bus_id = $row[2]} - elsif (defined $row[3] && $row[3] ne '0'){$bus_id = $row[3]} + if (defined $row->[2] && $row->[2] ne '0' && defined $row->[3]){$bus_id = "$row->[2].$row->[3]"} + elsif (defined $row->[2] && $row->[2] ne '0'){$bus_id = $row->[2]} + elsif (defined $row->[3] && $row->[3] ne '0'){$bus_id = $row->[3]} if ($extra > 0){ - if ($row[9] && !$bsd_type){ - my $version = main::get_module_version($row[9]); + if ($row->[9] && !$bsd_type){ + my $version = main::get_module_version($row->[9]); $version ||= 'N/A'; $rows[$j]{main::key($num++,0,3,'v')} = $version; } - if ($b_admin && $row[10]){ - $row[10] = main::get_driver_modules($row[9],$row[10]); - $rows[$j]{main::key($num++,0,3,'modules')} = $row[10] if $row[10]; + if ($b_admin && $row->[10]){ + $row->[10] = main::get_driver_modules($row->[9],$row->[10]); + $rows[$j]{main::key($num++,0,3,'modules')} = $row->[10] if $row->[10]; } - $row[8] ||= 'N/A'; + $row->[8] ||= 'N/A'; # as far as I know, wifi has no port, but in case it does in future, use it - $rows[$j]{main::key($num++,0,2,'port')} = $row[8] if (!$b_wifi || ( $b_wifi && $row[8] ne 'N/A') ); + $rows[$j]{main::key($num++,0,2,'port')} = $row->[8] if (!$b_wifi || ( $b_wifi && $row->[8] ne 'N/A') ); $rows[$j]{main::key($num++,0,2,'bus ID')} = $bus_id; } if ($extra > 1){ $rows[$j]{main::key($num++,0,2,'chip ID')} = $chip_id; } if ($show{'network-advanced'}){ - @data = (); + my @data; if (!$bsd_type){ - @data = advanced_data_sys($row[5],$row[6],$holder{$chip_id},$b_wifi,'',$bus_id); + @data = advanced_data_sys($row->[5],$row->[6],$holder{$chip_id},$b_wifi,'',$bus_id); } else { - @data = advanced_data_bsd("$row[9]$row[11]",$b_wifi) if defined $row[9] && defined $row[11]; + @data = advanced_data_bsd("$row->[9]$row->[11]",$b_wifi) if defined $row->[9] && defined $row->[11]; } - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; } - #print "$row[0]\n"; + #print "$row->[0]\n"; } # @rows = (); # we want to handle ARM errors in main get if (!@rows && !$b_arm && !$b_mips){ my $key = 'Message'; my $type = 'pci-card-data'; - if ($pci_tool && ${$alerts{$pci_tool}}{'action'} eq 'permissions'){ + if ($pci_tool && $alerts{$pci_tool}->{'action'} eq 'permissions'){ $type = 'pci-card-data-root'; } - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults($type,''), },); - @rows = (@rows,@data); - } - #my $ref = $pci[-1]; - #print $$ref[0],"\n"; eval $end if $b_log; return @rows; } sub usb_data { eval $start if $b_log; - my (@data,@rows,@temp2,$b_wifi,$driver, + my (@rows,@temp2,$b_wifi,$driver, $path,$path_id,$product,$test,$type); my ($j,$num) = (0,1); return if !@usb; - foreach my $ref (@usb){ - my @row = @$ref; + foreach my $row (@usb){ # a device will always be the second or > device on the bus, except for # daisychained hubs - if ($row[1] > 1 && $row[4] ne '9'){ + if ($row->[1] > 1 && $row->[4] ne '9'){ $num = 1; ($driver,$path,$path_id,$product,$test,$type) = ('','','','','',''); - $product = main::cleaner($row[13]) if $row[13]; - $driver = $row[15] if $row[15]; - $path = $row[3] if $row[3]; - $path_id = $row[2] if $row[2]; - $type = $row[14] if $row[14]; + $product = main::cleaner($row->[13]) if $row->[13]; + $driver = $row->[15] if $row->[15]; + $path = $row->[3] if $row->[3]; + $path_id = $row->[2] if $row->[2]; + $type = $row->[14] if $row->[14]; $test = "$driver $product $type"; if ($product && network_device($test)){ $driver ||= 'usb-network'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Device') => $product, main::key($num++,0,2,'type') => 'USB', main::key($num++,0,2,'driver') => $driver, },); $b_wifi = check_wifi($product); - @rows = (@rows,@data); if ($extra > 0){ - $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row[1]"; + $rows[$j]{main::key($num++,0,2,'bus ID')} = "$path_id:$row->[1]"; } if ($extra > 1){ - $rows[$j]{main::key($num++,0,2,'chip ID')} = $row[7]; + $rows[$j]{main::key($num++,0,2,'chip ID')} = $row->[7]; } - if ($extra > 2 && $row[16]){ - $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row[16]); + if ($extra > 2 && $row->[16]){ + $rows[$j]{main::key($num++,0,2,'serial')} = main::apply_filter($row->[16]); } if ($show{'network-advanced'}){ - @data = (); + my @data; if (!$bsd_type){ my (@temp,$vendor,$chip); - @temp = split (/:/, $row[7]) if $row[7]; + @temp = split(':', $row->[7]) if $row->[7]; ($vendor,$chip) = ($temp[0],$temp[1]) if @temp; @data = advanced_data_sys($vendor,$chip,0,$b_wifi,$path,''); } @@ -12123,9 +12646,9 @@ sub usb_data { # we can't get that from usb data, so we have to let it fall back down # to the check function for BSDs. #else { - # @data = advanced_data_bsd($row[2],$b_wifi); + # @data = advanced_data_bsd($row->[2],$b_wifi); #} - @rows = (@rows,@data) if @data; + push(@rows,@data) if @data; } $j = scalar @rows; } @@ -12160,17 +12683,17 @@ sub advanced_data_sys { $key = 'IF-ID'; ($cont_if,$ind_if) = (1,2); } - #print join '; ', @paths, $count, "\n"; + #print join('; ', @paths), $count, "\n"; foreach (@paths){ my ($data1,$data2,$duplex,$mac,$speed,$state); # for usb, we already know where we are if (!$b_usb){ if (( !$b_arm && !$b_ppc) || $b_pci_tool ){ $path = "$_/device/vendor"; - $data1 = (main::reader($path))[0] if -e $path; + $data1 = main::reader($path,'',0) if -r $path; $data1 =~ s/^0x// if $data1; $path = "$_/device/device"; - $data2 = (main::reader($path))[0] if -e $path; + $data2 = main::reader($path,'',0) if -r $path; $data2 =~ s/^0x// if $data2; # this is a fix for a redhat bug in virtio $data2 = (defined $data2 && $data2 eq '0001' && defined $chip && $chip eq '1000') ? '1000' : $data2; @@ -12193,16 +12716,16 @@ sub advanced_data_sys { # print "top: if: $if ifs: @ifs_found\n"; next if ($b_check && grep {/$if/} @ifs_found); $path = "$_/duplex"; - $duplex = (main::reader($path))[0] if -e $path; + $duplex = main::reader($path,'',0) if -r $path; $duplex ||= 'N/A'; $path = "$_/address"; - $mac = (main::reader($path))[0] if -e $path; + $mac = main::reader($path,'',0) if -r $path; $mac = main::apply_filter($mac); $path = "$_/speed"; - $speed = (main::reader($path))[0] if -e $path; + $speed = main::reader($path,'',0) if -r $path; $speed ||= 'N/A'; $path = "$_/operstate"; - $state = (main::reader($path))[0] if -e $path; + $state = main::reader($path,'',0) if -r $path; $state ||= 'N/A'; #print "$speed \n"; @row = ({ @@ -12210,7 +12733,7 @@ sub advanced_data_sys { main::key($num++,0,$ind_if,'state') => $state, },); #my $j = scalar @row - 1; - push (@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found)); + push(@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found)); # print "push: if: $if ifs: @ifs_found\n"; # no print out for wifi since it doesn't have duplex/speed data available # note that some cards show 'unknown' for state, so only testing explicitly @@ -12225,14 +12748,14 @@ sub advanced_data_sys { } $row[0]{main::key($num++,0,$ind_if,'mac')} = $mac; if ($b_check){ - @rows = (@rows,@row); + push(@rows,@row); } else { @rows = @row; } if ($show{'ip'}){ @row = if_ip($key,$if); - @rows = (@rows,@row); + push(@rows, @row); } last if !$b_check; } @@ -12255,14 +12778,14 @@ sub advanced_data_bsd { $key = 'IF-ID'; ($cont_if,$ind_if) = (1,2); } - foreach my $ref (@ifs_bsd){ - if (ref $ref ne 'ARRAY'){ - $working_if = $ref; + foreach my $item (@ifs_bsd){ + if (ref $item ne 'ARRAY'){ + $working_if = $item; # print "$working_if\n"; next; } else { - @data = @$ref; + @data = @$item; } if ( $b_check || $working_if eq $if){ $if = $working_if if $b_check; @@ -12282,7 +12805,7 @@ sub advanced_data_bsd { main::key($num++,1,$cont_if,$key) => $if, main::key($num++,0,$ind_if,'state') => $state, },); - push (@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found )); + push(@ifs_found, $if) if (!$b_check && (! grep {/$if/} @ifs_found )); # print "push: if: $if ifs: @ifs_found\n"; # no print out for wifi since it doesn't have duplex/speed data available # note that some cards show 'unknown' for state, so only testing explicitly @@ -12295,10 +12818,10 @@ sub advanced_data_bsd { } $row[0]{main::key($num++,0,$ind_if,'mac')} = $mac; } - @rows = (@rows,@row); - if ($show{'ip'}){ - @row = if_ip($key,$if) if $if; - @rows = (@rows,@row) if @row; + push(@rows, @row); + if ($show{'ip'} && $if){ + @row = if_ip($key,$if); + push(@rows,@row) if @row; } } } @@ -12314,7 +12837,7 @@ sub advanced_data_bsd { sub if_ip { eval $start if $b_log; my ($type,$if) = @_; - my (@data,@row,@rows,$working_if); + my (@data,@rows,$working_if); my ($cont_ip,$ind_ip) = (3,4); my $num = 0; my $j = 0; @@ -12323,36 +12846,34 @@ sub if_ip { ($cont_ip,$ind_ip) = (2,3); } OUTER: - foreach my $ref (@ifs){ - if (ref $ref ne 'ARRAY'){ - $working_if = $ref; + foreach my $item (@ifs){ + if (ref $item ne 'ARRAY'){ + $working_if = $item; # print "if:$if wif:$working_if\n"; next; } else { - @data = @$ref; - # print "ref:$ref\n"; + @data = @$item; + # print "ref:$item\n"; } if ($working_if eq $if){ - foreach my $ref2 (@data){ + foreach my $data2 (@data){ $j = scalar @rows; $num = 1; if ($limit > 0 && $j >= $limit){ - @row = ({ + push(@rows, { main::key($num++,0,$cont_ip,'Message') => main::row_defaults('output-limit',scalar @data), },); - @rows = (@rows,@row); last OUTER; } - my @data2 = @$ref2; - #print "$data2[0] $data2[1]\n"; + #print "$data2->[0] $data2->[1]\n"; my ($ipv,$ip,$broadcast,$scope,$scope_id); - $ipv = ($data2[0])? $data2[0]: 'N/A'; - $ip = main::apply_filter($data2[1]); - $scope = ($data2[3])? $data2[3]: 'N/A'; + $ipv = ($data2->[0])? $data2->[0]: 'N/A'; + $ip = main::apply_filter($data2->[1]); + $scope = ($data2->[3])? $data2->[3]: 'N/A'; # note: where is this ever set to 'all'? Old test condition? if ($if ne 'all'){ - if (defined $data2[4] && $working_if ne $data2[4]){ + if (defined $data2->[4] && $working_if ne $data2->[4]){ # scope global temporary deprecated dynamic # scope global dynamic # scope global temporary deprecated dynamic @@ -12363,31 +12884,30 @@ sub if_ip { # scope site dynamic # scope link # trim off if at end of multi word string if found - $data2[4] =~ s/\s$if$// if $data2[4] =~ /[^\s]+\s$if$/; - my $key = ($data2[4] =~ /deprecated|dynamic|temporary|noprefixroute/ ) ? 'type':'virtual' ; - @row = ({ + $data2->[4] =~ s/\s$if$// if $data2->[4] =~ /[^\s]+\s$if$/; + my $key = ($data2->[4] =~ /deprecated|dynamic|temporary|noprefixroute/ ) ? 'type':'virtual' ; + push(@rows, { main::key($num++,1,$cont_ip,"IP v$ipv") => $ip, - main::key($num++,0,$ind_ip,$key) => $data2[4], + main::key($num++,0,$ind_ip,$key) => $data2->[4], main::key($num++,0,$ind_ip,'scope') => $scope, },); } else { - @row = ({ + push(@rows, { main::key($num++,1,$cont_ip,"IP v$ipv") => $ip, main::key($num++,0,$ind_ip,'scope') => $scope, },); } } else { - @row = ({ + push(@rows, { main::key($num++,1,($cont_ip - 1 ),'IF') => $if, main::key($num++,1,$cont_ip,"IP v$ipv") => $ip, main::key($num++,0,$ind_ip,'scope') => $scope, },); } - @rows = (@rows,@row); - if ($extra > 1 && $data2[2]){ - $broadcast = main::apply_filter($data2[2]); + if ($extra > 1 && $data2->[2]){ + $broadcast = main::apply_filter($data2->[2]); $rows[$j]{main::key($num++,0,$ind_ip,'broadcast')} = $broadcast; } } @@ -12438,8 +12958,8 @@ sub wan_ip { $ip = main::download_file('stdout',$_,'',$ua); if ($ip){ # print "$_\n"; - chomp $ip; - $ip = (split /\s+/, $ip)[-1]; + chomp($ip); + $ip = (split(/\s+/, $ip))[-1]; last; } } @@ -12567,80 +13087,79 @@ sub get { $val1 = main::row_defaults('optical-data'); @data = ({main::key($num++,0,1,$key1) => $val1,}); } - @rows = (@rows,@data); + push(@rows,@data); eval $end if $b_log; return @rows; } sub create_output { eval $start if $b_log; my (%devices) = @_; - my (@data,@rows); + my (@rows); my $num = 0; my $j = 0; # build floppy if any foreach my $key (sort keys %devices){ - if ($devices{$key}{'type'} eq 'floppy'){ - @data = ({ main::key($num++,0,1,ucfirst($devices{$key}{'type'})) => "/dev/$key"}); - @rows = (@rows,@data); + if ($devices{$key}->{'type'} eq 'floppy'){ + push(@rows, { + main::key($num++,0,1,ucfirst($devices{$key}->{'type'})) => "/dev/$key", + }); delete $devices{$key}; } } foreach my $key (sort keys %devices){ $j = scalar @rows; $num = 1; - my $vendor = $devices{$key}{'vendor'}; + my $vendor = $devices{$key}->{'vendor'}; $vendor ||= 'N/A'; - my $model = $devices{$key}{'model'}; + my $model = $devices{$key}->{'model'}; $model ||= 'N/A'; - @data = ({ - main::key($num++,1,1,ucfirst($devices{$key}{'type'})) => "/dev/$key", + push(@rows, { + main::key($num++,1,1,ucfirst($devices{$key}->{'type'})) => "/dev/$key", main::key($num++,0,2,'vendor') => $vendor, main::key($num++,0,2,'model') => $model, }); - @rows = (@rows,@data); if ($extra > 0){ - my $rev = $devices{$key}{'rev'}; + my $rev = $devices{$key}->{'rev'}; $rev ||= 'N/A'; $rows[$j]{ main::key($num++,0,2,'rev')} = $rev; } - if ($extra > 1 && $devices{$key}{'serial'}){ - $rows[$j]{ main::key($num++,0,2,'serial')} = main::apply_filter($devices{$key}{'serial'}); + if ($extra > 1 && $devices{$key}->{'serial'}){ + $rows[$j]{ main::key($num++,0,2,'serial')} = main::apply_filter($devices{$key}->{'serial'}); } - my $ref = $devices{$key}{'links'}; - my $links = (@$ref) ? join ',', sort @$ref: 'N/A' ; + my $links = (@{$devices{$key}->{'links'}}) ? join(',', sort @{$devices{$key}->{'links'}}) : 'N/A' ; $rows[$j]{ main::key($num++,0,2,'dev-links')} = $links; if ($show{'optical'}){ $j = scalar @rows; - my $speed = $devices{$key}{'speed'}; + my $speed = $devices{$key}->{'speed'}; $speed ||= 'N/A'; my ($audio,$multisession) = ('',''); - if (defined $devices{$key}{'multisession'}){ - $multisession = ( $devices{$key}{'multisession'} == 1 ) ? 'yes' : 'no' ; + if (defined $devices{$key}->{'multisession'}){ + $multisession = ( $devices{$key}->{'multisession'} == 1 ) ? 'yes' : 'no' ; } $multisession ||= 'N/A'; - if (defined $devices{$key}{'audio'}){ - $audio = ( $devices{$key}{'audio'} == 1 ) ? 'yes' : 'no' ; + if (defined $devices{$key}->{'audio'}){ + $audio = ( $devices{$key}->{'audio'} == 1 ) ? 'yes' : 'no' ; } $audio ||= 'N/A'; my $dvd = 'N/A'; my (@rw,$rws); - if (defined $devices{$key}{'dvd'}){ - $dvd = ( $devices{$key}{'dvd'} == 1 ) ? 'yes' : 'no' ; + if (defined $devices{$key}->{'dvd'}){ + $dvd = ( $devices{$key}->{'dvd'} == 1 ) ? 'yes' : 'no' ; } - if ($devices{$key}{'cdr'}){ - push @rw, 'cd-r'; + if ($devices{$key}->{'cdr'}){ + push(@rw, 'cd-r'); } - if ($devices{$key}{'cdrw'}){ - push @rw, 'cd-rw'; + if ($devices{$key}->{'cdrw'}){ + push(@rw, 'cd-rw'); } - if ($devices{$key}{'dvdr'}){ - push @rw, 'dvd-r'; + if ($devices{$key}->{'dvdr'}){ + push(@rw, 'dvd-r'); } - if ($devices{$key}{'dvdram'}){ - push @rw, 'dvd-ram'; + if ($devices{$key}->{'dvdram'}){ + push(@rw, 'dvd-ram'); } - $rws = (@rw) ? join ',', @rw: 'none' ; - @data = ({ + $rws = (@rw) ? join(',', @rw) : 'none' ; + push(@rows, { main::key($num++,1,2,'Features') => '', main::key($num++,0,3,'speed') => $speed, main::key($num++,0,3,'multisession') => $multisession, @@ -12648,9 +13167,8 @@ sub create_output { main::key($num++,0,3,'dvd') => $dvd, main::key($num++,0,3,'rw') => $rws, }); - @rows = (@rows,@data); if ($extra > 0 ){ - my $state = $devices{$key}{'state'}; + my $state = $devices{$key}->{'state'}; $state ||= 'N/A'; $rows[$j]{ main::key($num++,0,3,'state')} = $state; } @@ -12662,11 +13180,11 @@ sub create_output { } sub optical_data_bsd { eval $start if $b_log; - my (@data,%devices,@rows,@temp); + my (%devices,@rows,@temp); my ($count,$i,$working) = (0,0,''); foreach (@dm_boot_optical){ $_ =~ s/(cd[0-9]+)\(([^:]+):([0-9]+):([0-9]+)\):/$1:$2-$3.$4,/; - my @row = split /:\s*/, $_; + my @row = split(/:\s*/, $_); next if ! defined $row[1]; if ($working ne $row[0]){ # print "$id_holder $row[0]\n"; @@ -12674,86 +13192,85 @@ sub optical_data_bsd { } # no dots, note: ada2: 2861588MB BUT: ada2: 600.000MB/s if (! exists $devices{$working}){ - $devices{$working} = ({}); - $devices{$working}{'links'} = ([]); - $devices{$working}{'model'} = ''; - $devices{$working}{'rev'} = ''; - $devices{$working}{'state'} = ''; - $devices{$working}{'vendor'} = ''; - $devices{$working}{'temp'} = ''; - $devices{$working}{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown'; + $devices{$working}->{'links'} = ([]); + $devices{$working}->{'model'} = ''; + $devices{$working}->{'rev'} = ''; + $devices{$working}->{'state'} = ''; + $devices{$working}->{'vendor'} = ''; + $devices{$working}->{'temp'} = ''; + $devices{$working}->{'type'} = ($working =~ /^cd/) ? 'optical' : 'unknown'; } #print "$_\n"; if ($bsd_type ne 'openbsd'){ if ($row[1] && $row[1] =~ /^<([^>]+)>/){ - $devices{$working}{'model'} = $1; - $count = ($devices{$working}{'model'} =~ tr/ //); + $devices{$working}->{'model'} = $1; + $count = ($devices{$working}->{'model'} =~ tr/ //); if ($count && $count > 1){ - @temp = split /\s+/, $devices{$working}{'model'}; - $devices{$working}{'vendor'} = $temp[0]; + @temp = split(/\s+/, $devices{$working}->{'model'}); + $devices{$working}->{'vendor'} = $temp[0]; my $index = ($#temp > 2 ) ? ($#temp - 1): $#temp; - $devices{$working}{'model'} = join ' ', @temp[1..$index]; - $devices{$working}{'rev'} = $temp[-1] if $count > 2; + $devices{$working}->{'model'} = join(' ', @temp[1..$index]); + $devices{$working}->{'rev'} = $temp[-1] if $count > 2; } if ($show{'optical'}){ if (/\bDVD\b/){ - $devices{$working}{'dvd'} = 1; + $devices{$working}->{'dvd'} = 1; } if (/\bRW\b/){ - $devices{$working}{'cdrw'} = 1; - $devices{$working}{'dvdr'} = 1 if $devices{$working}{'dvd'}; + $devices{$working}->{'cdrw'} = 1; + $devices{$working}->{'dvdr'} = 1 if $devices{$working}->{'dvd'}; } } } if ($row[1] && $row[1] =~ /^Serial/){ - @temp = split /\s+/,$row[1]; - $devices{$working}{'serial'} = $temp[-1]; + @temp = split(/\s+/,$row[1]); + $devices{$working}->{'serial'} = $temp[-1]; } if ($show{'optical'}){ if ($row[1] =~ /^([0-9\.]+[MGTP][B]?\/s)/){ - $devices{$working}{'speed'} = $1; - $devices{$working}{'speed'} =~ s/\.[0-9]+//; + $devices{$working}->{'speed'} = $1; + $devices{$working}->{'speed'} =~ s/\.[0-9]+//; } if (/\bDVD[-]?RAM\b/){ - $devices{$working}{'cdr'} = 1; - $devices{$working}{'dvdram'} = 1; + $devices{$working}->{'cdr'} = 1; + $devices{$working}->{'dvdram'} = 1; } if ($row[2] && $row[2] =~ /,\s(.*)$/){ - $devices{$working}{'state'} = $1; - $devices{$working}{'state'} =~ s/\s+-\s+/, /; + $devices{$working}->{'state'} = $1; + $devices{$working}->{'state'} =~ s/\s+-\s+/, /; } } } else { if ($row[2] && $row[2] =~ /<([^>]+)>/){ - $devices{$working}{'model'} = $1; - $count = ($devices{$working}{'model'} =~ tr/,//); + $devices{$working}->{'model'} = $1; + $count = ($devices{$working}->{'model'} =~ tr/,//); #print "c: $count $row[2]\n"; if ($count && $count > 1){ - @temp = split /,\s*/, $devices{$working}{'model'}; - $devices{$working}{'vendor'} = $temp[0]; - $devices{$working}{'model'} = $temp[1]; - $devices{$working}{'rev'} = $temp[2]; + @temp = split(/,\s*/, $devices{$working}->{'model'}); + $devices{$working}->{'vendor'} = $temp[0]; + $devices{$working}->{'model'} = $temp[1]; + $devices{$working}->{'rev'} = $temp[2]; } if ($show{'optical'}){ if (/\bDVD\b/){ - $devices{$working}{'dvd'} = 1; + $devices{$working}->{'dvd'} = 1; } if (/\bRW\b/){ - $devices{$working}{'cdrw'} = 1; - $devices{$working}{'dvdr'} = 1 if $devices{$working}{'dvd'}; + $devices{$working}->{'cdrw'} = 1; + $devices{$working}->{'dvdr'} = 1 if $devices{$working}->{'dvd'}; } if (/\bDVD[-]?RAM\b/){ - $devices{$working}{'cdr'} = 1; - $devices{$working}{'dvdram'} = 1; + $devices{$working}->{'cdr'} = 1; + $devices{$working}->{'dvdram'} = 1; } } } if ($show{'optical'}){ #print "$row[1]\n"; if (($row[1] =~ tr/,//) > 1){ - @temp = split /,\s*/, $row[1]; - $devices{$working}{'speed'} = $temp[2]; + @temp = split(/,\s*/, $row[1]); + $devices{$working}->{'speed'} = $temp[2]; } } @@ -12780,43 +13297,42 @@ sub optical_data_linux { # possible fix: puppy has these in /mnt not /dev they say $working =~ s/\/(dev|media|mnt)\///; $_ =~ s/\/(dev|media|mnt)\///; - if (! defined $devices{$working}){ - my @temp = ($_ ne $working) ? ([$_]) : ([]); - $devices{$working} = ({'links' => @temp}); - $devices{$working}{'type'} = ($working =~ /^fd/) ? 'floppy' : 'optical' ; + if (!defined $devices{$working}){ + my @temp = ($_ ne $working) ? ($_) : (); + $devices{$working}->{'links'} = \@temp; + $devices{$working}->{'type'} = ($working =~ /^fd/) ? 'floppy' : 'optical' ; } else { - my $ref = $devices{$working}{'links'}; - push @$ref, $_ if $_ ne $working; + push(@{$devices{$working}->{'links'}}, $_) if $_ ne $working; } #print "$working\n"; } if ($show{'optical'} && -e '/proc/sys/dev/cdrom/info'){ @info = main::reader('/proc/sys/dev/cdrom/info','strip'); } - #print join '; ', @data, "\n"; + #print join('; ', @data), "\n"; foreach my $key (keys %devices){ - next if $devices{$key}{'type'} eq 'floppy'; + next if $devices{$key}->{'type'} eq 'floppy'; my $device = "/sys/block/$key/device"; if ( -d $device){ - if (-e "$device/vendor"){ - $devices{$key}{'vendor'} = (main::reader("$device/vendor"))[0]; - $devices{$key}{'vendor'} = main::cleaner($devices{$key}{'vendor'}); - $devices{$key}{'state'} = (main::reader("$device/state"))[0]; - $devices{$key}{'model'} = (main::reader("$device/model"))[0]; - $devices{$key}{'model'} = main::cleaner($devices{$key}{'model'}); - $devices{$key}{'rev'} = (main::reader("$device/rev"))[0]; + if (-r "$device/vendor"){ + $devices{$key}->{'vendor'} = main::reader("$device/vendor",'',0); + $devices{$key}->{'vendor'} = main::cleaner($devices{$key}->{'vendor'}); + $devices{$key}->{'state'} = main::reader("$device/state",'',0); + $devices{$key}->{'model'} = main::reader("$device/model",'',0); + $devices{$key}->{'model'} = main::cleaner($devices{$key}->{'model'}); + $devices{$key}->{'rev'} = main::reader("$device/rev",'',0); } } - elsif ( -e "/proc/ide/$key/model"){ - $devices{$key}{'vendor'} = (main::reader("/proc/ide/$key/model"))[0]; - $devices{$key}{'vendor'} = main::cleaner($devices{$key}{'vendor'}); + elsif ( -r "/proc/ide/$key/model"){ + $devices{$key}->{'vendor'} = main::reader("/proc/ide/$key/model",'',0); + $devices{$key}->{'vendor'} = main::cleaner($devices{$key}->{'vendor'}); } if ($show{'optical'} && @info){ my $index = 0; foreach my $item (@info){ next if $item =~ /^\s*$/; - my @split = split '\s+', $item; + my @split = split(/\s+/, $item); if ($item =~ /^drive name:/){ foreach my $id (@split){ last if ($id eq $key); @@ -12825,31 +13341,31 @@ sub optical_data_linux { last if ! $index; # index will be > 0 if it was found } elsif ($item =~/^drive speed:/) { - $devices{$key}{'speed'} = $split[$index]; + $devices{$key}->{'speed'} = $split[$index]; } elsif ($item =~/^Can read multisession:/) { - $devices{$key}{'multisession'}=$split[$index+1]; + $devices{$key}->{'multisession'}=$split[$index+1]; } elsif ($item =~/^Can read MCN:/) { - $devices{$key}{'mcn'}=$split[$index+1]; + $devices{$key}->{'mcn'}=$split[$index+1]; } elsif ($item =~/^Can play audio:/) { - $devices{$key}{'audio'}=$split[$index+1]; + $devices{$key}->{'audio'}=$split[$index+1]; } elsif ($item =~/^Can write CD-R:/) { - $devices{$key}{'cdr'}=$split[$index+1]; + $devices{$key}->{'cdr'}=$split[$index+1]; } elsif ($item =~/^Can write CD-RW:/) { - $devices{$key}{'cdrw'}=$split[$index+1]; + $devices{$key}->{'cdrw'}=$split[$index+1]; } elsif ($item =~/^Can read DVD:/) { - $devices{$key}{'dvd'}=$split[$index+1]; + $devices{$key}->{'dvd'}=$split[$index+1]; } elsif ($item =~/^Can write DVD-R:/) { - $devices{$key}{'dvdr'}=$split[$index+1]; + $devices{$key}->{'dvdr'}=$split[$index+1]; } elsif ($item =~/^Can write DVD-RAM:/) { - $devices{$key}{'dvdram'}=$split[$index+1]; + $devices{$key}->{'dvdram'}=$split[$index+1]; } } } @@ -12889,7 +13405,7 @@ sub create_output { eval $start if $b_log; my $num = 0; my $j = 0; - my (@data,@data2,%part,@rows,$dev,$dev_type,$fs,$percent,$raw_size,$size,$used); + my (%part,@rows,$dev,$dev_type,$fs,$percent,$raw_size,$size,$used); # alpha sort for non numerics if ($show{'partition-sort'} !~ /^(percent-used|size|used)$/){ @partitions = sort { $a->{$show{'partition-sort'}} cmp $b->{$show{'partition-sort'}} } @partitions; @@ -12897,73 +13413,69 @@ sub create_output { else { @partitions = sort { $a->{$show{'partition-sort'}} <=> $b->{$show{'partition-sort'}} } @partitions; } - foreach my $ref (@partitions){ - my %row = %$ref; + foreach my $row (@partitions){ $num = 1; - next if $row{'type'} eq 'secondary' && $show{'partition'}; - next if $show{'swap'} && $row{'fs'} && $row{'fs'} eq 'swap'; - next if $row{'swap-type'} && $row{'swap-type'} ne 'partition'; - if (!$row{'hidden'}){ - @data2 = main::get_size($row{'size'}) if (defined $row{'size'}); - $size = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - @data2 = main::get_size($row{'used'}) if (defined $row{'used'}); - $used = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - $percent = (defined $row{'percent-used'}) ? ' (' . $row{'percent-used'} . '%)' : ''; + next if $row->{'type'} eq 'secondary' && $show{'partition'}; + next if $show{'swap'} && $row->{'fs'} && $row->{'fs'} eq 'swap'; + next if $row->{'swap-type'} && $row->{'swap-type'} ne 'partition'; + if (!$row->{'hidden'}){ + $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; + $used = ($row->{'used'}) ? main::get_size($row->{'used'},'string') : 'N/A'; + $percent = (defined $row->{'percent-used'}) ? ' (' . $row->{'percent-used'} . '%)' : ''; } else { $percent = ''; $used = $size = (!$b_root) ? main::row_defaults('root-required') : main::row_defaults('partition-hidden'); } %part = (); - $fs = ($row{'fs'}) ? lc($row{'fs'}): 'N/A'; - $dev_type = ($row{'dev-type'}) ? $row{'dev-type'} : 'dev'; - $row{'dev-base'} = '/dev/' . $row{'dev-base'} if $dev_type eq 'dev' && $row{'dev-base'}; - $dev = ($row{'dev-base'}) ? $row{'dev-base'} : 'N/A'; - $row{'id'} =~ s|/home/[^/]+/(.*)|/home/$filter_string/$1| if $use{'filter'}; + $fs = ($row->{'fs'}) ? lc($row->{'fs'}): 'N/A'; + $dev_type = ($row->{'dev-type'}) ? $row->{'dev-type'} : 'dev'; + $row->{'dev-base'} = '/dev/' . $row->{'dev-base'} if $dev_type eq 'dev' && $row->{'dev-base'}; + $dev = ($row->{'dev-base'}) ? $row->{'dev-base'} : 'N/A'; + $row->{'id'} =~ s|/home/[^/]+/(.*)|/home/$filter_string/$1| if $use{'filter'}; $j = scalar @rows; - @data = ({ - main::key($num++,1,1,'ID') => $row{'id'}, + push(@rows, { + main::key($num++,1,1,'ID') => $row->{'id'}, }); - @rows = (@rows,@data); - if (($b_admin || $row{'hidden'}) && $row{'raw-size'} ){ + if (($b_admin || $row->{'hidden'}) && $row->{'raw-size'} ){ # It's an error! permissions or missing tool - if (!main::is_numeric($row{'raw-size'})){ - $raw_size = $row{'raw-size'}; - } - else { - @data2 = main::get_size($row{'raw-size'}); - $raw_size = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - } + $raw_size = ($row->{'raw-size'}) ? main::get_size($row->{'raw-size'},'string') : 'N/A'; $rows[$j]{main::key($num++,0,2,'raw size')} = $raw_size; } - if ($b_admin && $row{'raw-available'} && $size ne 'N/A'){ - $size .= ' (' . $row{'raw-available'} . '%)'; + if ($b_admin && $row->{'raw-available'} && $size ne 'N/A'){ + $size .= ' (' . $row->{'raw-available'} . '%)'; } $rows[$j]{main::key($num++,0,2,'size')} = $size; $rows[$j]{main::key($num++,0,2,'used')} = $used . $percent; $rows[$j]{main::key($num++,0,2,'fs')} = $fs; - if ($b_admin && $fs eq 'swap' && defined $row{'swappiness'}){ - $rows[$j]{main::key($num++,0,2,'swappiness')} = $row{'swappiness'}; + if ($b_admin && $fs eq 'swap' && defined $row->{'swappiness'}){ + $rows[$j]{main::key($num++,0,2,'swappiness')} = $row->{'swappiness'}; } - if ($b_admin && $fs eq 'swap' && defined $row{'cache-pressure'}){ - $rows[$j]{main::key($num++,0,2,'cache pressure')} = $row{'cache-pressure'}; + if ($b_admin && $fs eq 'swap' && defined $row->{'cache-pressure'}){ + $rows[$j]{main::key($num++,0,2,'cache pressure')} = $row->{'cache-pressure'}; } - if ($extra > 1 && $fs eq 'swap' && defined $row{'priority'}){ - $rows[$j]{main::key($num++,0,2,'priority')} = $row{'priority'}; + if ($extra > 1 && $fs eq 'swap' && defined $row->{'priority'}){ + $rows[$j]{main::key($num++,0,2,'priority')} = $row->{'priority'}; } - if ($b_admin && $row{'block-size'}){ - $rows[$j]{main::key($num++,0,2,'block size')} = $row{'block-size'} . ' B';; - #$rows[$j]{main::key($num++,0,2,'physical')} = $row{'block-size'} . ' B'; - #$rows[$j]{main::key($num++,0,2,'logical')} = $row{'block-logical'} . ' B'; + if ($b_admin && $row->{'block-size'}){ + $rows[$j]{main::key($num++,0,2,'block size')} = $row->{'block-size'} . ' B';; + #$rows[$j]{main::key($num++,0,2,'physical')} = $row->{'block-size'} . ' B'; + #$rows[$j]{main::key($num++,0,2,'logical')} = $row->{'block-logical'} . ' B'; + } + $rows[$j]{main::key($num++,1,2,$dev_type)} = $dev; + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,3,'maj-min')} = $row->{'maj-min'}; + } + if ($extra > 0 && $row->{'dev-mapped'}){ + $rows[$j]{main::key($num++,0,3,'mapped')} = $row->{'dev-mapped'}; } - $rows[$j]{main::key($num++,0,2,$dev_type)} = $dev; if ($show{'label'}){ - $row{'label'} = main::apply_partition_filter('part', $row{'label'}, '') if $use{'filter-label'}; - $rows[$j]{main::key($num++,0,2,'label')} = ($row{'label'}) ? $row{'label'}: 'N/A'; + $row->{'label'} = main::apply_partition_filter('part', $row->{'label'}, '') if $use{'filter-label'}; + $rows[$j]{main::key($num++,0,2,'label')} = ($row->{'label'}) ? $row->{'label'}: 'N/A'; } if ($show{'uuid'}){ - $row{'uuid'} = main::apply_partition_filter('part', $row{'uuid'}, '') if $use{'filter-uuid'}; - $rows[$j]{main::key($num++,0,2,'uuid')} = ($row{'uuid'}) ? $row{'uuid'}: 'N/A'; + $row->{'uuid'} = main::apply_partition_filter('part', $row->{'uuid'}, '') if $use{'filter-uuid'}; + $rows[$j]{main::key($num++,0,2,'uuid')} = ($row->{'uuid'}) ? $row->{'uuid'}: 'N/A'; } } eval $end if $b_log; @@ -12973,19 +13485,20 @@ sub create_output { sub partition_data { eval $start if $b_log; #return if $bsd_type && $bsd_type eq 'darwin'; # darwin has muated output, of course - my (@data,@rows,@mapper,@mount,@partitions_working,%part,@working); + my (@data,@rows,@mount,@partitions_working,%part,@working); my ($b_fake_map,$b_fs,$b_load,$b_space,$cols,$roots) = (0,1,0,0,6,0); my ($back_size,$back_used) = (4,3); - my ($block_size,$blockdev,$dev_base,$dev_type,$fs,$id,$label,$percent_used, - $raw_size,$replace,$size_available,$size,$test,$type,$uuid,$used); + my ($block_size,$blockdev,$dev_base,$dev_mapped,$dev_type,$fs,$id,$label, + $maj_min,$percent_used,$raw_size,$replace,$size_available,$size,$test, + $type,$uuid,$used); $b_partitions = 1; if ($b_admin){ # for partition block size - $blockdev = main::check_program('blockdev'); - # for raw partition sizes - DiskData::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + $blockdev = $alerts{'blockdev'}->{'path'} if $alerts{'blockdev'}->{'path'}; } - set_lsblk() if !$bsd_type && !$b_lsblk; + # for raw partition sizes, maj_min + main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + main::set_lsblk() if !$bsd_type && !$b_lsblk; # set labels, uuid, gpart set_label_uuid() if !$b_label_uuid; # most current OS support -T and -k, but -P means different things @@ -12993,9 +13506,7 @@ sub partition_data { # android 7 no -T support if (!$bsd_type){ @partitions_working = main::grabber("df -P -T -k 2>/dev/null"); - if (-d '/dev/mapper'){ - @mapper = main::globber('/dev/mapper/*'); - } + main::set_mapper() if !$b_mapper; } else { # this is missing the file system data @@ -13051,14 +13562,14 @@ sub partition_data { #print "$_\n"; } } - - my @row = split /\s+/, $_; + my @row = split(/\s+/, $_); # autofs is a bsd thing, has size 0 if ($row[0] =~ /^($filters)$/ || $row[0] =~ /^ROOT/i || - ($b_fs && ($row[2] == 0 || $row[1] =~ /^(autofs|iso9660|tmpfs)$/ ) )){ + ($b_fs && ($row[2] == 0 || $row[1] =~ /^(autofs|devtmpfs|iso9660|tmpfs)$/ ) )){ next; } - ($dev_base,$dev_type,$fs,$id,$label,$type,$uuid) = ('','','','','',''); + ($dev_base,$dev_mapped,$dev_type,$fs,$id,$label, + $maj_min,$type,$uuid) = ('','','','','','','','',''); ($b_load,$block_size,$percent_used,$raw_size,$size_available, $size,$used) = (0,0,0,0,0,0,0,0); %part = (); @@ -13073,12 +13584,20 @@ sub partition_data { if ($row[0] =~ /by-label|by-uuid/){ $row[0] = Cwd::abs_path($row[0]); } - elsif ($row[0] =~ /mapper\// && @mapper){ - $row[0] = get_mapper($row[0],@mapper); + elsif ($row[0] =~ /mapper\// && %mapper){ + $dev_mapped = $row[0]; + $dev_mapped =~ s|^/.*/||; + $row[0] = $mapper{$dev_mapped} if $mapper{$dev_mapped}; + } + elsif ($row[0] =~ /\/dm-[0-9]+$/ && %dmmapper){ + my $temp = $row[0]; + $temp =~ s|^/.*/||; + $dev_mapped = $dmmapper{$temp}; } $dev_base = $row[0]; - $dev_base =~ s/^\/dev\///; - %part = check_lsblk($dev_base,0) if @lsblk; + $dev_base =~ s|^/.*/||; + %part = main::get_lsblk($dev_base) if @lsblk; + $maj_min = get_maj_min($dev_base) if @proc_partitions; } # this handles zfs type devices/partitions, which do not start with / but contain / # note: Main/jails/transmission_1 path can be > 1 deep @@ -13088,13 +13607,17 @@ sub partition_data { $dev_type = 'raid'; } # this handles yet another fredforfaen special case where a mounted drive - # has the search string in its name - if ($row[-1] =~ /^\/$|^\/boot$|^\/var$|^\/var\/tmp$|^\/var\/log$|^\/home$|^\/opt$|^\/tmp$|^\/usr$|^\/usr\/home$/){ + # has the search string in its name, includes / (| + if ($row[-1] =~ m%^/(|boot|boot/efi|home|opt|tmp|usr|usr/home|var|var/log|var/tmp)$% || + ($b_android && $row[-1] =~ /^\/(cache|data|firmware|system)$/)){ $b_load = 1; # note, older df in bsd do not have file system column $type = 'main'; } - elsif ($row[$cols] !~ /^\/$|^\/boot$|^\/var$|^\/var\/tmp$|^\/var\/log$|^\/home$|^\/opt$|^\/tmp$|^\/usr$|^\/usr\/home$|^filesystem/){ + # $cols in case where mount point has space in name, we only care about the first part + elsif ($row[$cols] !~ m%^\/(|boot|boot/efi|home|opt|tmp|usr|usr/home|var|var/log|var/tmp)$% && + $row[$cols] !~ /^filesystem/ && + !($b_android && $row[$cols] =~ /^\/(cache|data|firmware|system)$/)){ $b_load = 1; $type = 'secondary'; } @@ -13104,7 +13627,7 @@ sub partition_data { $fs = (%part && $part{'fs'}) ? $part{'fs'} : $row[1]; } else { - $fs = get_mounts_fs($row[0],@mount); + $fs = get_mounts_fs($row[0],\@mount); } if ($show{'label'}) { if (%part && $part{'label'}) { @@ -13124,7 +13647,7 @@ sub partition_data { } } else { - $fs = ($b_fs) ? $row[1]: get_mounts_fs($row[0],@mount); + $fs = ($b_fs) ? $row[1]: get_mounts_fs($row[0],\@mount); if (@gpart && ($show{'label'} || $show{'uuid'} ) ){ my @extra = get_bsd_label_uuid("$dev_base"); if (@extra){ @@ -13133,7 +13656,7 @@ sub partition_data { } } } - $id = join ' ', @row[$cols .. $#row]; + $id = join(' ', @row[$cols .. $#row]); $size = $row[$cols - $back_size]; if ($b_admin && -e "/sys/block/"){ @working = admin_data($blockdev,$dev_base,$size); @@ -13143,6 +13666,8 @@ sub partition_data { } $dev_base =~ s/\^\^/ /g if $b_space; if (!$dev_type){ + # need data set, this could maybe be converted to use + # dev-mapped and abspath but not without testing if ($dev_base =~ /^map:\/(.*)/){ $dev_type = 'mapped'; $dev_base = $1; @@ -13161,31 +13686,31 @@ sub partition_data { } } $used = $row[$cols - $back_used]; - $percent_used = sprintf( "%.1f", ( $used/$size )*100 ) if ($size && main::is_numeric($size) ); - @data = ({ + $percent_used = sprintf("%.1f", ( $used/$size )*100) if ($size && main::is_numeric($size) ); + push(@partitions,{ 'block-size' => $block_size, - 'id' => $id, 'dev-base' => $dev_base, + 'dev-mapped' => $dev_mapped, 'dev-type' => $dev_type, 'fs' => $fs, + 'id' => $id, 'label' => $label, - 'raw-size' => $raw_size, + 'maj-min' => $maj_min, + 'percent-used' => $percent_used, 'raw-available' => $size_available, + 'raw-size' => $raw_size, 'size' => $size, 'type' => $type, 'used' => $used, 'uuid' => $uuid, - 'percent-used' => $percent_used, }); - @partitions = (@partitions,@data); } } @data = swap_data(); - @partitions = (@partitions,@data); + push(@partitions,@data); # print Data::Dumper::Dumper \@partitions if $test[16]; if (!$bsd_type && @lsblk){ - @data = check_partition_data(); - @partitions = (@partitions,@data) if @data; + check_partition_data();# updates @partitions } main::log_data('dump','@partitions',\@partitions) if $b_log; print Data::Dumper::Dumper \@partitions if $test[16]; @@ -13197,9 +13722,9 @@ sub swap_data { return @swaps if $b_swaps; $b_swaps = 1; my (@data,@working); - my ($cache_pressure,$dev_base,$dev_type,$label,$mount,$path, - $pattern1,$pattern2,$percent_used,$priority,$size,$swap_type, - $swappiness,$used,$uuid); + my ($cache_pressure,$dev_base,$dev_mapped,$dev_type,$label,$maj_min, + $mount,$path,$pattern1,$pattern2,$percent_used,$priority,$size, + $swap_type,$swappiness,$used,$uuid); my ($s,$j,$size_id,$used_id) = (1,0,2,3); if (!$bsd_type){ # faster, avoid subshell, same as swapon -s @@ -13234,9 +13759,9 @@ sub swap_data { foreach (@working){ #next if ! /^\/dev/ || /^\/dev\/(ramzwap|zram)/; next if /^(Device|Filename)/; - ($dev_base,$dev_type,$label,$mount,$priority, - $swap_type,$uuid) = ('','','','',undef,'partition',''); - @data = split /\s+/, $_; + ($dev_base,$dev_mapped,$dev_type,$label,$maj_min,$mount,$priority, + $swap_type,$uuid) = ('','','','','','',undef,'partition',''); + @data = split(/\s+/, $_); if (/^\/dev\/(block\/)?(compcache|ramzwap|zram)/i){ $swap_type = 'zram'; $dev_type = 'dev'; @@ -13248,6 +13773,9 @@ sub swap_data { $swap_type = 'partition'; $dev_base = $data[0]; $dev_base =~ s|^/dev/||; + if (!$bsd_type && $dev_base =~ /^dm-/ && %dmmapper){ + $dev_mapped = $dmmapper{$dev_base}; + } if ($show{'label'} && @labels){ $label = get_label($data[0]); } @@ -13262,6 +13790,7 @@ sub swap_data { } } $dev_type = 'dev'; + $maj_min = get_maj_min($dev_base) if @proc_partitions; } elsif ($data[1] && $data[1] eq 'file' || m|^/|){ $swap_type = 'file'; @@ -13275,15 +13804,18 @@ sub swap_data { } $size = $data[$size_id]; $used = $data[$used_id]; - $percent_used = sprintf( "%.1f", ( $used/$size )*100 ); - @data = ({ + $percent_used = sprintf("%.1f", ( $used/$size )*100); + push(@swaps, { 'cache-pressure' => $cache_pressure, 'dev-base' => $dev_base, + 'dev-mapped' => $dev_mapped, 'dev-type' => $dev_type, 'fs' => 'swap', 'id' => "swap-$s", 'label' => $label, + 'maj-min' => $maj_min, 'mount' => $mount, + 'percent-used' => $percent_used, 'priority' => $priority, 'size' => $size, 'swappiness' => $swappiness, @@ -13291,9 +13823,7 @@ sub swap_data { 'swap-type' => $swap_type, 'used' => $used, 'uuid' => $uuid, - 'percent-used' => $percent_used, }); - @swaps = (@swaps,@data); $s++; } main::log_data('dump','@swaps',\@swaps) if $b_log; @@ -13305,13 +13835,13 @@ sub swap_advanced_data { eval $start if $b_log; my ($swappiness,$cache_pressure) = (undef,undef); if (-r "/proc/sys/vm/swappiness"){ - $swappiness = (main::reader("/proc/sys/vm/swappiness"))[0]; + $swappiness = main::reader("/proc/sys/vm/swappiness",'',0); if (defined $swappiness){ $swappiness .= ($swappiness == 60) ? ' (default)' : ' (default 60)' ; } } if (-r "/proc/sys/vm/vfs_cache_pressure"){ - $cache_pressure = (main::reader("/proc/sys/vm/vfs_cache_pressure"))[0]; + $cache_pressure = main::reader("/proc/sys/vm/vfs_cache_pressure",'',0); if (defined $cache_pressure){ $cache_pressure .= ($cache_pressure == 100) ? ' (default)' : ' (default 100)' ; } @@ -13321,14 +13851,14 @@ sub swap_advanced_data { } sub get_mounts_fs { eval $start if $b_log; - my ($item,@mount) = @_; + my ($item,$mount) = @_; $item =~ s/map:\/(\S+)/map $1/ if $bsd_type && $bsd_type eq 'darwin'; - return 'N/A' if ! @mount; + return 'N/A' if ! @$mount; my ($fs) = (''); # linux: /dev/sdb6 on /var/www/m type ext4 (rw,relatime,data=ordered) # /dev/sda3 on /root.dev/ugw type ext3 (rw,relatime,errors=continue,user_xattr,acl,barrier=1,data=journal) # bsd: /dev/ada0s1a on / (ufs, local, soft-updates) - foreach (@mount){ + foreach (@$mount){ if ($bsd_type && $_ =~ /^$item\son.*\(([^,\s\)]+)[,\s]*.*\)/){ $fs = $1; last; @@ -13351,7 +13881,7 @@ sub get_bsd_label_uuid { my ($item) = @_; my (@data,$b_found); foreach (@gpart){ - my @working = split /\s*:\s*/, $_; + my @working = split(/\s*:\s*/, $_); if ($_ =~ /^[0-9]+\.\sName:/ && $working[1] eq $item){ $b_found = 1; } @@ -13387,108 +13917,65 @@ sub set_label_uuid { } else { if ( my $path = main::check_program('gpart')){ - @gpart = main::grabber("$path list 2>/dev/null",'strip'); + @gpart = main::grabber("$path list 2>/dev/null",'','strip'); } } } eval $end if $b_log; } -sub set_lsblk { - eval $start if $b_log; - $b_lsblk = 1; - my (@temp,@working); - if (my $program = main::check_program('lsblk')){ - @working = main::grabber("$program -bP --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS 2>/dev/null"); - foreach (@working){ - if (/NAME="([^"]*)"\s+TYPE="([^"]*)"\s+RM="([^"]*)"\s+FSTYPE="([^"]*)"\s+SIZE="([^"]*)"\s+LABEL="([^"]*)"\s+UUID="([^"]*)"\s+SERIAL="([^"]*)"\s+MOUNTPOINT="([^"]*)"\s+PHY-SEC="([^"]*)"\s+LOG-SEC="([^"]*)"\s+PARTFLAGS="([^"]*)"/){ - my $size = ($5) ? $5/1024: 0; - # some versions of lsblk do not return serial, fs, uuid, or label - @temp = ({ - 'name' => $1, - 'type' => $2, - 'rm' => $3, - 'fs' => $4, - 'size' => $size, - 'label' => $6, - 'uuid' => $7, - 'serial' => $8, - 'mount' => $9, - 'block-physical' => $10, - 'block-logical' => $11, - 'partition-flags' => $12, - }); - @lsblk = (@lsblk,@temp); - } - } - } - #print Data::Dumper::Dumper \@lsblk; - main::log_data('dump','@lsblk',\@lsblk) if $b_log; - eval $end if $b_log; -} -sub check_lsblk { - eval $start if $b_log; - my ($name,$b_size) = @_; - my (%part); - foreach my $ref (@lsblk){ - my %row = %$ref; - next if ! $row{'name'}; - if ($name eq $row{'name'}){ - %part = %row; - last; - } - } - # print Data::Dumper::Dumper \%part; - main::log_data('dump','%part',\%part) if $b_log; - eval $end if $b_log; - return %part; -} + # handle cases of hidden file systems sub check_partition_data { eval $start if $b_log; - my ($b_found,@data,@temp); - # NOTE: these filters must match the fs filters in the main partition data sub!! + my ($b_found,$dev_mapped,$temp); + # NOTE: these filters must match the fs filters in sub partitiion_data!! my $fs_filters = 'aufs|cgmfs|configfs|devfs|devtmpfs|'; $fs_filters .= 'fdescfs|linprocfs|procfs|squashfs|swap|'; $fs_filters .= 'sysfs|tmpfs|unionfs'; - foreach my $ref (@lsblk){ - my %row = %$ref; + foreach my $row (@lsblk){ $b_found = 0; - if (!$row{'name'} || !$row{'mount'} || !$row{'type'} || - ($row{'fs'} && $row{'fs'} =~ /^($fs_filters)$/) || - ($row{'type'} =~ /^(disk|loop|rom)$/)){ + $dev_mapped = ''; + if (!$row->{'name'} || !$row->{'mount'} || !$row->{'type'} || + ($row->{'fs'} && $row->{'fs'} =~ /^($fs_filters)$/) || + ($row->{'type'} =~ /^(disk|loop|rom)$/)){ next; } - #print "$row{'name'} $row{'mount'}\n"; - foreach my $ref2 (@partitions){ - my %row2 = %$ref2; - #print "m:$row{'mount'} id:$row2{'id'}\n"; - next if !$row2{'id'}; - if ($row{'mount'} eq $row2{'id'}){ + #print "$row->{'name'} $row->{'mount'}\n"; + foreach my $row2 (@partitions){ + # print "m:$row->{'mount'} id:$row2->{'id'}\n"; + next if !$row2->{'id'}; + if ($row->{'mount'} eq $row2->{'id'}){ $b_found = 1; + if (%mapper && $mapper{$row->{'name'}}){ + $dev_mapped = $row->{'name'}; + $row->{'name'} = $mapper{$row->{'name'}}; + } last; } + #print "m:$row->{'mount'} id:$row2->{'id'}\n"; } if (!$b_found){ - #print "found: $row{'name'} $row{'mount'}\n"; - @temp = ({ - 'dev-base' => $row{'name'}, - 'fs' => $row{'fs'}, - 'id' => $row{'mount'}, + #print "found: $row->{'name'} $row->{'mount'}\n"; + $temp = { + 'dev-base' => $row->{'name'}, + 'dev-mapped' => $dev_mapped, + 'fs' => $row->{'fs'}, + 'id' => $row->{'mount'}, 'hidden' => 1, - 'label' => $row{'label'}, - 'raw-size' => $row{'size'}, + 'label' => $row->{'label'}, + 'maj-min' => $row->{'maj-min'}, + 'percent-used' => 0, + 'raw-size' => $row->{'size'}, 'size' => 0, 'type' => 'secondary', 'used' => 0, - 'uuid' => $row{'uuid'}, - 'percent-used' => 0, - }); - @partitions = (@partitions,@temp); - main::log_data('dump','lsblk check: @temp',\@temp) if $b_log; + 'uuid' => $row->{'uuid'}, + }; + push(@partitions,$temp); + main::log_data('dump','lsblk check: @temp',$temp) if $b_log; } } eval $end if $b_log; - return @data; } # args: 1: blockdev full path (part only); 2: block id; 3: size (part only) sub admin_data { @@ -13497,10 +13984,9 @@ sub admin_data { # 0: calc block 1: available percent 2: disk physical block size/partition block size; my @sizes = (0,0,0); my ($block_size,$percent,$size_raw) = (0,0,0); - foreach (@proc_partitions){ - my @row = split /\s+/, $_; - if ($row[-1] eq $id){ - $size_raw = $row[2]; + foreach my $row (@proc_partitions){ + if ($row->[-1] eq $id){ + $size_raw = $row->[2]; last; } } @@ -13518,6 +14004,19 @@ sub admin_data { eval $end if $b_log; return @sizes; } +sub get_maj_min { + eval $start if $b_log; + my ($id) = @_; + my ($maj_min,@working); + foreach my $row (@proc_partitions){ + if ($id eq $row->[-1]){ + $maj_min = $row->[0] . ':' . $row->[1]; + last; + } + } + eval $end if $b_log; + return $maj_min; +} sub get_label { eval $start if $b_log; my ($item) = @_; @@ -13535,24 +14034,6 @@ sub get_label { eval $end if $b_log; return $label; } -# args: $1 - dev item $2 - @mapper -# check for mapper, then get actual dev item if mapped -# /dev/mapper/ will usually be a symbolic link to the real /dev id -sub get_mapper { - eval $start if $b_log; - my ($item,@mapper) = @_; - my $mapped = ''; - foreach (@mapper){ - if ($item eq $_){ - my $temp = Cwd::abs_path($_); - $mapped = $temp if $temp; - last; - } - } - $mapped ||= $item; - eval $end if $b_log; - return $mapped; -} sub get_root { eval $start if $b_log; my ($path) = ('/dev/root'); @@ -13607,11 +14088,11 @@ sub get { if (@ps_aux){ if ($show{'ps-cpu'}){ @rows = cpu_processes(); - @processes = (@processes,@rows); + push(@processes,@rows); } if ($show{'ps-mem'}){ @rows = mem_processes(); - @processes = (@processes,@rows); + push(@processes,@rows); } } else { @@ -13619,7 +14100,7 @@ sub get { @rows = ({ main::key($num++,0,1,$key) => main::row_defaults('ps-data-null',''), },); - @processes = (@processes,@rows); + push(@processes,@rows); } eval $end if $b_log; return @processes; @@ -13631,8 +14112,8 @@ sub cpu_processes { my $count = ($b_irc)? 5: $ps_count; if ($ps_cols >= 10){ @rows = sort { - my @a = split(/\s+/,$a); - my @b = split(/\s+/,$b); + my @a = split(/\s+/, $a); + my @b = split(/\s+/, $b); $b[2] <=> $a[2] } @ps_aux; $pid_col = 1; } @@ -13651,12 +14132,12 @@ sub cpu_processes { my @data = ({ main::key($num++,1,1,'CPU top') => "$count$throttled" . ' of ' . scalar @ps_aux, },); - @processes = (@processes,@data); + push(@processes,@data); my $i = 1; foreach (@rows){ $num = 1; $j = scalar @processes; - my @row = split /\s+/, $_; + my @row = split(/\s+/, $_); my @command = process_starter(scalar @row, $row[$ps_cols],$row[$ps_cols + 1]); $cpu = ($ps_cols >= 10 ) ? $row[2] . '%': 'N/A'; @data = ({ @@ -13664,7 +14145,7 @@ sub cpu_processes { main::key($num++,0,3,'cpu') => $cpu, main::key($num++,1,3,'command') => $command[0], },); - @processes = (@processes,@data); + push(@processes,@data); if ($command[1]) { $processes[$j]{main::key($num++,0,4,'started by')} = $command[1]; } @@ -13672,7 +14153,7 @@ sub cpu_processes { $processes[$j]{main::key($num++,0,3,'pid')} = $pid; if ($extra > 0 && $ps_cols >= 10){ my $decimals = ($row[5]/1024 > 10 ) ? 1 : 2; - $mem = (defined $row[5]) ? sprintf( "%.${decimals}f", $row[5]/1024 ) . ' MiB' : 'N/A'; + $mem = (defined $row[5]) ? sprintf("%.${decimals}f", $row[5]/1024) . ' MiB' : 'N/A'; $mem .= ' (' . $row[3] . '%)'; $processes[$j]{main::key($num++,0,3,'mem')} = $mem; } @@ -13688,8 +14169,8 @@ sub mem_processes { my $count = ($b_irc)? 5: $ps_count; if ($ps_cols >= 10){ @rows = sort { - my @a = split(/\s+/,$a); - my @b = split(/\s+/,$b); + my @a = split(/\s+/, $a); + my @b = split(/\s+/, $b); $b[5] <=> $a[5] } @ps_aux; # 5 #$a[1] <=> $b[1] } @ps_aux; # 5 $pid_col = 1; @@ -13709,15 +14190,15 @@ sub mem_processes { @data = ({ main::key($num++,1,1,'Memory top') => "$count$throttled" . ' of ' . scalar @ps_aux, },); - @processes = (@processes,@data); + push(@processes,@data); my $i = 1; foreach (@rows){ $num = 1; $j = scalar @processes; - my @row = split /\s+/, $_; + my @row = split(/\s+/, $_); if ($ps_cols >= 10){ my $decimals = ($row[5]/1024 > 10 ) ? 1 : 2; - $mem = (main::is_int($row[5])) ? sprintf( "%.${decimals}f", $row[5]/1024 ) . ' MiB' : 'N/A'; + $mem = (main::is_int($row[5])) ? sprintf("%.${decimals}f", $row[5]/1024) . ' MiB' : 'N/A'; $mem .= " (" . $row[3] . "%)"; } else { @@ -13729,7 +14210,7 @@ sub mem_processes { main::key($num++,0,3,'mem') => $mem, main::key($num++,1,3,'command') => $command[0], },); - @processes = (@processes,@data); + push(@processes,@data); if ($command[1]) { $processes[$j]{main::key($num++,0,4,'started by')} = $command[1]; } @@ -13778,254 +14259,254 @@ sub throttled { { package RaidData; # debugger switches +my $b_lvm = 0; my $b_md = 0; my $b_zfs = 0; sub get { eval $start if $b_log; - my (@rows,$key1,$val1); + my (@data,@hardware_raid,@rows,$key1,$val1); my $num = 0; + @hardware_raid = hw_data() if $b_hardware_raid; raid_data() if !$b_raid; - #print 'get: ', Data::Dumper::Dumper \@raid; - if (!@raid && !@hardware_raid){ + #print 'get: ', Data::Dumper::Dumper \@lvm_raid; + #print 'get: ', Data::Dumper::Dumper \@md_raid; + #print 'get: ', Data::Dumper::Dumper \@zfs_raid; + if (!@lvm_raid && !@md_raid && !@zfs_raid && !@hardware_raid){ if ($show{'raid-forced'}){ $key1 = 'Message'; $val1 = main::row_defaults('raid-data'); } } else { - @rows = create_output(); + if (@hardware_raid){ + @data = create_output_hw(\@hardware_raid) ; + push(@rows,@data); + } + if (@lvm_raid){ + @data = create_output_lvm() ; + push(@rows,@data); + } + if (@md_raid){ + @data = create_output_md() ; + push(@rows,@data); + } + if (@zfs_raid){ + @data = create_output_zfs() ; + push(@rows,@data); + } } if (!@rows && $key1){ @rows = ({main::key($num++,0,1,$key1) => $val1,}); } eval $end if $b_log; - ($b_md,$b_zfs,@hardware_raid) = undef; + ($b_md,$b_zfs) = undef; return @rows; } -sub create_output { +sub create_output_hw { eval $start if $b_log; - my (@arrays,@arrays_holder,@components,@components_good,@data,@failed,@rows, - @sizes,@spare,@temp); - my ($allocated,$available,$blocks_avail,$chunk_raid,$component_string,$raid, - $ref2,$ref3,$report_size,$size,$status); - my ($b_row_1_sizes); - my ($cont_arr,$i,$ind_arr,$j,$num,$status_id) = (2,0,3,0,0,0); - #print Data::Dumper::Dumper \@raid; - if (@hardware_raid){ - foreach my $ref (@hardware_raid){ - my %row = %$ref; - $num = 1; - my $device = ($row{'device'}) ? $row{'device'}: 'N/A'; - my $driver = ($row{'driver'}) ? $row{'driver'}: 'N/A'; - @data = ({ - main::key($num++,1,1,'Hardware') => $device, - }); - @rows = (@rows,@data); - $j = scalar @rows - 1; - $rows[$j]{main::key($num++,0,2,'vendor')} = $row{'vendor'} if $row{'vendor'}; - $rows[$j]{main::key($num++,1,2,'driver')} = $driver; - if ($extra > 0){ - my $driver_version = ($row{'driver-version'}) ? $row{'driver-version'}: 'N/A' ; - $rows[$j]{main::key($num++,0,3,'v')} = $driver_version; - if ($extra > 2){ - my $port= ($row{'port'}) ? $row{'port'}: 'N/A' ; - $rows[$j]{main::key($num++,0,2,'port')} = $port; - } - my $bus_id = (defined $row{'bus-id'} && defined $row{'sub-id'}) ? "$row{'bus-id'}.$row{'sub-id'}": 'N/A' ; - $rows[$j]{main::key($num++,0,2,'bus ID')} = $bus_id; - } - if ($extra > 1){ - my $chip_id = (defined $row{'vendor-id'} && defined $row{'chip-id'}) ? "$row{'vendor-id'}.$row{'chip-id'}": 'N/A' ; - $rows[$j]{main::key($num++,0,2,'chip ID')} = $chip_id; - } - if ($extra > 2){ - my $rev= (defined $row{'rev'} && $row{'rev'}) ? $row{'rev'}: 'N/A' ; - $rows[$j]{main::key($num++,0,2,'rev')} = $rev; - } - } - } - if ($extra > 2 && $raid[0]{'system-supported'}){ - @data = ({ - main::key($num++,0,1,'Supported md-raid types') => $raid[0]{'system-supported'}, - }); - @rows = (@rows,@data); - } - foreach my $ref (@raid){ - $j = scalar @rows; - my %row = %$ref; - $b_row_1_sizes = 0; - next if !%row; + my ($hardware_raid) = @_; + my (@rows); + my ($j,$num) = (0,0); + foreach my $row (@$hardware_raid){ $num = 1; - @data = ({ - main::key($num++,1,1,'Device') => $row{'id'}, - main::key($num++,0,2,'type') => $row{'type'}, - main::key($num++,0,2,'status') => $row{'status'}, + my $device = ($row->{'device'}) ? $row->{'device'}: 'N/A'; + my $driver = ($row->{'driver'}) ? $row->{'driver'}: 'N/A'; + push(@rows, { + main::key($num++,1,1,'Hardware') => $device, }); - @rows = (@rows,@data); - if ($row{'type'} eq 'mdraid'){ - $blocks_avail = 'blocks'; - $chunk_raid = 'chunk size'; - $report_size = 'report'; - if ($extra > 0){ - $available = ($row{'blocks'}) ? $row{'blocks'} : 'N/A'; - } - $size = ($row{'report'}) ? $row{'report'}: ''; - $size .= " $row{'u-data'}" if $size; - $size ||= 'N/A'; - $status_id = 2; - } - else { - $blocks_avail = 'free'; - $chunk_raid = 'allocated'; - $report_size = 'size'; - @sizes = ($row{'size'}) ? main::get_size($row{'size'}) : (); - $size = (@sizes) ? "$sizes[0] $sizes[1]" : ''; - @sizes = ($row{'free'}) ? main::get_size($row{'free'}) : (); - $available = (@sizes) ? "$sizes[0] $sizes[1]" : ''; + $j = scalar @rows - 1; + $rows[$j]{main::key($num++,0,2,'vendor')} = $row->{'vendor'} if $row->{'vendor'}; + $rows[$j]{main::key($num++,1,2,'driver')} = $driver; + if ($extra > 0){ + my $driver_version = ($row->{'driver-version'}) ? $row->{'driver-version'}: 'N/A' ; + $rows[$j]{main::key($num++,0,3,'v')} = $driver_version; if ($extra > 2){ - @sizes = ($row{'allocated'}) ? main::get_size($row{'allocated'}) : (); - $allocated = (@sizes) ? "$sizes[0] $sizes[1]" : ''; + my $port= ($row->{'port'}) ? $row->{'port'}: 'N/A' ; + $rows[$j]{main::key($num++,0,2,'port')} = $port; } - $status_id = 1; + my $bus_id = (defined $row->{'bus-id'} && defined $row->{'sub-id'}) ? "$row->{'bus-id'}.$row->{'sub-id'}": 'N/A' ; + $rows[$j]{main::key($num++,0,2,'bus ID')} = $bus_id; } - $ref2 = $row{'arrays'}; - @arrays = @$ref2; - @arrays = grep {defined $_} @arrays; - @arrays_holder = @arrays; - if (($row{'type'} eq 'mdraid' && $extra == 0 ) || !defined $arrays[0]{'raid'} ){ - $raid = (defined $arrays[0]{'raid'}) ? $arrays[0]{'raid'}: 'no-raid'; - $rows[$j]{main::key($num++,0,2,'raid')} = $raid; + if ($extra > 1){ + my $chip_id = (defined $row->{'vendor-id'} && defined $row->{'chip-id'}) ? "$row->{'vendor-id'}.$row->{'chip-id'}": 'N/A' ; + $rows[$j]{main::key($num++,0,2,'chip ID')} = $chip_id; } - if ( ( $row{'type'} eq 'zfs' || ($row{'type'} eq 'mdraid' && $extra == 0 ) ) && $size){ - #print "here 0\n"; - $rows[$j]{main::key($num++,0,2,$report_size)} = $size; - $size = ''; - $b_row_1_sizes = 1; + if ($extra > 2){ + my $rev= (defined $row->{'rev'} && $row->{'rev'}) ? $row->{'rev'}: 'N/A' ; + $rows[$j]{main::key($num++,0,2,'rev')} = $rev; } - if ( $row{'type'} eq 'zfs' && $available){ - $rows[$j]{main::key($num++,0,2,$blocks_avail)} = $available; - $available = ''; - $b_row_1_sizes = 1; + } + eval $end if $b_log; + #print Data::Dumper::Dumper \@rows; + return @rows; +} +sub create_output_lvm { + eval $start if $b_log; + my (@components,@components_good,@components_meta,@rows); + my ($size); + my ($j,$num) = (0,0); + foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @lvm_raid){ + $j = scalar @rows; + push(@rows, { + main::key($num++,1,1,'Device') => $row->{'id'}, + }); + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,2,'maj-min')} = $row->{'maj-min'}; } - if ( $row{'type'} eq 'zfs' && $allocated){ - $rows[$j]{main::key($num++,0,2,$chunk_raid)} = $allocated; - $allocated = ''; + $rows[$j]{main::key($num++,0,2,'type')} = $row->{'type'}; + $rows[$j]{main::key($num++,0,2,'level')} = $row->{'level'}; + $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string'): 'N/A'; + $rows[$j]{main::key($num++,0,2,'size')} = $size; + if ($row->{'raid-sync'}){ + $rows[$j]{main::key($num++,0,2,'sync')} = $row->{'raid-sync'}; } - $i = 0; - my $count = scalar @arrays; - foreach $ref3 (@arrays){ - my %row2 = %$ref3; - ($cont_arr,$ind_arr) = (2,3); - if ($count > 1){ - ($cont_arr,$ind_arr) = (3,4); - $j = scalar @rows; - $num = 1; - @sizes = ($row2{'size'}) ? main::get_size($row2{'size'}) : (); - $size = (@sizes) ? "$sizes[0] $sizes[1]" : 'N/A'; - @sizes = ($row2{'free'}) ? main::get_size($row2{'free'}) : (); - $available = (@sizes) ? "$sizes[0] $sizes[1]" : ''; - $raid = (defined $row2{'raid'}) ? $row2{'raid'}: 'no-raid'; - $status = ($row2{'status'}) ? $row2{'status'}: 'N/A'; - @data = ({ - main::key($num++,1,2,'Array') => $raid, - main::key($num++,0,3,'status') => $status, - main::key($num++,0,3,'size') => $size, - main::key($num++,0,3,'free') => $available, - }); - @rows = (@rows,@data); - } - # items like cache may have one component, with a size on that component - elsif (!$b_row_1_sizes && $row{'type'} eq 'zfs'){ - #print "here $count\n"; - @sizes = ($row2{'size'}) ? main::get_size($row2{'size'}) : (); - $size = (@sizes) ? "$sizes[0] $sizes[1]" : ''; - @sizes = ($row2{'free'}) ? main::get_size($row2{'free'}) : (); - $available = (@sizes) ? "$sizes[0] $sizes[1]" : ''; - $rows[$j]{main::key($num++,0,2,'size')} = $size; - $rows[$j]{main::key($num++,0,2,'free')} = $available; - if ($extra > 2){ - @sizes = ($row{'allocated'}) ? main::get_size($row2{'allocated'}) : (); - $allocated = (@sizes) ? "$sizes[0] $sizes[1]" : ''; - if ($allocated){ - $rows[$j]{main::key($num++,0,2,$chunk_raid)} = $allocated; - } - } - } - $ref3 = $row2{'components'}; - @components = (ref $ref3 eq 'ARRAY') ? @$ref3 : (); - @failed = (); - @spare = (); - @components_good = (); - # @spare = split(/\s+/, $row{'unused'}) if $row{'unused'}; - foreach my $item (@components){ - @temp = split /~/, $item; - if (defined $temp[$status_id] && $temp[$status_id] =~ /^(F|DEGRADED|FAULTED|UNAVAIL)$/){ - $temp[0] = "$temp[0]~$temp[1]" if $status_id == 2; - push @failed, $temp[0]; - } - elsif (defined $temp[$status_id] && $temp[$status_id] =~ /(S|OFFLINE)$/){ - $temp[0] = "$temp[0]~$temp[1]" if $status_id == 2; - push @spare, $temp[0]; - } - else { - $temp[0] = ($status_id == 2) ? "$temp[0]~$temp[1]" : $temp[0]; - push @components_good, $temp[0]; - } - } - $component_string = (@components_good) ? join ' ', @components_good : 'N/A'; - $rows[$j]{main::key($num++,1,$cont_arr,'Components')} = ''; - $rows[$j]{main::key($num++,0,$ind_arr,'online')} = $component_string; - if (@failed){ - $rows[$j]{main::key($num++,0,$ind_arr,'FAILED')} = join ' ', @failed; - } - if (@spare){ - $rows[$j]{main::key($num++,0,$ind_arr,'spare')} = join ' ', @spare; - } - if ($row{'type'} eq 'mdraid' && $extra > 0 ){ - $j = scalar @rows; - $num = 1; - #print Data::Dumper::Dumper \@arrays_holder; - $rows[$j]{main::key($num++,1,$cont_arr,'Info')} = ''; - $raid = (defined $arrays_holder[0]{'raid'}) ? $arrays_holder[0]{'raid'}: 'no-raid'; - $rows[$j]{main::key($num++,0,$ind_arr,'raid')} = $raid; - $rows[$j]{main::key($num++,0,$ind_arr,$blocks_avail)} = $available; - if ($size){ - $rows[$j]{main::key($num++,0,$ind_arr,$report_size)} = $size; - } - my $chunk = ($row{'chunk-size'}) ? $row{'chunk-size'}: 'N/A'; - $rows[$j]{main::key($num++,0,$ind_arr,$chunk_raid)} = $chunk; - if ($extra > 1){ - if ($row{'bitmap'}){ - $rows[$j]{main::key($num++,0,$ind_arr,'bitmap')} = $row{'bitmap'}; - } - if ($row{'super-block'}){ - $rows[$j]{main::key($num++,0,$ind_arr,'super blocks')} = $row{'super-block'}; - } - if ($row{'algorithm'}){ - $rows[$j]{main::key($num++,0,$ind_arr,'algorithm')} = $row{'algorithm'}; - } - } - } - $i++; - } - if ($row{'recovery-percent'}){ + + if ($extra > 0){ $j = scalar @rows; $num = 1; - my $percent = $row{'recovery-percent'}; - if ($extra > 1 && $row{'progress-bar'}){ - $percent .= " $row{'progress-bar'}" + $rows[$j]{main::key($num++,1,2,'Info')} = ''; + if (defined $row->{'stripes'}){ + $rows[$j]{main::key($num++,0,3,'stripes')} = $row->{'stripes'}; } - $rows[$j]{main::key($num++,1,$cont_arr,'Recovering')} = $percent; - my $finish = ($row{'recovery-finish'})?$row{'recovery-finish'} : 'N/A'; - $rows[$j]{main::key($num++,0,$ind_arr,'time remaining')} = $finish; - if ($extra > 0){ - if ($row{'sectors-recovered'}){ - $rows[$j]{main::key($num++,0,$ind_arr,'sectors')} = $row{'sectors-recovered'}; + if (defined $row->{'raid-mismatches'} && ($extra > 1 || $row->{'raid-mismatches'} > 0 )){ + $rows[$j]{main::key($num++,0,3,'mismatches')} = $row->{'raid-mismatches'}; + } + if (defined $row->{'copy-percent'} && ($extra > 1 || $row->{'copy-percent'} < 100)){ + $rows[$j]{main::key($num++,0,3,'copied')} = ($row->{'copy-percent'} + 0) . '%'; + } + if ($row->{'vg'}){ + $rows[$j]{main::key($num++,1,3,'v-group')} = $row->{'vg'}; + } + $size = ($row->{'vg-size'}) ? main::get_size($row->{'vg-size'},'string') : 'N/A'; + $rows[$j]{main::key($num++,0,4,'vg-size')} = $size; + $size = ($row->{'vg-free'}) ? main::get_size($row->{'vg-free'},'string') : 'N/A'; + $rows[$j]{main::key($num++,0,4,'vg-free')} = $size; + } + @components = (ref $row->{'components'} eq 'ARRAY') ? @{$row->{'components'}} : (); + @components_good = (); + @components_meta = (); + foreach my $item (sort { $a->[0] cmp $b->[0]} @components){ + if ($item->[4] =~ /_rmeta/){ + push(@components_meta, $item); + } + else { + push(@components_good, $item); + } + } + $j = scalar @rows; + $rows[$j]{main::key($num++,1,2,'Components')} = ''; + my $b_bump; + create_components_output('lvm','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + create_components_output('lvm','Meta',\@rows,\@components_meta,\$j,\$num,\$b_bump); + } + eval $end if $b_log; + #print Data::Dumper::Dumper \@rows; + return @rows; +} +sub create_output_md { + eval $start if $b_log; + my (@components,@components_good,@failed,@rows,@spare,@temp); + my ($blocks,$chunk,$level,$report,$size,$status); + my ($j,$num) = (0,0); + #print Data::Dumper::Dumper \@md_raid; + if ($extra > 2 && $md_raid[0]->{'system-supported'}){ + push(@rows, { + main::key($num++,0,1,'System supports mdraid') => $md_raid[0]->{'system-supported'}, + }); + } + foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @md_raid){ + $j = scalar @rows; + next if !%$row; + $num = 1; + $level = (defined $row->{'level'}) ? $row->{'level'} : 'no-raid'; + push(@rows, { + main::key($num++,1,1,'Device') => $row->{'id'}, + }); + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,2,'maj-min')} = $row->{'maj-min'}; + } + $rows[$j]{main::key($num++,0,2,'type')} = $row->{'type'}; + $rows[$j]{main::key($num++,0,2,'level')} = $level; + $rows[$j]{main::key($num++,0,2,'status')} = $row->{'status'}; + if ($row->{'details'}{'state'}){ + $rows[$j]{main::key($num++,0,2,'state')} = $row->{'details'}{'state'}; + } + if ($row->{'size'}){ + $size = main::get_size($row->{'size'},'string'); + } + else { + $size = (!$b_root && !@lsblk) ? main::row_defaults('root-required'): 'N/A'; + } + $rows[$j]{main::key($num++,0,2,'size')} = $size; + $report = ($row->{'report'}) ? $row->{'report'}: ''; + $report .= " $row->{'u-data'}" if $report; + $report ||= 'N/A'; + if ($extra == 0){ + #print "here 0\n"; + $rows[$j]{main::key($num++,0,2,'report')} = $report; + } + if ($extra > 0){ + $j = scalar @rows; + $num = 1; + $rows[$j]{main::key($num++,1,2,'Info')} = ''; + #$rows[$j]{main::key($num++,0,3,'raid')} = $raid; + $rows[$j]{main::key($num++,0,3,'report')} = $report; + $blocks = ($row->{'blocks'}) ? $row->{'blocks'} : 'N/A'; + $rows[$j]{main::key($num++,0,3,'blocks')} = $blocks; + $chunk = ($row->{'chunk-size'}) ? $row->{'chunk-size'} : 'N/A'; + $rows[$j]{main::key($num++,0,3,'chunk size')} = $chunk; + if ($extra > 1){ + if ($row->{'bitmap'}){ + $rows[$j]{main::key($num++,0,3,'bitmap')} = $row->{'bitmap'}; + } + if ($row->{'super-block'}){ + $rows[$j]{main::key($num++,0,3,'super blocks')} = $row->{'super-block'}; + } + if ($row->{'algorithm'}){ + $rows[$j]{main::key($num++,0,3,'algorithm')} = $row->{'algorithm'}; } } - if ($extra > 1 && $row{'recovery-speed'}){ - $rows[$j]{main::key($num++,0,$ind_arr,'speed')} = $row{'recovery-speed'}; + } + @components = (ref $row->{'components'} eq 'ARRAY') ? @{$row->{'components'}} : (); + @failed = (); + @spare = (); + @components_good = (); + # @spare = split(/\s+/, $row->{'unused'}) if $row->{'unused'}; + foreach my $item (sort { $a->[1] <=> $b->[1]} @components){ + if (defined $item->[2] && $item->[2] =~ /^(F|DEGRADED|FAULTED|UNAVAIL)$/){ + push(@failed, $item); + } + elsif (defined $item->[2] && $item->[2] =~ /(S|OFFLINE)$/){ + push(@spare, $item); + } + else { + push(@components_good, $item); + } + } + $j = scalar @rows; + $rows[$j]{main::key($num++,1,2,'Components')} = ''; + my $b_bump; + create_components_output('mdraid','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + create_components_output('mdraid','FAILED',\@rows,\@failed,\$j,\$num,\$b_bump); + create_components_output('mdraid','Spare',\@rows,\@spare,\$j,\$num,\$b_bump); + if ($row->{'recovery-percent'}){ + $j = scalar @rows; + $num = 1; + my $percent = $row->{'recovery-percent'}; + if ($extra > 1 && $row->{'progress-bar'}){ + $percent .= " $row->{'progress-bar'}" + } + $rows[$j]{main::key($num++,1,2,'Recovering')} = $percent; + my $finish = ($row->{'recovery-finish'})?$row->{'recovery-finish'} : 'N/A'; + $rows[$j]{main::key($num++,0,3,'time remaining')} = $finish; + if ($extra > 0){ + if ($row->{'sectors-recovered'}){ + $rows[$j]{main::key($num++,0,3,'sectors')} = $row->{'sectors-recovered'}; + } + } + if ($extra > 1 && $row->{'recovery-speed'}){ + $rows[$j]{main::key($num++,0,3,'speed')} = $row->{'recovery-speed'}; } } } @@ -14033,23 +14514,182 @@ sub create_output { #print Data::Dumper::Dumper \@rows; return @rows; } + +sub create_output_zfs { + eval $start if $b_log; + my (@arrays,@arrays_holder,@components,@components_good,@failed,@rows,@spare); + my ($allocated,$available,$level,$size,$status); + my ($b_row_1_sizes); + my ($j,$num) = (0,0); + #print Data::Dumper::Dumper \@zfs_raid; + foreach my $row (sort {$a->{'id'} cmp $b->{'id'}} @zfs_raid){ + $j = scalar @rows; + $b_row_1_sizes = 0; + next if !%$row; + $num = 1; + push(@rows, { + main::key($num++,1,1,'Device') => $row->{'id'}, + main::key($num++,0,2,'type') => $row->{'type'}, + main::key($num++,0,2,'status') => $row->{'status'}, + }); + $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : ''; + $available = main::get_size($row->{'free'},'string',''); # could be zero free + if ($extra > 2){ + $allocated = ($row->{'allocated'}) ? main::get_size($row->{'allocated'},'string') : ''; + } + @arrays = @{$row->{'arrays'}}; + @arrays = grep {defined $_} @arrays; + @arrays_holder = @arrays; + if (!defined $arrays[0]{'level'} ){ + $level = 'no-raid'; + $rows[$j]{main::key($num++,0,2,'level')} = $level; + } + if ($size){ + #print "here 0\n"; + $rows[$j]{main::key($num++,0,2,'size')} = $size; + $size = ''; + $b_row_1_sizes = 1; + } + if ($available){ + $rows[$j]{main::key($num++,0,2,'free')} = $available; + $available = ''; + $b_row_1_sizes = 1; + } + if ($allocated){ + $rows[$j]{main::key($num++,0,2,'allocated')} = $allocated; + $allocated = ''; + } + my $count = scalar @arrays; + foreach my $row2 (@arrays){ + if ($count > 1){ + $j = scalar @rows; + $num = 1; + $size = ($row2->{'size'}) ? main::get_size($row2->{'size'},'string') : 'N/A'; + $available = ($row2->{'free'}) ? main::get_size($row2->{'free'},'string') : 'N/A'; + $level = (defined $row2->{'level'}) ? $row2->{'level'}: 'no-raid'; + $status = ($row2->{'status'}) ? $row2->{'status'}: 'N/A'; + push(@rows, { + main::key($num++,1,2,'Array') => $level, + main::key($num++,0,3,'status') => $status, + main::key($num++,0,3,'size') => $size, + main::key($num++,0,3,'free') => $available, + }); + } + # items like cache may have one component, with a size on that component + elsif (!$b_row_1_sizes){ + #print "here $count\n"; + $size = ($row2->{'size'}) ? main::get_size($row2->{'size'},'string') : 'N/A'; + $available = ($row2->{'free'}) ? main::get_size($row2->{'free'},'string') : 'N/A'; + $rows[$j]{main::key($num++,0,2,'size')} = $size; + $rows[$j]{main::key($num++,0,2,'free')} = $available; + if ($extra > 2){ + $allocated = ($row->{'allocated'}) ? main::get_size($row2->{'allocated'},'string') : ''; + if ($allocated){ + $rows[$j]{main::key($num++,0,2,'allocated')} = $allocated; + } + } + } + @components = (ref $row2->{'components'} eq 'ARRAY') ? @{$row2->{'components'}} : (); + @failed = (); + @spare = (); + @components_good = (); + # @spare = split(/\s+/, $row->{'unused'}) if $row->{'unused'}; + foreach my $item (sort { $a->[0] cmp $b->[0]} @components){ + if (defined $item->[3] && $item->[3] =~ /^(DEGRADED|FAULTED|UNAVAIL)$/){ + push(@failed, $item); + } + elsif (defined $item->[3] && $item->[3] =~ /(AVAIL|OFFLINE|REMOVED)$/){ + push(@spare, $item); + } + # note: spares in use show: INUSE but technically it's still a spare, + # but since it's in use, consider it online. + else { + push(@components_good, $item); + } + } + $j = scalar @rows; + $rows[$j]{main::key($num++,1,3,'Components')} = ''; + my $b_bump; + create_components_output('zfs','Online',\@rows,\@components_good,\$j,\$num,\$b_bump); + create_components_output('zfs','FAILED',\@rows,\@failed,\$j,\$num,\$b_bump); + create_components_output('zfs','Available',\@rows,\@spare,\$j,\$num,\$b_bump); + } + } + eval $end if $b_log; + #print Data::Dumper::Dumper \@rows; + return @rows; +} + +## Most key stuff passed by ref, and is changed on the fly +sub create_components_output { + eval $start if $b_log; + my ($type,$item,$rows_ref,$array_ref,$j_ref,$num_ref,$b_bump_ref) = @_; + my ($extra1,$extra2,$f1,$f2,$f3,$f4,$f5,$k,$k1,$key1,$l1,$l2,$l3); + return if !@$array_ref && $item ne 'Online'; + if ($type eq 'lvm'){ + ($f1,$f2,$f3,$f4,$f5,$l1,$l2,$l3) = (1,2,3,4,5,3,4,5); + $k = 1; + $extra1 = 'mapped'; + $extra2 = 'dev'; + } + elsif ($type eq 'mdraid'){ + ($f1,$f2,$f3,$f4,$k1,$l1,$l2,$l3) = (3,4,5,6,1,3,4,5); + $extra1 = 'mapped'; + } + elsif ($type eq 'zfs'){ + ($f1,$f2,$f3,$l1,$l2,$l3) = (1,2,3,4,5,6); + $k = 1; + } + $$j_ref++ if $$b_bump_ref; + $$b_bump_ref = 0; + my $good = ($item eq 'Online' && !@$array_ref ) ? 'N/A' : ''; + $$rows_ref[$$j_ref]{main::key($$num_ref++,1,$l1,$item)} = $good; + foreach my $device (@$array_ref){ + next if ref $device ne 'ARRAY'; + if ($b_admin && $device->[$f1] && $device->[$f2]){ + $$j_ref++; + $$b_bump_ref = 1; + $$num_ref = 1; + } + $key1 = (defined $k1) ? $device->[$k1] : $k++; + $$rows_ref[$$j_ref]{main::key($$num_ref++,1,$l2,$key1)} = $device->[0]; + if ($b_admin && $device->[$f2]){ + $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,'maj-min')} = $device->[$f2]; + } + if ($b_admin && $device->[$f1]){ + my $size = ($device->[$f1]) ? main::get_size($device->[$f1],'string') : 'N/A'; + $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,'size')} = $size; + } + if ($b_admin && $device->[$f3]){ + $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,'state')} = $device->[$f3]; + } + if ($b_admin && $extra1 && $device->[$f4]){ + $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,$extra1)} = $device->[$f4]; + } + if ($b_admin && $extra2 && $device->[$f5]){ + $$rows_ref[$$j_ref]{main::key($$num_ref++,0,$l3,$extra2)} = $device->[$f5]; + } + } + eval $end if $b_log; +} + sub raid_data { eval $start if $b_log; + main::set_lsblk() if !$bsd_type && !$b_lsblk; + main::set_mapper() if !$bsd_type && !$b_mapper; + main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; my (@data); $b_raid = 1; - if ($b_hardware_raid){ - hardware_raid(); + if (($b_fake_raid && $b_lvm) || + ($alerts{'lvs'}->{'action'} && $alerts{'lvs'}->{'action'} eq 'use')){ + @lvm_raid = lvm_data(); } - if ($b_md || (my $file = main::system_files('mdstat') )){ - @data = mdraid_data($file); - @raid = (@raid,@data) if @data; + if (($b_fake_raid && $b_md) || (my $file = main::system_files('mdstat') )){ + @md_raid = md_data($file); } - if ($b_zfs || (my $path = main::check_program('zpool') )){ - @data = zfs_data($path); - @raid = (@raid,@data) if @data; + if (($b_fake_raid && $b_zfs) || (my $path = main::check_program('zpool') )){ + @zfs_raid = zfs_data($path); } - main::log_data('dump','@raid',\@raid) if $b_log; - #print Data::Dumper::Dumper \@raid; eval $end if $b_log; } # 0 type @@ -14063,55 +14703,115 @@ sub raid_data { # 8 port # 9 driver # 10 modules -sub hardware_raid { +sub hw_data { eval $start if $b_log; - my ($driver,$vendor,@data,@working); - foreach my $ref (@devices_hwraid){ - @working = @$ref; - $driver = ($working[9]) ? lc($working[9]): ''; + my ($driver,$vendor,@hardware_raid); + foreach my $working (@devices_hwraid){ + $driver = ($working->[9]) ? lc($working->[9]): ''; $driver =~ s/-/_/g if $driver; my $driver_version = ($driver) ? main::get_module_version($driver): ''; - if ($extra > 2 && $b_pci_tool && $working[11]){ - $vendor = main::get_pci_vendor($working[4],$working[11]); + if ($extra > 2 && $b_pci_tool && $working->[11]){ + $vendor = main::get_pci_vendor($working->[4],$working->[11]); } - @data = ({ - 'bus-id' => $working[2], - 'chip-id' => $working[6], - 'device' => $working[4], + push(@hardware_raid, { + 'bus-id' => $working->[2], + 'chip-id' => $working->[6], + 'device' => $working->[4], 'driver' => $driver, 'driver-version' => $driver_version, - 'port' => $working[8], - 'rev' => $working[7], - 'sub-id' => $working[3], - 'vendor-id' => $working[5], + 'port' => $working->[8], + 'rev' => $working->[7], + 'sub-id' => $working->[3], + 'vendor-id' => $working->[5], 'vendor' => $vendor, }); - @hardware_raid = (@hardware_raid,@data); } # print Data::Dumper::Dumper \@hardware_raid; main::log_data('dump','@hardware_raid',\@hardware_raid) if $b_log; eval $end if $b_log; + return @hardware_raid; } -sub mdraid_data { +sub lvm_data { + eval $start if $b_log; + LogicalData::lvm_data() if !$b_lvm_data; + return if !@lvm; + my (@lvraid,$maj_min,$vg_used,@working); + foreach my $item (@lvm){ + next if $item->{'segtype'} !~ /^raid/; + my (@components,$dev,$maj_min,$vg_used); + #print Data::Dumper::Dumper $item; + if ($item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}){ + $maj_min = $item->{'lv_kernel_major'} . ':' . $item->{'lv_kernel_minor'}; + } + if (defined $item->{'vg_free'} && defined $item->{'vg_size'}){ + $vg_used = ($item->{'vg_size'} - $item->{'vg_free'}); + } + $raw_logical[0] += $item->{'lv_size'} if $item->{'lv_size'}; + @working = main::globber("/sys/dev/block/$maj_min/slaves/*") if $maj_min; + @working = map {$_ =~ s|^/.*/||; $_;} @working if @working; + foreach my $part (@working){ + my (@data,$dev,$maj_min,$mapped,$size); + if (@proc_partitions){ + @data = main::get_proc_partition($part); + $maj_min = $data[0] . ':' . $data[1] if defined $data[1]; + $size = $data[2]; + $raw_logical[1] += $size if $part =~ /^dm-/ && $size; + @data = main::globber("/sys/dev/block/$maj_min/slaves/*") if $maj_min; + @data = map {$_ =~ s|^/.*/||; $_;} @data if @data; + $dev = join(',', @data) if @data; + } + $mapped = $dmmapper{$part} if %dmmapper; + push(@components, [$part,$size,$maj_min,undef,$mapped,$dev],); + } + if ($item->{'segtype'}){ + if ($item->{'segtype'} eq 'raid1'){$item->{'segtype'} = 'mirror';} + else {$item->{'segtype'} =~ s/^raid([0-9]+)/raid-$1/; } + } + push(@lvraid, { + 'components' => \@components, + 'copy-percent' => $item->{'copy_percent'}, + 'id' => $item->{'lv_name'}, + 'level' => $item->{'segtype'}, + 'maj-min' => $maj_min, + 'raid-mismatches' => $item->{'raid_mismatch_count'}, + 'raid-sync' => $item->{'raid_sync_action'}, + 'size' => $item->{'lv_size'}, + 'stripes' => $item->{'stripes'}, + 'type' => $item->{'vg_fmt'}, + 'vg' => $item->{'vg_name'}, + 'vg-free' => $item->{'vg_free'}, + 'vg-size' => $item->{'vg_size'}, + 'vg-used' => $vg_used, + }); + } + + # print Data::Dumper::Dumper \@lvraid; + main::log_data('dump','@lvraid',\@lvraid) if $b_log; + eval $end if $b_log; + return @lvraid; +} +sub md_data { eval $start if $b_log; my ($mdstat) = @_; my $j = 0; - #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-4-device-1.txt"; - #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-rebuild-1.txt"; - #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-mirror-fserver2-1.txt"; - #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-raid10-abucodonosor.txt"; - #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-raid10-ant.txt"; + if ($b_fake_raid) { + #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-4-device-1.txt"; + #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-rebuild-1.txt"; + #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-mirror-fserver2-1.txt"; + #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-raid10-abucodonosor.txt"; + #$mdstat = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/md-2-raid10-ant.txt"; + } my @working = main::reader($mdstat,'strip'); #print Data::Dumper::Dumper \@working; - my (@data,@mdraid,@temp,$b_found,$system,$unused); + my (@mdraid,@temp,$b_found,$system,$unused); # NOTE: a system with empty mdstat will still show these values if ($working[0] && $working[0] =~ /^Personalities/){ - $system = ( split /:\s*/, $working[0])[1]; + $system = ( split(/:\s*/, $working[0]))[1]; $system =~ s/\[|\]//g if $system; shift @working; } if ($working[-1] && $working[-1] =~ /^used\sdevices/){ - $unused = ( split /:\s*/, $working[0])[1]; + $unused = ( split(/:\s*/, $working[0]))[1]; $unused =~ s/<|>|none//g if $unused; pop @working; } @@ -14122,33 +14822,72 @@ sub mdraid_data { if (/^(md[0-9]+)\s*:\s*([^\s]+)(\s\([^)]+\))?\s([^\s]+)\s(.*)/){ my $id = $1; my $status = $2; - my $raid = $4; + my $level = $4; my $component_string = $5; + my (@components,%details,%device,$maj_min,@part,$size); @temp = (); - $raid =~ s/^raid1$/mirror/; - $raid =~ s/^raid/raid-/; - $raid = 'mirror' if $raid eq '1'; - # remember, these include the [x] id, so remove that for disk/unmounted - my @components = split /\s+/, $component_string; - foreach my $component (@components){ - $component =~ /([\S]+)\[([0-9]+)\]\(?([SF])?\)?/; - my $string = "$1~"; - $string .= (defined $2) ? "c$2" : ''; - $string .= (defined $3) ? "~$3" : ''; - push @temp, $string; + $level =~ s/^raid1$/mirror/; + $level =~ s/^raid/raid-/; + $level = 'mirror' if $level eq '1'; + # cascade of tests, light to cpu intense + if ((!$maj_min || !$size) && @proc_partitions){ + @part = main::get_proc_partition($id); + if (@part){ + $maj_min = $part[0] . ':' . $part[1]; + $size = $part[2]; + } + } + if ((!$maj_min || !$size) && @lsblk){ + %device = main::get_lsblk($id) if @lsblk; + $maj_min = $device{'maj-min'} if $device{'maj-min'}; + $size = $device{'size'} if $device{'size'}; + } + if ((!$size || $b_admin) && $alerts{'mdadm'}->{'action'} eq 'use'){ + %details = md_details($id); + $size = $details{'size'} if $details{'size'}; + } + $raw_logical[0] += $size if $size; + # remember, these include the [x] id, so remove that for disk/unmounted + foreach my $component (split(/\s+/, $component_string)){ + my (%data,$maj_min,$name,$number,$info,$mapped,$part_size,$state); + if ($component =~ /([\S]+)\[([0-9]+)\]\(?([SF])?\)?/){ + ($name,$number,$info) = ($1,$2,$3); + } + next if !$name; + if ($details{'devices'} && ref $details{'devices'} eq 'HASH'){ + $maj_min = $details{'devices'}->{$name}{'maj-min'}; + $state = $details{'devices'}->{$name}{'state'}; + } + if ((!$maj_min || !$part_size) && @proc_partitions){ + @part = main::get_proc_partition($name); + if (@part){ + $maj_min = $part[0] . ':' . $part[1] if !$maj_min; + $part_size = $part[2] if !$part_size; + } + } + if ((!$maj_min || !$part_size) && @lsblk) { + %data= main::get_lsblk($name); + $maj_min = $data{'maj-min'} if !$maj_min; + $part_size = $data{'size'}if !$part_size; + } + $mapped = $dmmapper{$name} if %dmmapper; + $raw_logical[1] += $part_size if $part_size; + $state = $info if !$state && $info; + push(@components,[$name,$number,$info,$part_size,$maj_min,$state,$mapped]); } - @components = @temp; #print "$component_string\n"; $j = scalar @mdraid; - @data = ({ + push(@mdraid, { + 'chunk-size' => $details{'chunk-size'}, # if we got it, great, if not, further down + 'components' => \@components, + 'details' => \%details, 'id' => $id, - 'arrays' => ([],), + 'level' => $level, + 'maj-min' => $maj_min, + 'size' => $size, 'status' => $status, 'type' => 'mdraid', }); - @mdraid = (@mdraid,@data); - $mdraid[$j]{'arrays'}[0]{'raid'} = $raid; - $mdraid[$j]{'arrays'}[0]{'components'} = \@components; } #print "$_\n"; if ($_ =~ /^([0-9]+)\sblocks/){ @@ -14189,20 +14928,89 @@ sub mdraid_data { eval $end if $b_log; return @mdraid; } +sub md_details { + eval $start if $b_log; + my ($id) = @_; + my (%details,@working); + my $cmd = $alerts{'mdadm'}->{'path'} . " --detail /dev/$id 2>/dev/null"; + my @data = main::grabber($cmd,'','strip'); + main::log_data('dump',"$id raw: \@data",\@data) if $b_log; + foreach (@data) { + @working = split(/\s*:\s*/, $_, 2); + if (scalar @working == 2){ + if ($working[0] eq 'Array Size' && $working[1] =~ /^([0-9]+)\s\(/){ + $details{'size'} = $1; + } + elsif ($working[0] eq 'Active Devices'){ + $details{'c-active'} = $working[1]; + } + elsif ($working[0] eq 'Chunk Size'){ + $details{'chunk-size'} = $working[1]; + } + elsif ($working[0] eq 'Failed Devices'){ + $details{'c-failed'} = $working[1]; + } + elsif ($working[0] eq 'Raid Devices'){ + $details{'c-raid'} = $working[1]; + } + elsif ($working[0] eq 'Spare Devices'){ + $details{'c-spare'} = $working[1]; + } + elsif ($working[0] eq 'State'){ + $details{'state'} = $working[1]; + } + elsif ($working[0] eq 'Total Devices'){ + $details{'c-total'} = $working[1]; + } + elsif ($working[0] eq 'Used Dev Size' && $working[1] =~ /^([0-9]+)\s\(/){ + $details{'dev-size'} = $1; + } + elsif ($working[0] eq 'UUID'){ + $details{'uuid'} = $working[1]; + } + elsif ($working[0] eq 'Working Devices'){ + $details{'c-working'} = $working[1]; + } + } + # end component data lines + else { + @working = split(/\s+/,$_); + # 0 8 80 0 active sync /dev/sdf + # 2 8 128 - spare /dev/sdi + next if !@working || $working[0] eq 'Number' || scalar @working < 6; + $working[-1] =~ s|^/dev/(mapper/)?||; + $details{'devices'}->{$working[-1]} = { + 'maj-min' => $working[1] . ':' . $working[2], + 'number' => $working[0], + 'raid-device' => $working[3], + 'state' => join(' ', @working[4..($#working - 1)]), + }; + } + } + #print Data::Dumper::Dumper \%details; + main::log_data('dump',"$id: %details",\%details) if $b_log; + eval $end if $b_log; + return %details; +} sub zfs_data { eval $start if $b_log; my ($zpool) = @_; - my (@components,@data,@zfs); - my ($allocated,$free,$ref,$size,$status); + my (@components,@zfs); + my ($allocated,$free,$size,$size_holder,$size_logical,$status,@working); my $b_v = 1; my ($i,$j,$k) = (0,0,0); - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-1-mirror-main-solestar.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-2-mirror-main-solestar.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-tank-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-gojev-1.txt"; - #my @working = main::reader($file);$zpool = ''; - my @working = main::grabber("$zpool list -v 2>/dev/null"); + if ($b_fake_raid){ + my $file; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-1-mirror-main-solestar.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-2-mirror-main-solestar.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-tank-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-list-v-gojev-1.txt"; + #@working = main::reader($file);$zpool = ''; + } + else { + @working = main::grabber("$zpool list -v 2>/dev/null"); + } DiskData::set_glabel() if $bsd_type && !$b_glabel; # bsd sed does not support inserting a true \n so use this trick # some zfs does not have -v @@ -14221,22 +15029,23 @@ sub zfs_data { # NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT my $test = shift @working; # get rid of first header line if ($test){ - foreach (split /\s+/, $test){ + foreach (split(/\s+/, $test)){ last if $_ eq 'HEALTH'; $status_i++; } } foreach (@working){ - my @row = split /\s+/, $_; + my @row = split(/\s+/, $_); if (/^[\S]+/){ @components = (); $i = 0; - $size = ($row[1] && $row[1] ne '-')? main::translate_size($row[1]): ''; + $raw_logical[0] += $size_holder if $size_holder; + $size_holder = $size = ($row[1] && $row[1] ne '-')? main::translate_size($row[1]): ''; $allocated = ($row[2] && $row[2] ne '-')? main::translate_size($row[2]): ''; $free = ($row[3] && $row[3] ne '-')? main::translate_size($row[3]): ''; $status = (defined $row[$status_i] && $row[$status_i] ne '') ? $row[$status_i]: 'no-status'; $j = scalar @zfs; - @data = ({ + push(@zfs, { 'id' => $row[0], 'allocated' => $allocated, 'arrays' => ([],), @@ -14245,18 +15054,19 @@ sub zfs_data { 'status' => $status, 'type' => 'zfs', }); - @zfs = (@zfs,@data); } #print Data::Dumper::Dumper \@zfs; # raid level is the second item in the output, unless it is not, sometimes it is absent if ($row[1] =~ /raid|mirror/){ $row[1] =~ s/^raid1/mirror/; #$row[1] =~ s/^raid/raid-/; # need to match in zpool status - $ref = $zfs[$j]{'arrays'}; - $k = scalar @$ref; - $zfs[$j]{'arrays'}[$k]{'raid'} = $row[1]; + $k = scalar @{$zfs[$j]{'arrays'}}; + $zfs[$j]{'arrays'}[$k]{'level'} = $row[1]; $i = 0; - $zfs[$j]{'arrays'}[$k]{'size'} = ($row[2] && $row[2] ne '-') ? main::translate_size($row[2]) : ''; + $size_logical = $size = ($row[2] && $row[2] ne '-') ? main::translate_size($row[2]) : ''; + $size_holder = 0; + $raw_logical[0] += $size if $size; + $zfs[$j]{'arrays'}[$k]{'size'} = $size; $zfs[$j]{'arrays'}[$k]{'allocated'} = ($row[3] && $row[3] ne '-') ? main::translate_size($row[3]) : ''; $zfs[$j]{'arrays'}[$k]{'free'} = ($row[4] && $row[4] ne '-') ? main::translate_size($row[4]) : ''; } @@ -14274,6 +15084,7 @@ sub zfs_data { $row[1] =~ /^(sd[a-z]|[a-z0-9]+[0-9]+|([\S]+)\/.*)\s*(DEGRADED|FAULTED|OFFLINE)?$/; my $working = ($1) ? $1 : ''; # note: the negative case can never happen my $state = ($3) ? $3 : ''; + my ($maj_min,$part_size); if ($working =~ /[\S]+\// && @glabel){ $working = DiskData::match_glabel($working); } @@ -14282,8 +15093,10 @@ sub zfs_data { # component row: # ada0s2 25.9G 19.6G 6.25G - 0% 75% if (!$zfs[$j]{'size'} && $row[2] && $row[2] ne '-') { - $size = ($row[2])? main::translate_size($row[2]): ''; + $size_logical = $size = ($row[2])? main::translate_size($row[2]): ''; + $size_holder = 0; $zfs[$j]{'arrays'}[$k]{'size'} = $size; + $raw_logical[0] += $size if $size; } if (!$zfs[$j]{'allocated'} && $row[3] && $row[3] ne '-') { $allocated = ($row[3])? main::translate_size($row[3]): ''; @@ -14293,83 +15106,96 @@ sub zfs_data { $free = ($row[4])? main::translate_size($row[4]): ''; $zfs[$j]{'arrays'}[$k]{'free'} = $free; } - $zfs[$j]{'arrays'}[$k]{'components'}[$i] = $working . '~' . $state; + if ((!$maj_min || !$part_size) && @lsblk){ + my @part = main::get_proc_partition($working); + if (@part){ + $maj_min = $part[0] . ':' . $part[1]; + $part_size = $part[2]; + } + } + if ((!$maj_min || !$part_size) && @lsblk){ + my %data= main::get_lsblk($working); + $maj_min = $data{'maj-min'}; + $part_size = $data{'size'}; + } + $raw_logical[1] += $part_size if $part_size; + $zfs[$j]{'arrays'}[$k]{'components'}[$i] = [$working,$part_size,$maj_min,$state]; $i++; } } + $raw_logical[0] += $size_holder if $size_holder; # print Data::Dumper::Dumper \@zfs; # clear out undefined arrrays values $j = 0; - foreach $ref (@zfs){ - my %row = %$ref; - my $ref2 = $row{'arrays'}; - my @arrays = (ref $ref2 eq 'ARRAY' ) ? @$ref2 : (); + foreach my $row (@zfs){ + my @arrays = (ref $row->{'arrays'} eq 'ARRAY' ) ? @{$row->{'arrays'}} : (); @arrays = grep {defined $_} @arrays; $zfs[$j]{'arrays'} = \@arrays; $j++; } - @zfs = zfs_status($zpool,@zfs); + @zfs = zfs_status($zpool,\@zfs); # print Data::Dumper::Dumper \@zfs; eval $end if $b_log; return @zfs; } sub zfs_status { eval $start if $b_log; - my ($zpool,@zfs) = @_; - my ($cmd,$status,$file,$raid,@arrays,@pool_status,@temp); + my ($zpool,$zfs) = @_; + my ($cmd,$level,$status,@pool_status,@temp); my ($i,$j,$k,$l) = (0,0,0,0); - foreach my $ref (@zfs){ - my %row = %$ref; + foreach my $row (@$zfs){ $i = 0; $k = 0; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-1-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-2-mirror-main-solestar.txt"; - #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-tank-1.txt"; - #@pool_status = main::reader($file,'strip'); - $cmd = "$zpool status $row{'id'} 2>/dev/null"; - @pool_status = main::grabber($cmd,"\n",'strip'); + if ($b_fake_raid){ + my $file; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-1-mirror-main-solestar.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-2-mirror-main-solestar.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/raid/zpool-status-tank-1.txt"; + #@pool_status = main::reader($file,'strip'); + } + else { + $cmd = "$zpool status $row->{'id'} 2>/dev/null"; + @pool_status = main::grabber($cmd,"\n",'strip'); + } main::log_data('cmd',$cmd) if $b_log; - my $ref2 = $row{'arrays'}; - @arrays = (ref $ref2 eq 'ARRAY' ) ? @$ref2 : (); - #print "$row{'id'} rs:$row{'status'}\n"; - $status = ($row{'status'} && $row{'status'} eq 'no-status') ? check_status($row{'id'},@pool_status): $row{'status'}; - $zfs[$j]{'status'} = $status if $status; + #@arrays = (ref $row->{'arrays'} eq 'ARRAY' ) ? @{$row->{'arrays'}} : (); + #print "$row->{'id'} rs:$row->{'status'}\n"; + $status = ($row->{'status'} && $row->{'status'} eq 'no-status') ? check_zfs_status($row->{'id'},\@pool_status): $row->{'status'}; + $zfs->[$j]{'status'} = $status if $status; #@arrays = grep {defined $_} @arrays; - #print "$row{id} $#arrays\n"; + #print "$row->{id} $#arrays\n"; #print Data::Dumper::Dumper \@arrays; - foreach my $array (@arrays){ + foreach my $array (@{$row->{'arrays'}}){ #print 'ref: ', ref $array, "\n"; #next if ref $array ne 'HASH'; - my %row2 = %$array; - my $ref3 = $row2{'components'}; - my @components = (ref $ref3 eq 'ARRAY') ? @$ref3 : (); + my @components = (ref $array->{'components'} eq 'ARRAY') ? @{$array->{'components'}} : (); $l = 0; # zpool status: mirror-0 ONLINE 2 0 0 - $raid = ($row2{'raid'}) ? "$row2{'raid'}-$i": $row2{'raid'}; - $status = ($raid) ? check_status($raid,@pool_status): ''; - $zfs[$j]{'arrays'}[$k]{'status'} = $status; - #print "$raid i:$i j:$j k:$k $status\n"; + $level = ($array->{'level'}) ? "$array->{'level'}-$i": $array->{'level'}; + $status = ($level) ? check_zfs_status($level,\@pool_status): ''; + $zfs->[$j]{'arrays'}[$k]{'status'} = $status; + #print "$level i:$i j:$j k:$k $status\n"; foreach my $component (@components){ - my @temp = split /~/, $component; - $status = ($temp[0]) ? check_status($temp[0],@pool_status): ''; - $zfs[$j]{'arrays'}[$k]{'components'}[$l] .= $status if $status; + my @temp = split('~', $component); + $status = ($temp[0]) ? check_zfs_status($temp[0],\@pool_status): ''; + $zfs->[$j]{'arrays'}[$k]{'components'}[$l] .= $status if $status; $l++; } $k++; - # haven't seen a raid5/6 type array yet - $i++ if $row2{'raid'}; # && $row2{'raid'} eq 'mirror'; + # haven't seen a raid5/6 type array yet, zfs uses z1,z2,and z3 + $i++ if $array->{'level'}; # && $array->{'level'} eq 'mirror'; } $j++; } eval $end if $b_log; - return @zfs; + return @$zfs; } -sub check_status { +sub check_zfs_status { eval $start if $b_log; - my ($item,@pool_status) = @_; + my ($item,$pool_status) = @_; my ($status) = (''); - foreach (@pool_status){ - my @temp = split /\s+/, $_; + foreach (@$pool_status){ + my @temp = split(/\s+/, $_); if ($temp[0] eq $item){ last if !$temp[1]; $status = $temp[1]; @@ -14388,21 +15214,19 @@ package RamData; sub get { my (@data,@rows,$key1,@ram,$val1); my $num = 0; - my $ref = $alerts{'dmidecode'}; @rows = main::get_memory_data_full('ram') if !$b_mem; - if ( !$b_fake_dmidecode && $$ref{'action'} ne 'use'){ - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; - @data = ({ + if ( !$b_fake_dmidecode && $alerts{'dmidecode'}->{'action'} ne 'use'){ + $key1 = $alerts{'dmidecode'}->{'action'}; + $val1 = $alerts{'dmidecode'}->{$key1}; + push(@rows, { main::key($num++,1,1,'RAM Report') => '', main::key($num++,0,2,$key1) => $val1, }); - @rows = (@rows,@data); } else { @ram = dmidecode_data(); if (@ram){ - @data = create_output(@ram); + @data = create_output(\@ram); } else { $key1 = 'message'; @@ -14412,7 +15236,7 @@ sub get { main::key($num++,0,2,$key1) => $val1, }); } - @rows = (@rows,@data); + push(@rows,@data); } eval $end if $b_log; return @rows; @@ -14420,92 +15244,114 @@ sub get { sub create_output { eval $start if $b_log; - my (@ram) = @_; - return if !@ram; + my ($ram) = @_; + return if !@$ram; my $num = 0; my $j = 0; - my (@data,@rows,$b_non_system); + my (@rows,$b_non_system); my ($arrays,$modules,$slots,$type_holder) = (0,0,0,''); - foreach (@ram){ + foreach my $item (@$ram){ $j = scalar @rows; - my %ref = %$_; if (!$show{'ram-short'}){ - $b_non_system = ($ref{'use'} && lc($ref{'use'}) ne 'system memory') ? 1:0 ; + $b_non_system = ($item->{'use'} && lc($item->{'use'}) ne 'system memory') ? 1:0 ; $num = 1; - @data = ({ + push(@rows, { main::key($num++,1,1,'Array') => '', - main::key($num++,1,2,'capacity') => process_size($ref{'capacity'}), + main::key($num++,1,2,'capacity') => process_size($item->{'capacity'}), }); - @rows = (@rows,@data); - if ($ref{'cap-qualifier'}){ - $rows[$j]{main::key($num++,0,3,'note')} = $ref{'cap-qualifier'}; + if ($item->{'cap-qualifier'}){ + $rows[$j]{main::key($num++,0,3,'note')} = $item->{'cap-qualifier'}; } - $rows[$j]{main::key($num++,0,2,'use')} = $ref{'use'} if $b_non_system; - $rows[$j]{main::key($num++,0,2,'slots')} = $ref{'slots'}; - $ref{'eec'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'EC')} = $ref{'eec'}; + $rows[$j]{main::key($num++,0,2,'use')} = $item->{'use'} if $b_non_system; + $rows[$j]{main::key($num++,1,2,'slots')} = $item->{'slots'}; + if ($item->{'slots-qualifier'}){ + $rows[$j]{main::key($num++,0,3,'note')} = $item->{'slots-qualifier'}; + } + $item->{'eec'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'EC')} = $item->{'eec'}; if ($extra > 0 && (!$b_non_system || - ( main::is_numeric($ref{'max-module-size'}) && $ref{'max-module-size'} > 10 ) ) ){ - $rows[$j]{main::key($num++,1,2,'max module size')} = process_size($ref{'max-module-size'}); - if ($ref{'mod-qualifier'}){ - $rows[$j]{main::key($num++,0,3,'note')} = $ref{'mod-qualifier'}; + ( main::is_numeric($item->{'max-module-size'}) && $item->{'max-module-size'} > 10 ) ) ){ + $rows[$j]{main::key($num++,1,2,'max module size')} = process_size($item->{'max-module-size'}); + if ($item->{'mod-qualifier'}){ + $rows[$j]{main::key($num++,0,3,'note')} = $item->{'mod-qualifier'}; } } + if ($extra > 2 && $item->{'voltage'}){ + $rows[$j]{main::key($num++,0,2,'voltage')} = $item->{'voltage'}; + } } else { - $slots += $ref{'slots'} if $ref{'slots'}; + $slots += $item->{'slots'} if $item->{'slots'}; $arrays++; } - foreach my $ref2 ($ref{'modules'}){ - next if ref $ref2 ne 'ARRAY'; - my @modules = @$ref2; - # print Data::Dumper::Dumper \@modules; - foreach my $ref3 ( @modules){ + foreach my $entry ($item->{'modules'}){ + next if ref $entry ne 'ARRAY'; + # print Data::Dumper::Dumper $entry; + foreach my $mod ( @$entry){ $num = 1; $j = scalar @rows; # multi array setups will start index at next from previous array - next if ref $ref3 ne 'HASH'; - my %mod = %$ref3; + next if ref $mod ne 'HASH'; if ($show{'ram-short'}){ - $modules++ if ($mod{'size'} =~ /^\d/); - $type_holder = $mod{'device-type'} if $mod{'device-type'}; + $modules++ if ($mod->{'size'} =~ /^\d/); + $type_holder = $mod->{'device-type'} if $mod->{'device-type'}; next; } - next if ($show{'ram-modules'} && $mod{'size'} =~ /\D/); - $mod{'locator'} ||= 'N/A'; - @data = ({ - main::key($num++,1,2,'Device') => $mod{'locator'}, - main::key($num++,0,3,'size') => process_size($mod{'size'}), + next if ($show{'ram-modules'} && $mod->{'size'} =~ /\D/); + $mod->{'locator'} ||= 'N/A'; + push(@rows, { + main::key($num++,1,2,'Device') => $mod->{'locator'}, + main::key($num++,0,3,'size') => process_size($mod->{'size'}), }); - @rows = (@rows,@data); - next if ($mod{'size'} =~ /\D/); - if ($extra > 1 && $mod{'type'} ){ - $rows[$j]{main::key($num++,0,3,'info')} = $mod{'type'}; + next if ($mod->{'size'} =~ /\D/); + if ($extra > 1 && $mod->{'type'} ){ + $rows[$j]{main::key($num++,0,3,'info')} = $mod->{'type'}; + } + if ($mod->{'speed'} && $mod->{'configured-clock-speed'} && + $mod->{'speed'} ne $mod->{'configured-clock-speed'}){ + $rows[$j]{main::key($num++,1,3,'speed')} = ''; + $rows[$j]{main::key($num++,0,4,'spec')} = $mod->{'speed'}; + $rows[$j]{main::key($num++,0,4,'note')} = $mod->{'speed-note'} if $mod->{'speed-note'}; + $rows[$j]{main::key($num++,0,4,'actual')} = $mod->{'configured-clock-speed'}; + $rows[$j]{main::key($num++,0,5,'note')} = $mod->{'configured-note'} if $mod->{'configured-note'}; + } + else { + if (!$mod->{'speed'} && $mod->{'configured-clock-speed'}){ + if ($mod->{'configured-clock-speed'}){ + $mod->{'speed'} = $mod->{'configured-clock-speed'}; + $mod->{'speed-note'} = $mod->{'configured-note'} if $mod->{'configured-note'} ; + } + # rare instances, dmi type 6, no speed + else { + $mod->{'speed'} = 'N/A'; + } + } + $rows[$j]{main::key($num++,1,3,'speed')} = $mod->{'speed'}; + $rows[$j]{main::key($num++,0,4,'note')} = $mod->{'speed-note'} if $mod->{'speed-note'}; } - $rows[$j]{main::key($num++,0,3,'speed')} = $mod{'speed'}; if ($extra > 0 ){ - $mod{'device-type'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'type')} = $mod{'device-type'}; - if ($extra > 2 && $mod{'device-type'} ne 'N/A'){ - $mod{'device-type-detail'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'detail')} = $mod{'device-type-detail'}; + $mod->{'device-type'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'type')} = $mod->{'device-type'}; + if ($extra > 2 && $mod->{'device-type'} ne 'N/A'){ + $mod->{'device-type-detail'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'detail')} = $mod->{'device-type-detail'}; } } if ($extra > 2 ){ - $mod{'data-width'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'bus width')} = $mod{'data-width'}; - $mod{'total-width'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'total')} = $mod{'total-width'}; + $mod->{'data-width'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'bus width')} = $mod->{'data-width'}; + $mod->{'total-width'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'total')} = $mod->{'total-width'}; } if ($extra > 1 ){ - $mod{'manufacturer'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'manufacturer')} = $mod{'manufacturer'}; - $mod{'part-number'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,3,'part-no')} = $mod{'part-number'}; + $mod->{'manufacturer'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'manufacturer')} = $mod->{'manufacturer'}; + $mod->{'part-number'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,3,'part-no')} = $mod->{'part-number'}; } if ($extra > 2 ){ - $mod{'serial'} = main::apply_filter($mod{'serial'}); - $rows[$j]{main::key($num++,0,3,'serial')} = $mod{'serial'}; + $mod->{'serial'} = main::apply_filter($mod->{'serial'}); + $rows[$j]{main::key($num++,0,3,'serial')} = $mod->{'serial'}; } } } @@ -14513,14 +15359,13 @@ sub create_output { if ($show{'ram-short'}){ $num = 1; $type_holder ||= 'N/A'; - @data = ({ + push(@rows, { main::key($num++,1,1,'Report') => '', main::key($num++,0,2,'arrays') => $arrays, main::key($num++,0,2,'slots') => $slots, main::key($num++,0,2,'modules') => $modules, main::key($num++,0,2,'type') => $type_holder, }); - @rows = (@rows,@data); } eval $end if $b_log; return @rows; @@ -14531,14 +15376,14 @@ sub dmidecode_data { my ($b_5,$handle,@ram,@temp); my ($derived_module_size,$max_cap_5,$max_cap_16,$max_module_size) = (0,0,0,0); my ($i,$j,$k) = (0,0,0); - foreach (@dmi){ - my @ref = @$_; + my $check = main::row_defaults('note-check'); + foreach my $entry (@dmi){ ## NOTE: do NOT reset these values, that causes failures # ($derived_module_size,$max_cap_5,$max_cap_16,$max_module_size) = (0,0,0,0); - if ($ref[0] == 5){ + if ($entry->[0] == 5){ $ram[$k] = ({}) if !$ram[$k]; - foreach my $item (@ref){ - @temp = split /:\s*/, $item; + foreach my $item (@$entry){ + @temp = split(/:\s*/, $item, 2); next if ! $temp[1]; if ($temp[0] eq 'Maximum Memory Module Size'){ $max_module_size = calculate_size($temp[1],$max_module_size); @@ -14555,44 +15400,75 @@ sub dmidecode_data { elsif ($temp[0] eq 'Associated Memory Slots'){ $ram[$k]{'slots-5'} = $temp[1]; } + elsif ($temp[0] eq 'Error Detecting Method'){ + $temp[1] ||= 'None'; + $ram[$k]{'eec'} = $temp[1]; + } } $ram[$k]{'modules'} = ([],); #print Data::Dumper::Dumper \@ram; $b_5 = 1; } - elsif ($ref[0] == 6){ + elsif ($entry->[0] == 6){ my ($size,$speed,$type) = (0,0,0); - foreach my $item (@ref){ - @temp = split /:\s*/, $item; + my ($bank_locator,$device_type,$locator,$main_locator) = ('','','',''); + foreach my $item (@$entry){ + @temp = split(/:\s*/, $item, 2); next if ! $temp[1]; if ($temp[0] eq 'Installed Size'){ # get module size $size = calculate_size($temp[1],0); + # using this causes issues, really only works for 16 +# if ($size =~ /^[0-9][0-9]+$/) { +# $ram[$k]{'device-count-found'}++; +# $ram[$k]{'used-capacity'} += $size; +# } # get data after module size $temp[1] =~ s/ Connection\)?//; $temp[1] =~ s/^[0-9]+\s*[KkMGTP]B\s*\(?//; $type = lc($temp[1]); } elsif ($temp[0] eq 'Current Speed'){ - $speed = $temp[1]; + $speed = main::dmi_cleaner($temp[1]); + } + elsif ($temp[0] eq 'Locator' || $temp[0] eq 'Socket Designation' ){ + $temp[1] =~ s/D?RAM slot #?/Slot/i; # can be with or without # + $locator = $temp[1]; + } + elsif ($temp[0] eq 'Bank Locator'){ + $bank_locator = $temp[1]; + } + elsif ($temp[0] eq 'Type'){ + $device_type = $temp[1]; } } - $ram[$k]{'modules'}[$j] = ({ + # because of the wide range of bank/slot type data, we will just use + # the one that seems most likely to be right. Some have: Bank: SO DIMM 0 slot: J6A + # so we dump the useless data and use the one most likely to be visibly correct + if ( $bank_locator =~ /DIMM/ ) { + $main_locator = $bank_locator; + } + else { + $main_locator = $locator; + } + $ram[$k]{'modules'}[$j] = { + 'device-type' => $device_type, + 'locator' => $main_locator, 'size' => $size, - 'speed-ns' => $speed, + 'speed' => $speed, 'type' => $type, - }); + }; #print Data::Dumper::Dumper \@ram; $j++; } - elsif ($ref[0] == 16){ - $handle = $ref[1]; + elsif ($entry->[0] == 16){ + $handle = $entry->[1]; $ram[$handle] = $ram[$k] if $ram[$k]; $ram[$k] = undef; $ram[$handle] = ({}) if !$ram[$handle]; # ($derived_module_size,$max_cap_16) = (0,0); - foreach my $item (@ref){ - @temp = split /:\s*/, $item; + foreach my $item (@$entry){ + @temp = split(/:\s*/, $item, 2); next if ! $temp[1]; if ($temp[0] eq 'Maximum Capacity'){ $max_cap_16 = calculate_size($temp[1],$max_cap_16); @@ -14622,13 +15498,13 @@ sub dmidecode_data { $ram[$handle]{'used-capacity'} = 0; #print "s16: $ram[$handle]{'slots-16'}\n"; } - elsif ($ref[0] == 17){ - my ($bank_locator,$configured_clock_speed,$data_width) = ('','',''); + elsif ($entry->[0] == 17){ + my ($bank_locator,$configured_speed,$configured_note,$data_width) = ('','','',''); my ($device_type,$device_type_detail,$form_factor,$locator,$main_locator) = ('','','','',''); - my ($manufacturer,$part_number,$serial,$speed,$total_width) = ('','','','',''); + my ($manufacturer,$part_number,$serial,$speed,$speed_note,$total_width) = ('','','','','',''); my ($device_size,$i_data,$i_total,$working_size) = (0,0,0,0); - foreach my $item (@ref){ - @temp = split /:\s*/, $item; + foreach my $item (@$entry){ + @temp = split(/:\s*/, $item, 2); next if ! $temp[1]; if ($temp[0] eq 'Array Handle'){ $handle = hex($temp[1]); @@ -14652,7 +15528,7 @@ sub dmidecode_data { } } elsif ($temp[0] eq 'Locator'){ - $temp[1] =~ s/RAM slot #/Slot/; + $temp[1] =~ s/D?RAM slot #?/Slot/i; $locator = $temp[1]; } elsif ($temp[0] eq 'Bank Locator'){ @@ -14668,10 +15544,12 @@ sub dmidecode_data { $device_type_detail = $temp[1]; } elsif ($temp[0] eq 'Speed'){ - $speed = $temp[1]; + ($speed,$speed_note) = process_speed($temp[1],$device_type,$check); } - elsif ($temp[0] eq 'Configured Clock Speed'){ - $configured_clock_speed = $temp[1]; + # this is the actual speed the system booted at, speed is hardcoded + # clock speed means MHz, memory speed MT/S + elsif ($temp[0] eq 'Configured Clock Speed' || $temp[0] eq 'Configured Memory Speed'){ + ($configured_speed,$configured_note) = process_speed($temp[1],$device_type,$check); } elsif ($temp[0] eq 'Manufacturer'){ $temp[1] = main::dmi_cleaner($temp[1]); @@ -14714,7 +15592,8 @@ sub dmidecode_data { $total_width = $temp_width; } $ram[$handle]{'derived-module-size'} = $derived_module_size; - $ram[$handle]{'modules'}[$i]{'configured-clock-speed'} = $configured_clock_speed; + $ram[$handle]{'modules'}[$i]{'configured-clock-speed'} = $configured_speed; + $ram[$handle]{'modules'}[$i]{'configured-note'} = $configured_note if $configured_note; $ram[$handle]{'modules'}[$i]{'data-width'} = $data_width; $ram[$handle]{'modules'}[$i]{'size'} = $device_size; $ram[$handle]{'modules'}[$i]{'device-type'} = $device_type; @@ -14725,85 +15604,88 @@ sub dmidecode_data { $ram[$handle]{'modules'}[$i]{'part-number'} = $part_number; $ram[$handle]{'modules'}[$i]{'serial'} = $serial; $ram[$handle]{'modules'}[$i]{'speed'} = $speed; + $ram[$handle]{'modules'}[$i]{'speed-note'} = $speed_note if $speed_note; $ram[$handle]{'modules'}[$i]{'total-width'} = $total_width; $i++ } - elsif ($ref[0] < 17 ){ + elsif ($entry->[0] < 17 ){ next; } - elsif ($ref[0] > 17 ){ + elsif ($entry->[0] > 17 ){ last; } } - @ram = data_processor(@ram) if @ram; + @ram = process_data(\@ram) if @ram; main::log_data('dump','@ram',\@ram) if $b_log; # print Data::Dumper::Dumper \@ram; eval $end if $b_log; return @ram; } -sub data_processor { +sub process_data { eval $start if $b_log; - my (@ram) = @_; + my ($ram) = @_; my $b_debug = 0; - my (@return,@temp); - my $est = 'est.'; - foreach (@ram){ + my (@return); + my $check = main::row_defaults('note-check'); + my $est = main::row_defaults('note-est'); + foreach my $item (@$ram){ # because we use the actual array handle as the index, # there will be many undefined keys - next if ! defined $_; - my %ref = %$_; + next if ! defined $item; my ($max_cap,$max_mod_size) = (0,0); - my ($alt_cap,$est_cap,$est_mod,$unit) = (0,'','',''); - $max_cap = $ref{'max-capacity-16'}; + my ($alt_cap,$est_cap,$est_mod,$est_slots,$unit) = (0,'','','',''); + $max_cap = $item->{'max-capacity-16'}; $max_cap ||= 0; # make sure they are integers not string if empty - $ref{'slots-5'} ||= 0; - $ref{'slots-16'} ||= 0; - $ref{'max-capacity-5'} ||= 0; - $ref{'max-module-size'} ||= 0; - $ref{'used-capacity'} ||= 0; - #$ref{'max-module-size'} = 0;# debugger + $item->{'slots-5'} ||= 0; + $item->{'slots-16'} ||= 0; + $item->{'device-count-found'} ||= 0; + $item->{'max-capacity-5'} ||= 0; + $item->{'max-module-size'} ||= 0; + $item->{'used-capacity'} ||= 0; + #$item->{'max-module-size'} = 0;# debugger # 1: if max cap 1 is null, and max cap 2 not null, use 2 if ($b_debug){ - print "1: mms: $ref{'max-module-size'} :dms: $ref{'derived-module-size'} :mc: $max_cap :uc: $ref{'used-capacity'}\n"; - print "1a: s5: $ref{'slots-5'} s16: $ref{'slots-16'}\n"; + print "1: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; + print "1a: s5: $item->{'slots-5'} s16: $item->{'slots-16'}\n"; } - if (!$max_cap && $ref{'max-capacity-5'}) { - $max_cap = $ref{'max-capacity-5'}; + if (!$max_cap && $item->{'max-capacity-5'}) { + $max_cap = $item->{'max-capacity-5'}; } if ($b_debug){ - print "2: mms: $ref{'max-module-size'} :dms: $ref{'derived-module-size'} :mc: $max_cap :uc: $ref{'used-capacity'}\n"; + print "2: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } # 2: now check to see if actually found module sizes are > than listed max module, replace if > - if ( $ref{'max-module-size'} && $ref{'derived-module-size'} && - $ref{'derived-module-size'} > $ref{'max-module-size'} ){ - $ref{'max-module-size'} = $ref{'derived-module-size'}; + if ( $item->{'max-module-size'} && $item->{'derived-module-size'} && + $item->{'derived-module-size'} > $item->{'max-module-size'} ){ + $item->{'max-module-size'} = $item->{'derived-module-size'}; $est_mod = $est; } if ($b_debug){ - print "3: dcf: $ref{'device-count-found'} :dms: $ref{'derived-module-size'} :mc: $max_cap :uc: $ref{'used-capacity'}\n"; + print "3: dcf: $item->{'device-count-found'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } + # note: some cases memory capacity == max module size, so one stick will fill it # but I think only with cases of 2 slots does this happen, so if > 2, use the count of slots. - if ($max_cap && ($ref{'device-count-found'} || $ref{'slots-16'}) ){ + if ($max_cap && ($item->{'device-count-found'} || $item->{'slots-16'}) ){ # first check that actual memory found is not greater than listed max cap, or # checking to see module count * max mod size is not > used capacity - if ($ref{'used-capacity'} && $ref{'max-capacity-16'}){ - if ($ref{'used-capacity'} > $max_cap){ - if ($ref{'max-module-size'} && - $ref{'used-capacity'} < ($ref{'slots-16'} * $ref{'max-module-size'} )){ - $max_cap = $ref{'slots-16'} * $ref{'max-module-size'}; + if ($item->{'used-capacity'} && $item->{'max-capacity-16'}){ + if ($item->{'used-capacity'} > $max_cap){ + if ($item->{'max-module-size'} && + $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'max-module-size'} )){ + $max_cap = $item->{'slots-16'} * $item->{'max-module-size'}; $est_cap = $est; print "A\n" if $b_debug; } - elsif ($ref{'derived-module-size'} && - $ref{'used-capacity'} < ($ref{'slots-16'} * $ref{'derived-module-size'}) ){ - $max_cap = $ref{'slots-16'} * $ref{'derived-module-size'}; + elsif ($item->{'derived-module-size'} && + $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'derived-module-size'}) ){ + $max_cap = $item->{'slots-16'} * $item->{'derived-module-size'}; $est_cap = $est; print "B\n" if $b_debug; } else { - $max_cap = $ref{'used-capacity'}; + $max_cap = $item->{'used-capacity'}; $est_cap = $est; print "C\n" if $b_debug; } @@ -14813,63 +15695,62 @@ sub data_processor { # mobile devices if (!$est_cap){ # do not do this for only single modules found, max mod size can be equal to the array size - if ($ref{'slots-16'} > 1 && $ref{'device-count-found'} > 1 && - $max_cap < ($ref{'derived-module-size'} * $ref{'slots-16'} ) ){ - $max_cap = $ref{'derived-module-size'} * $ref{'slots-16'}; + if ($item->{'slots-16'} > 1 && $item->{'device-count-found'} > 1 && + $max_cap < ($item->{'derived-module-size'} * $item->{'slots-16'} ) ){ + $max_cap = $item->{'derived-module-size'} * $item->{'slots-16'}; $est_cap = $est; print "D\n" if $b_debug; } - elsif ($ref{'device-count-found'} > 0 && $max_cap < ( $ref{'derived-module-size'} * $ref{'device-count-found'} )){ - $max_cap = $ref{'derived-module-size'} * $ref{'device-count-found'}; + elsif ($item->{'device-count-found'} > 0 && $max_cap < ( $item->{'derived-module-size'} * $item->{'device-count-found'} )){ + $max_cap = $item->{'derived-module-size'} * $item->{'device-count-found'}; $est_cap = $est; print "E\n" if $b_debug; } ## handle cases where we have type 5 data: mms x device count equals type 5 max cap # however do not use it if cap / devices equals the derived module size - elsif ($ref{'max-module-size'} > 0 && - ($ref{'max-module-size'} * $ref{'slots-16'}) == $ref{'max-capacity-5'} && - $ref{'max-capacity-5'} != $ref{'max-capacity-16'} && - $ref{'derived-module-size'} != ($ref{'max-capacity-16'}/$ref{'slots-16'}) ){ - $max_cap = $ref{'max-capacity-5'}; + elsif ($item->{'max-module-size'} > 0 && + ($item->{'max-module-size'} * $item->{'slots-16'}) == $item->{'max-capacity-5'} && + $item->{'max-capacity-5'} != $item->{'max-capacity-16'} && + $item->{'derived-module-size'} != ($item->{'max-capacity-16'}/$item->{'slots-16'}) ){ + $max_cap = $item->{'max-capacity-5'}; $est_cap = $est; print "F\n" if $b_debug; } } if ($b_debug){ - print "4: mms: $ref{'max-module-size'} :dms: $ref{'derived-module-size'} :mc: $max_cap :uc: $ref{'used-capacity'}\n"; + print "4: mms: $item->{'max-module-size'} :dms: $item->{'derived-module-size'} :mc: $max_cap :uc: $item->{'used-capacity'}\n"; } # some cases of type 5 have too big module max size, just dump the data then since # we cannot know if it is valid or not, and a guess can be wrong easily - if ($ref{'max-module-size'} && $max_cap && $ref{'max-module-size'} > $max_cap){ - $ref{'max-module-size'} = 0; + if ($item->{'max-module-size'} && $max_cap && $item->{'max-module-size'} > $max_cap){ + $item->{'max-module-size'} = 0; } if ($b_debug){ - print "5: dms: $ref{'derived-module-size'} :s16: $ref{'slots-16'} :mc: $max_cap\n"; + print "5: dms: $item->{'derived-module-size'} :s16: $item->{'slots-16'} :mc: $max_cap\n"; } - # now prep for rebuilding the ram array data - if (!$ref{'max-module-size'}){ + if (!$item->{'max-module-size'}){ # ie: 2x4gB - if (!$est_cap && $ref{'derived-module-size'} > 0 && $max_cap > ($ref{'derived-module-size'} * $ref{'slots-16'} * 4) ){ - $est_cap = 'check'; + if (!$est_cap && $item->{'derived-module-size'} > 0 && $max_cap > ($item->{'derived-module-size'} * $item->{'slots-16'} * 4) ){ + $est_cap = $check; print "G\n" if $b_debug; } - if ($max_cap && ($ref{'slots-16'} || $ref{'slots-5'})){ + if ($max_cap && ($item->{'slots-16'} || $item->{'slots-5'})){ my $slots = 0; - if ($ref{'slots-16'} && $ref{'slots-16'} >= $ref{'slots-5'}){ - $slots = $ref{'slots-16'}; + if ($item->{'slots-16'} && $item->{'slots-16'} >= $item->{'slots-5'}){ + $slots = $item->{'slots-16'}; } - elsif ($ref{'slots-5'} && $ref{'slots-5'} > $ref{'slots-16'}){ - $slots = $ref{'slots-5'}; + elsif ($item->{'slots-5'} && $item->{'slots-5'} > $item->{'slots-16'}){ + $slots = $item->{'slots-5'}; } # print "slots: $slots\n" if $b_debug; - if ($ref{'derived-module-size'} * $slots > $max_cap){ - $ref{'max-module-size'} = $ref{'derived-module-size'}; + if ($item->{'derived-module-size'} * $slots > $max_cap){ + $item->{'max-module-size'} = $item->{'derived-module-size'}; print "H\n" if $b_debug; } else { - $ref{'max-module-size'} = sprintf("%.f",$max_cap/$slots); + $item->{'max-module-size'} = sprintf("%.f",$max_cap/$slots); print "J\n" if $b_debug; } $est_mod = $est; @@ -14878,36 +15759,60 @@ sub data_processor { # case where listed max cap is too big for actual slots x max cap, eg: # listed max cap, 8gb, max mod 2gb, slots 2 else { - if (!$est_cap && $ref{'max-module-size'} > 0){ - if ($max_cap > ( $ref{'max-module-size'} * $ref{'slots-16'})){ - $est_cap = 'check'; + if (!$est_cap && $item->{'max-module-size'} > 0){ + if ($max_cap > ( $item->{'max-module-size'} * $item->{'slots-16'})){ + $est_cap = $check; print "K\n" if $b_debug; } } } } - @temp = ({ + # no slots found due to legacy dmi probably. Note, too many logic errors + # happen if we just set a general slots above, so safest to do it here + $item->{'slots-16'} = $item->{'slots-5'} if $item->{'slots-5'} && !$item->{'slots-16'}; + if (!$item->{'slots-16'} && $item->{'modules'} && ref $item->{'modules'} eq 'ARRAY'){ + $est_slots = $check; + $item->{'slots-16'} = scalar @{$item->{'modules'}}; + print "L\n" if $b_debug; + } + push(@return, { 'capacity' => $max_cap, 'cap-qualifier' => $est_cap, - 'eec' => $ref{'eec'}, - 'location' => $ref{'location'}, - 'max-module-size' => $ref{'max-module-size'}, + 'eec' => $item->{'eec'}, + 'location' => $item->{'location'}, + 'max-module-size' => $item->{'max-module-size'}, 'mod-qualifier' => $est_mod, - 'modules' => $ref{'modules'}, - 'slots' => $ref{'slots-16'}, - 'use' => $ref{'use'}, - 'voltage' => $ref{'voltage'}, + 'modules' => $item->{'modules'}, + 'slots' => $item->{'slots-16'}, + 'slots-qualifier' => $est_slots, + 'use' => $item->{'use'}, + 'voltage' => $item->{'voltage'}, }); - @return = (@return,@temp); } eval $end if $b_log; return @return; } +sub process_speed { + my ($speed,$device_type,$check) = @_; + my $speed_note; + $speed = main::dmi_cleaner($speed) if $speed; + if ($device_type && $device_type =~ /ddr/i && $speed && $speed =~ /^([0-9]+) MHz/){ + $speed = ($1 * 2) . " MT/s ($speed)"; + } + # seen cases of 1 MT/s, 61690 MT/s, not sure why, bug + # crucial is shipping 5100 MT/s now, and 6666 has been hit, so speeds can hit 10k + if ($speed && $speed =~ /^([0-9]+) M/){ + $speed_note = $check if $1 < 50 || $1 > 20000 ; + } + return ($speed,$speed_note); +} +# this should be fixed, but for now, size in RAM is in MiB, not +# KiB like the rest of inxi. sub process_size { my ($size) = @_; my ($b_trim,$unit) = (0,''); #print "size0: $size\n"; - return 'N/A' if ( ! $size ); + return 'N/A' if !$size; #return $size if $size =~ /\D/; return $size if !main::is_numeric($size); #print "size: $size\n"; @@ -15043,12 +15948,12 @@ sub get_repos_linux { $b_apt_enabled,$file,$string); my $counter = 0; @files = main::globber("$apt.d/*.list"); - push @files, $apt; + push(@files, $apt); main::log_data('data',"apt repo files:\n" . main::joiner(\@files, "\n", 'unset') ) if $b_log; - foreach ( sort @files){ + foreach (sort @files){ # altlinux/pclinuxos use rpms in apt files @data = repo_builder($_,'apt','^\s*(deb|rpm)') if -r $_; - @rows = (@rows,@data); + push(@rows,@data); } #@files = main::globber("$ENV{'HOME'}/bin/scripts/inxi/data/repo/apt/*.sources"); @files = main::globber("$apt.d/*.sources"); @@ -15060,9 +15965,9 @@ sub get_repos_linux { #print Data::Dumper::Dumper \@data2; if (@data2){ @data2 = map {s/^\s*$/~/;$_} @data2; - push @data2, '~'; + push(@data2, '~'); } - push @dbg_files, $file if $debugger_dir; + push(@dbg_files, $file) if $debugger_dir; #print "$file\n"; @apt_urls = (); @apt_working = (); @@ -15085,10 +15990,10 @@ sub get_repos_linux { $string .= ' ' . $apt_suites if $apt_suites ; $string .= ' ' . $apt_comp if $apt_comp; #print "s1:$string\n"; - push @data3, $string; + push(@data3, $string); } - #print join "\n",@data3,"\n"; - @apt_urls = (@apt_urls,@data3); + #print join("\n",@data3),"\n"; + push(@apt_urls,@data3); } @data3 = (); @apt_working = (); @@ -15110,7 +16015,7 @@ sub get_repos_linux { elsif ($row =~ /^[^#]+:\//){ my $url = $row; $url =~ s/^URIs:\s*//i; - push @apt_working, $url if $url; + push(@apt_working, $url) if $url; } elsif ($row =~ /^Suites:\s*(.*)/i){ $apt_suites = $1; @@ -15124,16 +16029,15 @@ sub get_repos_linux { } if (@apt_urls){ $key = repo_data('active','apt'); - @apt_urls = url_cleaner(@apt_urls); + @apt_urls = url_cleaner(\@apt_urls); } else { $key = repo_data('missing','apt'); } - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $file}, [@apt_urls], ); - @rows = (@rows,@data); } @files = (); } @@ -15151,33 +16055,31 @@ sub get_repos_linux { } if (@files){ @files = map { - my @working = split( /\s+=\s+/, $_); + my @working = split(/\s+=\s+/, $_); $working[1]; } @files; } - @files = sort(@files); - @files = main::uniq(@files); - unshift @files, $pacman if @repos; + @files = sort @files; + main::uniq(\@files); + unshift(@files, $pacman) if @repos; foreach (@files){ if (-f $_){ @data = repo_builder($_,$repo,'^\s*Server','\s*=\s*',1); - @rows = (@rows,@data); + push(@rows,@data); } else { # set it so the debugger knows the file wasn't there - push @dbg_files, $_ if $debugger_dir; - @data = ( + push(@dbg_files, $_) if $debugger_dir; + push(@rows, {main::key($num++,1,1,'File listed in') => $pacman}, [("$_ does not seem to exist.")], ); - @rows = (@rows,@data); } } if (!@rows){ - @data = ( + push(@rows, {main::key($num++,0,1,repo_data('missing','files')) => $pacman }, ); - @rows = (@rows,@data); } } # slackware @@ -15185,35 +16087,35 @@ sub get_repos_linux { #$slackpkg = "$ENV{HOME}/bin/scripts/inxi/data/repo/slackware/slackpkg-2.conf"; if (-f $slackpkg){ @data = repo_builder($slackpkg,'slackpkg','^[[:space:]]*[^#]+'); - @rows = (@rows,@data); + push(@rows,@data); } if (-d $slapt_get){ @data2 = main::globber("${slapt_get}*"); foreach my $file (@data2){ @data = repo_builder($file,'slaptget','^\s*SOURCE','\s*=\s*',1); - @rows = (@rows,@data); + push(@rows,@data); } } if (-f $slackpkg_plus){ - push @dbg_files, $slackpkg_plus if $debugger_dir; + push(@dbg_files, $slackpkg_plus) if $debugger_dir; @data = main::reader($slackpkg_plus,'strip'); my (@repoplus_list,$active_repos); foreach my $row (@data){ - @data2 = split /\s*=\s*/, $row; + @data2 = split(/\s*=\s*/, $row); @data2 = map { $_ =~ s/^\s+|\s+$//g ; $_ } @data2; last if $data2[0] =~ /^SLACKPKGPLUS/i && $data2[1] eq 'off'; # REPOPLUS=( slackpkgplus restricted alienbob ktown multilib slacky) if ($data2[0] =~ /^REPOPLUS/i){ - @repoplus_list = split /\s+/, $data2[1]; + @repoplus_list = split(/\s+/, $data2[1]); @repoplus_list = map {s/\(|\)//g; $_} @repoplus_list; - $active_repos = join ('|',@repoplus_list); + $active_repos = join('|',@repoplus_list); } # MIRRORPLUS['multilib']=http://taper.alienbase.nl/mirrors/people/alien/multilib/14.1/ if ($active_repos && $data2[0] =~ /^MIRRORPLUS/i){ $data2[0] =~ s/MIRRORPLUS\[\'|\'\]//ig; if ($data2[0] =~ /$active_repos/){ - push @content,"$data2[0] ~ $data2[1]"; + push(@content,"$data2[0] ~ $data2[1]"); } } } @@ -15221,15 +16123,15 @@ sub get_repos_linux { $key = repo_data('missing','slackpkg+'); } else { - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active','slackpkg+'); } @data = ( {main::key($num++,1,1,$key) => $slackpkg_plus}, [@content], ); - @data = url_cleaner(@data); - @rows = (@rows,@data); + @data = url_cleaner(\@data); + push(@rows,@data); @content = (); } } @@ -15237,7 +16139,7 @@ sub get_repos_linux { if (-d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir){ if (-d $yum_repo_dir || -f $yum_conf){ @files = main::globber("$yum_repo_dir*.repo"); - push @files, $yum_conf if -f $yum_conf; + push(@files, $yum_conf) if -f $yum_conf; $repo = 'yum'; } elsif (-d $zypp_repo_dir){ @@ -15246,11 +16148,11 @@ sub get_repos_linux { $repo = 'zypp'; } #$repo = 'yum'; - #push @files, "$ENV{'HOME'}/bin/scripts/inxi/data/repo/yum/rpmfusion-nonfree-1.repo"; + #push(@files, "$ENV{'HOME'}/bin/scripts/inxi/data/repo/yum/rpmfusion-nonfree-1.repo"); if (@files){ foreach (sort @files){ @data2 = main::reader($_); - push @dbg_files, $_ if $debugger_dir; + push(@dbg_files, $_) if $debugger_dir; my ($enabled,$url,$title) = (undef,'',''); foreach my $line (@data2){ # this is a hack, assuming that each item has these fields listed, we collect the 3 @@ -15262,7 +16164,7 @@ sub get_repos_linux { my $temp = $1; if ($url && $title && defined $enabled){ if ($enabled > 0){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } ($enabled,$url,$title) = (undef,'',''); } @@ -15282,27 +16184,26 @@ sub get_repos_linux { # repoTitle is hit above, it will print out the line there instead if ($url && $title && defined $enabled){ if ($enabled > 0){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } ($enabled,$url,$title) = (0,'',''); } } # print the last one if there is data for it if ($url && $title && $enabled){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } if (! @content){ $key = repo_data('missing',$repo); } else { - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active',$repo); } - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $_}, [@content], ); - @rows = (@rows,@data); @content = (); } } @@ -15315,7 +16216,7 @@ sub get_repos_linux { if (@files){ foreach (sort @files){ @data2 = main::reader($_); - push @dbg_files, $_ if $debugger_dir; + push(@dbg_files, $_) if $debugger_dir; my ($enabled,$url,$title) = (undef,'',''); foreach my $line (@data2){ # this is a hack, assuming that each item has these fields listed, we collect the 3 @@ -15327,7 +16228,7 @@ sub get_repos_linux { my $temp = $1; if ($url && $title && defined $enabled){ if ($enabled > 0){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } ($enabled,$url,$title) = (undef,'',''); } @@ -15346,27 +16247,26 @@ sub get_repos_linux { # repoTitle is hit above, it will print out the line there instead if ($url && $title && defined $enabled){ if ($enabled > 0){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } ($enabled,$url,$title) = (undef,'',''); } } # print the last one if there is data for it if ($url && $title && $enabled){ - push @content, "$title ~ $url"; + push(@content, "$title ~ $url"); } if (! @content){ $key = repo_data('missing','portage'); } else { - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active','portage'); } - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $_}, [@content], ); - @rows = (@rows,@data); @content = (); } } @@ -15374,55 +16274,54 @@ sub get_repos_linux { # Alpine linux if (-f $apk){ @data = repo_builder($apk,'apk','^\s*[^#]+'); - @rows = (@rows,@data); + push(@rows,@data); } # cards/nutyx if (-f $cards){ @data3 = main::reader($cards,'clean'); - push @dbg_files, $cards if $debugger_dir; + push(@dbg_files, $cards) if $debugger_dir; foreach (@data3){ if ($_ =~ /^dir\s+\/[^\|]+\/([^\/\|]+)\s*(\|\s*((http|ftp).*))?/){ my $type = ($3) ? $3: 'local'; - push @content, "$1 ~ $type"; + push(@content, "$1 ~ $type"); } } if (! @content){ $key = repo_data('missing','cards'); } else { - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active','cards'); } - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $cards}, [@content], ); - @rows = (@rows,@data); @content = (); } # TinyCore if (-e $tce_app || -f $tce_file || -f $tce_file2){ @data = repo_builder($tce_file,'tce','^\s*[^#]+'); - @rows = (@rows,@data); + push(@rows,@data); if (-f $tce_file2){ @data = repo_builder($tce_file2,'tce','^\s*[^#]+'); - @rows = (@rows,@data); + push(@rows,@data); } } # Void if (-d $xbps_dir_1 || -d $xbps_dir_2){ @files = main::globber("$xbps_dir_1*.conf"); - @files = (@files,main::globber("$xbps_dir_2*.conf")) if -d $xbps_dir_2; + push(@files,main::globber("$xbps_dir_2*.conf")) if -d $xbps_dir_2; main::log_data('data',"xbps repo files:\n" . main::joiner(\@files, "\n", 'unset') ) if $b_log; - foreach ( sort @files){ + foreach (sort @files){ @data = repo_builder($_,'xbps','^\s*repository\s*=','\s*=\s*',1) if -r $_; - @rows = (@rows,@data); + push(@rows,@data); } } # Mandriva/Mageia using: urpmq if ( $path = main::check_program('urpmq') ){ @data2 = main::grabber("$path --list-media active --list-url","\n",'strip'); - main::writer("$debugger_dir/system-repo-data-urpmq.txt",@data2) if $debugger_dir; + main::writer("$debugger_dir/system-repo-data-urpmq.txt",\@data2) if $debugger_dir; # now we need to create the structure: repo info: repo path # we do that by looping through the lines of the output and then # putting it back into the : format print repos expects to see @@ -15441,15 +16340,14 @@ sub get_repos_linux { # rsync://, ftp://, file://, http:// OR repo is locally mounted on FS in some cases if (/(.+)\s([\S]+:\/\/.+)/){ # pack the repo url - push @content, $1; - @content = url_cleaner(@content); + push(@content, $1); + @content = url_cleaner(\@content); # get the repo $repo = $2; - @data = ( + push(@rows, {main::key($num++,1,1,'urpmq repo') => $repo}, [@content], ); - @rows = (@rows,@data); @content = (); } } @@ -15463,7 +16361,7 @@ sub get_repos_linux { #my $file = "$ENV{HOME}/bin/scripts/inxi/data/repo/solus/eopkg-2.txt"; #@data2 = main::reader($file,'strip'); @data2 = main::grabber("$cmd 2>/dev/null","\n",'strip'); - main::writer("$debugger_dir/system-repo-data-$which.txt",@data2) if $debugger_dir; + main::writer("$debugger_dir/system-repo-data-$which.txt",\@data2) if $debugger_dir; # now we need to create the structure: repo info: repo path # we do that by looping through the lines of the output and then # putting it back into the : format print repos expects to see @@ -15481,7 +16379,7 @@ sub get_repos_linux { $_ =~ s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g; $_ =~ s/\e\[([0-9];)?[0-9]+m//g; if (/^\/|:\/\//){ - push @content, $_ if $repo; + push(@content, $_) if $repo; } # Local [inactive] Unstable [active] elsif ( /^(.*)\s\[([\S]+)\]/){ @@ -15489,26 +16387,24 @@ sub get_repos_linux { $repo = ($2 =~ /^activ/i) ? $repo : ''; } if ($repo && @content){ - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active',$which); - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $repo}, [@content], ); - @rows = (@rows,@data); $repo = ''; @content = (); } } # last one if present if ($repo && @content){ - @content = url_cleaner(@content); + @content = url_cleaner(\@content); $key = repo_data('active',$which); - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $repo}, [@content], ); - @rows = (@rows,@data); } } # print Dumper \@rows; @@ -15529,23 +16425,23 @@ sub get_repos_bsd { if ( -f $portsnap || -f $freebsd || -d $bsd_pkg){ if ( -f $portsnap ) { @data = repo_builder($portsnap,'portsnap','^\s*SERVERNAME','\s*=\s*',1); - @rows = (@rows,@data); + push(@rows,@data); } if ( -f $freebsd ){ @data = repo_builder($freebsd,'freebsd','^\s*ServerName','\s+',1); - @rows = (@rows,@data); + push(@rows,@data); } # if ( -f $freebsd_pkg ){ # @data = repo_builder($freebsd_pkg,'freebsd-pkg','^\s*url',':\s+',1); -# @rows = (@rows,@data); +# push(@rows,@data); # } if ( -d $bsd_pkg || -f $freebsd_pkg){ @files = main::globber('/usr/local/etc/pkg/repos/*.conf'); - push @files, $freebsd_pkg if -f $freebsd_pkg; + push(@files, $freebsd_pkg) if -f $freebsd_pkg; if (@files){ my ($url); foreach (@files){ - push @dbg_files, $_ if $debugger_dir; + push(@dbg_files, $_) if $debugger_dir; # these will be result sets separated by an empty line # first dump all lines that start with # @content = main::reader($_,'strip'); @@ -15555,7 +16451,7 @@ sub get_repos_bsd { my $url = ''; foreach my $line (@content){ if ($line !~ /^\s*$/){ - my @data2 = split /\s*:\s*/, $line; + my @data2 = split(/\s*:\s*/, $line); @data2 = map { $_ =~ s/^\s+|\s+$//g; $_; } @data2; if ($data2[0] eq 'url'){ $url = "$data2[1]:$data2[2]"; @@ -15564,7 +16460,7 @@ sub get_repos_bsd { #print "url:$url\n" if $url; if ($data2[0] eq 'enabled'){ if ($url && $data2[1] eq 'yes'){ - push @data3, "$url" + push(@data3, "$url"); } $url = ''; } @@ -15574,14 +16470,13 @@ sub get_repos_bsd { $key = repo_data('missing','bsd-package'); } else { - @data3 = url_cleaner(@data3); + @data3 = url_cleaner(\@data3); $key = repo_data('active','bsd-package'); } - @data = ( + push(@rows, {main::key($num++,1,1,$key) => $_}, [@data3], ); - @rows = (@rows,@data); @data3 = (); } } @@ -15590,17 +16485,17 @@ sub get_repos_bsd { elsif (-f $openbsd || -f $openbsd2) { if (-f $openbsd){ @data = repo_builder($openbsd,'openbsd','^installpath','\s*=\s*',1); - @rows = (@rows,@data); + push(@rows,@data); } if (-f $openbsd2){ @data = repo_builder($openbsd2,'openbsd','^(http|ftp)','',1); - @rows = (@rows,@data); + push(@rows,@data); } } elsif (-f $netbsd){ # not an empty row, and not a row starting with # @data = repo_builder($netbsd,'netbsd','^\s*[^#]+$'); - @rows = (@rows,@data); + push(@rows,@data); } # BSDs do not default always to having repo files, so show correct error # mesage in that case @@ -15617,11 +16512,10 @@ sub get_repos_bsd { else { $key = repo_data('missing','bsd-files'); } - @data = ( + push(@rows, {main::key($num++,0,1,'Message') => $key}, [()], ); - @rows = (@rows,@data); } eval $start if $b_log; return @rows; @@ -15685,15 +16579,15 @@ sub repo_builder { eval $start if $b_log; my ($file,$type,$search,$split,$count) = @_; my (@content,@data,$key); - push @dbg_files, $file if $debugger_dir; + push(@dbg_files, $file) if $debugger_dir; if (-r $file){ @content = main::reader($file); @content = grep {/$search/i && !/^\s*$/} @content if @content; - @content = data_cleaner(@content) if @content; + @content = data_cleaner(\@content) if @content; } if ($split && @content){ @content = map { - my @inner = split (/$split/, $_); + my @inner = split(/$split/, $_); $inner[$count]; } @content; } @@ -15702,7 +16596,7 @@ sub repo_builder { } else { $key = repo_data('active',$type); - @content = url_cleaner(@content); + @content = url_cleaner(\@content); } @data = ( {main::key($num++,1,1,$key) => $file}, @@ -15712,16 +16606,16 @@ sub repo_builder { return @data; } sub data_cleaner { - my (@content) = @_; + my ($content) = @_; # basics: trim white space, get rid of double spaces - @content = map { $_ =~ s/^\s+|\s+$//g; $_ =~ s/\s\s+/ /g; $_} @content; - return @content; + @$content = map { $_ =~ s/^\s+|\s+$//g; $_ =~ s/\s\s+/ /g; $_} @$content; + return @$content; } # clean if irc sub url_cleaner { - my (@content) = @_; - @content = map { $_ =~ s/:\//: \//; $_} @content if $b_irc; - return @content; + my ($content) = @_; + @$content = map { $_ =~ s/:\//: \//; $_} @$content if $b_irc; + return @$content; } sub file_path { my ($filename,$dir) = @_; @@ -15751,87 +16645,85 @@ sub get { ( $program = main::check_program('ipmitool') ) ) ) ){ if ($b_ipmi || $b_root){ %sensors = ipmi_data($program); - @data = create_output('ipmi',%sensors); + @data = create_output('ipmi',\%sensors); if (!@data) { $key1 = 'Message'; $val1 = main::row_defaults('sensors-data-ipmi'); #$val1 = main::row_defaults('dev'); @data = ({main::key($num++,0,1,$key1) => $val1,}); } - @rows = (@rows,@data); + push(@rows,@data); $source = 'lm-sensors'; # trips per sensor type output } else { $key1 = 'Permissions'; $val1 = main::row_defaults('sensors-ipmi-root'); @data = ({main::key($num++,0,1,$key1) => $val1,}); - @rows = (@rows,@data); + push(@rows,@data); } } - my $ref = $alerts{'sensors'}; - if ( $$ref{'action'} ne 'use'){ + if ( $alerts{'sensors'}->{'action'} ne 'use'){ #print "here 1\n"; - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; + $key1 = $alerts{'sensors'}->{'action'}; + $val1 = $alerts{'sensors'}->{$key1}; $key1 = ucfirst($key1); @data = ({main::key($num++,0,1,$key1) => $val1,}); - @rows = (@rows,@data); + push(@rows,@data); } else { %sensors = lm_sensors_data(); - @data = create_output($source,%sensors); + @data = create_output($source,\%sensors); #print "here 2\n"; if (!@data) { $key1 = 'Message'; $val1 = main::row_defaults('sensors-data-linux'); @data = ({main::key($num++,0,1,$key1) => $val1,}); } - @rows = (@rows,@data); + push(@rows,@data); } eval $end if $b_log; return @rows; } sub create_output { eval $start if $b_log; - my ($source,%sensors) = @_; + my ($source,$sensors) = @_; # note: might revisit this, since gpu sensors data might be present - return if ! %sensors; - my (@gpu,@data,@rows,@fan_default,@fan_main); + return if ! %$sensors; + my (@gpu,@rows,@fan_default,@fan_main); my ($data_source) = (''); my $fan_number = 0; my $num = 0; my $j = 0; @gpu = gpu_data() if ( $source eq 'sensors' || $source eq 'lm-sensors' ); - my $temp_unit = (defined $sensors{'temp-unit'}) ? " $sensors{'temp-unit'}": ''; - my $cpu_temp = (defined $sensors{'cpu-temp'}) ? $sensors{'cpu-temp'} . $temp_unit: 'N/A'; - my $mobo_temp = (defined $sensors{'mobo-temp'}) ? $sensors{'mobo-temp'} . $temp_unit: 'N/A'; - my $cpu1_key = ($sensors{'cpu2-temp'}) ? 'cpu-1': 'cpu' ; + my $temp_unit = (defined $sensors->{'temp-unit'}) ? " $sensors->{'temp-unit'}": ''; + my $cpu_temp = (defined $sensors->{'cpu-temp'}) ? $sensors->{'cpu-temp'} . $temp_unit: 'N/A'; + my $mobo_temp = (defined $sensors->{'mobo-temp'}) ? $sensors->{'mobo-temp'} . $temp_unit: 'N/A'; + my $cpu1_key = ($sensors->{'cpu2-temp'}) ? 'cpu-1': 'cpu' ; $data_source = $source if ($source eq 'ipmi' || $source eq 'lm-sensors'); - @data = ({ + push(@rows, { main::key($num++,1,1,'System Temperatures') => $data_source, main::key($num++,0,2,$cpu1_key) => $cpu_temp, }); - @rows = (@rows,@data); - if ($sensors{'cpu2-temp'}){ - $rows[$j]{main::key($num++,0,2,'cpu-2')} = $sensors{'cpu2-temp'} . $temp_unit; + if ($sensors->{'cpu2-temp'}){ + $rows[$j]{main::key($num++,0,2,'cpu-2')} = $sensors->{'cpu2-temp'} . $temp_unit; } - if ($sensors{'cpu3-temp'}){ - $rows[$j]{main::key($num++,0,2,'cpu-3')} = $sensors{'cpu3-temp'} . $temp_unit; + if ($sensors->{'cpu3-temp'}){ + $rows[$j]{main::key($num++,0,2,'cpu-3')} = $sensors->{'cpu3-temp'} . $temp_unit; } - if ($sensors{'cpu4-temp'}){ - $rows[$j]{main::key($num++,0,2,'cpu-4')} = $sensors{'cpu4-temp'} . $temp_unit; + if ($sensors->{'cpu4-temp'}){ + $rows[$j]{main::key($num++,0,2,'cpu-4')} = $sensors->{'cpu4-temp'} . $temp_unit; } $rows[$j]{main::key($num++,0,2,'mobo')} = $mobo_temp; - if (defined $sensors{'sodimm-temp'}){ - my $sodimm_temp = $sensors{'sodimm-temp'} . $temp_unit; + if (defined $sensors->{'sodimm-temp'}){ + my $sodimm_temp = $sensors->{'sodimm-temp'} . $temp_unit; $rows[$j]{main::key($num++,0,2,'sodimm')} = $sodimm_temp; } - if (defined $sensors{'psu-temp'}){ - my $psu_temp = $sensors{'psu-temp'} . $temp_unit; + if (defined $sensors->{'psu-temp'}){ + my $psu_temp = $sensors->{'psu-temp'} . $temp_unit; $rows[$j]{main::key($num++,0,2,'psu')} = $psu_temp; } - if (defined $sensors{'ambient-temp'}){ - my $ambient_temp = $sensors{'ambient-temp'} . $temp_unit; + if (defined $sensors->{'ambient-temp'}){ + my $ambient_temp = $sensors->{'ambient-temp'} . $temp_unit; $rows[$j]{main::key($num++,0,2,'ambient')} = $ambient_temp; } if (scalar @gpu == 1 && defined $gpu[0]{'temp'}){ @@ -15845,10 +16737,8 @@ sub create_output { } } $j = scalar @rows; - my $ref_main = $sensors{'fan-main'}; - my $ref_default = $sensors{'fan-default'}; - @fan_main = @$ref_main if @$ref_main; - @fan_default = @$ref_default if @$ref_default; + @fan_main = @{$sensors->{'fan-main'}} if @{$sensors->{'fan-main'}}; + @fan_default = @{$sensors->{'fan-default'}} if @{$sensors->{'fan-default'}}; my $fan_def = ($data_source) ? $data_source : ''; if (!@fan_main && !@fan_default){ $fan_def = ($fan_def) ? "$data_source N/A" : 'N/A'; @@ -15883,9 +16773,9 @@ sub create_output { $rows[$j]{main::key($num++,0,2,"fan-$i")} = $fan_default[$i]; } } - $rows[$j]{main::key($num++,0,2,'psu')} = $sensors{'fan-psu'} if defined $sensors{'fan-psu'}; - $rows[$j]{main::key($num++,0,2,'psu-1')} = $sensors{'fan-psu1'} if defined $sensors{'fan-psu1'}; - $rows[$j]{main::key($num++,0,2,'psu-2')} = $sensors{'fan-psu2'} if defined $sensors{'fan-psu2'}; + $rows[$j]{main::key($num++,0,2,'psu')} = $sensors->{'fan-psu'} if defined $sensors->{'fan-psu'}; + $rows[$j]{main::key($num++,0,2,'psu-1')} = $sensors->{'fan-psu1'} if defined $sensors->{'fan-psu1'}; + $rows[$j]{main::key($num++,0,2,'psu-2')} = $sensors->{'fan-psu2'} if defined $sensors->{'fan-psu2'}; # note: so far, only nvidia-settings returns speed, and that's in percent if (scalar @gpu == 1 && defined $gpu[0]{'fan-speed'}){ my $gpu_fan = $gpu[0]{'fan-speed'} . $gpu[0]{'speed-unit'}; @@ -15897,50 +16787,49 @@ sub create_output { $j = scalar @rows; $rows[$j]{main::key($num++,1,1,'GPU')} = ''; my $gpu_unit = (defined $gpu[0]{'temp-unit'} ) ? " $gpu[0]{'temp-unit'}" : ' C'; - foreach my $ref (@gpu){ - my %info = %$ref; + foreach my $info (@gpu){ # speed unit is either '' or % - my $gpu_fan = (defined $info{'fan-speed'}) ? $info{'fan-speed'} . $info{'speed-unit'}: undef ; - my $gpu_type = $info{'type'}; - my $gpu_temp = (defined $info{'temp'} ) ? $info{'temp'} . $gpu_unit: 'N/A'; + my $gpu_fan = (defined $info->{'fan-speed'}) ? $info->{'fan-speed'} . $info->{'speed-unit'}: undef ; + my $gpu_type = $info->{'type'}; + my $gpu_temp = (defined $info->{'temp'} ) ? $info->{'temp'} . $gpu_unit: 'N/A'; $rows[$j]{main::key($num++,1,2,'device')} = $gpu_type; - if (defined $info{'screen'} ){ - $rows[$j]{main::key($num++,0,3,'screen')} = $info{'screen'}; + if (defined $info->{'screen'} ){ + $rows[$j]{main::key($num++,0,3,'screen')} = $info->{'screen'}; } $rows[$j]{main::key($num++,0,3,'temp')} = $gpu_temp; - if ($extra > 1 && $info{'temp-mem'}){ - $rows[$j]{main::key($num++,0,3,'mem')} = $info{'temp-mem'} . $gpu_unit; + if ($extra > 1 && $info->{'temp-mem'}){ + $rows[$j]{main::key($num++,0,3,'mem')} = $info->{'temp-mem'} . $gpu_unit; } if (defined $gpu_fan){ $rows[$j]{main::key($num++,0,3,'fan')} = $gpu_fan; } - if ($extra > 2 && $info{'watts'}){ - $rows[$j]{main::key($num++,0,3,'watts')} = $info{'watts'}; + if ($extra > 2 && $info->{'watts'}){ + $rows[$j]{main::key($num++,0,3,'watts')} = $info->{'watts'}; } - if ($extra > 2 && $info{'mvolts'}){ - $rows[$j]{main::key($num++,0,3,'mV')} = $info{'mvolts'}; + if ($extra > 2 && $info->{'mvolts'}){ + $rows[$j]{main::key($num++,0,3,'mV')} = $info->{'mvolts'}; } } } if ($extra > 0 && ($source eq 'ipmi' || - ($sensors{'volts-12'} || $sensors{'volts-5'} || $sensors{'volts-3.3'} || $sensors{'volts-vbat'}))){ + ($sensors->{'volts-12'} || $sensors->{'volts-5'} || $sensors->{'volts-3.3'} || $sensors->{'volts-vbat'}))){ $j = scalar @rows; - $sensors{'volts-12'} ||= 'N/A'; - $sensors{'volts-5'} ||= 'N/A'; - $sensors{'volts-3.3'} ||= 'N/A'; - $sensors{'volts-vbat'} ||= 'N/A'; + $sensors->{'volts-12'} ||= 'N/A'; + $sensors->{'volts-5'} ||= 'N/A'; + $sensors->{'volts-3.3'} ||= 'N/A'; + $sensors->{'volts-vbat'} ||= 'N/A'; $rows[$j]{main::key($num++,1,1,'Power')} = $data_source; - $rows[$j]{main::key($num++,0,2,'12v')} = $sensors{'volts-12'}; - $rows[$j]{main::key($num++,0,2,'5v')} = $sensors{'volts-5'}; - $rows[$j]{main::key($num++,0,2,'3.3v')} = $sensors{'volts-3.3'}; - $rows[$j]{main::key($num++,0,2,'vbat')} = $sensors{'volts-vbat'}; + $rows[$j]{main::key($num++,0,2,'12v')} = $sensors->{'volts-12'}; + $rows[$j]{main::key($num++,0,2,'5v')} = $sensors->{'volts-5'}; + $rows[$j]{main::key($num++,0,2,'3.3v')} = $sensors->{'volts-3.3'}; + $rows[$j]{main::key($num++,0,2,'vbat')} = $sensors->{'volts-vbat'}; if ($extra > 1 && $source eq 'ipmi' ){ - $sensors{'volts-dimm-p1'} ||= 'N/A'; - $sensors{'volts-dimm-p2'} ||= 'N/A'; - $rows[$j]{main::key($num++,0,2,'dimm-p1')} = $sensors{'volts-dimm-p1'} if $sensors{'volts-dimm-p1'}; - $rows[$j]{main::key($num++,0,2,'dimm-p2')} = $sensors{'volts-dimm-p2'} if $sensors{'volts-dimm-p2'}; - $rows[$j]{main::key($num++,0,2,'soc-p1')} = $sensors{'volts-soc-p1'} if $sensors{'volts-soc-p1'}; - $rows[$j]{main::key($num++,0,2,'soc-p2')} = $sensors{'volts-soc-p2'} if $sensors{'volts-soc-p2'}; + $sensors->{'volts-dimm-p1'} ||= 'N/A'; + $sensors->{'volts-dimm-p2'} ||= 'N/A'; + $rows[$j]{main::key($num++,0,2,'dimm-p1')} = $sensors->{'volts-dimm-p1'} if $sensors->{'volts-dimm-p1'}; + $rows[$j]{main::key($num++,0,2,'dimm-p2')} = $sensors->{'volts-dimm-p2'} if $sensors->{'volts-dimm-p2'}; + $rows[$j]{main::key($num++,0,2,'soc-p1')} = $sensors->{'volts-soc-p1'} if $sensors->{'volts-soc-p1'}; + $rows[$j]{main::key($num++,0,2,'soc-p2')} = $sensors->{'volts-soc-p2'} if $sensors->{'volts-soc-p2'}; } if (scalar @gpu == 1 && $extra > 2 && ($gpu[0]{'watts'} || $gpu[0]{'mvolts'})){ $rows[$j]{main::key($num++,1,2,'gpu')} = $gpu[0]{'type'}; @@ -15974,12 +16863,12 @@ sub ipmi_data { ($b_ipmitool,$i_key,$i_value,$i_unit) = (1,0,1,2); } @data = main::grabber("$cmd 2>/dev/null"); - # print join ("\n", @data), "\n"; + # print join("\n", @data), "\n"; return if ! @data; foreach (@data){ next if /^\s*$/; # print "$_\n"; - @row = split /\s*\|\s*/, $_; + @row = split(/\s*\|\s*/, $_); #print "$row[$i_value]\n"; next if !main::is_numeric($row[$i_value]); # print "$row[$i_key] - $row[$i_value]\n"; @@ -16110,7 +16999,7 @@ sub ipmi_data { } } # print Data::Dumper::Dumper \%sensors; - %sensors = data_processor(%sensors) if %sensors; + %sensors = process_data(%sensors) if %sensors; main::log_data('dump','ipmi: %sensors',\%sensors) if $b_log; eval $end if $b_log; # print Data::Dumper::Dumper \%sensors; @@ -16121,7 +17010,7 @@ sub lm_sensors_data { my (%sensors); my ($sys_fan_nu) = (0); my ($adapter,$fan_working,$temp_working,$working_unit) = ('','','','',''); - lm_sensors_processor() if !$b_sensors; + process_lm_sensors() if !$b_sensors; foreach $adapter (keys %{$sensors_raw{'main'}}){ next if !$adapter || ref $sensors_raw{'main'}->{$adapter} ne 'ARRAY'; # not sure why hwmon is excluded, forgot to add info in comments @@ -16130,7 +17019,7 @@ sub lm_sensors_data { next; } foreach (@{$sensors_raw{'main'}->{$adapter}}){ - my @working = split /:/, $_; + my @working = split(':', $_); next if !$working[0]; #print "$working[0]:$working[1]\n"; # There are some guesses here, but with more sensors samples it will get closer. @@ -16141,7 +17030,7 @@ sub lm_sensors_data { # note that because of charset issues, no "°" degree sign used, but it is required # in testing regex to avoid error. It might be because I got that data from a forum post, # note directly via debugger. - if ($_ =~ /^(AMBIENT|M\/B|MB|Motherboard|SIO|SYS).*:([0-9\.]+)[\s°]*(C|F)/i) { + if ($_ =~ /^T?(AMBIENT|M\/B|MB|Motherboard|SIO|SYS).*:([0-9\.]+)[\s°]*(C|F)/i) { # avoid SYSTIN: 118 C if (main::is_numeric($2) && $2 < 90 ){ $sensors{'mobo-temp'} = $2; @@ -16157,7 +17046,7 @@ sub lm_sensors_data { # NOTE: I've seen an inexplicable case where: CPU:52.0°C fails to match with [\s°] but # does match with: [\s°]*. I can't account for this, but that's why the * is there # Tdie is a new k10temp-pci syntax for cpu die temp - elsif ($_ =~ /^(CPU.*|Tdie.*):([0-9\.]+)[\s°]*(C|F)/i) { + elsif ($_ =~ /^(T?CPU.*|Tdie.*):([0-9\.]+)[\s°]*(C|F)/i) { $temp_working = $2; $working_unit = $3; if ( !$sensors{'cpu-temp'} || @@ -16171,12 +17060,12 @@ sub lm_sensors_data { $working_unit = $2; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; } - elsif ($_ =~ /^(P\/S|Power).*:([0-9\.]+)[\s°]*(C|F)/i) { + elsif ($_ =~ /^T?(P\/S|Power).*:([0-9\.]+)[\s°]*(C|F)/i) { $sensors{'psu-temp'} = $2; $working_unit = $3; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; } - elsif ($_ =~ /^SODIMM.*:([0-9\.]+)[\s°]*(C|F)/i) { + elsif ($_ =~ /^T?(dimm|mem|sodimm).*:([0-9\.]+)[\s°]*(C|F)/i) { $sensors{'sodimm-temp'} = $1; $working_unit = $2; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; @@ -16212,7 +17101,7 @@ sub lm_sensors_data { } # final fallback if all else fails, funtoo user showed sensors putting # temp on wrapped second line, not handled - elsif ($_ =~ /^(core0|core 0|Physical id 0)(.*):([0-9\.]+)[\s°]*(C|F)/i) { + elsif ($_ =~ /^T?(core0|core 0|Physical id 0)(.*):([0-9\.]+)[\s°]*(C|F)/i) { $temp_working = $3; $working_unit = $4; if ( !$sensors{'core-0-temp'} || @@ -16222,26 +17111,26 @@ sub lm_sensors_data { $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; } # note: can be cpu fan:, cpu fan speed:, etc. - elsif (!$sensors{'fan-main'}[1] && $_ =~ /^(CPU|Processor).*:([0-9]+)[\s]RPM/i) { + elsif (!$sensors{'fan-main'}[1] && $_ =~ /^F?(CPU|Processor).*:([0-9]+)[\s]RPM/i) { $sensors{'fan-main'} = () if !$sensors{'fan-main'}; $sensors{'fan-main'}[1] = $2; } - elsif (!$sensors{'fan-main'}[2] && $_ =~ /^(M\/B|MB|SYS|Motherboard).*:([0-9]+)[\s]RPM/i) { + elsif (!$sensors{'fan-main'}[2] && $_ =~ /^F?(M\/B|MB|SYS|Motherboard).*:([0-9]+)[\s]RPM/i) { $sensors{'fan-main'} = () if !$sensors{'fan-main'}; $sensors{'fan-main'}[2] = $2; } - elsif (!$sensors{'fan-main'}[3] && $_ =~ /(Power|P\/S|POWER).*:([0-9]+)[\s]RPM/i) { + elsif (!$sensors{'fan-main'}[3] && $_ =~ /F?(Power|P\/S|POWER).*:([0-9]+)[\s]RPM/i) { $sensors{'fan-main'} = () if !$sensors{'fan-main'}; $sensors{'fan-main'}[3] = $2; } - elsif (!$sensors{'fan-main'}[4] && $_ =~ /(SODIMM).*:([0-9]+)[\s]RPM/i) { + elsif (!$sensors{'fan-main'}[4] && $_ =~ /F?(dimm|mem|sodimm).*:([0-9]+)[\s]RPM/i) { $sensors{'fan-main'} = () if !$sensors{'fan-main'}; $sensors{'fan-main'}[4] = $2; } # note that the counters are dynamically set for fan numbers here # otherwise you could overwrite eg aux fan2 with case fan2 in theory # note: cpu/mobo/ps/sodimm are 1/2/3/4 - elsif ($_ =~ /^(AUX|CASE|CHASSIS).*:([0-9]+)[\s]RPM/i) { + elsif ($_ =~ /^F?(AUX|CASE|CHASSIS|FRONT|REAR).*:([0-9]+)[\s]RPM/i) { $temp_working = $2; $sensors{'fan-main'} = () if !$sensors{'fan-main'}; for ( my $i = 5; $i < 30; $i++ ){ @@ -16274,49 +17163,57 @@ sub lm_sensors_data { } } if ($extra > 0){ - if ($_ =~ /^[+]?(12 Volt|12V).*:([0-9\.]+)\sV/i) { + if ($_ =~ /^[+]?(12 Volt|12V|V\+?12).*:([0-9\.]+)\sV/i) { $sensors{'volts-12'} = $2; } # note: 5VSB is a field name - elsif ($_ =~ /^[+]?(5 Volt|5V):([0-9\.]+)\sV/i) { + elsif ($_ =~ /^[+]?(5 Volt|5V|V\+?5):([0-9\.]+)\sV/i) { $sensors{'volts-5'} = $2; } - elsif ($_ =~ /^[+]?(3\.3 Volt|3\.3V).*:([0-9\.]+)\sV/i) { + elsif ($_ =~ /^[+]?(3\.3 Volt|3\.3V|V\+?3\.3).*:([0-9\.]+)\sV/i) { $sensors{'volts-3.3'} = $2; } elsif ($_ =~ /^(Vbat).*:([0-9\.]+)\sV/i) { $sensors{'volts-vbat'} = $2; } + elsif ($_ =~ /^v(dimm|mem|sodimm).*:([0-9\.]+)\sV/i) { + $sensors{'volts-mem'} = $2; + } } } } # print Data::Dumper::Dumper \%sensors; - %sensors = data_processor(%sensors) if %sensors; + %sensors = process_data(%sensors) if %sensors; main::log_data('dump','lm-sensors: %sensors',\%sensors) if $b_log; # print Data::Dumper::Dumper \%sensors; eval $end if $b_log; return %sensors; } -sub lm_sensors_processor { +sub process_lm_sensors { eval $start if $b_log; my (@data,@sensors_data,@values); my ($adapter,$holder,$type) = ('','',''); - @sensors_data = main::grabber(main::check_program('sensors') . " 2>/dev/null"); - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/amdgpu-w-fan-speed-stretch-k10.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/peci-tin-geggo.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-w-other-biker.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-asus-chassis-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-devnull-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-jammin1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-mx-incorrect-1.txt"; - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-maximus-arch-1.txt"; - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/kernel-58-sensors-ant-1.txt"; - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-zenpower-nvme-2.txt"; - # @sensors_data = main::reader($file); # only way to get sensor array data? Unless using sensors -j, but can't assume json - # print join ("\n", @sensors_data), "\n"; + if ($b_fake_sensors){ + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/amdgpu-w-fan-speed-stretch-k10.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/peci-tin-geggo.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-w-other-biker.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-asus-chassis-1.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-devnull-1.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-jammin1.txt"; + #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-mx-incorrect-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-maximus-arch-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/kernel-58-sensors-ant-1.txt"; + # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-zenpower-nvme-2.txt"; + #@sensors_data = main::reader($file); + } + else { + # only way to get sensor array data? Unless using sensors -j, but can't assume json + @sensors_data = main::grabber($alerts{'sensors'}->{'path'} . ' 2>/dev/null'); + } + # print join("\n", @sensors_data), "\n"; if (@sensors_data){ @sensors_data = map {$_ =~ s/\s*:\s*\+?/:/;$_} @sensors_data; - push @sensors_data, 'END'; + push(@sensors_data, 'END'); } #print Data::Dumper::Dumper \@sensors_data; foreach (@sensors_data){ @@ -16349,7 +17246,7 @@ sub lm_sensors_processor { $adapter = $holder; } elsif (/\S:\S/){ - push @values, $_; + push(@values, $_); } else { $holder = $_; @@ -16375,11 +17272,11 @@ sub sysctl_data { my $sensor = $1; my $type = $2; my $number = $3; - my @working = split /:/, $_; + my @working = split(':', $_); } last if /^(hw.cpuspeed|hw.vendor|hw.physmem)/; } - %sensors = data_processor(%sensors) if %sensors; + %sensors = process_data(%sensors) if %sensors; main::log_data('dump','%sensors',\%sensors) if $b_log; # print Data::Dumper::Dumper \%sensors; eval $end if $b_log; @@ -16397,7 +17294,7 @@ sub set_temp_unit { return $return_unit; } -sub data_processor { +sub process_data { eval $start if $b_log; my (%sensors) = @_; my ($cpu_temp,$cpu2_temp,$cpu3_temp,$cpu4_temp,$index_count_fan_default, @@ -16654,7 +17551,7 @@ sub gpu_data { @data = main::grabber("$path -q screens 2>/dev/null"); foreach (@data){ if ( /(:[0-9]\.[0-9])/ ) { - push @screens, $1; + push(@screens, $1); } } } @@ -16686,7 +17583,7 @@ sub gpu_data { $cmd = "$path -c $screen2 $cmd 2>/dev/null"; @data = main::grabber($cmd); main::log_data('cmd',$cmd) if $b_log; - @data = (@data,@data2); + push(@data,@data2); $j = scalar @gpudata; $gpudata[$j] = ({}); foreach my $item (@data){ @@ -16782,8 +17679,7 @@ sub get { eval $start if $b_log; my (@data,@rows,$key1,$val1); my $num = 0; - my $ref = $alerts{'dmidecode'}; - if ($b_fake_dmidecode || ( $$ref{'action'} eq 'use' && (!$b_arm || $b_slot_tool ) )){ + if ($b_fake_dmidecode || ( $alerts{'dmidecode'}->{'action'} eq 'use' && (!$b_arm || $b_slot_tool ) )){ @rows = slot_data(); } elsif ($b_arm && !$b_slot_tool){ @@ -16791,9 +17687,9 @@ sub get { $val1 = main::row_defaults('arm-pci',''); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } - elsif ( $$ref{'action'} ne 'use'){ - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; + elsif ( $alerts{'dmidecode'}->{'action'} ne 'use'){ + $key1 = $alerts{'dmidecode'}->{'action'}; + $val1 = $alerts{'dmidecode'}->{$key1}; $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); } @@ -16802,19 +17698,18 @@ sub get { } sub slot_data { eval $start if $b_log; - my (@data,@rows); + my (@rows); my $num = 0; - foreach (@dmi){ + foreach my $entry (@dmi){ $num = 1; - my @ref = @$_; - if ($ref[0] == 9){ + if ($entry->[0] == 9){ my ($designation,$id,$length,$type,$usage) = ('','','','',''); # skip first two row, we don't need that data - splice @ref, 0, 2 if @ref; + splice @$entry, 0, 2 if @$entry; my $j = scalar @rows; - foreach my $item (@ref){ + foreach my $item (@$entry){ if ($item !~ /^~/){ # skip the indented rows - my @value = split /:\s+/, $item; + my @value = split(/:\s+/, $item); if ($value[0] eq 'Type'){ $type = $value[1]; } @@ -16841,14 +17736,11 @@ sub slot_data { elsif ($type && $designation) { $type = "$type $designation"; } - @data = ( - { + push(@rows, { main::key($num++,1,1,'Slot') => $id, main::key($num++,0,2,'type') => $type, main::key($num++,0,2,'status') => $usage, - }, - ); - @rows = (@rows,@data); + },); if ($extra > 1 ){ $rows[$j]{main::key($num++,0,2,'length')} = $length; } @@ -16857,10 +17749,9 @@ sub slot_data { } if (!@rows){ my $key = 'Message'; - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults('pci-slot-data',''), },); - @rows = (@rows,@data); } eval $end if $b_log; return @rows; @@ -16873,14 +17764,13 @@ package SwapData; sub get { eval $start if $b_log; - my (@data,@rows,$key1,$val1); + my (@rows,$key1,$val1); my $num = 0; - @rows =create_output(); + @rows = create_output(); if (!@rows){ - @data = ( + push(@rows, {main::key($num++,0,1,'Alert') => main::row_defaults('swap-data')}, ); - @rows = (@data); } eval $end if $b_log; return @rows; @@ -16889,28 +17779,27 @@ sub create_output { eval $start if $b_log; my $num = 0; my $j = 0; - my (@data,@data2,%part,@rows,$dev,$percent,$raw_size,$size,$used); + my (%part,@rows,$dev,$percent,$raw_size,$size,$used); + main::set_proc_partitions() if !$bsd_type && !$b_proc_partitions; + main::set_mapper() if !$b_mapper; my @swap_data = PartitionData::swap_data(); - foreach my $ref (@swap_data){ - my %row = %$ref; + foreach my $row (@swap_data){ $num = 1; - @data2 = main::get_size($row{'size'}) if (defined $row{'size'}); - $size = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - @data2 = main::get_size($row{'used'}) if (defined $row{'used'}); - $used = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - $percent = (defined $row{'percent-used'}) ? ' (' . $row{'percent-used'} . '%)' : ''; + $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; + $used = main::get_size($row->{'used'},'string','N/A'); # used can be 0 + $percent = (defined $row->{'percent-used'}) ? ' (' . $row->{'percent-used'} . '%)' : ''; %part = (); - $dev = ($row{'swap-type'} eq 'file') ? 'file' : 'dev'; - $row{'swap-type'} = ($row{'swap-type'}) ? $row{'swap-type'} : 'N/A'; + $dev = ($row->{'swap-type'} eq 'file') ? 'file' : 'dev'; + $row->{'swap-type'} = ($row->{'swap-type'}) ? $row->{'swap-type'} : 'N/A'; if ($b_admin && !$bsd_type && $j == 0){ $j = scalar @rows; - if (defined $row{'swappiness'} || defined $row{'cache-pressure'}){ + if (defined $row->{'swappiness'} || defined $row->{'cache-pressure'}){ $rows[$j]{main::key($num++,1,1,'Kernel')} = ''; - if (defined $row{'swappiness'}){ - $rows[$j]{main::key($num++,0,2,'swappiness')} = $row{'swappiness'}; + if (defined $row->{'swappiness'}){ + $rows[$j]{main::key($num++,0,2,'swappiness')} = $row->{'swappiness'}; } - if (defined $row{'cache-pressure'}){ - $rows[$j]{main::key($num++,0,2,'cache pressure')} = $row{'cache-pressure'}; + if (defined $row->{'cache-pressure'}){ + $rows[$j]{main::key($num++,0,2,'cache pressure')} = $row->{'cache-pressure'}; } } else { @@ -16918,47 +17807,46 @@ sub create_output { } } $j = scalar @rows; - @data = ({ - main::key($num++,1,1,'ID') => $row{'id'}, - main::key($num++,0,2,'type') => $row{'swap-type'}, + push(@rows, { + main::key($num++,1,1,'ID') => $row->{'id'}, + main::key($num++,0,2,'type') => $row->{'swap-type'}, }); - @rows = (@rows,@data); # not used for swap as far as I know - if ($b_admin && $row{'raw-size'} ){ + if ($b_admin && $row->{'raw-size'} ){ # It's an error! permissions or missing tool - if (!main::is_numeric($row{'raw-size'})){ - $raw_size = $row{'raw-size'}; - } - else { - @data2 = main::get_size($row{'raw-size'}); - $raw_size = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - } + $raw_size = main::get_size($row->{'raw-size'},'string'); $rows[$j]{main::key($num++,0,2,'raw size')} = $raw_size; } # not used for swap as far as I know - if ($b_admin && $row{'raw-available'} && $size ne 'N/A'){ - $size .= ' (' . $row{'raw-available'} . '%)'; + if ($b_admin && $row->{'raw-available'} && $size ne 'N/A'){ + $size .= ' (' . $row->{'raw-available'} . '%)'; } $rows[$j]{main::key($num++,0,2,'size')} = $size; $rows[$j]{main::key($num++,0,2,'used')} = $used . $percent; # not used for swap as far as I know - if ($b_admin && $row{'block-size'}){ - $rows[$j]{main::key($num++,0,2,'block size')} = $row{'block-size'} . ' B';; - #$rows[$j]{main::key($num++,0,2,'physical')} = $row{'block-size'} . ' B'; - #$rows[$j]{main::key($num++,0,2,'logical')} = $row{'block-logical'} . ' B'; + if ($b_admin && $row->{'block-size'}){ + $rows[$j]{main::key($num++,0,2,'block size')} = $row->{'block-size'} . ' B';; + #$rows[$j]{main::key($num++,0,2,'physical')} = $row->{'block-size'} . ' B'; + #$rows[$j]{main::key($num++,0,2,'logical')} = $row->{'block-logical'} . ' B'; } - if ($extra > 1 && defined $row{'priority'}){ - $rows[$j]{main::key($num++,0,2,'priority')} = $row{'priority'}; + if ($extra > 1 && defined $row->{'priority'}){ + $rows[$j]{main::key($num++,0,2,'priority')} = $row->{'priority'}; } - $row{'mount'} =~ s|/home/[^/]+/(.*)|/home/$filter_string/$1| if $row{'mount'} && $use{'filter'}; - $rows[$j]{main::key($num++,0,2,$dev)} = ($row{'mount'}) ? $row{'mount'} : 'N/A'; - if ($show{'label'} && ($row{'label'} || $row{'swap-type'} eq 'partition') ){ - $row{'label'} = main::apply_partition_filter('part', $row{'label'}, '') if $use{'filter-label'}; - $rows[$j]{main::key($num++,0,2,'label')} = ($row{'label'}) ? $row{'label'}: 'N/A'; + $row->{'mount'} =~ s|/home/[^/]+/(.*)|/home/$filter_string/$1| if $row->{'mount'} && $use{'filter'}; + $rows[$j]{main::key($num++,1,2,$dev)} = ($row->{'mount'}) ? $row->{'mount'} : 'N/A'; + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,3,'maj-min')} = $row->{'maj-min'}; } - if ($show{'uuid'} && ($row{'uuid'} || $row{'swap-type'} eq 'partition' )){ - $row{'uuid'} = main::apply_partition_filter('part', $row{'uuid'}, '') if $use{'filter-uuid'}; - $rows[$j]{main::key($num++,0,2,'uuid')} = ($row{'uuid'}) ? $row{'uuid'}: 'N/A'; + if ($extra > 0 && $row->{'dev-mapped'}){ + $rows[$j]{main::key($num++,0,3,'mapped')} = $row->{'dev-mapped'}; + } + if ($show{'label'} && ($row->{'label'} || $row->{'swap-type'} eq 'partition') ){ + $row->{'label'} = main::apply_partition_filter('part', $row->{'label'}, '') if $use{'filter-label'}; + $rows[$j]{main::key($num++,0,2,'label')} = ($row->{'label'}) ? $row->{'label'}: 'N/A'; + } + if ($show{'uuid'} && ($row->{'uuid'} || $row->{'swap-type'} eq 'partition' )){ + $row->{'uuid'} = main::apply_partition_filter('part', $row->{'uuid'}, '') if $use{'filter-uuid'}; + $rows[$j]{main::key($num++,0,2,'uuid')} = ($row->{'uuid'}) ? $row->{'uuid'}: 'N/A'; } } eval $end if $b_log; @@ -16980,14 +17868,14 @@ sub get { $val1 = main::row_defaults('unmounted-data-bsd'); } else { - if (my $file = main::system_files('partitions')){ - @data = unmounted_data($file); + if (main::system_files('partitions')){ + @data = unmounted_data(); if (!@data){ $key1 = 'Message'; $val1 = main::row_defaults('unmounted-data'); } else { - @rows = create_output(@data); + @rows = create_output(\@data); } } else { @@ -17003,17 +17891,15 @@ sub get { } sub create_output { eval $start if $b_log; - my (@unmounted) = @_; - my (@data,@rows,$fs); - my $num = 0; - @unmounted = sort { $a->{'dev-base'} cmp $b->{'dev-base'} } @unmounted; - foreach my $ref (@unmounted){ - my %row = %$ref; + my ($unmounted) = @_; + my (@rows,$fs); + my ($j,$num) = (0,0); + @$unmounted = sort { $a->{'dev-base'} cmp $b->{'dev-base'} } @$unmounted; + foreach my $row (@$unmounted){ $num = 1; - my @data2 = main::get_size($row{'size'}) if (defined $row{'size'}); - my $size = (@data2) ? $data2[0] . ' ' . $data2[1]: 'N/A'; - if ($row{'fs'}){ - $fs = lc($row{'fs'}); + my $size = ($row->{'size'}) ? main::get_size($row->{'size'},'string') : 'N/A'; + if ($row->{'fs'}){ + $fs = lc($row->{'fs'}); } else { if (main::check_program('file')){ @@ -17023,72 +17909,87 @@ sub create_output { $fs = main::row_defaults('tool-missing-basic','file'); } } - $row{'label'} = main::apply_partition_filter('part', $row{'label'}, '') if $use{'filter-label'}; - $row{'uuid'} = main::apply_partition_filter('part', $row{'uuid'}, '') if $use{'filter-uuid'}; - @data = ({ - main::key($num++,1,1,'ID') => "/dev/$row{'dev-base'}", - main::key($num++,0,2,'size') => $size, - main::key($num++,0,2,'fs') => $fs, - main::key($num++,0,2,'label') => $row{'label'}, - main::key($num++,0,2,'uuid') => $row{'uuid'}, + $row->{'label'} = main::apply_partition_filter('part', $row->{'label'}, '') if $use{'filter-label'}; + $row->{'uuid'} = main::apply_partition_filter('part', $row->{'uuid'}, '') if $use{'filter-uuid'}; + $j = scalar @rows; + push(@rows, { + main::key($num++,1,1,'ID') => "/dev/$row->{'dev-base'}", }); - @rows = (@rows,@data); + if ($b_admin && $row->{'maj-min'}){ + $rows[$j]{main::key($num++,0,2,'maj-min')} = $row->{'maj-min'}; + } + if ($extra > 0 && $row->{'dev-mapped'}){ + $rows[$j]{main::key($num++,0,2,'mapped')} = $row->{'dev-mapped'}; + } + $rows[$j]{main::key($num++,0,2,'size')} = $size; + $rows[$j]{main::key($num++,0,2,'fs')} = $fs; + $rows[$j]{main::key($num++,0,2,'label')} = $row->{'label'}; + $rows[$j]{main::key($num++,0,2,'uuid')} = $row->{'uuid'}; } eval $end if $b_log; return @rows; } sub unmounted_data { eval $start if $b_log; - my ($file) = @_; - my ($fs,$label,$size,$uuid,@data,%part,@unmounted); + my ($dev_mapped,$fs,$label,$maj_min,$size,$uuid,%part,@unmounted); # last filters to make sure these are dumped my @filters = ('scd[0-9]+','sr[0-9]+','cdrom[0-9]*','cdrw[0-9]*', 'dvd[0-9]*','dvdrw[0-9]*','fd[0-9]','ram[0-9]*'); - my @mounts = main::reader($file,'strip'); my $num = 0; - PartitionData::set_lsblk() if !$bsd_type && !$b_lsblk; # set labels, uuid, gpart PartitionData::partition_data() if !$b_partitions; - PartitionData::set_label_uuid() if !$b_label_uuid; RaidData::raid_data() if !$b_raid; my @mounted = get_mounted(); #print join("\n",(@filters,@mounted)),"\n"; - foreach (@mounts){ - my @working = split /\s+/, $_; - ($fs,$label,$uuid,$size) = ('','','',''); + foreach my $row (@proc_partitions){ + ($dev_mapped,$fs,$label,$maj_min,$uuid,$size) = ('','','','','',''); # note that size 1 means it is a logical extended partition container # lvm might have dm-1 type syntax # need to exclude loop type file systems, squashfs for example # NOTE: nvme needs special treatment because the main device is: nvme0n1 # note: $working[2] != 1 is wrong, it's not related - # note: for zfs using /dev/sda no partitions, this will also remove those from - # the unmounted report because sdb is found in sdb1, this is acceptable + # note: for zfs using /dev/sda no partitions, previous rule would have removed + # the unmounted report because sdb was found in sdb1, but match of eg sdb1 and sdb12 + # makes this a problem, so usinig zfs_member test instead to filter out zfs members. # in arm/android seen /dev/block/mmcblk0p12 - #print "mount: $working[-1] row: $_ \n"; - if ( $working[-1] !~ /^(nvme[0-9]+n|mmcblk|mtdblk|mtdblock)[0-9]+$/ && - $working[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && - $working[-1] !~ /\bloop/ && - !(grep {$working[-1] =~ /$_$/} (@filters,@mounted)) && - !(grep {$_ =~ /(block\/)?$working[-1]$/} @mounted)){ - %part = PartitionData::check_lsblk($working[-1],0) if (@lsblk && $working[-1]); - if (%part){ - $fs = $part{'fs'}; - $label = $part{'label'}; - $uuid = $part{'uuid'}; - $size = $part{'size'} if $part{'size'} && !$working[2]; + #print "mount: $row->[-1]\n"; + if ( $row->[-1] !~ /^(nvme[0-9]+n|mmcblk|mtdblk|mtdblock)[0-9]+$/ && + $row->[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && + $row->[-1] !~ /\bloop/ && + !(grep {$row->[-1] =~ /$_$/} (@filters,@mounted)) && + !(grep {$_ =~ /(block\/)?$row->[-1]$/} @mounted)){ + $dev_mapped = $dmmapper{$row->[-1]} if $dmmapper{$row->[-1]}; + if (@lsblk){ + my $id = ($dev_mapped) ? $dev_mapped: $row->[-1]; + %part = main::get_lsblk($id); + if (%part){ + $fs = $part{'fs'}; + $label = $part{'label'}; + $maj_min = $part{'maj-min'}; + $uuid = $part{'uuid'}; + $size = $part{'size'} if $part{'size'} && !$row->[2]; + } } - $size ||= $working[2]; - $fs = unmounted_filesystem($working[-1]) if !$fs; - $label = PartitionData::get_label("/dev/$working[-1]") if !$label; - $uuid = PartitionData::get_uuid("/dev/$working[-1]") if !$uuid; - @data = ({ - 'dev-base' => $working[-1], + $size ||= $row->[2]; + $fs = unmounted_filesystem($row->[-1]) if !$fs; + # seen: (zfs|lvm2|linux_raid)_member; crypto_luks + # no te: lvm, raid members are neverm ounted. luks member is never mounted. + next if $fs && $fs =~ /(bcache|crypto|luks|_member)$/i; + # these components of lvm raid will show as partitions byt are reserved private lvm member + # See man lvm for all current reserved private volume names + next if $dev_mapped && $dev_mapped =~ /_([ctv]data|corig|[mr]image|mlog|[crt]meta|pmspare|pvmove|vorigin)(_[0-9]+)?$/; + $label = PartitionData::get_label("/dev/$row->[-1]") if !$label; + $maj_min = "$row->[0]:$row->[1]" if !$maj_min; + $uuid = PartitionData::get_uuid("/dev/$row->[-1]") if !$uuid; + push(@unmounted, { + 'dev-base' => $row->[-1], + 'dev-mapped' => $dev_mapped, 'fs' => $fs, 'label' => $label, + 'maj-min' => $maj_min, 'size' => $size, 'uuid' => $uuid, }); - @unmounted = (@unmounted,@data); } } # print Data::Dumper::Dumper @unmounted; @@ -17099,24 +18000,19 @@ sub unmounted_data { sub get_mounted { eval $start if $b_log; my (@mounted); - foreach my $ref (@partitions){ - my %row = %$ref; - push @mounted, $row{'dev-base'} if $row{'dev-base'}; + foreach my $row (@partitions){ + push(@mounted, $row->{'dev-base'}) if $row->{'dev-base'}; } - foreach my $ref (@raid){ - my %row = %$ref; - my $ref2 = $row{'arrays'}; + foreach my $row ((@lvm_raid,@md_raid,@zfs_raid)){ # we want to not show md0 etc in unmounted report - push @mounted, $row{'id'} if $row{'id'}; - my @arrays = (ref $ref2 eq 'ARRAY' ) ? @$ref2 : (); + push(@mounted, $row->{'id'}) if $row->{'id'}; + my @arrays = (ref $row->{'arrays'} eq 'ARRAY' ) ? @{$row->{'arrays'}} : (); @arrays = grep {defined $_} @arrays; foreach my $array (@arrays){ - my %row2 = %$array; - my $ref3 = $row2{'components'}; - my @components = (ref $ref3 eq 'ARRAY') ? @$ref3 : (); + my @components = (ref $array->{'components'} eq 'ARRAY') ? @{$array->{'components'}} : (); foreach my $component (@components){ - my @temp = split /~/, $component; - push @mounted, $temp[0]; + my @temp = split('~', $component); + push(@mounted, $temp[0]); } } } @@ -17163,18 +18059,16 @@ package UsbData; sub get { eval $start if $b_log; - my (@data,@rows,$key1,$val1); + my (@rows,$key1,$val1); my $num = 0; - my $ref = $alerts{'lsusb'}; - my $ref2 = $alerts{'usbdevs'}; - if ( !@usb && $$ref{'action'} ne 'use' && $$ref2{'action'} ne 'use'){ + if ( !@usb && $alerts{'lsusb'}->{'action'} ne 'use' && $alerts{'usbdevs'}->{'action'} ne 'use'){ if ($os eq 'linux' ){ - $key1 = $$ref{'action'}; - $val1 = $$ref{$key1}; + $key1 = $alerts{'lsusb'}->{'action'}; + $val1 = $alerts{'lsusb'}->{$key1}; } else { - $key1 = $$ref2{'action'}; - $val1 = $$ref2{$key1}; + $key1 = $alerts{'usbdevs'}->{'action'}; + $val1 = $alerts{'usbdevs'}->{$key1}; } $key1 = ucfirst($key1); @rows = ({main::key($num++,0,1,$key1) => $val1,}); @@ -17183,10 +18077,9 @@ sub get { @rows = usb_data(); if (!@rows){ my $key = 'Message'; - @data = ({ + push(@rows, { main::key($num++,0,1,$key) => main::row_defaults('usb-data',''), },); - @rows = (@rows,@data); } } eval $end if $b_log; @@ -17195,45 +18088,43 @@ sub get { sub usb_data { eval $start if $b_log; return if ! @usb; - my (@data,@rows); + my (@rows); my ($b_hub,$bus_id,$chip_id,$driver,$ind_sc,$path_id,$ports,$product,$serial,$speed,$type); my $num = 0; my $j = 0; # note: the data has been presorted in set_lsusb_data by: # bus id then device id, so we don't need to worry about the order - foreach my $ref (@usb){ - my @id = @$ref; + foreach my $id (@usb){ $j = scalar @rows; ($b_hub,$ind_sc,$num) = (0,3,1); - $chip_id = $id[7]; + $chip_id = $id->[7]; ($driver,$path_id,$ports,$product, $serial,$speed,$type) = ('','','','','','',''); - $speed = ( main::is_numeric($id[8]) ) ? sprintf("%1.1f",$id[8]) : $id[8] if $id[8]; - $product = main::cleaner($id[13]) if $id[13]; - $serial = main::apply_filter($id[16]) if $id[16]; + $speed = ( main::is_numeric($id->[8]) ) ? sprintf("%1.1f",$id->[8]) : $id->[8] if $id->[8]; + $product = main::cleaner($id->[13]) if $id->[13]; + $serial = main::apply_filter($id->[16]) if $id->[16]; $product ||= 'N/A'; $speed ||= 'N/A'; - $path_id = $id[2] if $id[2]; - $bus_id = "$path_id:$id[1]"; + $path_id = $id->[2] if $id->[2]; + $bus_id = "$path_id:$id->[1]"; # it's a hub - if ($id[4] eq '9'){ - $ports = $id[10] if $id[10]; + if ($id->[4] eq '9'){ + $ports = $id->[10] if $id->[10]; $ports ||= 'N/A'; #print "pt0:$protocol\n"; - @data = ({ + push(@rows, { main::key($num++,1,1,'Hub') => $bus_id, main::key($num++,0,2,'info') => $product, main::key($num++,0,2,'ports') => $ports, main::key($num++,0,2,'rev') => $speed, },); - @rows = (@rows,@data); $b_hub = 1; $ind_sc =2; } # it's a device else { - $type = $id[14] if $id[14]; - $driver = $id[15] if $id[15]; + $type = $id->[14] if $id->[14]; + $driver = $id->[15] if $id->[15]; $type ||= 'N/A'; $driver ||= 'N/A'; #print "pt3:$class:$product\n"; @@ -17243,16 +18134,16 @@ sub usb_data { if ($extra > 0){ $rows[$j]{main::key($num++,0,3,'driver')} = $driver; } - if ($extra > 2 && $id[9]){ - $rows[$j]{main::key($num++,0,3,'interfaces')} = $id[9]; + if ($extra > 2 && $id->[9]){ + $rows[$j]{main::key($num++,0,3,'interfaces')} = $id->[9]; } $rows[$j]{main::key($num++,0,3,'rev')} = $speed; } # for either hub or device - if ($extra > 2 && main::is_numeric($id[17])){ - my $speed = $id[17]; - if ($speed >= 1000) {$speed = ($id[17] / 1000 ) . " Gb/s"} - else {$speed = $id[17] . " Mb/s"} + if ($extra > 2 && main::is_numeric($id->[17])){ + my $speed = $id->[17]; + if ($speed >= 1000) {$speed = ($id->[17] / 1000 ) . " Gb/s"} + else {$speed = $id->[17] . " Mb/s"} $rows[$j]{main::key($num++,0,$ind_sc,'speed')} = $speed; } if ($extra > 1){ @@ -17286,14 +18177,14 @@ sub get { sub create_output { eval $start if $b_log; my ($j,$num) = (0,0); - my (@data,@location,@rows,$value,%weather,); + my (@location,@rows,$value,%weather,); my ($conditions) = ('NA'); if ($show{'weather-location'}){ my $location_string; $location_string = $show{'weather-location'}; $location_string =~ s/\+/ /g; if ( $location_string =~ /,/){ - my @temp = split /,/, $location_string; + my @temp = split(',', $location_string); my $sep = ''; my $string = ''; foreach (@temp){ @@ -17314,7 +18205,7 @@ sub create_output { }); } } - %weather = get_weather(@location); + %weather = get_weather(\@location); if ($weather{'error'}) { return @rows = ({ main::key($num++,0,1,'Message') => main::row_defaults('weather-error',$weather{'error'}), @@ -17328,12 +18219,11 @@ sub create_output { $conditions = "$weather{'weather'}"; my $temp = unit_output($weather{'temp'},$weather{'temp-c'},'C',$weather{'temp-f'},'F'); $j = scalar @rows; - @data = ({ + push(@rows, { main::key($num++,1,1,'Report') => '', main::key($num++,0,2,'temperature') => $temp, main::key($num++,0,2,'conditions') => $conditions, },); - @rows = (@rows,@data); if ($extra > 0){ my $pressure = unit_output($weather{'pressure'},$weather{'pressure-mb'},'mb',$weather{'pressure-in'},'in'); my $wind = wind_output($weather{'wind'},$weather{'wind-direction'},$weather{'wind-mph'},$weather{'wind-ms'}, @@ -17377,10 +18267,9 @@ sub create_output { if ($extra > 2){ if ($weather{'forecast'}){ $j = scalar @rows; - @data = ({ + push(@rows, { main::key($num++,1,1,'Forecast') => $weather{'forecast'}, },); - @rows = (@rows,@data); } } } @@ -17389,10 +18278,9 @@ sub create_output { if ($extra > 2 && !$use{'filter'}){ $location = complete_location($location[1],$weather{'city'},$weather{'state'},$weather{'country'}); } - @data = ({ + push(@rows, { main::key($num++,1,1,'Locale') => $location, },); - @rows = (@rows,@data); if ($extra > 2 && !$use{'filter'} && ($weather{'elevation-m'} || $weather{'elevation-ft'} )){ $rows[$j]{main::key($num++,0,2,'altitude')} = elevation_output($weather{'elevation-m'},$weather{'elevation-ft'}); } @@ -17478,15 +18366,15 @@ sub wind_output { # calculate and round, order matters so that rounding only happens after math done $ms = 0.44704 * $mph if defined $mph && !defined $ms; $mph = $ms * 2.23694 if defined $ms && !defined $mph; - $kmh = sprintf("%.0f", 18 * $ms / 5) if defined $ms; - $ms = sprintf("%.1f", $ms ) if defined $ms; # very low mph speeds yield 0, which is wrong + $kmh = sprintf("%.0f", 18*$ms/5) if defined $ms; + $ms = sprintf("%.1f", $ms) if defined $ms; # very low mph speeds yield 0, which is wrong $mph = sprintf("%.0f", $mph) if defined $mph; $gust_ms = 0.44704 * $gust_mph if $gust_mph && !$gust_ms; $gust_kmh = 18 * $gust_ms / 5 if $gust_ms; $gust_mph = $gust_ms * 2.23694 if $gust_ms && !$gust_mph; $gust_mph = sprintf("%.0f", $gust_mph) if $gust_mph; $gust_kmh = sprintf("%.0f", $gust_kmh) if $gust_kmh; - $gust_ms = sprintf("%.0f", $gust_ms ) if $gust_ms; + $gust_ms = sprintf("%.0f", $gust_ms) if $gust_ms; if (!defined $mph && $primary){ $result = $primary; } @@ -17529,25 +18417,25 @@ sub wind_output { } sub get_weather { eval $start if $b_log; - my (@location) = @_; + my ($location) = @_; my $now = POSIX::strftime "%Y%m%d%H%M", localtime; my ($date_time,$freshness,$tz,@weather_data,%weather); - my $loc_name = lc($location[0]); + my $loc_name = lc($location->[0]); $loc_name =~ s/-\/|\s|,/-/g; $loc_name =~ s/--/-/g; my $file_cached = "$user_data_dir/weather-$loc_name-$weather_source.txt"; - if (-f $file_cached){ + if (-r $file_cached){ @weather_data = main::reader($file_cached); - $freshness = (split /\^\^/, $weather_data[0])[1]; + $freshness = (split(/\^\^/, $weather_data[0]))[1]; #print "$now:$freshness\n"; } if (!$freshness || $freshness < ($now - 60) ) { - @weather_data = download_weather($now,$file_cached,@location); + @weather_data = download_weather($now,$file_cached,$location); } - #print join "\n", @weather_data, "\n"; + #print join("\n", @weather_data), "\n"; # NOTE: because temps can be 0, we can't do if value tests foreach (@weather_data){ - my @working = split /\s*\^\^\s*/,$_; + my @working = split(/\s*\^\^\s*/, $_); next if ! defined $working[1] || $working[1] eq ''; if ( $working[0] eq 'api_source' ){ $weather{'api-source'} = $working[1]; @@ -17764,7 +18652,7 @@ sub get_weather { else { $date_time = POSIX::strftime "%c", localtime(); $date_time = test_locale_date($date_time,'',''); - $tz = ( $location[2] ) ? " ($location[2])" : ''; + $tz = ( $location->[2] ) ? " ($location->[2])" : ''; $weather{'date-time'} = $date_time . $tz; } # we get the wrong time using epoch for remote -W location @@ -17778,21 +18666,21 @@ sub get_weather { } sub download_weather { eval $start if $b_log; - my ($now,$file_cached,@location) = @_; + my ($now,$file_cached,$location) = @_; my (@weather,$temp,$ua,$url); - $url = "https://smxi.org/opt/xr2.php?loc=$location[0]&src=$weather_source"; + $url = "https://smxi.org/opt/xr2.php?loc=$location->[0]&src=$weather_source"; $ua = 'weather'; # { # #my $file2 = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/weather-1.xml"; # # my $file2 = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/feed-oslo-1.xml"; # local $/; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/weather-1.xml"; -# open my $fh, '<', $file or die "can't open $file: $!"; +# open(my $fh, '<', $file) or die "can't open $file: $!"; # $temp = <$fh>; # } $temp = main::download_file('stdout',$url,'',$ua); - @weather = split(/\n/, $temp) if $temp; - unshift (@weather,("timestamp^^$now")); + @weather = split('\n', $temp) if $temp; + unshift(@weather, "timestamp^^$now"); main::writer($file_cached,\@weather); #print "$file_cached: download/cleaned\n"; eval $end if $b_log; @@ -17821,9 +18709,9 @@ sub get_location { my ($city,$country,$freshness,%loc,$loc_arg,$loc_string,@loc_data,$state); my $now = POSIX::strftime "%Y%m%d%H%M", localtime; my $file_cached = "$user_data_dir/location-main.txt"; - if (-f $file_cached){ + if (-r $file_cached){ @loc_data = main::reader($file_cached); - $freshness = (split /\^\^/, $loc_data[0])[1]; + $freshness = (split(/\^\^/, $loc_data[0]))[1]; } if (!$freshness || $freshness < $now - 90) { my $temp; @@ -17831,11 +18719,11 @@ sub get_location { # { # local $/; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/weather/location-1.xml"; -# open my $fh, '<', $file or die "can't open $file: $!"; +# open(my $fh, '<', $file) or die "can't open $file: $!"; # $temp = <$fh>; # } $temp = main::download_file('stdout',$url); - @loc_data = split /\n/, $temp; + @loc_data = split('\n', $temp); @loc_data = map { s/<\?.*//; s/<\/[^>]+>/\n/g; @@ -17843,13 +18731,13 @@ sub get_location { s/{'action'} && $alerts{'sysctl'}->{'action'} eq 'use'){ # for dragonfly, we will use free mem, not used because free is 0 my @working; foreach (@sysctl){ @@ -17947,7 +18835,7 @@ sub get_compiler_version_bsd { # most have it. This appears to be 10.x late feature add, I don't see it # on earlier BSDs if (/^kern.compiler_version/){ - @working = split /:\s*/, $_; + @working = split(/:\s*/, $_); $working[1] =~ /.*(gcc|clang)\sversion\s([\S]+)\s.*/; @compiler = ($1,$2); last; @@ -18270,7 +19158,7 @@ sub check_gnome { sub get_env_xprop_non_gnome_based_data { eval $start if $b_log; my ($program,@version_data,$version); - #print join "\n", @xprop, "\n"; + #print join("\n", @xprop), "\n"; # String: "This is xfdesktop version 4.2.12" # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10) # note: some distros/wm (e.g. bunsen) set xdg to xfce to solve some other @@ -18573,9 +19461,9 @@ sub get_wm_version { # we don't want the gnome-shell version, and the others have no --version # we also don't want to run --version again on stuff we already have tested return if ! $wm || $wm =~ /^(budgie-wm|gnome-shell)$/ || ($desktop[0] && lc($desktop[0]) eq lc($wm) ); - my $temp = (split /\s+/, $wm)[0]; + my $temp = (split(/\s+/, $wm))[0]; if ($temp){ - $temp = (split /\s+/, $temp)[0]; + $temp = (split(/\s+/, $temp))[0]; $temp = lc($temp); $temp = 'wmaker' if $temp eq 'windowmaker'; my @data = main::program_data($temp,$temp,3); @@ -18607,13 +19495,13 @@ sub set_info_data { if (! grep {$item =~ /$_/} @info){ $item = main::trimmer($item); $item =~ s/.*\///; - push @info, (split /\s+/, $item)[0]; + push(@info, (split(/\s+/, $item))[0]); } } } if (@info){ - @info = main::uniq(@info); - $desktop[4] = join (', ', @info); + main::uniq(\@info); + $desktop[4] = join(', ', @info); } eval $end if $b_log; } @@ -18677,7 +19565,7 @@ sub get_display_manager { @data = program_data($working,$path,3); $working = $data[0]; $working .= ' ' . $data[1] if $data[1]; - push @found, $working; + push(@found, $working); } } if (!@found){ @@ -18698,7 +19586,7 @@ sub get_display_manager { # unknown dm, so we'll keep output to N/A log_data('dump','display manager: @found',\@found) if $b_log; eval $end if $b_log; - return join ', ', @found if @found; + return join(', ', @found) if @found; } ## Get DistroData @@ -18727,7 +19615,7 @@ sub get_bsd_os { @data = grep {/(ProductName|ProductVersion)/} @data if @data; @data = grep {//} @data if @data; @data = map {s/<[\/]?string>//g; } @data if @data; - $distro = join (' ', @data); + $distro = join(' ', @data); } } # seen a case without osx file, or was it permissions? @@ -18746,10 +19634,10 @@ sub get_linux_distro { knoppix-version pclinuxos-release mandrake-release manjaro-release mx-version pardus-release porteus-version q4os_version sabayon-release siduction-version sidux-version slitaz-release solusos-release turbolinux-release zenwalk-version); - my $derived_s = join "|", @derived; + my $derived_s = join('|', @derived); my @primary = qw(altlinux-release arch-release gentoo-release redhat-release slackware-version SuSE-release); - my $primary_s = join "|", @primary; + my $primary_s = join('|', @primary); my $exclude_s = 'debian_version|devuan_version|ubuntu_version'; # note, pclinuxos has all these mandrake/mandriva files, careful! my $lsb_good_s = 'mandrake-release|mandriva-release|mandrakelinux-release|manjaro-release'; @@ -18759,14 +19647,14 @@ sub get_linux_distro { # wait to handle since crunchbang file is one of the few in the world that # uses this method my @distro_files = main::globber('/etc/*[-_]{[rR]elease,[vV]ersion,issue}*'); - push @distro_files, '/etc/bodhibuilder.conf' if -r '/etc/bodhibuilder.conf'; + push(@distro_files, '/etc/bodhibuilder.conf') if -r '/etc/bodhibuilder.conf'; my $lsb_release = '/etc/lsb-release'; my $b_lsb = 1 if -f $lsb_release; my ($etc_issue,$issue,$lc_issue) = ('','/etc/issue',''); $b_issue = 1 if -f $issue; # note: OpenSuse Tumbleweed 2018-05 has made /etc/issue created by sym link to /run/issue # and then made that resulting file 700 permissions, which is obviously a mistake - $etc_issue = (main::reader($issue))[0] if -r $issue; + $etc_issue = main::reader($issue,'',0) if -r $issue; $etc_issue = main::clean_characters($etc_issue); my $os_release = '/etc/os-release'; @osr = main::reader($os_release) if -r $os_release; @@ -18804,7 +19692,7 @@ sub get_linux_distro { @distro_files = grep {!/arch-release/} @distro_files; #$system_base = 'Arch Linux'; } - my $distro_files_s = join "|", @distro_files; + my $distro_files_s = join('|', @distro_files); @working = (@derived,@primary); foreach my $file (@working){ if ( "/etc/$file" =~ /($distro_files_s)$/){ @@ -18828,7 +19716,7 @@ sub get_linux_distro { } main::log_data('data',"distro_file-2: $distro_file") if $b_log; # first test for the legacy antiX distro id file - if ( -f '/etc/antiX'){ + if ( -r '/etc/antiX'){ @working = main::reader('/etc/antiX'); $distro = main::awk(\@working,'antix.*\.iso') if @working; $distro = main::clean_characters($distro) if $distro; @@ -18863,7 +19751,7 @@ sub get_linux_distro { $distro =~ s/"//g if $distro; } else { - $distro = (main::reader($distro_file))[0]; + $distro = main::reader($distro_file,'',0); # only contains version number. Why? who knows. if ($distro_file eq '/etc/q4os_version' && $distro !~ /q4os/i){ $distro = "Q4OS $distro" ; @@ -19006,7 +19894,7 @@ sub get_linux_distro { } else { # android fallback, sometimes requires root, sometimes doesn't - if (-e '/system/build.prop') { + if ($b_android) { main::set_build_prop() if !$b_build_prop;; $distro = 'Android'; $distro .= ' ' . $build_prop{'build-version'} if $build_prop{'build-version'}; @@ -19040,7 +19928,7 @@ sub get_lsb_release { @content = map {s/,|\*|\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @content if @content; foreach (@content){ next if /^\s*$/; - my @working = split /\s*=\s*/, $_; + my @working = split(/\s*=\s*/, $_); next if !$working[0]; if ($working[0] eq 'DISTRIB_ID' && $working[1]){ if ($working[1] =~ /^Manjaro/i){ @@ -19086,7 +19974,7 @@ sub get_os_release { @content = map {s/\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @content if @content; foreach (@content){ next if /^\s*$/; - my @working = split /\s*=\s*/, $_; + my @working = split(/\s*=\s*/, $_); next if !$working[0]; if ($working[0] eq 'PRETTY_NAME' && $working[1]){ $pretty_name = $working[1]; @@ -19170,7 +20058,7 @@ sub debian_id { eval $start if $b_log; my ($codename) = @_; my ($debian_version,$id); - $debian_version = (main::reader('/etc/debian_version','strip'))[0] if -r '/etc/debian_version'; + $debian_version = main::reader('/etc/debian_version','strip',0) if -r '/etc/debian_version'; $id = 'Debian'; return if !$debian_version && !$codename; # note, 3.0, woody, 3.1, sarge, but after it's integer per version @@ -19184,6 +20072,7 @@ sub debian_id { '10' => 'buster', '11' => 'bullseye', '12' => 'bookworm', + '13' => 'trixie', ); if (main::is_numeric($debian_version)){ $id .= " $debian_version $debians{int($debian_version)}"; @@ -19240,10 +20129,10 @@ sub get_driver_modules { eval $start if $b_log; my ($driver,$modules) = @_; return if ! $modules; - my @mods = split /,\s+/, $modules; + my @mods = split(/,\s+/, $modules); if ($driver){ @mods = grep {!/^$driver$/} @mods; - $modules = join ',', @mods; + $modules = join(',', @mods); } log_data('data','$modules',$modules) if $b_log; eval $end if $b_log; @@ -19272,11 +20161,11 @@ sub get_gcc_data { @temp = globber('/usr/bin/gcc-*'); foreach (@temp){ if (/\/gcc-([0-9.]+)$/){ - push @gccs, $1; + push(@gccs, $1); } } } - unshift @gccs, $gcc; + unshift(@gccs, $gcc); log_data('dump','@gccs',\@gccs) if $b_log; eval $end if $b_log; return @gccs; @@ -19290,7 +20179,7 @@ sub get_gpu_ram_arm { # gpu=128M # "VCHI initialization failed" - you need to add video group to your user my $working = (grabber("$program get_mem gpu 2>/dev/null"))[0]; - $working = (split /\s*=\s*/, $working)[1] if $working; + $working = (split(/\s*=\s*/, $working))[1] if $working; $gpu_ram = translate_size($working) if $working; } log_data('data',"gpu ram: $gpu_ram") if $b_log; @@ -19312,8 +20201,8 @@ sub get_hostname { if ( $ENV{'HOSTNAME'} ){ $hostname = $ENV{'HOSTNAME'}; } - elsif ( !$bsd_type && -f "/proc/sys/kernel/hostname" ){ - $hostname = (reader('/proc/sys/kernel/hostname'))[0]; + elsif ( !$bsd_type && -r "/proc/sys/kernel/hostname" ){ + $hostname = reader('/proc/sys/kernel/hostname','',0); } # puppy removed this from core modules, sigh # this is faster than subshell of hostname @@ -19334,7 +20223,7 @@ sub get_init_data { my $runlevel = get_runlevel_data(); my $default = ($extra > 1) ? get_runlevel_default() : ''; my ($init,$init_version,$rc,$rc_version,$program) = ('','','','',''); - my $comm = ( -e '/proc/1/comm' ) ? (reader('/proc/1/comm'))[0] : ''; + my $comm = ( -r '/proc/1/comm' ) ? reader('/proc/1/comm','',0) : ''; my (@data); # this test is pretty solid, if pid 1 is owned by systemd, it is systemd # otherwise that is 'init', which covers the rest of the init systems. @@ -19396,11 +20285,11 @@ sub get_init_data { elsif ($program = check_program('rc')){ $rc_version = program_version($program, '^rc', '3','--version'); } - if ( -e '/run/openrc/softlevel' ){ - $runlevel = (reader('/run/openrc/softlevel'))[0]; + if ( -r '/run/openrc/softlevel' ){ + $runlevel = reader('/run/openrc/softlevel','',0); } - elsif ( -e '/var/run/openrc/softlevel'){ - $runlevel = (reader('/var/run/openrc/softlevel'))[0]; + elsif ( -r '/var/run/openrc/softlevel'){ + $runlevel = reader('/var/run/openrc/softlevel','',0); } elsif ( $program = check_program('rc-status')){ $runlevel = (grabber("$program -r 2>/dev/null"))[0]; @@ -19435,6 +20324,7 @@ sub get_kernel_data { } $kernel ||= 'N/A'; log_data('data',"kernel: $kernel ksplice: $ksplice") if $b_log; + log_data('dump','perl @uname', \@uname) if $b_log; eval $end if $b_log; return $kernel; } @@ -19471,7 +20361,7 @@ sub get_kernel_parameters_linux { eval $start if $b_log; my ($file) = @_; # unrooted android may have file only root readable - my $line = (reader($file))[0] if -r $file; + my $line = reader($file,'',0) if -r $file; eval $end if $b_log; return $line; } @@ -19482,6 +20372,22 @@ sub get_kernel_parameters_bsd { return $parameters; } +# 1 - partition name +sub get_lsblk { + eval $start if $b_log; + my $item = $_[0]; + return if !@lsblk; + my (%device); + foreach my $device (@lsblk){ + if ($device->{'name'} eq $item){ + %device = %$device; + last; + } + } + eval $start if $b_log; + return %device; +} + sub get_memory_data_full { eval $start if $b_log; my ($source) = @_; @@ -19491,16 +20397,13 @@ sub get_memory_data_full { if ($show{'ram'} || (!$show{'info'} && $show{'process'} )){ $memory = get_memory_data('splits'); if ($memory){ - my @temp = split /:/, $memory; - my @temp2 = get_size($temp[0]); + my @temp = split(':', $memory); $gpu_ram = $temp[3] if $temp[3]; - $total = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0]; - @temp2 = get_size($temp[1]); - $used = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0]; + $total = ($temp[0]) ? get_size($temp[0],'string') : 'N/A'; + $used = ($temp[1]) ? get_size($temp[1],'string') : 'N/A'; $used .= " ($temp[2]%)" if $temp[2]; if ($gpu_ram){ - @temp2 = get_size($gpu_ram); - $gpu_ram = $temp2[0] . ' ' . $temp2[1] if $temp2[1]; + $gpu_ram = get_size($gpu_ram,'string'); } } my $key = ($source eq 'process') ? 'System RAM': 'RAM'; @@ -19589,7 +20492,7 @@ sub get_memory_data_bsd { # see above, it's the last line. -H makes it hopefully all in kB so no need # for K/M/G tests my @vmstat = grabber("vmstat $arg 2>/dev/null",'\n','strip'); - my @header = split /\s+/, $vmstat[1]; + my @header = split(/\s+/, $vmstat[1]); foreach ( @header){ if ($_ eq 'avm'){$avm = $cnt} elsif ($_ eq 'fre'){$fre = $cnt} @@ -19598,7 +20501,7 @@ sub get_memory_data_bsd { } my $row = $vmstat[-1]; if ( $row ){ - @data = split /\s+/, $row; + @data = split(/\s+/, $row); # 6.3 introduced an M character, sigh. if ($data[$avm] && $data[$avm] =~ /^([0-9]+)M$/){ $data[$avm] = $1 * 1024; @@ -19608,22 +20511,21 @@ sub get_memory_data_bsd { } # dragonfly can have 0 avg, but they may fix that so make test dynamic if ($data[$avm] != 0){ - $av_pages = ($bsd_type ne 'openbsd') ? sprintf ('%.1f',$data[$avm]/1024) : $data[$avm]; + $av_pages = ($bsd_type ne 'openbsd') ? sprintf('%.1f',$data[$avm]/1024) : $data[$avm]; } elsif ($data[$fre] != 0){ - $free_mem = sprintf ('%.1f',$data[$fre]); + $free_mem = sprintf('%.1f',$data[$fre]); } } } ## code to get total goes here: - my $ref = $alerts{'sysctl'}; - if ($$ref{'action'} eq 'use'){ + if ($alerts{'sysctl'}->{'action'} eq 'use'){ # for dragonfly, we will use free mem, not used because free is 0 my @working; foreach (@sysctl){ # freebsd seems to use bytes here if (!$real_mem && /^hw.physmem:/){ - @working = split /:\s*/,$_; + @working = split(/:\s*/, $_); #if ($working[1]){ $working[1] =~ s/^[^0-9]+|[^0-9]+$//g; $real_mem = sprintf("%.1f", $working[1]/1024); @@ -19633,7 +20535,7 @@ sub get_memory_data_bsd { # But, it uses K here. Openbsd/Dragonfly do not seem to have this item # this can be either: Free Memory OR Free Memory Pages elsif (/^Free Memory:/){ - @working = split /:\s*/,$_; + @working = split(/:\s*/, $_); $working[1] =~ s/[^0-9]+//g; $free_mem = sprintf("%.1f", $working[1]); last if $real_mem; @@ -19641,7 +20543,7 @@ sub get_memory_data_bsd { } } else { - $message = "sysctl $$ref{'action'}" + $message = "sysctl $alerts{'sysctl'}->{'action'}" } # not using, but leave in place for a bit in case we want it # my $type = ($free_mem) ? ' free':'' ; @@ -19681,8 +20583,8 @@ sub get_module_version { return if ! $module; my ($version); my $path = "/sys/module/$module/version"; - if (-f $path){ - $version = (reader($path))[0]; + if (-r $path){ + $version = reader($path,'',0); } elsif (-f "/sys/module/$module/uevent"){ $version = 'kernel'; @@ -19825,13 +20727,13 @@ sub appimage_counts { } } sub count_libs { - my ($ref,$pos,$split) = @_; + my ($items,$pos,$split) = @_; my (@data); my $i = 0; $split ||= '\\s+'; - #print scalar @$ref, '::', $split, '::', $pos, "\n"; - foreach (@$ref){ - @data = split /$split/, $_; + #print scalar @$items, '::', $split, '::', $pos, "\n"; + foreach (@$items){ + @data = split(/$split/, $_); #print scalar @data, '::', $data[$pos], "\n"; $i++ if $data[$pos] && $data[$pos] =~ m%^lib%; } @@ -19848,7 +20750,7 @@ sub get_pci_vendor { # get rid of any [({ type characters that will make regex fail # and similar matches show as non-match $subsystem = regex_cleaner($subsystem); - my @data = split /\s+/, $subsystem; + my @data = split(/\s+/, $subsystem); # when using strings in patterns for regex have to escape them foreach (@data){ $temp = $_; @@ -19865,6 +20767,22 @@ sub get_pci_vendor { return $vendor; } +# 1 - partition name, without /dev, like sda1, sde +sub get_proc_partition { + eval $start if $b_log; + my $item = $_[0]; + return if !@proc_partitions; + my (@device); + foreach my $device (@proc_partitions){ + if ($device->[3] eq $item){ + @device = @$device; + last; + } + } + eval $start if $b_log; + return @device; +} + # # check? /var/run/nologin for bsds? sub get_runlevel_data { eval $start if $b_log; @@ -19898,13 +20816,13 @@ sub get_runlevel_default { # http://askubuntu.com/questions/86483/how-can-i-see-or-change-default-run-level # note that technically default can be changed at boot but for inxi purposes # that does not matter, we just want to know the system default - elsif ( -e $upstart){ + elsif ( -r $upstart){ # env DEFAULT_RUNLEVEL=2 @data = reader($upstart); $default = awk(\@data,'^env\s+DEFAULT_RUNLEVEL',2,'='); } # handle weird cases where null but inittab exists - if (!$default && -e $inittab ){ + if (!$default && -r $inittab ){ @data = reader($inittab); $default = awk(\@data,'^id.*initdefault',2,':'); } @@ -20207,7 +21125,7 @@ sub get_wakeups { return if $b_arm || $b_mips || $b_ppc; my ($wakeups); my $path = '/sys/power/wakeup_count'; - $wakeups = (reader($path,'strip'))[0] if -r $path; + $wakeups = reader($path,'strip',0) if -r $path; eval $end if $b_log; return $wakeups; } @@ -20224,7 +21142,7 @@ sub set_build_prop { return if ! -r $path; my @data = reader($path,'strip'); foreach (@data){ - my @working = split /=/, $_; + my @working = split('=', $_); next if $working[0] !~ /^ro\.(build|product)/; if ($working[0] eq 'ro.build.date.utc'){ $build_prop{'build-date'} = strftime "%F", gmtime($working[1]); @@ -20297,7 +21215,7 @@ sub set { $_[0] = 1; # check boolean passed by reference if ( $b_pci ){ if (!$bsd_type){ - if ($alerts{'lspci'}{'action'} eq 'use' ){ + if ($alerts{'lspci'}->{'action'} eq 'use' ){ lspci_data(); } # ! -d '/proc/bus/pci' @@ -20309,10 +21227,10 @@ sub set { } else { #if (1 == 1){ - if ($alerts{'pciconf'}{'action'} eq 'use'){ + if ($alerts{'pciconf'}->{'action'} eq 'use'){ pciconf_data(); } - elsif ($alerts{'pcidump'}{'action'} eq 'use'){ + elsif ($alerts{'pcidump'}->{'action'} eq 'use'){ pcidump_data(); } } @@ -20347,13 +21265,13 @@ sub lspci_data { if ($_ =~ /^~$/) { @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, $rev,$port,$driver,$modules,$driver_nu,$subsystem,$subsystem_id); - assign_data('pci',@temp); + assign_data('pci',\@temp); $device = ''; #print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; } elsif ($_ =~ /^Subsystem.*\[([a-f0-9]{4}:[a-f0-9]{4})\]/){ $subsystem_id = $1; - $subsystem = (split /^Subsystem:\s*/,$_)[1]; + $subsystem = (split(/^Subsystem:\s*/, $_))[1]; $subsystem =~ s/(\s?\[[^\]]+\])+$//g; $subsystem = main::cleaner($subsystem); $subsystem = main::pci_cleaner($subsystem,'pci'); @@ -20361,14 +21279,14 @@ sub lspci_data { #print "ss:$subsystem\n"; } elsif ($_ =~ /^I\/O\sports/){ - $port = (split /\s+/,$_)[3]; + $port = (split(/\s+/, $_))[3]; #print "p:$port\n"; } elsif ($_ =~ /^Kernel\sdriver\sin\suse/){ - $driver = (split /:\s*/,$_)[1]; + $driver = (split(/:\s*/, $_))[1]; } elsif ($_ =~ /^Kernel\smodules/i){ - $modules = (split /:\s*/,$_)[1]; + $modules = (split(/:\s*/, $_))[1]; } } # note: arm servers can have more complicated patterns @@ -20376,7 +21294,7 @@ sub lspci_data { elsif ($_ =~ /^(([0-9a-f]{2,4}:)?[0-9a-f]{2}:[0-9a-f]{2})[.:]([0-9a-f]+)\s(.*)\s\[([0-9a-f]{4}):([0-9a-f]{4})\](\s\(rev\s([^\)]+)\))?/){ $busid = $1; $busid_nu = hex($3); - @temp = split /:\s+/, $4; + @temp = split(/:\s+/, $4); $device = $temp[1]; $type = $temp[0]; $vendor_id = $5; @@ -20424,19 +21342,19 @@ sub pciconf_data { } @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, $rev,$port,$driver,$modules,$driver_nu); - assign_data('pci',@temp); + assign_data('pci',\@temp); $driver = ''; #print "$busid $device_id r:$rev p: $port\n$type\n$device\n"; } elsif ($_ =~ /^vendor/){ - $vendor = (split /\s+=\s+/,$_)[1]; + $vendor = (split(/\s+=\s+/, $_))[1]; #print "p:$port\n"; } elsif ($_ =~ /^device/){ - $device = (split /\s+=\s+/,$_)[1]; + $device = (split(/\s+=\s+/, $_))[1]; } elsif ($_ =~ /^class/i){ - $type = (split /\s+=\s+/,$_)[1]; + $type = (split(/\s+=\s+/, $_))[1]; } } elsif (/^([^@]+)\@pci([0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}):([0-9]{1,3}).*class=([^\s]+)\scard=([^\s]+)\schip=([^\s]+)\srev=([^\s]+)/){ @@ -20468,7 +21386,7 @@ sub pcidump_data { if ($_ =~ /^~$/ && $busid && $device) { @temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, $rev,$port,$driver,$modules,$driver_nu); - assign_data('pci',@temp); + assign_data('pci',\@temp); ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id, $rev,$port,$driver,$modules,$driver_nu) = undef; next; @@ -20494,20 +21412,22 @@ sub pcidump_data { sub pci_grabber { eval $start if $b_log; my ($program) = @_; - my ($args,$pattern,@working); + my ($args,$path,$pattern,@working); if ($program eq 'lspci'){ $args = ' -knnv'; + $path = $alerts{'lspci'}->{'path'}; $pattern = '^[0-9a-f]+:'; } elsif ($program eq 'pciconf'){ $args = ' -lv'; + $path = $alerts{'pciconf'}->{'path'}; $pattern = '^([^@]+)\@pci'; } elsif ($program eq 'pcidump'){ $args = ' -v'; + $path = $alerts{'pcidump'}->{'path'}; $pattern = '^[0-9a-f]+:'; } - my $path = main::check_program($program); @data = main::grabber("$path $args 2>/dev/null",'','strip'); #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pciconf/pci-freebsd-8.2-2"; #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/pcidump/pci-openbsd-6.1-vm.txt"; @@ -20518,11 +21438,11 @@ sub pci_grabber { $b_pci_tool = 1 if scalar @data > 10; foreach (@data){ if ($_ =~ /$pattern/i){ - push @working, '~'; + push(@working, '~'); } - push @working, $_; + push(@working, $_); } - push @working, '~'; + push(@working, '~'); } #print Data::Dumper::Dumper \@working; eval $end if $b_log; @@ -20563,24 +21483,24 @@ sub soc_devices_files { if (-d '/sys/devices/platform/'){ @files = main::globber('/sys/devices/platform/soc*/*/uevent'); @temp2 = main::globber('/sys/devices/platform/soc*/*/*/uevent'); - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; @temp2 = main::globber('/sys/devices/platform/*/uevent'); - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; } if (main::globber('/sys/devices/soc*')){ @temp2 = main::globber('/sys/devices/soc*/*/uevent'); - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; @temp2 = main::globber('/sys/devices/soc*/*/*/uevent'); - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; } @temp2 = main::globber('/sys/devices/*/uevent'); # see case 8 - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; @temp2 = main::globber('/sys/devices/*/*/uevent'); # see case 10 - @files = (@files,@temp2) if @temp2; + push(@files,@temp2) if @temp2; @temp2 = undef; # not sure why, but even as root/sudo, /subsystem|driver/uevent are unreadable with -r test true @files = grep {!/\/(subsystem|driver)\//} @files if @files; - @files = main::uniq(@files); + main::uniq(\@files); eval $end if $b_log; } sub soc_devices { @@ -20598,7 +21518,7 @@ sub soc_devices { @working = main::reader($file, 'strip') if -r $file; ($device,$driver,$handle,$type,$vendor_id) = (undef,undef,undef,undef,undef); foreach my $data (@working){ - @temp2 = split /=/, $data; + @temp2 = split('=', $data); if ($temp2[0] eq 'DRIVER'){ $driver = $temp2[1]; $driver =~ s/-/_/g if $driver; # kernel uses _, not - in module names @@ -20609,11 +21529,11 @@ sub soc_devices { # we'll use these paths to test in device tree pci completer elsif ($temp2[0] eq 'OF_FULLNAME' && $temp2[1]){ # we don't want the short names like /soc, /led and so on - push @full_names, $temp2[1] if (() = $temp2[1] =~ /\//g) > 1; - $handle = (split /@/, $temp2[1])[-1] if $temp2[1] =~ /@/; + push(@full_names, $temp2[1]) if (() = $temp2[1] =~ /\//g) > 1; + $handle = (split('@', $temp2[1]))[-1] if $temp2[1] =~ /@/; } elsif ($temp2[0] eq 'OF_COMPATIBLE_0'){ - @temp3 = split /,/, $temp2[1]; + @temp3 = split(',', $temp2[1]); $device = $temp3[-1]; $vendor_id = $temp3[0]; } @@ -20621,7 +21541,6 @@ sub soc_devices { # it's worthless, we can't use it next if ! defined $type; $type_id = $type; - $type = 'display' if $type =~ /mali/i; $chip_id = '' if ! defined $chip_id; $vendor_id = '' if ! defined $vendor_id; $driver = '' if ! defined $driver; @@ -20631,7 +21550,7 @@ sub soc_devices { ($busid_nu,$modules,$port,$rev) = (0,'','',''); @temp3 = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,$rev, $port,$driver,$modules,'','','',$handle); - assign_data('soc',@temp3); + assign_data('soc',\@temp3); } eval $end if $b_log; } @@ -20644,15 +21563,14 @@ sub soc_devicetree { foreach $file (@files){ if ( $file !~ m%$test%){ ($handle,$content,$device,$type,$type_id,$vendor_id) = ('','','','','',''); - $content = (main::reader($file, 'strip'))[0] if -r $file; + $content = main::reader($file, 'strip',0) if -r $file; $file =~ m%soc/([^@]+)@([^/]+)/compatible$%; $type = $1; next if !$type || !$content; $handle = $2 if $2; $type_id = $type; - $type = 'display' if $type =~ /mali/i; if ($content){ - @temp3 = split /,/, $content; + @temp3 = split(',', $content); $vendor_id = $temp3[0]; $device = $temp3[-1]; # strip off those weird device tree special characters @@ -20660,7 +21578,7 @@ sub soc_devicetree { } $type = soc_type($type,$vendor_id,''); @temp3 = ($type,$type_id,0,0,$device,$vendor_id,'soc','','','','','','','',$handle); - assign_data('soc',@temp3); + assign_data('soc',\@temp3); main::log_data('dump','@devices @temp3',\@temp3) if $b_log; } } @@ -20668,31 +21586,31 @@ sub soc_devicetree { eval $end if $b_log; } sub assign_data { - my ($tool,@data) = @_; - if (check_graphics($data[0],$data[1])){ - @devices_graphics = (@devices_graphics,[@data]); + my ($tool,$data) = @_; + if (check_graphics($data->[0],$data->[1])){ + push(@devices_graphics,[@$data]); $b_soc_gfx = 1 if $tool eq 'soc'; } # for hdmi, we need gfx/audio both - if (check_audio($data[0],$data[1])){ - @devices_audio = (@devices_audio,[@data]); + if (check_audio($data->[0],$data->[1])){ + push(@devices_audio,[@$data]); $b_soc_audio = 1 if $tool eq 'soc'; } - elsif (check_hwraid($data[0],$data[1])){ - @devices_hwraid = (@devices_hwraid,[@data]); + elsif (check_hwraid($data->[0],$data->[1])){ + push(@devices_hwraid,[@$data]); $b_soc_net = 1 if $tool eq 'soc'; } - elsif (check_network($data[0],$data[1])){ - @devices_network = (@devices_network,[@data]); + elsif (check_network($data->[0],$data->[1])){ + push(@devices_network,[@$data]); $b_soc_net = 1 if $tool eq 'soc'; } - elsif (check_timer($data[0],$data[1])){ - @devices_timer = (@devices_timer,[@data]); + elsif (check_timer($data->[0],$data->[1])){ + push(@devices_timer,[@$data]); $b_soc_timer = 1; } # not used at this point, -M comes before ANG # $device_vm = check_vm($data[4]) if ( (!$b_ppc && !$b_mips) && !$device_vm ); - @devices = (@devices,[@data]); + push(@devices,[@$data]); } # note: for soc, these have been converted in soc_type() sub check_audio { @@ -20736,26 +21654,33 @@ sub soc_type { my ($type,$info,$driver) = @_; # I2S or i2s. I2C is i2 controller |[iI]2[Ss]. note: odroid hdmi item is sound only # snd_soc_dummy. simple-audio-amplifier driver: speaker_amp - if ($type =~ /^(daudio|.*hifi.*|.*sound[_-]card|.*dac[0-9]?)$/ || - ($info && $info !~ /amp|codec|dummy/ && $info =~ /(sound|audio)/) || - ($driver && $driver !~ /(codec|dummy)/ && $driver =~ /(audio|snd|sound)/) ){ + if (($driver && $driver =~ /codec/) || ($info && $info =~ /codec/) || + ($type && $type =~ /codec/) ){ + $type = 'codec'; + } + elsif (($driver && $driver =~ /dummy/i) || ($info && $info =~ /dummy/i)){ + $type = 'dummy'; + } + elsif ($type =~ /^(daudio|.*hifi.*|.*sound[_-]card|.*dac[0-9]?)$/i || + ($info && $info !~ /amp/i && $info =~ /(sound|audio)/i) || + ($driver && $driver =~ /(audio|snd|sound)/i) ){ $type = 'audio'; } - elsif ($type =~ /^((meson-?)?fb|disp|display(-[^\s]+)?|gpu|mali)$/){ + elsif ($type =~ /^((meson-?)?fb|disp|display(-[^\s]+)?|gpu|.*mali|vpu)$/i){ $type = 'display'; } # includes ethernet-phy, meson-eth - elsif ($type =~ /^(([^\s]+-)?eth|ethernet(-[^\s]+)?|lan|l-lan)$/){ + elsif ($type =~ /^(([^\s]+-)?eth|ethernet(-[^\s]+)?|lan|l-lan)$/i){ $type = 'ethernet'; } - elsif ($type =~ /^(.*wlan.*|.*wifi.*)$/){ + elsif ($type =~ /^(.*wlan.*|.*wifi.*)$/i){ $type = 'wifi'; } # needs to catch variants like hdmi-tx but not hdmi-connector - elsif ( (!$driver || $driver !~ /(codec|dummy)/) && $type =~ /^(.*hdmi(-?tx)?)$/){ + elsif ( $type =~ /^(.*hdmi(-?tx)?)$/i){ $type = 'hdmi'; } - elsif ($type =~ /^timer$/){ + elsif ($type =~ /^timer$/i){ $type = 'timer'; } return $type; @@ -20827,9 +21752,9 @@ sub set_dmesg_boot_data { $_ =~ s/^\s+/~/; $_ =~ s/\s\s/ /g; $_ =~ s/^(\S+)\sat\s/$1:at /; # ada0 at ahcich0 - push @temp, $_; + push(@temp, $_); if (/^bios[0-9]:(at|vendor)/){ - push @sysctl_machine, $_; + push(@sysctl_machine, $_); } } @dmesg_boot = @temp; @@ -20855,7 +21780,7 @@ sub set_dmesg_boot_data { sub set_dmi_data { eval $start if $b_log; $_[0] = 1; # check boolean passed by reference - if ($b_fake_dmidecode || $alerts{'dmidecode'}{'action'} eq 'use' ){ + if ($b_fake_dmidecode || $alerts{'dmidecode'}->{'action'} eq 'use' ){ set_dmidecode_data(); } eval $end if $b_log; @@ -20865,18 +21790,21 @@ sub set_dmidecode_data { eval $start if $b_log; my ($content,@data,@working,$type,$handle); if ($b_fake_dmidecode){ - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/pci-freebsd-8.2-2"; - # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-loki-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-t41-1.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-mint-20180106.txt"; - #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-vmware-ram-1.txt"; - #open my $fh, '<', $file or die "can't open $file: $!"; - #chomp(@data = <$fh>); + my $file; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/pci-freebsd-8.2-2"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-loki-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-t41-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-mint-20180106.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-vmware-ram-1.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-tyan-4408.txt"; + #$file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-1.txt"; + $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt"; + open(my $fh, '<', $file) or die "can't open $file: $!"; + chomp(@data = <$fh>); } else { - my $path = check_program('dmidecode'); - $content = qx($path 2>/dev/null) if $path; - @data = split /\n/, $content; + $content = qx($alerts{'dmidecode'}->{'path'} 2>/dev/null); + @data = split('\n', $content); } # we don't need the opener lines of dmidecode output # but we do want to preserve the indentation. Empty lines @@ -20891,12 +21819,12 @@ sub set_dmidecode_data { if (/^[^\s]/){ $_ = lc($_); $_ =~ s/\s(information)//; - push @working, $_; + push(@working, $_); } elsif (/^\t/){ $_ =~ s/^\t\t/~/; $_ =~ s/^\t|\s+$//g; - push @working, $_; + push(@working, $_); } } elsif (/^Handle\s(0x[0-9A-Fa-f]+).*DMI\stype\s([0-9]+),.*/){ @@ -20934,10 +21862,10 @@ sub set_dmidecode_data { sub set_ip_data { eval $start if $b_log; - if ($alerts{'ip'}{'action'} eq 'use' ){ + if ($alerts{'ip'}->{'action'} eq 'use' ){ set_ip_addr(); } - elsif ($alerts{'ifconfig'}{'action'} eq 'use'){ + elsif ($alerts{'ifconfig'}->{'action'} eq 'use'){ set_ifconfig(); } eval $end if $b_log; @@ -20945,8 +21873,7 @@ sub set_ip_data { sub set_ip_addr { eval $start if $b_log; - my $program = check_program('ip'); - my @data = grabber("$program addr 2>/dev/null",'\n','strip') if $program; + my @data = grabber($alerts{'ip'}->{'path'} . " addr 2>/dev/null",'\n','strip'); # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/if/scope-ipaddr-1.txt"; # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/networking/ip-addr-blue-advance.txt"; #my @data = reader($file,'strip') or die $!; @@ -20957,10 +21884,10 @@ sub set_ip_addr { if (@ips){ #print "$if\n"; @temp = ($if,[@ips]); - @ifs = (@ifs,@temp); + push(@ifs,@temp); @ips = (); } - @temp = split /:\s+/,$_; + @temp = split(/:\s+/, $_); $if = $temp[1]; if ($if eq 'lo'){ $b_skip = 1; @@ -20972,7 +21899,7 @@ sub set_ip_addr { } elsif (!$b_skip && /^inet/){ #print "$_\n"; - @temp = split /\s+/, $_; + @temp = split(/\s+/, $_); ($broadcast,$ip,$scope,$if_id,$type) = ('','','','',''); $ip = $temp[1]; $type = ($temp[0] eq 'inet') ? 4 : 6 ; @@ -20984,14 +21911,14 @@ sub set_ip_addr { $if_id = $3; } @temp = ($type,$ip,$broadcast,$scope,$if_id); - @ips = (@ips,[@temp]); + push(@ips,[@temp]); #print Dumper \@ips; } } #print Dumper \@ips if $test[4]; if (@ips){ @temp = ($if,[@ips]); - @ifs = (@ifs,@temp); + push(@ifs,@temp); } log_data('dump','@ifs',\@ifs) if $b_log; print Dumper \@ifs if $test[3]; @@ -21000,8 +21927,7 @@ sub set_ip_addr { sub set_ifconfig { eval $start if $b_log; - my $program = check_program('ifconfig'); # not in user path, sbin - my @data = grabber("$program 2>/dev/null",'\n','') if $program; + my @data = grabber($alerts{'ifconfig'}->{'path'} . " 2>/dev/null",'\n',''); #my @data = reader("$ENV{'HOME'}/bin/scripts/inxi/data/if/vps-ifconfig-1.txt",'') or die $!; my ($b_skip,$broadcast,$if,@ips_bsd,$ip,@ips,$scope,$if_id,$type,@temp,@temp2); my ($state,$speed,$duplex,$mac); @@ -21011,18 +21937,18 @@ sub set_ifconfig { if (@ips){ #print "here\n"; @temp = ($if,[@ips]); - @ifs = (@ifs,@temp); + push(@ifs,@temp); @ips = (); } if ($mac){ @temp = ($if,[($state,$speed,$duplex,$mac)]); - @ifs_bsd = (@ifs_bsd,@temp); + push(@ifs_bsd,@temp); ($state,$speed,$duplex,$mac,$if_id) = ('','','','',''); } - $if = (split /\s+/,$_)[0]; + $if = (split(/\s+/, $_))[0]; $if =~ s/:$//; # em0: flags=8843 $if_id = $if; - $if = (split /:/, $if)[0] if $if; + $if = (split(':', $if))[0] if $if; if ($if =~ /^lo/){ $b_skip = 1; $if = ''; @@ -21052,17 +21978,17 @@ sub set_ifconfig { $speed =~ s/\s+$// if $speed; } elsif (!$mac && /^ether|lladdr/){ - $mac = (split /\s+/, $_)[1]; + $mac = (split(/\s+/, $_))[1]; } elsif (/^status/){ - $state = (split /\s+/, $_)[1]; + $state = (split(/\s+/, $_))[1]; } } elsif (!$b_skip && /^\s+inet/){ #print "$_\n"; $_ =~ s/^\s+//; $_ =~ s/addr:\s/addr:/; - @temp = split /\s+/, $_; + @temp = split(/\s+/, $_); ($broadcast,$ip,$scope,$type) = ('','','',''); $ip = $temp[1]; # fe80::225:90ff:fe13:77ce%em0 @@ -21079,17 +22005,17 @@ sub set_ifconfig { } $scope = 'link' if $ip =~ /^fe80/; @temp = ($type,$ip,$broadcast,$scope,$if_id); - @ips = (@ips,[@temp]); + push(@ips,[@temp]); #print Dumper \@ips; } } if (@ips){ @temp = ($if,[@ips]); - @ifs = (@ifs,@temp); + push(@ifs,@temp); } if ($mac){ @temp = ($if,[($state,$speed,$duplex,$mac)]); - @ifs_bsd = (@ifs_bsd,@temp); + push(@ifs_bsd,@temp); ($state,$speed,$duplex,$mac) = ('','','',''); } print Dumper \@ifs if $test[3]; @@ -21099,6 +22025,86 @@ sub set_ifconfig { eval $end if $b_log; } +sub set_lsblk { + eval $start if $b_log; + $b_lsblk = 1; + if ($alerts{'lsblk'} && $alerts{'lsblk'}->{'path'}){ + my $cmd = $alerts{'lsblk'}->{'path'} . ' -bP --output NAME,TYPE,RM,FSTYPE,SIZE,LABEL,UUID,'; + $cmd .= 'SERIAL,MOUNTPOINT,PHY-SEC,LOG-SEC,PARTFLAGS,MAJ:MIN,PKNAME 2>/dev/null'; + my $pattern = 'NAME="([^"]*)"\s+TYPE="([^"]*)"\s+RM="([^"]*)"\s+'; + $pattern .= 'FSTYPE="([^"]*)"\s+SIZE="([^"]*)"\s+LABEL="([^"]*)"\s+'; + $pattern .= 'UUID="([^"]*)"\s+SERIAL="([^"]*)"\s+MOUNTPOINT="([^"]*)"\s+'; + $pattern .= 'PHY-SEC="([^"]*)"\s+LOG-SEC="([^"]*)"\s+PARTFLAGS="([^"]*)"\s+'; + $pattern .= 'MAJ:MIN="([^"]*)"\s+PKNAME="([^"]*)"'; + my @working = main::grabber($cmd); + foreach (@working){ + if (/$pattern/){ + my $size = ($5) ? $5/1024: 0; + # some versions of lsblk do not return serial, fs, uuid, or label + push(@lsblk, { + 'name' => $1, + 'type' => $2, + 'rm' => $3, + 'fs' => $4, + 'size' => $size, + 'label' => $6, + 'uuid' => $7, + 'serial' => $8, + 'mount' => $9, + 'block-physical' => $10, + 'block-logical' => $11, + 'partition-flags' => $12, + 'maj-min' => $13, + 'parent' => $14, + }); + # must be below assignments!! otherwise the result of the match replaces values + # note: for bcache and luks, the device that has that fs is the parent!! + if ($show{'logical'}){ + $b_active_lvm = 1 if !$b_active_lvm && $2 && $2 eq 'lvm'; + if (!$b_active_general && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) + || ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) || + $2 eq 'crypto' || $2 eq 'mpath' || $2 eq 'multipath'))){ + $b_active_general = 1; + } + } + } + } + } + #print Data::Dumper::Dumper \@lsblk; + main::log_data('dump','@lsblk',\@lsblk) if $b_log; + eval $end if $b_log; +} + +sub set_mapper { + eval $start if $b_log; + $b_mapper = 1; + return if ! -d '/dev/mapper'; + foreach ((globber('/dev/mapper/*'))){ + my ($key,$value) = ($_,Cwd::abs_path("$_")); + next if !$value; + $key =~ s|^/.*/||; + $value =~ s|^/.*/||; + $mapper{$key} = $value; + } + %dmmapper = reverse %mapper if %mapper; + eval $end if $b_log; +} + +sub set_proc_partitions { + eval $start if $b_log; + $b_proc_partitions = 1; + if (my $file = main::system_files('partitions')){ + @proc_partitions = main::reader($file,'strip'); + shift @proc_partitions; # get rid of headers + @proc_partitions = map { + my @temp = split(/\s+/, $_); + next if ! defined $temp[2]; + [$temp[0],$temp[1],$temp[2],$temp[3]]; + } @proc_partitions; + } + eval $end if $b_log; +} + sub set_ps_aux { eval $start if $b_log; my ($header,@temp); @@ -21121,13 +22127,13 @@ sub set_ps_aux { @ps_aux = grep {!/\/$self_name\b/} @ps_aux if $self_name eq 'inxi'; # this is for testing for the presence of the command @ps_cmd = grep {!/^\[/} map { - my @split = split /\s+/, $_; + my @split = split(/\s+/, $_); # slice out 10th to last elements of ps aux rows my $final = $#split; # some stuff has a lot of data, chrome for example $final = ($final > ($ps_cols + 2) ) ? $ps_cols + 2 : $final; @split = @split[$ps_cols .. $final]; - join " ", @split; + join(' ', @split); } @ps_aux; #@ps_cmd = grep {!/^\[/} @ps_cmd; # never, because ps loaded before option handler @@ -21143,7 +22149,7 @@ sub set_ps_gui { if ($show{'system'}){ @temp=qw(razor-desktop razor-session lxsession lxqt-session tdelauncher tdeinit_phase1); - @match = (@match,@temp); + push(@match,@temp); @temp=qw(3dwm 9wm afterstep aewm aewm\+\+ amiwm antiwm awesome blackbox bspwm cagebreak calmwm (sh|c?lisp).*clfswm (openbsd-)?cwm dwm evilwm @@ -21155,7 +22161,7 @@ sub set_ps_gui { tinywm tvtwm twm waycooler way-cooler windowlab WindowMaker wm2 wmii2 wmii wmx xfdesktop xmonad yeahwm); - @match = (@match,@temp); + push(@match,@temp); } # wm: if ($show{'system'} && $extra > 1){ @@ -21163,10 +22169,10 @@ sub set_ps_gui { twin kwin_wayland kwin_x11 kwin marco deepin-metacity metacity metisse mir muffin deepin-mutter mutter ukwm xfwm4 xfwm5); - @match = (@match,@temp); + push(@match,@temp); # startx: /bin/sh /usr/bin/startx @temp=qw(ly .*startx xinit); # possible dm values - @match = (@match,@temp); + push(@match,@temp); } # info: NOTE: glx-dock is cairo-dock if ($show{'system'} && $extra > 2){ @@ -21179,7 +22185,7 @@ sub set_ps_gui { razor-panel razorqt-panel stalonetray swaybar taskbar tint2 trayer ukui-panel vala-panel wbar wharf wingpanel witray xfce4-panel xfce5-panel xmobar yabar); - @match = (@match,@temp); + push(@match,@temp); } # compositors (for wayland these are also the server, note. # for wayland always show, so always load these @@ -21190,29 +22196,28 @@ sub set_ps_gui { orbital papyros perceptia picom rustland sommelier sway swc ukwm unagi unity-system-compositor wavy waycooler way-cooler wayfire wayhouse westford weston xcompmgr); - @match = (@match,@temp); + push(@match,@temp); } - @match = uniq(@match); - my $matches = join '|', @match; + uniq(\@match); + my $matches = join('|', @match); foreach (@ps_cmd){ if (/^(|[\S]*\/)($matches)(\/|\s|$)/){ $working = $2; - push @ps_gui, $working; # deal with duplicates with uniq + push(@ps_gui, $working); # deal with duplicates with uniq } } - @ps_gui = uniq(@ps_gui) if @ps_gui; + uniq(\@ps_gui) if @ps_gui; print Dumper \@ps_gui if $test[5]; log_data('dump','@ps_gui',\@ps_gui) if $b_log; eval $end if $b_log; } sub set_sysctl_data { eval $start if $b_log; - return if $alerts{'sysctl'}{'action'} ne 'use'; + return if !$alerts{'sysctl'} || $alerts{'sysctl'}->{'action'} ne 'use'; my (@temp); # darwin sysctl has BOTH = and : separators, and repeats data. Why? if (!$b_fake_sysctl){ - my $program = check_program('sysctl'); - @temp = grabber("$program -a 2>/dev/null"); + @temp = grabber($alerts{'sysctl'}->{'path'} . " -a 2>/dev/null"); } else { #my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sysctl/obsd_6.1_sysctl_soekris6501_root.txt"; @@ -21226,17 +22231,17 @@ sub set_sysctl_data { foreach (@temp){ $_ =~ s/\s*=\s*|:\s+/:/; $_ =~ s/\"//g; - push @sysctl, $_; + push(@sysctl, $_); # we're building these here so we can use these arrays to test # in each feature if we will try to build the feature for bsds if (/^hw\.sensors/ && !/^hw\.sensors\.acpi(bat|cmb)/ && !/^hw.sensors.softraid/){ - push @sysctl_sensors, $_; + push(@sysctl_sensors, $_); } elsif (/^hw\.(vendor|product|version|serialno|uuid)/){ - push @sysctl_machine, $_; + push(@sysctl_machine, $_); } elsif (/^hw\.sensors\.acpi(bat|cmb)/){ - push @sysctl_battery, $_; + push(@sysctl_battery, $_); } } print Dumper \@sysctl if $test[7]; @@ -21279,13 +22284,13 @@ sub set { eval $start if $b_log; $b_usb_check = 1; # if user config sets USB_SYS you can override with --usb-tool - if ((!$b_usb_sys || $b_usb_tool) && $alerts{'lsusb'}{'action'} eq 'use' ){ + if ((!$b_usb_sys || $b_usb_tool) && $alerts{'lsusb'}->{'action'} eq 'use' ){ lsusb_data(); } elsif (-d '/sys/bus/usb/devices'){ sys_data('main'); } - elsif ( $alerts{'usbdevs'}{'action'} eq 'use'){ + elsif ( $alerts{'usbdevs'}->{'action'} eq 'use'){ usbdevs_data(); } eval $end if $b_log; @@ -21298,7 +22303,7 @@ sub lsusb_data { foreach (@data){ next if /^\s*$|^Couldn't/; # expensive second call: || /UNAVAIL/ - @working = split /\s+/, $_; + @working = split(/\s+/, $_); $working[3] =~ s/:$//; # Seen FreeBSD lsusb with: # Bus /dev/usb Device /dev/ugen0.3: ID 24ae:1003 Shenzhen Rapoo Technology Co., Ltd. @@ -21308,7 +22313,7 @@ sub lsusb_data { $path_id = "$bus_id-$addr_id"; $chip_id = $working[5]; @temp = @working[6..$#working]; - $name = join ' ', @temp; + $name = main::remove_duplicates(join(' ', @temp)); $name = $name; #print "$name\n"; $working[0] = $bus_id; @@ -21330,8 +22335,8 @@ sub lsusb_data { $working[16] = ''; $working[17] = ''; $working[18] = ''; - @usb = (@usb,[@working]); - #print join ("\n",@working),"\n\n=====\n"; + push(@usb,[@working]); + #print join("\n",@working),"\n\n=====\n"; } print Data::Dumper::Dumper \@usb if $test[6]; sys_data('lsusb') if @usb; @@ -21364,7 +22369,7 @@ sub usbdevs_data { $addr_id = $1; $speed = $2; $chip_id = "$4:$6"; - $name="$5 $3"; + $name = main::remove_duplicates("$5 $3"); #print "p1:$protocol\n"; $path_id = "$bus_id-$hub_id"; $port_value = ''; @@ -21394,7 +22399,7 @@ sub usbdevs_data { $addr_id = "$2"; $speed = "$3"; $chip_id = "$5:$7"; - $name="$6 $4"; + $name = main::remove_duplicates("$6 $4"); #print "p2:$protocol\n"; $ports++; $path_id = "$bus_id-$hub_id.$port"; @@ -21443,8 +22448,7 @@ sub data_grabber { my %args = ('lsusb' => '', 'usbdevs' => '-v'); my (@data); if ($b_live && !$b_fake_usbdevs){ - my $path = main::check_program($program); - @data = main::grabber("$path $args{$program} 2>/dev/null") if $path; + @data = main::grabber($alerts{$program}->{'path'} . " $args{$program} 2>/dev/null"); } else { my $file; @@ -21470,7 +22474,7 @@ sub sys_data { my @files = main::globber('/sys/bus/usb/devices/*'); # we want to get rid of the hubs with x-0: syntax, those are hubs found in /usbx @files = grep {!/\/[0-9]+-0:/} @files; - #print join "\n", @files; + #print join("\n", @files); foreach (@files){ @uevent = main::reader("$_/uevent") if -r "$_/uevent"; $ids = main::awk(\@uevent,'^(DEVNAME|DEVICE\b)',2,'='); @@ -21486,7 +22490,7 @@ sub sys_data { $path_id =~ s/^usb([0-9]+)/$1-0/; # if DEVICE= then path = /proc/bus/usb/001/001 else: bus/usb/006/001 $ids =~ s/^\///; - @working = split /\//, $ids; + @working = split('/', $ids); shift @working if $working[0] eq 'proc'; $bus_id = int($working[2]); $bus_id_alpha = bus_id_alpha($path_id); @@ -21494,9 +22498,12 @@ sub sys_data { $class_id = sys_item("$_/bDeviceClass"); $class_id = hex($class_id) if $class_id; @drivers = uevent_data("$_/[0-9]*/uevent"); - @drivers = (@drivers, uevent_data("$_/[0-9]*/*/uevent")) if !$b_hub; + push(@drivers, uevent_data("$_/[0-9]*/*/uevent")) if !$b_hub; $ports = sys_item("$_/maxchild") if $b_hub; - $driver = join ',', sort(main::uniq(@drivers)) if @drivers; + if (@drivers){ + main::uniq(\@drivers); + $driver = join(',', sort @drivers); + } $interfaces = sys_item("$_/bNumInterfaces"); $serial = sys_item("$_/serial"); $usb_version = sys_item("$_/version"); @@ -21551,6 +22558,7 @@ sub sys_data { elsif ($b_hub){ $name = $type; } + $name = main::remove_duplicates($name) if $name; # this isn't that useful, but save in case something shows up #if ($configuration){ # $name = ($name) ? "$name $configuration" : $configuration; @@ -21596,7 +22604,7 @@ sub uevent_data { # print "f2: $_\n"; ($interface) = (''); @working = main::reader($_) if -r $_; - #print join ("\n",@working), "\n"; + #print join("\n",@working), "\n"; if (@working){ $driver = main::awk(\@working,'^DRIVER',2,'='); $interface = main::awk(\@working,'^INTERFACE',2,'='); @@ -21604,16 +22612,16 @@ sub uevent_data { $interface = device_type($interface); if ($interface){ if ($interface ne ''){ - push @interfaces, $interface; + push(@interfaces, $interface); } # networking requires more data but this test is reliable elsif (!@interfaces) { $temp = $_; $temp =~ s/\/uevent$//; - push @interfaces, 'Network' if -d "$temp/net/"; + push(@interfaces, 'Network') if -d "$temp/net/"; } if (!@interfaces){ - push @interfaces, $interface; + push(@interfaces, $interface); } } } @@ -21621,15 +22629,15 @@ sub uevent_data { #print "driver:$driver\n"; $b_hub = 1 if $driver && $driver eq 'hub'; $driver = '' if $driver && ($driver eq 'usb' || $driver eq 'hub'); - push @drivers,$driver if $driver; + push(@drivers,$driver) if $driver; } if (@interfaces){ - @interfaces = main::uniq(@interfaces); + main::uniq(\@interfaces); # clear out values like: ,Printer if ( scalar @interfaces > 1 && (grep {/^ \&CpuData::get, 'disk' => \&DiskData::get, 'graphic' => \&GraphicData::get, + 'logical' => \&LogicalData::get, 'machine' => \&MachineData::get, 'network' => \&NetworkData::get, 'partition' => \&PartitionData::get, @@ -21917,10 +22930,10 @@ sub generate_short_data { $cpu_string = $cpu[0] . ' ' . $cpu[1] . $type; } elsif ($bsd_type) { - if ($alerts{'sysctl'}{'action'}){ - if ($alerts{'sysctl'}{'action'} ne 'use'){ - $cpu_string = "sysctl $alerts{'sysctl'}{'action'}"; - $speed = "sysctl $alerts{'sysctl'}{'action'}"; + if ($alerts{'sysctl'}->{'action'}){ + if ($alerts{'sysctl'}->{'action'} ne 'use'){ + $cpu_string = "sysctl $alerts{'sysctl'}->{'action'}"; + $speed = "sysctl $alerts{'sysctl'}->{'action'}"; } else { $cpu_string = 'bsd support coming'; @@ -21931,35 +22944,31 @@ sub generate_short_data { my @disk = DiskData::get('short'); # print Dumper \@disk; my $disk_string = 'N/A'; - my ($size,$used,$size_type,$used_type) = ('','','',''); - my (@temp,$size_holder,$used_holder); + my ($size,$used) = ('',''); + my ($size_holder,$used_holder); if (@disk){ - $size = $disk[0]{'size'}; + $size = ($disk[0]{'logical-size'}) ? $disk[0]{'logical-size'} : $disk[0]{'size'}; # must be > 0 - if ($disk[0]{'size'} && is_numeric($disk[0]{'size'}) ){ - $size_holder = $disk[0]{'size'}; - @temp = get_size($size); - $size = $temp[0]; - $size_type = " $temp[1]"; + if ($size && is_numeric($size) ){ + $size_holder = $size; + $size = get_size($size,'string'); } $used = $disk[0]{'used'}; - if (is_numeric($disk[0]{'used'}) ){ + if ($used && is_numeric($disk[0]{'used'}) ){ $used_holder = $disk[0]{'used'}; - @temp = get_size($used); - $used = $temp[0]; - $used_type = " $temp[1]"; + $used = get_size($used,'string'); } # in some fringe cases size can be 0 so only assign 'N/A' if no percents etc if ($size_holder && $used_holder){ my $percent = ' (' . sprintf("%.1f", $used_holder/$size_holder*100) . '% used)'; - $disk_string = "$size$size_type$percent"; + $disk_string = "$size$percent"; } else { $size ||= row_defaults('disk-size-0'); - $disk_string = "$used$used_type/$size$size_type"; + $disk_string = "$used/$size"; } } - #print join '; ', @cpu, " sleep: $cpu_sleep\n"; + #print join('; ', @cpu), " sleep: $cpu_sleep\n"; $memory ||= 'N/A'; my @data = ({ main::key($num++,0,0,'CPU') => $cpu_string, @@ -21990,13 +22999,13 @@ sub generate_info_data { my $gcc_alt = ''; my $running_in = ''; my $data_name = main::key($prefix++,1,0,'Info'); - my ($b_gcc,$gcc,$index,$ref,%row); + my ($b_gcc,$gcc,$index); my ($gpu_ram,$parent,$percent,$total,$used) = (0,'','','',''); my @gccs = get_gcc_data(); if (@gccs){ $gcc = shift @gccs; if ($extra > 1 && @gccs){ - $gcc_alt = join '/', @gccs; + $gcc_alt = join('/', @gccs); } $b_gcc = 1; } @@ -22018,16 +23027,13 @@ sub generate_info_data { if (!$b_mem){ my $memory = get_memory_data('splits'); if ($memory){ - my @temp = split /:/, $memory; - my @temp2 = get_size($temp[0]); + my @temp = split(':', $memory); $gpu_ram = $temp[3] if $temp[3]; - $total = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0]; - @temp2 = get_size($temp[1]); - $used = ($temp2[1]) ? $temp2[0] . ' ' . $temp2[1] : $temp2[0]; + $total = ($temp[0]) ? get_size($temp[0],'string') : 'N/A'; + $used = ($temp[1]) ? get_size($temp[1],'string') : 'N/A'; $used .= " ($temp[2]%)" if $temp[2]; if ($gpu_ram){ - @temp2 = get_size($gpu_ram); - $gpu_ram = $temp2[0] . ' ' . $temp2[1] if $temp2[1]; + $gpu_ram = get_size($gpu_ram,'string'); } } $data{$data_name}[$index]{main::key($num++,1,1,'Memory')} = $total; @@ -22129,7 +23135,7 @@ sub generate_info_data { sub generate_system_data { eval $start if $b_log; my ($cont_desk,$ind_dm,$num) = (1,2,0); - my (%row,$ref,$index,$val1); + my ($index); my $data_name = main::key($prefix++,1,0,'System'); my ($desktop,$desktop_info,$desktop_key,$dm_key,$toolkit,$wm) = ('','','Desktop','dm','',''); my (@desktop_data,$desktop_version); diff --git a/inxi.1 b/inxi.1 index efda382..f4937d9 100644 --- a/inxi.1 +++ b/inxi.1 @@ -1,4 +1,4 @@ -.TH INXI 1 "2020\-11\-11" inxi "inxi manual" +.TH INXI 1 "2020\-12\-15" inxi "inxi manual" .SH NAME inxi \- Command line system information script for console and IRC @@ -6,7 +6,7 @@ inxi \- Command line system information script for console and IRC .SH SYNOPSIS \fBinxi\fR -\fBinxi\fR [\fB\-AbBCdDfFGhijJIlmMnNopPrRsSuUVwzZ\fR] +\fBinxi\fR [\fB\-AbBCdDfFGhiIjJlLmMnNopPrRsSuUVwzZ\fR] \fBinxi\fR [\fB\-c NUMBER\fR] [\fB\-\-sensors\-exclude SENSORS\fR] [\fB\-\-sensors\-use SENSORS\fR] @@ -173,11 +173,21 @@ few more features. .B \-D\fR,\fB \-\-disk\fR Show Hard Disk info. Shows total disk space and used percentage. The disk used percentage includes space used by swap partition(s), since those are not usable -for data storage. Note that with RAID disks, the percentage will be wrong since -the total is computed from the disk sizes, but used is computed from mounted -partition used percentages. This small defect may get corrected in the future. -Also, unmounted partitions are not counted in disk use percentages since inxi -has no access to the used amount. +for data storage. Also, unmounted partitions are not counted in disk use percentages +since inxi has no access to the used amount. + +If the system has RAID or other logical storage, and if inxi can determine +the size of those vs their components, you will see the storage total raw and usable +sizes, plus the percent used of the usable size. The no argument short form +of inxi will show only the usable (or total if no usable) and used percent. +If there is no logical storage detected, only \fBtotal:\fR and \fBused:\fR will +show. Sample (with RAID logical size calculated): + +\fBLocal Storage: total: raw: 5.49 TiB usable: 2.80 TiB used: 1.35 TiB (48.3%)\fR + +Without logical storage detected: + +\fBLocal Storage: total: 2.89 TiB used: 1.51 TiB (52.3%)\fR Also shows per disk information: Disk ID, type (if present), vendor (if detected), model, and size. See \fBExtra Data Options\fR (\fB\-x\fR options) and @@ -284,6 +294,81 @@ The \fBrev: 2.0\fR item refers to the USB revision number, like \fB1.0\fR or Show partition labels. Default: main partitions \fB\-P\fR. For full \fB\-p\fR output, use: \fB\-pl\fR. +.TP +.B \-L\fR, \fB\-\-logical\fR +Show Logical volume information, for LVM, LUKS, bcache, MultiPath, etc. Shows +size, free space (for LVM VG). For LVM, shows \fBDevice\-[xx]: VG:\fR +(Volume Group) size/free, \fBLV\-[xx]\fR (Logical Volume). LV shows type, +size, and components. Note that components are made up of either containers +(aka, logical devices), or physical devices. The full report requires sudo/root. + +Logical block devices can be thought of as devices that are made up out +of either other logical devices, or physical devices. inxi does its best +to show what each logical device is made out of. RAID devices form a subset +of all possible Logical devices, but have their own section, \fB\-R\fR. + +If \fB\-R\fR is used with \fB\-Lxx\fR, \fB\-Lxx\fR will not show RAID +information for LVM RAID devices since it's redundant. If \fB\-R\fR is +not used, a simple RAID line will appear for LVM RAID in \fB\-Lxx\fR. + +\fB\-Lxx\fR also shows all components and devices. Note that since +components can go in many levels, each level per primary component is +indicated by either another 'c', or ends with a 'p' device, the physical +device. The number of c's or p's indicates the depth, so you can see which +component belongs to which. + +\fB\-L\fR shows only the top level components/devices (like \fB\-R\fR). +\fB\-La\fR shows component/device size, maj:min ID, mapped name +(if applicable), and puts each component/device on its own line. + +Sample: + +\fBDevice\-10: mybackup type: LUKS dm: dm\-28 size: 6.36 GiB Components: c\-1: md1 +cc\-1: dm\-26 ppp\-1: sdj2 cc\-2: dm\-27 ppp\-1: sdk2\fR + +.nf +\fBLV-5: lvm_raid1 type: raid1 dm: dm\-16 size: 4.88 GiB +RAID: stripes: 2 sync: idle copied: 100% mismatches: 0 +Components: c\-1: dm\-10 pp\-1: sdd1 c\-2: dm\-11 pp\-1: sdd1 c\-3: dm\-13 +pp\-1: sde1 c\-4: dm\-15 pp\-1: sde1\fR +.fi + +It is easier to follow the flow of components and devices using \fB\-y1\fR. In +this example, there is one primary component (c\-1), md1, which is made up of two +components (cc\-1,2), dm\-26 and dm\-27. These are respectively made from physical +devices (p\-1) sdj2 and sdk2. + +.nf +\fBDevice-10: mybackup + maj-min: 254:28 + type: LUKS + dm: dm-28 + size: 6.36 GiB + Components: + c\-1: md1 + maj\-min: 9:1 + size: 6.37 GiB + cc-1: dm\-26 + maj-min: 254:26 + mapped: vg5\-level1a + size: 12.28 GiB + ppp\-1: sdj2 + maj\-min: 8:146 + size: 12.79 GiB + cc\-2: dm\-27 + maj\-min: 254:27 + mapped: vg5\-level1b + size: 6.38 GiB + ppp-1: sdk2 + maj\-min: 8:162 + size: 12.79 GiB\fR +.fi + +Other types of logical block handling like LUKS, bcache, multipath, +show as: + +\fBDevice\-[xx] [name/id] type: [LUKS|Crypto|bcache|MultiPath]:\fR + .TP .B \-m\fR,\fB \-\-memory\fR Memory (RAM) data. Does not display with \fB\-b\fR or \fB\-F\fR unless you use \fB\-m\fR @@ -310,6 +395,30 @@ will put this data into \fB/sys\fR, and make it real data, taken from the actual not dmi data. For most people, the data will be right, but a significant percentage of users will have either a wrong max module size, if present, or max capacity. +Under dmidecode, \fBSpeed:\fR is the expected speed of the memory +(what is advertised on the memory spec sheet) and \fBConfigured Clock Speed:\fR +is what the actual speed is now. To handle this, if speed and configured speed values +are different, you will see this instead: + +\fBspeed: spec: [specified speed] MT/S actual: [actual] MT/S\fR + +Also, if DDR, and speed in MHz, will change to: \fBspeed: [speed] MT/S ([speed] MHz\fR + +If the detected speed is logically absurd, like 1 MT/s or 69910 MT/s, adds: +\fBnote: check\fR. Sample: + +.nf +\fBMemory: + RAM: total: 31.38 GiB used: 20.65 GiB (65.8%) + Array-1: capacity: N/A slots: 4 note: check EC: N/A + Device-1: DIMM_A1 size: 8 GiB speed: 1600 MT/s (800 MHz) + Device-2: DIMM_A2 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) + actual: 61910 MT/s (30955 MHz) note: check + Device-3: DIMM_B1 size: 8 GiB speed: 1600 MT/s (800 MHz) + Device-4: DIMM_B2 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) + actual: 2 MT/s (1 MHz) note: check\fR +.fi + See \fB\-\-memory\-modules\fR and \fB\-\-memory\-short\fR if you want a shorter report. .TP @@ -370,9 +479,10 @@ Show full Partition information (\fB\-P\fR plus all other detected mounted parti .TP .B \-P\fR,\fB \-\-partitions\fR Show basic Partition information. -Shows, if detected: \fB/ /boot /home /opt /tmp /usr /usr/home /var /var/tmp /var/log\fR. +Shows, if detected: \fB/ /boot /boot/efi /home /opt /tmp /usr /usr/home /var /var/tmp +/var/log\fR (for android, shows \fB/cache /data /firmware /system\fR). If \fB\-\-swap\fR is not used, shows active swap partitions (never shows file or -zram type swap). +zram type swap). Use \fB\-p\fR to see all mounted partitions. .TP @@ -418,15 +528,19 @@ See \fB\-rx\fR, \fB\-rxx\fR, and \fB\-ra\fR for installed package count informat .TP .B \-R\fR,\fB \-\-raid\fR -Show RAID data. Shows RAID devices, states, levels and components, and -extra data with \fB\-x\fR / \fB\-xx\fR. +Show RAID data. Shows RAID devices, states, levels, device/array size, +and components. See extra data with \fB\-x\fR / \fB\-xx\fR. md\-raid: If device is resyncing, also shows resync progress line. -Note: Only md\-raid and ZFS are currently supported. Other software RAID types could -be added, but only if users supply all data required, and if the software +Note: Only md\-raid, ZFS and hardware RAID are currently supported. +Other software RAID types may be added, if the software RAID actually can be made to give the required output. +The component ID numbers work like this: mdraid: the numerator +is the actual mdraid component number; ZFS: the numerator is +auto-incremented counter only. Eg. \fBOnline: 1: sdb1\fR + If hardware RAID is detected, shows basic information. Due to complexity of adding hardware RAID device disk / RAID reports, those will only be added if there is demand, and reasonable reporting tools. @@ -474,8 +588,8 @@ Make sure that there is no space between letters and numbers (e.g. write as \fB\ .TP .B \-t m\fR \- memory only. With \fB\-x\fR, also shows CPU for that process on same line. -If the \-I line is not triggered, will also show the system RAM used/total -information. +If the \fB\-I\fR or \fB\-m\fR lines are not triggered, will also show the +system RAM used/total information. .TP .B \-t cm\fR @@ -557,9 +671,9 @@ USB (\fB\-J\fR); triggers \fB\-xx\fR extra data option. .TP .B \-v 8 -\- All system data available. Adds Repos (\fB\-r\fR), PCI slots (\fB\-\-slots\fR), -processes (\fB\-tcm\fR), admin (\fB\-\-admin\fR). Useful for testing output and to -see what data you can get from your system. +\- All system data available. Adds Logical (\fB\-L\fR), Repos (\fB\-r\fR), +PCI slots (\fB\-\-slots\fR), processes (\fB\-tcm\fR), admin (\fB\-\-admin\fR). +Useful for testing output and to see what data you can get from your system. .TP .B \-w\fR,\fB \-\-weather\fR @@ -687,10 +801,14 @@ have this feature. \- Adds CPU microarchitecture + revision (e.g. Sandy Bridge, K8, ARMv8, P6, etc.). Only shows data if detected. Newer microarchitectures will have -to be added as they appear, and require the CPU family ID and model ID. +to be added as they appear, and require the CPU family ID, model ID, +and stepping. Examples: \fBarch: Sandy Bridge rev: 2\fR, \fBarch: K8 rev.F+ rev: 2\fR +If unable to non\-ambiguosly determine architecture, will show something like: +\fBarch: Amber Lake note: check rev: 9\fR + .TP .B \-x \-d\fR \- Adds more items to \fBFeatures\fR line of optical drive; @@ -698,11 +816,33 @@ dds rev version to optical drive. .TP .B \-x \-D\fR -\- Adds HDD temperature with disk data if you have hddtemp installed, if you are root +\- Adds HDD temperature with disk data. + +Method 1: if you have hddtemp installed, if you are root or if you have added to \fB/etc/sudoers\fR (sudo v. 1.7 or newer): .B ALL = NOPASSWD: /usr/sbin/hddtemp (sample) +Method 2: systems running Linux kernels ~5.8 and newer may have drive temp data +available from /sys. If your system has /sys hwmon drive data, the temps +will come from /sys data for each drive with that data, and will not require +root or hddtemp!! This method is MUCH faster than using hddtemp! + +If you see drive temps running as regular user and you did not configure system +to use sudo hddtemp, then your system supports this feature. Sometimes one type +of drive will have the /sys temp data, and another won't, it varies widely. +If no /sys data is found, inxi will try to use hddtemp methods instead +for that drive. + +Hint: is /sys sourced, the temps will be to 1 decimal, like 34.8, if hddtemp +sourced, they will be integers. + +You can force use of \fBhddtemp\fR for all drives using \fB\-\-hddtemp\fR. + +\- If free LVM volume group size detected (root required), show \fBlvm-free:\fR +on Local Storage line. This is how much unused space the VGs contain, that is, +space not assigned to LVs. + .TP .B \-x \-G\fR \- Adds (if available and/or relevant) \fBvendor:\fR item, which shows @@ -759,10 +899,19 @@ discover those. \- If in shell (i.e. not in IRC client), adds shell version number, if available. +.TP +.B \-x \-j\fR, \fB\-x \-\-swap\fR +Add \fBmapper:\fR. See \fB\-x \-o\fR. + .TP .B \-x \-J\fR (\fB\-\-usb\fR) \- For Devices, adds driver(s). +.TP +.B \-x \-L\fR, \fB\-x \-\-logical\fR +\- Adds \fBdm: dm-x\fR to VG > LV and other Device types. This can help tracking +down which device belongs to what. + .TP .B \-x \-m\fR, \fB\-\-memory\-modules\fR \- If present, adds maximum memory module/device size in the Array line. @@ -780,6 +929,13 @@ specific vendor [product] information. \- Adds PCI Bus ID/USB ID number of each Network card. +.TP +.B \-x \-o\fR, \fB\-x \-p\fR, \fB\-x \-P\fR +\- Adds \fBmapper:\fR (the \fB/dev/mapper/\fR partitioni ID) +if mapped partition. + +Example: \fBID-4: /home ... dev: /dev/dm-6 mapped: ar0-home\fR + .TP .B \-x \-r\fR \- Adds Package info. See \fB\-Ix\fR @@ -901,6 +1057,15 @@ swap types (for \fB\-j\fR). .B \-xx \-J\fR (\fB\-\-usb\fR) \- Adds vendor:chip id. +.TP +.B \-xx \-L\fR, \fB\-xx \-\-logical\fR +\- Adds internal LVM Logical volumes, like raid image and meta data volumes. + +\- Adds full list of Components, sub\-components, and their physical devices. + +\- For LVM RAID, adds a RAID report line (if not \fB\-R\fR). Read up on LVM +documentation to better understand their use of the term 'stripes'. + .TP .B \-xx \-m\fR, \fB\-\-memory\-modules\fR \- Adds memory device Manufacturer. @@ -1137,6 +1302,8 @@ Using \fBsmartctl\fR (requires sudo/root privileges). \- Adds SATA type (eg 1.0, 2.6, 3.0) if a SATA device. +\- Adds device kernel major:minor number (Linux only). + \- Adds SMART report line: status, enabled/disabled, health, powered on, cycles, and some error cases if out of range values. Note that for Pre\-fail items, it will show the VALUE and THRESHOLD numbers. It will also fall back for unknown @@ -1241,7 +1408,7 @@ Info: .fi .TP -.B \-a \-j\fR, \fB\-a \-P\fR , \fB\-a \-P\fR +.B \-a \-j\fR, \fB\-a \-P\fR [swap], \fB\-a \-P\fR [swap] \- Adds swappiness and vfs cache pressure, and a message to indicate if the value is the default value or not (Linux only, and only if available). If not the default value, shows default value as well, e.g. @@ -1254,6 +1421,15 @@ For \fB\-j\fR row 1 output: \fBKernel: swappiness: 60 (default) cache pressure: 90 (default 100)\fR +\- Adds device kernel major:minor number (Linux only). + +.TP +.B \-a \-L\fR +\- Expands Component report, shows size / maj-min of components and devices, and +mapped name for logical components. Puts each component/device on its own line. + +\- Adds maj-min to LV and other devices. + .TP .B \-a \-n\fR, \fB\-a \-N\fR, \fB\-a \-i\fR \- Adds, if present, possible \fBalternate:\fR kernel modules capable of driving @@ -1262,6 +1438,10 @@ modules found, shows nothing. NOTE: just because it lists a module does NOT mean available in the system, it's just something the kernel knows could possibly be used instead. +.TP +.B \-a \-o\fR +\- Adds device kernel major:minor number (Linux only). + .TP .B \-a \-p\fR,\fB\-a \-P\fR \- Adds raw partition size, including file system overhead, partition table, e.g. @@ -1277,10 +1457,19 @@ not the raw size. \- Adds partition filesystem block size if found (requires root and blockdev). +\- Adds device kernel major:minor number (Linux only). + .TP .B \-a \-r\fR \- Adds Packages. See \fB\-Ia\fR +.TP +.B \-a \-R\fR +\- Adds device kernel major:minor number (mdraid, Linux only). + +\- Adds, if available, component size, major:minor number, state (Linux only). +Turns Component report to 1 component per line if size and major:minor present. + .TP .B \-a \-S\fR \- Adds kernel boot parameters to \fBKernel\fR section (if detected). Support @@ -1346,6 +1535,10 @@ e.g. \fB\-M\fR or \fB\-B\fR. .B \-\-downloader [curl|fetch|perl|wget]\fR Force inxi to use Curl, Fetch, Perl, or Wget for downloads. +.TP +.B \-\-hddtemp\fR +Force use of hddtemp instead of /sys temp data for disks. + .TP .B \-\-host\fR Turns on hostname in System line. Overrides inxi config file value (if set): @@ -1416,7 +1609,7 @@ Overrides user set \fBSENSOR_FORCE\fR configuration value. Restores default beha Skip SSL certificate checks for all downloader actions (\fB\-U\fR, \fB\-w\fR, \fB\-W\fR, \fB\-i\fR). Use if your system does not have current SSL certificate lists, or if you have problems making a connection for any reason. Works with -\fBWget\fR, \fBCurl\fR, \fBPerl HTTP::Tiny\fRand \fBFetch\fR. +\fBWget\fR, \fBCurl\fR, \fBPerl HTTP::Tiny\fR and \fBFetch\fR. .TP .B \-\-no\-sudo\fR @@ -1618,7 +1811,7 @@ For alternate ftp upload locations: Example: .SH DEBUGGING OPTIONS TO DEBUG DEBUGGER FAILURES -Only used the following in conjunction with \fB\-\-debug 2[012]\fR, and only +Only use the following in conjunction with \fB\-\-debug 2[012]\fR, and only use if you experienced a failure or hang, or were instructed to do so. .TP diff --git a/inxi.changelog b/inxi.changelog index 6a07097..9a933b9 100644 --- a/inxi.changelog +++ b/inxi.changelog @@ -1,3 +1,396 @@ +===================================================================================== +Version: 3.2.00 +Patch: 00 +Date: 2020-12-15 +----------------------------------- +Changes: +----------------------------------- + +Huge upgrade, major rewrite/refactor, new features, everything is polished!!! + +Note that due to large number of internal changes to code, a separate +INTERNAL CODE CHANGES section is at the bottom. Those are changes which in +general do not impact what users see that much, but which definitely impact +working on and with inxi! They also make errors less likely, and removed many +possible bad data error situations. + +BUGS: + +1. Obscure, but very old Tyan Mobo used a form of dmidecode data for RAM that I'd +never gotten a dataset for before, this tripped a series of errors in inxi, which +were actually caused by small errors and failures to check certain things, as +well as simply never assigning data in corner cases. This system used only dmi +handles 6 and 7, which is a very rare setup, from the very early days of dmi +data being settled, but it was valid data, and actually inxi was supposed to support +it, because I'd never gotten a dataset containing such legacy hardware data, the +support didn't work. There were actually several bugs discovered while tracking +this down, all were corrected. + +2. Going along with the cpu fixes below, there was a bug that if stepping was 0, +stepping would not show. I had not realized stepping could be 0, so did a true/false +test instead of a defined test, which makes 0 in perl always test as false. This is +corrected. + +3. While going through code, discovered that missing second argument to main::grabber +would have made glabel tool (BSD I think mostly) always fail, without exception. +That explains why bsd systems were never getting glabel data, heh. + +4. Many null get_size tests would not have worked because they were testing +for null array but ('','') was actually being returned, which is not a null array. +The testing and results for get_size were quite random, now hey are all the same +and consistent, and confirmed correct. + +5. In unmounted devices, the match sent to @lsblk to get extended device data +would never work with dm-xx type names, failed to translate them to their +mapped name, which is what is used in lsblk matches, this is corrected. +This could lead to failures to match fs of members of luks, raid, etc, +particularly noticeable with complex logical device structures. This means +the fallback filters against internal logic volume names, various file system +type matches, would always fail. + +6. A small host of further bugs found and fixed during the major refactor, but +not all of them were noted, they were just fixed, sorry, those will be lost +to history unless you compare with diffs the two versions, but that's thousands +of lines, but there were more bugs fixed than listed above, just can't remember +them all. + +FIXES: + +1. There was some ambiguity about when inxi falls back to showing hardware graphics +driver instead of xorg gfx driver when it can't find an xorg driver. That can happen +for instance because of wayland, or because of obscure xorg drivers not yet supported. +Now the message is very clear, it says the gfx software driver is n/a, and that it's +showing the hardware gfx driver. + +2. Big redo of cpu microarch, finally handled cases where same stepping/model ID +has two micorarches listed, now that is shown clearly to users, like AMD Zen family +17, model 18, which can be either Zen or Zen+, so now it shows that ambiguity, and +a comment: note: check, like it shows for ram report when it's not sure. Shows +for instance: +arch: Zen/Zen+ note: check +in such cases, in other words, it tells users that the naming convention +basically changed during the same hardware/die cycle. + +3. There were some raid component errors in the unmounted tests which is supposed +to test the raid components and remove them from the mounted list. Note that inxi +now also tests better if something is a raid component, or an lvm component, or +various other things, so unmounted will be right more often now, though it's still +not perfect since there are still more unhandled logical storage components that +will show as unmounted when tney are parts of logical volumes. Bit by bit!! + +4. Part of a significant android fine tuning and fix series, for -P, android uses +different default names for partitions, so none showed, now a subset of standard +android partitions, like /System, /firmware, etc, shows. Android will never work +well though because google keeps locking down key file read/search permissions in +/sys and /proc. + +5. More ARM device detections, that got tuned quite a bit and cleaned up, for +instance, it was doing case sensitive checks, but found cases where the value +is all upper case, so it was missing it. Now it does case sensitive device type +searches. + +6. One of the oldest glitches in inxi was the failure to take the size of the raid +arrays versus the size totals of the raid array components led to Local Storage +results that were uselessly wrong, being based on what is now called 'raw' disk +totals, that's the raw physical total of all system disks. Now if raid is detected +the old total: used:... is expanded to: total: raw:... usable:....used:, the usable +being the actual disk space that can be used to store data. Also in the case of +LVM systems, a further item is added, lvm-free: to report the unused but available +volume group space, that is, space not currently taken by logical volumes. This +can provide a useful overview of your system storage, and is much improved over +the previous version, which was technically unable to solve that issue because +the internal structures did not support it, now they do. LVM data requires sudo/ +root unfortunately, so you will see different disk raw totals depending on +if it's root or not if there is LVM RAID running. + +Sample: inxi -D +Drives: Local Storage: total: raw: 340.19 GiB usable: 276.38 GiB + lvm-free: 84.61 GiB used: 8.49 GiB (3.1%) + +lvm-free is non assigned volume group size, that is, size not assigned +to a logical volume in the volume group, but available in the volume group. +raw: is the total of all detected block devices, usable is how much of that +can be used in file systems, that is, raid is > 1 devices, but those devices +are not available for storage, only the total of the raid volume is. +Note that if you are not using LVM, you will never see lvm-free:. + +7. An anonymous user sent a dataset that contained a reasonable alternate +syntax for sensors output, that made inxi fail to get the sensors data. That was +prepending 'T' to temp items, and 'F' to fan items, which made enough sense though +I'd never seen it before, so inxi now supports that alternate sensors temp/fan +syntax, so that should expand the systems it supports by default out of the box. + +8. Finally was able to resolve a long standing issue of loading File::Find, which +is only used in --debug 20-22 debugger, from top of inxi to require load in the +debugger. I'd tried to fix this before, but failed, the problem is that redhat +/fedora have broken apart Perl core modules, and made some of them into external +modules, which made inxi fail to start due to missing use of required module that +was not really required. Thanks to mrmazda for pointing this out to me, I'd tried +to get this working before but failed, but this time I figured out how to recode +some of the uses of File::Find so it would work when loaded without the package +debugger, hard to figure it, turned out a specific sub routine call in that +specific case required the parentheses that had been left off, very subtle. + +9. Subtle issue, unlike most of the other device data processors, the USB +data parser did not use the remove duplicates tool, which led in some cases +to duplicated company names in the output for USB, which looks silly. + +10. Somehow devtmpfs was not being detected in all cases to remove that from +partitions report, that was added to the file systen filters to make sure it +gets caught. + +11. Removed LVM image/meta/data data slices from unmounted report, those are LVM +items, but they are internal LVM volumes, not available or usable. I believe +there are other data/meta type variants for different LVM features but I have +added as many types as I could find.. Also explictly now remove any _member type +item, which is always part of some other logical structure, like RAID or +LVM, those were not explicitly handled before. + +12. Corrected the varous terms ZFS can use for spare drives, and due to how +those describe slightly different situations than simply spare, changed the spare +section header to Available, which is more accureate for ZFS. + +ENHANCEMENTS: + +1. Going along with FIX 2 is updating and adding to intel, elbrus microarch family/ +model/stepping IDs (E8C2), so that is fairly up to date now. + +2. Added in a very crude and highly unreliable default fallback for intel: +/sys/devices/cpu/caps/pmu_name which will show the basic internal name used +which can be quite different from what the actual microarch name is, but the hope +is that for new intel cpus that come out after these last inxi updates, something +may show, instead of nothing. Note these names are often much more generic, like +using skylake for many different microarches. + +3. More android enhancements, for androids that allow reading of /system/build.prop, +which is a very useful informative system info file, more android data will show, +like the device name and variant, and a few other specialized items. You can see if +your android device lets inxi read build.prop if you see under -S Distro: +Android 7.1 (2016-07-23) or just Android. If it shows just android, that means +it can't read that file. Showing Android however is also new, since while inxi +can't always read build.prop if that file is there, it's android, so inxi +finally can recognize it's in android, even though it can't give much info if +it's locked down. Inxi in fact did not previously know it was running in android, +which is quite different from ARM systems in some ways, but now it does. + +If the data is available, it will be used in Distro: and in Machine: data to add +more information about the android version and device. + +4. A big one, for -p/-P/-o/-j now shows with -x the mapped device name, not just +the /dev/dm-xx ID, which makes connecting the various new bits easier, for RAID, +Logical reports. Note that /dev/mapper/ is removed from the mapped name since +that's redundant and verbose and makes the output harder to read. For mapped +devices, the new --logical / -L report lets you drill into the devices to find +out what dm-xx is actually based on, though that is a limited feature which only +supports drilling to a depth of 2 components/devices, there can be more, +particularly for bcache, luks setups, but it's just too hard to code that +level of depth, so something is better than nothing in this case, which +is the actual choice I was faced, the perfect in this case really is/was +the enemy of the good, as they say. + +5. More big ones, for -a -p/-P/-o/-j shows kernel device major:minor number, +which again lets you trace each device around the system and report. + +6. Added mdadm if root for mdraid report, that let me add a few other +details for mdraid not previously available. This added item 'state;' +to the mdraid report with right -x options. + +7. Added vpu component type to ARM gfx device type detection, don't know +how video processing vcu had escaped my notice. + +8. Added fio[a-z] block device, I'd never heard of that before, but saw +use of it in dataset, so learned it's real, but was never handled as a +valid block device type before, like sda, hda, vda, nvme, mmcblk, +etc. fio works the same, it's fio + [a-z] + [0-9]+ partition number. + +9. Expanded to alternate syntax Elbrus cpu L1, L2, L3 reporting. Note +that in their nomenclature, L0 and L1 are actually both L1, so add those +together when detected. + +10. RAM, thanks to a Mint user, antikythera, learned, and handled something +new, module 'speed:' vs module 'configured clock speed:'. +To quote from supermicro: + +<<< +Question: Under dmidecode, my 'Configured Clock Speed' is lower than my +'Speed'. What does each term mean and why are they not the same? +Answer: Under dmidecode, Speed is the expected speed of the memory +(what is advertised on the memory spec sheet) and Configured Clock Speed +is what the actual speed is now. The cause could be many things but the +main possibilities are mismatching memory and using a CPU that doesn't +support your expected memory clock speed. +Please use only one type of memory and make sure that your CPU supports +your memory. +>>> + +11. Since RAM was gettng a look, also changed cases where ddr ram speed is reported +in MHz, now it will show the speeds as: [speed * 2] MT/S ([speed] MHz). This +will let users make apples to apples speed comparisons between different systems. +Since MT/S is largely standard now, there's no need to translate that to MHz. + +12. And, even more!! When RAM speeds are logically absurd, adds in note: check +This is from a real user's data by the way, as you can see, it triggers all +the new RAM per Device report features. + +Sample: +Memory: + RAM: total: 31.38 GiB used: 20.65 GiB (65.8%) + Array-1: capacity: N/A slots: 4 note: check EC: N/A + Device-1: DIMM_A1 size: 8 GiB speed: 1600 MT/s (800 MHz) + Device-2: DIMM_A2 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) + actual: 61910 MT/s (30955 MHz) note: check + Device-3: DIMM_B1 size: 8 GiB speed: 1600 MT/s (800 MHz) + Device-4: DIMM_B2 size: 8 GiB speed: spec: 1600 MT/s (800 MHz) + actual: 2 MT/s (1 MHz) note: check + +13. More disks vendor!!! More disk vendor IDs!!! Yes, that's right, eternity +exists, here, now, and manifests every day!! Thanks to linux-lite hardware +database for this eternally generating list. Never underestimate the +creativity of mankind to make more disk drive companies, and to release +new model IDs for existing companies. Yes, I feel that this is a metaphore +for something much larger, but what that is, I'm not entirely clear about. + +CHANGES: + +1. Recent kernel changes have added a lot more sensor data in /sys, although +this varies system to system, but now, if your system supports it, you can +get at least partial hdd temp reports without needing hddtemp or root. Early +results suggest that nvme may have better support than spinning disks, but it +really varies. inxi will now look for the /sys based temp first, then fall +back to the much slower and root / sudo only hddtemp. You can force hddtemp +always with --hddtemp option, which has a corresponding configuration item. + +2. The long requested and awaited yet arcane and obscure feature -L/--logical, +which tries to give a reasonably good report on LVM, LUKS, VeraCrypt, as well +as handling LVM raid, both regular and thin, is now working, more or less. +This took a lot of testing and will probably not be reasonably complete for +a while, mainly because the levels of abstraction possible between lvm, +lvm raid, mdraid, LUKS, bcache, and other caching and other encryption +options are just too deep to allow for easy handling, or easy outputs. +But a very solid and good start in my view, going from nothing to something +is always a big improvement!! LVM reports require root/sudo. This will, +finally, close issue #135. + +3. Going along with -L, and serving as a model for the logic of -L, was the +complete refactor of -R, RAID, which was a real mess internally, definitely +one of the messiest and hardest to work with features of inxi before the +refactor. It's now completely cleaned up and modularized, and is easy to add +raid types, which was not possible before, now it cleanly supports zfs, mdraid, +and lvm raid, with in depth reports and added items like mdraid size, raid +component device sizes and maj:min numbers if the -a option is used. Note +that LVM RAID requires root/sudo. + +4. Added some more sensors dimm, volts items, slight expansion. Note that the +possible expansion of sensors made possible by the recently upgraded sensors +output logic, as well as the new inxi internal sensors data structure, +which is far more granular than the previous version, and allows for much +more fine grained control and output, though only gpu data currently takes +advantage of this new power under the covers, although as noted, the /sys based +hdd temps use the same source, only straight from /sys, since it was actually +easier using the data directly from sys than trying to map the drive locations to +specific drives in sensors output. Well, to be accurate, since now only +board type sensors are used for the temp/fan speed, voltage, etc, reports, +the removal of entire sensor groups means less chance of wrong results. + +5. To bring the ancient RAID logic to fit the rest of inxi style, made +zfs, mdraid, and lvm raid components use incrementing numbers, like cpu +cores does. This got rid of the kind of ugly hacks used previously +which were not the same for zfs or mdraid, but now they are all the same, +except that the numbers for mdraid are the actual device numbers that +mdraid supplies, and the LVM and ZFS numbers are just autoincremented, +starting at 1. + +6. Changed message to because +it's shorter and communicates the same thing. + +INTERNAL CODE CHANGES: + +1. Small, transparent test, tested on Perl 5.032 for Perl 7 compatibility. All +tests passed, no legacy code issues in inxi as of now. + +2. Although most users won't notice, a big chunk of inxi was refactored +internally, which is why the new -L, the revamped -R, and the fixed +disk totals finally all can work now. This may hopefully result in more +consistent output and fewer oddities and randomnesses, since more of the +methods all use the same tools now under the covers. Ths refactor also +significantly improved inxi's execution speed, by about 4-5%, but most +of those gains are not visible due to the added new features, but the +end result is new inxi runs roughly the same speed as pre 3.2.00 inxi, but +does more, and does it better, internally at least. If you have a very +good eye you may also note a few places where this manifests externally +as well. Last I checked about 10-12% of the lines of inxi had been changed, +but I think that number is higher now. Everything that could be optimized +was, everything could be made more efficient was. + +3. Several core tools in inxi were expanded to work much more cleanly, +like reader(), which now supports returning just the index value you want, +that always happened on the caller end before, which led to extra code. +get_size likewise was expanded to do a string return, which let me +remove a lot of internal redundant code in creating the size unit output, +like 32 MiB. uniq() was also redone to work exclusively by reference. + +4. Many bad reference and dereference practices that had slipped into inxi +from the start are mostly corrected now, array assignments use push now, +rather than assign to array, then add array to another array, and assign +those to the master array. Several unnecessary and cpu/ram intensive copying +steps, that is, were removed in many locations internally in inxi. Also +now inxi uses more direct anonymous array and hash refernce assignments, +which again removes redundant array/hash creation, copy, and assignment. + +5. Also added explicit -> dereferencing arrows to make the code more clear +and readable, and to make it easier for perl to know what is happening. +The lack of consistency actually created confusion, I was not aware of +what certain code was doing, and didn't realize it was doing the same +thing as other code because of using different methods and syntaxes for +referencing array/hash components. I probably missed some, but I got many +of them, most probably. + +6. Instituted a new perl builtin sub routine rule which is: if the sub +takes 2 or more arguments, always put in parentheses, it makes the +code much easier to follow because you see the closing ), like: +push(@rows,@row); Most perl builtins that take only one arg do not +use parentheses, except length, which just looks weird when used in +math tests, that is: length($var) > 13 looks better than length $var > 13. +This resolved inconsistent uses that had grown over time, so now all the +main builtins follow these rules consistently internally. + +Due to certain style elements, and the time required to carefully go through +all these rules, grep and map do not yet consistently use these rules, that's +because the tendency has been to use the grep {..test..} @array and +map {...actions...} @array + +7. Mainly to deal with android failures to read standard system files due to +google locking it down, moved most file queries to use -r, is readable, rather +than -e, exists, or -f, is file, unless it only needs to know if it exists, +of course. This fixed many null data errors in android even on locked androids. + +8. Added in %mapper and %dmmapper hashes to allow for easy mapping and +unmapping of mapped block devices. Got rid of other ways of doing that, +and made it consistent throughout inxi. These are globals that load once. + +9. Learned that perl builtin split() has a very strange and in my view originally +terrible decision that involves treating as regex rules string characters in split +string, like split('^^',$string), which should logically be a string value, not +a ^ start search followed by a ^, but that's how it is, so that was carefully checked +and made consistent as well. Also expanded split to take advantage of the number of +splits to do, which I had only used occasionally before, but only updated field/value +splits where I have a good idea of what the data is. This is very useful when the +data is in the form of field: value, but value can contain : as well. You have to +be very careful however, since some data we do want in fact the 2nd split, but not +the subsequent ones, so I only updated the ones I was very sure about. + +10. Going along with the cpu microarch fixes, updated and cleaned up all the lists +of model/stepping matches, now they are all in order and much easier to scan and +find, that had gotten sloppy over the years. + +11. More ARM, moved dummy and codec device values into their own storage arrays, +that let me remove the filters against those in the other detections. Makes logic +easier to read and maintain as well. + + +----------------------------------- +-- Harald Hope - Tue, 15 Dec 2020 15:08:05 -0800 + ===================================================================================== Version: 3.1.09 Patch: 00