penguins-eggs 25.11.29 → 25.12.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oclif.manifest.json +1 -1
- package/README.md +118 -127
- package/README.pdf +10950 -11893
- package/addons/eggs/theme/livecd/simple.grub.main.cfg +3 -3
- package/conf/derivatives.yaml +2 -1
- package/conf/distros/buster/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/focal/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/noble/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/noble/calamares/libexec/calamares-l10n-helper.sh +2 -1
- package/conf/distros/noble/calamares/settings.yml +1 -0
- package/conf/distros/trixie/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/exclude.list.d/var.list +11 -6
- package/dist/appimage/dependency-manager.js +1 -1
- package/dist/classes/cli-autologin.d.ts +37 -4
- package/dist/classes/cli-autologin.js +153 -115
- package/dist/classes/compressors.d.ts +7 -10
- package/dist/classes/compressors.js +44 -31
- package/dist/classes/daddy.js +4 -1
- package/dist/classes/distro.js +2 -2
- package/dist/classes/diversions.js +2 -3
- package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +3 -5
- package/dist/classes/incubation/fisherman-helper/initcpio.js +28 -20
- package/dist/classes/incubation/fisherman-helper/settings.js +1 -1
- package/dist/classes/incubation/fisherman.js +1 -1
- package/dist/classes/incubation/incubator.d/manjaro.js +1 -0
- package/dist/classes/incubation/incubator.js +1 -1
- package/dist/classes/ovary.d/create-xdg-autostart.js +1 -1
- package/dist/classes/ovary.d/edit-live-fs.d.ts +2 -13
- package/dist/classes/ovary.d/edit-live-fs.js +33 -146
- package/dist/classes/ovary.d/fertilization.js +1 -1
- package/dist/classes/ovary.d/luks-home.js +33 -19
- package/dist/classes/ovary.d/luks-root.d.ts +1 -2
- package/dist/classes/ovary.d/luks-root.js +46 -27
- package/dist/classes/ovary.d/luks-shrink.d.ts +14 -0
- package/dist/classes/ovary.d/luks-shrink.js +86 -0
- package/dist/classes/ovary.d/make-dot-disk.js +1 -1
- package/dist/classes/ovary.d/produce.js +64 -22
- package/dist/classes/ovary.d/user-create-live.d.ts +4 -10
- package/dist/classes/ovary.d/user-create-live.js +82 -84
- package/dist/classes/ovary.d/users-remove.d.ts +5 -6
- package/dist/classes/ovary.d/users-remove.js +61 -31
- package/dist/classes/ovary.d.ts +5 -3
- package/dist/classes/ovary.js +5 -3
- package/dist/classes/pacman.d/alpine.js +2 -2
- package/dist/classes/pacman.d/archlinux.js +2 -2
- package/dist/classes/pacman.d/debian.js +2 -3
- package/dist/classes/pacman.d/fedora.js +2 -3
- package/dist/classes/pacman.d/openmamba.js +2 -3
- package/dist/classes/pacman.d/opensuse.js +2 -3
- package/dist/classes/pacman.d.ts +0 -5
- package/dist/classes/pacman.js +3 -16
- package/dist/classes/pve-live.js +1 -1
- package/dist/classes/settings.js +1 -1
- package/dist/classes/sys-users.d.ts +76 -0
- package/dist/classes/sys-users.js +206 -0
- package/dist/classes/utils.d/kernel.js +3 -3
- package/dist/classes/utils.d.ts +15 -6
- package/dist/classes/utils.js +80 -47
- package/dist/classes/xdg.js +1 -1
- package/dist/classes/yolk.js +3 -5
- package/dist/commands/export/appimage.js +3 -3
- package/dist/commands/export/pkg.js +3 -3
- package/dist/commands/export/tarballs.js +3 -3
- package/dist/commands/krill.js +1 -1
- package/dist/commands/produce.js +14 -5
- package/dist/commands/setup/install.js +1 -1
- package/dist/commands/setup/purge.js +1 -1
- package/dist/commands/tools/yolk.js +1 -1
- package/dist/commands/update.js +1 -2
- package/dist/interfaces/calamares/i-calamares-branding.d.ts +56 -38
- package/dist/interfaces/calamares/i-calamares-branding.js +10 -0
- package/dist/interfaces/i-exec.d.ts +1 -0
- package/dist/krill/classes/prepare.d/location.js +1 -1
- package/dist/krill/classes/prepare.d/partitions.js +1 -1
- package/dist/krill/classes/prepare.d/users.js +2 -2
- package/dist/krill/classes/prepare.js +5 -5
- package/dist/krill/classes/sequence.d/add_user.d.ts +3 -15
- package/dist/krill/classes/sequence.d/add_user.js +87 -57
- package/dist/krill/classes/sequence.d/change_password.d.ts +5 -7
- package/dist/krill/classes/sequence.d/change_password.js +25 -10
- package/dist/krill/classes/sequence.d/del_live_user.d.ts +5 -7
- package/dist/krill/classes/sequence.d/del_live_user.js +39 -25
- package/dist/krill/classes/sequence.d/fstab.js +2 -2
- package/dist/krill/classes/sequence.d/grubcfg.d.ts +3 -7
- package/dist/krill/classes/sequence.d/grubcfg.js +33 -13
- package/dist/krill/classes/sequence.d/mkfs.js +2 -3
- package/dist/krill/classes/sequence.d/unpackfs.d.ts +2 -4
- package/dist/krill/classes/sequence.d/unpackfs.js +8 -5
- package/dist/krill/classes/sequence.d.ts +1 -5
- package/dist/krill/classes/sequence.js +28 -32
- package/dist/krill/components/finished.js +2 -2
- package/dist/krill/components/install.js +2 -2
- package/dist/krill/components/keyboard.js +2 -2
- package/dist/krill/components/location.js +2 -2
- package/dist/krill/components/network.js +2 -2
- package/dist/krill/components/partitions.js +2 -2
- package/dist/krill/components/summary.js +2 -2
- package/dist/krill/components/title.js +2 -2
- package/dist/krill/components/users.js +2 -2
- package/dist/krill/components/welcome.js +2 -2
- package/dist/krill/lib/select_installation_device.js +1 -1
- package/dist/krill/lib/select_replaced_partition.js +1 -1
- package/dist/lib/utils.d.ts +52 -19
- package/dist/lib/utils.js +271 -20
- package/manpages/doc/man/eggs.1.gz +0 -0
- package/manpages/doc/man/eggs.html +8 -8
- package/package.json +9 -9
- package/perrisbrewery/template/dependencies.yaml +1 -0
- package/scripts/boot-encrypted-root.sh +220 -0
- package/scripts/mount-encrypted-home.sh +324 -0
- package/scripts/restore_homecrypt_krill.sh +93 -0
- package/dracut/create-symlink +0 -71
- package/dracut/dracut-log.txt +0 -3
- package/dracut/export +0 -4
- package/dracut/export-dracut-analysis +0 -51
- package/dracut/export-dracut-log +0 -2
- package/dracut/mkisofs +0 -10
- package/dracut/renew-initramfs +0 -17
- package/dracut/sbin2bin +0 -10
- package/dracut/update-dracut-conf-d +0 -2
- package/dracut/update-dracut-modules +0 -62
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/classes/sys-users.ts
|
|
3
|
+
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
+
* * "THE SYSUSER MASTER"
|
|
5
|
+
* Gestione pura Node.js per utenti e gruppi di sistema.
|
|
6
|
+
* Sostituisce i binari (useradd/usermod/deluser) per garantire operazioni atomiche
|
|
7
|
+
* e compatibilità SELinux (Fedora/RHEL) scrivendo file puliti.
|
|
8
|
+
*/
|
|
9
|
+
export interface IPasswdEntry {
|
|
10
|
+
username: string;
|
|
11
|
+
password: string;
|
|
12
|
+
uid: string;
|
|
13
|
+
gid: string;
|
|
14
|
+
gecos: string;
|
|
15
|
+
home: string;
|
|
16
|
+
shell: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IShadowEntry {
|
|
19
|
+
username: string;
|
|
20
|
+
hash: string;
|
|
21
|
+
lastChange: string;
|
|
22
|
+
min: string;
|
|
23
|
+
max: string;
|
|
24
|
+
warn: string;
|
|
25
|
+
inactive: string;
|
|
26
|
+
expire: string;
|
|
27
|
+
}
|
|
28
|
+
export interface IGroupEntry {
|
|
29
|
+
groupName: string;
|
|
30
|
+
password: string;
|
|
31
|
+
gid: string;
|
|
32
|
+
members: string[];
|
|
33
|
+
}
|
|
34
|
+
export default class SysUsers {
|
|
35
|
+
private targetRoot;
|
|
36
|
+
private distroFamily;
|
|
37
|
+
private passwd;
|
|
38
|
+
private shadow;
|
|
39
|
+
private group;
|
|
40
|
+
private gshadowLines;
|
|
41
|
+
private subuidLines;
|
|
42
|
+
private subgidLines;
|
|
43
|
+
constructor(targetRoot: string, distroFamily: string);
|
|
44
|
+
/**
|
|
45
|
+
* Carica tutti i file di configurazione in memoria
|
|
46
|
+
*/
|
|
47
|
+
load(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Salva lo stato della memoria su disco e applica SELinux fix
|
|
50
|
+
*/
|
|
51
|
+
save(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Crea un nuovo utente completo
|
|
54
|
+
*/
|
|
55
|
+
addUser(user: IPasswdEntry, cleanPassword: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Rimuove completamente un utente
|
|
58
|
+
*/
|
|
59
|
+
removeUser(username: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Aggiunge utente a un gruppo supplementare
|
|
62
|
+
*/
|
|
63
|
+
addUserToGroup(username: string, groupName: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Cambia password utente
|
|
66
|
+
*/
|
|
67
|
+
setPassword(username: string, password: string): void;
|
|
68
|
+
private readFile;
|
|
69
|
+
private writeFile;
|
|
70
|
+
private parsePasswd;
|
|
71
|
+
private serializePasswd;
|
|
72
|
+
private parseShadow;
|
|
73
|
+
private serializeShadow;
|
|
74
|
+
private parseGroup;
|
|
75
|
+
private serializeGroup;
|
|
76
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/classes/sys-users.ts
|
|
3
|
+
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
+
* * "THE SYSUSER MASTER"
|
|
5
|
+
* Gestione pura Node.js per utenti e gruppi di sistema.
|
|
6
|
+
* Sostituisce i binari (useradd/usermod/deluser) per garantire operazioni atomiche
|
|
7
|
+
* e compatibilità SELinux (Fedora/RHEL) scrivendo file puliti.
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import * as bcrypt from 'bcryptjs';
|
|
12
|
+
import { exec } from '../lib/utils.js';
|
|
13
|
+
export default class SysUsers {
|
|
14
|
+
targetRoot;
|
|
15
|
+
distroFamily;
|
|
16
|
+
// Cache in memoria
|
|
17
|
+
passwd = [];
|
|
18
|
+
shadow = [];
|
|
19
|
+
group = [];
|
|
20
|
+
// File "minori" gestiti a righe raw per semplicità
|
|
21
|
+
gshadowLines = [];
|
|
22
|
+
subuidLines = [];
|
|
23
|
+
subgidLines = [];
|
|
24
|
+
constructor(targetRoot, distroFamily) {
|
|
25
|
+
this.targetRoot = targetRoot;
|
|
26
|
+
this.distroFamily = distroFamily;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Carica tutti i file di configurazione in memoria
|
|
30
|
+
*/
|
|
31
|
+
load() {
|
|
32
|
+
this.passwd = this.parsePasswd(this.readFile('etc/passwd'));
|
|
33
|
+
this.shadow = this.parseShadow(this.readFile('etc/shadow'));
|
|
34
|
+
this.group = this.parseGroup(this.readFile('etc/group'));
|
|
35
|
+
this.gshadowLines = this.readFile('etc/gshadow');
|
|
36
|
+
this.subuidLines = this.readFile('etc/subuid');
|
|
37
|
+
this.subgidLines = this.readFile('etc/subgid');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Salva lo stato della memoria su disco e applica SELinux fix
|
|
41
|
+
*/
|
|
42
|
+
async save() {
|
|
43
|
+
// Serializzazione
|
|
44
|
+
const passwdContent = this.serializePasswd(this.passwd);
|
|
45
|
+
const shadowContent = this.serializeShadow(this.shadow);
|
|
46
|
+
const groupContent = this.serializeGroup(this.group);
|
|
47
|
+
// Scrittura Atomica + Fix SELinux
|
|
48
|
+
await this.writeFile('etc/passwd', passwdContent, 'passwd_file_t');
|
|
49
|
+
await this.writeFile('etc/shadow', shadowContent, 'shadow_t');
|
|
50
|
+
await this.writeFile('etc/group', groupContent, 'passwd_file_t');
|
|
51
|
+
// File raw
|
|
52
|
+
if (this.gshadowLines.length > 0)
|
|
53
|
+
await this.writeFile('etc/gshadow', this.gshadowLines.join('\n'), 'shadow_t');
|
|
54
|
+
if (this.subuidLines.length > 0)
|
|
55
|
+
await this.writeFile('etc/subuid', this.subuidLines.join('\n'), 'passwd_file_t');
|
|
56
|
+
if (this.subgidLines.length > 0)
|
|
57
|
+
await this.writeFile('etc/subgid', this.subgidLines.join('\n'), 'passwd_file_t');
|
|
58
|
+
}
|
|
59
|
+
// =========================================================================
|
|
60
|
+
// API PUBBLICA
|
|
61
|
+
// =========================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Crea un nuovo utente completo
|
|
64
|
+
*/
|
|
65
|
+
addUser(user, cleanPassword) {
|
|
66
|
+
// Rimuovi se esiste (idempotenza)
|
|
67
|
+
this.removeUser(user.username);
|
|
68
|
+
// 1. Passwd
|
|
69
|
+
this.passwd.push(user);
|
|
70
|
+
// 2. Shadow (Hash Password)
|
|
71
|
+
const salt = bcrypt.genSaltSync(10);
|
|
72
|
+
const hash = bcrypt.hashSync(cleanPassword, salt);
|
|
73
|
+
this.shadow.push({
|
|
74
|
+
username: user.username,
|
|
75
|
+
hash: hash,
|
|
76
|
+
lastChange: '19700', // Data approssimativa
|
|
77
|
+
min: '0',
|
|
78
|
+
max: '99999',
|
|
79
|
+
warn: '7',
|
|
80
|
+
inactive: '',
|
|
81
|
+
expire: ''
|
|
82
|
+
});
|
|
83
|
+
// 3. Gruppo Primario
|
|
84
|
+
// Solo se non esiste già un gruppo con quel nome
|
|
85
|
+
if (!this.group.find(g => g.groupName === user.username)) {
|
|
86
|
+
this.group.push({
|
|
87
|
+
groupName: user.username,
|
|
88
|
+
password: 'x',
|
|
89
|
+
gid: user.gid,
|
|
90
|
+
members: []
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// 4. GShadow (placeholder)
|
|
94
|
+
this.gshadowLines.push(`${user.username}:!::`);
|
|
95
|
+
// 5. SubUID/SubGID (Podman rootless)
|
|
96
|
+
// Calcolo offset standard: 100000 + (UID-1000)*65536
|
|
97
|
+
const uidNum = parseInt(user.uid);
|
|
98
|
+
if (!isNaN(uidNum) && uidNum >= 1000) {
|
|
99
|
+
const startUid = 100000 + (uidNum - 1000) * 65536;
|
|
100
|
+
const subEntry = `${user.username}:${startUid}:65536`;
|
|
101
|
+
this.subuidLines.push(subEntry);
|
|
102
|
+
this.subgidLines.push(subEntry);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Rimuove completamente un utente
|
|
107
|
+
*/
|
|
108
|
+
removeUser(username) {
|
|
109
|
+
this.passwd = this.passwd.filter(u => u.username !== username);
|
|
110
|
+
this.shadow = this.shadow.filter(s => s.username !== username);
|
|
111
|
+
this.group = this.group.filter(g => g.groupName !== username);
|
|
112
|
+
// Rimuovi dai membri di altri gruppi
|
|
113
|
+
this.group.forEach(g => {
|
|
114
|
+
g.members = g.members.filter(m => m !== username);
|
|
115
|
+
});
|
|
116
|
+
this.gshadowLines = this.gshadowLines.filter(l => !l.startsWith(`${username}:`));
|
|
117
|
+
this.subuidLines = this.subuidLines.filter(l => !l.startsWith(`${username}:`));
|
|
118
|
+
this.subgidLines = this.subgidLines.filter(l => !l.startsWith(`${username}:`));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Aggiunge utente a un gruppo supplementare
|
|
122
|
+
*/
|
|
123
|
+
addUserToGroup(username, groupName) {
|
|
124
|
+
const grp = this.group.find(g => g.groupName === groupName);
|
|
125
|
+
if (grp) {
|
|
126
|
+
if (!grp.members.includes(username)) {
|
|
127
|
+
grp.members.push(username);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Se il gruppo non esiste, lo ignoriamo silenziosamente o potremmo crearlo
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Cambia password utente
|
|
134
|
+
*/
|
|
135
|
+
setPassword(username, password) {
|
|
136
|
+
const entry = this.shadow.find(s => s.username === username);
|
|
137
|
+
if (entry) {
|
|
138
|
+
const salt = bcrypt.genSaltSync(10);
|
|
139
|
+
entry.hash = bcrypt.hashSync(password, salt);
|
|
140
|
+
entry.lastChange = '19700';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// =========================================================================
|
|
144
|
+
// IMPLEMENTAZIONE FILE (Privata)
|
|
145
|
+
// =========================================================================
|
|
146
|
+
readFile(relativePath) {
|
|
147
|
+
const fullPath = path.join(this.targetRoot, relativePath);
|
|
148
|
+
if (fs.existsSync(fullPath)) {
|
|
149
|
+
return fs.readFileSync(fullPath, 'utf8').split('\n').filter(l => l.trim().length > 0);
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
async writeFile(relativePath, content, contextType) {
|
|
154
|
+
const fullPath = path.join(this.targetRoot, relativePath);
|
|
155
|
+
// Crea dir se manca (es. /etc/sudoers.d/ o simili)
|
|
156
|
+
const dir = path.dirname(fullPath);
|
|
157
|
+
if (!fs.existsSync(dir))
|
|
158
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
159
|
+
try {
|
|
160
|
+
// 1. Scrittura
|
|
161
|
+
fs.writeFileSync(fullPath, content + '\n');
|
|
162
|
+
// 2. Fix SELinux (Solo RHEL Family)
|
|
163
|
+
if (['fedora', 'rhel', 'centos', 'almalinux', 'rocky'].includes(this.distroFamily)) {
|
|
164
|
+
// await exec, echo false per non sporcare i log
|
|
165
|
+
await exec(`chcon -t ${contextType} ${fullPath}`, { echo: false }).catch(() => { });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
console.error(`SysUsers Error writing ${relativePath}:`, e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// --- PARSERS & SERIALIZERS ---
|
|
173
|
+
parsePasswd(lines) {
|
|
174
|
+
return lines.map(line => {
|
|
175
|
+
const p = line.split(':');
|
|
176
|
+
if (p.length < 7)
|
|
177
|
+
return null;
|
|
178
|
+
return { username: p[0], password: p[1], uid: p[2], gid: p[3], gecos: p[4], home: p[5], shell: p[6] };
|
|
179
|
+
}).filter((u) => u !== null);
|
|
180
|
+
}
|
|
181
|
+
serializePasswd(entries) {
|
|
182
|
+
return entries.map(u => `${u.username}:${u.password}:${u.uid}:${u.gid}:${u.gecos}:${u.home}:${u.shell}`).join('\n');
|
|
183
|
+
}
|
|
184
|
+
parseShadow(lines) {
|
|
185
|
+
return lines.map(line => {
|
|
186
|
+
const p = line.split(':');
|
|
187
|
+
if (p.length < 2)
|
|
188
|
+
return null;
|
|
189
|
+
return { username: p[0], hash: p[1], lastChange: p[2] || '', min: p[3] || '', max: p[4] || '', warn: p[5] || '', inactive: p[6] || '', expire: p[7] || '' };
|
|
190
|
+
}).filter((u) => u !== null);
|
|
191
|
+
}
|
|
192
|
+
serializeShadow(entries) {
|
|
193
|
+
return entries.map(s => `${s.username}:${s.hash}:${s.lastChange}:${s.min}:${s.max}:${s.warn}:${s.inactive}:${s.expire}:`).join('\n');
|
|
194
|
+
}
|
|
195
|
+
parseGroup(lines) {
|
|
196
|
+
return lines.map(line => {
|
|
197
|
+
const p = line.split(':');
|
|
198
|
+
if (p.length < 3)
|
|
199
|
+
return null;
|
|
200
|
+
return { groupName: p[0], password: p[1], gid: p[2], members: p[3] && p[3].trim() ? p[3].split(',') : [] };
|
|
201
|
+
}).filter((g) => g !== null);
|
|
202
|
+
}
|
|
203
|
+
serializeGroup(entries) {
|
|
204
|
+
return entries.map(g => `${g.groupName}:${g.password}:${g.gid}:${g.members.join(',')}`).join('\n');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -8,7 +8,7 @@ import fs from 'node:fs';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import Distro from '../distro.js';
|
|
10
10
|
import Utils from '../utils.js';
|
|
11
|
-
import { execSync } from '
|
|
11
|
+
import { execSync } from '../../lib/utils.js';
|
|
12
12
|
/**
|
|
13
13
|
* Kernel utilities for managing vmlinuz and initramfs paths
|
|
14
14
|
*/
|
|
@@ -55,7 +55,7 @@ export default class Kernel {
|
|
|
55
55
|
Utils.warning("Non è possibile determinare il kernel in un container.");
|
|
56
56
|
process.exit(1);
|
|
57
57
|
}
|
|
58
|
-
targetKernel = execSync('uname -r')
|
|
58
|
+
targetKernel = (execSync('uname -r', { stdio: 'ignore' }) || '').trim();
|
|
59
59
|
}
|
|
60
60
|
const kernelVersionShort = targetKernel.split('.').slice(0, 2).join('.');
|
|
61
61
|
const bootDir = '/boot';
|
|
@@ -138,7 +138,7 @@ export default class Kernel {
|
|
|
138
138
|
* debian, fedora, opensuse, rasberry
|
|
139
139
|
*/
|
|
140
140
|
static vmlinuzFromUname() {
|
|
141
|
-
let kernelVersion = execSync('uname -r')
|
|
141
|
+
let kernelVersion = (execSync('uname -r', { stdio: 'ignore' }) || '').trim();
|
|
142
142
|
// Try 1: path standard (es. Debian, Ubuntu, Fedora)
|
|
143
143
|
let standardPath = `/boot/vmlinuz-${kernelVersion}`;
|
|
144
144
|
if (fs.existsSync(standardPath)) {
|
package/dist/classes/utils.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export default class Utils {
|
|
|
62
62
|
*/
|
|
63
63
|
static isOpenRc(): boolean;
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* Usata da pacman e config credo non serva affatto
|
|
66
66
|
*/
|
|
67
67
|
static machineId(): string;
|
|
68
68
|
/**
|
|
@@ -153,11 +153,10 @@ export default class Utils {
|
|
|
153
153
|
*/
|
|
154
154
|
static getUsedSpace(): number;
|
|
155
155
|
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
*/
|
|
156
|
+
* Estimate the linuxfs dimension
|
|
157
|
+
* (Refactored to use native FS instead of dd/od)
|
|
158
|
+
* @returns {number} GB
|
|
159
|
+
*/
|
|
161
160
|
static getLiveRootSpace(type?: string): number;
|
|
162
161
|
/**
|
|
163
162
|
* Return true if i686 architecture
|
|
@@ -327,4 +326,14 @@ export default class Utils {
|
|
|
327
326
|
static wardrobe(): Promise<string>;
|
|
328
327
|
static getOsRelease(): IOsRelease;
|
|
329
328
|
static sleep(ms?: number): Promise<void>;
|
|
329
|
+
/**
|
|
330
|
+
* chpasswdPath
|
|
331
|
+
* @returns
|
|
332
|
+
*/
|
|
333
|
+
static chpasswdPath(): string;
|
|
334
|
+
/**
|
|
335
|
+
*
|
|
336
|
+
* @param cmd
|
|
337
|
+
*/
|
|
338
|
+
static commandExists(cmd: string): boolean;
|
|
330
339
|
}
|
package/dist/classes/utils.js
CHANGED
|
@@ -7,13 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Refactored Utils class - imports from modular utilities
|
|
9
9
|
*/
|
|
10
|
-
import shx from '
|
|
10
|
+
import { shx, spawnSync } from '../lib/utils.js';
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import dns from 'dns';
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import os from 'os';
|
|
15
15
|
import inquirer from 'inquirer';
|
|
16
|
-
import { execSync, spawnSync } from 'child_process';
|
|
17
16
|
import chalk from 'chalk';
|
|
18
17
|
import Kernel from './utils.d/kernel.js';
|
|
19
18
|
// libraries
|
|
@@ -155,18 +154,12 @@ export default class Utils {
|
|
|
155
154
|
static isOpenRc() {
|
|
156
155
|
let isOpenRc = false;
|
|
157
156
|
if (!this.isContainer()) {
|
|
158
|
-
|
|
159
|
-
execSync('command -v openrc');
|
|
160
|
-
isOpenRc = true;
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
isOpenRc = false;
|
|
164
|
-
}
|
|
157
|
+
isOpenRc = Utils.commandExists('openrc');
|
|
165
158
|
}
|
|
166
159
|
return isOpenRc;
|
|
167
160
|
}
|
|
168
161
|
/**
|
|
169
|
-
*
|
|
162
|
+
* Usata da pacman e config credo non serva affatto
|
|
170
163
|
*/
|
|
171
164
|
static machineId() {
|
|
172
165
|
let result = '';
|
|
@@ -245,7 +238,7 @@ export default class Utils {
|
|
|
245
238
|
* @param device
|
|
246
239
|
*/
|
|
247
240
|
static uuid(device) {
|
|
248
|
-
const uuid = shx.exec(`blkid -s UUID -o value ${device}
|
|
241
|
+
const uuid = shx.exec(`blkid -p -s UUID -o value ${device}`, { silent: true }).stdout.trim();
|
|
249
242
|
return uuid;
|
|
250
243
|
}
|
|
251
244
|
/**
|
|
@@ -436,49 +429,71 @@ export default class Utils {
|
|
|
436
429
|
return fileSizeInBytes;
|
|
437
430
|
}
|
|
438
431
|
/**
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
*/
|
|
432
|
+
* Estimate the linuxfs dimension
|
|
433
|
+
* (Refactored to use native FS instead of dd/od)
|
|
434
|
+
* @returns {number} GB
|
|
435
|
+
*/
|
|
444
436
|
static getLiveRootSpace(type = 'debian-live') {
|
|
445
437
|
let squashFs = '/run/live/medium/live/filesystem.squashfs';
|
|
446
438
|
if (type === 'mx') {
|
|
447
439
|
squashFs = '/live/boot-dev/antiX/linuxfs';
|
|
448
440
|
}
|
|
449
|
-
//
|
|
450
|
-
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
else if (compressedFs_compression_type === '4') {
|
|
464
|
-
compression_factor = 31; // xz
|
|
465
|
-
}
|
|
466
|
-
else if (compressedFs_compression_type === '5') {
|
|
467
|
-
compression_factor = 52; // lz4
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
compression_factor = 30; // anything else or linuxfs not reachable (toram), should be pretty conservative
|
|
441
|
+
// 1. Leggiamo il tipo di compressione DIRETTAMENTE dall'header del file SquashFS
|
|
442
|
+
// L'identificativo della compressione è a offset 20 (2 bytes, little endian)
|
|
443
|
+
// 1=gzip, 2=lzo, 3=lzma, 4=xz, 5=lz4, 6=zstd
|
|
444
|
+
let compressionId = 0;
|
|
445
|
+
try {
|
|
446
|
+
if (fs.existsSync(squashFs)) {
|
|
447
|
+
const fd = fs.openSync(squashFs, 'r');
|
|
448
|
+
const buffer = Buffer.alloc(2);
|
|
449
|
+
// Leggi 2 byte alla posizione 20
|
|
450
|
+
fs.readSync(fd, buffer, 0, 2, 20);
|
|
451
|
+
fs.closeSync(fd);
|
|
452
|
+
compressionId = buffer.readUInt16LE(0);
|
|
453
|
+
}
|
|
471
454
|
}
|
|
455
|
+
catch (e) {
|
|
456
|
+
console.error("Error reading squashfs header:", e);
|
|
457
|
+
}
|
|
458
|
+
// 2. Determiniamo il fattore di compressione in base all'ID letto
|
|
459
|
+
let compression_factor = 30; // Default conservative
|
|
460
|
+
switch (compressionId) {
|
|
461
|
+
case 1: // gzip
|
|
462
|
+
compression_factor = 37;
|
|
463
|
+
break;
|
|
464
|
+
case 2: // lzo
|
|
465
|
+
compression_factor = 52;
|
|
466
|
+
break;
|
|
467
|
+
case 3: // lzma
|
|
468
|
+
compression_factor = 52;
|
|
469
|
+
break;
|
|
470
|
+
case 4: // xz
|
|
471
|
+
compression_factor = 31;
|
|
472
|
+
break;
|
|
473
|
+
case 5: // lz4
|
|
474
|
+
compression_factor = 52;
|
|
475
|
+
break;
|
|
476
|
+
case 6: // zstd (aggiunto per completezza)
|
|
477
|
+
compression_factor = 37; // simile a gzip come ratio medio
|
|
478
|
+
break;
|
|
479
|
+
default:
|
|
480
|
+
compression_factor = 30;
|
|
481
|
+
}
|
|
482
|
+
// 3. Calcolo dimensione Linux FS
|
|
483
|
+
// Nota: shx.exec ritorna un oggetto, dobbiamo prendere .stdout e pulirlo
|
|
472
484
|
let rootfs_file_size = 0;
|
|
473
|
-
const
|
|
485
|
+
const dfCmdLinux = 'df /live/linux --output=used --total | /usr/bin/tail -n1';
|
|
486
|
+
const dfResultLinux = shx.exec(dfCmdLinux, { silent: true }).stdout.trim();
|
|
487
|
+
const linuxfs_used = Number(dfResultLinux) || 0; // Gestione caso NaN
|
|
488
|
+
const linuxfs_file_size = (linuxfs_used * 1024 * 100) / compression_factor;
|
|
489
|
+
// 4. Calcolo persist-root (se esiste)
|
|
474
490
|
if (fs.existsSync('/live/persist-root')) {
|
|
475
|
-
|
|
491
|
+
const dfCmdRoot = 'df /live/persist-root --output=used --total | /usr/bin/tail -n1';
|
|
492
|
+
const dfResultRoot = shx.exec(dfCmdRoot, { silent: true }).stdout.trim();
|
|
493
|
+
rootfs_file_size = (Number(dfResultRoot) || 0) * 1024;
|
|
476
494
|
}
|
|
477
495
|
let rootSpaceNeeded;
|
|
478
496
|
if (type === 'mx') {
|
|
479
|
-
/**
|
|
480
|
-
* add rootfs file size to the calculated linuxfs file size. Probaby conservative, as rootfs will likely have some overlap with linuxfs
|
|
481
|
-
*/
|
|
482
497
|
rootSpaceNeeded = linuxfs_file_size + rootfs_file_size;
|
|
483
498
|
}
|
|
484
499
|
else {
|
|
@@ -845,7 +860,7 @@ export default class Utils {
|
|
|
845
860
|
msg = 'Press a key to continue...';
|
|
846
861
|
}
|
|
847
862
|
console.log(msg);
|
|
848
|
-
const pressKeyToExit = spawnSync('read _ ', { shell: true, stdio: [0, 1, 2] });
|
|
863
|
+
const pressKeyToExit = spawnSync('read _ ', [], { shell: true, stdio: [0, 1, 2] });
|
|
849
864
|
if (!procContinue) {
|
|
850
865
|
process.exit(0);
|
|
851
866
|
}
|
|
@@ -857,7 +872,7 @@ export default class Utils {
|
|
|
857
872
|
msg = 'Press a key to continue...';
|
|
858
873
|
}
|
|
859
874
|
console.log(msg);
|
|
860
|
-
const pressKeyToExit = spawnSync('read _ ', { shell: true, stdio: [0, 1, 2] });
|
|
875
|
+
const pressKeyToExit = spawnSync('read _ ', [], { shell: true, stdio: [0, 1, 2] });
|
|
861
876
|
if (!procContinue) {
|
|
862
877
|
process.exit(0);
|
|
863
878
|
}
|
|
@@ -881,12 +896,12 @@ export default class Utils {
|
|
|
881
896
|
static flag() {
|
|
882
897
|
let type = '';
|
|
883
898
|
if (!Utils.isAppImage()) {
|
|
884
|
-
type = 'native';
|
|
899
|
+
type = ' native';
|
|
885
900
|
}
|
|
886
901
|
let title = `${pjson.name}`;
|
|
887
902
|
let green = ` ${title}`.padEnd(25, " ");
|
|
888
903
|
let white = ` Perri's brewery edition `.padEnd(25, " ");
|
|
889
|
-
let red = ` v${pjson.version}
|
|
904
|
+
let red = ` v${pjson.version}${type} `.padStart(25, " ");
|
|
890
905
|
return chalk.bgGreen.whiteBright(green) +
|
|
891
906
|
chalk.bgWhite.blue(white) +
|
|
892
907
|
chalk.bgRed.whiteBright(red);
|
|
@@ -984,4 +999,22 @@ export default class Utils {
|
|
|
984
999
|
// console.log('wait...')
|
|
985
1000
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
986
1001
|
}
|
|
1002
|
+
/**
|
|
1003
|
+
* chpasswdPath
|
|
1004
|
+
* @returns
|
|
1005
|
+
*/
|
|
1006
|
+
static chpasswdPath() {
|
|
1007
|
+
let chpasswdPath = '/usr/sbin/chpasswd';
|
|
1008
|
+
if (fs.existsSync(chpasswdPath)) {
|
|
1009
|
+
chpasswdPath = '/usr/bin/chpasswd';
|
|
1010
|
+
}
|
|
1011
|
+
return chpasswdPath;
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
*
|
|
1015
|
+
* @param cmd
|
|
1016
|
+
*/
|
|
1017
|
+
static commandExists(cmd) {
|
|
1018
|
+
return !!shx.which(cmd);
|
|
1019
|
+
}
|
|
987
1020
|
}
|
package/dist/classes/xdg.js
CHANGED
package/dist/classes/yolk.js
CHANGED
|
@@ -7,10 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import yaml from 'js-yaml';
|
|
9
9
|
import fs from 'node:fs';
|
|
10
|
-
import shx from '
|
|
11
|
-
import { exec } from '../lib/utils.js';
|
|
10
|
+
import { shx, exec } from '../lib/utils.js';
|
|
12
11
|
import Bleach from './bleach.js';
|
|
13
|
-
import Pacman from './pacman.js';
|
|
14
12
|
import Utils from './utils.js';
|
|
15
13
|
/**
|
|
16
14
|
*
|
|
@@ -31,7 +29,7 @@ export default class Yolk {
|
|
|
31
29
|
}
|
|
32
30
|
Utils.warning(`Creating yolk on ${this.yolkDir}`);
|
|
33
31
|
Utils.warning('Updating system');
|
|
34
|
-
if (!
|
|
32
|
+
if (!Utils.commandExists('dpkg-scanpackages')) {
|
|
35
33
|
Utils.warning(`I cannot find the command dpkg-scanpackages`);
|
|
36
34
|
process.exit(0);
|
|
37
35
|
}
|
|
@@ -68,7 +66,7 @@ export default class Yolk {
|
|
|
68
66
|
Utils.warning(cmd);
|
|
69
67
|
await exec(cmd, { capture: true, echo: false });
|
|
70
68
|
// Create Release date: Sat, 14 Aug 2021 07:42:00 UTC
|
|
71
|
-
const now = shx.exec('date -R -u').stdout.trim();
|
|
69
|
+
const now = shx.exec('date -R -u', { silent: true }).stdout.trim();
|
|
72
70
|
const content = `Archive: stable\nComponent: yolk\nOrigin: penguins-eggs\nArchitecture: ${Utils.uefiArch()} \nDate: ${now}\n`;
|
|
73
71
|
Utils.warning('Writing Release');
|
|
74
72
|
fs.writeFileSync('Release', content);
|
|
@@ -10,7 +10,7 @@ import Tools from '../../classes/tools.js';
|
|
|
10
10
|
import Utils from '../../classes/utils.js';
|
|
11
11
|
import { exec } from '../../lib/utils.js';
|
|
12
12
|
import os from 'node:os';
|
|
13
|
-
import { execSync } from '
|
|
13
|
+
import { execSync } from '../../lib/utils.js';
|
|
14
14
|
export default class ExportAppimage extends Command {
|
|
15
15
|
static description = 'export penguins-eggs AppImage to the destination host';
|
|
16
16
|
static examples = ['eggs export pkg', 'eggs export pkg --clean', 'eggs export pkg --all'];
|
|
@@ -34,9 +34,9 @@ export default class ExportAppimage extends Command {
|
|
|
34
34
|
// Ora servono in più parti
|
|
35
35
|
this.user = os.userInfo().username;
|
|
36
36
|
if (this.user === 'root') {
|
|
37
|
-
this.user = execSync('echo $
|
|
37
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
38
38
|
if (this.user === '') {
|
|
39
|
-
this.user = execSync('echo $DOAS_USER'
|
|
39
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
this.clean = flags.clean;
|
|
@@ -12,7 +12,7 @@ import Tools from '../../classes/tools.js';
|
|
|
12
12
|
import Utils from '../../classes/utils.js';
|
|
13
13
|
import { exec } from '../../lib/utils.js';
|
|
14
14
|
import os from 'node:os';
|
|
15
|
-
import { execSync } from '
|
|
15
|
+
import { execSync } from '../../lib/utils.js';
|
|
16
16
|
export default class ExportPkg extends Command {
|
|
17
17
|
static description = 'export penguins-eggs package to the destination host';
|
|
18
18
|
static examples = ['eggs export pkg', 'eggs export pkg --clean', 'eggs export pkg --all'];
|
|
@@ -38,9 +38,9 @@ export default class ExportPkg extends Command {
|
|
|
38
38
|
// Ora servono in più parti
|
|
39
39
|
this.user = os.userInfo().username;
|
|
40
40
|
if (this.user === 'root') {
|
|
41
|
-
this.user = execSync('echo $
|
|
41
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
42
42
|
if (this.user === '') {
|
|
43
|
-
this.user = execSync('echo $DOAS_USER'
|
|
43
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
this.all = flags.all;
|
|
@@ -16,7 +16,7 @@ import path from 'path';
|
|
|
16
16
|
import { createRequire } from 'module';
|
|
17
17
|
const require = createRequire(import.meta.url);
|
|
18
18
|
const pjson = require('../../../package.json');
|
|
19
|
-
import { execSync } from '
|
|
19
|
+
import { execSync } from '../../lib/utils.js';
|
|
20
20
|
export default class ExportTarballs extends Command {
|
|
21
21
|
static description = 'export pkg/iso/tarballs to the destination host';
|
|
22
22
|
static examples = ['eggs export tarballs', 'eggs export tarballs --clean'];
|
|
@@ -40,9 +40,9 @@ export default class ExportTarballs extends Command {
|
|
|
40
40
|
// Ora servono in più parti
|
|
41
41
|
this.user = os.userInfo().username;
|
|
42
42
|
if (this.user === 'root') {
|
|
43
|
-
this.user = execSync('echo $
|
|
43
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
44
44
|
if (this.user === '') {
|
|
45
|
-
this.user = execSync('echo $DOAS_USER'
|
|
45
|
+
this.user = (execSync('echo $DOAS_USER') || '').trim();
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
this.clean = flags.clean;
|
package/dist/commands/krill.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Command, Flags } from '@oclif/core';
|
|
|
9
9
|
import yaml from 'js-yaml';
|
|
10
10
|
import fs from 'node:fs';
|
|
11
11
|
import https from 'node:https';
|
|
12
|
-
import shx from '
|
|
12
|
+
import { shx } from '../lib/utils.js';
|
|
13
13
|
import Utils from '../classes/utils.js';
|
|
14
14
|
import Krill from '../krill/classes/prepare.js';
|
|
15
15
|
const agent = new https.Agent({
|