From 5234e3903d072601c5e8e2a41b6ba6aa134ba142 Mon Sep 17 00:00:00 2001 From: Harald Hope Date: Tue, 15 Dec 2020 15:13:14 -0800 Subject: [PATCH] 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. --- inxi | 7044 +++++++++++++++++++++++++++--------------------- inxi.1 | 239 +- inxi.changelog | 393 +++ 3 files changed, 4634 insertions(+), 3042 deletions(-) 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