penguins-eggs 25.11.21 → 25.12.7

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.
Files changed (114) hide show
  1. package/.oclif.manifest.json +53 -41
  2. package/README.md +80 -36
  3. package/README.pdf +21575 -3241
  4. package/addons/eggs/theme/livecd/full.grub.main.cfg +39 -4
  5. package/addons/eggs/theme/livecd/full.isolinux.main.cfg +47 -4
  6. package/bin/run.js +11 -0
  7. package/conf/derivatives.yaml +4 -2
  8. package/conf/exclude.list.d/var.list +11 -6
  9. package/dist/appimage/dependency-manager.d.ts +31 -0
  10. package/dist/appimage/dependency-manager.js +292 -0
  11. package/dist/appimage/first-run-check.js +3 -3
  12. package/dist/bin/run.js +11 -0
  13. package/dist/classes/cli-autologin.js +78 -53
  14. package/dist/classes/compressors.d.ts +7 -10
  15. package/dist/classes/compressors.js +44 -31
  16. package/dist/classes/daddy.js +11 -11
  17. package/dist/classes/distro.js +2 -2
  18. package/dist/classes/diversions.js +2 -3
  19. package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +4 -0
  20. package/dist/classes/incubation/fisherman-helper/initcpio.js +14 -4
  21. package/dist/classes/incubation/fisherman-helper/settings.js +1 -1
  22. package/dist/classes/incubation/fisherman.js +1 -3
  23. package/dist/classes/incubation/incubator.js +1 -1
  24. package/dist/classes/network.d.ts +1 -1
  25. package/dist/classes/ovary.d/create-xdg-autostart.js +1 -1
  26. package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -12
  27. package/dist/classes/ovary.d/edit-live-fs.js +216 -186
  28. package/dist/classes/ovary.d/fertilization.js +1 -1
  29. package/dist/classes/ovary.d/make-dot-disk.js +1 -1
  30. package/dist/classes/ovary.d/produce.js +1 -1
  31. package/dist/classes/ovary.d/user-create-live.d.ts +4 -10
  32. package/dist/classes/ovary.d/user-create-live.js +82 -84
  33. package/dist/classes/ovary.d/users-remove.d.ts +5 -6
  34. package/dist/classes/ovary.d/users-remove.js +61 -31
  35. package/dist/classes/ovary.d/xorriso-command.js +1 -5
  36. package/dist/classes/ovary.d.ts +2 -2
  37. package/dist/classes/ovary.js +2 -2
  38. package/dist/classes/pacman.d/alpine.js +2 -2
  39. package/dist/classes/pacman.d/archlinux.js +2 -2
  40. package/dist/classes/pacman.d/debian.js +2 -3
  41. package/dist/classes/pacman.d/fedora.js +2 -3
  42. package/dist/classes/pacman.d/openmamba.js +2 -3
  43. package/dist/classes/pacman.d/opensuse.js +2 -3
  44. package/dist/classes/pacman.d.ts +21 -12
  45. package/dist/classes/pacman.js +55 -47
  46. package/dist/classes/pve-live.js +1 -1
  47. package/dist/classes/settings.js +1 -1
  48. package/dist/classes/sys-users.d.ts +76 -0
  49. package/dist/classes/sys-users.js +206 -0
  50. package/dist/classes/utils.d/kernel.js +3 -3
  51. package/dist/classes/utils.d.ts +16 -11
  52. package/dist/classes/utils.js +92 -56
  53. package/dist/classes/xdg.js +1 -1
  54. package/dist/classes/yolk.js +2 -4
  55. package/dist/commands/config.js +3 -14
  56. package/dist/commands/cuckoo.js +1 -1
  57. package/dist/commands/export/appimage.js +3 -3
  58. package/dist/commands/export/pkg.js +3 -3
  59. package/dist/commands/export/tarballs.js +3 -3
  60. package/dist/commands/krill.js +1 -1
  61. package/dist/commands/produce.js +9 -4
  62. package/dist/commands/{setup.d.ts → setup/install.d.ts} +1 -5
  63. package/dist/commands/setup/install.js +71 -0
  64. package/dist/commands/setup/purge.d.ts +17 -0
  65. package/dist/commands/setup/purge.js +71 -0
  66. package/dist/commands/tools/yolk.js +1 -1
  67. package/dist/commands/update.d.ts +15 -0
  68. package/dist/commands/update.js +74 -7
  69. package/dist/interfaces/i-exec.d.ts +1 -0
  70. package/dist/krill/classes/prepare.d/location.js +1 -1
  71. package/dist/krill/classes/prepare.d/partitions.js +1 -1
  72. package/dist/krill/classes/prepare.d/users.js +2 -2
  73. package/dist/krill/classes/prepare.js +5 -5
  74. package/dist/krill/classes/sequence.d/add_user.d.ts +3 -15
  75. package/dist/krill/classes/sequence.d/add_user.js +87 -57
  76. package/dist/krill/classes/sequence.d/change_password.d.ts +5 -7
  77. package/dist/krill/classes/sequence.d/change_password.js +25 -10
  78. package/dist/krill/classes/sequence.d/del_live_user.d.ts +5 -7
  79. package/dist/krill/classes/sequence.d/del_live_user.js +39 -25
  80. package/dist/krill/classes/sequence.d/fstab.js +1 -1
  81. package/dist/krill/classes/sequence.d/grubcfg.d.ts +3 -7
  82. package/dist/krill/classes/sequence.d/grubcfg.js +33 -13
  83. package/dist/krill/classes/sequence.d/mkfs.js +1 -2
  84. package/dist/krill/classes/sequence.d/unpackfs.d.ts +2 -4
  85. package/dist/krill/classes/sequence.d/unpackfs.js +8 -5
  86. package/dist/krill/classes/sequence.js +2 -3
  87. package/dist/krill/components/title.js +4 -4
  88. package/dist/krill/lib/select_installation_device.js +1 -1
  89. package/dist/krill/lib/select_replaced_partition.js +1 -1
  90. package/dist/lib/utils.d.ts +51 -19
  91. package/dist/lib/utils.js +225 -39
  92. package/manpages/doc/man/eggs.1.gz +0 -0
  93. package/manpages/doc/man/eggs.html +29 -17
  94. package/package.json +13 -14
  95. package/perrisbrewery/template/dependencies.yaml +1 -0
  96. package/scripts/_eggs +35 -7
  97. package/scripts/boot-encrypted-root.sh +220 -0
  98. package/scripts/eggs.bash +2 -1
  99. package/scripts/mount-encrypted-home.sh +324 -0
  100. package/dist/appimage/prerequisites.d.ts +0 -34
  101. package/dist/appimage/prerequisites.js +0 -350
  102. package/dist/commands/setup.js +0 -90
  103. package/dracut/create-symlink +0 -71
  104. package/dracut/dracut-log.txt +0 -3
  105. package/dracut/export +0 -4
  106. package/dracut/export-dracut-analysis +0 -51
  107. package/dracut/export-dracut-log +0 -2
  108. package/dracut/mkisofs +0 -10
  109. package/dracut/renew-initramfs +0 -17
  110. package/dracut/sbin2bin +0 -10
  111. package/dracut/update-dracut-conf-d +0 -2
  112. package/dracut/update-dracut-modules +0 -62
  113. package/scripts/appimage-build.sh +0 -152
  114. package/scripts/appimage-install.sh +0 -43
