From ba979bf1ecc0f2352f4c481aa7d8cff8e10ce282 Mon Sep 17 00:00:00 2001 From: Cthulhux Date: Tue, 31 Jan 2023 01:23:15 +0100 Subject: [PATCH 1/2] A desperate second attempt to fix #263, based upon the FreeBSD implementation and my own previous attempt... VERY lightly tested. --- lib/OperatingSystems/SunOS.php | 248 +++++++++++++++++++++++++++++++++ lib/Os.php | 7 +- 2 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 lib/OperatingSystems/SunOS.php diff --git a/lib/OperatingSystems/SunOS.php b/lib/OperatingSystems/SunOS.php new file mode 100644 index 00000000..f609ef0e --- /dev/null +++ b/lib/OperatingSystems/SunOS.php @@ -0,0 +1,248 @@ + + * + */ + +namespace OCA\ServerInfo\OperatingSystems; + +use OCA\ServerInfo\Resources\Disk; +use OCA\ServerInfo\Resources\Memory; +use OCA\ServerInfo\Resources\NetInterface; +use RuntimeException; + +class SunOS implements IOperatingSystem { + private const AF_INET = 2; + private const AF_INET6 = 26; + + public function supported(): bool { + return false; + } + + public function getMemory(): Memory { + $data = new Memory(); + + try { + $swapinfo = $this->executeCommand('/usr/sbin/swap -s'); + } catch (\RuntimeException $e) { + $swapinfo = ''; + } + + $matches = []; + $pattern = '/(?\d+)k used, (?\d+)k available$/'; + + $result = preg_match_all($pattern, $swapinfo, $matches); + if ($result === 1) { + $data->setSwapTotal((int)($matches['Avail'][0] / 1024)); + $data->setSwapFree(($data->getSwapTotal() - (int)($matches['Used'][0] / 1024))); + } + + unset($matches, $result); + + try { + $meminfo = $this->executeCommand('/usr/bin/vmstat -p'); + } catch (\RuntimeException $e) { + $meminfo = ''; + } + + $lines = explode("\n", $meminfo); + $relevantLine = explode(" ", trim($lines[2])); + $data->setMemTotal((int)($relevantLine[0] / 1024 / 1024)); + $data->setMemAvailable(((int)($relevantLine[1] / 1024 / 1024))); + + unset($relevantLine); + unset($lines); + + return $data; + } + + public function getCpuName(): string { + $data = 'Unknown Processor'; + + try { + $modelCmd = $this->executeCommand('/usr/sbin/psrinfo -pv'); + $modelAry = explode("\n", $coresCmd); + $model = trim($modelAry[count($modelAry)-1]); + $coresCmd = $this->executeCommand('/usr/sbin/psrinfo'); + $cores = count(explode("\n", $coresCmd)); + + if ($numCores === 1) { + $data = $model . ' (1 core)'; + } else { + $data = $model . ' (' . $cores . ' cores)'; + } + } catch (\RuntimeException $e) { + return $data; + } + return $data; + } + + public function getTime(): string { + try { + return $this->executeCommand('date'); + } catch (RuntimeException $e) { + return ''; + } + } + + public function getUptime(): int { + $uptime = -1; + + try { + $shell_boot = $this->executeCommand('/usr/bin/kstat -p unix:0:system_misc:boot_time'); + preg_match("/[\d]+/", $shell_boot, $boottime); + $time = $this->executeCommand('date +%s'); + $uptime = (int)$time - (int)$boottime[0]; + } catch (\RuntimeException $e) { + return $uptime; + } + return $uptime; + } + + public function getNetworkInfo(): array { + $result = []; + $result['hostname'] = \gethostname(); + + try { + $dns = $this->executeCommand('cat /etc/resolv.conf 2>/dev/null'); + preg_match_all("/(?<=^nameserver ).\S*/m", $dns, $matches); + $alldns = implode(' ', $matches[0]); + $result['dns'] = $alldns; + $netstat = $this->executeCommand('netstat -rn'); + preg_match_all("/(?<=^default)\s*[0-9a-fA-f\.:]+/m", $netstat, $gw); + if (count($gw[0]) > 0) { + $result['gateway'] = implode(", ", array_map("trim", $gw[0])); + } + } catch (RuntimeException $e) { + return $result; + } + return $result; + } + + public function getNetworkInterfaces(): array { + $data = []; + + foreach ($this->getNetInterfaces() as $interfaceName => $interface) { + $netInterface = new NetInterface($interfaceName, $interface['up']); + $data[] = $netInterface; + + foreach ($interface['unicast'] as $unicast) { + if ($unicast['family'] === self::AF_INET) { + $netInterface->addIPv4($unicast['address']); + } + if ($unicast['family'] === self::AF_INET6) { + $netInterface->addIPv6($unicast['address']); + } + } + + if ($netInterface->isLoopback()) { + continue; + } + + try { + $details = $this->executeCommand('/usr/sbin/ifconfig ' . $interfaceName); + } catch (RuntimeException $e) { + continue; + } + + preg_match("/(?<=ether ).*/m", $details, $mac); + if (isset($mac[0])) { + $netInterface->setMAC($mac[0]); + } + + preg_match("/\b[0-9].*?(?=base)/m", $details, $speed); + if (isset($speed[0])) { + if (substr($speed[0], -1) === 'G') { + $netInterface->setSpeed(rtrim($speed[0], 'G') . ' Gbps'); + } else { + $netInterface->setSpeed($speed[0] . ' Mbps'); + } + } + + preg_match("/(?<=\<).*(?=-)/m", $details, $duplex); + if (isset($duplex[0])) { + $netInterface->setDuplex($duplex[0]); + } + + unset($mac, $speed, $duplex); + } + + return $data; + } + + public function getDiskInfo(): array { + $data = []; + + try { + $disks = $this->executeCommand('/usr/bin/df -Pk'); + } catch (\RuntimeException $e) { + return $data; + } + + $matches = []; + $pattern = '/^(?[\w\/-]+)\s*(?\w+)\s*(?\d+)\s*(?\d+)\s*(?\d+)\s*(?\d+%)\s*(?[\w\/-]+)$/m'; + + $result = preg_match_all($pattern, $disks, $matches); + if ($result === 0 || $result === false) { + return $data; + } + + foreach ($matches['Filesystem'] as $i => $filesystem) { + if (in_array($matches['Type'][$i], ['tmpfs', 'devtmpfs'], false)) { + continue; + } + + $disk = new Disk(); + $disk->setDevice($filesystem); + $disk->setFs($matches['Type'][$i]); + $disk->setUsed((int)($matches['Used'][$i] / 1024)); + $disk->setAvailable((int)($matches['Available'][$i] / 1024)); + $disk->setPercent($matches['Capacity'][$i]); + $disk->setMount($matches['Mounted'][$i]); + + $data[] = $disk; + } + + return $data; + } + + public function getThermalZones(): array { + return []; + } + + protected function executeCommand(string $command): string { + $output = @shell_exec(escapeshellcmd($command)); + if ($output === null || $output === '' || $output === false) { + throw new RuntimeException('No output for command: "' . $command . '"'); + } + return $output; + } + + /** + * Wrapper for net_get_interfaces + * + * @throws RuntimeException + */ + protected function getNetInterfaces(): array { + $data = net_get_interfaces(); + if ($data === false) { + throw new RuntimeException('Unable to get network interfaces'); + } + return $data; + } +} diff --git a/lib/Os.php b/lib/Os.php index b3448f77..7589fd88 100644 --- a/lib/Os.php +++ b/lib/Os.php @@ -25,6 +25,7 @@ use OCA\ServerInfo\OperatingSystems\DefaultOs; use OCA\ServerInfo\OperatingSystems\FreeBSD; +use OCA\ServerInfo\OperatingSystems\SunOS; use OCA\ServerInfo\OperatingSystems\IOperatingSystem; use OCA\ServerInfo\Resources\Memory; @@ -36,9 +37,11 @@ class Os implements IOperatingSystem { */ public function __construct() { if (PHP_OS === 'FreeBSD') { - $this->backend = new FreeBSD(); + $this->backend = new FreeBSD(); + } else if (PHP_OS === 'SunOS') { + $this->backend = new SunOS(); } else { - $this->backend = new DefaultOs(); + $this->backend = new DefaultOs(); } } From 90f25a5d59fed97f15c5a73d6995e002c3768073 Mon Sep 17 00:00:00 2001 From: Cthulhux Date: Sun, 23 Apr 2023 21:05:25 +0200 Subject: [PATCH 2/2] Update SunOS.php fixed a few copy&paste problems Signed-off-by: Cthulhux --- lib/OperatingSystems/SunOS.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/OperatingSystems/SunOS.php b/lib/OperatingSystems/SunOS.php index f609ef0e..59b6a60a 100644 --- a/lib/OperatingSystems/SunOS.php +++ b/lib/OperatingSystems/SunOS.php @@ -48,8 +48,8 @@ public function getMemory(): Memory { $result = preg_match_all($pattern, $swapinfo, $matches); if ($result === 1) { - $data->setSwapTotal((int)($matches['Avail'][0] / 1024)); - $data->setSwapFree(($data->getSwapTotal() - (int)($matches['Used'][0] / 1024))); + $data->setSwapTotal((int)((int)$matches['Avail'][0] / 1024)); + $data->setSwapFree(($data->getSwapTotal() - (int)((int)$matches['Used'][0] / 1024))); } unset($matches, $result); @@ -62,8 +62,8 @@ public function getMemory(): Memory { $lines = explode("\n", $meminfo); $relevantLine = explode(" ", trim($lines[2])); - $data->setMemTotal((int)($relevantLine[0] / 1024 / 1024)); - $data->setMemAvailable(((int)($relevantLine[1] / 1024 / 1024))); + $data->setMemTotal((int)((int)$relevantLine[0] / 1024 / 1024)); + $data->setMemAvailable(((int)((int)$relevantLine[1] / 1024 / 1024))); unset($relevantLine); unset($lines); @@ -76,12 +76,12 @@ public function getCpuName(): string { try { $modelCmd = $this->executeCommand('/usr/sbin/psrinfo -pv'); - $modelAry = explode("\n", $coresCmd); + $modelAry = explode("\n", $modelCmd); $model = trim($modelAry[count($modelAry)-1]); $coresCmd = $this->executeCommand('/usr/sbin/psrinfo'); - $cores = count(explode("\n", $coresCmd)); + $numCores = count(explode("\n", $coresCmd)); - if ($numCores === 1) { + if ($numCores == 1) { $data = $model . ' (1 core)'; } else { $data = $model . ' (' . $cores . ' cores)'; @@ -210,8 +210,8 @@ public function getDiskInfo(): array { $disk = new Disk(); $disk->setDevice($filesystem); $disk->setFs($matches['Type'][$i]); - $disk->setUsed((int)($matches['Used'][$i] / 1024)); - $disk->setAvailable((int)($matches['Available'][$i] / 1024)); + $disk->setUsed((int)((int)$matches['Used'][$i] / 1024)); + $disk->setAvailable((int)((int)$matches['Available'][$i] / 1024)); $disk->setPercent($matches['Capacity'][$i]); $disk->setMount($matches['Mounted'][$i]);