Refactoring how we exec commands in chroot to make it less error prone.

This commit is contained in:
Sergiotarxz 2023-10-01 11:45:16 +02:00
parent 0c2a06934b
commit 09039d1900
2 changed files with 99 additions and 88 deletions

37
lib/BaseUtils.pm Normal file
View File

@ -0,0 +1,37 @@
package BaseUtils;
use v5.36.0;
use strict;
use warnings;
use utf8;
use Moo;
sub forkWait($self) {
my $pid = fork;
if ($pid) {
return sub {
wait;
my $return_code = $?;
return $return_code;
};
}
return;
}
sub chroot($self, $target) {
chroot "$target";
chdir '/';
}
sub execChroot($self, $target, @command) {
my $parent_subroutine = $self->forkWait();
if (defined $parent_subroutine) {
return $parent_subroutine->();
}
$self->chroot($target);
my $return_code = system @command;
exit $return_code;
}
1;

View File

@ -7,6 +7,11 @@ use warnings;
use utf8; use utf8;
use Path::Tiny; use Path::Tiny;
use lib path(__FILE__)->parent->child('lib') . '';
use BaseUtils;
my $utils = BaseUtils->new;
main(); main();
@ -22,73 +27,62 @@ sub main {
my $resolv_conf = path('/etc/resolv.conf'); my $resolv_conf = path('/etc/resolv.conf');
my $zz_use = path('zz-use'); my $zz_use = path('zz-use');
my $packages = _readPackagesToInstall(); my $packages = _readPackagesToInstall();
_checkValidSystem($target_dir); _checkValidSystem($target_dir);
my $make_conf_changed = _installMakeConf( $target_dir, $make_conf ); _installMakeConf( $target_dir, $make_conf );
_installGentooConf($target_dir, $gentoo_conf); _installGentooConf( $target_dir, $gentoo_conf );
_installResolvConf($target_dir,$resolv_conf); _installResolvConf( $target_dir, $resolv_conf );
my $package_use_changed = _installPackageUse($target_dir, $zz_use); _installPackageUse( $target_dir, $zz_use );
_mountNecessaryFilesystems($target_dir); _mountNecessaryFilesystems($target_dir);
_webrsync($target_dir); _webrsync($target_dir);
if ($rebuild_bin && $package_use_changed || $make_conf_changed) { if ( $rebuild_bin ) {
_rebuildBinaries($target_dir); _rebuildBinaries($target_dir);
} }
_updateSystem($target_dir); _updateSystem($target_dir);
_depclean($target_dir); _depclean($target_dir);
_installNeededPackages($target_dir, $packages); _installNeededPackages( $target_dir, $packages );
} }
sub _depclean($target) { sub _depclean ($target) {
_forkWait() or return; my $return_code = $utils->execChroot( $target, 'emerge', '--depclean' );
_chroot($target); if ( $return_code != 0 ) {
my $return_code = system 'emerge', '--depclean';
if ($return_code != 0) {
die 'Unable to depclean system.'; die 'Unable to depclean system.';
} }
exit 0;
} }
sub _updateSystem($target) { sub _updateSystem ($target) {
_forkWait() or return; my $return_code =
_chroot($target); $utils->execChroot( $target, 'emerge', '-uUDN', '@world' );
my $return_code = system 'emerge', '-uUDN', '@world'; if ( $return_code != 0 ) {
if ($return_code != 0) {
die 'Unable to update the system.'; die 'Unable to update the system.';
} }
exit 0;
} }
sub _rebuildBinaries($target) { sub _rebuildBinaries ($target) {
_forkWait() or return; my $return_code = $utils->execChroot( $target, 'emerge', '-e', '@system' );
_chroot($target); if ( $return_code != 0 ) {
my $return_code = system 'emerge', '-e', '@system';
if ($return_code != 0) {
die 'Unable to rebuild binaries for system.'; die 'Unable to rebuild binaries for system.';
} }
my $return_code = system 'emerge', '-e', '@world'; $return_code = $utils->execChroot( $target, 'emerge', '-e', '@world' );
if ($return_code != 0) { if ( $return_code != 0 ) {
die 'Unable to rebuild binaries for world.'; die 'Unable to rebuild binaries for world.';
} }
exit 0;
} }
sub _installNeededPackages($target, $packages) { sub _installNeededPackages ( $target, $packages ) {
_forkWait() or return; my $return_code =
_chroot($target); $utils->execChroot( $target, 'emerge', '--noreplace', @$packages );
my $return_code = system 'emerge', '--noreplace', @$packages; if ( $return_code != 0 ) {
if ($return_code != 0) { die 'Unable to install needed packages.';
exit $return_code;
} }
exit 0;
} }
sub _readPackagesToInstall { sub _readPackagesToInstall {
my @packages; my @packages;
open my $fh, '<', 'packages'; open my $fh, '<', 'packages';
while (my $line = <$fh>) { while ( my $line = <$fh> ) {
chomp $line; chomp $line;
push @packages, $line; push @packages, $line;
} }
@ -96,62 +90,42 @@ sub _readPackagesToInstall {
return \@packages; return \@packages;
} }
sub _forkWait { sub _webrsync ($target) {
my $pid = fork; my $return_code = $utils->execChroot( $target, 'emerge-webrsync' );
if ($pid) { if ( $return_code != 0 ) {
wait; die 'Unable to webrsync.';
my $return_code = $?;
if ($? != 0) {
exit $?;
} }
return 0;
}
return 1;
} }
sub _webrsync($target) { sub _mountNecessaryFilesystems ($target) {
_forkWait() or return;
_chroot($target);
my $return_code = system 'emerge-webrsync';
if ($return_code != 0) {
return $return_code;
}
exit 0;
}
sub _chroot($target) {
chroot "$target";
chdir '/';
}
sub _mountNecessaryFilesystems($target) {
my $dest_proc = $target->child('proc'); my $dest_proc = $target->child('proc');
my $dest_dev = $target->child('dev'); my $dest_dev = $target->child('dev');
my $dest_sys = $target->child('sys'); my $dest_sys = $target->child('sys');
_mountType('proc', $dest_proc) if !_checkMounted($dest_proc); _mountType( 'proc', $dest_proc ) if !_checkMounted($dest_proc);
_mountType('sysfs', $dest_sys) if !_checkMounted($dest_sys); _mountType( 'sysfs', $dest_sys ) if !_checkMounted($dest_sys);
_mountRbind('/dev', $dest_dev) if !_checkMounted($dest_dev); _mountRbind( '/dev', $dest_dev ) if !_checkMounted($dest_dev);
} }
sub _checkMounted($fs) { sub _checkMounted ($fs) {
$fs = $fs->realpath; $fs = $fs->realpath;
my $return = index(_getMounts(), $fs) != -1; my $return = index( _getMounts(), $fs ) != -1;
say "$fs is mounted." if $return; say "$fs is mounted." if $return;
return $return; return $return;
} }
sub _mountRbind($source, $fs) { sub _mountRbind ( $source, $fs ) {
my $return_code = system 'sudo', 'mount', '--rbind', $source, $fs; my $return_code = system 'sudo', 'mount', '--rbind', $source, $fs;
if ($return_code != 0) { if ( $return_code != 0 ) {
die "Unable to mount $fs."; die "Unable to mount $fs.";
} }
} }
{ {
my $mounts; my $mounts;
sub _getMounts { sub _getMounts {
if (!defined $mounts) { if ( !defined $mounts ) {
open my $fh, '-|', 'sudo', 'mount'; open my $fh, '-|', 'sudo', 'mount';
$mounts = join '', <$fh>; $mounts = join '', <$fh>;
close $fh; close $fh;
@ -160,9 +134,9 @@ sub _mountRbind($source, $fs) {
} }
} }
sub _mountType($fs_type, $fs) { sub _mountType ( $fs_type, $fs ) {
my $return_code = system 'sudo', 'mount', '-t', $fs_type, $fs_type, $fs; my $return_code = system 'sudo', 'mount', '-t', $fs_type, $fs_type, $fs;
if ($return_code != 0) { if ( $return_code != 0 ) {
die "Unable to mount $fs."; die "Unable to mount $fs.";
} }
} }
@ -173,37 +147,37 @@ sub _checkValidSystem ($target) {
} }
} }
sub _installResolvConf($target, $resolv_conf) { sub _installResolvConf ( $target, $resolv_conf ) {
my $dest_resolv_conf = $target->child('etc/resolv.conf'); my $dest_resolv_conf = $target->child('etc/resolv.conf');
_install($resolv_conf, $dest_resolv_conf); _install( $resolv_conf, $dest_resolv_conf );
} }
sub _installGentooConf($target, $gentoo_conf) { sub _installGentooConf ( $target, $gentoo_conf ) {
my $dest_gentoo_conf = $target->child('etc/portage/repos.conf/gentoo.conf'); my $dest_gentoo_conf = $target->child('etc/portage/repos.conf/gentoo.conf');
my $repos_conf = $dest_gentoo_conf->parent; my $repos_conf = $dest_gentoo_conf->parent;
my $return_code = system 'sudo', 'mkdir', '-p', $repos_conf; my $return_code = system 'sudo', 'mkdir', '-p', $repos_conf;
if ($return_code != 0) { if ( $return_code != 0 ) {
say "Unable to create $repos_conf."; say "Unable to create $repos_conf.";
} }
_install($gentoo_conf, $dest_gentoo_conf); _install( $gentoo_conf, $dest_gentoo_conf );
} }
sub _installPackageUse($target, $zz_use) { sub _installPackageUse ( $target, $zz_use ) {
my $dest_zz_use = $target->child('etc/portage/package.use/zz-use'); my $dest_zz_use = $target->child('etc/portage/package.use/zz-use');
my $package_use = $dest_zz_use->parent; my $package_use = $dest_zz_use->parent;
my $return_code = system 'sudo', 'mkdir', '-p', $package_use; my $return_code = system 'sudo', 'mkdir', '-p', $package_use;
if ($return_code != 0) { if ( $return_code != 0 ) {
say "Unable to create $package_use."; say "Unable to create $package_use.";
} }
_install($zz_use, $dest_zz_use); _install( $zz_use, $dest_zz_use );
} }
sub _installMakeConf ( $target, $make_conf ) { sub _installMakeConf ( $target, $make_conf ) {
my $dest_make_conf = $target->child('etc/portage/make.conf'); my $dest_make_conf = $target->child('etc/portage/make.conf');
return _install($make_conf, $dest_make_conf); return _install( $make_conf, $dest_make_conf );
} }
sub _install($source, $dest) { sub _install ( $source, $dest ) {
if ( -e $dest if ( -e $dest
&& _getSha512SumFile($dest) eq _getSha512SumFile($source) ) && _getSha512SumFile($dest) eq _getSha512SumFile($source) )
{ {