penguins-eggs
Version:
A remaster system tool, compatible with Almalinux, Alpine, Arch, Debian, Devuan, Fedora, Manjaro, Opensuse, Ubuntu and derivatives
1,091 lines (1,090 loc) • 33 kB
JavaScript
/**
* ./src/classes/utils.ts
* penguins-eggs v.25.7.x / ecmascript 2020
* author: Piero Proietti
* email: piero.proietti@gmail.com
* license: MIT
*
* Refactored Utils class - imports from modular utilities
*/
import chalk from 'chalk';
import dns from 'dns';
import fs from 'fs';
// pjson
import { createRequire } from 'module';
import os from 'os';
import path from 'path';
import { shx, spawnSync } from '../lib/utils.js';
// libraries
import Distro from './distro.js';
import Kernel from './utils.d/kernel.js';
const require = createRequire(import.meta.url);
const pjson = require('../../package.json');
// __dirname
const __dirname = path.dirname(new URL(import.meta.url).pathname);
/**
* Utils: general porpourse utils
* @remarks all the utilities
*/
export default class Utils {
/**
* address
*/
static address() {
const interfaces = os.networkInterfaces();
let address = '';
if (interfaces !== undefined) {
for (const devName in interfaces) {
const iface = interfaces[devName];
if (iface !== undefined) {
for (const alias of iface) {
if (alias.family === 'IPv4' &&
alias.address !== '127.0.0.1' &&
!alias.internal
&& // take just the first!
address === '') {
address = alias.address;
}
}
}
}
}
return address;
}
static broadcast() {
const netmask = Utils.netmask();
const ip = Utils.address();
const ipParts = ip.split('.').map(Number);
const maskParts = netmask.split('.').map(Number);
const broadcastParts = ipParts.map((part, index) =>
// Bitwise OR tra il blocco IP e il blocco Netmask invertito (255 - mask)
part | (255 - maskParts[index]));
return broadcastParts.join('.');
}
/**
* chpasswdPath
* @returns
*/
static chpasswdPath() {
let chpasswdPath = '/usr/sbin/chpasswd';
if (fs.existsSync(chpasswdPath)) {
chpasswdPath = '/usr/bin/chpasswd';
}
return chpasswdPath;
}
/**
* cidr
*/
static cidr() {
const interfaces = os.networkInterfaces();
let cidr = '';
if (interfaces !== undefined) {
for (const devName in interfaces) {
const iface = interfaces[devName];
if (iface !== undefined) {
for (const alias of iface) {
if (alias.family === 'IPv4' &&
alias.address !== '127.0.0.1' &&
!alias.internal
&& // take just the first!
cidr === '' && alias.cidr !== null) {
cidr = alias.cidr;
}
}
}
}
}
return cidr;
}
/**
*
* @param cmd
*/
static commandExists(cmd) {
return Boolean(shx.which(cmd));
}
/**
*
* @param msg
*/
static async customConfirm(msg = 'Select yes to continue... ') {
const { select } = await import('@inquirer/prompts');
const answer = await select({
message: msg,
choices: [
{ name: 'No', value: 'No' },
{ name: 'Yes', value: 'Yes' },
],
default: 'No',
});
console.log('User selected:', answer); // Debug logging
return answer === 'Yes';
}
/**
*
* @param msg
*/
static async customConfirmAbort(msg = 'Confirm') {
const { select } = await import('@inquirer/prompts');
const answer = await select({
message: msg,
choices: [
{ name: 'No', value: 'No' },
{ name: 'Yes', value: 'Yes' },
{ name: 'Abort', value: 'Abort' },
],
default: 'Yes',
});
return JSON.stringify({ confirm: answer });
}
/**
*
* @param msg
*/
static async customConfirmCompanion(msg = 'Select yes to continue... ') {
const { select } = await import('@inquirer/prompts');
const answer = await select({
message: msg,
choices: [
{ name: 'No', value: 'No' },
{ name: 'Yes', value: 'Yes' },
],
default: 'No',
});
return JSON.stringify({ confirm: answer });
}
static async debug(cmd = 'cmd', procContinue = true) {
console.log(chalk.redBright('DEBUG >>> ') + cmd + '\n');
let msg = 'Press a key to exit...';
if (procContinue) {
msg = 'Press a key to continue...';
}
console.log(msg);
const pressKeyToExit = spawnSync('read _ ', [], { shell: true, stdio: [0, 1, 2] });
if (!procContinue) {
process.exit(0);
}
}
static error(msg = '') {
console.error(pjson.shortName + ' >>> ' + chalk.bgRed(chalk.whiteBright(msg)));
}
/**
*
* @returns flag
*/
static flag() {
let arch = "-";
if (Utils.isAppImage()) {
arch += "AppImage";
}
else
switch (process.arch) {
case "arm64": {
arch += "arm64";
break;
}
case "ia32": {
arch += "i386";
break;
}
case "riscv64": {
arch += "riscv64";
break;
}
case "x64": {
arch += "x86_64";
break;
}
// No default
}
const title = `${pjson.name}`;
const green = ` ${title}`.padEnd(25, " ");
const white = ` Perri's brewery edition `.padEnd(25, " ");
const red = ` v${pjson.version}${arch} `.padStart(25, " ");
return chalk.bgGreen.whiteBright(green) +
chalk.bgWhite.blue(white) +
chalk.bgRed.whiteBright(red);
}
/**
*
* @param bytes
* @param decimals
* @returns
*/
static formatBytes(bytes, decimals = 2) {
if (bytes === 0)
return '0 Bytes';
const k = 1024;
const dm = Math.max(decimals, 0);
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];
}
/**
*
* @param date
*/
static formatDate(date) {
const d = new Date(date);
let month = String(d.getMonth() + 1);
let day = String(d.getDate());
const year = d.getFullYear();
let hh = String(d.getHours());
let mm = String(d.getMinutes());
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
if (hh.length < 2) {
hh = '0' + hh;
}
if (mm.length < 2) {
mm = '0' + mm;
}
return [year, month, day].join('-') + '_' + hh + mm;
}
/**
* @returns gateway
*/
static gateway() {
return shx.exec(`ip r | grep 'default' | awk '{print $3}'`, { silent: true }).stdout.trim();
// return shx.exec(`route -n | grep 'UG[ \t]' | awk '{print $2}'`, { silent: true }).stdout.trim()
}
/**
* Get author name
*/
static getAuthorName() {
return 'Piero Proietti piero.proietti@gmail.com';
}
/**
* Return the Debian version
* @returns {number} Versione di Debian
*/
static getDebianVersion() {
const cmd = "cat /etc/debian_version | /usr/bin/cut -f1 -d'.'";
const version = Number(shx.exec(cmd, { silent: true }).stdout);
return version;
}
/**
* dns
*/
static getDns() {
return dns.getServers();
}
/**
* getDomain
*/
static getDomain() {
return shx.exec('domainname', { silent: true }).stdout.trim();
// return shx.exec(`route -n | grep 'UG[ \t]' | awk '{print $2}'`, { silent: true }).stdout.trim()
}
/**
* return the short name of the package: eggs
* @returns eggs
*/
static getFriendName() {
return pjson.shortName;
}
/**
* Estimate the linuxfs dimension
* (Refactored to use native FS instead of dd/od)
* @returns {number} GB
*/
static getLiveRootSpace(type = 'debian-live') {
let squashFs = '/run/live/medium/live/filesystem.squashfs';
if (type === 'mx') {
squashFs = '/live/boot-dev/antiX/linuxfs';
}
// 1. Leggiamo il tipo di compressione DIRETTAMENTE dall'header del file SquashFS
// L'identificativo della compressione è a offset 20 (2 bytes, little endian)
// 1=gzip, 2=lzo, 3=lzma, 4=xz, 5=lz4, 6=zstd
let compressionId = 0;
try {
if (fs.existsSync(squashFs)) {
const fd = fs.openSync(squashFs, 'r');
const buffer = Buffer.alloc(2);
// Leggi 2 byte alla posizione 20
fs.readSync(fd, buffer, 0, 2, 20);
fs.closeSync(fd);
compressionId = buffer.readUInt16LE(0);
}
}
catch (error) {
console.error("Error reading squashfs header:", error);
}
// 2. Determiniamo il fattore di compressione in base all'ID letto
let compression_factor = 30; // Default conservative
switch (compressionId) {
case 1: { // gzip
compression_factor = 37;
break;
}
case 2: { // lzo
compression_factor = 52;
break;
}
case 3: { // lzma
compression_factor = 52;
break;
}
case 4: { // xz
compression_factor = 31;
break;
}
case 5: { // lz4
compression_factor = 52;
break;
}
case 6: { // zstd (aggiunto per completezza)
compression_factor = 37; // simile a gzip come ratio medio
break;
}
default: {
compression_factor = 30;
}
}
// 3. Calcolo dimensione Linux FS
// Nota: shx.exec ritorna un oggetto, dobbiamo prendere .stdout e pulirlo
let rootfs_file_size = 0;
const dfCmdLinux = 'df /live/linux --output=used --total | /usr/bin/tail -n1';
const dfResultLinux = shx.exec(dfCmdLinux, { silent: true }).stdout.trim();
const linuxfs_used = Number(dfResultLinux) || 0; // Gestione caso NaN
const linuxfs_file_size = (linuxfs_used * 1024 * 100) / compression_factor;
// 4. Calcolo persist-root (se esiste)
if (fs.existsSync('/live/persist-root')) {
const dfCmdRoot = 'df /live/persist-root --output=used --total | /usr/bin/tail -n1';
const dfResultRoot = shx.exec(dfCmdRoot, { silent: true }).stdout.trim();
rootfs_file_size = (Number(dfResultRoot) || 0) * 1024;
}
let rootSpaceNeeded;
if (type === 'mx') {
rootSpaceNeeded = linuxfs_file_size + rootfs_file_size;
}
else {
rootSpaceNeeded = linuxfs_file_size;
}
return rootSpaceNeeded / 1_073_741_824; // Converte in GB
}
// Se il metodo fa parte di una classe, usa `static`. Altrimenti, rimuovilo.
static getOsRelease() {
const osReleasePath = path.join('/etc', 'os-release');
// Inizializza l'oggetto con valori predefiniti
const osInfo = {
ID: '',
VERSION_CODENAME: 'n/a',
VERSION_ID: ''
};
// Verifica se il file esiste
if (!fs.existsSync(osReleasePath)) {
console.error('/etc/os-release file does not exist.');
return osInfo;
}
// Leggi il contenuto del file
let fileContent;
try {
fileContent = fs.readFileSync(osReleasePath, 'utf8');
}
catch (error) {
console.error('Error reading /etc/os-release:', error);
return osInfo;
}
// Analizza ogni linea
const lines = fileContent.split('\n');
for (const line of lines) {
if (line.startsWith('#') || line.trim() === '')
continue;
const [key, value] = line.split('=');
if (key && value) {
const trimmedKey = key.trim();
const trimmedValue = value.trim().replaceAll('"', '');
// Popola solo le chiavi desiderate
switch (trimmedKey) {
case 'ID': {
osInfo.ID = trimmedValue;
break;
}
case 'VERSION_CODENAME': {
osInfo.VERSION_CODENAME = trimmedValue;
break;
}
case 'VERSION_ID': {
osInfo.VERSION_ID = trimmedValue;
break;
}
// No default
}
}
}
// capitalize distroId
osInfo.ID = osInfo.ID[0].toUpperCase() + osInfo.ID.slice(1).toLowerCase();
osInfo.VERSION_CODENAME = osInfo.VERSION_CODENAME.toLowerCase();
return osInfo;
}
/**
* return the name of the package: penguins-eggs
* @returns penguins-eggs
*/
static getPackageName() {
return pjson.shortName;
}
/**
* return the version of the package
* @returns version example 8.0.0
*/
static getPackageVersion() {
return pjson.version;
}
/**
* Return postfix
* @param basename
* @returns eggName
*/
static getPostfix() {
const postfix = '_' + Utils.formatDate(new Date()) + '.iso';
return postfix;
}
/**
*
* @param prefix
* @param backup
* @returns
*/
static getPrefix(prefix, backup = false) {
if (backup) {
if (prefix.slice(0, 7) === 'egg-of_') {
prefix = 'egg-bk_' + prefix.slice(7);
}
else {
prefix = 'egg-bk_' + prefix;
}
}
return prefix;
}
/**
* Return the primary user's name
*/
static async getPrimaryUser() {
const { execSync } = require('child_process');
let primaryUser = '';
try {
// Attempt to get the user from logname
primaryUser = execSync('/usr/bin/logname 2>/dev/null', { encoding: 'utf-8' }).trim();
}
catch {
// console.log("logname failed, so we continue with other methods")
}
if (primaryUser === 'root') {
primaryUser = '';
}
if (primaryUser === '') {
try {
// Check if doas is installed and get the DOAS_USER
execSync('command -v doas', { stdio: 'ignore' });
primaryUser = execSync('echo $DOAS_USER', { encoding: 'utf-8' }).trim();
}
catch {
// console.log("doas is not installed or DOAS_USER is not set, continue with the next method")
}
}
if (primaryUser === '') {
try {
// Check for the SUDO_USER
primaryUser = execSync('echo $SUDO_USER', { encoding: 'utf-8' }).trim();
}
catch {
// console.log("SUDO_USER is not set, continue with the next method")
}
}
if (primaryUser === '') {
// console.log("Fallback to the USER environment variable")
primaryUser = process.env.USER || '';
}
if (primaryUser === '') {
primaryUser = 'dummy';
// console.error('Cannot determine the primary user.');
// process.exit(1);
}
return primaryUser;
}
/**
* Count the eggs present in the nest
* @returns {number} Numero degli snapshot presenti
*/
static getSnapshotCount(snapshot_dir = '/') {
if (fs.existsSync(snapshot_dir)) {
const files = fs.readdirSync(snapshot_dir);
let nIsos = 0;
for (const f of files) {
if (f.endsWith('.iso')) {
nIsos++;
}
}
return nIsos;
}
return 0;
}
/**
* Get the syze of the snapshot
* @returns {string} grandezza dello snapshot in Byte
*/
static getSnapshotSize(snapshot_dir = '/') {
let fileSizeInBytes = 0;
const size = shx.exec(`/usr/bin/find ${snapshot_dir} -maxdepth 1 -type f -name '*.iso' -exec du -sc {} + | tail -1 | awk '{print $1}'`, { silent: true }).stdout.trim();
if (size === '') {
fileSizeInBytes = 0;
}
else {
fileSizeInBytes = Number(size);
}
return fileSizeInBytes;
}
/**
* Calculate the space used on the disk
* @returns {void}
*/
static getUsedSpace() {
let fileSizeInBytes = 0;
if (this.isLive()) {
fileSizeInBytes = 0; // this.getLiveRootSpace()
}
else {
fileSizeInBytes = Number(shx.exec(`df /home | /usr/bin/awk 'NR==2 {print $3}'`, {
silent: true
}).stdout);
}
return fileSizeInBytes;
}
/**
* return the name of network device
*/
static async iface() {
// return shx.exec(`ifconfig | awk 'FNR==1 { print $1 }' | tr --d :`, { silent: true }).stdout.trim()
const interfaces = Object.keys(os.networkInterfaces());
let netDeviceName = '';
for (const k in interfaces) {
if (interfaces[k] != 'lo') {
netDeviceName = interfaces[k];
}
}
return netDeviceName;
}
static info(msg = '') {
console.log(pjson.shortName + ' >>> ' + chalk.white(msg));
}
/**
* @deprecated Use Kernel.initramfs() instead
*/
static initrdImg(kernel = '') {
return Kernel.initramfs(kernel);
}
/**
* isAppImage
*/
static isAppImage() {
return Boolean(process.env.APPIMAGE) ||
process.execPath.includes('.AppImage') ||
process.execPath.includes('/tmp/.mount_');
}
/**
*
* @param device
* @returns
*/
static isBlockDevice(device = '') {
const cmd = `lsblk -d -o name | grep ${device}`;
const result = shx.exec(cmd, { silent: true }).code;
return result === 0;
}
/**
* Detect if running inside a standard chroot environment
* (Distinguishes chroot from Containers/Host)
*/
static isChroot() {
try {
// 1. Check for Debian specific chroot file
// Many Debian tools (debootstrap, schroot) create this file.
if (fs.existsSync('/etc/debian_chroot')) {
return true;
}
// 2. Inode comparison method
// We compare the Inode and Device ID of '/' vs '/proc/1/root'.
// In a chroot (sharing the host's PID namespace via bind-mounted /proc),
// PID 1 refers to the host's init process.
// Therefore, if '/' is NOT the same file as '/proc/1/root', we are in a chroot.
const rootStat = fs.statSync('/');
const procRootStat = fs.statSync('/proc/1/root');
// If dev or ino are different, we are inside a chroot
return (rootStat.dev !== procRootStat.dev) || (rootStat.ino !== procRootStat.ino);
}
catch {
// If /proc is not mounted or not accessible, detection via inode fails.
// However, usually in eggs /proc is mounted.
// If strictly needed, one could assume that if /proc/1/root is unreadable
// but / exists, it might be a weird chroot state, but returning false is safer.
return false;
}
}
/**
* Detect if running inside a container (Docker or LXC)
*/
static isContainer() {
// Check for Docker's specific file
if (fs.existsSync('/.dockerenv')) {
return true;
}
// Check the cgroup file, which works for Docker, Podman, LXC, etc.
try {
const cgroupContent = fs.readFileSync('/proc/1/cgroup', 'utf8');
return cgroupContent.includes('/docker/') || cgroupContent.includes('/kubepods/');
}
catch {
return false;
}
}
/**
* Return true if i686 architecture
* @remarks to move in Utils
* @returns {boolean} true se l'architettura è i686
*/
static isi686() {
return process.arch === 'ia32';
}
/**
* Return true if live system
* @returns {boolean} isLive
*/
static isLive() {
let retVal = false;
const paths = [
'/lib/live/mount', // debian-live
'/run/live/rootfs/filesystem.squashfs', // debian trixie
'/lib/live/mount/rootfs/filesystem.squashfs', // ubuntu bionic
'/live/aufs', // mx-linux
'/media/root-rw', // AlpineLinux
'/run/archiso/airootfs', // Arch
'/run/miso/sfs/livefs', // Manjarolinux
'/run/rootfsbase' // Fedora
];
for (const path_ of paths) {
if (Utils.isMountpoint(path_)) {
retVal = true;
}
}
return retVal;
}
/**
* Ritorna vero se path è un mountpoint
* @param path
*/
static isMountpoint(path = '') {
const cmd = `mountpoint -q ${path}`;
// return 0 if the directory is a mountpoint, non-zero if not.
const result = shx.exec(cmd, { silent: true }).code;
return result === 0;
}
/**
* Controlla se è un pacchetto npm
*/
static isNpmPackage() {
return !(this.isPackage() || this.isSources());
}
/**
* Check if the system uses OpenRC
*/
static isOpenRc() {
let isOpenRc = false;
if (!this.isContainer()) {
isOpenRc = Utils.commandExists('openrc');
}
return isOpenRc;
}
/**
* Controlla se è un pacchetto deb
* /usr/lib/penguins-eggs/bin/node
*/
static isPackage() {
let ret = false;
// if (process.execPath !== '/usr/bin/node') {
if (process.execPath === '/usr/lib/penguins-eggs/bin/node') {
ret = true;
}
return ret;
}
/**
* return true if eggs run as root
* @returns isRoot
*/
static isRoot(command = '') {
if (process.getuid && process.getuid() === 0) {
return true;
}
return false;
}
/**
* Controlla se è un pacchetto sorgente
*/
static isSources() {
let ret = false;
if (__dirname.slice(0, 6) === '/home/') {
ret = true;
}
return ret;
}
/**
* Check if the system uses Systemd
*/
static isSystemd() {
let isSystemd = false;
if (this.isContainer()) {
isSystemd = true;
const distro = new Distro();
if (distro.distroId === "Devuan") {
isSystemd = false;
}
}
else {
isSystemd = fs.readFileSync("/proc/1/comm").includes('systemd');
}
return isSystemd;
}
/**
* Check if the system uses SysVinit
*/
static isSysvinit() {
let isSysvinit = false;
if (this.isContainer()) {
const distro = new Distro();
if (distro.distroId === "Devuan") {
isSysvinit = true;
}
}
else {
isSysvinit = fs.readFileSync("/proc/1/comm").includes('init');
}
return isSysvinit;
}
/**
* get the kernel version
*/
static kernelVersion() {
return os.release();
}
/**
* Usata da pacman e config credo non serva affatto
*/
static machineId() {
let result = '';
if (fs.existsSync('/etc/machine-id')) {
result = fs.readFileSync('/etc/machine-id', 'utf8').trim();
}
else if (fs.existsSync('/var/lib/dbus/machine-id')) {
result = fs.readFileSync('/var/lib/dbus/machine-id', 'utf8').trim();
}
return result;
}
/**
* netmask
*/
static netmask() {
const interfaces = os.networkInterfaces();
let netmask = '';
if (interfaces !== undefined) {
for (const devName in interfaces) {
const iface = interfaces[devName];
if (iface !== undefined) {
for (const alias of iface) {
if (alias.family === 'IPv4' &&
alias.address !== '127.0.0.1' &&
!alias.internal
&& // take just the first!
netmask === '') {
netmask = alias.netmask;
}
}
}
}
}
return netmask;
}
/**
*
*/
static async pressKeyToExit(warning = 'Process will end', procContinue = true) {
Utils.warning(warning);
let msg = 'Press a key to exit...';
if (procContinue) {
msg = 'Press a key to continue...';
}
console.log(msg);
const pressKeyToExit = spawnSync('read _ ', [], { shell: true, stdio: [0, 1, 2] });
if (!procContinue) {
process.exit(0);
}
}
/**
*
*/
static rootPenguin() {
return path.resolve(__dirname, '../../');
}
/**
*
* @param file
* @param search
* @returns value
*/
static searchOnFile(file = '', search = '') {
const lines = fs.readFileSync(file, 'utf8').split("\n");
let value = '';
for (let line of lines) {
line = line.replaceAll(/\s+/g, ' '); // Remove multiple spaces with single space
if (line.includes(search)) {
value = line.slice(Math.max(0, line.indexOf('=') + 1));
}
}
value = value.replaceAll('"', ''); // Remove "
return value.trim();
}
/**
*
* @param verbose
*/
static setEcho(verbose = false) {
let echo = { echo: false, ignore: true };
if (verbose) {
echo = { echo: true, ignore: false };
}
return echo;
}
/* Funzione helper che crea una pausa non bloccante.
* @param ms Millisecondi da attendere
*/
static sleep(ms = 60_000) {
// console.log('wait...')
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Restituisce il prefisso della iso
* @param distroId
* @param codenameId
*/
static snapshotPrefix(distroId, codenameId) {
let result = `egg-of_${distroId.toLowerCase()}-`;
if (codenameId === 'rolling' || codenameId === '') {
const releaseId = Utils.getOsRelease().VERSION_ID.trim();
if (releaseId !== '') {
result += releaseId;
}
}
else {
result += `${codenameId.toLowerCase()}`;
}
if (!result.endsWith('-')) {
result += '-';
}
return result;
}
/**
* Custom function to sort object keys
* @param obj
* @returns
*/
static sortObjectKeys(obj) {
const sorted = {};
for (const key of Object.keys(obj)
.sort()) {
sorted[key] = obj[key];
}
return sorted;
}
static success(msg = '') {
console.log(pjson.shortName + ' >>> ' + chalk.greenBright(msg));
}
/**
* titles
* Penguin's are gettings alive!
*/
static titles(command = '') {
console.clear();
console.log('');
console.log(' E G G S: the reproductive system of penguins');
console.log('');
console.log(Utils.flag());
console.log('command: ' + chalk.bgBlack.white(command) + '\n');
}
/**
* uefiArch
* @returns arch
*/
static uefiArch() {
let arch = '';
switch (process.arch) {
case 'arm64': {
arch = 'arm64';
break;
}
case 'ia32': {
arch = 'i386';
//
if (shx.exec('uname -m', { silent: true }).stdout.trim() === 'x86_64') {
arch = 'amd64';
}
break;
}
case 'riscv64': {
arch = 'riscv64';
break;
}
case 'x64': {
arch = 'amd64';
break;
}
// No default
}
return arch;
}
/**
* i386-pc,
* i386-efi,
* x86_64-efi,
* arm64-efi,
*
* ATTEMZIONE: install efibootmgr
*
* Fedora/RHEL have i386-pc
*/
static uefiFormat() {
let format = '';
switch (process.arch) {
case 'arm64': {
format = 'arm64-efi';
break;
}
case 'ia32': {
format = 'i386-efi';
if (shx.exec('uname -m', { silent: true }).stdout.trim() === 'x86_64') {
format = 'x86_64-efi';
}
break;
}
case 'riscv64': {
format = 'riscv64-efi';
break;
}
case 'x64': {
format = 'x86_64-efi';
break;
}
// No default
}
return format;
}
/**
*
* @param command
*/
static useRoot(command = '') {
Utils.titles(pjson.shortName + ' ' + command + ` need to run with root privileges. Please, prefix it with sudo`);
}
/**
*
* @returns
*/
static usrLibPath() {
let path = '';
if (process.arch === 'x64') {
path = 'x86_64-linux-gnu';
}
else if (process.arch === 'arm64') {
path = 'aarch64-linux-gnu';
}
return path;
}
/**
* restituisce uuid
* @param device
*/
static uuid(device) {
const uuid = shx.exec(`blkid -p -s UUID -o value ${device}`, { silent: true }).stdout.trim();
return uuid;
}
/**
*
* @param device
* @returns
*/
static uuidGen() {
const uuid = shx.exec(`uuidgen`, { silent: true }).stdout.trim();
return uuid;
}
static vmlinuz(kernel = '') {
return Kernel.vmlinuz(kernel);
}
/**
*
* @param volid
*/
static VolidTrim(volid = 'unknown') {
// // 28 + 4 .iso = 32 lunghezza max di volid
if (volid.length >= 32) {
volid = volid.slice(0, 32);
}
return volid;
}
/**
*
* @returns wardrobe
*/
static async wardrobe() {
let wardrobe = `${os.homedir()}/.wardrobe`;
if (Utils.isRoot()) {
wardrobe = `/home/${await Utils.getPrimaryUser()}/.wardrobe`;
}
return wardrobe;
}
/**
*
* @param msg
*/
static warning(msg = '') {
console.log(pjson.shortName + ' >>> ' + chalk.cyanBright(msg));
}
/**
* write a file
* @param file
* @param text
*/
static write(file, text) {
text = text.trim() + '\n';
file = file.trim();
fs.writeFileSync(file, text);
}
/**
*
* @param file
* @param cmd
*/
static writeX(file, cmd) {
let text = `#!/bin/sh\n\n`;
text += `# Created at: ${Utils.formatDate(new Date())}\n`;
text += `# By: penguins_eggs v. ${Utils.getPackageVersion()}\n`;
text += `# ==> Perri\'s Brewery edition <== \n\n`;
text += cmd;
Utils.write(file, text);
shx.chmod('+x', file);
}
/**
*
* @param file
* @param cmd
*/
static writeXs(file, cmds) {
let cmd = '';
for (const elem of cmds) {
cmd += elem + '\n';
}
Utils.writeX(file, cmd);
}
}