1019 lines
28 KiB
PHP
1019 lines
28 KiB
PHP
<?php
|
|
|
|
/*
|
|
Phoronix Test Suite
|
|
URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
|
|
Copyright (C) 2009 - 2024, Phoronix Media
|
|
Copyright (C) 2009 - 2024, Michael Larabel
|
|
phodevi.php: The object for interacting with the PTS device framework
|
|
|
|
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.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
class phodevi extends phodevi_base
|
|
{
|
|
public static $vfs = false;
|
|
private static $device_cache = array();
|
|
private static $smart_cache = array();
|
|
private static $sensors = null;
|
|
|
|
private static $operating_system = null;
|
|
private static $graphics_detected = false;
|
|
private static $graphics = array(
|
|
'mesa' => false,
|
|
'ati' => false,
|
|
'nvidia' => false
|
|
);
|
|
private static $operating_systems = array(
|
|
'linux' => false,
|
|
'macosx' => false,
|
|
'solaris' => false,
|
|
'bsd' => false,
|
|
'hurd' => false,
|
|
'minix' => false,
|
|
'windows' => false
|
|
);
|
|
|
|
// A variable that modules can use to override Phodevi caching support, etc
|
|
public static $allow_phodevi_caching = true;
|
|
protected static $sanitize_string = null;
|
|
|
|
const no_caching = 1;
|
|
const std_caching = 2;
|
|
const smart_caching = 3;
|
|
|
|
public static function read_name($device)
|
|
{
|
|
return phodevi::read_property($device, 'identifier');
|
|
}
|
|
public static function load_sensors()
|
|
{
|
|
if(!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300)
|
|
{
|
|
// Phodevi sensors don't work prior to PHP 5.3
|
|
self::$sensors = array();
|
|
return false;
|
|
}
|
|
|
|
foreach(glob(dirname(__FILE__) . '/sensors/*') as $sensor_obj_file)
|
|
{
|
|
$sensor_obj_name = basename($sensor_obj_file, '.php');
|
|
|
|
if(!class_exists($sensor_obj_name, false))
|
|
{
|
|
include($sensor_obj_file);
|
|
}
|
|
|
|
$type = call_user_func(array($sensor_obj_name, 'get_type'));
|
|
$sensor = call_user_func(array($sensor_obj_name, 'get_sensor'));
|
|
|
|
if($type != null && $sensor != null)
|
|
{
|
|
self::$sensors[$type][$sensor] = $sensor_obj_name;
|
|
}
|
|
}
|
|
}
|
|
public static function available_sensors()
|
|
{
|
|
static $available_sensors = null;
|
|
|
|
if($available_sensors == null)
|
|
{
|
|
$available_sensors = array();
|
|
|
|
foreach(self::$sensors as $sensor_type => &$sensor)
|
|
{
|
|
foreach(array_keys($sensor) as $sensor_senses)
|
|
{
|
|
array_push($available_sensors, array($sensor_type, $sensor_senses, self::$sensors[$sensor_type][$sensor_senses]));
|
|
}
|
|
}
|
|
}
|
|
|
|
return $available_sensors;
|
|
}
|
|
public static function is_sensor_supported($sensor)
|
|
{
|
|
$supported = false;
|
|
$sensors = self::query_sensors();
|
|
foreach($sensors as $s)
|
|
{
|
|
if($s[0] == $sensor[0] && $s[1] == $sensor[1])
|
|
{
|
|
$supported = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $supported;
|
|
}
|
|
public static function query_sensors($limit_sensor_selection = false)
|
|
{
|
|
static $supported_sensors = null;
|
|
|
|
if($limit_sensor_selection != false)
|
|
{
|
|
$selected = array();
|
|
foreach(self::available_sensors() as $sensor)
|
|
{
|
|
if($limit_sensor_selection == false || (is_array($limit_sensor_selection) && in_array($sensor[2], $limit_sensor_selection)))
|
|
{
|
|
array_push($selected, $sensor);
|
|
}
|
|
}
|
|
return $selected;
|
|
}
|
|
else if($supported_sensors == null)
|
|
{
|
|
$supported_sensors = array();
|
|
foreach(self::available_sensors() as $sensor)
|
|
{
|
|
if(self::sensor_supported($sensor))
|
|
{
|
|
array_push($supported_sensors, $sensor);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $supported_sensors;
|
|
}
|
|
public static function read_sensor($sensor)
|
|
{
|
|
if($sensor instanceof phodevi_sensor)
|
|
{
|
|
$sensor_object = $sensor;
|
|
}
|
|
else
|
|
{
|
|
$sensor_object = new self::$sensors[$sensor[0]][$sensor[1]](null, null);
|
|
}
|
|
|
|
return $sensor_object->read_sensor();
|
|
}
|
|
public static function read_sensor_object_unit(&$sensor_object)
|
|
{
|
|
$sensor = array($sensor_object->get_type(), $sensor_object->get_sensor(), get_class($sensor_object));
|
|
return self::read_sensor_unit($sensor);
|
|
}
|
|
public static function read_sensor_object_unit_short(&$sensor_object)
|
|
{
|
|
$sensor_unit = self::read_sensor_object_unit($sensor_object);
|
|
|
|
switch($sensor_unit)
|
|
{
|
|
case 'Celsius':
|
|
$sensor_unit = 'C';
|
|
break;
|
|
case 'Percent':
|
|
$sensor_unit = '%';
|
|
break;
|
|
case 'Megabytes':
|
|
$sensor_unit = 'MB';
|
|
break;
|
|
case 'Megahertz':
|
|
$sensor_unit = 'MHz';
|
|
break;
|
|
case 'Volts':
|
|
$sensor_unit = 'V';
|
|
break;
|
|
case 'Kilobytes/seconds':
|
|
$sensor_unit = 'KBps';
|
|
break;
|
|
case 'Millivolts':
|
|
$sensor_unit = 'mV';
|
|
break;
|
|
}
|
|
|
|
return $sensor_unit;
|
|
}
|
|
public static function read_sensor_unit($sensor)
|
|
{
|
|
return call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_unit'));
|
|
}
|
|
public static function sensor_supported($sensor)
|
|
{
|
|
$sensor_object = new self::$sensors[$sensor[0]][$sensor[1]](null, null);
|
|
|
|
return isset(self::$sensors[$sensor[0]][$sensor[1]]) && $sensor_object->support_check();
|
|
}
|
|
public static function sensor_object_identifier(&$sensor_object)
|
|
{
|
|
$sensor = array($sensor_object->get_type(), $sensor_object->get_sensor(), get_class($sensor_object));
|
|
return self::sensor_identifier($sensor) . ($sensor_object->get_instance() != 0 ? '.' . $sensor_object->get_instance() : null);
|
|
}
|
|
public static function sensor_identifier($sensor)
|
|
{
|
|
return $sensor[0] . '.' . $sensor[1];
|
|
}
|
|
public static function sensor_object_name(&$sensor_object)
|
|
{
|
|
$sensor = array($sensor_object->get_type(), $sensor_object->get_sensor(), get_class($sensor_object));
|
|
$name = self::sensor_name($sensor);
|
|
$params = $sensor_object->get_readable_device_name();
|
|
|
|
if($params !== NULL)
|
|
{
|
|
$name .= ' (' . $params . ')';
|
|
}
|
|
|
|
return $name;
|
|
}
|
|
public static function sensor_name($sensor)
|
|
{
|
|
$type = call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_type'));
|
|
$sensor = call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_sensor'));
|
|
|
|
if(strlen($type) < 4)
|
|
{
|
|
$formatted = strtoupper($type);
|
|
}
|
|
else
|
|
{
|
|
$formatted = ucwords($type);
|
|
}
|
|
|
|
switch($formatted)
|
|
{
|
|
case 'SYS':
|
|
$formatted = 'System';
|
|
break;
|
|
case 'HDD':
|
|
$formatted = 'Drive';
|
|
break;
|
|
}
|
|
|
|
$formatted .= ' ';
|
|
|
|
switch($sensor)
|
|
{
|
|
case 'temp':
|
|
$formatted .= 'Temperature';
|
|
break;
|
|
case 'freq':
|
|
$formatted .= 'Frequency';
|
|
break;
|
|
case 'memory':
|
|
$formatted .= 'Memory Usage';
|
|
break;
|
|
case 'power':
|
|
$formatted .= 'Power Consumption';
|
|
break;
|
|
default:
|
|
$formatted .= ucwords(str_replace('-', ' ', $sensor));
|
|
break;
|
|
}
|
|
|
|
return $formatted;
|
|
}
|
|
public static function system_hardware($return_as_string = true)
|
|
{
|
|
return self::system_information_parse(self::available_hardware_devices(), $return_as_string);
|
|
}
|
|
public static function system_software($return_as_string = true)
|
|
{
|
|
return self::system_information_parse(self::available_software_components(), $return_as_string);
|
|
}
|
|
public static function system_centralized_view($return_as_string = true)
|
|
{
|
|
$core_count = phodevi::read_property('cpu', 'physical-core-count');
|
|
$thread_count = phodevi::read_property('cpu', 'thread-count');
|
|
|
|
$sys = array(
|
|
'Processor' => phodevi::read_property('cpu', 'model-and-speed'),
|
|
array(
|
|
'Core Count' => $core_count,
|
|
'Thread Count' => !empty($core_count) && $core_count == $thread_count ? '' : $thread_count, // don't show thread count if it's same as core count
|
|
'Extensions' => phodevi_cpu::instruction_set_extensions(),
|
|
// 'Virtualization' => (phodevi_cpu::virtualization_technology() ? phodevi_cpu::virtualization_technology() : ''),
|
|
'Cache Size' => phodevi::read_property('cpu', 'cache-size-string'),
|
|
'Microcode'=> phodevi::read_property('cpu', 'microcode-version'),
|
|
'Core Family' => phodevi::read_property('cpu', 'core-family-name'),
|
|
'Scaling Driver'=> phodevi::read_property('cpu', 'scaling-governor'),
|
|
),
|
|
'Graphics' => phodevi::read_name('gpu'),
|
|
array(
|
|
'Frequency' => phodevi::read_property('gpu', 'frequency'),
|
|
'BAR1 / Visible vRAM' => phodevi::read_property('gpu', 'bar1-visible-vram'),
|
|
'OpenGL' => phodevi::read_property('system', 'opengl-driver'),
|
|
'Vulkan' => phodevi::read_property('system', 'vulkan-driver'),
|
|
'OpenCL' => phodevi::read_property('system', 'opencl-driver'),
|
|
'Display Driver' => phodevi::read_property('system', 'display-driver-string'),
|
|
'Monitor' => phodevi::read_name('monitor'),
|
|
'Screen' => phodevi::read_property('gpu', 'screen-resolution-string'),
|
|
),
|
|
'Motherboard' => phodevi::read_name('motherboard'),
|
|
array(
|
|
'BIOS Version' => phodevi::read_property('motherboard', 'bios-version'),
|
|
'Chipset' => phodevi::read_name('chipset'),
|
|
'Audio' => phodevi::read_name('audio'),
|
|
'Network' => phodevi::read_name('network'),
|
|
'Platform Profile'=> phodevi::read_property('system', 'platform-profile'),
|
|
),
|
|
'Memory' => phodevi::read_name('memory'),
|
|
array(),
|
|
'Disk' => phodevi::read_name('disk'),
|
|
array(
|
|
'File-System' => phodevi::read_property('system', 'filesystem'),
|
|
'Mount Options' => phodevi::read_property('disk', 'mount-options-string'),
|
|
//'Block Size' => phodevi::read_property('disk', 'block-size'),
|
|
'Disk Scheduler' => phodevi::read_property('disk', 'scheduler'),
|
|
'Disk Details' => phodevi::read_property('disk', 'extra-disk-details'),
|
|
),
|
|
'Operating System' => phodevi::read_property('system', 'operating-system'),
|
|
array(
|
|
'Kernel' => phodevi::read_property('system', 'kernel-string'),
|
|
'Desktop' => phodevi::read_property('system', 'desktop-environment'),
|
|
'Display Server' => phodevi::read_property('system', 'display-server'),
|
|
'Compiler' => phodevi::read_property('system', 'compiler'),
|
|
'System Layer' => phodevi::read_property('system', 'system-layer'),
|
|
'Security' => phodevi::read_property('system', 'security-features'),
|
|
)
|
|
);
|
|
|
|
if($return_as_string)
|
|
{
|
|
$sys_string = null;
|
|
$tabled = array();
|
|
foreach($sys as $key => &$in)
|
|
{
|
|
$space_in = 2;
|
|
if(is_array($in))
|
|
{
|
|
$tabled = array();
|
|
foreach($in as $key => $value)
|
|
{
|
|
if(!empty($value))
|
|
{
|
|
if(isset($value[64]) && strpos($value, ' + ') !== false)
|
|
{
|
|
$values = explode(' + ', $value);
|
|
$tabled[] = array(pts_client::cli_just_bold($key) . ':' . str_repeat(' ', (20 - strlen($key))), array_shift($values));
|
|
foreach($values as $value)
|
|
{
|
|
$tabled[] = array(pts_client::cli_just_bold(' '), '+ ' . $value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$tabled[] = array(pts_client::cli_just_bold($key) . ':' . str_repeat(' ', (20 - strlen($key))), $value);
|
|
//$sys_string .= ' ' . strtoupper($key) . ':' . $value . PHP_EOL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!empty($in) && ($x = strpos($in, ' (')))
|
|
{
|
|
$in = substr($in, 0, $x);
|
|
}
|
|
|
|
if(!empty($tabled))
|
|
{
|
|
$sys_string .= pts_user_io::display_text_table($tabled, ' ', 0, 17) . PHP_EOL;
|
|
}
|
|
|
|
if(isset($in[80]) && strpos($in, ' + ') !== false)
|
|
{
|
|
$values = explode(' + ', $in);
|
|
$sys_string .= PHP_EOL . pts_client::cli_just_bold(strtoupper($key)) . ': ' . str_repeat(' ', (24 - strlen($key))) . pts_client::cli_colored_text(array_shift($values), 'green', true);
|
|
foreach($values as $value)
|
|
{
|
|
$sys_string .= PHP_EOL . str_repeat(' ', 22) . pts_client::cli_colored_text('+ ' . $value, 'green', true);
|
|
}
|
|
$sys_string .= PHP_EOL;
|
|
}
|
|
else
|
|
{
|
|
$sys_string .= PHP_EOL . pts_client::cli_just_bold(strtoupper($key)) . ': ' . str_repeat(' ', (24 - strlen($key))) . pts_client::cli_colored_text($in, 'green', true) . PHP_EOL;
|
|
}
|
|
}
|
|
|
|
}
|
|
if(!empty($tabled))
|
|
{
|
|
$sys_string .= pts_user_io::display_text_table($tabled, ' ', 0, 17) . PHP_EOL;
|
|
}
|
|
return $sys_string;
|
|
}
|
|
|
|
return $sys;
|
|
}
|
|
public static function system_id_string()
|
|
{
|
|
$extra = null;
|
|
foreach(array('CC', 'CXX', 'CFLAGS', 'CPPFLAGS', 'CXXFLAGS', 'USE_WINE') as $env)
|
|
{
|
|
$val = getenv($env);
|
|
|
|
if(!empty($val))
|
|
{
|
|
$extra .= $env . '=' . $val . ';';
|
|
}
|
|
}
|
|
|
|
$components = array(phodevi::read_property('cpu', 'model'), phodevi::read_property('system', 'operating-system'), phodevi::read_property('system', 'compiler'), $extra);
|
|
return base64_encode(implode('__', $components));
|
|
}
|
|
public static function read_property($device, $read_property, $strip_string = true)
|
|
{
|
|
static $properties_table = array();
|
|
$value = false;
|
|
|
|
if(!isset($properties_table[$device]))
|
|
{
|
|
$properties_table[$device] = call_user_func(array('phodevi_' . $device, 'properties'));
|
|
}
|
|
|
|
if(!isset($properties_table[$device][$read_property]))
|
|
{
|
|
echo 'NOTICE: ' . $read_property . ' does not exist for ' . $device . '.' . PHP_EOL;
|
|
}
|
|
|
|
if(!($properties_table[$device][$read_property] instanceof phodevi_device_property))
|
|
{
|
|
return $properties_table[$device][$read_property];
|
|
}
|
|
|
|
$cache_code = $properties_table[$device][$read_property]->cache_code();
|
|
if($cache_code != phodevi::no_caching && phodevi::$allow_phodevi_caching && isset(self::$device_cache[$device][$read_property]))
|
|
{
|
|
$value = self::$device_cache[$device][$read_property];
|
|
}
|
|
else
|
|
{
|
|
$dev_function_r = pts_arrays::to_array($properties_table[$device][$read_property]->get_device_function());
|
|
$dev_function = $dev_function_r[0];
|
|
$function_pass = array();
|
|
|
|
for($i = 1; $i < count($dev_function_r); $i++)
|
|
{
|
|
array_push($function_pass, $dev_function_r[$i]);
|
|
}
|
|
if(method_exists('phodevi_' . $device, $dev_function))
|
|
{
|
|
$value = call_user_func_array(array('phodevi_' . $device, $dev_function), $function_pass);
|
|
if(!is_array($value) && $value != null)
|
|
{
|
|
if($strip_string)
|
|
{
|
|
$value = pts_strings::strip_string($value);
|
|
}
|
|
if(function_exists('preg_replace'))
|
|
{
|
|
$value = preg_replace('/[^(\x20-\x7F)]*/','', $value);
|
|
}
|
|
}
|
|
|
|
if($cache_code != phodevi::no_caching)
|
|
{
|
|
self::$device_cache[$device][$read_property] = $value;
|
|
|
|
if($cache_code == phodevi::smart_caching)
|
|
{
|
|
// TODO: For now just copy the smart cache to other var, but come up with better yet efficient way
|
|
self::$smart_cache[$device][$read_property] = $value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!empty(self::$sanitize_string) && !empty($value) && is_string($value))
|
|
{
|
|
$read_property_lower = strtolower($read_property);
|
|
$device_lower = strtolower($device);
|
|
foreach(self::$sanitize_string as $limit_or_index => $sanitize)
|
|
{
|
|
if(!is_numeric($limit_or_index) && $limit_or_index != $read_property && $limit_or_index != $device_lower)
|
|
{
|
|
// If index is set as property name, make sure reading the same property now or can skip it...
|
|
continue;
|
|
}
|
|
$value = str_ireplace($sanitize, '', $value);
|
|
}
|
|
$value = trim($value);
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
public static function read_all_properties()
|
|
{
|
|
$all_properties = array();
|
|
$components = array();
|
|
foreach(glob(__DIR__ . '/components/phodevi_*.php') as $file)
|
|
{
|
|
$components[] = substr(basename($file, '.php'), 8);
|
|
}
|
|
|
|
foreach($components as $device)
|
|
{
|
|
$properties = call_user_func(array('phodevi_' . $device, 'properties'));
|
|
$all_properties[$device] = array();
|
|
foreach($properties as $id => $property)
|
|
{
|
|
$dev_function_r = pts_arrays::to_array($property->get_device_function());
|
|
$dev_function = $dev_function_r[0];
|
|
$function_pass = array();
|
|
|
|
for($i = 1; $i < count($dev_function_r); $i++)
|
|
{
|
|
array_push($function_pass, $dev_function_r[$i]);
|
|
}
|
|
if(method_exists('phodevi_' . $device, $dev_function))
|
|
{
|
|
$value = call_user_func_array(array('phodevi_' . $device, $dev_function), $function_pass);
|
|
if(!is_array($value) && $value != null)
|
|
{
|
|
$value = pts_strings::strip_string($value);
|
|
if(function_exists('preg_replace'))
|
|
{
|
|
$value = preg_replace('/[^(\x20-\x7F)]*/','', $value);
|
|
}
|
|
}
|
|
$all_properties[$device][$id] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $all_properties;
|
|
}
|
|
public static function set_property($device, $set_property, $pass_args = array())
|
|
{
|
|
$return_value = false;
|
|
|
|
if(method_exists('phodevi_' . $device, 'set_property'))
|
|
{
|
|
$return_value = call_user_func(array('phodevi_' . $device, 'set_property'), $set_property, $pass_args);
|
|
}
|
|
|
|
return $return_value;
|
|
}
|
|
public static function create_vfs()
|
|
{
|
|
self::$vfs = new phodevi_vfs();
|
|
}
|
|
public static function set_sanitize_string($str)
|
|
{
|
|
self::$sanitize_string = array();
|
|
|
|
// Multiple strings to remove can be delimited by a comma
|
|
foreach(explode(',', $str) as $to_sanitize)
|
|
{
|
|
if(!empty($to_sanitize))
|
|
{
|
|
$to_sanitize = explode('=', $to_sanitize);
|
|
if(count($to_sanitize) == 2)
|
|
{
|
|
// Limiting sanitize string to a particular Phodevi property
|
|
self::$sanitize_string[strtolower($to_sanitize[0])] = $to_sanitize[1];
|
|
}
|
|
else
|
|
{
|
|
// Check all Phodevi properties
|
|
self::$sanitize_string[] = $to_sanitize[0];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public static function initial_setup()
|
|
{
|
|
phodevi::set_sanitize_string(pts_env::read('PHODEVI_SANITIZE'));
|
|
|
|
// Operating System Detection
|
|
$supported_operating_systems = pts_types::operating_systems();
|
|
$uname_s = strtolower(php_uname('s'));
|
|
|
|
foreach($supported_operating_systems as $os_check)
|
|
{
|
|
for($i = 0; $i < count($os_check); $i++)
|
|
{
|
|
if(strpos($uname_s, strtolower($os_check[$i])) !== false) // Check for OS
|
|
{
|
|
self::$operating_system = $os_check[0];
|
|
self::$operating_systems[strtolower($os_check[0])] = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(self::$operating_system != null)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(self::operating_system() == false)
|
|
{
|
|
self::$operating_system = 'Unknown';
|
|
}
|
|
|
|
self::load_sensors();
|
|
}
|
|
private static function detect_graphics()
|
|
{
|
|
if(self::$graphics_detected == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// OpenGL / graphics detection
|
|
$graphics_detection = array('NVIDIA', array('Mesa', 'SGI'), array('AMD'));
|
|
$opengl_driver = phodevi::read_property('system', 'opengl-vendor') . ' ' . phodevi::read_property('system', 'opengl-driver') . ' ' . phodevi::read_property('system', 'dri-display-driver');
|
|
$opengl_driver = trim(str_replace('Corporation', '', $opengl_driver)); // Prevents a possible false positive for ATI being in CorporATIon
|
|
|
|
foreach($graphics_detection as $gpu_check)
|
|
{
|
|
if(!is_array($gpu_check))
|
|
{
|
|
$gpu_check = array($gpu_check);
|
|
}
|
|
|
|
for($i = 0; $i < count($gpu_check); $i++)
|
|
{
|
|
if(stripos($opengl_driver, $gpu_check[$i]) !== false) // Check for GPU
|
|
{
|
|
self::$graphics[(strtolower($gpu_check[0]))] = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
self::$graphics_detected = true;
|
|
}
|
|
public static function set_device_cache($cache_array)
|
|
{
|
|
if(is_array($cache_array) && !empty($cache_array))
|
|
{
|
|
self::$smart_cache = array_merge(self::$smart_cache, $cache_array);
|
|
self::$device_cache = array_merge(self::$device_cache, $cache_array);
|
|
}
|
|
}
|
|
public static function clear_cache()
|
|
{
|
|
self::$smart_cache = array();
|
|
self::$device_cache = array();
|
|
}
|
|
public static function get_phodevi_cache_object($store_dir, $client_version = 0)
|
|
{
|
|
return new phodevi_cache(self::$smart_cache, $store_dir, $client_version);
|
|
}
|
|
protected static function system_information_parse($component_array, $return_as_string = true)
|
|
{
|
|
// Returns string of hardware information
|
|
$info = array();
|
|
|
|
foreach($component_array as $string => $id)
|
|
{
|
|
if(is_array($id) && count($id) == 2)
|
|
{
|
|
$value = self::read_property($id[0], $id[1]);
|
|
}
|
|
else
|
|
{
|
|
$value = self::read_name($id);
|
|
}
|
|
|
|
if($value != -1 && !empty($value))
|
|
{
|
|
$info[$string] = $value;
|
|
}
|
|
}
|
|
|
|
if($return_as_string)
|
|
{
|
|
$info_array = $info;
|
|
$info = null;
|
|
|
|
foreach($info_array as $type => $value)
|
|
{
|
|
if($info != null)
|
|
{
|
|
$info .= ', ';
|
|
}
|
|
|
|
$info .= $type . ': ' . $value;
|
|
}
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
public static function system_uptime()
|
|
{
|
|
// Returns the system's uptime in seconds
|
|
$uptime = 1;
|
|
|
|
if(phodevi::is_windows())
|
|
{
|
|
$uptime = trim(shell_exec('powershell -NoProfile "((get-date) - (gcim Win32_OperatingSystem).LastBootUpTime).TotalSeconds"'));
|
|
$uptime = is_numeric($uptime) && $uptime > 1 ? round($uptime) : 1;
|
|
}
|
|
else if(is_file('/proc/uptime'))
|
|
{
|
|
$uptime = pts_strings::first_in_string(pts_file_io::file_get_contents('/proc/uptime'));
|
|
}
|
|
else if(($uptime_cmd = pts_client::executable_in_path('uptime')) != false)
|
|
{
|
|
$uptime_counter = 0;
|
|
$uptime_output = shell_exec($uptime_cmd . ' 2>&1');
|
|
$uptime_output = substr($uptime_output, strpos($uptime_output, ' up') + 3);
|
|
$uptime_output = substr($uptime_output, 0, strpos($uptime_output, ' user'));
|
|
$uptime_output = substr($uptime_output, 0, strrpos($uptime_output, ',')) . ' ';
|
|
|
|
if(($day_end_pos = strpos($uptime_output, ' day')) !== false)
|
|
{
|
|
$day_output = substr($uptime_output, 0, $day_end_pos);
|
|
$day_output = substr($day_output, strrpos($day_output, ' ') + 1);
|
|
|
|
if(is_numeric($day_output))
|
|
{
|
|
$uptime_counter += $day_output * 86400;
|
|
}
|
|
}
|
|
|
|
if(($mins_end_pos = strpos($uptime_output, ' mins')) !== false)
|
|
{
|
|
$mins_output = substr($uptime_output, 0, $mins_end_pos);
|
|
$mins_output = substr($mins_output, strrpos($mins_output, ' ') + 1);
|
|
|
|
if(is_numeric($mins_output))
|
|
{
|
|
$uptime_counter += $mins_output * 60;
|
|
}
|
|
}
|
|
|
|
if(($time_split_pos = strpos($uptime_output, ':')) !== false)
|
|
{
|
|
$hours_output = substr($uptime_output, 0, $time_split_pos);
|
|
$hours_output = substr($hours_output, strrpos($hours_output, ' ') + 1);
|
|
$mins_output = substr($uptime_output, $time_split_pos + 1);
|
|
$mins_output = substr($mins_output, 0, strpos($mins_output, ' '));
|
|
|
|
if(is_numeric($hours_output))
|
|
{
|
|
$uptime_counter += $hours_output * 3600;
|
|
}
|
|
if(is_numeric($mins_output))
|
|
{
|
|
$uptime_counter += $mins_output * 60;
|
|
}
|
|
}
|
|
|
|
if(is_numeric($uptime_counter) && $uptime_counter > 0)
|
|
{
|
|
$uptime = $uptime_counter;
|
|
}
|
|
}
|
|
|
|
return intval($uptime);
|
|
}
|
|
public static function reboot()
|
|
{
|
|
$reboot_cmd = '';
|
|
|
|
if(phodevi::is_windows())
|
|
{
|
|
$reboot_cmd = 'shutdown /r';
|
|
}
|
|
else if(pts_client::executable_in_path('systemctl'))
|
|
{
|
|
$reboot_cmd = 'systemctl reboot';
|
|
}
|
|
else if(pts_client::executable_in_path('reboot'))
|
|
{
|
|
$reboot_cmd = 'reboot';
|
|
}
|
|
else if(pts_client::executable_in_path('shutdown'))
|
|
{
|
|
// macOS
|
|
$reboot_cmd = 'shutdown -r now';
|
|
}
|
|
|
|
if($reboot_cmd)
|
|
{
|
|
shell_exec($reboot_cmd);
|
|
// Buffer in case reboot isn't immediate
|
|
echo PHP_EOL . PHP_EOL . 'Waiting for reboot...' . PHP_EOL;
|
|
sleep(600);
|
|
}
|
|
}
|
|
public static function shutdown()
|
|
{
|
|
// some systems like systemctl poweroff, others just like poweroff, but not consistent one method for all systems in testing
|
|
if(pts_client::executable_in_path('systemctl') && rand(0, 1) == 1)
|
|
{
|
|
// Try systemd's poweroff method first
|
|
shell_exec('systemctl poweroff');
|
|
sleep(5);
|
|
}
|
|
if(pts_client::executable_in_path('poweroff'))
|
|
{
|
|
shell_exec('poweroff');
|
|
sleep(5);
|
|
}
|
|
if(phodevi::is_windows())
|
|
{
|
|
shell_exec('shutdown /s');
|
|
sleep(5);
|
|
}
|
|
}
|
|
public static function cpu_arch_compatible($check_against)
|
|
{
|
|
$compatible = true;
|
|
$this_arch = phodevi::read_property('system', 'kernel-architecture');
|
|
$check_against = pts_arrays::to_array($check_against);
|
|
|
|
if(isset($this_arch[2]) && substr($this_arch, -2) == '86')
|
|
{
|
|
$this_arch = 'x86';
|
|
}
|
|
if(!in_array($this_arch, $check_against))
|
|
{
|
|
$compatible = false;
|
|
}
|
|
if(phodevi::is_macos())
|
|
{
|
|
$compatible = true;
|
|
}
|
|
|
|
return $compatible;
|
|
}
|
|
public static function is_vendor_string($vendor)
|
|
{
|
|
return isset($vendor[2]) && pts_strings::string_only_contains($vendor, (pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_SPACE | pts_strings::CHAR_DASH)) && !pts_strings::has_in_istring($vendor, array('manufacturer', 'vendor', 'unknown', 'generic', 'warning')) && (!isset($vendor[7]) || strpos($vendor, ' ') !== false || pts_strings::times_occurred($vendor, pts_strings::CHAR_NUMERIC) == 0) && pts_strings::string_contains($vendor, pts_strings::CHAR_LETTER) && (isset($vendor[4]) || pts_strings::times_occurred($vendor, pts_strings::CHAR_LETTER) > 1) && substr($vendor, -1) != '-';
|
|
}
|
|
public static function is_product_string($product)
|
|
{
|
|
return phodevi::is_vendor_string($product) && !pts_strings::has_in_istring($product, array('VBOX', 'QEMU', 'Virtual', 'Family', '440BX', 'VMware', ' Gen', 'Core IGP'));
|
|
}
|
|
public static function opencl_support_detected()
|
|
{
|
|
$supported = true;
|
|
|
|
if(($clinfo = pts_client::executable_in_path('clinfo')))
|
|
{
|
|
$clinfo = shell_exec($clinfo);
|
|
if(strpos($clinfo, 'Number of platforms 0') !== false)
|
|
{
|
|
$supported = false;
|
|
}
|
|
}
|
|
|
|
return $supported;
|
|
}
|
|
public static function vulkan_support_detected()
|
|
{
|
|
static $supported = -1;
|
|
|
|
if($supported !== -1)
|
|
{
|
|
return $supported;
|
|
}
|
|
$supported = true;
|
|
|
|
if(($vulkaninfo = pts_client::executable_in_path('vulkaninfo 2>&1')))
|
|
{
|
|
$vulkaninfo = shell_exec($vulkaninfo);
|
|
if(strpos($vulkaninfo, 'Cannot create Vulkan instance') !== false)
|
|
{
|
|
$supported = false;
|
|
}
|
|
else if(strpos($vulkaninfo, 'failed with ERROR_INITIALIZATION_FAILED') !== false)
|
|
{
|
|
$supported = false;
|
|
}
|
|
}
|
|
|
|
return $supported;
|
|
}
|
|
public static function is_fake_device($str)
|
|
{
|
|
$string_check = array(
|
|
'Logical Volume',
|
|
'QEMU',
|
|
' KVM',
|
|
'KVM ',
|
|
'Eng Sample',
|
|
'Unknown',
|
|
' virt',
|
|
'virtual',
|
|
'svga',
|
|
' VM',
|
|
'Storage ',
|
|
'Aspeed',
|
|
'440BX',
|
|
'Cirrus',
|
|
);
|
|
|
|
foreach($string_check as $check)
|
|
{
|
|
if(stripos($str, $check) !== false)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
$without_multiplier = $str;
|
|
if(($x = strpos($without_multiplier, ' x ')) !== false)
|
|
{
|
|
$without_multiplier = substr($without_multiplier, $x + 3);
|
|
}
|
|
if(!preg_match('~[0-9]+~', $without_multiplier))
|
|
{
|
|
// No numbers at all in string so probably not a real device (e.g. some Virtual "Intel" CPU or similar components generic
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
public static function os_under_test($force_override = false, $force_value = null)
|
|
{
|
|
static $os_under_test = null;
|
|
if($force_override && !empty($force_value))
|
|
{
|
|
$os_under_test = $force_value;
|
|
}
|
|
else if($os_under_test == null)
|
|
{
|
|
$os_under_test = self::operating_system();
|
|
}
|
|
|
|
// The operating system under test
|
|
return $os_under_test;
|
|
}
|
|
public static function operating_system()
|
|
{
|
|
return self::$operating_system;
|
|
}
|
|
public static function is_linux()
|
|
{
|
|
return self::$operating_systems['linux'];
|
|
}
|
|
public static function is_minix()
|
|
{
|
|
return self::$operating_systems['minix'];
|
|
}
|
|
public static function is_solaris()
|
|
{
|
|
return self::$operating_systems['solaris'];
|
|
}
|
|
public static function is_bsd()
|
|
{
|
|
return self::$operating_systems['bsd'];
|
|
}
|
|
public static function is_macos()
|
|
{
|
|
return self::$operating_systems['macosx'];
|
|
}
|
|
public static function is_hurd()
|
|
{
|
|
return self::$operating_systems['hurd'];
|
|
}
|
|
public static function is_windows()
|
|
{
|
|
return self::$operating_systems['windows'];
|
|
}
|
|
public static function is_mesa_graphics()
|
|
{
|
|
self::detect_graphics();
|
|
return self::$graphics['mesa'];
|
|
}
|
|
public static function is_nvidia_graphics()
|
|
{
|
|
self::detect_graphics();
|
|
return self::$graphics['nvidia'];
|
|
}
|
|
public static function is_root()
|
|
{
|
|
return phodevi::read_property('system', 'username') == 'root' || is_writable('/root');
|
|
}
|
|
public static function is_display_server_active()
|
|
{
|
|
if(phodevi::read_property('system', 'system-layer') == 'Docker')
|
|
{
|
|
// hopefully temp workaround XXX TODO
|
|
return false;
|
|
}
|
|
|
|
return getenv('DISPLAY') != false || getenv('WAYLAND_DISPLAY') != false || phodevi::is_windows() || phodevi::is_macos();
|
|
}
|
|
}
|
|
|
|
phodevi::create_vfs();
|
|
|
|
if(PTS_IS_CLIENT)
|
|
{
|
|
phodevi::initial_setup();
|
|
}
|
|
|
|
?>
|