RaveOS-Gnome/releng/airootfs/usr/share/gnome-shell/extensions/customreboot@nova1545/systemdBoot.js
2025-03-15 15:27:53 +01:00

121 lines
3.1 KiB
JavaScript

import Gio from "gi://Gio";
import { ExecCommand, Log, LogWarning } from './utils.js';
/**
* Represents Systemdboot
*/
export class SystemdBoot {
/**
* Get's all available boot options
* @returns {[Map, string]} Map(title, id), defaultOption
*/
static async GetBootOptions() {
let bootctl = await this.GetBinary();
if (bootctl == "") {
Log(`Failed to find bootctl binary`);
return undefined;
}
try {
let [status, stdout, stderr] = await ExecCommand([bootctl, "list"]);
if (status !== 0)
throw new Error(`Failed to get list from bootctl: ${status}\n${stdout}\n${stderr}`);
Log(`bootctl list: ${status}\n${stdout}\n${stderr}`);
let lines = String(stdout).split('\n');
let titleRx = /(?<=title:\s+).+/;
let idRx = /(?<=id:\s+).+/;
let defaultRx = /\(default\)/;
let titles = [];
let ids = []
let defaultOpt;
lines.forEach(l => {
let title = titleRx.exec(l);
let id = idRx.exec(l);
if (title && title.length) {
titles.push(String(title));
} else if (id && id.length) {
ids.push(String(id));
}
});
if (titles.length !== ids.length)
throw new Error("Number of titles and ids do not match!");
let bootOptions = new Map();
for (let i = 0; i < titles.length; i++) {
bootOptions.set(titles[i], ids[i])
}
bootOptions.forEach((id, title) => {
Log(`${id} = ${title}`);
let defaultRes = defaultRx.exec(title);
if (defaultRes) {
defaultOpt = title;
}
})
return [bootOptions, bootOptions.get(defaultOpt)];
} catch (e) {
LogWarning(e);
return undefined;
}
}
/**
* Set's the next boot option
* @param {string} id
* @returns True if the boot option was set, otherwise false
*/
static async SetBootOption(id) {
if (!this.IsUseable()) return false;
const [status, stdout, stderr] = await ExecCommand(['/usr/bin/pkexec', '/usr/bin/bootctl', 'set-oneshot', id],);
if (status === 0) {
Log(`Set boot option to ${id}`);
return true;
}
LogWarning("Unable to set boot option using bootctl");
return false;
}
/**
* Can we use this bootloader?
* @returns True if useable otherwise false
*/
static async IsUseable() {
return await this.GetBinary() !== "";
}
/**
* Get's bootctl binary path
* @returns A string containing the location of the binary, if none is found returns a blank string
*/
static async GetBinary() {
let paths = ["/usr/sbin/bootctl", "/usr/bin/bootctl"];
let file;
for (let i = 0; i < paths.length; i++) {
file = Gio.file_new_for_path(paths[i]);
if (file.query_exists(null)) {
return paths[i];
}
}
return "";
}
/**
* This boot loader cannot be quick rebooted
*/
static async CanQuickReboot() {
return false;
}
/**
* This boot loader cannot be quick rebooted
*/
static async QuickRebootEnabled() {
return false;
}
}