@@ -5,11 +5,10 @@
5
5
  * email: piero.proietti@gmail.com
6
6
  * license: MIT
7
7
  */
8
- import { execSync } from 'node:child_process';
8
+ import { shx, execSync } from '../lib/utils.js';
9
9
  import fs from 'node:fs';
10
10
  // _dirname
11
11
  import path from 'node:path';
12
- import shx from 'shelljs';
13
12
  import { exec } from '../lib/utils.js';
14
13
  import Distro from './distro.js';
15
14
  import Diversions from './diversions.js';
@@ -33,24 +32,35 @@ export default class Pacman {
33
32
  distro = {};
34
33
  remix = {};
35
34
  /**
36
- *
35
+ * autocompleteInstall()
37
36
  * @param verbose
38
37
  */
39
- static async autocompleteInstall(verbose = false) {
38
+ static async autocompleteInstall() {
40
39
  if (Pacman.packageIsInstalled('bash-completion')) {
41
40
  if (fs.existsSync('/usr/share/bash-completion/completions/')) {
42
41
  await exec(`cp ${__dirname}/../../scripts/eggs.bash /usr/share/bash-completion/completions/`);
43
42
  }
44
- else if (fs.existsSync('/etc/bash_completion.d/')) {
45
- await exec(`cp ${__dirname}/../../scripts/eggs.bash /etc/bash_completion.d/`);
43
+ }
44
+ // Su arch è ok, su debian God know
45
+ if (Pacman.packageIsInstalled('zsh-completions')) {
46
+ if (fs.existsSync('/usr/share/zsh/site-functions')) {
47
+ await exec(`cp ${__dirname}/../../scripts/_eggs /usr/share/zsh/site-functions/`);
46
48
  }
47
49
  }
48
50
  }
51
+ /**
52
+ * autocompleteRemove
53
+ * @param verbose
54
+ */
55
+ static async autocompleteRemove(verbose = false) {
56
+ await exec(`rm -f /usr/share/bash-completion/completions/eggs.bash`);
57
+ await exec(`rm -f /usr/share/zsh/site-functions/._eggs`);
58
+ }
49
59
  /**
50
60
  * return true if calamares is installed
51
61
  */
52
62
  static calamaresExists() {
53
- return this.commandIsInstalled('calamares');
63
+ return Utils.commandExists('calamares');
54
64
  }
55
65
  /**
56
66
  *
@@ -133,19 +143,6 @@ export default class Pacman {
133
143
  }
134
144
  return retVal;
135
145
  }
136
- /**
137
- *
138
- * @param cmd
139
- */
140
- static commandIsInstalled(cmd) {
141
- let installed = false;
142
- // if (shx.exec(`command -V ${cmd} &>/dev/null`).code == 0) {
143
- // remove output
144
- if (shx.exec(`command -V ${cmd} >/dev/null 2>&1`).code == 0) {
145
- installed = true;
146
- }
147
- return installed;
148
- }
149
146
  /**
150
147
  * Restituisce VERO se i file di configurazione SONO presenti
151
148
  */
@@ -186,7 +183,7 @@ export default class Pacman {
186
183
  /**
187
184
  * Salvo la configurazione di eggs.yaml
188
185
  */
189
- config.machine_id = Utils.machineId();
186
+ config.machine_id = ''; //Utils.machineId()
190
187
  config.vmlinuz = Utils.vmlinuz();
191
188
  config.initrd_img = Utils.initrdImg();
192
189
  const settings = new Settings();
@@ -222,7 +219,6 @@ export default class Pacman {
222
219
  execSync(`rm -rf ${init}`);
223
220
  }
224
221
  execSync(`mkdir -p ${init}`);
225
- shx.ln('-s', path.resolve(__dirname, '../../addons'), addons);
226
222
  shx.cp(path.resolve(__dirname, '../../conf/README.md'), confRoot);
227
223
  shx.cp(path.resolve(__dirname, '../../conf/derivatives.yaml'), confRoot);
228
224
  shx.cp(path.resolve(__dirname, '../../conf/derivatives_fedora.yaml'), confRoot);
@@ -240,6 +236,21 @@ export default class Pacman {
240
236
  shx.cp(path.resolve(__dirname, '../../conf/exclude.list.d/*'), '/etc/penguins-eggs.d/exclude.list.d');
241
237
  await this.configurationFresh();
242
238
  }
239
+ /**
240
+ * Rimozione dei file di configurazione
241
+ */
242
+ static async configurationRemove(verbose = false) {
243
+ const echo = Utils.setEcho(verbose);
244
+ if (fs.existsSync('/etc/penguins-eggs.d')) {
245
+ await exec('rm /etc/penguins-eggs.d -rf', echo);
246
+ }
247
+ /**
248
+ * No remove calamares more
249
+ */
250
+ // if (fs.existsSync('/etc/calamares')) {
251
+ // await exec('rm /etc/calamares -rf', echo)
252
+ // }
253
+ }
243
254
  /**
244
255
  * Ritorna vero se machine-id è uguale
245
256
  */
@@ -252,18 +263,6 @@ export default class Pacman {
252
263
  }
253
264
  return result;
254
265
  }
255
- /**
256
- * Rimozione dei file di configurazione
257
- */
258
- static async configurationRemove(verbose = true) {
259
- const echo = Utils.setEcho(verbose);
260
- if (fs.existsSync('/etc/penguins-eggs.d')) {
261
- await exec('rm /etc/penguins-eggs.d -rf', echo);
262
- }
263
- if (fs.existsSync('/etc/calamares')) {
264
- await exec('rm /etc/calamares -rf', echo);
265
- }
266
- }
267
266
  /**
268
267
  *
269
268
  * @returns
@@ -591,22 +590,26 @@ export default class Pacman {
591
590
  /**
592
591
  * Installa manPage
593
592
  */
594
- static async manPageInstall(verbose = false) {
595
- const manPageSrc = path.resolve(__dirname, '../../manpages/doc/man/eggs.1.gz');
596
- if (fs.existsSync(manPageSrc)) {
597
- const manPageDest = `/usr/share/man/man1`;
598
- if (!fs.existsSync(manPageDest)) {
599
- exec(`mkdir ${manPageDest} -p`);
600
- }
601
- exec(`cp ${manPageSrc} ${manPageDest}`);
602
- if (shx.exec('which mandb', { silent: true }).stdout.trim() !== '') {
603
- await exec('mandb > /dev/null');
604
- if (verbose) {
605
- console.log('manPage eggs installed...');
606
- }
593
+ static async manpageInstall() {
594
+ const manpageSrc = path.resolve(__dirname, '../../manpages/doc/man/eggs.1.gz');
595
+ if (fs.existsSync(manpageSrc)) {
596
+ const manpageDest = `/usr/share/man/man1`;
597
+ if (!fs.existsSync(manpageDest)) {
598
+ await exec(`mkdir ${manpageDest} -p`);
607
599
  }
600
+ await exec(`cp ${manpageSrc} ${manpageDest}`);
601
+ // if (shx.exec('which mandb', { silent: true }).stdout.trim() !== '') {
602
+ // await exec('mandb > /dev/null')
603
+ // }
608
604
  }
609
605
  }
606
+ /**
607
+ * manpageRemove
608
+ */
609
+ static async manpageRemove() {
610
+ const manpageEggs = `/usr/share/man/man1/eggs.1.gz`;
611
+ await exec(`rm -rf ${manpageEggs}`);
612
+ }
610
613
  /**
611
614
  *
612
615
  * @param debPackage
@@ -674,6 +677,11 @@ export default class Pacman {
674
677
  }
675
678
  return installed;
676
679
  }
680
+ /**
681
+ *
682
+ * @param packageNpm
683
+ * @returns
684
+ */
677
685
  static async packageNpmLast(packageNpm = 'penguins-eggs') {
678
686
  return shx.exec('npm show ' + packageNpm + ' version', { silent: true }).stdout.trim();
679
687
  }
@@ -14,7 +14,7 @@
14
14
  * This will remove the symbolic link that indicated that the service should be started automatically.
15
15
  */
16
16
  import path from 'node:path';
17
- import shx from 'shelljs';
17
+ import { shx } from '../lib/utils.js';
18
18
  import Systemctl from './systemctl.js';
19
19
  // _dirname
20
20
  const __dirname = path.dirname(new URL(import.meta.url).pathname);
@@ -10,7 +10,7 @@ import yaml from 'js-yaml';
10
10
  // packages
11
11
  import fs from 'node:fs';
12
12
  import os from 'node:os';
13
- import shx from 'shelljs';
13
+ import { shx } from '../lib/utils.js';
14
14
  // pjson
15
15
  import { createRequire } from 'node:module';
16
16
  const require = createRequire(import.meta.url);
@@ -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 'node:child_process';
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').toString().trim();
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').toString().trim();
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)) {
@@ -62,7 +62,7 @@ export default class Utils {
62
62
  */
63
63
  static isOpenRc(): boolean;
64
64
  /**
65
- * Occore vedere un modo per creare machine-id dove non esiste
65
+ * Usata da pacman e config credo non serva affatto
66
66
  */
67
67
  static machineId(): string;
68
68
  /**
@@ -140,7 +140,7 @@ export default class Utils {
140
140
  *
141
141
  * @param volid
142
142
  */
143
- static getVolid(volid?: string): string;
143
+ static VolidTrim(volid?: string): string;
144
144
  /**
145
145
  * Return postfix
146
146
  * @param basename
@@ -153,11 +153,10 @@ export default class Utils {
153
153
  */
154
154
  static getUsedSpace(): number;
155
155
  /**
156
- * Extimate the linuxfs dimension
157
- * probably is better to rename it as
158
- * getLiveSpaceRootNeed
159
- * @returns {number} Byte
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
@@ -247,10 +246,6 @@ export default class Utils {
247
246
  * cidr
248
247
  */
249
248
  static cidr(): string;
250
- /**
251
- *
252
- * broadcast
253
- */
254
249
  static broadcast(): string;
255
250
  /**
256
251
  * dns
@@ -331,4 +326,14 @@ export default class Utils {
331
326
  static wardrobe(): Promise<string>;
332
327
  static getOsRelease(): IOsRelease;
333
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;
334
339
  }