penguins-eggs
Version:
A remaster system tool, compatible with Arch, Debian, Devuan, Ubuntu and others
178 lines (177 loc) • 8.37 kB
JavaScript
/**
* ./src/classes/ovary.d/bind-live-fs.ts
* penguins-eggs v.10.0.0 / ecmascript 2020
* author: Piero Proietti
* email: piero.proietti@gmail.com
* license: MIT
*/
// packages
import fs from 'fs';
import path from 'node:path';
import os from 'os';
// classes
import { exec } from '../../lib/utils.js';
import Utils from '../utils.js';
// functions
import rexec from './rexec.js';
// _dirname
const __dirname = path.dirname(new URL(import.meta.url).pathname);
/**
* Esegue il bind del filesystem live e
* crea lo script bind
*/
export async function bindLiveFs() {
if (this.verbose) {
console.log('Ovary: bindLiveFs');
}
/**
* dirs = readdirsync /
*/
const dirs = fs.readdirSync('/');
const startLine = '#############################################################';
const endLine = '#\n';
let lnkDest = '';
let cmd = '';
const cmds = [];
cmds.push('# NOTE: cdrom, dev, live, media, mnt, proc, run, sys and tmp', `# need just a mkdir in ${this.settings.work_dir.merged}`);
cmds.push(`# host: ${os.hostname()} user: ${await Utils.getPrimaryUser()}\n`);
for (const dir of dirs) {
cmds.push(startLine);
let statDir = fs.lstatSync(`/${dir}`);
if (statDir.isSymbolicLink()) {
/**
* Link
*/
cmds.push(`# /${dir} is a symbolic link to /${lnkDest}`);
lnkDest = fs.readlinkSync(`/${dir}`);
if (fs.existsSync(`${this.settings.work_dir.merged}/${dir}`)) {
cmds.push('# SymbolicLink exist... skip');
}
else if (fs.existsSync(lnkDest)) {
cmds.push(`ln -s ${this.settings.work_dir.merged}/${lnkDest} ${this.settings.work_dir.merged}/${lnkDest}`);
}
else {
cmds.push(await rexec(`cp -r /${dir} ${this.settings.work_dir.merged}`, this.verbose));
}
}
else if (statDir.isDirectory()) {
/**
* Directory
*/
cmds.push(`# /${dir} is a directory`);
if (dir !== 'ci' && dir !== 'lost+found') {
if (this.copied(dir)) {
cmds.push(`# /${dir} is copied`);
cmds.push(await rexec(`cp -r /${dir} ${this.settings.config.snapshot_mnt}filesystem.squashfs`, this.verbose));
}
else if (this.mergedAndOverlay(dir)) {
cmds.push(`# /${dir} mergedAndOverlay (rw)\n`, '# create mountpoint lower');
cmds.push(await makeIfNotExist(`${this.settings.work_dir.lowerdir}/${dir}`), `# first: mount /${dir} rw in ${this.settings.work_dir.lowerdir}/${dir}`);
cmds.push(await rexec(`mount --bind --make-slave /${dir} ${this.settings.work_dir.lowerdir}/${dir}`, this.verbose), '# now remount it ro');
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}`);
cmds.push(await makeIfNotExist(`${this.settings.work_dir.upperdir}/${dir}`, this.verbose));
cmds.push(await makeIfNotExist(`${this.settings.work_dir.workdir}/${dir}`, this.verbose));
cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose), `\n# thirth: mount /${dir} rw in ${this.settings.work_dir.merged}`);
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));
}
else if (this.merged(dir)) {
cmds.push(`# /${dir} merged (ro)`);
cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose));
cmds.push(await rexec(`mount --bind --make-slave /${dir} ${this.settings.work_dir.merged}/${dir}`, this.verbose));
cmds.push(await rexec(`mount -o remount,bind,ro ${this.settings.work_dir.merged}/${dir}`, this.verbose));
}
else {
cmds.push(`# /${dir} just created`);
cmds.push(await makeIfNotExist(`${this.settings.work_dir.merged}/${dir}`, this.verbose));
}
}
/**
* File
*/
}
else if (statDir.isFile()) {
cmds.push(`# /${dir} is just a file`);
if (fs.existsSync(`${this.settings.work_dir.merged}/${dir}`)) {
cmds.push('# file exist... skip');
}
else {
cmds.push(await rexec(`cp /${dir} ${this.settings.work_dir.merged}`, this.verbose));
}
}
cmds.push(endLine);
}
// Utils.writeXs(`${this.settings.config.snapshot_dir}bind`, cmds)
Utils.writeXs(`${this.settings.work_dir.ovarium}bind`, cmds);
}
/**
* ubind del fs live
* @param verbose
*/
export async function uBindLiveFs() {
if (this.verbose) {
console.log('Ovary: uBindLiveFs');
}
const startLine = '#############################################################';
const endLine = '#\n';
const cmds = [];
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}`);
cmds.push(`# host: ${os.hostname()} user: ${await Utils.getPrimaryUser()}\n`);
if (fs.existsSync(this.settings.work_dir.merged)) {
const bindDirs = fs.readdirSync(this.settings.work_dir.merged, {
withFileTypes: true
});
for (const dir of bindDirs) {
const dirname = dir.name;
cmds.push(startLine);
if (fs.statSync(`/${dirname}`).isDirectory()) {
cmds.push(`\n# directory: ${dirname}`);
if (this.mergedAndOverlay(dirname)) {
cmds.push(`\n# ${dirname} has overlay`, `\n# First, umount it from ${this.settings.config.snapshot_dir}`);
cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/${dirname}`, this.verbose), `\n# Second, umount it from ${this.settings.work_dir.lowerdir}`);
cmds.push(await rexec(`umount ${this.settings.work_dir.lowerdir}/${dirname}`, this.verbose));
}
else if (this.merged(dirname)) {
cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
}
cmds.push(`\n# remove in ${this.settings.work_dir.merged} and ${this.settings.work_dir.lowerdir}`);
/**
* We can't remove the nest!!!
*/
const nest = this.settings.config.snapshot_dir.split('/');
if (dirname !== nest[1]) {
// We can't remove first level nest
cmds.push(await rexec(`rm -rf ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
}
}
else if (fs.statSync(`/${dirname}`).isFile()) {
cmds.push(`\n# ${dirname} = file`);
cmds.push(await rexec(`rm -f ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
}
else if (fs.statSync(`/${dirname}`).isSymbolicLink()) {
cmds.push(`\n# ${dirname} = symbolicLink`);
cmds.push(await rexec(`rm -f ${this.settings.work_dir.merged}/${dirname}`, this.verbose));
}
}
}
if (this.clone) {
cmds.push(await rexec(`umount ${this.settings.work_dir.merged}/home`, this.verbose));
}
// Utils.writeXs(`${this.settings.config.snapshot_dir}ubind`, cmds)
Utils.writeXs(`${this.settings.work_dir.ovarium}ubind`, cmds);
}
/**
* Crea il path se non esiste
* @param path
*/
async function makeIfNotExist(path, verbose = false) {
if (verbose) {
console.log(`Ovary: makeIfNotExist(${path})`);
}
const echo = Utils.setEcho(verbose);
let cmd = `# ${path} alreasy exist`;
if (!fs.existsSync(path)) {
cmd = `mkdir ${path} -p`;
await exec(cmd, echo);
}
return cmd;
}