penguins-eggs 10.0.28 → 10.0.30

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 (361) hide show
  1. package/.oclif.manifest.json +1500 -2
  2. package/README.md +760 -0
  3. package/addons/README.md +0 -2
  4. package/addons/eggs/adapt/applications/eggs-adapt.desktop +1 -1
  5. package/addons/eggs/theme/livecd/isolinux.main.alpine.cfg +43 -0
  6. package/addons/eggs/theme/livecd/{isolinux.main.cfg → isolinux.main.original.cfg} +1 -1
  7. package/conf/distros/alpine/README.md +1 -1
  8. package/conf/distros/alpine/calamares/calamares-modules/bootloader-config/bootloader-config.sh +40 -0
  9. package/conf/distros/alpine/calamares/calamares-modules/bootloader-config/module.yml +9 -0
  10. package/conf/distros/alpine/calamares/calamares-modules/cleanup/cleanup.sh +13 -0
  11. package/conf/distros/alpine/calamares/calamares-modules/cleanup/module.yml +9 -0
  12. package/conf/distros/alpine/calamares/modules/bootloader.yml +57 -0
  13. package/conf/distros/alpine/calamares/modules/displaymanager.yml +23 -0
  14. package/conf/distros/alpine/calamares/modules/finished.yml +5 -0
  15. package/conf/distros/alpine/calamares/modules/fstab.yml +12 -0
  16. package/conf/distros/alpine/calamares/modules/locale.yml +98 -0
  17. package/conf/distros/alpine/calamares/modules/luksopenswaphookcfg.yml +5 -0
  18. package/conf/distros/alpine/calamares/modules/machineid.yml +17 -0
  19. package/conf/distros/alpine/calamares/modules/mount.yml +56 -0
  20. package/conf/distros/alpine/calamares/modules/packages.yml +6 -0
  21. package/conf/distros/alpine/calamares/modules/partition.yml +242 -0
  22. package/conf/distros/alpine/calamares/modules/removeuser.yml +15 -0
  23. package/conf/distros/alpine/calamares/modules/unpackfs.yml +6 -0
  24. package/conf/distros/alpine/calamares/modules/users.yml +18 -0
  25. package/conf/distros/alpine/calamares/modules/welcome.yml +19 -0
  26. package/conf/distros/alpine/calamares/settings.yml +57 -0
  27. package/conf/love.yaml +8 -0
  28. package/dist/classes/bleach.d.ts +32 -0
  29. package/dist/classes/bleach.js +136 -0
  30. package/dist/classes/cfs.d.ts +17 -0
  31. package/dist/classes/cfs.js +39 -0
  32. package/dist/classes/cli-autologin.d.ts +52 -0
  33. package/dist/classes/cli-autologin.js +230 -0
  34. package/dist/classes/compressors.d.ts +54 -0
  35. package/dist/classes/compressors.js +109 -0
  36. package/dist/classes/daddy.d.ts +26 -0
  37. package/dist/classes/daddy.js +161 -0
  38. package/dist/classes/distro.d.ts +36 -0
  39. package/dist/classes/distro.js +346 -0
  40. package/dist/classes/families/alpine.d.ts +55 -0
  41. package/dist/classes/families/alpine.js +163 -0
  42. package/dist/classes/families/archlinux.d.ts +61 -0
  43. package/dist/classes/families/archlinux.js +140 -0
  44. package/dist/classes/families/debian.d.ts +65 -0
  45. package/dist/classes/families/debian.js +138 -0
  46. package/dist/classes/families/fedora.d.ts +52 -0
  47. package/dist/classes/families/fedora.js +100 -0
  48. package/dist/classes/families/mockup.d.ts +60 -0
  49. package/dist/classes/families/mockup.js +79 -0
  50. package/dist/classes/families/opensuse.d.ts +52 -0
  51. package/dist/classes/families/opensuse.js +104 -0
  52. package/dist/classes/incubation/branding.d.ts +17 -0
  53. package/dist/classes/incubation/branding.js +89 -0
  54. package/dist/classes/incubation/distros/alpine.d.ts +32 -0
  55. package/dist/classes/incubation/distros/alpine.js +80 -0
  56. package/dist/classes/incubation/distros/bionic.d.ts +32 -0
  57. package/dist/classes/incubation/distros/bionic.js +83 -0
  58. package/dist/classes/incubation/distros/buster.d.ts +32 -0
  59. package/dist/classes/incubation/distros/buster.js +85 -0
  60. package/dist/classes/incubation/distros/jessie.d.ts +31 -0
  61. package/dist/classes/incubation/distros/jessie.js +44 -0
  62. package/dist/classes/incubation/distros/noble.d.ts +32 -0
  63. package/dist/classes/incubation/distros/noble.js +85 -0
  64. package/dist/classes/incubation/distros/rolling.d.ts +32 -0
  65. package/dist/classes/incubation/distros/rolling.js +82 -0
  66. package/dist/classes/incubation/fisherman-helper/displaymanager.d.ts +11 -0
  67. package/dist/classes/incubation/fisherman-helper/displaymanager.js +39 -0
  68. package/dist/classes/incubation/fisherman-helper/packages.d.ts +20 -0
  69. package/dist/classes/incubation/fisherman-helper/packages.js +72 -0
  70. package/dist/classes/incubation/fisherman-helper/settings.d.ts +15 -0
  71. package/dist/classes/incubation/fisherman-helper/settings.js +83 -0
  72. package/dist/classes/incubation/fisherman.d.ts +77 -0
  73. package/dist/classes/incubation/fisherman.js +251 -0
  74. package/dist/classes/incubation/incubator.d.ts +40 -0
  75. package/dist/classes/incubation/incubator.js +328 -0
  76. package/dist/classes/incubation/installer.d.ts +13 -0
  77. package/dist/classes/incubation/installer.js +64 -0
  78. package/dist/classes/keyboards.d.ts +50 -0
  79. package/dist/classes/keyboards.js +287 -0
  80. package/dist/classes/locales.d.ts +21 -0
  81. package/dist/classes/locales.js +80 -0
  82. package/dist/classes/n8.d.ts +18 -0
  83. package/dist/classes/n8.js +36 -0
  84. package/dist/classes/network.d.ts +37 -0
  85. package/dist/classes/network.js +98 -0
  86. package/dist/classes/ovary.d.ts +214 -0
  87. package/dist/classes/ovary.js +1872 -0
  88. package/dist/classes/pacman.d.ts +149 -0
  89. package/dist/classes/pacman.js +703 -0
  90. package/dist/classes/pve-live.d.ts +17 -0
  91. package/dist/classes/pve-live.js +52 -0
  92. package/dist/classes/pxe.d.ts +74 -0
  93. package/dist/classes/pxe.js +410 -0
  94. package/dist/classes/settings.d.ts +53 -0
  95. package/dist/classes/settings.js +185 -0
  96. package/dist/classes/sources_list.d.ts +28 -0
  97. package/dist/classes/sources_list.js +89 -0
  98. package/dist/classes/systemctl.d.ts +47 -0
  99. package/dist/classes/systemctl.js +86 -0
  100. package/dist/classes/tailor.d.ts +46 -0
  101. package/dist/classes/tailor.js +587 -0
  102. package/dist/classes/tools.d.ts +30 -0
  103. package/dist/classes/tools.js +54 -0
  104. package/dist/classes/users.d.ts +28 -0
  105. package/dist/classes/users.js +143 -0
  106. package/dist/classes/utils.d.ts +323 -0
  107. package/dist/classes/utils.js +951 -0
  108. package/dist/classes/xdg.d.ts +45 -0
  109. package/dist/classes/xdg.js +329 -0
  110. package/dist/classes/yolk.d.ts +33 -0
  111. package/dist/classes/yolk.js +114 -0
  112. package/dist/commands/adapt.d.ts +17 -0
  113. package/dist/commands/adapt.js +33 -0
  114. package/dist/commands/analyze.d.ts +26 -0
  115. package/dist/commands/analyze.js +95 -0
  116. package/dist/commands/calamares.d.ts +29 -0
  117. package/dist/commands/calamares.js +110 -0
  118. package/dist/commands/config.d.ts +35 -0
  119. package/dist/commands/config.js +192 -0
  120. package/dist/commands/cuckoo.d.ts +16 -0
  121. package/dist/commands/cuckoo.js +62 -0
  122. package/dist/commands/dad.d.ts +20 -0
  123. package/dist/commands/dad.js +46 -0
  124. package/dist/commands/export/deb.d.ts +19 -0
  125. package/dist/commands/export/deb.js +51 -0
  126. package/dist/commands/export/iso.d.ts +19 -0
  127. package/dist/commands/export/iso.js +55 -0
  128. package/dist/commands/install.d.ts +37 -0
  129. package/dist/commands/install.js +92 -0
  130. package/dist/commands/kill.d.ts +24 -0
  131. package/dist/commands/kill.js +50 -0
  132. package/dist/commands/love.d.ts +20 -0
  133. package/dist/commands/love.js +55 -0
  134. package/dist/commands/mom.d.ts +16 -0
  135. package/dist/commands/mom.js +30 -0
  136. package/dist/commands/produce.d.ts +34 -0
  137. package/dist/commands/produce.js +196 -0
  138. package/dist/commands/status.d.ts +23 -0
  139. package/dist/commands/status.js +31 -0
  140. package/dist/commands/syncfrom.d.ts +45 -0
  141. package/dist/commands/syncfrom.js +152 -0
  142. package/dist/commands/syncto.d.ts +40 -0
  143. package/dist/commands/syncto.js +175 -0
  144. package/dist/commands/tools/clean.d.ts +18 -0
  145. package/dist/commands/tools/clean.js +37 -0
  146. package/dist/commands/tools/ppa.d.ts +26 -0
  147. package/dist/commands/tools/ppa.js +138 -0
  148. package/dist/commands/tools/skel.d.ts +18 -0
  149. package/dist/commands/tools/skel.js +44 -0
  150. package/dist/commands/tools/stat.d.ts +31 -0
  151. package/dist/commands/tools/stat.js +70 -0
  152. package/dist/commands/tools/yolk.d.ts +24 -0
  153. package/dist/commands/tools/yolk.js +45 -0
  154. package/dist/commands/update.d.ts +47 -0
  155. package/dist/commands/update.js +140 -0
  156. package/dist/commands/wardrobe/get.d.ts +23 -0
  157. package/dist/commands/wardrobe/get.js +52 -0
  158. package/dist/commands/wardrobe/list.d.ts +24 -0
  159. package/dist/commands/wardrobe/list.js +125 -0
  160. package/dist/commands/wardrobe/show.d.ts +25 -0
  161. package/dist/commands/wardrobe/show.js +97 -0
  162. package/dist/commands/wardrobe/wear.d.ts +26 -0
  163. package/dist/commands/wardrobe/wear.js +81 -0
  164. package/dist/components/finished.d.ts +15 -0
  165. package/dist/components/finished.js +55 -0
  166. package/dist/components/information.d.ts +8 -0
  167. package/dist/components/information.js +153 -0
  168. package/dist/components/install.d.ts +15 -0
  169. package/dist/components/install.js +56 -0
  170. package/dist/components/keyboard.d.ts +16 -0
  171. package/dist/components/keyboard.js +54 -0
  172. package/dist/components/location.d.ts +16 -0
  173. package/dist/components/location.js +59 -0
  174. package/dist/components/network.d.ts +19 -0
  175. package/dist/components/network.js +65 -0
  176. package/dist/components/partitions.d.ts +16 -0
  177. package/dist/components/partitions.js +73 -0
  178. package/dist/components/steps.d.ts +13 -0
  179. package/dist/components/steps.js +148 -0
  180. package/dist/components/summary.d.ts +24 -0
  181. package/dist/components/summary.js +82 -0
  182. package/dist/components/title.d.ts +11 -0
  183. package/dist/components/title.js +35 -0
  184. package/dist/components/users.d.ts +24 -0
  185. package/dist/components/users.js +80 -0
  186. package/dist/components/welcome.d.ts +13 -0
  187. package/dist/components/welcome.js +63 -0
  188. package/dist/index.d.ts +8 -0
  189. package/dist/index.js +8 -0
  190. package/dist/interfaces/i-addons.d.ts +12 -0
  191. package/dist/interfaces/i-addons.js +8 -0
  192. package/dist/interfaces/i-analyze.d.ts +17 -0
  193. package/dist/interfaces/i-analyze.js +17 -0
  194. package/dist/interfaces/i-app.d.ts +14 -0
  195. package/dist/interfaces/i-app.js +8 -0
  196. package/dist/interfaces/i-branding.d.ts +36 -0
  197. package/dist/interfaces/i-branding.js +8 -0
  198. package/dist/interfaces/i-calamares-partition.d.ts +18 -0
  199. package/dist/interfaces/i-calamares-partition.js +8 -0
  200. package/dist/interfaces/i-config-tools.d.ts +18 -0
  201. package/dist/interfaces/i-config-tools.js +8 -0
  202. package/dist/interfaces/i-devices.d.ts +20 -0
  203. package/dist/interfaces/i-devices.js +8 -0
  204. package/dist/interfaces/i-distro.d.ts +27 -0
  205. package/dist/interfaces/i-distro.js +8 -0
  206. package/dist/interfaces/i-drive-list.d.ts +33 -0
  207. package/dist/interfaces/i-drive-list.js +8 -0
  208. package/dist/interfaces/i-eggs-config.d.ts +32 -0
  209. package/dist/interfaces/i-eggs-config.js +8 -0
  210. package/dist/interfaces/i-excludes.d.ts +14 -0
  211. package/dist/interfaces/i-excludes.js +8 -0
  212. package/dist/interfaces/i-exec.d.ts +11 -0
  213. package/dist/interfaces/i-exec.js +8 -0
  214. package/dist/interfaces/i-initrd.d.ts +13 -0
  215. package/dist/interfaces/i-initrd.js +8 -0
  216. package/dist/interfaces/i-install.d.ts +16 -0
  217. package/dist/interfaces/i-install.js +8 -0
  218. package/dist/interfaces/i-installer.d.ts +17 -0
  219. package/dist/interfaces/i-installer.js +8 -0
  220. package/dist/interfaces/i-krill-config.d.ts +33 -0
  221. package/dist/interfaces/i-krill-config.js +8 -0
  222. package/dist/interfaces/i-krill.d.ts +42 -0
  223. package/dist/interfaces/i-krill.js +8 -0
  224. package/dist/interfaces/i-materia.d.ts +41 -0
  225. package/dist/interfaces/i-materia.js +8 -0
  226. package/dist/interfaces/i-net.d.ts +16 -0
  227. package/dist/interfaces/i-net.js +8 -0
  228. package/dist/interfaces/i-packages.d.ts +16 -0
  229. package/dist/interfaces/i-packages.js +8 -0
  230. package/dist/interfaces/i-partitions.d.ts +16 -0
  231. package/dist/interfaces/i-partitions.js +8 -0
  232. package/dist/interfaces/i-pxe.d.ts +45 -0
  233. package/dist/interfaces/i-pxe.js +1 -0
  234. package/dist/interfaces/i-remix.d.ts +21 -0
  235. package/dist/interfaces/i-remix.js +8 -0
  236. package/dist/interfaces/i-settings.d.ts +33 -0
  237. package/dist/interfaces/i-settings.js +8 -0
  238. package/dist/interfaces/i-user.d.ts +14 -0
  239. package/dist/interfaces/i-user.js +8 -0
  240. package/dist/interfaces/i-workdir.d.ts +14 -0
  241. package/dist/interfaces/i-workdir.js +8 -0
  242. package/dist/interfaces/i-xkb-model.d.ts +24 -0
  243. package/dist/interfaces/i-xkb-model.js +8 -0
  244. package/dist/interfaces/index.d.ts +25 -0
  245. package/dist/interfaces/index.js +8 -0
  246. package/dist/krill/modules/add-user.d.ts +20 -0
  247. package/dist/krill/modules/add-user.js +49 -0
  248. package/dist/krill/modules/bootloader-config-alpine.d.ts +14 -0
  249. package/dist/krill/modules/bootloader-config-alpine.js +37 -0
  250. package/dist/krill/modules/bootloader-config-arch.d.ts +14 -0
  251. package/dist/krill/modules/bootloader-config-arch.js +37 -0
  252. package/dist/krill/modules/bootloader-config-debian.d.ts +10 -0
  253. package/dist/krill/modules/bootloader-config-debian.js +50 -0
  254. package/dist/krill/modules/bootloader-config.d.ts +10 -0
  255. package/dist/krill/modules/bootloader-config.js +25 -0
  256. package/dist/krill/modules/bootloader.d.ts +14 -0
  257. package/dist/krill/modules/bootloader.js +30 -0
  258. package/dist/krill/modules/change-password.d.ts +15 -0
  259. package/dist/krill/modules/change-password.js +18 -0
  260. package/dist/krill/modules/del-live-user.d.ts +14 -0
  261. package/dist/krill/modules/del-live-user.js +38 -0
  262. package/dist/krill/modules/fstab.d.ts +14 -0
  263. package/dist/krill/modules/fstab.js +121 -0
  264. package/dist/krill/modules/grubcfg.d.ts +17 -0
  265. package/dist/krill/modules/grubcfg.js +29 -0
  266. package/dist/krill/modules/hostname.d.ts +13 -0
  267. package/dist/krill/modules/hostname.js +50 -0
  268. package/dist/krill/modules/initramfs-cfg.d.ts +14 -0
  269. package/dist/krill/modules/initramfs-cfg.js +25 -0
  270. package/dist/krill/modules/initramfs.d.ts +13 -0
  271. package/dist/krill/modules/initramfs.js +48 -0
  272. package/dist/krill/modules/locale-cfg.d.ts +10 -0
  273. package/dist/krill/modules/locale-cfg.js +61 -0
  274. package/dist/krill/modules/locale.d.ts +13 -0
  275. package/dist/krill/modules/locale.js +48 -0
  276. package/dist/krill/modules/m-keyboard.d.ts +14 -0
  277. package/dist/krill/modules/m-keyboard.js +79 -0
  278. package/dist/krill/modules/m-timezone.d.ts +14 -0
  279. package/dist/krill/modules/m-timezone.js +22 -0
  280. package/dist/krill/modules/machine-id.d.ts +15 -0
  281. package/dist/krill/modules/machine-id.js +30 -0
  282. package/dist/krill/modules/mkfs.d.ts +13 -0
  283. package/dist/krill/modules/mkfs.js +48 -0
  284. package/dist/krill/modules/mount-fs.d.ts +17 -0
  285. package/dist/krill/modules/mount-fs.js +60 -0
  286. package/dist/krill/modules/mount-vfs.d.ts +17 -0
  287. package/dist/krill/modules/mount-vfs.js +40 -0
  288. package/dist/krill/modules/network-cfg.d.ts +19 -0
  289. package/dist/krill/modules/network-cfg.js +64 -0
  290. package/dist/krill/modules/packages.d.ts +14 -0
  291. package/dist/krill/modules/packages.js +111 -0
  292. package/dist/krill/modules/partition.d.ts +20 -0
  293. package/dist/krill/modules/partition.js +324 -0
  294. package/dist/krill/modules/remove-installer-link.d.ts +13 -0
  295. package/dist/krill/modules/remove-installer-link.js +35 -0
  296. package/dist/krill/modules/umount.d.ts +14 -0
  297. package/dist/krill/modules/umount.js +27 -0
  298. package/dist/krill/modules/unpackfs.d.ts +13 -0
  299. package/dist/krill/modules/unpackfs.js +19 -0
  300. package/dist/krill/prepare.d.ts +78 -0
  301. package/dist/krill/prepare.js +626 -0
  302. package/dist/krill/sequence.d.ts +159 -0
  303. package/dist/krill/sequence.js +687 -0
  304. package/dist/lib/get_address.d.ts +8 -0
  305. package/dist/lib/get_address.js +23 -0
  306. package/dist/lib/get_dns.d.ts +8 -0
  307. package/dist/lib/get_dns.js +23 -0
  308. package/dist/lib/get_domain.d.ts +8 -0
  309. package/dist/lib/get_domain.js +23 -0
  310. package/dist/lib/get_gateway.d.ts +8 -0
  311. package/dist/lib/get_gateway.js +23 -0
  312. package/dist/lib/get_hostname.d.ts +8 -0
  313. package/dist/lib/get_hostname.js +23 -0
  314. package/dist/lib/get_netmask.d.ts +8 -0
  315. package/dist/lib/get_netmask.js +23 -0
  316. package/dist/lib/get_password.d.ts +8 -0
  317. package/dist/lib/get_password.js +36 -0
  318. package/dist/lib/get_userfullname.d.ts +8 -0
  319. package/dist/lib/get_userfullname.js +23 -0
  320. package/dist/lib/get_username.d.ts +8 -0
  321. package/dist/lib/get_username.js +23 -0
  322. package/dist/lib/kill_me_softly.d.ts +11 -0
  323. package/dist/lib/kill_me_softly.js +61 -0
  324. package/dist/lib/select_address_type.d.ts +8 -0
  325. package/dist/lib/select_address_type.js +24 -0
  326. package/dist/lib/select_filesystem_type.d.ts +8 -0
  327. package/dist/lib/select_filesystem_type.js +45 -0
  328. package/dist/lib/select_installation_device.d.ts +8 -0
  329. package/dist/lib/select_installation_device.js +30 -0
  330. package/dist/lib/select_installation_mode.d.ts +8 -0
  331. package/dist/lib/select_installation_mode.js +24 -0
  332. package/dist/lib/select_interface.d.ts +8 -0
  333. package/dist/lib/select_interface.js +24 -0
  334. package/dist/lib/select_keyboard_layout.d.ts +11 -0
  335. package/dist/lib/select_keyboard_layout.js +36 -0
  336. package/dist/lib/select_keyboard_model.d.ts +11 -0
  337. package/dist/lib/select_keyboard_model.js +34 -0
  338. package/dist/lib/select_keyboard_option.d.ts +11 -0
  339. package/dist/lib/select_keyboard_option.js +34 -0
  340. package/dist/lib/select_keyboard_variant.d.ts +11 -0
  341. package/dist/lib/select_keyboard_variant.js +35 -0
  342. package/dist/lib/select_languages.d.ts +8 -0
  343. package/dist/lib/select_languages.js +28 -0
  344. package/dist/lib/select_regions.d.ts +8 -0
  345. package/dist/lib/select_regions.js +24 -0
  346. package/dist/lib/select_user_swap_choice.d.ts +8 -0
  347. package/dist/lib/select_user_swap_choice.js +34 -0
  348. package/dist/lib/select_zones.d.ts +8 -0
  349. package/dist/lib/select_zones.js +518 -0
  350. package/dist/lib/utils.d.ts +34 -0
  351. package/dist/lib/utils.js +79 -0
  352. package/manpages/doc/man/eggs.1.gz +0 -0
  353. package/manpages/doc/man/eggs.html +21 -5
  354. package/mkinitfs/README.md +9 -0
  355. package/package.json +4 -4
  356. package/scripts/_eggs +9 -2
  357. package/scripts/eggs.bash +2 -1
  358. package/addons/eggs/ichoice/applications/eggs-ichoice.desktop +0 -23
  359. package/addons/eggs/ichoice/bin/eggs-ichoice.sh +0 -44
  360. package/scripts/love +0 -25
  361. /package/{addons/eggs/adapt/bin/adapt → scripts/adapt.sh} +0 -0
