diff --git a/lib/OperatingSystems/FreeBSD.php b/lib/OperatingSystems/FreeBSD.php
new file mode 100644
index 00000000..ffa9be4a
--- /dev/null
+++ b/lib/OperatingSystems/FreeBSD.php
@@ -0,0 +1,258 @@
+
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\ServerInfo\OperatingSystems;
+
+/**
+ * Class FreeBSD
+ *
+ * @package OCA\ServerInfo\OperatingSystems
+ */
+class FreeBSD {
+
+ /**
+ * @return bool
+ */
+ public function supported(): bool {
+ return false;
+ }
+
+ /**
+ * Get memory will return a list key => value where all values are in bytes.
+ * [MemTotal => 0, MemFree => 0, MemAvailable => 0, SwapTotal => 0, SwapFree => 0].
+ *
+ * @return array
+ */
+ public function getMemory(): array {
+ $data = ['MemTotal' => -1, 'MemFree' => -1, 'MemAvailable' => -1, 'SwapTotal' => -1, 'SwapFree' => -1];
+
+ try {
+ $swapinfo = $this->executeCommand('/usr/sbin/swapinfo');
+ $line = preg_split("/[\s]+/", $swapinfo);
+
+ if (count($line) > 3) {
+ $data['SwapTotal'] = (int)$line[3];
+ $data['SwapFree'] = $data['SwapTotal'] - (int)$line[2];
+ }
+
+ $meminfo = $this->executeCommand('/sbin/sysctl -n hw.physmem hw.pagesize vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count');
+
+ $line = preg_split('/\s+/', trim($meminfo));
+ if (count($line) > 4) {
+ $data['MemTotal'] = (int)$line[0];
+ $data['MemAvailable'] = (int)$line[1] * ((int)$line[2] + (int)$line[3] + (int)$line[4]);
+ }
+ } catch (\RuntimeException $e) {
+ return $data;
+ }
+
+ return $data;
+ }
+
+ /**
+ * Get name of the processor
+ *
+ * @return string
+ */
+ public function getCPUName(): string {
+ $data = 'Unknown Processor';
+
+ try {
+ $data = $this->executeCommand('/sbin/sysctl -n hw.model');
+ } catch (\RuntimeException $e) {
+ return $data;
+ }
+ return $data;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTime() {
+ $time = '';
+
+ try {
+ $time = $this->executeCommand('date');
+ } catch (\RuntimeException $e) {
+ return $time;
+ }
+ return $time;
+ }
+
+ /**
+ * Get the total number of seconds the system has been up or -1 on failure.
+ *
+ * @return int
+ */
+ public function getUptime(): int {
+ $uptime = -1;
+
+ try {
+ $shell_boot = $this->executeCommand('/sbin/sysctl -n kern.boottime');
+ preg_match("/[\d]+/", $shell_boot, $boottime);
+ $time = $this->executeCommand('date +%s');
+ $uptime = (int)$time - (int)$boottime[0];
+ } catch (\RuntimeException $e) {
+ return $uptime;
+ }
+ return $uptime;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTimeServers() {
+ $servers = " ";
+
+ try {
+ $servers = $this->executeCommand('cat /etc/ntp.conf 2>/dev/null');
+ preg_match_all("/(?<=^pool ).\S*/m", $servers, $matches);
+ $allservers = implode(' ', $matches[0]);
+ } catch (\RuntimeException $e) {
+ return $servers;
+ }
+ return $allservers;
+ }
+
+ /**
+ * @return string
+ */
+ public function getNetworkInfo() {
+ $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("/(?<=^default).*\b\d/m", $netstat, $gw);
+ $result['gateway'] = $gw[0];
+ } catch (\RuntimeException $e) {
+ return $result;
+ }
+ return $result;
+ }
+
+ /**
+ * @return string
+ */
+ public function getNetworkInterfaces() {
+ $result = [];
+
+ $ifconfig = $this->executeCommand('/sbin/ifconfig -a');
+ preg_match_all("/^(?<=(?!\t)).*(?=:)/m", $ifconfig, $interfaces);
+
+ foreach ($interfaces[0] as $interface) {
+ $iface = [];
+ $iface['interface'] = $interface;
+ $intface = $this->executeCommand('/sbin/ifconfig ' . $iface['interface']);
+ preg_match_all("/(?<=inet ).\S*/m", $intface, $ipv4);
+ preg_match_all("/(?<=inet6 )((.*(?=%))|(.\S*))/m", $intface, $ipv6);
+ $iface['ipv4'] = implode(' ', $ipv4[0]);
+ $iface['ipv6'] = implode(' ', $ipv6[0]);
+
+ if ($iface['interface'] !== 'lo0') {
+ preg_match_all("/(?<=ether ).*/m", $intface, $mac);
+ preg_match("/(?<=status: ).*/m", $intface, $status);
+ preg_match("/(?<=\().*(?=b)/m", $intface, $speed);
+ preg_match("/(?<=\<).*(?=-)/m", $intface, $duplex);
+
+ $iface['mac'] = implode(' ', $mac[0]);
+ $iface['status'] = $status[0];
+ $iface['speed'] = $speed[0];
+
+ if ($iface['speed'] !== '') {
+ $iface['speed'] = $iface['speed'];
+ } else {
+ $iface['speed'] = 'unknown';
+ }
+
+ if ($duplex[0] !== '') {
+ $iface['duplex'] = 'Duplex: ' . $duplex[0];
+ } else {
+ $iface['duplex'] = '';
+ }
+ } else {
+ $iface['status'] = 'active';
+ $iface['speed'] = 'unknown';
+ $iface['duplex'] = '';
+ }
+ $result[] = $iface;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get diskInfo will return a list of disks. Used and Available in bytes.
+ *
+ * [
+ * [device => /dev/mapper/homestead--vg-root, fs => ext4, used => 6205468, available => 47321220, percent => 12%, mount => /]
+ * ]
+ *
+ * @return array
+ */
+ public function getDiskInfo(): array {
+ $data = [];
+
+ try {
+ $disks = $this->executeCommand('df -TP');
+ } 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;
+ }
+
+ $data[] = [
+ 'device' => $filesystem,
+ 'fs' => $matches['Type'][$i],
+ 'used' => (int)$matches['Used'][$i] * 1024,
+ 'available' => (int)$matches['Available'][$i] * 1024,
+ 'percent' => $matches['Capacity'][$i],
+ 'mount' => $matches['Mounted'][$i],
+ ];
+ }
+
+ return $data;
+ }
+
+ protected function executeCommand(string $command): string {
+ $output = @shell_exec(escapeshellcmd($command));
+ if ($output === null || $output === '') {
+ throw new \RuntimeException('No output for command: "' . $command . '"');
+ }
+ return $output;
+ }
+}
diff --git a/lib/Os.php b/lib/Os.php
index 7b2154fc..46c34132 100644
--- a/lib/Os.php
+++ b/lib/Os.php
@@ -22,6 +22,7 @@
use bantu\IniGetWrapper\IniGetWrapper;
use OCA\ServerInfo\OperatingSystems\DefaultOs;
+use OCA\ServerInfo\OperatingSystems\FreeBSD;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -66,7 +67,11 @@ public function __construct(IClientService $clientService,
$this->connection = $connection;
$this->phpIni = $phpIni;
$this->l = $l;
- $this->backend = new DefaultOs();
+ if (PHP_OS === 'FreeBSD') {
+ $this->backend = new FreeBSD();
+ } else {
+ $this->backend = new DefaultOs();
+ }
}
/**