From 3a0f8535c48021a3f8a204db2d8a62c29bb6b930 Mon Sep 17 00:00:00 2001 From: qindel Date: Wed, 29 May 2024 15:19:30 +0000 Subject: [PATCH] Refs #401 adds functions that needs oglivecli --- bin/composer.phar | 1748 ++++++++++++++++++++ bin/console | 18 + bin/oglivecli | 514 ++++++ lib/ogfunctions.sh | 66 + sources/interface/Apagar | 3 + sources/interface/CambiarAcceso | 54 + sources/interface/Configurar | 159 ++ sources/interface/ConsolaRemota | 3 + sources/interface/CrearImagen | 91 + sources/interface/CrearImagenBasica | 98 ++ sources/interface/CrearSoftIncremental | 98 ++ sources/interface/EjecutarScript | 44 + sources/interface/IniciarSesion | 13 + sources/interface/InventarioHardware | 6 + sources/interface/InventarioSoftware | 19 + sources/interface/Reiniciar | 3 + sources/interface/RestaurarImagen | 15 + sources/interface/RestaurarImagenBasica | 89 + sources/interface/RestaurarSoftIncremental | 82 + sources/interface/getConfiguration | 88 + sources/interface/getIpAddress | 2 + sources/interface/procesaCache | 2 + 22 files changed, 3215 insertions(+) create mode 100644 bin/composer.phar create mode 100755 bin/console create mode 100755 bin/oglivecli create mode 100644 lib/ogfunctions.sh create mode 100755 sources/interface/Apagar create mode 100755 sources/interface/CambiarAcceso create mode 100755 sources/interface/Configurar create mode 100755 sources/interface/ConsolaRemota create mode 100755 sources/interface/CrearImagen create mode 100755 sources/interface/CrearImagenBasica create mode 100755 sources/interface/CrearSoftIncremental create mode 100755 sources/interface/EjecutarScript create mode 100755 sources/interface/IniciarSesion create mode 100755 sources/interface/InventarioHardware create mode 100755 sources/interface/InventarioSoftware create mode 100755 sources/interface/Reiniciar create mode 100755 sources/interface/RestaurarImagen create mode 100755 sources/interface/RestaurarImagenBasica create mode 100755 sources/interface/RestaurarSoftIncremental create mode 100755 sources/interface/getConfiguration create mode 100755 sources/interface/getIpAddress create mode 100755 sources/interface/procesaCache diff --git a/bin/composer.phar b/bin/composer.phar new file mode 100644 index 0000000..a5efbed --- /dev/null +++ b/bin/composer.phar @@ -0,0 +1,1748 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +setupEnvironment(); +process(is_array($argv) ? $argv : array()); + +/** + * Initializes various values + * + * @throws RuntimeException If uopz extension prevents exit calls + */ +function setupEnvironment() +{ + ini_set('display_errors', 1); + + if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { + // uopz works at opcode level and disables exit calls + if (function_exists('uopz_allow_exit')) { + @uopz_allow_exit(true); + } else { + throw new RuntimeException('The uopz extension ignores exit calls and breaks this installer.'); + } + } + + $installer = 'ComposerInstaller'; + + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + if ($version = getenv('COMPOSERSETUP')) { + $installer = sprintf('Composer-Setup.exe/%s', $version); + } + } + + define('COMPOSER_INSTALLER', $installer); +} + +/** + * Processes the installer + */ +function process($argv) +{ + // Determine ANSI output from --ansi and --no-ansi flags + setUseAnsi($argv); + + $help = in_array('--help', $argv) || in_array('-h', $argv); + if ($help) { + displayHelp(); + exit(0); + } + + $check = in_array('--check', $argv); + $force = in_array('--force', $argv); + $quiet = in_array('--quiet', $argv); + $channel = 'stable'; + if (in_array('--snapshot', $argv)) { + $channel = 'snapshot'; + } elseif (in_array('--preview', $argv)) { + $channel = 'preview'; + } elseif (in_array('--1', $argv)) { + $channel = '1'; + } elseif (in_array('--2', $argv)) { + $channel = '2'; + } elseif (in_array('--2.2', $argv)) { + $channel = '2.2'; + } + $disableTls = in_array('--disable-tls', $argv); + $installDir = getOptValue('--install-dir', $argv, false); + $version = getOptValue('--version', $argv, false); + $filename = getOptValue('--filename', $argv, 'composer.phar'); + $cafile = getOptValue('--cafile', $argv, false); + + if (!checkParams($installDir, $version, $cafile)) { + exit(1); + } + + $ok = checkPlatform($warnings, $quiet, $disableTls, true); + + if ($check) { + // Only show warnings if we haven't output any errors + if ($ok) { + showWarnings($warnings); + showSecurityWarning($disableTls); + } + exit($ok ? 0 : 1); + } + + if ($ok || $force) { + if ($channel === '1' && !$quiet) { + out('Warning: You forced the install of Composer 1.x via --1, but Composer 2.x is the latest stable version. Updating to it via composer self-update --stable is recommended.', 'error'); + } + + $installer = new Installer($quiet, $disableTls, $cafile); + if ($installer->run($version, $installDir, $filename, $channel)) { + showWarnings($warnings); + showSecurityWarning($disableTls); + exit(0); + } + } + + exit(1); +} + +/** + * Displays the help + */ +function displayHelp() +{ + echo << $value) { + $next = $key + 1; + if (0 === strpos($value, $opt)) { + if ($optLength === strlen($value) && isset($argv[$next])) { + return trim($argv[$next]); + } else { + return trim(substr($value, $optLength + 1)); + } + } + } + + return $default; +} + +/** + * Checks that user-supplied params are valid + * + * @param mixed $installDir The required istallation directory + * @param mixed $version The required composer version to install + * @param mixed $cafile Certificate Authority file + * + * @return bool True if the supplied params are okay + */ +function checkParams($installDir, $version, $cafile) +{ + $result = true; + + if (false !== $installDir && !is_dir($installDir)) { + out("The defined install dir ({$installDir}) does not exist.", 'info'); + $result = false; + } + + if (false !== $version && 1 !== preg_match('/^\d+\.\d+\.\d+(\-(alpha|beta|RC)\d*)*$/', $version)) { + out("The defined install version ({$version}) does not match release pattern.", 'info'); + $result = false; + } + + if (false !== $cafile && (!file_exists($cafile) || !is_readable($cafile))) { + out("The defined Certificate Authority (CA) cert file ({$cafile}) does not exist or is not readable.", 'info'); + $result = false; + } + return $result; +} + +/** + * Checks the platform for possible issues running Composer + * + * Errors are written to the output, warnings are saved for later display. + * + * @param array $warnings Populated by method, to be shown later + * @param bool $quiet Quiet mode + * @param bool $disableTls Bypass tls + * @param bool $install If we are installing, rather than diagnosing + * + * @return bool True if there are no errors + */ +function checkPlatform(&$warnings, $quiet, $disableTls, $install) +{ + getPlatformIssues($errors, $warnings, $install); + + // Make openssl warning an error if tls has not been specifically disabled + if (isset($warnings['openssl']) && !$disableTls) { + $errors['openssl'] = $warnings['openssl']; + unset($warnings['openssl']); + } + + if (!empty($errors)) { + // Composer-Setup.exe uses "Some settings" to flag platform errors + out('Some settings on your machine make Composer unable to work properly.', 'error'); + out('Make sure that you fix the issues listed below and run this script again:', 'error'); + outputIssues($errors); + return false; + } + + if (empty($warnings) && !$quiet) { + out('All settings correct for using Composer', 'success'); + } + return true; +} + +/** + * Checks platform configuration for common incompatibility issues + * + * @param array $errors Populated by method + * @param array $warnings Populated by method + * @param bool $install If we are installing, rather than diagnosing + * + * @return bool If any errors or warnings have been found + */ +function getPlatformIssues(&$errors, &$warnings, $install) +{ + $errors = array(); + $warnings = array(); + + if ($iniPath = php_ini_loaded_file()) { + $iniMessage = PHP_EOL.'The php.ini used by your command-line PHP is: ' . $iniPath; + } else { + $iniMessage = PHP_EOL.'A php.ini file does not exist. You will have to create one.'; + } + $iniMessage .= PHP_EOL.'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.'; + + if (ini_get('detect_unicode')) { + $errors['unicode'] = array( + 'The detect_unicode setting must be disabled.', + 'Add the following to the end of your `php.ini`:', + ' detect_unicode = Off', + $iniMessage + ); + } + + if (extension_loaded('suhosin')) { + $suhosin = ini_get('suhosin.executor.include.whitelist'); + $suhosinBlacklist = ini_get('suhosin.executor.include.blacklist'); + if (false === stripos($suhosin, 'phar') && (!$suhosinBlacklist || false !== stripos($suhosinBlacklist, 'phar'))) { + $errors['suhosin'] = array( + 'The suhosin.executor.include.whitelist setting is incorrect.', + 'Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):', + ' suhosin.executor.include.whitelist = phar '.$suhosin, + $iniMessage + ); + } + } + + if (!function_exists('json_decode')) { + $errors['json'] = array( + 'The json extension is missing.', + 'Install it or recompile php without --disable-json' + ); + } + + if (!extension_loaded('Phar')) { + $errors['phar'] = array( + 'The phar extension is missing.', + 'Install it or recompile php without --disable-phar' + ); + } + + if (!extension_loaded('filter')) { + $errors['filter'] = array( + 'The filter extension is missing.', + 'Install it or recompile php without --disable-filter' + ); + } + + if (!extension_loaded('hash')) { + $errors['hash'] = array( + 'The hash extension is missing.', + 'Install it or recompile php without --disable-hash' + ); + } + + if (!extension_loaded('iconv') && !extension_loaded('mbstring')) { + $errors['iconv_mbstring'] = array( + 'The iconv OR mbstring extension is required and both are missing.', + 'Install either of them or recompile php without --disable-iconv' + ); + } + + if (!ini_get('allow_url_fopen')) { + $errors['allow_url_fopen'] = array( + 'The allow_url_fopen setting is incorrect.', + 'Add the following to the end of your `php.ini`:', + ' allow_url_fopen = On', + $iniMessage + ); + } + + if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) { + $ioncube = ioncube_loader_version(); + $errors['ioncube'] = array( + 'Your ionCube Loader extension ('.$ioncube.') is incompatible with Phar files.', + 'Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:', + ' zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so', + $iniMessage + ); + } + + if (version_compare(PHP_VERSION, '5.3.2', '<')) { + $errors['php'] = array( + 'Your PHP ('.PHP_VERSION.') is too old, you must upgrade to PHP 5.3.2 or higher.' + ); + } + + if (version_compare(PHP_VERSION, '5.3.4', '<')) { + $warnings['php'] = array( + 'Your PHP ('.PHP_VERSION.') is quite old, upgrading to PHP 5.3.4 or higher is recommended.', + 'Composer works with 5.3.2+ for most people, but there might be edge case issues.' + ); + } + + if (!extension_loaded('openssl')) { + $warnings['openssl'] = array( + 'The openssl extension is missing, which means that secure HTTPS transfers are impossible.', + 'If possible you should enable it or recompile php with --with-openssl' + ); + } + + if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) { + // Attempt to parse version number out, fallback to whole string value. + $opensslVersion = trim(strstr(OPENSSL_VERSION_TEXT, ' ')); + $opensslVersion = substr($opensslVersion, 0, strpos($opensslVersion, ' ')); + $opensslVersion = $opensslVersion ? $opensslVersion : OPENSSL_VERSION_TEXT; + + $warnings['openssl_version'] = array( + 'The OpenSSL library ('.$opensslVersion.') used by PHP does not support TLSv1.2 or TLSv1.1.', + 'If possible you should upgrade OpenSSL to version 1.0.1 or above.' + ); + } + + if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) { + $warnings['apc_cli'] = array( + 'The apc.enable_cli setting is incorrect.', + 'Add the following to the end of your `php.ini`:', + ' apc.enable_cli = Off', + $iniMessage + ); + } + + if (!$install && extension_loaded('xdebug')) { + $warnings['xdebug_loaded'] = array( + 'The xdebug extension is loaded, this can slow down Composer a little.', + 'Disabling it when using Composer is recommended.' + ); + + if (ini_get('xdebug.profiler_enabled')) { + $warnings['xdebug_profile'] = array( + 'The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.', + 'Add the following to the end of your `php.ini` to disable it:', + ' xdebug.profiler_enabled = 0', + $iniMessage + ); + } + } + + if (!extension_loaded('zlib')) { + $warnings['zlib'] = array( + 'The zlib extension is not loaded, this can slow down Composer a lot.', + 'If possible, install it or recompile php with --with-zlib', + $iniMessage + ); + } + + if (defined('PHP_WINDOWS_VERSION_BUILD') + && (version_compare(PHP_VERSION, '7.2.23', '<') + || (version_compare(PHP_VERSION, '7.3.0', '>=') + && version_compare(PHP_VERSION, '7.3.10', '<')))) { + $warnings['onedrive'] = array( + 'The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.', + 'Upgrade your PHP ('.PHP_VERSION.') to use this location with Composer.' + ); + } + + if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { + $warnings['uopz'] = array( + 'The uopz extension ignores exit calls and may not work with all Composer commands.', + 'Disabling it when using Composer is recommended.' + ); + } + + ob_start(); + phpinfo(INFO_GENERAL); + $phpinfo = ob_get_clean(); + if (preg_match('{Configure Command(?: *| *=> *)(.*?)(?:|$)}m', $phpinfo, $match)) { + $configure = $match[1]; + + if (false !== strpos($configure, '--enable-sigchild')) { + $warnings['sigchild'] = array( + 'PHP was compiled with --enable-sigchild which can cause issues on some platforms.', + 'Recompile it without this flag if possible, see also:', + ' https://bugs.php.net/bug.php?id=22999' + ); + } + + if (false !== strpos($configure, '--with-curlwrappers')) { + $warnings['curlwrappers'] = array( + 'PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.', + 'Recompile it without this flag if possible' + ); + } + } + + // Stringify the message arrays + foreach ($errors as $key => $value) { + $errors[$key] = PHP_EOL.implode(PHP_EOL, $value); + } + + foreach ($warnings as $key => $value) { + $warnings[$key] = PHP_EOL.implode(PHP_EOL, $value); + } + + return !empty($errors) || !empty($warnings); +} + + +/** + * Outputs an array of issues + * + * @param array $issues + */ +function outputIssues($issues) +{ + foreach ($issues as $issue) { + out($issue, 'info'); + } + out(''); +} + +/** + * Outputs any warnings found + * + * @param array $warnings + */ +function showWarnings($warnings) +{ + if (!empty($warnings)) { + out('Some settings on your machine may cause stability issues with Composer.', 'error'); + out('If you encounter issues, try to change the following:', 'error'); + outputIssues($warnings); + } +} + +/** + * Outputs an end of process warning if tls has been bypassed + * + * @param bool $disableTls Bypass tls + */ +function showSecurityWarning($disableTls) +{ + if ($disableTls) { + out('You have instructed the Installer not to enforce SSL/TLS security on remote HTTPS requests.', 'info'); + out('This will leave all downloads during installation vulnerable to Man-In-The-Middle (MITM) attacks', 'info'); + } +} + +/** + * colorize output + */ +function out($text, $color = null, $newLine = true) +{ + $styles = array( + 'success' => "\033[0;32m%s\033[0m", + 'error' => "\033[31;31m%s\033[0m", + 'info' => "\033[33;33m%s\033[0m" + ); + + $format = '%s'; + + if (isset($styles[$color]) && USE_ANSI) { + $format = $styles[$color]; + } + + if ($newLine) { + $format .= PHP_EOL; + } + + printf($format, $text); +} + +/** + * Returns the system-dependent Composer home location, which may not exist + * + * @return string + */ +function getHomeDir() +{ + $home = getenv('COMPOSER_HOME'); + if ($home) { + return $home; + } + + $userDir = getUserDir(); + + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + return $userDir.'/Composer'; + } + + $dirs = array(); + + if (useXdg()) { + // XDG Base Directory Specifications + $xdgConfig = getenv('XDG_CONFIG_HOME'); + if (!$xdgConfig) { + $xdgConfig = $userDir . '/.config'; + } + + $dirs[] = $xdgConfig . '/composer'; + } + + $dirs[] = $userDir . '/.composer'; + + // select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer + foreach ($dirs as $dir) { + if (is_dir($dir)) { + return $dir; + } + } + + // if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise) + return $dirs[0]; +} + +/** + * Returns the location of the user directory from the environment + * @throws RuntimeException If the environment value does not exists + * + * @return string + */ +function getUserDir() +{ + $userEnv = defined('PHP_WINDOWS_VERSION_MAJOR') ? 'APPDATA' : 'HOME'; + $userDir = getenv($userEnv); + + if (!$userDir) { + throw new RuntimeException('The '.$userEnv.' or COMPOSER_HOME environment variable must be set for composer to run correctly'); + } + + return rtrim(strtr($userDir, '\\', '/'), '/'); +} + +/** + * @return bool + */ +function useXdg() +{ + foreach (array_keys($_SERVER) as $key) { + if (strpos($key, 'XDG_') === 0) { + return true; + } + } + + if (is_dir('/etc/xdg')) { + return true; + } + + return false; +} + +function validateCaFile($contents) +{ + // assume the CA is valid if php is vulnerable to + // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html + if ( + PHP_VERSION_ID <= 50327 + || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50422) + || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50506) + ) { + return !empty($contents); + } + + return (bool) openssl_x509_parse($contents); +} + +class Installer +{ + private $quiet; + private $disableTls; + private $cafile; + private $displayPath; + private $target; + private $tmpFile; + private $tmpCafile; + private $baseUrl; + private $algo; + private $errHandler; + private $httpClient; + private $pubKeys = array(); + private $installs = array(); + + /** + * Constructor - must not do anything that throws an exception + * + * @param bool $quiet Quiet mode + * @param bool $disableTls Bypass tls + * @param mixed $cafile Path to CA bundle, or false + */ + public function __construct($quiet, $disableTls, $caFile) + { + if (($this->quiet = $quiet)) { + ob_start(); + } + $this->disableTls = $disableTls; + $this->cafile = $caFile; + $this->errHandler = new ErrorHandler(); + } + + /** + * Runs the installer + * + * @param mixed $version Specific version to install, or false + * @param mixed $installDir Specific installation directory, or false + * @param string $filename Specific filename to save to, or composer.phar + * @param string $channel Specific version channel to use + * @throws Exception If anything other than a RuntimeException is caught + * + * @return bool If the installation succeeded + */ + public function run($version, $installDir, $filename, $channel) + { + try { + $this->initTargets($installDir, $filename); + $this->initTls(); + $this->httpClient = new HttpClient($this->disableTls, $this->cafile); + $result = $this->install($version, $channel); + + // in case --1 or --2 is passed, we leave the default channel for next self-update to stable + if (1 === preg_match('{^\d+$}D', $channel)) { + $channel = 'stable'; + } + + if ($result && $channel !== 'stable' && !$version && defined('PHP_BINARY')) { + $null = (defined('PHP_WINDOWS_VERSION_MAJOR') ? 'NUL' : '/dev/null'); + @exec(escapeshellarg(PHP_BINARY) .' '.escapeshellarg($this->target).' self-update --'.$channel.' --set-channel-only -q > '.$null.' 2> '.$null, $output); + } + } catch (Exception $e) { + $result = false; + } + + // Always clean up + $this->cleanUp($result); + + if (isset($e)) { + // Rethrow anything that is not a RuntimeException + if (!$e instanceof RuntimeException) { + throw $e; + } + out($e->getMessage(), 'error'); + } + return $result; + } + + /** + * Initialization methods to set the required filenames and composer url + * + * @param mixed $installDir Specific installation directory, or false + * @param string $filename Specific filename to save to, or composer.phar + * @throws RuntimeException If the installation directory is not writable + */ + protected function initTargets($installDir, $filename) + { + $this->displayPath = ($installDir ? rtrim($installDir, '/').'/' : '').$filename; + $installDir = $installDir ? realpath($installDir) : getcwd(); + + if (!is_writeable($installDir)) { + throw new RuntimeException('The installation directory "'.$installDir.'" is not writable'); + } + + $this->target = $installDir.DIRECTORY_SEPARATOR.$filename; + $this->tmpFile = $installDir.DIRECTORY_SEPARATOR.basename($this->target, '.phar').'-temp.phar'; + + $uriScheme = $this->disableTls ? 'http' : 'https'; + $this->baseUrl = $uriScheme.'://getcomposer.org'; + } + + /** + * A wrapper around methods to check tls and write public keys + * @throws RuntimeException If SHA384 is not supported + */ + protected function initTls() + { + if ($this->disableTls) { + return; + } + + if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) { + throw new RuntimeException('SHA384 is not supported by your openssl extension'); + } + + $this->algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384'; + $home = $this->getComposerHome(); + + $this->pubKeys = array( + 'dev' => $this->installKey(self::getPKDev(), $home, 'keys.dev.pub'), + 'tags' => $this->installKey(self::getPKTags(), $home, 'keys.tags.pub') + ); + + if (empty($this->cafile) && !HttpClient::getSystemCaRootBundlePath()) { + $this->cafile = $this->tmpCafile = $this->installKey(HttpClient::getPackagedCaFile(), $home, 'cacert-temp.pem'); + } + } + + /** + * Returns the Composer home directory, creating it if required + * @throws RuntimeException If the directory cannot be created + * + * @return string + */ + protected function getComposerHome() + { + $home = getHomeDir(); + + if (!is_dir($home)) { + $this->errHandler->start(); + + if (!mkdir($home, 0777, true)) { + throw new RuntimeException(sprintf( + 'Unable to create Composer home directory "%s": %s', + $home, + $this->errHandler->message + )); + } + $this->installs[] = $home; + $this->errHandler->stop(); + } + return $home; + } + + /** + * Writes public key data to disc + * + * @param string $data The public key(s) in pem format + * @param string $path The directory to write to + * @param string $filename The name of the file + * @throws RuntimeException If the file cannot be written + * + * @return string The path to the saved data + */ + protected function installKey($data, $path, $filename) + { + $this->errHandler->start(); + + $target = $path.DIRECTORY_SEPARATOR.$filename; + $installed = file_exists($target); + $write = file_put_contents($target, $data, LOCK_EX); + @chmod($target, 0644); + + $this->errHandler->stop(); + + if (!$write) { + throw new RuntimeException(sprintf('Unable to write %s to: %s', $filename, $path)); + } + + if (!$installed) { + $this->installs[] = $target; + } + + return $target; + } + + /** + * The main install function + * + * @param mixed $version Specific version to install, or false + * @param string $channel Version channel to use + * + * @return bool If the installation succeeded + */ + protected function install($version, $channel) + { + $retries = 3; + $result = false; + $infoMsg = 'Downloading...'; + $infoType = 'info'; + + while ($retries--) { + if (!$this->quiet) { + out($infoMsg, $infoType); + $infoMsg = 'Retrying...'; + $infoType = 'error'; + } + + if (!$this->getVersion($channel, $version, $url, $error)) { + out($error, 'error'); + continue; + } + + if (!$this->downloadToTmp($url, $signature, $error)) { + out($error, 'error'); + continue; + } + + if (!$this->verifyAndSave($version, $signature, $error)) { + out($error, 'error'); + continue; + } + + $result = true; + break; + } + + if (!$this->quiet) { + if ($result) { + out(PHP_EOL."Composer (version {$version}) successfully installed to: {$this->target}", 'success'); + out("Use it: php {$this->displayPath}", 'info'); + out(''); + } else { + out('The download failed repeatedly, aborting.', 'error'); + } + } + return $result; + } + + /** + * Sets the version url, downloading version data if required + * + * @param string $channel Version channel to use + * @param false|string $version Version to install, or set by method + * @param null|string $url The versioned url, set by method + * @param null|string $error Set by method on failure + * + * @return bool If the operation succeeded + */ + protected function getVersion($channel, &$version, &$url, &$error) + { + $error = ''; + + if ($version) { + if (empty($url)) { + $url = $this->baseUrl."/download/{$version}/composer.phar"; + } + return true; + } + + $this->errHandler->start(); + + if ($this->downloadVersionData($data, $error)) { + $this->parseVersionData($data, $channel, $version, $url); + } + + $this->errHandler->stop(); + return empty($error); + } + + /** + * Downloads and json-decodes version data + * + * @param null|array $data Downloaded version data, set by method + * @param null|string $error Set by method on failure + * + * @return bool If the operation succeeded + */ + protected function downloadVersionData(&$data, &$error) + { + $url = $this->baseUrl.'/versions'; + $errFmt = 'The "%s" file could not be %s: %s'; + + if (!$json = $this->httpClient->get($url)) { + $error = sprintf($errFmt, $url, 'downloaded', $this->errHandler->message); + return false; + } + + if (!$data = json_decode($json, true)) { + $error = sprintf($errFmt, $url, 'json-decoded', $this->getJsonError()); + return false; + } + return true; + } + + /** + * A wrapper around the methods needed to download and save the phar + * + * @param string $url The versioned download url + * @param null|string $signature Set by method on successful download + * @param null|string $error Set by method on failure + * + * @return bool If the operation succeeded + */ + protected function downloadToTmp($url, &$signature, &$error) + { + $error = ''; + $errFmt = 'The "%s" file could not be downloaded: %s'; + $sigUrl = $url.'.sig'; + $this->errHandler->start(); + + if (!$fh = fopen($this->tmpFile, 'w')) { + $error = sprintf('Could not create file "%s": %s', $this->tmpFile, $this->errHandler->message); + + } elseif (!$this->getSignature($sigUrl, $signature)) { + $error = sprintf($errFmt, $sigUrl, $this->errHandler->message); + + } elseif (!fwrite($fh, $this->httpClient->get($url))) { + $error = sprintf($errFmt, $url, $this->errHandler->message); + } + + if (is_resource($fh)) { + fclose($fh); + } + $this->errHandler->stop(); + return empty($error); + } + + /** + * Verifies the downloaded file and saves it to the target location + * + * @param string $version The composer version downloaded + * @param string $signature The digital signature to check + * @param null|string $error Set by method on failure + * + * @return bool If the operation succeeded + */ + protected function verifyAndSave($version, $signature, &$error) + { + $error = ''; + + if (!$this->validatePhar($this->tmpFile, $pharError)) { + $error = 'The download is corrupt: '.$pharError; + + } elseif (!$this->verifySignature($version, $signature, $this->tmpFile)) { + $error = 'Signature mismatch, could not verify the phar file integrity'; + + } else { + $this->errHandler->start(); + + if (!rename($this->tmpFile, $this->target)) { + $error = sprintf('Could not write to file "%s": %s', $this->target, $this->errHandler->message); + } + chmod($this->target, 0755); + $this->errHandler->stop(); + } + + return empty($error); + } + + /** + * Parses an array of version data to match the required channel + * + * @param array $data Downloaded version data + * @param mixed $channel Version channel to use + * @param false|string $version Set by method + * @param mixed $url The versioned url, set by method + */ + protected function parseVersionData(array $data, $channel, &$version, &$url) + { + foreach ($data[$channel] as $candidate) { + if ($candidate['min-php'] <= PHP_VERSION_ID) { + $version = $candidate['version']; + $url = $this->baseUrl.$candidate['path']; + break; + } + } + + if (!$version) { + $error = sprintf( + 'None of the %d %s version(s) of Composer matches your PHP version (%s / ID: %d)', + count($data[$channel]), + $channel, + PHP_VERSION, + PHP_VERSION_ID + ); + throw new RuntimeException($error); + } + } + + /** + * Downloads the digital signature of required phar file + * + * @param string $url The signature url + * @param null|string $signature Set by method on success + * + * @return bool If the download succeeded + */ + protected function getSignature($url, &$signature) + { + if (!$result = $this->disableTls) { + $signature = $this->httpClient->get($url); + + if ($signature) { + $signature = json_decode($signature, true); + $signature = base64_decode($signature['sha384']); + $result = true; + } + } + + return $result; + } + + /** + * Verifies the signature of the downloaded phar + * + * @param string $version The composer versione + * @param string $signature The downloaded digital signature + * @param string $file The temp phar file + * + * @return bool If the operation succeeded + */ + protected function verifySignature($version, $signature, $file) + { + if (!$result = $this->disableTls) { + $path = preg_match('{^[0-9a-f]{40}$}', $version) ? $this->pubKeys['dev'] : $this->pubKeys['tags']; + $pubkeyid = openssl_pkey_get_public('file://'.$path); + + $result = 1 === openssl_verify( + file_get_contents($file), + $signature, + $pubkeyid, + $this->algo + ); + + // PHP 8 automatically frees the key instance and deprecates the function + if (PHP_VERSION_ID < 80000) { + openssl_free_key($pubkeyid); + } + } + + return $result; + } + + /** + * Validates the downloaded phar file + * + * @param string $pharFile The temp phar file + * @param null|string $error Set by method on failure + * + * @return bool If the operation succeeded + */ + protected function validatePhar($pharFile, &$error) + { + if (ini_get('phar.readonly')) { + return true; + } + + try { + // Test the phar validity + $phar = new Phar($pharFile); + // Free the variable to unlock the file + unset($phar); + $result = true; + + } catch (Exception $e) { + if (!$e instanceof UnexpectedValueException && !$e instanceof PharException) { + throw $e; + } + $error = $e->getMessage(); + $result = false; + } + return $result; + } + + /** + * Returns a string representation of the last json error + * + * @return string The error string or code + */ + protected function getJsonError() + { + if (function_exists('json_last_error_msg')) { + return json_last_error_msg(); + } else { + return 'json_last_error = '.json_last_error(); + } + } + + /** + * Cleans up resources at the end of the installation + * + * @param bool $result If the installation succeeded + */ + protected function cleanUp($result) + { + if (!$result) { + // Output buffered errors + if ($this->quiet) { + $this->outputErrors(); + } + // Clean up stuff we created + $this->uninstall(); + } elseif ($this->tmpCafile) { + @unlink($this->tmpCafile); + } + } + + /** + * Outputs unique errors when in quiet mode + * + */ + protected function outputErrors() + { + $errors = explode(PHP_EOL, ob_get_clean()); + $shown = array(); + + foreach ($errors as $error) { + if ($error && !in_array($error, $shown)) { + out($error, 'error'); + $shown[] = $error; + } + } + } + + /** + * Uninstalls newly-created files and directories on failure + * + */ + protected function uninstall() + { + foreach (array_reverse($this->installs) as $target) { + if (is_file($target)) { + @unlink($target); + } elseif (is_dir($target)) { + @rmdir($target); + } + } + + if ($this->tmpFile !== null && file_exists($this->tmpFile)) { + @unlink($this->tmpFile); + } + } + + public static function getPKDev() + { + return <<message) { + $this->message .= PHP_EOL; + } + $this->message .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg); + } + + /** + * Starts error-handling if not already active + * + * Any message is cleared + */ + public function start() + { + if (!$this->active) { + set_error_handler(array($this, 'handleError')); + $this->active = true; + } + $this->message = ''; + } + + /** + * Stops error-handling if active + * + * Any message is preserved until the next call to start() + */ + public function stop() + { + if ($this->active) { + restore_error_handler(); + $this->active = false; + } + } +} + +class NoProxyPattern +{ + private $composerInNoProxy = false; + private $rulePorts = array(); + + public function __construct($pattern) + { + $rules = preg_split('{[\s,]+}', $pattern, null, PREG_SPLIT_NO_EMPTY); + + if ($matches = preg_grep('{getcomposer\.org(?::\d+)?}i', $rules)) { + $this->composerInNoProxy = true; + + foreach ($matches as $match) { + if (strpos($match, ':') !== false) { + list(, $port) = explode(':', $match); + $this->rulePorts[] = (int) $port; + } + } + } + } + + /** + * Returns true if NO_PROXY contains getcomposer.org + * + * @param string $url http(s)://getcomposer.org + * + * @return bool + */ + public function test($url) + { + if (!$this->composerInNoProxy) { + return false; + } + + if (empty($this->rulePorts)) { + return true; + } + + if (strpos($url, 'http://') === 0) { + $port = 80; + } else { + $port = 443; + } + + return in_array($port, $this->rulePorts); + } +} + +class HttpClient { + + /** @var null|string */ + private static $caPath; + + private $options = array('http' => array()); + private $disableTls = false; + + public function __construct($disableTls = false, $cafile = false) + { + $this->disableTls = $disableTls; + if ($this->disableTls === false) { + if (!empty($cafile) && !is_dir($cafile)) { + if (!is_readable($cafile) || !validateCaFile(file_get_contents($cafile))) { + throw new RuntimeException('The configured cafile (' .$cafile. ') was not valid or could not be read.'); + } + } + $options = $this->getTlsStreamContextDefaults($cafile); + $this->options = array_replace_recursive($this->options, $options); + } + } + + public function get($url) + { + $context = $this->getStreamContext($url); + $result = file_get_contents($url, false, $context); + + if ($result && extension_loaded('zlib')) { + $decode = false; + foreach ($http_response_header as $header) { + if (preg_match('{^content-encoding: *gzip *$}i', $header)) { + $decode = true; + continue; + } elseif (preg_match('{^HTTP/}i', $header)) { + $decode = false; + } + } + + if ($decode) { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + $result = zlib_decode($result); + } else { + // work around issue with gzuncompress & co that do not work with all gzip checksums + $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); + } + + if (!$result) { + throw new RuntimeException('Failed to decode zlib stream'); + } + } + } + + return $result; + } + + protected function getStreamContext($url) + { + if ($this->disableTls === false) { + if (PHP_VERSION_ID < 50600) { + $this->options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST); + } + } + // Keeping the above mostly isolated from the code copied from Composer. + return $this->getMergedStreamContext($url); + } + + protected function getTlsStreamContextDefaults($cafile) + { + $ciphers = implode(':', array( + 'ECDHE-RSA-AES128-GCM-SHA256', + 'ECDHE-ECDSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES256-GCM-SHA384', + 'ECDHE-ECDSA-AES256-GCM-SHA384', + 'DHE-RSA-AES128-GCM-SHA256', + 'DHE-DSS-AES128-GCM-SHA256', + 'kEDH+AESGCM', + 'ECDHE-RSA-AES128-SHA256', + 'ECDHE-ECDSA-AES128-SHA256', + 'ECDHE-RSA-AES128-SHA', + 'ECDHE-ECDSA-AES128-SHA', + 'ECDHE-RSA-AES256-SHA384', + 'ECDHE-ECDSA-AES256-SHA384', + 'ECDHE-RSA-AES256-SHA', + 'ECDHE-ECDSA-AES256-SHA', + 'DHE-RSA-AES128-SHA256', + 'DHE-RSA-AES128-SHA', + 'DHE-DSS-AES128-SHA256', + 'DHE-RSA-AES256-SHA256', + 'DHE-DSS-AES256-SHA', + 'DHE-RSA-AES256-SHA', + 'AES128-GCM-SHA256', + 'AES256-GCM-SHA384', + 'AES128-SHA256', + 'AES256-SHA256', + 'AES128-SHA', + 'AES256-SHA', + 'AES', + 'CAMELLIA', + 'DES-CBC3-SHA', + '!aNULL', + '!eNULL', + '!EXPORT', + '!DES', + '!RC4', + '!MD5', + '!PSK', + '!aECDH', + '!EDH-DSS-DES-CBC3-SHA', + '!EDH-RSA-DES-CBC3-SHA', + '!KRB5-DES-CBC3-SHA', + )); + + /** + * CN_match and SNI_server_name are only known once a URL is passed. + * They will be set in the getOptionsForUrl() method which receives a URL. + * + * cafile or capath can be overridden by passing in those options to constructor. + */ + $options = array( + 'ssl' => array( + 'ciphers' => $ciphers, + 'verify_peer' => true, + 'verify_depth' => 7, + 'SNI_enabled' => true, + ) + ); + + /** + * Attempt to find a local cafile or throw an exception. + * The user may go download one if this occurs. + */ + if (!$cafile) { + $cafile = self::getSystemCaRootBundlePath(); + } + if (is_dir($cafile)) { + $options['ssl']['capath'] = $cafile; + } elseif ($cafile) { + $options['ssl']['cafile'] = $cafile; + } else { + throw new RuntimeException('A valid cafile could not be located automatically.'); + } + + /** + * Disable TLS compression to prevent CRIME attacks where supported. + */ + if (version_compare(PHP_VERSION, '5.4.13') >= 0) { + $options['ssl']['disable_compression'] = true; + } + + return $options; + } + + /** + * function copied from Composer\Util\StreamContextFactory::initOptions + * + * Any changes should be applied there as well, or backported here. + * + * @param string $url URL the context is to be used for + * @return resource Default context + * @throws \RuntimeException if https proxy required and OpenSSL uninstalled + */ + protected function getMergedStreamContext($url) + { + $options = $this->options; + + // Handle HTTP_PROXY/http_proxy on CLI only for security reasons + if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) { + $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); + } + + // Prefer CGI_HTTP_PROXY if available + if (!empty($_SERVER['CGI_HTTP_PROXY'])) { + $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']); + } + + // Override with HTTPS proxy if present and URL is https + if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) { + $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']); + } + + // Remove proxy if URL matches no_proxy directive + if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) { + $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']); + if ($pattern->test($url)) { + unset($proxy); + } + } + + if (!empty($proxy)) { + $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : ''; + $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; + + if (isset($proxy['port'])) { + $proxyURL .= ":" . $proxy['port']; + } elseif (strpos($proxyURL, 'http://') === 0) { + $proxyURL .= ":80"; + } elseif (strpos($proxyURL, 'https://') === 0) { + $proxyURL .= ":443"; + } + + // check for a secure proxy + if (strpos($proxyURL, 'https://') === 0) { + if (!extension_loaded('openssl')) { + throw new RuntimeException('You must enable the openssl extension to use a secure proxy.'); + } + if (strpos($url, 'https://') === 0) { + throw new RuntimeException('PHP does not support https requests through a secure proxy.'); + } + } + + // http(s):// is not supported in proxy + $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); + + $options['http'] = array( + 'proxy' => $proxyURL, + ); + + // add request_fulluri for http requests + if ('http' === parse_url($url, PHP_URL_SCHEME)) { + $options['http']['request_fulluri'] = true; + } + + // handle proxy auth if present + if (isset($proxy['user'])) { + $auth = rawurldecode($proxy['user']); + if (isset($proxy['pass'])) { + $auth .= ':' . rawurldecode($proxy['pass']); + } + $auth = base64_encode($auth); + + $options['http']['header'] = "Proxy-Authorization: Basic {$auth}\r\n"; + } + } + + if (isset($options['http']['header'])) { + $options['http']['header'] .= "Connection: close\r\n"; + } else { + $options['http']['header'] = "Connection: close\r\n"; + } + if (extension_loaded('zlib')) { + $options['http']['header'] .= "Accept-Encoding: gzip\r\n"; + } + $options['http']['header'] .= "User-Agent: ".COMPOSER_INSTALLER."\r\n"; + $options['http']['protocol_version'] = 1.1; + $options['http']['timeout'] = 600; + + return stream_context_create($options); + } + + /** + * This method was adapted from Sslurp. + * https://github.com/EvanDotPro/Sslurp + * + * (c) Evan Coury + * + * For the full copyright and license information, please see below: + * + * Copyright (c) 2013, Evan Coury + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + public static function getSystemCaRootBundlePath() + { + if (self::$caPath !== null) { + return self::$caPath; + } + + // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. + // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. + $envCertFile = getenv('SSL_CERT_FILE'); + if ($envCertFile && is_readable($envCertFile) && validateCaFile(file_get_contents($envCertFile))) { + return self::$caPath = $envCertFile; + } + + // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that. + // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. + $envCertDir = getenv('SSL_CERT_DIR'); + if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) { + return self::$caPath = $envCertDir; + } + + $configured = ini_get('openssl.cafile'); + if ($configured && strlen($configured) > 0 && is_readable($configured) && validateCaFile(file_get_contents($configured))) { + return self::$caPath = $configured; + } + + $configured = ini_get('openssl.capath'); + if ($configured && is_dir($configured) && is_readable($configured)) { + return self::$caPath = $configured; + } + + $caBundlePaths = array( + '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) + '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) + '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) + '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) + '/usr/ssl/certs/ca-bundle.crt', // Cygwin + '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package + '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) + '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? + '/etc/ssl/cert.pem', // OpenBSD + '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x + '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package + '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package + '/opt/homebrew/etc/openssl@3/cert.pem', // macOS silicon homebrew, openssl@3 package + '/opt/homebrew/etc/openssl@1.1/cert.pem', // macOS silicon homebrew, openssl@1.1 package + ); + + foreach ($caBundlePaths as $caBundle) { + if (@is_readable($caBundle) && validateCaFile(file_get_contents($caBundle))) { + return self::$caPath = $caBundle; + } + } + + foreach ($caBundlePaths as $caBundle) { + $caBundle = dirname($caBundle); + if (is_dir($caBundle) && glob($caBundle.'/*')) { + return self::$caPath = $caBundle; + } + } + + return self::$caPath = false; + } + + public static function getPackagedCaFile() + { + return <</dev/null) OGLIVEISO=$(basename $6 2>/dev/null) + # JSON data for installed ogLive. + DATA=$(cat << EOT | jq . +{"distribution":"$OGLIVEDIST","kernel":"$OGLIVEKRNL","architecture":"$OGLIVEARCH","revision":"$OGLIVEREV","directory":"$OGLIVEDIR","iso":"$OGLIVEISO"} +EOT + ) + # Check JSON file consistency. + if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == '["default","oglive"]' ]; then + # Check if ogLive is defined into JSON file. + n=$(jq ".oglive | length" $INFOFILE) + for ((i=0; i/dev/null || raiseError access "Installation directory." + [ ! -f $OGCLIENT/ogvmlinuz ] && raiseError notfound "\"ogclient\"." + # Add entry to JSON file using ogclient kernel version. + OGLIVEKRNL=$(file -bkr $OGCLIENT/ogvmlinuz | awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);sub(/-.*/,"",v);print v}}') + OGLIVEDIR=$DEFOGLIVE-$OGLIVEKRNL + [ -r $OLDINFOFILE ] && OGLIVEISO="$(head -1 $OLDINFOFILE)" + addToJson "$(echo $OGLIVEISO|cut -f2 -d-)" "$OGLIVEKRNL" "i386" "${OGLIVEISO##*-}" "$OGLIVEDIR" "$OGLIVEISO.iso" + # Rename directory, link to default and clean old files. + mv -v $OGCLIENT $OGLIVEDIR + ln -vfs $OGLIVEDIR $DEFOGLIVE + rm -f $OGCLIENT + ln -vfs $DEFOGLIVE $OGCLIENT + mv -v $OGCLIENT.old $OGLIVEDIR.old 2>/dev/null + rm -fv {ogvmlinuz,oginitrd.img}{,.sum} $OLDINFOFILE + popd >/dev/null + # Delete old config file. + rm -f $OLDINFOFILE +} + +# Show script configuration parameters. +function config() { + local DATA + DATA=$(cat << EOT +[ + { "param": "config-file", "description": "Configuration file", "value": "$INFOFILE" }, + { "param": "download-url", "description": "ogLive download URL", "value": "$DOWNLOADURL" }, + { "param": "download-dir", "description": "ogLive download directory", "value": "$DOWNLOADDIR" }, + { "param": "install-dir", "description": "ogLive installation directory", "value": "$TFTPDIR" }, + { "param": "default-name", "description": "Default ogLive name", "value": "$DEFOGLIVE" }, + { "param": "min-release", "description": "Minimum compatibility release", "value": "r$MINREL" } +] +EOT + ) + case $# in + 0) # Show all parameters. + echo "$DATA" | jq -r '.[] | .description + " (" + .param + ")," + .value' | column -ts, + ;; + 1) # Show specified parameter. + DATA=$(echo "$DATA" | jq -r ".[] | select(.param==\"$1\").value") + [ "$DATA" ] || raiseError notfound "\"$1\"." + echo "$DATA" + ;; + *) # Usage error. + raiseError usage + ;; + esac +} + +# Check consistency, showing configuration problems. +function check() { + local ERR=0 AUX INST DEF + [ $# -ne 0 ] && raiseError usage + # Check for old system that needs conversion. + if [ -z "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ]; then + echo "This server uses old ogclient, please run \"$PROG convert\" to update." + let ERR++ + [ ! -f $INFOFILE ] && return $ERR + fi + # Check for other problems. + [ ! -f $INFOFILE ] && echo "Configuration file does not exists: $INFOFILE" && let ERR++ + [ -f $INFOFILE -a "$(jq -c keys $INFOFILE 2>/dev/null)" != "[\"default\",\"oglive\"]" ] && echo "Format error in configuration file: $INFOFILE" && let ERR++ + [ ! -e $TFTPDIR ] && echo "TFTP directory does not exist: $TFTPDIR." && let ERR++ + # Check for installed ogLive clients. + INST=( $(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) ) + [[ ${#INST[@]} -eq 0 ]] && echo "No ogLive clients are installed." && let ERR++ + DEF=( $(jq -r .oglive[].directory $INFOFILE 2>/dev/null | sort) ) + # Compare installed and defined ogLive clients. + AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]})) + [ -n "$AUX" ] && echo "Some ogLive are installed but not defined: ${AUX//$'\n'/, }" && let ERR++ + AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]})) + [ -n "$AUX" ] && echo "Some ogLive are defined but not installed: ${AUX//$'\n'/, }" && let ERR++ + # Compare downloaded and defined ISO images. + INST=( $(find $DOWNLOADDIR/ -type f -name "$DEFOGLIVE-*.iso" -printf "%f\n" | sort) ) + DEF=( $(jq -r .oglive[].iso $INFOFILE 2>/dev/null | sort) ) + AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]})) + [ -n "$AUX" ] && echo "Some ISOs are downloaded but not defined: ${AUX//$'\n'/, }" && let ERR++ + AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]})) + [ -n "$AUX" ] && echo "Some ISOs are defined but not downloaded: ${AUX//$'\n'/, }" && let ERR++ + # Check for new ISO files downloaded after installation. + AUX=$(jq -r '.oglive[] as $og | $og.iso + ":" + $og.directory' $INFOFILE 2>/dev/null | \ + while IFS=":" read -r DEF INST; do + [ $DOWNLOADDIR/$DEF -nt $TFTPDIR/$INST ] && echo "$DEF" + done) + [ -n "$AUX" ] && echo "Some ISOs are downloaded after installation: ${AUX//$'\n'/, }" && let ERR++ + AUX=$(jq -r '.oglive[] as $og | if ($og.revision[1:9] | tonumber) < '$MINREL' then $og.directory else "" end' $INFOFILE 2>/dev/null) + [ -n "$AUX" ] && echo "Some installed ogLive aren't fully compatible: ${AUX//$'\n'/, }" && let ERR++ + DEF=$(jq -r ".oglive[$(getdefault)].directory" $INFOFILE 2>/dev/null) + INST=$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | cut -f4 -d\') + [ "$DEF" != "$INST" ] && echo "Default ogLive is not linked to right directory: $DEF <> $INST" && let ERR++ + # Print result. + [ $ERR -eq 0 ] && echo "OK!" || echo "Problems detected: $ERR" + return $ERR +} + +# List installed ogLive clients. +function list() { + [ $# -ne 0 ] && raiseError usage + [ ! -r $INFOFILE ] && raiseError access "Configuration file." + # List all defined indexes, directories and check if missing. + jq -r .oglive[].directory $INFOFILE | nl -v 0 | \ + awk '{system("echo -n "$0"; test -d '$TFTPDIR'/"$2" || echo -n \" (missing)\"; echo")}' | column -t +} + +# Show information about an installed ogLive client. +function show() { + local INDEX + [ $# -ne 1 ] && raiseError usage + [ ! -r $INFOFILE ] && raiseError access "Configuration file." + # Show JSON entries. + case "$1" in + default) # Default index. + INDEX="[$(jq -r .default $INFOFILE)]" ;; + all) # All intries. + ;; + [0-9]*) # Index. + INDEX="[$1]" ;; + *) # Directory. + INDEX="[$(search "$1" 2>/dev/null)]" || raiseError notfound "Directory \"$1\"." + ;; + esac + jq ".oglive$INDEX" $INFOFILE || raiseError notfound "Index \"$1\"." +} + +# Show index or directory corresponding to searching parameter. +function search() { + [ $# -ne 1 ] && raiseError usage + [ ! -r $INFOFILE ] && raiseError access "Configuration file." + # Show corresponding index or directory. + list | awk -v d="$1" '{if ($2==d) print $1; if ($1==d) print $2}' | grep . || raiseError notfound "Index/Directory \"$1\"." +} + +# Show a menu to select and download an ogLive ISO image from the OpenGnsys website. +function download() { + local OGLIVE NISOS i HTTPCODE ISOREL + + # Verificar si el directorio de descarga existe y tiene permisos de escritura. + [ ! -d "$DOWNLOADDIR" ] && raiseError notfound "Directorio de descarga." + [ ! -w "$DOWNLOADDIR" ] && raiseError access "Directorio de descarga." + + # Si no se proporciona ningún parámetro, mostrar el menú de descargas. + if [ -z "$1" ]; then + downloadMenu + else + local selected_name="$1" + + # Obtener la lista de archivos disponibles. + OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") ) + + # Buscar el archivo seleccionado por nombre. + OGLIVEFILE="" + for iso in "${OGLIVE[@]}"; do + if [[ "$iso" == *"$selected_name"* ]]; then + OGLIVEFILE=$iso + break + fi + done + + [ -n "$OGLIVEFILE" ] || raiseError download "Nombre \"$selected_name\" inválido." + + # Obtener el tamaño de descarga. + local SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 "$DOWNLOADURL/$OGLIVEFILE" | awk -F: '/Content-Length:/ {print $2}') + [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE" + + # Descargar ogLive. + local TARGETFILE="$DOWNLOADDIR/$OGLIVEFILE" + trap "rm -f $TARGETFILE" 1 2 3 6 9 15 + curl -k --retry 5 --retry-delay 5 "$DOWNLOADURL/$OGLIVEFILE" -o "$TARGETFILE" || raiseError download "\"$OGLIVEFILE\"." + install "$OGLIVEFILE" + fi +} +# Muestra un menú para seleccionar y descargar un archivo ogLive ISO del sitio web de OpenGnsys. +function downloadMenu() { + + local OGLIVE NISOS i HTTPCODE ISOREL + OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") ) + NISOS=${#OGLIVE[@]} + echo "Descargas disponibles (+ = instalado, * = compatibilidad completa):" + for i in $(seq 1 $NISOS); do + [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="(+) ${OGLIVE[i-1]}" + ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*} + [ $ISOREL -ge $MINREL ] && OGLIVE[i-1]="(*) ${OGLIVE[i-1]}" + echo "$i) ${OGLIVE[i-1]}" + done +} + +# Show a menu to select and download an ogLive ISO image from the OpenGnsys website. +function download_old() { + local OGLIVE NISOS i HTTPCODE TARGETFILE + local ISOREL + [ $# -gt 1 ] && raiseError usage + [ ! -d $DOWNLOADDIR ] && raiseError notfound "Download directory." + [ ! -w $DOWNLOADDIR ] && raiseError access "Download directory." + # Check parameter. + if [ -n "$1" ]; then + # ogLive to download. + OGLIVEFILE="$1" + else + # Show download menu. + OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") ) + NISOS=${#OGLIVE[@]} + echo "Available downloads (+ = installed, * = full compatibility):" + for i in $(seq 1 $NISOS); do + [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="(+) ${OGLIVE[i-1]}" + ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*} + [ $ISOREL -ge $MINREL ] && OGLIVE[i-1]="(*) ${OGLIVE[i-1]}" + done + select opt in "${OGLIVE[@]}"; do + [ -n "$opt" ] && OGLIVEFILE=${opt##* } && break + done + fi + # Get download size. + SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE | awk -F: '/Content-Length:/ {print $2}') + [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE" + # Download ogLive. + TARGETFILE=$DOWNLOADDIR/$OGLIVEFILE + trap "rm -f $TARGETFILE" 1 2 3 6 9 15 + curl -k --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE -o $TARGETFILE || raiseError download "\"$OGLIVEFILE\"." +} + +# Install an ogLive client from a previously downloaded ISO image. +function install() { + local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS OGCLIENT=ogclient + local COMPRESS SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT + [ $# -ne 1 ] && raiseError usage + OGLIVEFILE=$(realpath $DOWNLOADDIR/$1) + # Only 1 file in pathname expansion. + [ $(echo $OGLIVEFILE | wc -w) -gt 1 ] && raiseError usage + [ ! -f $OGLIVEFILE ] && raiseError notfound "Downloaded file: \"$1\"." + [ ! -r $OGLIVEFILE ] && raiseError access "Downloaded file: \"$1\"." + [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration directory." + [ ! -w $TFTPDIR ] && raiseError access "Installation directory." + [ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && raiseError access "File is not an ogLive ISO image." + # Working directory: + # 64-bit: ogLive-KernelVersion-rCodeRelease + # 32-bit: ogLive-KernelVersion-i386-rCodeRelease + OGLIVEDIST="$(echo $OGLIVEFILE|cut -f2 -d-)" + OGLIVEREV="${OGLIVEFILE##*-}"; OGLIVEREV="${OGLIVEREV%%.*}" + OGLIVEKRNL="$(echo $OGLIVEFILE|cut -f3- -d-)"; OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEREV.*}" + OGLIVEARCH="$(echo $OGLIVEFILE|awk -F- '{print $(NF-1)}')" + case "$OGLIVEARCH" in + i386|amd64) # Get architecture. + OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEARCH}" ;; + *) # 32-bit by default. + OGLIVEARCH="i386" ;; + esac + OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-${OGLIVEKRNL%%-*}-$OGLIVEARCH-$OGLIVEREV" + OGLIVEDIR="${OGLIVEDIR/amd64-/}" + # Get current or default Samba key. + OGINITRD=$OGLIVEDIR/oginitrd.img + [ ! -r $OGINITRD ] && OGINITRD=$TFTPDIR/$DEFOGLIVE/oginitrd.img + if [ -r $OGINITRD ]; then + COMPRESS=$(file -b "$OGINITRD" | awk '{print tolower($1);}') + SAMBAPASS=$($COMPRESS -dc $OGINITRD | \ + cpio -i --to-stdout scripts/ogfunctions 2>&1 | \ + sed -n '/^[ ].*OPTIONS=/s/.*pass=\(\w*\).*/\1/p') + fi + # Make ogLive backup. + rm -fr ${OGLIVEDIR}.old + mv -fv $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null + # Mount ogLive ISO image, update its files and unmount it. + TMPDIR=/tmp/${OGLIVEFILE%.iso} + mkdir -p $OGLIVEDIR $TMPDIR + trap "umount $TMPDIR; rm -fr $TMPDIR" 1 2 3 6 9 15 + mount -o loop,ro $OGLIVEFILE $TMPDIR + cp -va $TMPDIR/ogclient/* $OGLIVEDIR || raiseError access "Cannot copy files to ogLive directory." + umount $TMPDIR + # Link to default directory if it's the first ogLive. + if [ ! -f $INFOFILE ]; then + rm -f $TFTPDIR/$DEFOGLIVE $TFTPDIR/$OGCLIENT + ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE + ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT + fi + # Recover or ask for a new Samba access key. + if [ -n "$SAMBAPASS" ]; then + echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" + else + $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" + fi + # Set permissions. + find -L $OGLIVEDIR -type d -exec chmod 755 {} \; + find -L $OGLIVEDIR -type f -exec chmod 644 {} \; + chown -R :opengnsys $OGLIVEDIR + # Mount SquashFS and check Rsync version. + OGSQFS=$OGLIVEDIR/ogclient.sqfs + mount -o loop,ro $OGSQFS $TMPDIR + # If Rsync server version > client version, link to compiled file. + RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}') + RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}') + if [ -z "$RSYNCSERV" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then + [ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync + else + # Else, rename compiled file using Rsync protocol number. + [ -e $OPENGNSYS/client/bin/rsync ] && mv -f $OPENGNSYS/client/bin/rsync $OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}') + fi + # Unmount SquashFS. + umount $TMPDIR + rmdir $TMPDIR + # Update JSON file. + addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEARCH" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE" +} + +# Uninstall an ogLive client. +function uninstall() { + local ISO DIR INDEX DEFINDEX + [ $# -ne 1 ] && raiseError usage + [ ! -r $INFOFILE ] && raiseError access "Configuration file." + [ ! -w $TFTPDIR ] && raiseError access "Installation directory." + # Get index and directory for the entry. + case "$1" in + */*) # Error (access to other directory). + raiseError access "Cannot access outside installation directory." + ;; + *.iso) # ISO file. + ISO="$1" + # Working directory (ogLive-Distribution-KernelVersion-CodeRevision). + DIR="$(echo $ISO|cut -f1,3 -d-)-${ISO##*-}"; DIR=${DIR%.*} + INDEX=$(search $DIR 2>/dev/null) + ;; + [0-9]*) # Index. + INDEX=$1; DIR=$(search $INDEX 2>/dev/null) + ;; + *) # Directory. + DIR="$1"; INDEX=$(search $DIR 2>/dev/null) + ;; + esac + DEFINDEX=$(getdefault) + [[ $INDEX = $DEFINDEX ]] && raiseError access "Cannot uninstall default ogLive." + # Remove files and delete index entry. + rm -vfr ${ISO:+$DOWNLOADDIR/$ISO} ${DIR:+$TFTPDIR/$DIR} ### Remove $TFTPDIR/$DIR.old ? + if [ -n "$INDEX" ]; then + jq "del(.oglive[$INDEX])" $INFOFILE | sponge $INFOFILE + # Decrement default index if needed (removed < default). + [[ $INDEX < $DEFINDEX ]] && jq ".default=$((DEFINDEX-1))" $INFOFILE | sponge $INFOFILE + fi +} + +# Get default ogLive index. +function getdefault() { + [ $# -ne 0 ] && raiseError usage + [ ! -r $INFOFILE ] && raiseError access "Configuration file." + # Read default parameter. + jq -r .default $INFOFILE || raiseError notfound "Undefined default index." +} + +# Set default ogLive index. +function setdefault() { + local INDEX OGLIVEDIR + [ $# -ne 1 ] && raiseError usage + [ ! -w $INFOFILE ] && raiseError access "Configuration file." + INDEX=$1 + # Check if index entry exists. + jq ".oglive[$INDEX]" $INFOFILE || raiseError notfound "Index \"$INDEX\"." + # Get ogLive directory. + OGLIVEDIR=$(jq -r ".oglive[$INDEX].directory" $INFOFILE) || raiseError notfound "Directory for index \"$INDEX\"." + # Update default parameter. + jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE + # Link to default directory. + rm -f $TFTPDIR/$DEFOGLIVE + ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE +} + +# Rebuild a lost configuration file. +function rebuild() { + local i INST NF DEF + [ $# -ne 0 ] && raiseError usage + [ -f $INFOFILE ] && raiseError access "Configuration file exists." + INST=$(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) + for i in $INST; do + NF=$(echo $i | awk -F- '{print NF-1}') + case $NF in + 1) addToJson "" "$(echo $i|cut -f2 -d-)" "i386" "" "$i" "" ;; + 2) eval addToJson $(echo $i | awk -F- '{printf "\"\" %s amd64 %s %s \"\"",$2,$3,$0}') ;; + 3) eval addToJson $(echo $i | awk -F- '{if ($3=="i386") printf "\"\" %s %s %s %s \"\"",$2,$3,$4,$0; else printf "%s %s i386 %s %s \"\"",$2,$3,$4,$0}') ;; + 4) eval addToJson $(echo $i | awk -F- '{printf "%s %s %s %s %s \"\"",$2,$3,$4,$5,$0}') ;; + esac + # Check for is default oglive. + [ -n "$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | awk '$3~/'$i'/ {print}')" ] && DEF="$i" + done + # Set default ogLive. + [ -n "$DEF" ] && setdefault $(search $DEF) +} + +# Assign an ISO file to a JSON entry. +function assign() { +local ISOFILE DIR + [ $# -ne 2 ] && raiseError usage + [ ! -w $INFOFILE ] && raiseError access "Configuration file." + # Check if ISO file and index directory exist. + ISOFILE=$DOWNLOADFILE/$1 + [ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"." + DIR=$(search $2 2>/dev/null) + [ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"." + # Assign ISO file to JSON entry. + jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE +} + + +# Main progrram. + +# Access control. +[ -r $OPENGNSYS/www/controlacceso.php ] && ACCESS="web" +[ "$USER" = "root" ] && ACCESS="root" +[ -z "$ACCESS" ] && raiseError access "Need to be root." +# Check dependencies. +which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"." +# Commands control. +shopt -s extglob +case "$ACCESS" in + root) CMDS='+(help|version|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|rebuild|assign)' ;; + web) CMDS='+(list|show|search|get-default)' ;; +esac +case "$1" in + $CMDS) COMMAND="${1/-/}"; shift; $COMMAND "$@" ;; + *) raiseError usage ;; +esac + +exit $? + + diff --git a/lib/ogfunctions.sh b/lib/ogfunctions.sh new file mode 100644 index 0000000..062a9a4 --- /dev/null +++ b/lib/ogfunctions.sh @@ -0,0 +1,66 @@ +#!/bin/bash +#/** +#@file ogfunctions.sh +#@brief Generic functions for OpenGnsys Server and OpenGnsys Repository. +#@version 1.1.1 - Initial version +#@author Ramón M. Gómez, ETSII Universidad de Sevilla +#@date 2017-10-08 +#*/ + + +# Showing an error message. +function raiseError() { + case "$1" in + usage) + echo "$PROG: Usage error: Type \"$PROG help\"" >&2 + exit 1 ;; + notfound) + echo "$PROG: Resource not found: $2" >&2 + exit 2 ;; + access) + echo "$PROG: Access error: $2" >&2 + exit 3 ;; + download) + echo "$PROG: Download error: $2" >&2 + exit 4 ;; + *) + echo "$PROG: Unknown error" >&2 + exit 1 ;; + esac +} + +# Showing help message. +function help() { + [ -n "$1" ] && DESCRIPTION="$1" || DESCRIPTION=$(grep "^#@brief" "$0" | cut -f2- -d" ") + shift + if [ -n "$1" ]; then + USAGE="$1" + shift + else + USAGE=$(grep "^#@usage" "$0" | cut -f2- -d" ") + [ -n "$USAGE" ] && PARAMS=$(awk '$1=="#@param" {sub($1,""); print "\t",$0}' "$0") + fi + # Showing help. + echo "$PROG: ${DESCRIPTION:-"no description"}" + echo "Usage: ${USAGE:-"no usage info"}" + [ -n "$PARAMS" ] && echo -e "$PARAMS" + if [ -n "$*" ]; then + echo "Examples:" + while (( "$#" )); do + echo -e "\t$1" + shift + done + fi + exit 0 +} + +# Metafunction to check if JSON result exists. +JQ=$(which jq 2>/dev/null) || raiseError notfound "Need to install \"jq\"." +function jq() { + local OUTPUT + OUTPUT=$($JQ "$@") || return $? + [[ "$OUTPUT" = "null" ]] && return 1 + echo "$OUTPUT" +} + + diff --git a/sources/interface/Apagar b/sources/interface/Apagar new file mode 100755 index 0000000..ae1e5ba --- /dev/null +++ b/sources/interface/Apagar @@ -0,0 +1,3 @@ +#!/bin/bash +poweroff +exit 0 diff --git a/sources/interface/CambiarAcceso b/sources/interface/CambiarAcceso new file mode 100755 index 0000000..f698d19 --- /dev/null +++ b/sources/interface/CambiarAcceso @@ -0,0 +1,54 @@ +#!/bin/bash + +#______________________________________ +# +# PARAMETROS RECIBIDOS DESDE EL CLIENTE +# $1 modo (admin, user) +#______________________________________ + +# Error si llamada no se realliza desde OpenGnsys Client. +PROG=$(basename $0) +CALLER=$(ogGetCaller) +if ! $(ogCheckStringInGroup "$CALLER" "CrearImagen ConsolaRemota CrearImagenBasica CrearSoftIncremental"); then + ogRaiseError $OG_ERR_NOTEXEC "$CALLER -> $PROG" + exit $? +fi + +# Salir si el repositorio está bloquedo (tiene ficheros abiertos). +REPOIP=$(ogGetRepoIp) +if [ -z "$REPOIP" ]; then + ogRaiseError $OG_ERR_NOTFOUND "repo no montado" + exit $? +fi +if ogIsRepoLocked; then + ogRaiseError $OG_ERR_LOCKED "repo $REPOIP" + exit $? +fi + +# Comprobar protocolo y modo de acceso. +PROTO=${ogprotocol:-"smb"} +case "$PROTO" in + nfs|smb) ;; + *) ogRaiseError $OG_ERR_FORMAT "protocolo desconocido $PROTO" + exit $? ;; +esac +case "$1" in + admin) MODE="rw" ;; + user) MODE="ro" ;; + *) ogRaiseError $OG_ERR_FORMAT "modo desconocido $1" + exit $? ;; +esac + +# Desmontar repositorio y volver a montarlo con el modo adecuado. +umount $OGIMG +# Unidad organizativa +[ "$ogunit" != "" ] && OGUNIT="/$ogunit" +ogEcho info "$PROG: Montar repositorio $REPO por $PROTO en modo $1" +case "$PROTO" in + nfs) mount -t nfs $REPOIP:$OGIMG$OGUNIT $OGIMG -o $MODE ;; + smb) PASS=$(grep "^[ ]*\(export \)\?OPTIONS=" /scripts/ogfunctions 2>&1 | \ + sed 's/\(.*\)pass=\(\w*\)\(.*\)/\2/') + PASS=${PASS:-"og"} + mount.cifs //$REPOIP/ogimages$OGUNIT $OGIMG -o $MODE,serverino,acl,username=opengnsys,password=$PASS +esac + diff --git a/sources/interface/Configurar b/sources/interface/Configurar new file mode 100755 index 0000000..e88d073 --- /dev/null +++ b/sources/interface/Configurar @@ -0,0 +1,159 @@ +#!/bin/bash + + +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg +[ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimieincludento para httpdlog +echo " " > $OGLOGSESSION; echo " " > $OGLOGCOMMAND; echo " " > ${OGLOGCOMMAND}.tmp + +# Registro de inicio de ejecución +ogEcho log session "$MSG_INTERFACE_START $0 $*" + +# Solo ejecutable por OpenGnsys Client. +PATH=$PATH:$(dirname $0) +PROG=$(basename $0) + +#____________________________________________________________________ +# +# El parámetro $2 es el que aporta toda la información y el $1 se queda obsoleto +# Formato de entrada: +# dis=Número de disco +# *=caracter de separación +# che=Vale 0 o 1 +# *=caracter de separación +# $tch=tamaño cache +# != caracter de separación +# +# Y un numero indeterminado de cadenas del tipo siguuenteseparadas por el caracter '$': +# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación +# @= caracter de separación +#____________________________________________________________________ + +# Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores). +#param='dis=1*che=0*tch=70000000!par=1*cpt=NTFS*sfi=NTFS*tam=11000000*ope=0%' +shift +param="$(echo $* | sed 's/[ ]//g')" + +# Activa navegador para ver progreso +coproc /opt/opengnsys/bin/browser -qws http://localhost/cgi-bin/httpd-log.sh + +# Leer los dos bloques de parámetros, separados por '!'. +declare -a TBPRM + +IFS='!' read -a TBPRM <<<"$param" +pparam="${TBPRM[0]}" # Parámetros generales del disco. +sparam="${TBPRM[1]}" # Parámetros de particionado y formateo. + + +# Toma valores de disco y caché, separados por "*". +# Los valores están en las variables $dis: disco, $che: existe cache (1, 0), $tch: Tamaño de la cache. +unset TBPRM +IFS='*' read -a TBPRM <<<"$pparam" +[[ ${TBPRM} =~ = ]] && eval ${TBPRM[@]} # Comprobar asignación antes de exportar valores. + +# Error si no se define el parámetro de disco (dis). +[ -z "$dis" ] && exit $OG_ERR_FORMAT + +# Toma valores de distribución de particiones, separados por "%". +declare -a CFG # Valores de configuración. +declare -a TBP # Tabla de particionado. +declare -a TBF # Tabla de formateo. + +unset TBPRM +IFS='%' read -a TBPRM <<<"$sparam" + +maxp=0 +for ((i=0; i<${#TBPRM[@]}; i++)); do + # Leer datos de la partición, separados por "*". + unset par + IFS='*' read -a CFG <<<"${TBPRM[i]}" 2>/dev/null + [[ ${CFG} =~ = ]] && eval ${CFG[@]} # Comprobar asignación antes de exportar valores. + # Componer datos de particionado. + if [ "$cpt" != "CACHE" ]; then + TBP[par]="$cpt:$tam" + fi + # Si se activa operación de formatear, componer datos de formateo. + if [ "$ope" == 1 ]; then + # Comprobamos que la particion y el s.f sean validos. + ogCheckStringInGroup $cpt "EMPTY EXTENDED LINUX-LVM LVM ZPOOL" + [ $? -ne 0 ] && TBF[par]="$sfi" + fi + # Obtener la partición mayor. + [ $par -gt $maxp ] && maxp=$par +done +#____________________________________________________ +# +# Proceso +#____________________________________________________ + +# Tamaño actual de la cache +CACHESIZE=$(ogGetCacheSize) + +# Desmonta todas las particiones y la caché + +ogEcho session log "[10] $MSG_HELP_ogUnmountAll" +ogUnmountAll $dis &>/dev/null +ogUnmountCache + +# Elimina la tabla de particiones +if [ `ogGetPartitionTableType 1` != 'MSDOS' ]; then + ogDeletePartitionTable $dis + ogExecAndLog COMMAND ogUpdatePartitionTable $dis + + # Crea tabla de particiones MSDOS (NOTA: adaptar para tablas GPT). + ogCreatePartitionTable $dis MSDOS +fi + +# Inicia la cache. +if echo "$sparam" |grep "CACHE" >/dev/null; then + ogEcho session log "[30] $MSG_HELP_ogCreateCache" + ogEcho session log " initCache $tch" + ogExecAndLog COMMAND initCache $tch +fi + +# Definir particionado. +ogEcho session log "[50] $MSG_HELP_ogCreatePartitions" +ogEcho session log " ogCreatePartitions $dis ${TBP[@]}" +ogExecAndLog COMMAND ogCreatePartitions $dis ${TBP[@]} +if [ $? -ne 0 ]; then + kill $COPROC_PID + exit $(ogRaiseError session log $OG_ERR_GENERIC "ogCreatePartitions $dis ${TBP[@]}") +fi +ogExecAndLog COMMAND ogUpdatePartitionTable $dis + +# Formatear particiones +ogEcho session log "[70] $MSG_HELP_ogFormat" + +for ((par=1; par<=$maxp; par++)); do + case "${TBF[par]}" in + CACHE) # Si el tamaño es distinto ya se ha formateado. + if [ "$CACHESIZE" == $tch ]; then + ogEcho session log " ogFormatCache" + ogExecAndLog COMMAND ogFormatCache + fi + ;; + "") ;; + *) ogEcho session log " ogFormatFs $dis $par ${TBF[par]}" + ogExecAndLog COMMAND ogFormatFs $dis $par ${TBF[par]} + if [ $? -ne 0 ]; then + kill $COPROC_PID + exit $(ogRaiseError session log $OG_ERR_GENERIC "ogFormatFs $dis $par ${TBF[par]}"); + fi + ;; + esac +done +RETVAL=$? +# Registro de fin de ejecución +ogEcho log session "$MSG_INTERFACE_END $RETVAL" + +#___________________________________________________________________ +# +# Retorno +#___________________________________________________________________ + +kill $COPROC_PID +exit 0 + diff --git a/sources/interface/ConsolaRemota b/sources/interface/ConsolaRemota new file mode 100755 index 0000000..f569771 --- /dev/null +++ b/sources/interface/ConsolaRemota @@ -0,0 +1,3 @@ +#!/bin/bash +chmod +x $1 +$1>$2 || exit $? diff --git a/sources/interface/CrearImagen b/sources/interface/CrearImagen new file mode 100755 index 0000000..e3b21c7 --- /dev/null +++ b/sources/interface/CrearImagen @@ -0,0 +1,91 @@ +#!/bin/bash + +#___________________________________________________ +# +# PARAMETROS RECIBIDOS DESDE EL CLIENTE: +# $1 Número de disco +# $2 Número de particion +# $3 Nombre canónico de la imagen (sin extensión) +# $4 Dirección del repositorio (REPO, por defecto) +#___________________________________________________ + + +#$OG_ERR_NOTEXEC Si no es llamada por OG client +#$OG_ERR_LOCKED=4 Si la particion está bloqueada. + + +#Codigos de error del scripts createImage +#@exception OG_ERR_FORMAT # 1 formato incorrecto. +#@exception OG_ERR_PARTITION # 3 Error en partición de disco o en su sistema de archivos +#@exception OG_ERR_IMAGE # 5 Error en funcion ogCreateImage o ogRestoreImage. +#@exception OG_ERR_NOTWRITE # 14 error de escritura +#@exception OG_ERR_NOTCACHE # 15 si cache no existe 15 +#@exception OG_ERR_CACHESIZE # 16 si espacio de la cache local o remota no tiene espacio 16 +#@exception OG_ERR_REDUCEFS # 17 error al reducir sistema de archivos. +#@exception OG_ERR_EXTENDFS # 18 Errror al expandir el sistema de archivos. + + +#Códigos de error de la funcion ogCreateImage + + + +TIME1=$SECONDS + +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg +[ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +echo " " > $OGLOGSESSION; echo " " > $OGLOGCOMMAND; echo " " > ${OGLOGCOMMAND}.tmp + +# Registro de inicio de ejecución +ogEcho log session "$MSG_INTERFACE_START $0 $*" + +# Solo ejecutable por OpenGnsys Client. +PATH=$PATH:$(dirname $0) +PROG=$(basename $0) +CALLER=$(ogGetCaller) +if [ "$CALLER" != "ogAdmClient" ]; then + ogRaiseError $OG_ERR_NOTEXEC "$CALLER -> $PROG" + exit $? +fi + +# Valor por defecto para el repositorio. +REPO=${4:-"REPO"} +[ "$REPO" == "$(ogGetIpAddress)" ] && REPO="CACHE" +# Si es una ip y es distinta a la del recurso samba cambiamos de REPO. +ogCheckIpAddress $REPO +if [ $? == 0 -o $REPO == "REPO" ] ; then + # Unidad organizativa + [ "$ogunit" != "" ] && OGUNIT="$ogunit" + # Si falla el cambio -> salimos con error repositorio no valido + ogChangeRepo $REPO $OGUNIT || exit $(ogRaiseError $OG_ERR_NOTFOUND '$REPO'; echo $?) + REPO="REPO" +fi + +# Si el destino es REPO y el cliente no está en modo "admin"; activar repositorio para escritura, +if [ "$REPO" == "REPO" -a "$boot" != "admin" ] +then + CambiarAcceso admin &>> $OGLOGFILE + RETVAL=$? + [ $RETVAL -gt 0 ] && exit $RETVAL +fi + +ogEcho createImage "$1" "$2" "$4" /"$3" +# Si existe, ejecuta script personalizado "createImageCustom"; si no, llama al genérico "createImage". +if which createImageCustom &>/dev/null; then + createImageCustom "$1" "$2" "$4" /"$3" &>> $OGLOGCOMMAND +else + createImage "$1" "$2" "$4" /"$3" &>> $OGLOGCOMMAND +fi +RETVAL=$? + +# Cambiar acceso a modo usuario, si es necesario. +[ "$REPO" == "REPO" -a "$boot" != "admin" ] && CambiarAcceso user + +# Registro de fin de ejecución +ogEcho log session "$MSG_INTERFACE_END $RETVAL" + +exit $RETVAL + diff --git a/sources/interface/CrearImagenBasica b/sources/interface/CrearImagenBasica new file mode 100755 index 0000000..8aaf5aa --- /dev/null +++ b/sources/interface/CrearImagenBasica @@ -0,0 +1,98 @@ +#!/bin/bash +#___________________________________________________________________ +# +# CREAR IMAGEN BÁSICA +#___________________________________________________________________ +# +# Parámetros recibidos desde el cliente: +# +# $1 Número de disco +# $2 Número de particion +# $3 Nombre canónico de la imagen básica (sin extensión) +# $4 Dirección del repositorio +# $5 Es una cadena "nnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnn" donde "n" vale 0 ó 1. +# 1XX: Gestionar fichero completo en lugar de diferencas +# X1X: Eliminar archivos de la imagen que no estén en la partición +# XX1: Comprimir archivos para enviarlos por la red +# El valor X indica que no importa el valor que tenga el dato +# $6 Es una cadena "nnnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnnn" donde "n" vale 0 ó 1. +# 1XXX: Borrar la imagen del repositorio antes de crearla +# X1XX: Copiar Imagen básica también a la cache +# XX1X: Borrar previamente la imagen de la cache antes de copiarla +# XXX1: No borrar archivos en destino +# El valor X indica que no importa el valor que tenga el dato +# $7 Método de syncronización 1=Sincronización1 2=Sincronizacion2 +# $8 Ruta de origen de la Imagen (Carpeta) + +#___________________________________________________________________ +# +# Control parámetros +#___________________________________________________________________ + + + PROG="$(basename $0)" + if [ $# -lt 7 ]; then + usage=" ndisco nparticion nombre_imagen_basica ip_repositorio" + usage="$usage copiar_a_caché Borrar_cache_previamente Ruta_origen" + ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: $PROG $usage" + exit $? + fi + + #Load engine configurator from engine.cfg file. + #Carga el configurador del engine desde el fichero engine.cfg + [ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + + # Clear temporary file used as log track by httpdlog + # Limpia los ficheros temporales usados como log de seguimiento para httpdlog + echo -n "" > $OGLOGSESSION; echo -n "" > $OGLOGCOMMAND + + # Registro de inicio de ejecución + ogEcho log session "$MSG_INTERFACE_START $0 $*" + + # Si el destino es REPO y el cliente no está en modo "admin"; activar repositorio para escritura, + PATH=$PATH:$(dirname $0) + CLIENTIP=$(ogGetIpAddress) + [ "$4" == "$CLIENTIP" ] && DEST=CACHE || DEST=REPO + if [ "$DEST" == "REPO" -a "$boot" != "admin" ]; then + CambiarAcceso admin &>> $OGLOGFILE + RETVAL=$? + [ $RETVAL -gt 0 ] && exit $RETVAL + fi + + if [ $7 -eq 1 ]; then + #sincronizacion1 + ogCrearImagenBasica "$@" + RETVAL=$? + fi + + if [ $7 -eq 2 ]; then + # Sincronizacion2 + flag=$5 + WHOLE=${flag:0:1} + DELFILE=${flag:1:1} + COMPRESS=${flag:2:1} + + # Nota los valores se pasan como variables de entorno, + # la idea es que mas adelante vayan en el fichero PXE. + [ $WHOLE -eq 1 ] && export ogrsyncw=true || export ogrsyncw=false + [ $DELFILE -eq 1 ] && export ogrsyncdel=true || export ogrsyncdel=false + [ $COMPRESS -eq 1 ] && export ogrsyncz=true || export ogrsyncz=false + + # [ "$4" == "0.0.0.0" ] && DEST="CACHE" || DEST="REPO" + + createBaseImage $1 $2 $DEST "$3" + RETVAL=$? + + fi + + # Si estamos en modo user montamos el repositorio en modo lectura. + [ "$DEST" == "REPO" -a "$boot" != "admin" ] && CambiarAcceso user + # Registro de fin de ejecución + ogEcho log session "$MSG_INTERFACE_END $RETVAL" + + + + exit $RETVAL + diff --git a/sources/interface/CrearSoftIncremental b/sources/interface/CrearSoftIncremental new file mode 100755 index 0000000..fc29451 --- /dev/null +++ b/sources/interface/CrearSoftIncremental @@ -0,0 +1,98 @@ +#!/bin/bash +#___________________________________________________________________ +# +# CREAR IMAGEN INCREMENTAL +#___________________________________________________________________ +# +# Parámetros recibidos desde el cliente: +# +# $1 Número de disco +# $2 Número de particion +# $3 Nombre canónico de la imagen básica (sin extensión) +# $4 Dirección del repositorio +# $5 Nombre canónico de la imagen incremental (sin extensión) +# $6 Es una cadena "nnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnn" donde "n" vale 0 ó 1. +# 1XX: Gestionar fichero completo en lugar de diferencas +# X1X: Eliminar archivos de la imagen que no estén en la partición +# XX1: Comprimir archivos para enviarlos por la red +# El valor X indica que no importa el valor que tenga el dato +# $7 Es una cadena "nnnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnnn" donde "n" vale 0 ó 1. +# 1XXX: Borrar la imagen incremental del repositorio antes de crearla +# X1XX: Copiar imagen incremental también a la cache +# XX1X: Borrar previamente la imagen incremental de la cache antes de copiarla +# XXX1: No borrar archivos en destino +# El valor X indica que no importa el valor que tenga el dato +# $8 Método de syncronización 1=Sincronización1 2=Sincronizacion2 +# $9 Ruta de origen de la Imagen (Carpeta) + +#___________________________________________________________________ +# +# Control parámetros +#___________________________________________________________________ + PROG="$(basename $0)" + if [ $# -lt 8 ]; then + usage=" ndisco nparticion nombre_imagen_basica ip_repositorio nombre_imagen_incremental" + usage="$usage copiar_a_caché Borrar_cache_previamente Ruta_origen" + ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: $PROG $usage" + exit $? + fi + + #Load engine configurator from engine.cfg file. + #Carga el configurador del engine desde el fichero engine.cfg + [ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + + # Clear temporary file used as log track by httpdlog + # Limpia los ficheros temporales usados como log de seguimiento para httpdlog + echo -n "" > $OGLOGSESSION; echo -n "" > $OGLOGCOMMAND + + # Registro de inicio de ejecución + ogEcho log session "$MSG_INTERFACE_START $0 $*" + + + # Si el destino es REPO y el cliente no está en modo "admin"; activar repositorio para escritura, + PATH=$PATH:$(dirname $0) + CLIENTIP=$(ogGetIpAddress) + [ "$4" == "$CLIENTIP" ] && DEST=CACHE || DEST=REPO + if [ "$DEST" == "REPO" -a "$boot" != "admin" ]; then + CambiarAcceso admin &>> $OGLOGFILE + RETVAL=$? + [ $RETVAL -gt 0 ] && exit $RETVAL + fi + + if [ $8 -eq 1 ]; then + #sincronizacion1 + ogCrearSoftIncremental "$@" + RETVAL=$? + fi + + + if [ $8 -eq 2 ]; then + #sincronizacion 2 + flag=$6 + WHOLE=${flag:0:1} + DELFILE=${flag:1:1} + COMPRESS=${flag:2:1} + + # Nota los valores se pasan como variables de entorno, + # la idea es que mas adelante vayan en el fichero PXE. + [ $WHOLE -eq 1 ] && export ogrsyncw=true || export ogrsyncw=false + [ $DELFILE -eq 1 ] && export ogrsyncdel=true || export ogrsyncdel=false + [ $COMPRESS -eq 1 ] && export ogrsyncz=true || export ogrsyncz=false + + # REPOSITORIO: Si la ip es la del propio equipo CACHE, si no REPO + #CLIENTIP=$(ogGetIpAddress) + #[ "$4" == "$CLIENTIP" ] && DEST=CACHE || DEST=REPO + createDiffImage $1 $2 $DEST "$3" "$5" + RETVAL=$? + + fi + + # Si estamos en modo user montamos el repositorio en modo lectura. + [ "$DEST" == "REPO" -a "$boot" != "admin" ] && CambiarAcceso user + + # Registro de fin de ejecución + ogEcho log session "$MSG_INTERFACE_END $RETVAL" + + exit $RETVAL diff --git a/sources/interface/EjecutarScript b/sources/interface/EjecutarScript new file mode 100755 index 0000000..26453ed --- /dev/null +++ b/sources/interface/EjecutarScript @@ -0,0 +1,44 @@ +#!/bin/bash +TIME1=$SECONDS + + +#Load engine configurator from engine.cfg file. +#Carga el configurador del engine desde el fichero engine.cfg +[ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + +# Clear temporary file used as log track by httpdlog +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +echo -n "" > $OGLOGSESSION; echo -n "" > $OGLOGCOMMAND + +# Registro de inicio de ejecución +ogEcho log session "$MSG_INTERFACE_START $0 $*" + +echo -e "\n Instrucciones a ejecutar: *****************************" >> $OGLOGFILE +cat $1 >> $OGLOGFILE + + +echo -e "\n Salida de las instrucciones: *****************************" >> $OGLOGFILE +chmod +x $1 +# Si mandamos la salida a OGLOGCOMMAND reescribimos lo que manda el comando. +#$1 &>> $OGLOGCOMMAND +$1 +RETVAL=$? + + + +TIME=$[SECONDS-TIME1] +if [ $RETVAL == 0 ] +then + ogEcho log session "[100] Duracion de la operacion $[TIME/60]m $[TIME%60]s" +else + ogRaiseError log session $RETVAL + ogEcho log session error "Operacion no realizada" +fi + + +# Registro de fin de ejecución +ogEcho log session "$MSG_INTERFACE_END $RETVAL" + + +exit $RETVAL + diff --git a/sources/interface/IniciarSesion b/sources/interface/IniciarSesion new file mode 100755 index 0000000..750d96d --- /dev/null +++ b/sources/interface/IniciarSesion @@ -0,0 +1,13 @@ +#!/bin/bash + +# UHU - Comprobamos el disco, si solo hay un parametro, disco es 1, por compatibilidad con clientes antiguos +if [ $# == 1 ] +then + disk=1 + part=$1 +else + disk=$1 + part=$2 +fi + +bootOs $disk $part diff --git a/sources/interface/InventarioHardware b/sources/interface/InventarioHardware new file mode 100755 index 0000000..17614a5 --- /dev/null +++ b/sources/interface/InventarioHardware @@ -0,0 +1,6 @@ +#!/bin/bash +# Script de interfaz para guardar en un fichero el inventario de hardware de un cliente. + +file=$(listHardwareInfo) +tail -n+2 $file >$1 + diff --git a/sources/interface/InventarioSoftware b/sources/interface/InventarioSoftware new file mode 100755 index 0000000..fa96565 --- /dev/null +++ b/sources/interface/InventarioSoftware @@ -0,0 +1,19 @@ +#!/bin/bash + +TIME1=$SECONDS + +#Carga el configurador del engine desde el fichero engine.cfg +[ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + +# Limpia los ficheros temporales usados como log de seguimiento para httpdlog +echo -n " " | tee $OGLOGSESSION $OGLOGCOMMAND ${OGLOGCOMMAND}.tmp + +# Registro de inicio de ejecución +ogEcho log session "$MSG_INTERFACE_START $0 $*" + +file=$(listSoftwareInfo $1 $2) +cp $file $3 + +TIME=$[SECONDS-TIME1] +ogEcho log session " [ ] $MSG_SCRIPTS_TIME_PARTIAL : $[TIME/60]m $[TIME%60]s" + diff --git a/sources/interface/Reiniciar b/sources/interface/Reiniciar new file mode 100755 index 0000000..df93c1b --- /dev/null +++ b/sources/interface/Reiniciar @@ -0,0 +1,3 @@ +#!/bin/bash +reboot +exit 0 diff --git a/sources/interface/RestaurarImagen b/sources/interface/RestaurarImagen new file mode 100755 index 0000000..6f9ae24 --- /dev/null +++ b/sources/interface/RestaurarImagen @@ -0,0 +1,15 @@ +#!/bin/bash +#_______________________________________________________________________________________________________________________________ +# +# PARAMETROS RECIBIDOS DESDE EL CLIENTE: +# $1 disco +# $2 par=Número de particion +# $3 Nombre canónico de la imagen +# $4 Dirección IP del repositorio +# $5 Protocolo UNICAST MULTICAST TORRENT +# $6 Opciones del protocolo +#_______________________________________________________________________________________________________________________________ + +# Llamar al script de despliegue "deployImage". +deployImage "$4" "$3" "$1" "$2" "$5" "$6" "$7" "$8" || exit $? + diff --git a/sources/interface/RestaurarImagenBasica b/sources/interface/RestaurarImagenBasica new file mode 100755 index 0000000..c87b318 --- /dev/null +++ b/sources/interface/RestaurarImagenBasica @@ -0,0 +1,89 @@ +#!/bin/bash +#___________________________________________________________________ +# +# RESTAURAR IMAGEN BÁSICA +#___________________________________________________________________ +# +# Parámetros recibidos desde el cliente: +# +# $1 Número de disco +# $2 Número de particion +# $3 Nombre canónico de la imagen básica (sin extensión) +# $4 Dirección del repositorio +# $5 Tipo de transmisión 0=Unicast 1=Multicast +# $6 Es una cadena "nnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnn" donde "n" vale 0 ó 1. +# 1XX: Gestionar fichero completo en lugar de diferencas +# X1X: Eliminar archivos de la partición que no estén en la imagen +# XX1: Comprimir archivos para enviarlos por la red +# El valor X indica que no importa el valor que tenga el dato +# $7 Es una cadena "nnnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnnn" donde "n" vale 0 ó 1. +# 1XXX: Borrar la particion de destino antes de restaurar la imagen basica +# X1XX: Copiar Imagen básica también a la cache +# XX1X: Borrar previamente la imagen basica de la cache antes de copiarla +# XXX1: No borrar archivos en destino +# El valor X indica que no importa el valor que tenga el dato +# $8 Método de clonación 0=Desde caché 1=Desde repositorio +# $9 Metodo de sincronizacion 1=Sincronización1 2=Sincronizacion2 +# $10 Ruta de origen de la Imagen (Carpeta) + +#___________________________________________________________________ +# +# Control parámetros +#___________________________________________________________________ + + PROG="$(basename $0)" + if [ $# -lt 9 ]; then + usage=" ndisco nparticion nombre_imagen_basica ip_repositorio copiar_a_caché " + usage="$usage Borrar_cache_previamente metodo_clonación Ruta_origen" + ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: $PROG $usage" + exit $? + fi + + #Load engine configurator from engine.cfg file. + #Carga el configurador del engine desde el fichero engine.cfg + [ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + + # Clear temporary file used as log track by httpdlog + # Limpia los ficheros temporales usados como log de seguimiento para httpdlog + echo -n "" > $OGLOGSESSION; echo " " > $OGLOGCOMMAND + + # Registro de inicio de ejecución + ogEcho log session "$MSG_INTERFACE_START $0 $*" + + if [ $9 -eq 1 ]; then + #sincronizacion1 + ogRestaurarImagenBasica "$@" + RETVAL=$? + fi + + if [ $9 -eq 2 ]; then + #sincronizacion2 + # Opciones de clonacion + flag=$6 + WHOLE=${flag:0:1} + DELFILE=${flag:1:1} + COMPRESS=${flag:2:1} + + # Nota los valores se pasan como variables de entorno, + # la idea es que mas adelante vayan en el fichero PXE. + [ $WHOLE -eq 1 ] && export ogrsyncw=true || export ogrsyncw=false + [ $DELFILE -eq 1 ] && export ogrsyncdel=true || export ogrsyncdel=false + [ $COMPRESS -eq 1 ] && export ogrsyncz=true || export ogrsyncz=false + + # Origen de la imagen. + [ $8 -eq 0 ] && DEST="CACHE" || DEST="REPO" + + # Protocolo de clonacion y opciones + PROTO=${5%_*} + OPT=${5#*_} + + restoreBaseImage $DEST "$3" $1 $2 $PROTO $OPT + RETVAL=$? + fi + + # Registro de fin de ejecución + ogEcho log session "$MSG_INTERFACE_END $RETVAL" + + exit $RETVAL diff --git a/sources/interface/RestaurarSoftIncremental b/sources/interface/RestaurarSoftIncremental new file mode 100755 index 0000000..ee895d9 --- /dev/null +++ b/sources/interface/RestaurarSoftIncremental @@ -0,0 +1,82 @@ +#!/bin/bash +#___________________________________________________________________ +# +# RESTAURAR IMAGEN INCREMENTAL +#___________________________________________________________________ +# +# Parámetros recibidos desde el cliente: +# +# $1 Número de disco +# $2 Número de particion +# $3 Nombre canónico de la imagen básica (sin extensión) +# $4 Dirección del repositorio +# $5 Nombre canónico del software incremental (sin extensión) +# $6 Tipo de transmisión 0=Unicast 1=Multicast +# $7 Es una cadena "nnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnn" donde "n" vale 0 ó 1. +# 1XX: Gestionar fichero completo en lugar de diferencas +# X1X: Eliminar archivos de la partición que no estén en la imagen +# XX1: Comprimir archivos para enviarlos por la red +# El valor X indica que no importa el valor que tenga el dato +# $8 Es una cadena "nnnn" tipo flags que codifica varios parametros. +# Tiene el formato "nnnn" donde "n" vale 0 ó 1. +# 1XXX: Borrar la particion de destino antes de restaurar la imagen basica +# X1XX: Copiar Imagen básica también a la cache +# XX1X: Borrar previamente la imagen basica de la cache antes de copiarla +# XXX1: No borrar archivos en destino +# El valor X indica que no importa el valor que tenga el dato +# $9 Método de clonación 0=Desde caché 1=Desde repositorio +# $10 Metodo de sincronizacion 1=Sincronización1 2=Sincronizacion2 +# $11 Ruta de origen de la Imagen (Carpeta) + +#___________________________________________________________________ +# +# Control parámetros +#___________________________________________________________________ + #Load engine configurator from engine.cfg file. + #Carga el configurador del engine desde el fichero engine.cfg + [ -z $OGENGINECONFIGURATE ] && source /opt/opengnsys/etc/engine.cfg + + # Clear temporary file used as log track by httpdlog + # Limpia los ficheros temporales usados como log de seguimiento para httpdlog + echo " " > $OGLOGSESSION; echo " " > $OGLOGCOMMAND + + # Registro de inicio de ejecución + ogEcho log session "$MSG_INTERFACE_START $0 $*" + + + if [ ${10} -eq 1 ]; then + #sincronizacion1 + ogRestaurarSoftIncremental "$@" + RETVAL=$? + fi + + if [ ${10} -eq 2 ]; then + #sincronizacion2 + # Opciones de clonacion + flag=$7 + WHOLE=${flag:0:1} + DELFILE=${flag:1:1} + COMPRESS=${flag:2:1} + + # Nota los valores se pasan como variables de entorno, + # la idea es que mas adelante vayan en el fichero PXE. + [ $WHOLE -eq 1 ] && export ogrsyncw=true || export ogrsyncw=false + [ $DELFILE -eq 1 ] && export ogrsyncdel=true || export ogrsyncdel=false + [ $COMPRESS -eq 1 ] && export ogrsyncz=true || export ogrsyncz=false + + # Origen de la imagen. + [ $9 -eq 0 ] && DEST="CACHE" || DEST="REPO" + + # Protocolo de clonacion y opciones + PROTO=${6%_*} + OPT=${6#*_} + + restoreDiffImage $DEST "$3" "$5" $1 $2 $PROTO $OPT + RETVAL=$? + fi + + # Registro de fin de ejecución + ogEcho log session "$MSG_INTERFACE_END $RETVAL" + + exit $RETVAL diff --git a/sources/interface/getConfiguration b/sources/interface/getConfiguration new file mode 100755 index 0000000..ddfc382 --- /dev/null +++ b/sources/interface/getConfiguration @@ -0,0 +1,88 @@ +#!/bin/bash + +#_______________________________________________________________________________________________________________________________ +# +# Formato de salida: +# disk=Número de disco\tpar=Número de particion\tcod=Código de partición\tsfi=Sistema de ficheros\tsoi=Sistema instalado\ttam=Tamaño de la partición\n +#_______________________________________________________________________________________________________________________________ + + +# No registrar los errores. +export DEBUG="no" + +ser=$(ogGetSerialNumber) +cfg="" +disks=$(ogDiskToDev | wc -w) +for ((dsk=1; dsk<=$disks; dsk++)); do + particiones=$(ogGetPartitionsNumber $dsk) + particiones=${particiones:-0} + # Tipo de tabla de particiones: 1=MSDOS, 2=GPT + ptt=$(ogGetPartitionTableType $dsk) + case "$ptt" in + MSDOS) ptt=1 ;; + GPT) ptt=2 ;; + LVM) ptt=3 ;; + ZPOOL) ptt=4 ;; + *) ptt=0 ;; + esac + # Información de disco (partición 0) + cfg="$cfg$dsk:0:$ptt:::$(ogGetDiskSize $dsk):0;" + for ((par=1;par<=$particiones;par++)); do + # Código del identificador de tipo de partición + cod=$(ogGetPartitionId $dsk $par 2>/dev/null) + # Tipo del sistema de ficheros + fsi=$(getFsType $dsk $par 2>/dev/null) + fsi=${fsi:-"EMPTY"} + # Tamaño de la particón + tam=$(ogGetPartitionSize $dsk $par 2>/dev/null) + tam=${tam:-"0"} + # Sistema operativo instalado + case "$fsi" in + ""|EMPTY|LINUX-SWAP|LINUX-LVM|ZVOL) + soi=""; uso=0 ;; + *) if [ -n "$(ogMount $dsk $par 2>/dev/null)" ]; then + soi=$(getOsVersion $dsk $par 2>/dev/null | cut -f2 -d:) + # Hacer un 2º intento para algunos casos especiales. + [ -z "$soi" ] && soi=$(getOsVersion $dsk $par 2>/dev/null | cut -f2 -d:) + # Sistema de archivos para datos (sistema operativo "DATA") + [ -z "$soi" -a "$fsi" != "EMPTY" -a "$fsi" != "CACHE" ] && soi="DATA" + # Obtener porcentaje de uso. + uso=$(df $(ogGetMountPoint $dsk $par) | awk '{getline; printf "%d",$5}') + uso=${uso:0} + else + soi=""; uso=0 + fi + ;; + esac + cfg="$cfg$dsk:$par:$cod:$fsi:$soi:$tam:$uso;" + done +done + +# Crear configuración por defecto para cliente sin disco. +[ -z "$cfg" ] && cfg="1:0:0:::0;" + +# Guardar salida en fichero temporal. +cfgfile=/tmp/getconfig +echo "${ser:+$ser;}$cfg" > $cfgfile + +# Crear el menú por defecto a partir del fichero generado (no dar ninguna salida). +generateMenuDefault &>/dev/null + +# Componer salida formateada. +awk '{ n=split($0,sep,";"); + for (i=1; i