penguins-eggs
Version:
A remaster system tool, compatible with Almalinux, Alpine, Arch, Debian, Devuan, Fedora, Manjaro, Opensuse, Ubuntu and derivatives
169 lines (168 loc) • 6.81 kB
JavaScript
/**
* penguins-eggs
* Kernel management utilities
*/
import fs from 'node:fs';
import path from 'path';
import { execSync } from '../../lib/utils.js';
import Utils from '../utils.js';
export default class Kernel {
/**
* Cerca initramfs
*/
static initramfs(kernel = '') {
let targetKernel = kernel;
if (targetKernel === '') {
if (Utils.isContainer() && !Utils.isChroot()) {
Utils.warning('Non è possibile determinare il kernel in un container.');
process.exit(1);
}
targetKernel = (execSync('uname -r', { stdio: 'ignore' }) || '').trim();
}
const kernelVersionShort = targetKernel.split('.').slice(0, 2).join('.');
const bootDir = '/boot';
let bootFiles;
try {
bootFiles = fs.readdirSync(bootDir);
}
catch {
console.error(`ERRORE: Impossibile leggere la directory ${bootDir}.`);
process.exit(1);
}
const candidates = [];
for (const filename of bootFiles) {
if ((filename.startsWith('initramfs-') || filename.startsWith('initrd.img-') || filename.startsWith('initrd-')) && (filename.includes(targetKernel) || filename.includes(kernelVersionShort))) {
candidates.push(filename);
}
}
if (candidates.length > 0) {
let foundPath = path.join(bootDir, candidates[0]);
if (candidates.length > 1) {
const nonFallbackCandidates = candidates.filter((c) => !c.includes('-fallback'));
const searchArray = nonFallbackCandidates.length > 0 ? nonFallbackCandidates : candidates;
foundPath = path.join(bootDir, searchArray[0]);
for (const candidate of searchArray) {
const current = path.join(bootDir, candidate);
if (current.length < foundPath.length) {
foundPath = current;
}
}
}
return foundPath;
}
// Fallbacks
const staticFallbacks = ['initramfs-lts', 'initramfs-virt', 'initramfs-standard', 'initramfs-rpi', 'initramfs-linux.img', 'initramfs-linux-lts.img', 'initramfs-linux-zen.img', 'initramfs-linux-hardened.img', 'initramfs-linux-cachyos.img', 'initramfs-linux-cachyos-lts.img'];
for (const fallback of staticFallbacks) {
const fallbackPath = path.join(bootDir, fallback);
if (fs.existsSync(fallbackPath)) {
return fallbackPath;
}
}
Utils.warning(`Could not find an initramfs file for kernel ${targetKernel} in ${bootDir}.`);
process.exit(1);
}
/**
* Ricava path per vmlinuz (o vmlinux su RISC-V)
*/
static vmlinuz(kernel = '') {
let kernelFile = '';
// Esegui se NON è un container
if (Utils.isContainer()) {
Utils.warning('cannot work on containers actually!');
process.exit(1);
}
else {
kernelFile = this.vmlinuzFromUname();
if (kernelFile === '') {
kernelFile = this.vmlinuzFromCmdline();
if (kernelFile === '') {
console.log('kernel (vmlinuz/vmlinux) not found');
process.exit(1);
}
}
}
if (!fs.existsSync(kernelFile)) {
console.log(`kernel: ${kernelFile} does not exist!`);
process.exit(1);
}
return kernelFile;
}
/**
* PRIVATE METHODS
*/
static vmlinuzFromCmdline() {
let kernelFile = '';
// ... (Logica esistente invariata) ...
try {
const cmdline = fs.readFileSync('/proc/cmdline', 'utf8').split(' ');
for (const cmd of cmdline) {
if (cmd.includes('BOOT_IMAGE')) {
kernelFile = cmd.slice(Math.max(0, cmd.indexOf('=') + 1));
if (kernelFile.includes(')')) {
kernelFile = cmd.slice(Math.max(0, cmd.indexOf(')') + 1));
}
if (!fs.existsSync(kernelFile) && fs.existsSync(`/boot/${kernelFile}`)) {
kernelFile = `/boot/${kernelFile}`;
}
}
}
if (kernelFile.includes('@')) {
const subvolumeEnd = kernelFile.indexOf('/', kernelFile.indexOf('@'));
kernelFile = kernelFile.slice(Math.max(0, subvolumeEnd));
}
if (path.dirname(kernelFile) === '/' && fs.existsSync(`/boot${kernelFile}`)) {
kernelFile = `/boot${kernelFile}`;
}
}
catch {
/* ignore read error */
}
return kernelFile;
}
static vmlinuzFromUname() {
const kernelVersion = (execSync('uname -r', { stdio: 'ignore' }) || '').trim();
// --- CHECK FOR RISC-V (vmlinux) ---
if (process.arch === 'riscv64') {
// 1. Caso Perfetto: uname corrisponde al file vmlinux
const riscvPath = `/boot/vmlinux-${kernelVersion}`;
if (fs.existsSync(riscvPath)) {
return riscvPath;
}
// 2. Caso "Ciambella di Salvataggio": uname non trova file esatto?
// Scansioniamo la cartella per trovare QUALSIASI vmlinux disponibile.
try {
const files = fs.readdirSync('/boot');
const found = files.find((file) => file.startsWith('vmlinux-'));
if (found) {
return path.join('/boot', found);
}
}
catch (error) {
console.error('Errore leggendo /boot:', error);
}
// 3. Fallback su vmlinuz (se usassero kernel compressi)
const riscvZPath = `/boot/vmlinuz-${kernelVersion}`;
if (fs.existsSync(riscvZPath)) {
return riscvZPath;
}
}
// --- STANDARD ARCHITECTURES (x86, ARM) ---
const standardPath = `/boot/vmlinuz-${kernelVersion}`;
if (fs.existsSync(standardPath)) {
return standardPath;
}
// Arch Linux specifics
let archPath = '';
if (kernelVersion.includes('-lts'))
archPath = `/boot/vmlinuz-linux-lts`;
else if (kernelVersion.includes('-zen'))
archPath = `/boot/vmlinuz-linux-zen`;
else if (kernelVersion.includes('-hardened'))
archPath = `/boot/vmlinuz-linux-hardened`;
else if (kernelVersion.includes('-arch'))
archPath = `/boot/vmlinuz-linux`;
if (archPath && fs.existsSync(archPath))
return archPath;
return '';
}
}