@@ -0,0 +1,1872 @@
1
+ /**
2
+ * ./src/classes/ovary.ts
3
+ * penguins-eggs v.10.0.0 / ecmascript 2020
4
+ * author: Piero Proietti
5
+ * email: piero.proietti@gmail.com
6
+ * license: MIT
7
+ */
8
+ import chalk from 'chalk';
9
+ import yaml from 'js-yaml';
10
+ import mustache from 'mustache';
11
+ // packages
12
+ import fs from 'node:fs';
13
+ import { constants } from 'node:fs';
14
+ // backup
15
+ import { access } from 'node:fs/promises';
16
+ import os from 'node:os';
17
+ import path from 'node:path';
18
+ import shx from 'shelljs';
19
+ // libraries
20
+ import { exec } from '../lib/utils.js';
21
+ import Bleach from './bleach.js';
22
+ import CliAutologin from './cli-autologin.js';
23
+ import { displaymanager } from './incubation/fisherman-helper/displaymanager.js';
24
+ import Incubator from './incubation/incubator.js';
25
+ import N8 from './n8.js';
26
+ import Pacman from './pacman.js';
27
+ import PveLive from './pve-live.js';
28
+ import Settings from './settings.js';
29
+ import Systemctl from './systemctl.js';
30
+ import Users from './users.js';
31
+ // classes
32
+ import Utils from './utils.js';
33
+ import Xdg from './xdg.js';
34
+ import Repo from './yolk.js';
35
+ // _dirname
36
+ const __dirname = path.dirname(new URL(import.meta.url).pathname);
37
+ /**
38
+ * Ovary:
39
+ */
40
+ export default class Ovary {
41
+ cliAutologin = new CliAutologin();
42
+ clone = false;
43
+ compression = '';
44
+ cryptedclone = false;
45
+ echo = {};
46
+ familyId = '';
47
+ genisoimage = false;
48
+ incubator = {};
49
+ nest = '';
50
+ settings = {};
51
+ snapshot_basename = '';
52
+ snapshot_prefix = '';
53
+ theme = '';
54
+ toNull = '';
55
+ verbose = false;
56
+ volid = '';
57
+ /**
58
+ * Add or remove exclusion
59
+ * @param add {boolean} true = add, false remove
60
+ * @param exclusion {string} path to add/remove
61
+ */
62
+ addRemoveExclusion(add, exclusion) {
63
+ if (this.verbose) {
64
+ console.log('Ovary: addRemoveExclusion');
65
+ }
66
+ if (exclusion.startsWith('/')) {
67
+ exclusion = exclusion.slice(1); // remove / initial Non compatible with rsync
68
+ }
69
+ if (add) {
70
+ this.settings.session_excludes += this.settings.session_excludes === '' ? `-e '${exclusion}' ` : ` '${exclusion}' `;
71
+ }
72
+ else {
73
+ this.settings.session_excludes.replace(` '${exclusion}'`, '');
74
+ if (this.settings.session_excludes === '-e') {
75
+ this.settings.session_excludes = '';
76
+ }
77
+ }
78
+ }
79
+ /**
80
+ * Esegue il bind del fs live e
81
+ * crea lo script bind
82
+ *
83
+ * @param verbose
84
+ */
85
+ async bindLiveFs() {
86
+ if (this.verbose) {
87
+ console.log('Ovary: bindLiveFs');
88
+ }
89
+ /**
90
+ * Attenzione:
91
+ * fs.readdirSync('/', { withFileTypes: true })
92
+ * viene ignorato da Node8, ma da problemi da Node10 in poi
93
+ */
94
+ const dirs = fs.readdirSync('/');
95
+ const startLine = '#############################################################';
96
+ const titleLine = '# ---------------------------------------------------------';
97
+ const endLine = '# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n';
98
+ let lnkDest = '';
99
+ let cmd = '';
100
+ const cmds = [];
101
+ cmds.push('# NOTE: cdrom, dev, live, media, mnt, proc, run, sys and tmp', `# need just a mkdir in ${this.settings.work_dir.merged}`);
102
+ cmds.push(`# host: ${os.hostname()} user: ${await Utils.getPrimaryUser()}\n`);
103
+ for (const dir of dirs) {
104
+ cmds.push(startLine);
105
+ if (N8.isDirectory(dir)) {
106
+ if (dir === 'boot') {
107
+ cmds.push(`# /boot is copied actually`);
108
+ cmds.push(await rexec(`cp -r /boot ${this.settings.config.snapshot_mnt}filesystem.squashfs`, this.verbose));
109
+ }
110
+ if (dir !== 'boot' && dir !== 'lost+found') {
111
+ cmd = `# /${dir} is a directory`;
112
+ if (this.mergedAndOverlay(dir)) {
113
+ /**
114
+ * mergedAndOverlay creazione directory, overlay e mount rw
115
+ */
116
+ cmds.push(`${cmd} need to be presente, and rw`, titleLine, '# create mountpoint lower');
117
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.lowerdir}/${dir}`), `# first: mount /${dir} rw in ${this.settings.work_dir.lowerdir}/${dir}`);
118
+ cmds.push(await rexec(`mount --bind --make-slave /${dir} ${this.settings.work_dir.lowerdir}/${dir}`, this.verbose), '# now remount it ro');
119
+ cmds.push(await rexec(`mount -o remount,bind,ro ${this.settings.work_dir.lowerdir}/${dir}`, this.verbose), `\n# second: create mountpoint upper, work and ${this.settings.work_dir.merged} and mount ${dir}`);
120
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.upperdir}/${dir}`, this.verbose));
121
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.workdir}/${dir}`, this.verbose));
122
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose), `\n# thirth: mount /${dir} rw in ${this.settings.work_dir.merged}`);
123
+ cmds.push(await rexec(`mount -t overlay overlay -o lowerdir=${this.settings.work_dir.lowerdir}/${dir},upperdir=${this.settings.work_dir.upperdir}/${dir},workdir=${this.settings.work_dir.workdir}/${dir} ${this.settings.work_dir.merged}/${dir}`, this.verbose));
124
+ }
125
+ else if (this.merged(dir)) {
126
+ /*
127
+ * merged creazione della directory e mount ro
128
+ */
129
+ cmds.push(`${cmd} need to be present, mount ro`, titleLine);
130
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose));
131
+ cmds.push(await rexec(`mount --bind --make-slave /${dir} ${this.settings.work_dir.merged}/${dir}`, this.verbose));
132
+ cmds.push(await rexec(`mount -o remount,bind,ro ${this.settings.work_dir.merged}/${dir}`, this.verbose));
133
+ }
134
+ else {
135
+ /**
136
+ * normal solo la creazione della directory, nessun mount
137
+ */
138
+ cmds.push(`${cmd} need to be present, no mount`, titleLine);
139
+ cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose), `# mount -o bind /${dir} ${this.settings.work_dir.merged}/${dir}`);
140
+ }
141
+ }
142
+ }
143
+ else if (N8.isFile(dir)) {
144
+ cmds.push(`# /${dir} is just a file`, titleLine);
145
+ if (fs.existsSync(`${this.settings.work_dir.merged}/${dir}`)) {
146
+ cmds.push('# file exist... skip');
147
+ }
148
+ else {
149
+ cmds.push(await rexec(`cp /${dir} ${this.settings.work_dir.merged}`, this.verbose));
150
+ }
151
+ }
152
+ else if (N8.isSymbolicLink(dir)) {
153
+ lnkDest = fs.readlinkSync(`/${dir}`);
154
+ cmds.push(`# /${dir} is a symbolic link to /${lnkDest} in the system`, '# we need just to recreate it', `# ln -s ${this.settings.work_dir.merged}/${lnkDest} ${this.settings.work_dir.merged}/${lnkDest}`, "# but we don't know if the destination exist, and I'm too lazy today. So, for now: ", titleLine);
155
+ if (fs.existsSync(`${this.settings.work_dir.merged}/${dir}`)) {
156
+ cmds.push('# SymbolicLink exist... skip');
157
+ }
158
+ else if (fs.existsSync(lnkDest)) {
159
+ cmds.push(`ln -s ${this.settings.work_dir.merged}/${lnkDest} ${this.settings.work_dir.merged}/${lnkDest}`);
160
+ }
161
+ else {
162
+ cmds.push(await rexec(`cp -r /${dir} ${this.settings.work_dir.merged}`, this.verbose));
163
+ }
164
+ }
165
+ cmds.push(endLine);
166
+ }
167
+ // Utils.writeXs(`${this.settings.config.snapshot_dir}bind`, cmds)
168
+ Utils.writeXs(`${this.settings.work_dir.ovarium}bind`, cmds);
169
+ }
170
+ /**
171
+ * bind dei virtual file system
172
+ */
173
+ async bindVfs() {
174
+ if (this.verbose) {
175
+ console.log('Ovary: bindVfs');
176
+ }
177
+ const cmds = [];
178
+ cmds.push(`mount -o bind /dev ${this.settings.work_dir.merged}/dev`, `mount -o bind /dev/pts ${this.settings.work_dir.merged}/dev/pts`, `mount -o bind /proc ${this.settings.work_dir.merged}/proc`, `mount -o bind /sys ${this.settings.work_dir.merged}/sys`, `mount -o bind /run ${this.settings.work_dir.merged}/run`);
179
+ // Utils.writeXs(`${this.settings.config.snapshot_dir}bindvfs`, cmds)
180
+ Utils.writeXs(`${this.settings.work_dir.ovarium}bindvfs`, cmds);
181
+ }
182
+ /**
183
+ *
184
+ * @param verbose
185
+ */
186
+ async cleanUsersAccounts() {
187
+ if (this.verbose) {
188
+ console.log('Ovary: cleanUsersAccounts');
189
+ }
190
+ /**
191
+ * delete all user in chroot
192
+ */
193
+ const cmds = [];
194
+ const cmd = `chroot ${this.settings.work_dir.merged} getent passwd {1000..60000} |awk -F: '{print $1}'`;
195
+ const result = await exec(cmd, {
196
+ capture: true,
197
+ echo: this.verbose,
198
+ ignore: false
199
+ });
200
+ const users = result.data.split('\n');
201
+ let deluser = 'deluser';
202
+ if (this.familyId === 'archlinux') {
203
+ deluser = 'userdel';
204
+ }
205
+ for (let i = 0; i < users.length - 1; i++) {
206
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} ${deluser} ${users[i]}`, this.verbose));
207
+ }
208
+ }
209
+ /**
210
+ * list degli utenti: grep -E 1[0-9]{3} /etc/passwd | sed s/:/\ / | awk '{print $1}'
211
+ * create la home per user_opt
212
+ * @param verbose
213
+ */
214
+ async createUserLive() {
215
+ if (this.verbose) {
216
+ console.log('Ovary: createUserLive');
217
+ }
218
+ const cmds = [];
219
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' rm /home/' + this.settings.config.user_opt + ' -rf', this.verbose));
220
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' mkdir /home/' + this.settings.config.user_opt, this.verbose));
221
+ // Create user using useradd
222
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' useradd ' + this.settings.config.user_opt + ' --home-dir /home/' + this.settings.config.user_opt + ' --shell /bin/bash ', this.verbose));
223
+ // live password
224
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' echo ' + this.settings.config.user_opt + ':' + this.settings.config.user_opt_passwd + ' | chroot ' + this.settings.work_dir.merged + ' chpasswd', this.verbose));
225
+ // root password
226
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' echo root:' + this.settings.config.root_passwd + ' | chroot ' + this.settings.work_dir.merged + ' chpasswd', this.verbose));
227
+ // Alpine naked don't have /etc/skel
228
+ if (fs.existsSync('/etc/skel')) {
229
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' cp /etc/skel/. /home/' + this.settings.config.user_opt + ' -R', this.verbose));
230
+ }
231
+ // da problemi con il mount sshfs
232
+ cmds.push(await rexec('chroot ' + this.settings.work_dir.merged + ' chown ' + this.settings.config.user_opt + ':users' + ' /home/' + this.settings.config.user_opt + ' -R', this.verbose));
233
+ switch (this.familyId) {
234
+ case 'debian': {
235
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG sudo ${this.settings.config.user_opt}`, this.verbose));
236
+ break;
237
+ }
238
+ case 'alpine': {
239
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG cdrom ${this.settings.config.user_opt}`, this.verbose));
240
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG games ${this.settings.config.user_opt}`, this.verbose));
241
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG input ${this.settings.config.user_opt}`, this.verbose));
242
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG users ${this.settings.config.user_opt}`, this.verbose));
243
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG video ${this.settings.config.user_opt}`, this.verbose));
244
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG wheel ${this.settings.config.user_opt}`, this.verbose));
245
+ break;
246
+ }
247
+ case 'archlinux': {
248
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} gpasswd -a ${this.settings.config.user_opt} wheel`, this.verbose));
249
+ // check or create group: autologin
250
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} getent group autologin || chroot ${this.settings.work_dir.merged} groupadd autologin`, this.verbose));
251
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} gpasswd -a ${this.settings.config.user_opt} autologin`, this.verbose));
252
+ break;
253
+ }
254
+ // No default
255
+ }
256
+ /**
257
+ * educaandos and others themes
258
+ * users.yml
259
+ */
260
+ let usersConf = path.resolve(__dirname, `../../addons/${this.theme}/theme/calamares/users.yml`);
261
+ if (this.theme.includes('/')) {
262
+ usersConf = `${this.theme}/theme/calamares/modules/users.yml`;
263
+ }
264
+ if (fs.existsSync(usersConf)) {
265
+ const o = yaml.load(fs.readFileSync(usersConf, 'utf8'));
266
+ for (const group of o.defaultGroups) {
267
+ cmds.push(await rexec(`chroot ${this.settings.work_dir.merged} usermod -aG ${group} ${this.settings.config.user_opt}`, this.verbose));
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ *
273
+ */
274
+ async createXdgAutostart(theme = 'eggs', myAddons, myLinks = [], noicons = false) {
275
+ if (this.verbose) {
276
+ console.log('Ovary: createXdgAutostart');
277
+ }
278
+ const pathHomeLive = `/home/${this.settings.config.user_opt}`;
279
+ // VOGLIO le icone
280
+ // Copia icona penguins-eggs
281
+ shx.cp(path.resolve(__dirname, '../../assets/eggs.png'), '/usr/share/icons/');
282
+ shx.cp(path.resolve(__dirname, '../../assets/krill.svg'), '/usr/share/icons/');
283
+ shx.cp(path.resolve(__dirname, '../../assets/leaves.svg'), '/usr/share/icons/');
284
+ /**
285
+ * creazione dei link in /usr/share/applications
286
+ */
287
+ shx.cp(path.resolve(__dirname, '../../assets/penguins-eggs.desktop'), '/usr/share/applications/');
288
+ /**
289
+ * Scrivania/install-system.desktop
290
+ */
291
+ let installerUrl = 'install-system.desktop';
292
+ let installerIcon = 'install-system.sh';
293
+ if (Pacman.calamaresExists()) {
294
+ shx.cp(path.resolve(__dirname, `../../addons/${theme}/theme/applications/install-system.desktop`), `${this.settings.work_dir.merged}/usr/share/applications/`);
295
+ }
296
+ else if (Pacman.packageIsInstalled('live-installer')) {
297
+ // carico la policy per live-installer
298
+ const policySource = path.resolve(__dirname, '../../assets/live-installer/com.github.pieroproietti.penguins-eggs.policy');
299
+ const policyDest = '/usr/share/polkit-1/actions/com.github.pieroproietti.penguins-eggs.policy';
300
+ shx.cp(policySource, policyDest);
301
+ await exec(`sed -i 's/auth_admin/yes/' ${policyDest}`);
302
+ // carico in filesystem.live packages-remove
303
+ shx.cp(path.resolve(__dirname, '../../assets/live-installer/filesystem.packages-remove'), `${this.settings.iso_work}/live/`);
304
+ shx.touch(`${this.settings.iso_work}/live/filesystem.packages`);
305
+ installerUrl = 'penguins-live-installer.desktop';
306
+ installerIcon = 'utilities-terminal';
307
+ shx.cp(path.resolve(__dirname, '../../assets/penguins-live-installer.desktop'), `${this.settings.work_dir.merged}/usr/share/applications/`);
308
+ }
309
+ else {
310
+ installerUrl = 'penguins-krill.desktop';
311
+ installerIcon = 'utilities-terminal';
312
+ shx.cp(path.resolve(__dirname, '../../assets/penguins-krill.desktop'), `${this.settings.work_dir.merged}/usr/share/applications/`);
313
+ }
314
+ /**
315
+ * flags
316
+ */
317
+ // adapt
318
+ if (myAddons.adapt) {
319
+ const dirAddon = path.resolve(__dirname, '../../addons/eggs/adapt/');
320
+ shx.cp(`${dirAddon}/applications/eggs-adapt.desktop`, `${this.settings.work_dir.merged}/usr/share/applications/`);
321
+ }
322
+ // pve
323
+ if (myAddons.pve) {
324
+ /**
325
+ * create service pve-live
326
+ */
327
+ const pve = new PveLive();
328
+ pve.create(this.settings.work_dir.merged);
329
+ /**
330
+ * adding a desktop link for pve
331
+ */
332
+ const dirAddon = path.resolve(__dirname, '../../addons/eggs/pve');
333
+ shx.cp(`${dirAddon}/artwork/eggs-pve.png`, `${this.settings.work_dir.merged}/usr/share/icons/`);
334
+ shx.cp(`${dirAddon}/applications/eggs-pve.desktop`, `${this.settings.work_dir.merged}/usr/share/applications/`);
335
+ }
336
+ // rsupport
337
+ if (myAddons.rsupport) {
338
+ const dirAddon = path.resolve(__dirname, '../../addons/eggs/rsupport');
339
+ shx.cp(`${dirAddon}/applications/eggs-rsupport.desktop`, `${this.settings.work_dir.merged}/usr/share/applications/`);
340
+ shx.cp(`${dirAddon}/artwork/eggs-rsupport.png`, `${this.settings.work_dir.merged}/usr/share/icons/`);
341
+ }
342
+ /**
343
+ * configuro add-penguins-desktop-icons in /etc/xdg/autostart
344
+ */
345
+ const dirAutostart = `${this.settings.work_dir.merged}/etc/xdg/autostart`;
346
+ if (fs.existsSync(dirAutostart)) {
347
+ // Creo l'avviatore xdg: DEVE essere add-penguins-links.desktop
348
+ shx.cp(path.resolve(__dirname, '../../assets/penguins-links-add.desktop'), dirAutostart);
349
+ // create /usr/bin/penguins-links-add.sh
350
+ const script = '/usr/bin/penguins-links-add.sh';
351
+ let text = '';
352
+ text += '#!/bin/sh\n';
353
+ text += 'DESKTOP=$(xdg-user-dir DESKTOP)\n';
354
+ text += 'while [ ! -d "$DESKTOP" ]; do\n';
355
+ text += ' DESKTOP=$(xdg-user-dir DESKTOP)\n';
356
+ text += ' sleep 1\n';
357
+ text += 'done\n';
358
+ text += `cp /usr/share/applications/${installerUrl} "$DESKTOP"\n`;
359
+ if (Pacman.packageIsInstalled('lxde-core')) {
360
+ if (!noicons) {
361
+ text += this.lxdeLink('penguins-eggs.desktop', "Penguins' eggs", 'eggs');
362
+ }
363
+ if (myAddons.adapt)
364
+ text += this.lxdeLink('eggs-adapt.desktop', 'Adapt', 'video-display');
365
+ if (myAddons.pve)
366
+ text += this.lxdeLink('eggs-pve.desktop', 'Proxmox VE', 'proxmox-ve');
367
+ if (myAddons.rsupport)
368
+ text += this.lxdeLink('eggs-rsupport.desktop', 'Remote assistance', 'remote-assistance');
369
+ }
370
+ else {
371
+ if (!noicons) {
372
+ text += 'cp /usr/share/applications/penguins-eggs.desktop "$DESKTOP"\n';
373
+ }
374
+ if (myLinks.length > 0) {
375
+ for (const link of myLinks) {
376
+ text += `cp /usr/share/applications/${link}.desktop "$DESKTOP"\n`;
377
+ }
378
+ }
379
+ if (myAddons.adapt)
380
+ text += 'cp /usr/share/applications/eggs-adapt.desktop "$DESKTOP"\n';
381
+ if (myAddons.pve)
382
+ text += 'cp /usr/share/applications/eggs-pve.desktop "$DESKTOP"\n';
383
+ if (myAddons.rsupport)
384
+ text += 'cp /usr/share/applications/eggs-rsupport.desktop "$DESKTOP"\n';
385
+ }
386
+ /**
387
+ * enable desktop links
388
+ */
389
+ if (Pacman.packageIsInstalled('gdm3') || Pacman.packageIsInstalled('gdm')) {
390
+ // GNOME
391
+ text += 'test -f /usr/share/applications/penguins-eggs.desktop && cp /usr/share/applications/penguins-eggs.desktop "$DESKTOP"\n';
392
+ text += 'test -f "$DESKTOP"/op && chmod a+x "$DESKTOP"/penguins-eggs.desktop\n';
393
+ text += 'test -f "$DESKTOP"/penguins-eggs.desktop && gio set "$DESKTOP"/penguins-eggs.desktop metadata::trusted true\n';
394
+ text += `test -f /usr/share/applications/${installerUrl} && cp /usr/share/applications/${installerUrl} "$DESKTOP"\n`;
395
+ text += `test -f "$DESKTOP"/${installerUrl} && chmod a+x "$DESKTOP"/${installerUrl}\n`;
396
+ text += `test -f "$DESKTOP"/${installerUrl} && gio set "$DESKTOP"/${installerUrl} metadata::trusted true\n`;
397
+ }
398
+ else if (Pacman.packageIsInstalled('xfce4-session')) {
399
+ // f=FILE; gio set -t string $f metadata::xfce-exe-checksum "$(sha256sum $f | awk '{print $1}')"
400
+ text += 'chmod +x "$DESKTOP"/*.desktop';
401
+ // await exec(`f="$DESKTOP"/*.desktop; gio set -t string $f metadata::xfce-exe-checksum "$(sha256sum $f | awk '{print $1}')"`)
402
+ }
403
+ else {
404
+ // OTHERS: CINNAMON/KDE/ETC
405
+ text += 'chmod +x "$DESKTOP"/*.desktop';
406
+ }
407
+ fs.writeFileSync(script, text, 'utf8');
408
+ await exec(`chmod a+x ${script}`, this.echo);
409
+ }
410
+ await Xdg.autologin(await Utils.getPrimaryUser(), this.settings.config.user_opt, this.settings.work_dir.merged);
411
+ }
412
+ /**
413
+ * editLiveFs
414
+ * - Truncate logs, remove archived log
415
+ * - Allow all fixed drives to be mounted with pmount
416
+ * - Enable or disable password login trhough ssh for users (not root)
417
+ * - Create an empty /etc/fstab
418
+ * - Blanck /etc/machine-id
419
+ * - Add some basic files to /dev
420
+ * - Clear configs from /etc/network/interfaces, wicd and NetworkManager and netman
421
+ */
422
+ async editLiveFs(clone = false, cryptedclone = false) {
423
+ if (this.verbose) {
424
+ console.log('Ovary: editLiveFs');
425
+ }
426
+ /**
427
+ * /etc/penguins-eggs.d/is_clone file created on live
428
+ */
429
+ if (clone) {
430
+ await exec(`touch ${this.settings.work_dir.merged}/etc/penguins-eggs.d/is_clone`, this.echo);
431
+ }
432
+ /**
433
+ * /etc/penguins-eggs.d/is_crypted_clone file created on live
434
+ */
435
+ if (cryptedclone) {
436
+ await exec(`touch ${this.settings.work_dir.merged}/etc/penguins-eggs.d/is_crypted_clone`, this.echo);
437
+ }
438
+ /**
439
+ * /etc/default/epoptes-client created on live
440
+ */
441
+ if (Pacman.packageIsInstalled('epoptes')) {
442
+ const file = `${this.settings.work_dir.merged}/etc/default/epoptes-client`;
443
+ const text = `SERVER=${os.hostname}.local\n`;
444
+ fs.writeFileSync(file, text);
445
+ }
446
+ if (this.familyId === 'debian') {
447
+ // Aggiungo UMASK=0077 in /etc/initramfs-tools/conf.d/calamares-safe-initramfs.conf
448
+ const text = 'UMASK=0077\n';
449
+ const file = '/etc/initramfs-tools/conf.d/eggs-safe-initramfs.conf';
450
+ Utils.write(file, text);
451
+ }
452
+ // Truncate logs, remove archived logs.
453
+ let cmd = `find ${this.settings.work_dir.merged}/var/log -name "*gz" -print0 | xargs -0r rm -f`;
454
+ await exec(cmd, this.echo);
455
+ cmd = `find ${this.settings.work_dir.merged}/var/log/ -type f -exec truncate -s 0 {} \\;`;
456
+ await exec(cmd, this.echo);
457
+ // Allow all fixed drives to be mounted with pmount
458
+ if (this.settings.config.pmount_fixed && fs.existsSync(`${this.settings.work_dir.merged}/etc/pmount.allow`)) {
459
+ // MX aggiunto /etc
460
+ await exec(`sed -i 's:#/dev/sd\[a-z\]:/dev/sd\[a-z\]:' ${this.settings.work_dir.merged}/etc/pmount.allow`, this.echo);
461
+ }
462
+ // Remove obsolete live-config file
463
+ if (fs.existsSync(`${this.settings.work_dir.merged}lib/live/config/1161-openssh-server`)) {
464
+ await exec(`rm -f ${this.settings.work_dir.merged}/lib/live/config/1161-openssh-server`, this.echo);
465
+ }
466
+ if (fs.existsSync(`${this.settings.work_dir.merged}/etc/ssh/sshd_config`)) {
467
+ /**
468
+ * enable/disable SSH root/users password login
469
+ */
470
+ await exec(`sed -i '/PermitRootLogin/d' ${this.settings.work_dir.merged}/etc/ssh/sshd_config`);
471
+ await exec(`sed -i '/PasswordAuthentication/d' ${this.settings.work_dir.merged}/etc/ssh/sshd_config`);
472
+ if (this.settings.config.ssh_pass) {
473
+ /** removed on 2023-12-28
474
+ * await exec(`echo 'PermitRootLogin yes' | tee -a ${this.settings.work_dir.merged}/etc/ssh/sshd_config`)
475
+ */
476
+ await exec(`echo 'PasswordAuthentication yes' | tee -a ${this.settings.work_dir.merged}/etc/ssh/sshd_config`);
477
+ }
478
+ else {
479
+ await exec(`echo 'PermitRootLogin prohibit-password' | tee -a ${this.settings.work_dir.merged}/etc/ssh/sshd_config`);
480
+ await exec(`echo 'PasswordAuthentication no' | tee -a ${this.settings.work_dir.merged}/etc/ssh/sshd_config`);
481
+ }
482
+ }
483
+ /**
484
+ * ufw --force reset
485
+ */
486
+ // if (Pacman.packageIsInstalled('ufw')) {
487
+ // await exec('ufw --force reset')
488
+ // }
489
+ /**
490
+ * /etc/fstab should exist, even if it's empty,
491
+ * to prevent error messages at boot
492
+ */
493
+ await exec(`rm ${this.settings.work_dir.merged}/etc/fstab`, this.echo);
494
+ await exec(`touch ${this.settings.work_dir.merged}/etc/fstab`, this.echo);
495
+ /**
496
+ * Remove crypttab if exists
497
+ * this is crucial for tpm systems.
498
+ */
499
+ if (fs.existsSync(`${this.settings.work_dir.merged}/etc/crypttab`)) {
500
+ await exec(`rm ${this.settings.work_dir.merged}/etc/crypttab`, this.echo);
501
+ }
502
+ /**
503
+ * Blank out systemd machine id.
504
+ * If it does not exist, systemd-journald will fail,
505
+ * but if it exists and is empty, systemd will automatically
506
+ * set up a new unique ID.
507
+ */
508
+ if (fs.existsSync(`${this.settings.work_dir.merged}/etc/machine-id`)) {
509
+ await exec(`rm ${this.settings.work_dir.merged}/etc/machine-id`, this.echo);
510
+ await exec(`touch ${this.settings.work_dir.merged}/etc/machine-id`, this.echo);
511
+ Utils.write(`${this.settings.work_dir.merged}/etc/machine-id`, ':');
512
+ }
513
+ /**
514
+ * LMDE4: utilizza UbuntuMono16.pf2
515
+ * aggiungo un link a /boot/grub/fonts/UbuntuMono16.pf2
516
+ */
517
+ shx.cp(`${this.settings.work_dir.merged}/boot/grub/fonts/unicode.pf2`, `${this.settings.work_dir.merged}/boot/grub/fonts/UbuntuMono16.pf2`);
518
+ /**
519
+ * cleaning /etc/resolv.conf
520
+ */
521
+ const resolvFile = `${this.settings.work_dir.merged}/etc/resolv.conf`;
522
+ shx.rm(resolvFile);
523
+ /**
524
+ * Per tutte le distro systemd
525
+ */
526
+ if (Utils.isSystemd()) {
527
+ const systemdctl = new Systemctl(this.verbose);
528
+ /**
529
+ * systemd-systemd-resolved
530
+ */
531
+ let resolvContent = '';
532
+ if (await systemdctl.isActive('systemd-resolved.service')) {
533
+ await systemdctl.stop('systemd-resolved.service');
534
+ resolvContent = 'nameserver 127.0.0.53\noptions edns0 trust-ad\nsearch .\n';
535
+ }
536
+ fs.writeFileSync(resolvFile, resolvContent);
537
+ if (await systemdctl.isEnabled('systemd-networkd.service')) {
538
+ await systemdctl.disable('systemd-networkd.service', this.settings.work_dir.merged, true);
539
+ }
540
+ if (await systemdctl.isEnabled('remote-cryptsetup.target')) {
541
+ await systemdctl.disable('remote-cryptsetup.target', this.settings.work_dir.merged, true);
542
+ }
543
+ if (await systemdctl.isEnabled('speech-dispatcherd.service')) {
544
+ await systemdctl.disable('speech-dispatcherd.service', this.settings.work_dir.merged, true);
545
+ }
546
+ if (await systemdctl.isEnabled('wpa_supplicant-nl80211@.service')) {
547
+ await systemdctl.disable('wpa_supplicant-nl80211@.service', this.settings.work_dir.merged, true);
548
+ }
549
+ if (await systemdctl.isEnabled('wpa_supplicant@.service')) {
550
+ await systemdctl.disable('wpa_supplicant@.service', this.settings.work_dir.merged, true);
551
+ }
552
+ if (await systemdctl.isEnabled('wpa_supplicant-wired@.service')) {
553
+ await systemdctl.disable('wpa_supplicant-wired@.service', this.settings.work_dir.merged, true);
554
+ }
555
+ /**
556
+ * All systemd distros rm
557
+ */
558
+ await exec(`rm -f ${this.settings.work_dir.merged}/var/lib/wicd/configurations/*`, this.echo);
559
+ await exec(`rm -f ${this.settings.work_dir.merged}/etc/wicd/wireless-settings.conf`, this.echo);
560
+ await exec(`rm -f ${this.settings.work_dir.merged}/etc/NetworkManager/system-connections/*`, this.echo);
561
+ await exec(`rm -f ${this.settings.work_dir.merged}/etc/network/wifi/*`, this.echo);
562
+ /**
563
+ * removing from /etc/network/:
564
+ * if-down.d if-post-down.d if-pre-up.d if-up.d interfaces interfaces.d
565
+ */
566
+ const cleanDirs = ['if-down.d', 'if-post-down.d', 'if-pre-up.d', 'if-up.d', 'interfaces.d'];
567
+ let cleanDir = '';
568
+ for (cleanDir of cleanDirs) {
569
+ await exec(`rm -f ${this.settings.work_dir.merged}/etc/network/${cleanDir}/wpasupplicant`, this.echo);
570
+ }
571
+ }
572
+ /**
573
+ * Clear configs from /etc/network/interfaces, wicd and NetworkManager
574
+ * and netman, so they aren't stealthily included in the snapshot.
575
+ */
576
+ if (this.familyId === 'debian') {
577
+ if (fs.existsSync(`${this.settings.work_dir.merged}/etc/network/interfaces`)) {
578
+ await exec(`rm -f ${this.settings.work_dir.merged}/etc/network/interfaces`, this.echo);
579
+ Utils.write(`${this.settings.work_dir.merged}/etc/network/interfaces`, 'auto lo\niface lo inet loopback');
580
+ }
581
+ /**
582
+ * add some basic files to /dev
583
+ */
584
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/console`)) {
585
+ await exec(`mknod -m 622 ${this.settings.work_dir.merged}/dev/console c 5 1`, this.echo);
586
+ }
587
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/null`)) {
588
+ await exec(`mknod -m 666 ${this.settings.work_dir.merged}/dev/null c 1 3`, this.echo);
589
+ }
590
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/zero`)) {
591
+ await exec(`mknod -m 666 ${this.settings.work_dir.merged}/dev/zero c 1 5`, this.echo);
592
+ }
593
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/ptmx`)) {
594
+ await exec(`mknod -m 666 ${this.settings.work_dir.merged}/dev/ptmx c 5 2`, this.echo);
595
+ }
596
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/tty`)) {
597
+ await exec(`mknod -m 666 ${this.settings.work_dir.merged}/dev/tty c 5 0`, this.echo);
598
+ }
599
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/random`)) {
600
+ await exec(`mknod -m 444 ${this.settings.work_dir.merged}/dev/random c 1 8`, this.echo);
601
+ }
602
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/urandom`)) {
603
+ await exec(`mknod -m 444 ${this.settings.work_dir.merged}/dev/urandom c 1 9`, this.echo);
604
+ }
605
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/{console,ptmx,tty}`)) {
606
+ await exec(`chown -v root:tty ${this.settings.work_dir.merged}/dev/{console,ptmx,tty}`, this.echo);
607
+ }
608
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/fd`)) {
609
+ await exec(`ln -sv /proc/self/fd ${this.settings.work_dir.merged}/dev/fd`, this.echo);
610
+ }
611
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/stdin`)) {
612
+ await exec(`ln -sv /proc/self/fd/0 ${this.settings.work_dir.merged}/dev/stdin`, this.echo);
613
+ }
614
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/stdout`)) {
615
+ await exec(`ln -sv /proc/self/fd/1 ${this.settings.work_dir.merged}/dev/stdout`, this.echo);
616
+ }
617
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/stderr`)) {
618
+ await exec(`ln -sv /proc/self/fd/2 ${this.settings.work_dir.merged}/dev/stderr`, this.echo);
619
+ }
620
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/core`)) {
621
+ await exec(`ln -sv /proc/kcore ${this.settings.work_dir.merged}/dev/core`, this.echo);
622
+ }
623
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/shm`)) {
624
+ await exec(`mkdir -v ${this.settings.work_dir.merged}/dev/shm`, this.echo);
625
+ }
626
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/pts`)) {
627
+ await exec(`mkdir -v ${this.settings.work_dir.merged}/dev/pts`, this.echo);
628
+ }
629
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/dev/shm`)) {
630
+ await exec(`chmod 1777 ${this.settings.work_dir.merged}/dev/shm`, this.echo);
631
+ }
632
+ /**
633
+ * creo /tmp
634
+ */
635
+ if (!fs.existsSync(`${this.settings.work_dir.merged}/tmp`)) {
636
+ await exec(`mkdir ${this.settings.work_dir.merged}/tmp`, this.echo);
637
+ }
638
+ /**
639
+ * Assegno 1777 a /tmp creava problemi con MXLINUX
640
+ */
641
+ await exec(`chmod 1777 ${this.settings.work_dir.merged}/tmp`, this.echo);
642
+ }
643
+ }
644
+ /**
645
+ * @returns {boolean} success
646
+ */
647
+ async fertilization(snapshot_prefix = '', snapshot_basename = '', theme = '', compression = '', nointeratctive = false) {
648
+ this.settings = new Settings();
649
+ if (await this.settings.load()) {
650
+ await this.settings.loadRemix(this.theme);
651
+ this.volid = Utils.getVolid(this.settings.remix.name);
652
+ this.familyId = this.settings.distro.familyId;
653
+ this.nest = this.settings.config.snapshot_mnt;
654
+ if (snapshot_prefix !== '') {
655
+ this.settings.config.snapshot_prefix = snapshot_prefix;
656
+ }
657
+ if (snapshot_basename !== '') {
658
+ this.settings.config.snapshot_basename = snapshot_basename;
659
+ }
660
+ if (theme !== '') {
661
+ this.theme = theme;
662
+ }
663
+ if (compression !== '') {
664
+ this.settings.config.compression = compression;
665
+ }
666
+ if (!nointeratctive) {
667
+ return true;
668
+ }
669
+ this.settings.listFreeSpace();
670
+ if (await Utils.customConfirm('Select yes to continue...')) {
671
+ return true;
672
+ }
673
+ }
674
+ return false;
675
+ }
676
+ /**
677
+ * finished = show the results
678
+ * @param scriptOnly
679
+ */
680
+ finished(scriptOnly = false) {
681
+ Utils.titles('produce');
682
+ if (scriptOnly) {
683
+ console.log('eggs is finished!\n\nYou can find the scripts to build iso: ' + chalk.cyanBright(this.settings.isoFilename) + '\nin the ovarium: ' + chalk.cyanBright(this.settings.config.snapshot_dir) + '.');
684
+ console.log('usage');
685
+ console.log(chalk.cyanBright(`cd ${this.settings.config.snapshot_dir}`));
686
+ console.log(chalk.cyanBright('sudo ./bind'));
687
+ console.log('Make all yours modifications in the directories filesystem.squashfs and iso.');
688
+ console.log('After when you are ready:');
689
+ console.log(chalk.cyanBright('sudo ./mksquashfs'));
690
+ console.log(chalk.cyanBright('sudo ./mkisofs'));
691
+ console.log(chalk.cyanBright('sudo ./ubind'));
692
+ console.log('happy hacking!');
693
+ }
694
+ else {
695
+ console.log('eggs is finished!\n\nYou can find the file iso: ' + chalk.cyanBright(this.settings.isoFilename) + '\nin the nest: ' + chalk.cyanBright(this.settings.config.snapshot_dir) + '.');
696
+ }
697
+ console.log();
698
+ console.log('Remember, on liveCD user = ' + chalk.cyanBright(this.settings.config.user_opt) + '/' + chalk.cyanBright(this.settings.config.user_opt_passwd));
699
+ console.log(' root = ' + chalk.cyanBright('root') + '/' + chalk.cyanBright(this.settings.config.root_passwd));
700
+ if (this.genisoimage) {
701
+ console.log(`Note: format UDF, generated by ${chalk.cyanBright('genisoimage')}`);
702
+ }
703
+ }
704
+ /**
705
+ * initrdAlpine()
706
+ */
707
+ async initrdAlpine() {
708
+ Utils.warning(`creating ${path.basename(this.settings.initrdImg)} Alpine on ISO/live`);
709
+ const initrdImg = 'initramfs-lts';
710
+ // dracut
711
+ // const pathConf = path.resolve(__dirname, `../../dracut/dracut.conf.d`)
712
+ // await exec(`dracut --confdir ${pathConf} ${this.settings.iso_work}live/${initrdImg}`, Utils.setEcho(true))
713
+ // mkinitfs
714
+ const pathConf = path.resolve(__dirname, `../../mkinitfs/live.conf`);
715
+ await exec(`mkinitfs -c ${pathConf} -o ${this.settings.iso_work}live/${initrdImg}`, Utils.setEcho(true));
716
+ const sidecars = path.resolve(__dirname, `../../mkinitfs/*.sh`);
717
+ await exec(`cp ${sidecars} ${this.settings.iso_work}live/`);
718
+ }
719
+ /**
720
+ * initrdArch()
721
+ * necessita di echoYes
722
+ */
723
+ async initrdArch() {
724
+ let initrdImg = Utils.initrdImg();
725
+ initrdImg = initrdImg.slice(Math.max(0, initrdImg.lastIndexOf('/') + 1));
726
+ Utils.warning(`creating ${path.basename(this.settings.initrdImg)} ArchLinux on ISO/live`);
727
+ const { distroId } = this.settings.distro;
728
+ let fileConf = 'arch';
729
+ if (isMiso(distroId)) {
730
+ fileConf = 'manjarolinux';
731
+ if (distroId.toLowerCase().includes('biglinux')) {
732
+ fileConf = 'biglinux';
733
+ }
734
+ }
735
+ const pathConf = path.resolve(__dirname, `../../mkinitcpio/${fileConf}/live.conf`);
736
+ await exec(`mkinitcpio -c ${pathConf} -g ${this.settings.iso_work}live/${initrdImg}`, Utils.setEcho(true));
737
+ }
738
+ /**
739
+ * initrdDebian()
740
+ * Actually based on live* packages
741
+ * We must upgrade to initrdCreate for Debian/Ubuntu
742
+ */
743
+ async initrdDebian(verbose = false) {
744
+ Utils.warning(`creating ${path.basename(this.settings.initrdImg)} Debian/Devuan/Ubuntu on ISO/live`);
745
+ let isCrypted = false;
746
+ if (fs.existsSync('/etc/crypttab')) {
747
+ isCrypted = true;
748
+ await exec('mv /etc/crypttab /etc/crypttab.saved', this.echo);
749
+ }
750
+ await exec(`mkinitramfs -o ${this.settings.iso_work}/live/initrd.img-$(uname -r) ${this.toNull}`, this.echo);
751
+ if (isCrypted) {
752
+ await exec('mv /etc/crypttab.saved /etc/crypttab', this.echo);
753
+ }
754
+ }
755
+ /**
756
+ * initrdFedora()
757
+ */
758
+ async initrdFedora() {
759
+ Utils.warning(`creating ${path.basename(this.settings.initrdImg)} Fedora on ISO/live`);
760
+ // dracut
761
+ const kernelVersion = shx.exec('uname -r', { silent: true }).stdout.trim();
762
+ const initrdImg = `initramfs-${kernelVersion}`;
763
+ const pathConf = path.resolve(__dirname, `../../dracut/dracut.conf.d`);
764
+ await exec(`dracut --confdir ${pathConf} ${this.settings.iso_work}live/${initrdImg}`, Utils.setEcho(true));
765
+ // await exec(`cp /boot/initramfs-*.img ${this.settings.iso_work}/live/`, this.echo)
766
+ }
767
+ /**
768
+ * initrdSuse()
769
+ */
770
+ async initrdSuse() {
771
+ Utils.warning(`creating ${path.basename(this.settings.initrdImg)} Fedora on ISO/live`);
772
+ await exec(`cp /boot/initrd-* ${this.settings.iso_work}/live/`, this.echo);
773
+ }
774
+ /**
775
+ * async isolinux
776
+ */
777
+ async isolinux(theme = 'eggs') {
778
+ if (this.verbose) {
779
+ console.log('Ovary: isolinux');
780
+ }
781
+ /**
782
+ * isolinux.bin
783
+ */
784
+ await exec(`cp ${this.settings.distro.isolinuxPath}/isolinux.bin ${this.settings.iso_work}/isolinux/`, this.echo);
785
+ /**
786
+ * isolinux.theme.cfg
787
+ */
788
+ const isolinuxThemeDest = this.settings.iso_work + 'isolinux/isolinux.theme.cfg';
789
+ let isolinuxThemeSrc = path.resolve(__dirname, `../../addons/${theme}/theme/livecd/isolinux.theme.cfg`);
790
+ if (this.theme.includes('/')) {
791
+ isolinuxThemeSrc = `${theme}/theme/livecd/isolinux.theme.cfg`;
792
+ }
793
+ if (!fs.existsSync(isolinuxThemeSrc)) {
794
+ Utils.warning('Cannot find: ' + isolinuxThemeSrc);
795
+ process.exit();
796
+ }
797
+ fs.copyFileSync(isolinuxThemeSrc, isolinuxThemeDest);
798
+ /**
799
+ * isolinux.cfg from isolinux.main.cfg
800
+ */
801
+ const isolinuxDest = `${this.settings.iso_work}/isolinux/isolinux.cfg`;
802
+ this.settings.iso_work + 'isolinux/isolinux.cfg';
803
+ let isolinuxTemplate = `${theme}/theme/livecd/isolinux.main.cfg`;
804
+ if (!fs.existsSync(isolinuxTemplate)) {
805
+ // isolinuxTemplate = path.resolve(__dirname, '../../addons/templates/isolinux.main.cfg')
806
+ isolinuxTemplate = path.resolve(__dirname, '../../addons/eggs/theme/livecd/isolinux.main.cfg');
807
+ }
808
+ if (!fs.existsSync(isolinuxTemplate)) {
809
+ Utils.warning('Cannot find: ' + isolinuxTemplate);
810
+ process.exit();
811
+ }
812
+ const kernel_parameters = this.kernelParameters();
813
+ const template = fs.readFileSync(isolinuxTemplate, 'utf8');
814
+ const view = {
815
+ fullname: this.settings.remix.fullname.toUpperCase(),
816
+ initrdImg: `/live${this.settings.initrdImg}`,
817
+ kernel: Utils.kernelVersion(),
818
+ kernel_parameters,
819
+ vmlinuz: `/live${this.settings.vmlinuz}`
820
+ };
821
+ fs.writeFileSync(isolinuxDest, mustache.render(template, view));
822
+ /**
823
+ * splash
824
+ */
825
+ const splashDest = `${this.settings.iso_work}/isolinux/splash.png`;
826
+ let splashSrc = path.resolve(__dirname, `../../addons/${theme}/theme/livecd/splash.png`);
827
+ if (this.theme.includes('/')) {
828
+ splashSrc = path.resolve(`${theme}/theme/livecd/splash.png`);
829
+ }
830
+ if (!fs.existsSync(splashSrc)) {
831
+ Utils.warning('Cannot find: ' + splashSrc);
832
+ process.exit();
833
+ }
834
+ fs.copyFileSync(splashSrc, splashDest);
835
+ }
836
+ /**
837
+ * kernelCopy
838
+ */
839
+ async kernelCopy() {
840
+ Utils.warning(`copying ${path.basename(this.settings.kernel_image)} on ISO/live`);
841
+ let lackVmlinuzImage = false;
842
+ if (fs.existsSync(this.settings.kernel_image)) {
843
+ await exec(`cp ${this.settings.kernel_image} ${this.settings.iso_work}live/`, this.echo);
844
+ }
845
+ else {
846
+ Utils.error(`Cannot find ${this.settings.kernel_image}`);
847
+ lackVmlinuzImage = true;
848
+ }
849
+ if (lackVmlinuzImage) {
850
+ Utils.warning('Try to edit /etc/penguins-eggs.d/eggs.yaml and check for');
851
+ Utils.warning(`vmlinuz: ${this.settings.kernel_image}`);
852
+ process.exit(1);
853
+ }
854
+ }
855
+ /**
856
+ *
857
+ * @returns kernelParameters
858
+ */
859
+ kernelParameters() {
860
+ if (this.verbose) {
861
+ console.log('Ovary: kernelParameters');
862
+ }
863
+ // GRUB_CMDLINE_LINUX='ipv6.disable=1'
864
+ const { distroId } = this.settings.distro;
865
+ let kp = `boot=live components locales=${process.env.LANG}`;
866
+ if (this.familyId === 'archlinux') {
867
+ kp += isMiso(distroId) ? ` misobasedir=manjaro misolabel=${this.volid}` : ` archisobasedir=arch archisolabel=${this.volid}`;
868
+ }
869
+ kp += ` cow_spacesize=4G`;
870
+ return kp;
871
+ }
872
+ /**
873
+ * Crea la struttura della workdir
874
+ */
875
+ async liveCreateStructure() {
876
+ if (this.verbose) {
877
+ console.log('Ovary: liveCreateStructure');
878
+ }
879
+ Utils.warning(`creating egg in ${this.settings.config.snapshot_dir}`);
880
+ let cmd;
881
+ if (!fs.existsSync(this.settings.config.snapshot_dir)) {
882
+ cmd = `mkdir -p ${this.settings.config.snapshot_dir}`;
883
+ this.tryCatch(cmd);
884
+ }
885
+ if (!fs.existsSync(this.settings.config.snapshot_dir + '/README.md')) {
886
+ cmd = `cp ${path.resolve(__dirname, '../../conf/README.md')} ${this.settings.config.snapshot_dir}README.md`;
887
+ this.tryCatch(cmd);
888
+ }
889
+ // Ovarium
890
+ if (!fs.existsSync(this.settings.work_dir.ovarium)) {
891
+ cmd = `mkdir -p ${this.settings.work_dir.ovarium}`;
892
+ this.tryCatch(cmd);
893
+ }
894
+ if (!fs.existsSync(this.settings.work_dir.lowerdir)) {
895
+ cmd = `mkdir -p ${this.settings.work_dir.lowerdir}`;
896
+ this.tryCatch(cmd);
897
+ }
898
+ if (!fs.existsSync(this.settings.work_dir.upperdir)) {
899
+ cmd = `mkdir -p ${this.settings.work_dir.upperdir}`;
900
+ this.tryCatch(cmd);
901
+ }
902
+ if (!fs.existsSync(this.settings.work_dir.workdir)) {
903
+ cmd = `mkdir -p ${this.settings.work_dir.workdir}`;
904
+ this.tryCatch(cmd);
905
+ }
906
+ if (!fs.existsSync(this.settings.work_dir.merged)) {
907
+ cmd = `mkdir -p ${this.settings.work_dir.merged}`;
908
+ this.tryCatch(cmd);
909
+ }
910
+ /**
911
+ * Creo le directory di destinazione per boot, efi, isolinux e live
912
+ */
913
+ if (!fs.existsSync(this.settings.iso_work)) {
914
+ cmd = `mkdir -p ${this.settings.iso_work}boot/grub/${Utils.uefiFormat()}`;
915
+ this.tryCatch(cmd);
916
+ cmd = `mkdir -p ${this.settings.iso_work}efi/boot`;
917
+ this.tryCatch(cmd);
918
+ cmd = `mkdir -p ${this.settings.iso_work}isolinux`;
919
+ this.tryCatch(cmd);
920
+ cmd = `mkdir -p ${this.settings.iso_work}live`;
921
+ this.tryCatch(cmd);
922
+ }
923
+ // ln iso
924
+ cmd = `ln -s ${this.settings.iso_work} ${this.settings.config.snapshot_dir}/iso`;
925
+ this.tryCatch(cmd);
926
+ // ln livefs
927
+ cmd = `ln -s ${this.settings.work_dir.merged} ${this.settings.config.snapshot_dir}/livefs`;
928
+ this.tryCatch(cmd);
929
+ }
930
+ /**
931
+ * makeDotDisk
932
+ */
933
+ makeDotDisk(info = '', mksquashfs = '', mkisofs = '') {
934
+ if (this.verbose) {
935
+ console.log('Ovary: makeDotDisk');
936
+ }
937
+ const dotDisk = this.settings.iso_work + '.disk';
938
+ if (fs.existsSync(dotDisk)) {
939
+ shx.rm('-rf', dotDisk);
940
+ }
941
+ shx.mkdir('-p', dotDisk);
942
+ let text = `# Created at: ${Utils.formatDate(new Date())}\n`;
943
+ text += `# penguins_eggs v. ${Utils.getPackageVersion()}\n`;
944
+ // .disk/info
945
+ fs.writeFileSync(dotDisk + '/info', text, 'utf-8');
946
+ // .disk/mksquashfs
947
+ fs.writeFileSync(dotDisk + '/mksquashfs', text + mksquashfs, 'utf-8');
948
+ // .disk/mkisofs
949
+ fs.writeFileSync(dotDisk + '/mkisofs', text + mkisofs, 'utf-8');
950
+ }
951
+ // #######################################################################################
952
+ async makeEfi(theme = 'eggs') {
953
+ if (this.verbose) {
954
+ console.log('Ovary: makeEfi');
955
+ }
956
+ const memdiskDir = this.settings.config.snapshot_mnt + 'memdiskDir';
957
+ const efiWorkDir = this.settings.efi_work;
958
+ const isoDir = this.settings.iso_work;
959
+ /**
960
+ * il pachetto grub/grub2 DEVE essere presente
961
+ */
962
+ const grubName = Pacman.whichGrubIsInstalled();
963
+ if (grubName === '') {
964
+ Utils.error('Something went wrong! Cannot find grub! Run lsb_release -a and check the result');
965
+ process.exit(1);
966
+ }
967
+ /**
968
+ * Creo o cancello e creo: memdiskDir
969
+ */
970
+ if (fs.existsSync(memdiskDir)) {
971
+ await exec(`rm ${memdiskDir} -rf`, this.echo);
972
+ }
973
+ Utils.warning('creating temporary memdiskDir on ' + memdiskDir);
974
+ await exec(`mkdir ${memdiskDir}`);
975
+ await exec(`mkdir ${memdiskDir}/boot`, this.echo);
976
+ await exec(`mkdir ${memdiskDir}/boot/grub`, this.echo);
977
+ /**
978
+ * for initial grub.cfg in memdisk
979
+ */
980
+ const grubCfg = `${memdiskDir}/boot/grub/grub.cfg`;
981
+ let text = '';
982
+ text += 'search --file --set=root /.disk/info\n';
983
+ text += 'set prefix=($root)/boot/grub\n';
984
+ text += `source $prefix/${Utils.uefiFormat()}/grub.cfg\n`;
985
+ Utils.write(grubCfg, text);
986
+ // #################################
987
+ /**
988
+ * start with empty efiWorkDir
989
+ */
990
+ if (fs.existsSync(efiWorkDir)) {
991
+ await exec(`rm ${efiWorkDir} -rf`, this.echo);
992
+ }
993
+ Utils.warning('creating temporary efiWordDir on ' + efiWorkDir);
994
+ await exec(`mkdir ${efiWorkDir}`, this.echo);
995
+ await exec(`mkdir ${efiWorkDir}boot`, this.echo);
996
+ await exec(`mkdir ${efiWorkDir}boot/grub`, this.echo);
997
+ await exec(`mkdir ${efiWorkDir}boot/grub/${Utils.uefiFormat()}`, this.echo);
998
+ await exec(`mkdir ${efiWorkDir}efi`, this.echo);
999
+ await exec(`mkdir ${efiWorkDir}efi/boot`, this.echo);
1000
+ /**
1001
+ * copy splash to efiWorkDir
1002
+ */
1003
+ const splashDest = `${efiWorkDir}boot/grub/splash.png`;
1004
+ let splashSrc = path.resolve(__dirname, `../../addons/${theme}/theme/livecd/splash.png`);
1005
+ if (this.theme.includes('/')) {
1006
+ splashSrc = `${theme}/theme/livecd/splash.png`;
1007
+ }
1008
+ if (!fs.existsSync(splashSrc)) {
1009
+ Utils.warning('Cannot find: ' + splashSrc);
1010
+ process.exit();
1011
+ }
1012
+ await exec(`cp ${splashSrc} ${splashDest}`, this.echo);
1013
+ /**
1014
+ * copy theme
1015
+ */
1016
+ const themeDest = `${efiWorkDir}boot/grub/theme.cfg`;
1017
+ let themeSrc = path.resolve(__dirname, `../../addons/${theme}/theme/livecd/grub.theme.cfg`);
1018
+ if (this.theme.includes('/')) {
1019
+ themeSrc = `${theme}/theme/livecd/grub.theme.cfg`;
1020
+ }
1021
+ if (!fs.existsSync(themeSrc)) {
1022
+ Utils.warning('Cannot find: ' + themeSrc);
1023
+ process.exit();
1024
+ }
1025
+ await exec(`cp ${themeSrc} ${themeDest}`, this.echo);
1026
+ /**
1027
+ * second grub.cfg file in efiWork
1028
+ */
1029
+ // for i in $(ls /usr/lib/grub/x86_64-efi |grep part_|grep \.mod|sed 's/.mod//'); do echo "insmod $i" >> boot/grub/x86_64-efi/grub.cfg; done
1030
+ let cmd = `for i in $(ls /usr/lib/grub/${Utils.uefiFormat()}|grep part_|grep \.mod|sed 's/.mod//'); do echo "insmod $i" >> ${efiWorkDir}boot/grub/${Utils.uefiFormat()}/grub.cfg; done`;
1031
+ await exec(cmd, this.echo);
1032
+ // cmd = `for i in efi_gop efi_uga ieee1275_fb vbe vga video_bochs video_cirrus jpeg png gfxterm ; do echo "insmod $i" >> ${efiWorkDir}boot/grub/${Utils.uefiFormat()}/grub.cfg ; done`
1033
+ cmd = `for i in efi_gop efi_uga ieee1275_fb vbe vga video_bochs video_cirrus jpeg png gfxterm ; do echo "insmod $i" >> ${efiWorkDir}boot/grub/${Utils.uefiFormat()}/grub.cfg ; done`;
1034
+ await exec(cmd, this.echo);
1035
+ await exec(`echo "source /boot/grub/grub.cfg" >> ${efiWorkDir}boot/grub/${Utils.uefiFormat()}/grub.cfg`, this.echo);
1036
+ /**
1037
+ * andiamo in memdiskDir
1038
+ */
1039
+ /**
1040
+ * make a tarred "memdisk" to embed in the grub image
1041
+ *
1042
+ * NOTE: it's CRUCIAL to chdir before tar!!!
1043
+ */
1044
+ const currentDir = process.cwd();
1045
+ process.chdir(memdiskDir);
1046
+ await exec('tar -cvf memdisk boot', this.echo);
1047
+ process.chdir(currentDir);
1048
+ // -O, --format=FORMAT
1049
+ // -m --memdisk=FILE embed FILE as a memdisk image
1050
+ // -o, --output=FILE embed FILE as a memdisk image
1051
+ // -p, --prefix=DIR set prefix directory
1052
+ // --format=x86_64-efi --memdisk=memdisk --output=bootx64.efi --prefix?DIR set prefix directory
1053
+ // grub-mkimage -O "x86_64-efi" -m "memdisk" -o "bootx64.efi" -p '(memdisk)/boot/grub' search iso9660 configfile normal memdisk tar cat part_msdos part_gpt fat ext2 ntfs ntfscomp hfsplus chain boot linux
1054
+ // arm64-efi
1055
+ await exec(`${grubName}-mkimage -O "${Utils.uefiFormat()}" \
1056
+ -m "${memdiskDir}/memdisk" \
1057
+ -o "${memdiskDir}/${Utils.uefiBN()}" \
1058
+ -p '(memdisk)/boot/grub' \
1059
+ search iso9660 configfile normal memdisk tar cat part_msdos part_gpt fat ext2 ntfs ntfscomp hfsplus chain boot linux`, this.echo);
1060
+ // popd torna in efiWorkDir
1061
+ // copy the grub image to efi/boot (to go later in the device's root)
1062
+ await exec(`cp ${memdiskDir}/${Utils.uefiBN()} ${efiWorkDir}efi/boot`, this.echo);
1063
+ // #######################
1064
+ // Do the boot image "boot/grub/efiboot.img"
1065
+ await exec(`dd if=/dev/zero of=${efiWorkDir}boot/grub/efiboot.img bs=1K count=1440`, this.echo);
1066
+ await exec(`/sbin/mkdosfs -F 12 ${efiWorkDir}boot/grub/efiboot.img`, this.echo);
1067
+ await exec(`mkdir ${efiWorkDir}img-mnt`, this.echo);
1068
+ await exec(`mount -o loop ${efiWorkDir}boot/grub/efiboot.img ${efiWorkDir}img-mnt`, this.echo);
1069
+ await exec(`mkdir ${efiWorkDir}img-mnt/efi`, this.echo);
1070
+ await exec(`mkdir ${efiWorkDir}img-mnt/efi/boot`, this.echo);
1071
+ // era cp -r
1072
+ await exec(`cp ${memdiskDir}/${Utils.uefiBN()} ${efiWorkDir}img-mnt/efi/boot`, this.echo);
1073
+ // #######################
1074
+ // copy modules and font
1075
+ await exec(`cp -r /usr/lib/grub/${Utils.uefiFormat()}/* ${efiWorkDir}boot/grub/${Utils.uefiFormat()}/`, this.echo);
1076
+ // if this doesn't work try another font from the same place (grub's default, unicode.pf2, is much larger)
1077
+ // Either of these will work, and they look the same to me. Unicode seems to work with qemu. -fsr
1078
+ if (fs.existsSync('/usr/share/grub/font.pf2')) {
1079
+ await exec(`cp /usr/share/grub/font.pf2 ${efiWorkDir}boot/grub/font.pf2`, this.echo);
1080
+ }
1081
+ else if (fs.existsSync('/usr/share/grub/unicode.pf2')) {
1082
+ await exec(`cp /usr/share/grub/unicode.pf2 ${efiWorkDir}boot/grub/font.pf2`, this.echo);
1083
+ }
1084
+ else if (fs.existsSync('/usr/share/grub/ascii.pf2')) {
1085
+ await exec(`cp /usr/share/grub/ascii.pf2 ${efiWorkDir}boot/grub/font.pf2`, this.echo);
1086
+ }
1087
+ // doesn't need to be root-owned
1088
+ // chown -R 1000:1000 $(pwd) 2>/dev/null
1089
+ // Cleanup efi temps
1090
+ await exec(`umount ${efiWorkDir}img-mnt`, this.echo);
1091
+ await exec(`rmdir ${efiWorkDir}img-mnt`, this.echo);
1092
+ await exec(`rm ${memdiskDir}/img-mnt -rf`, this.echo);
1093
+ // popd
1094
+ // Copy efi files to iso
1095
+ await exec(`rsync -avx ${efiWorkDir}boot ${isoDir}/`, this.echo);
1096
+ await exec(`rsync -avx ${efiWorkDir}efi ${isoDir}/`, this.echo);
1097
+ // Do the main grub.cfg (which gets loaded last):
1098
+ // grub.theme.cfg
1099
+ let grubThemeSrc = path.resolve(__dirname, `../../addons/${theme}/theme/livecd/grub.theme.cfg`);
1100
+ if (this.theme.includes('/')) {
1101
+ grubThemeSrc = `${theme}/theme/livecd/grub.theme.cfg`;
1102
+ }
1103
+ const grubThemeDest = `${isoDir}/boot/grub/theme.cfg`;
1104
+ if (!fs.existsSync(grubThemeSrc)) {
1105
+ Utils.warning('Cannot find: ' + grubThemeSrc);
1106
+ process.exit();
1107
+ }
1108
+ fs.copyFileSync(grubThemeSrc, grubThemeDest);
1109
+ /**
1110
+ * prepare grub.cfg from grub.main.cfg
1111
+ */
1112
+ let grubTemplate = `${theme}/theme/livecd/grub.main.cfg`;
1113
+ if (!fs.existsSync(grubTemplate)) {
1114
+ // grubTemplate = path.resolve(__dirname, '../../addons/templates/grub.main.cfg')
1115
+ grubTemplate = path.resolve(__dirname, '../../addons/eggs/theme/livecd/grub.main.cfg');
1116
+ }
1117
+ if (!fs.existsSync(grubTemplate)) {
1118
+ Utils.warning('Cannot find: ' + grubTemplate);
1119
+ process.exit();
1120
+ }
1121
+ const kernel_parameters = this.kernelParameters();
1122
+ const grubDest = `${isoDir}/boot/grub/grub.cfg`;
1123
+ const template = fs.readFileSync(grubTemplate, 'utf8');
1124
+ const view = {
1125
+ fullname: this.settings.remix.fullname.toUpperCase(),
1126
+ initrdImg: `/live${this.settings.initrdImg}`,
1127
+ kernel: Utils.kernelVersion(),
1128
+ kernel_parameters,
1129
+ vmlinuz: `/live${this.settings.vmlinuz}`
1130
+ };
1131
+ fs.writeFileSync(grubDest, mustache.render(template, view));
1132
+ /**
1133
+ * loopback.cfg
1134
+ */
1135
+ fs.writeFileSync(`${isoDir}/boot/grub/loopback.cfg`, 'source /boot/grub/grub.cfg\n');
1136
+ // console.log('end makeEfi')
1137
+ // process.exit()
1138
+ }
1139
+ /**
1140
+ * makeIso
1141
+ * cmd: cmd 4 xorirriso
1142
+ */
1143
+ async makeIso(cmd, scriptOnly = false) {
1144
+ // echo = { echo: true, ignore: false }
1145
+ if (this.verbose) {
1146
+ console.log('Ovary: makeIso');
1147
+ }
1148
+ Utils.writeX(`${this.settings.work_dir.ovarium}mkisofs`, cmd);
1149
+ // Create link to iso ALLWAYES
1150
+ const src = this.settings.config.snapshot_mnt + this.settings.isoFilename;
1151
+ const dest = this.settings.config.snapshot_dir + this.settings.isoFilename;
1152
+ await exec(`ln -s ${src} ${dest}`);
1153
+ if (!scriptOnly) {
1154
+ const test = (await exec(cmd, Utils.setEcho(true))).code;
1155
+ if (test !== 0) {
1156
+ process.exit();
1157
+ }
1158
+ // Create link to iso
1159
+ const src = this.settings.config.snapshot_mnt + this.settings.isoFilename;
1160
+ const dest = this.settings.config.snapshot_dir + this.settings.isoFilename;
1161
+ await exec(`ln -s ${src} ${dest}`);
1162
+ // Create md5sum, sha256sum
1163
+ if (this.settings.config.make_md5sum) {
1164
+ Utils.warning('creating md5, sha256');
1165
+ await exec(`md5sum ${src} > ${dest.replace('.iso', '.md5')}`);
1166
+ await exec(`sha256sum ${src} > ${dest.replace('.iso', '.sha256')}`);
1167
+ }
1168
+ }
1169
+ }
1170
+ /**
1171
+ * squashFs: crea in live filesystem.squashfs
1172
+ */
1173
+ async makeSquashfs(scriptOnly = false, unsecure = false) {
1174
+ if (this.verbose) {
1175
+ console.log('Ovary: makeSquashfs');
1176
+ }
1177
+ /**
1178
+ * exclude all the accurence of cryptdisks in rc0.d, etc
1179
+ */
1180
+ const fexcludes = ['/boot/efi/EFI', '/etc/fstab', '/etc/mtab', '/etc/udev/rules.d/70-persistent-cd.rules', '/etc/udev/rules.d/70-persistent-net.rules'];
1181
+ for (const i in fexcludes) {
1182
+ this.addRemoveExclusion(true, fexcludes[i]);
1183
+ }
1184
+ /**
1185
+ * Non sò che fa, ma sicuro non serve per archlinux
1186
+ */
1187
+ if (this.familyId === 'debian') {
1188
+ const rcd = ['rc0.d', 'rc1.d', 'rc2.d', 'rc3.d', 'rc4.d', 'rc5.d', 'rc6.d', 'rcS.d'];
1189
+ let files;
1190
+ for (const i in rcd) {
1191
+ files = fs.readdirSync(`${this.settings.work_dir.merged}/etc/${rcd[i]}`);
1192
+ for (const n in files) {
1193
+ if (files[n].includes('cryptdisks')) {
1194
+ this.addRemoveExclusion(true, `/etc/${rcd[i]}${files[n]}`);
1195
+ }
1196
+ }
1197
+ }
1198
+ }
1199
+ /**
1200
+ * secure
1201
+ */
1202
+ if (!unsecure) {
1203
+ this.addRemoveExclusion(true, `root/*`);
1204
+ this.addRemoveExclusion(true, `root/.*`);
1205
+ }
1206
+ if (shx.exec('/usr/bin/test -L /etc/localtime', { silent: true }) && shx.exec('cat /etc/timezone', { silent: true }) !== 'Europe/Rome') {
1207
+ // this.addRemoveExclusion(true, '/etc/localtime')
1208
+ }
1209
+ this.addRemoveExclusion(true, this.settings.config.snapshot_dir /* .absolutePath() */);
1210
+ if (fs.existsSync(`${this.settings.iso_work}/live/filesystem.squashfs`)) {
1211
+ fs.unlinkSync(`${this.settings.iso_work}/live/filesystem.squashfs`);
1212
+ }
1213
+ const compression = `-comp ${this.settings.config.compression}`;
1214
+ /**
1215
+ * limit: patch per Raspberry
1216
+ */
1217
+ const limit = '';
1218
+ if (Utils.uefiArch() === 'arm64') {
1219
+ // limit = ' -processors 2 -mem 1024M'
1220
+ }
1221
+ /**
1222
+ * mksquashfs
1223
+ *
1224
+ * SYNTAX: mksquashfs source1 source2 ...
1225
+ * FILESYSTEM [OPTIONS]
1226
+ * [-ef exclude.list]
1227
+ * [-e list of exclude dirs/files]
1228
+ */
1229
+ let cmd = `mksquashfs ${this.settings.work_dir.merged} ${this.settings.iso_work}live/filesystem.squashfs ${compression} ${limit} -wildcards -ef ${this.settings.config.snapshot_excludes} ${this.settings.session_excludes}`;
1230
+ cmd = cmd.replaceAll(/\s\s+/g, ' ');
1231
+ Utils.writeX(`${this.settings.work_dir.ovarium}mksquashfs`, cmd);
1232
+ if (!scriptOnly) {
1233
+ Utils.warning('creating filesystem.squashfs on ISO/live');
1234
+ // Utils.warning(`compression: ` + compression)
1235
+ const test = (await exec(cmd, Utils.setEcho(true))).code;
1236
+ if (test !== 0) {
1237
+ process.exit();
1238
+ }
1239
+ }
1240
+ return cmd;
1241
+ }
1242
+ /**
1243
+ * Ritorna true se c'è bisogno del mount --bind
1244
+ *
1245
+ * Ci sono tre tipologie:
1246
+ *
1247
+ * - normal solo la creazione della directory, nessun mount
1248
+ * - merged creazione della directory e mount ro
1249
+ * - mergedAndOverlay creazione directory, overlay e mount rw
1250
+ * - copied: creazione directory e copia
1251
+ */
1252
+ merged(dir) {
1253
+ if (this.verbose) {
1254
+ console.log('Ovary: merged');
1255
+ }
1256
+ let merged = true;
1257
+ if (dir === 'home') {
1258
+ merged = this.clone;
1259
+ }
1260
+ else {
1261
+ const noMergeDirs = [
1262
+ 'boot', // will be copied now
1263
+ 'cdrom',
1264
+ 'dev',
1265
+ 'media',
1266
+ 'mnt',
1267
+ 'proc',
1268
+ 'run',
1269
+ 'swapfile',
1270
+ 'sys',
1271
+ 'tmp'
1272
+ ];
1273
+ // deepin
1274
+ noMergeDirs.push('data', 'recovery');
1275
+ for (const noMergeDir of noMergeDirs) {
1276
+ if (dir === noMergeDir) {
1277
+ merged = false;
1278
+ }
1279
+ }
1280
+ }
1281
+ return merged;
1282
+ }
1283
+ /**
1284
+ * Restituisce true per le direcory da montare con overlay
1285
+ *
1286
+ * Ci sono tre tipologie:
1287
+ *
1288
+ * - normal solo la creazione della directory, nessun mount
1289
+ * - merged creazione della directory e mount ro
1290
+ * - mergedAndOverlay creazione directory, overlay e mount rw
1291
+ *
1292
+ * @param dir
1293
+ */
1294
+ mergedAndOverlay(dir) {
1295
+ if (this.verbose) {
1296
+ console.log('Ovary: mergedAndOverlay');
1297
+ }
1298
+ // agginto bin per autologin su Alpine
1299
+ const mountDirs = ['bin', 'etc', 'usr', 'var'];
1300
+ let mountDir = '';
1301
+ let overlay = false;
1302
+ for (mountDir of mountDirs) {
1303
+ if (mountDir === dir) {
1304
+ overlay = true;
1305
+ }
1306
+ }
1307
+ return overlay;
1308
+ }
1309
+ /**
1310
+ * produce
1311
+ * @param clone
1312
+ * @param cryptedclone
1313
+ * @param scriptOnly
1314
+ * @param yolkRenew
1315
+ * @param release
1316
+ * @param myAddons
1317
+ * @param nointeractive
1318
+ * @param noicons
1319
+ * @param unsecure
1320
+ * @param verbose
1321
+ */
1322
+ async produce(clone = false, cryptedclone = false, scriptOnly = false, yolkRenew = false, release = false, myAddons, myLinks, excludes, nointeractive = false, noicons = false, unsecure = false, verbose = false) {
1323
+ this.verbose = verbose;
1324
+ this.echo = Utils.setEcho(verbose);
1325
+ if (this.verbose) {
1326
+ this.toNull = ' > /dev/null 2>&1';
1327
+ }
1328
+ this.clone = clone;
1329
+ this.cryptedclone = cryptedclone;
1330
+ const luksName = 'luks-volume';
1331
+ const luksFile = `/tmp/${luksName}`;
1332
+ if (this.familyId === 'debian' && Utils.uefiArch() === 'amd64') {
1333
+ const yolk = new Repo();
1334
+ if (!yolk.exists()) {
1335
+ Utils.warning('creating yolk');
1336
+ await yolk.create(verbose);
1337
+ }
1338
+ else if (yolkRenew) {
1339
+ Utils.warning('refreshing yolk');
1340
+ await yolk.erase();
1341
+ await yolk.create(verbose);
1342
+ }
1343
+ else {
1344
+ Utils.warning('using preesixent yolk');
1345
+ }
1346
+ }
1347
+ if (!fs.existsSync(this.settings.config.snapshot_dir)) {
1348
+ shx.mkdir('-p', this.settings.config.snapshot_dir);
1349
+ }
1350
+ if (Utils.isLive()) {
1351
+ console.log(chalk.red('>>> eggs: This is a live system! An egg cannot be produced from an egg!'));
1352
+ }
1353
+ else {
1354
+ await this.liveCreateStructure();
1355
+ // Carica calamares sono se le icone sono accettate
1356
+ if (!noicons && // se VOGLIO le icone
1357
+ !nointeractive &&
1358
+ this.settings.distro.isCalamaresAvailable &&
1359
+ Pacman.isInstalledGui() &&
1360
+ this.settings.config.force_installer &&
1361
+ !Pacman.calamaresExists()) {
1362
+ console.log('Installing ' + chalk.bgGray('calamares') + ' due force_installer=yes.');
1363
+ await Pacman.calamaresInstall(verbose);
1364
+ const bleach = new Bleach();
1365
+ await bleach.clean(verbose);
1366
+ }
1367
+ if (cryptedclone) {
1368
+ /**
1369
+ * cryptedclone
1370
+ */
1371
+ console.log("eggs will SAVE users and users' data ENCRYPTED");
1372
+ /*
1373
+ const users = await this.usersFill()
1374
+ for (const user of users) {
1375
+ if (user.saveIt) {
1376
+ let utype = 'user '
1377
+ if (Number.parseInt(user.uid) < 1000) {
1378
+ utype = 'service'
1379
+ }
1380
+ //console.log(`- ${utype}: ${user.login.padEnd(16)} \thome: ${user.home}`)
1381
+ if (user.login !== 'root') {
1382
+ this.addRemoveExclusion(true, user.home)
1383
+ }
1384
+ }
1385
+ }
1386
+ */
1387
+ }
1388
+ else if (this.clone) {
1389
+ /**
1390
+ * clone
1391
+ *
1392
+ * users tend to set user_opt as
1393
+ * real user when create a clone,
1394
+ * this is WRONG here we correct
1395
+ */
1396
+ this.settings.config.user_opt = 'live'; // patch for humans
1397
+ this.settings.config.user_opt_passwd = 'evolution';
1398
+ this.settings.config.root_passwd = 'evolution';
1399
+ Utils.warning("eggs will SAVE users and users' data UNCRYPTED on the live");
1400
+ }
1401
+ else {
1402
+ /**
1403
+ * normal
1404
+ */
1405
+ Utils.warning("eggs will REMOVE users and users' data from live");
1406
+ }
1407
+ /**
1408
+ * exclude.list
1409
+ */
1410
+ if (!excludes.static /**
1411
+ * create exclude.list if not exists
1412
+ */
1413
+ &&
1414
+ !fs.existsSync('/etc/penguins-eggs/exclude.list')) {
1415
+ const excludeListTemplateDir = '/etc/penguins-eggs.d/exclude.list.d/';
1416
+ const excludeListTemplate = excludeListTemplateDir + 'master.list';
1417
+ if (!fs.existsSync(excludeListTemplate)) {
1418
+ Utils.warning('Cannot find: ' + excludeListTemplate);
1419
+ process.exit(1);
1420
+ }
1421
+ let excludeUsr = '';
1422
+ let excludeVar = '';
1423
+ let excludeHomes = '';
1424
+ let excludeHome = '';
1425
+ if (excludes.usr) {
1426
+ excludeUsr = fs.readFileSync(`${excludeListTemplateDir}usr.list`, 'utf8');
1427
+ }
1428
+ if (excludes.var) {
1429
+ excludeVar = fs.readFileSync(`${excludeListTemplateDir}var.list`, 'utf8');
1430
+ }
1431
+ if (excludes.homes) {
1432
+ excludeHomes = fs.readFileSync(`${excludeListTemplateDir}homes.list`, 'utf8');
1433
+ }
1434
+ if (excludes.home) {
1435
+ excludeHome = `home/${await Utils.getPrimaryUser()}/*`;
1436
+ }
1437
+ const view = {
1438
+ home_list: excludeHome,
1439
+ homes_list: excludeHomes,
1440
+ usr_list: excludeUsr,
1441
+ var_list: excludeVar
1442
+ };
1443
+ const template = fs.readFileSync(excludeListTemplate, 'utf8');
1444
+ fs.writeFileSync(this.settings.config.snapshot_excludes, mustache.render(template, view));
1445
+ }
1446
+ /**
1447
+ * NOTE: reCreate = false
1448
+ *
1449
+ * reCreate = false is just for develop
1450
+ * put reCreate = true in release
1451
+ */
1452
+ const reCreate = true;
1453
+ let mksquashfsCmd = '';
1454
+ if (reCreate) {
1455
+ // start pre-clone
1456
+ /**
1457
+ * installer
1458
+ */
1459
+ this.incubator = new Incubator(this.settings.remix, this.settings.distro, this.settings.config.user_opt, this.theme, this.clone, verbose);
1460
+ await this.incubator.config(release);
1461
+ await this.syslinux();
1462
+ await this.isolinux(this.theme);
1463
+ await this.kernelCopy();
1464
+ /**
1465
+ * we need different initfs
1466
+ * for different families
1467
+ */
1468
+ switch (this.familyId) {
1469
+ case 'archlinux': {
1470
+ await this.initrdArch();
1471
+ break;
1472
+ }
1473
+ case 'alpine': {
1474
+ await this.initrdAlpine();
1475
+ break;
1476
+ }
1477
+ case 'fedora': {
1478
+ await this.initrdFedora();
1479
+ break;
1480
+ }
1481
+ case 'suse': {
1482
+ await this.initrdSuse();
1483
+ break;
1484
+ }
1485
+ case 'debian': {
1486
+ await this.initrdDebian();
1487
+ break;
1488
+ }
1489
+ // No default
1490
+ }
1491
+ if (this.settings.config.make_efi) {
1492
+ await this.makeEfi(this.theme);
1493
+ }
1494
+ await this.bindLiveFs();
1495
+ if (!this.clone) {
1496
+ /**
1497
+ * ANCHE per cryptedclone
1498
+ */
1499
+ await this.cleanUsersAccounts();
1500
+ await this.createUserLive();
1501
+ if (Pacman.isInstalledGui()) {
1502
+ await this.createXdgAutostart(this.settings.config.theme, myAddons, myLinks, noicons);
1503
+ /**
1504
+ * GUI installed but NOT Desktop Manager: just create motd and issue
1505
+ */
1506
+ if (displaymanager() === '') {
1507
+ this.cliAutologin.addIssue(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged);
1508
+ this.cliAutologin.addMotd(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged);
1509
+ }
1510
+ }
1511
+ else {
1512
+ this.cliAutologin.add(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged);
1513
+ }
1514
+ // Here we are forcing alwats cliAutologin
1515
+ // this.cliAutologin.add(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged)
1516
+ }
1517
+ await this.editLiveFs(clone, cryptedclone);
1518
+ mksquashfsCmd = await this.makeSquashfs(scriptOnly, unsecure);
1519
+ await this.uBindLiveFs(); // Lo smonto prima della fase di backup
1520
+ }
1521
+ if (cryptedclone) {
1522
+ let synctoCmd = `eggs syncto -f ${luksFile}`;
1523
+ if (excludes.home) {
1524
+ synctoCmd += ' --excludes'; // from Marco, usa home.list
1525
+ }
1526
+ await exec(synctoCmd, Utils.setEcho(true));
1527
+ Utils.warning(`moving ${luksFile} in ${this.nest}iso/live`);
1528
+ await exec(`mv ${luksFile} ${this.nest}iso/live`, this.echo);
1529
+ }
1530
+ const mkIsofsCmd = (await this.xorrisoCommand(clone, cryptedclone)).replaceAll(/\s\s+/g, ' ');
1531
+ this.makeDotDisk(this.volid, mksquashfsCmd, mkIsofsCmd);
1532
+ /**
1533
+ * AntiX/MX LINUX
1534
+ */
1535
+ if (fs.existsSync('/etc/antix-version')) {
1536
+ let uname = (await exec('uname -r', { capture: true })).data;
1537
+ uname = uname.replaceAll('\n', '');
1538
+ let content = '';
1539
+ content = '#!/usr/bin/env bash';
1540
+ content += 'mkdir /live/bin -p\n';
1541
+ content += '## \n';
1542
+ content += '# cp /usr/lib/penguins-eggs/scripts/non-live-cmdline /live/bin -p\n';
1543
+ content += '# chmod +x /live/bin/non-live-cmdline\n';
1544
+ content += '## \n';
1545
+ content += 'mkdir /live/boot-dev/antiX -p\n';
1546
+ content += 'ln -s /run/live/medium/live/filesystem.squashfs /live/boot-dev/antiX/linuxfs\n';
1547
+ content += `ln -s /run/live/medium/live/initrd.img-${uname} /live/boot-dev/antiX/initrd.gz\n`;
1548
+ content += `ln -s /run/live/medium/live/vmlinuz-${uname} /live/boot-dev/antiX/vmlinuz\n`;
1549
+ content += `# md5sum /live/boot-dev/antiX/linuxfs > /live/boot-dev/antiX/linuxfs.md5\n`;
1550
+ content += `# md5sum /live/boot-dev/antiX/initrd.gz > /live/boot-dev/antiX/initrd.gz.md5\n`;
1551
+ content += `# md5sum /live/boot-dev/antiX/vmlinuz > /live/boot-dev/antiX/vmlinuz.md5\n`;
1552
+ content += `# /live/aufs -> /run/live/rootfs/filesystem.squashfs\n`;
1553
+ content += 'ln -s /run/live/rootfs/filesystem.squashfs /live/aufs\n';
1554
+ content += `# use: minstall -no-media-check\n`;
1555
+ content += 'minstall --no-media-check\n';
1556
+ const file = `${this.settings.iso_work}antix-mx-installer`;
1557
+ fs.writeFileSync(file, content);
1558
+ await exec(`chmod +x ${file}`);
1559
+ }
1560
+ /**
1561
+ * patch to emulate miso/archiso on archilinux family
1562
+ */
1563
+ if (this.familyId === 'archlinux') {
1564
+ let pathName = `arch/x86_64/airootfs`;
1565
+ let hashCmd = 'sha512sum';
1566
+ let hashExt = '.sha512';
1567
+ if (isMiso(this.settings.distro.distroId)) {
1568
+ pathName = `manjaro/x86_64/livefs`;
1569
+ hashCmd = `md5sum`;
1570
+ hashExt = '.md5';
1571
+ }
1572
+ await exec(`mkdir ${this.settings.iso_work}${pathName}/x86_64 -p`, this.echo);
1573
+ fs.linkSync(`${this.settings.iso_work}live/filesystem.squashfs`, `${this.settings.iso_work}${pathName}.sfs`);
1574
+ }
1575
+ await this.makeIso(mkIsofsCmd, scriptOnly);
1576
+ }
1577
+ }
1578
+ /**
1579
+ * syslinux
1580
+ */
1581
+ async syslinux() {
1582
+ if (this.verbose) {
1583
+ console.log('Ovary: syslinux');
1584
+ }
1585
+ await exec(`cp ${this.settings.distro.syslinuxPath}/vesamenu.c32 ${this.settings.iso_work}/isolinux/`, this.echo);
1586
+ await exec(`cp ${this.settings.distro.syslinuxPath}/chain.c32 ${this.settings.iso_work}/isolinux/`, this.echo);
1587
+ /**
1588
+ * per openSuse non sono riusciuto a determinare
1589
+ * quale pacchetto installi:
1590
+ * ldllinux.c43, libcom32 e libutil.c32
1591
+ */
1592
+ if (this.familyId !== 'suse') {
1593
+ await exec(`cp ${this.settings.distro.syslinuxPath}/ldlinux.c32 ${this.settings.iso_work}/isolinux/`, this.echo);
1594
+ await exec(`cp ${this.settings.distro.syslinuxPath}/libcom32.c32 ${this.settings.iso_work}/isolinux/`, this.echo);
1595
+ await exec(`cp ${this.settings.distro.syslinuxPath}/libutil.c32 ${this.settings.iso_work}/isolinux/`, this.echo);
1596
+ }
1597
+ }
1598
+ // #######################################################################################
1599
+ /**
1600
+ * makeEfi
1601
+ */
1602
+ /**
1603
+ *
1604
+ * @param cmd
1605
+ */
1606
+ async tryCatch(cmd = '') {
1607
+ if (this.verbose) {
1608
+ console.log('Ovary: tryCatch');
1609
+ }
1610
+ try {
1611
+ await exec(cmd, this.echo);
1612
+ }
1613
+ catch (error) {
1614
+ console.log(`Error: ${error}`);
1615
+ await Utils.pressKeyToExit(cmd);
1616
+ }
1617
+ }
1618
+ // #######################################################################################
1619
+ /**
1620
+ * ubind del fs live
1621
+ * @param verbose
1622
+ */
1623
+ async uBindLiveFs() {
1624
+ if (this.verbose) {
1625
+ console.log('Ovary: uBindLiveFs');
1626
+ }
1627
+ const cmds = [];
1628
+ cmds.push('# NOTE: home, cdrom, dev, live, media, mnt, proc, run, sys and tmp', `# need just to be removed in ${this.settings.work_dir.merged}`);
1629
+ cmds.push(`# host: ${os.hostname()} user: ${await Utils.getPrimaryUser()}\n`);
1630
+ if (fs.existsSync(this.settings.work_dir.merged)) {
1631
+ const bindDirs = fs.readdirSync(this.settings.work_dir.merged, {
1632
+ withFileTypes: true
1633
+ });
1634
+ for (const dir of bindDirs) {
1635
+ const dirname = N8.dirent2string(dir);
1636
+ cmds.push('#############################################################');
1637
+ if (N8.isDirectory(dirname)) {
1638
+ cmds.push(`\n# directory: ${dirname}`);
1639
+ if (this.mergedAndOverlay(dirname)) {
1640
+ cmds.push(`\n# ${dirname} has overlay`, `\n# First, umount it from ${this.settings.config.snapshot_dir}`);
1641
+ cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/${dirname}`, this.verbose), `\n# Second, umount it from ${this.settings.work_dir.lowerdir}`);
1642
+ cmds.push(await rexec(`umount ${this.settings.work_dir.lowerdir}/${dirname}`, this.verbose));
1643
+ }
1644
+ else if (this.merged(dirname)) {
1645
+ cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
1646
+ }
1647
+ cmds.push(`\n# remove in ${this.settings.work_dir.merged} and ${this.settings.work_dir.lowerdir}`);
1648
+ /**
1649
+ * We can't remove the nest!!!
1650
+ */
1651
+ const nest = this.settings.config.snapshot_dir.split('/');
1652
+ if (dirname !== nest[1]) {
1653
+ // We can't remove first level nest
1654
+ cmds.push(await rexec(`rm ${this.settings.work_dir.merged}/${dirname} -rf`, this.verbose));
1655
+ }
1656
+ }
1657
+ else if (N8.isFile(dirname)) {
1658
+ cmds.push(`\n# ${dirname} = file`);
1659
+ cmds.push(await rexec(`rm ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
1660
+ }
1661
+ else if (N8.isSymbolicLink(dirname)) {
1662
+ cmds.push(`\n# ${dirname} = symbolicLink`);
1663
+ cmds.push(await rexec(`rm ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
1664
+ }
1665
+ }
1666
+ }
1667
+ if (this.clone) {
1668
+ cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/home`, this.verbose));
1669
+ }
1670
+ // Utils.writeXs(`${this.settings.config.snapshot_dir}ubind`, cmds)
1671
+ Utils.writeXs(`${this.settings.work_dir.ovarium}ubind`, cmds);
1672
+ }
1673
+ /**
1674
+ *
1675
+ * @param verbose
1676
+ */
1677
+ async ubindVfs() {
1678
+ if (this.verbose) {
1679
+ console.log('Ovary: ubindVfs');
1680
+ }
1681
+ const cmds = [];
1682
+ cmds.push(`umount ${this.settings.work_dir.merged}/dev/pts`, `umount ${this.settings.work_dir.merged}/dev`, `umount ${this.settings.work_dir.merged}/proc`, `umount ${this.settings.work_dir.merged}/run`, `umount ${this.settings.work_dir.merged}/sys`);
1683
+ // Utils.writeXs(`${this.settings.config.snapshot_dir}ubindvfs`, cmds)
1684
+ Utils.writeXs(`${this.settings.work_dir.ovarium}ubindvfs`, cmds);
1685
+ }
1686
+ /**
1687
+ * fill
1688
+ */
1689
+ async usersFill() {
1690
+ if (this.verbose) {
1691
+ console.log('Ovary: usersFill');
1692
+ }
1693
+ const usersArray = [];
1694
+ await access('/etc/passwd', constants.R_OK | constants.W_OK);
1695
+ const passwd = fs.readFileSync('/etc/passwd', 'utf8').split('\n');
1696
+ for (const element of passwd) {
1697
+ const line = element.split(':');
1698
+ const users = new Users(line[0], line[1], line[2], line[3], line[4], line[5], line[6]);
1699
+ await users.getValues();
1700
+ if (users.password !== undefined) {
1701
+ usersArray.push(users);
1702
+ }
1703
+ }
1704
+ return usersArray;
1705
+ }
1706
+ /**
1707
+ *
1708
+ * @param cryptedclone
1709
+ * @returns cmd 4 mkiso
1710
+ */
1711
+ async xorrisoCommand(clone = false, cryptedclone = false) {
1712
+ if (this.verbose) {
1713
+ console.log('Ovary: xorrisoCommand');
1714
+ }
1715
+ const prefix = this.settings.config.snapshot_prefix;
1716
+ let typology = '';
1717
+ // typology is applied only with standard egg-of
1718
+ if (prefix.slice(0, 7) === 'egg-of_') {
1719
+ if (clone) {
1720
+ typology = '_clone';
1721
+ }
1722
+ else if (cryptedclone) {
1723
+ typology = '_crypted';
1724
+ }
1725
+ if (fs.existsSync('/usr/bin/eui-start.sh')) {
1726
+ typology += '_EUI';
1727
+ }
1728
+ }
1729
+ const postfix = Utils.getPostfix();
1730
+ this.settings.isoFilename = prefix + this.volid + '_' + Utils.uefiArch() + typology + postfix;
1731
+ //
1732
+ const output = this.settings.config.snapshot_mnt + this.settings.isoFilename;
1733
+ let command = '';
1734
+ // const appid = `-appid "${this.settings.distro.distroId}" `
1735
+ // const publisher = `-publisher "${this.settings.distro.distroId}/${this.settings.distro.codenameId}" `
1736
+ // const preparer = '-preparer "prepared by eggs <https://penguins-eggs.net>" '
1737
+ let isoHybridMbr = '';
1738
+ if (this.settings.config.make_isohybrid) {
1739
+ const isolinuxFile = this.settings.distro.isolinuxPath + 'isohdpfx.bin';
1740
+ if (fs.existsSync(isolinuxFile)) {
1741
+ isoHybridMbr = `-isohybrid-mbr ${isolinuxFile}`;
1742
+ }
1743
+ else {
1744
+ Utils.warning(`Can't create isohybrid image. File: ${isolinuxFile} not found. \nThe resulting image will be a standard iso file`);
1745
+ }
1746
+ }
1747
+ // uefi_opt="-uefi_elToritoAltBoot-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
1748
+ let uefi_elToritoAltBoot = '';
1749
+ let uefi_e = '';
1750
+ let uefi_isohybridGptBasdat = '';
1751
+ let uefi_noEmulBoot = '';
1752
+ if (this.settings.config.make_efi) {
1753
+ uefi_elToritoAltBoot = '-eltorito-alt-boot';
1754
+ uefi_e = '-e boot/grub/efiboot.img';
1755
+ uefi_isohybridGptBasdat = '-isohybrid-gpt-basdat';
1756
+ uefi_noEmulBoot = '-no-emul-boot';
1757
+ }
1758
+ if (Pacman.packageIsInstalled('genisoimage')) {
1759
+ this.genisoimage = true;
1760
+ command = `genisoimage \
1761
+ -iso-level 3 \
1762
+ -allow-limited-size \
1763
+ -joliet-long \
1764
+ -r \
1765
+ -V ${this.volid} \
1766
+ -cache-inodes \
1767
+ -J \
1768
+ -l \
1769
+ -b isolinux/isolinux.bin \
1770
+ -c isolinux/boot.cat \
1771
+ -no-emul-boot \
1772
+ -boot-load-size 4 \
1773
+ -boot-info-table \
1774
+ -eltorito-alt-boot \
1775
+ -e boot/grub/efiboot.img \
1776
+ -o ${output} ${this.settings.iso_work}`;
1777
+ return command;
1778
+ }
1779
+ // xorriso
1780
+ command = `xorriso -as mkisofs \
1781
+ -J \
1782
+ -joliet-long \
1783
+ -l \
1784
+ -iso-level 3 \
1785
+ ${isoHybridMbr} \
1786
+ -partition_offset 16 \
1787
+ -V ${this.volid} \
1788
+ -b isolinux/isolinux.bin \
1789
+ -c isolinux/boot.cat \
1790
+ -no-emul-boot \
1791
+ -boot-load-size 4 \
1792
+ -boot-info-table \
1793
+ ${uefi_elToritoAltBoot} \
1794
+ ${uefi_e} \
1795
+ ${uefi_isohybridGptBasdat} \
1796
+ ${uefi_noEmulBoot} \
1797
+ -o ${output} ${this.settings.iso_work}`;
1798
+ return command;
1799
+ }
1800
+ /**
1801
+ * Creazione link desktop per lxde
1802
+ * @param name
1803
+ * @param icon
1804
+ */
1805
+ lxdeLink(file, name, icon) {
1806
+ if (this.verbose) {
1807
+ console.log('Ovary: lxdeLink');
1808
+ }
1809
+ const lnk = `lnk-${file}`;
1810
+ let text = '';
1811
+ text += `echo "[Desktop Entry]" >$DESKTOP/${lnk}\n`;
1812
+ text += `echo "Type=Link" >> $DESKTOP/${lnk}\n`;
1813
+ text += `echo "Name=${name}" >> $DESKTOP/${lnk}\n`;
1814
+ text += `echo "Icon=${icon}" >> $DESKTOP/${lnk}\n`;
1815
+ text += `echo "URL=/usr/share/applications/${file}" >> $DESKTOP/${lnk}\n\n`;
1816
+ return text;
1817
+ }
1818
+ }
1819
+ /**
1820
+ * FUNCTIONS
1821
+ */
1822
+ /**
1823
+ * Crea il path se non esiste
1824
+ * @param path
1825
+ */
1826
+ async function makeIfNotExist(path, verbose = false) {
1827
+ if (verbose) {
1828
+ console.log(`Ovary: makeIfNotExist(${path})`);
1829
+ }
1830
+ const echo = Utils.setEcho(verbose);
1831
+ let cmd = `# ${path} alreasy exist`;
1832
+ if (!fs.existsSync(path)) {
1833
+ cmd = `mkdir ${path} -p`;
1834
+ await exec(cmd, echo);
1835
+ }
1836
+ return cmd;
1837
+ }
1838
+ /**
1839
+ *
1840
+ * @param cmd
1841
+ * @param echo
1842
+ */
1843
+ async function rexec(cmd, verbose = false) {
1844
+ if (verbose) {
1845
+ console.log(`Ovary: rexec(${cmd})`);
1846
+ }
1847
+ const echo = Utils.setEcho(verbose);
1848
+ const check = await exec(cmd, echo);
1849
+ if (!cmd.startsWith('umount') && // skip umount errors
1850
+ check.code !== 0) {
1851
+ console.log(`eggs >>> error on command: ` + chalk.cyan(cmd) + ', code: ' + chalk.cyan(check.code));
1852
+ }
1853
+ return cmd;
1854
+ }
1855
+ /**
1856
+ * isMiso
1857
+ */
1858
+ function isMiso(distro) {
1859
+ let found = false;
1860
+ if (distro.includes('ManjaroLinux') || distro.toLowerCase().includes('biglinux')) {
1861
+ found = true;
1862
+ }
1863
+ return found;
1864
+ }
1865
+ /**
1866
+ * se non zuppa, pan bagnato
1867
+ * @param distro
1868
+ * @returns
1869
+ */
1870
+ function isArchiso(distro) {
1871
+ return !isMiso(distro);
1872
+ }