273 lines
8.1 KiB
Perl
Executable File
273 lines
8.1 KiB
Perl
Executable File
#!/usr/bin/env perl
|
||
|
||
use strict;
|
||
use warnings;
|
||
|
||
use Data::Dumper;
|
||
|
||
print "Sanitize script for node removal from container.\n";
|
||
|
||
system("pwd");
|
||
{
|
||
my @l = (".","..");
|
||
for(1..8) {
|
||
push @l, (("../" x $_)."..")
|
||
}
|
||
for(@l) {
|
||
my $cmd = "ls -ld $_";
|
||
print "running: $cmd\n";
|
||
system $cmd;
|
||
}
|
||
}
|
||
|
||
my $tmpdir = "tmp-sanitize";
|
||
|
||
die "Has already run, abort" if -e $tmpdir;
|
||
|
||
mkdir $tmpdir;
|
||
|
||
chmodWrap(0755, $tmpdir);
|
||
chdir($tmpdir);
|
||
system("ln -s ../uniworx.tar.gz .");
|
||
system("tar xzvf uniworx.tar.gz");
|
||
chmodWrap(0755, '.'); # tar can change the rights of '.' if it contains an entry for '.' with other rights
|
||
|
||
my %truerights = ();
|
||
storeRightsMake7(".");
|
||
|
||
#print "=== Extended rights:\n";
|
||
#system("ls -l *");
|
||
#resetRights(".");
|
||
#print "=== Reset rights:\n";
|
||
#system("ls -l *");
|
||
|
||
sub chmodWrap {
|
||
my ($mode, $fn) = @_;
|
||
my $tries = 0;
|
||
die "file '$fn' does not exist; cannot change its permissions to $mode" unless -e $fn;
|
||
RIGHTS: {
|
||
chmod($mode, $fn);
|
||
my $ismode = (stat($fn))[2];
|
||
my $fm = $ismode % 512;
|
||
if($fm != $mode) {
|
||
if($tries++ > 20) {
|
||
die "Problem with file permissions, abort"
|
||
}
|
||
warn sprintf "File rights were meant to be set, but were not updated properly for file '%s', is %03o but was set to %03o; try again in 1 second";
|
||
sleep 1;
|
||
redo RIGHTS;
|
||
}
|
||
}
|
||
}
|
||
|
||
#
|
||
sub storeRightsMake7 {
|
||
my ($pwd) = @_;
|
||
my $dh = undef;
|
||
opendir($dh, $pwd) or die "Could not read dir '$pwd', because: $!";
|
||
while(my $fn = readdir($dh)) {
|
||
next if $fn=~m#^\.\.?$#;
|
||
#perl -le 'my $dh = undef;opendir($dh, ".");while(my $fn = readdir($dh)) { my $mode = (stat($fn))[2];my $fm = $mode % 512;my $fmo=sprintf("%03o",$fm);print "$fn -> $fmo" }'
|
||
my $fullname = "$pwd/$fn";
|
||
my $mode = (stat($fullname))[2];
|
||
my $fm = $mode % 512;
|
||
#my $fmo = sprintf("%03o",$fm);
|
||
$truerights{$fullname} = $fm;
|
||
chmodWrap(($fm | 0700), $fullname);
|
||
storeRightsMake7($fullname) if -d $fullname;
|
||
}
|
||
}
|
||
|
||
sub resetRights {
|
||
my ($pwd) = @_;
|
||
print "Resetting rights to:\n" if '.' eq $pwd;
|
||
print Data::Dumper::Dumper(\%truerights);
|
||
my $dh = undef;
|
||
opendir($dh, $pwd) or die "Could not read dir '$pwd', because: $!";
|
||
while(my $fn = readdir($dh)) {
|
||
next if $fn=~m#^\.\.?$#;
|
||
#perl -le 'my $dh = undef;opendir($dh, ".");while(my $fn = readdir($dh)) { my $mode = (stat($fn))[2];my $fm = $mode % 512;my $fmo=sprintf("%03o",$fm);print "$fn -> $fmo" }'
|
||
my $fullname = "$pwd/$fn";
|
||
printf(" set rights of '$fullname' back to %03o\n", $truerights{$fullname});
|
||
chmodWrap($truerights{$fullname}, $fullname);
|
||
resetRights($fullname) if -d $fullname;
|
||
}
|
||
}
|
||
|
||
sub renameWithRights {
|
||
my ($from, $to) = @_;
|
||
print " rename file '$from' to '$to'\n";
|
||
my %oldrights = %truerights;
|
||
%truerights = ();
|
||
while(my ($k,$v) = each %oldrights) {
|
||
$k =~ s#^\./\Q$from\E#./$to#;
|
||
$truerights{$k} = $v;
|
||
}
|
||
#my $rights = $truerights{$from};
|
||
#delete $truerights{$from};
|
||
rename($from, $to) or die "Could not rename '$from' to '$to', because $!";
|
||
my $waittimer = 20;
|
||
while(-e $from || not(-e $to) and $waittimer-- > 0) {
|
||
sleep 1
|
||
}
|
||
die "rename file from '$from' to '$to', but it is still there" if -e $from;
|
||
die "rename file from '$from' to '$to', but there is no file under the new name" unless -e $to;
|
||
#$truerights{$to} = $rights
|
||
}
|
||
|
||
print Data::Dumper::Dumper(\%truerights);
|
||
#exit 0;
|
||
|
||
# Checksummen:
|
||
# outerjson c27f -- toplevel $outerjson.json, by sha256sum $outerjson.json
|
||
# imageid d940 -- toplevel verzeichnis mit der layer darin; doc says: Each image’s ID is given by the SHA256 hash of its configuration JSON.
|
||
# we'll try as configuration "remove nodejs $oldhash"
|
||
# or we just use a random number ;)
|
||
# layertar fd3d -- doc says: Each image’s ID is given by the SHA256 hash of its configuration JSON.
|
||
#
|
||
##### FOUND
|
||
# outerjson c27f64c8de183296ef409baecc27ddac8cd4065aac760b1b512caf482ad782dd -- in manifest.json
|
||
# imageid d940253667b5ab47060e8bf537bd5b3e66a2447978f3c784a22b115a262fccbf -- in manifest.json
|
||
# imageid d940253667b5ab47060e8bf537bd5b3e66a2447978f3c784a22b115a262fccbf -- as toplevel dirname
|
||
# outerjson c27f64c8de183296ef409baecc27ddac8cd4065aac760b1b512caf482ad782dd -- as toplevel filename
|
||
# imageid d940253667b5ab47060e8bf537bd5b3e66a2447978f3c784a22b115a262fccbf -- in $layerdir/json
|
||
# layertar fd3d3cdf4ece09864ac933aa664eb5f397cf5ca28652125addd689726f8485cd -- in $outerjson.json
|
||
#
|
||
#
|
||
##### COMPUTE
|
||
# toplevel
|
||
# outerjson c27f64c8de183296ef409baecc27ddac8cd4065aac760b1b512caf482ad782dd $outerjson.json
|
||
# b21db3fcc85b23d91067a2a5834e114ca9eec0364742c8680546f040598d8cd9 manifest.json
|
||
# 238f234e3a1ddb27a034f4ee1e59735175741e5cc05673b5dd41d9a42bac2ebd uniworx.tar.gz
|
||
# in $layerdir/
|
||
# 028c1e8d9688b420f7316bb44ce0e26f4712dc21ef93c5af8000c102b1405ad4 json
|
||
# layertar fd3d3cdf4ece09864ac933aa664eb5f397cf5ca28652125addd689726f8485cd layer.tar
|
||
# d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6 VERSION
|
||
#
|
||
#
|
||
# sha256sum layer.tar fd3d3cdf4ece09864ac933aa664eb5f397cf5ca28652125addd689726f8485cd
|
||
|
||
my ($outerjson, $imageid) = ();
|
||
|
||
{
|
||
my $dirh = undef;
|
||
opendir($dirh, '.') or die "Could not read dir '.', because: $!";
|
||
while(my $fn = readdir($dirh)) {
|
||
next if $fn=~m#^\.#;
|
||
if($fn=~m#(.{16,})\.json#) { # it shall match on hash sums but not for example on manifest.json
|
||
$outerjson = $1;
|
||
next
|
||
}
|
||
if($fn=~m#^[0-9a-f]{64}$#) {
|
||
$imageid = $fn
|
||
}
|
||
}
|
||
}
|
||
|
||
die "Bad archive, could not found expected files and directories" unless defined($outerjson) and defined($imageid);
|
||
|
||
#system("pwd");
|
||
#print "will run: sha256sum $imageid/layer.tar\n";
|
||
|
||
my $oldLayerdir = qx(sha256sum $imageid/layer.tar);
|
||
#print "oldLayerdir is for now $oldLayerdir\n\n";
|
||
$oldLayerdir =~ m#^([0-9a-f]{64}).*$# or die "layer.tar not found or sha256sum not installed!";
|
||
$oldLayerdir = $1;
|
||
|
||
# tar --delete --file layer.tar nix/store/cdalbhzm3z4gz07wyg89maprdbjc4yah-nodejs-14.17.0
|
||
my $layerContent = qx(tar -tf $imageid/layer.tar);
|
||
|
||
my @rms = $layerContent=~m#^((?:\./)?nix/store/[a-z0-9]+-(?:nodejs|openjdk|ghc)-[^/]+/)$#gm;
|
||
|
||
print "rm <<$_>>\n" for @rms;
|
||
|
||
system("tar --delete --file $imageid/layer.tar '$_'") for @rms;
|
||
|
||
|
||
### Deconstruction finished, now lets put everything together again after fixing the checksums
|
||
|
||
|
||
my $newImageId = qx(echo 'remove nodejs $imageid' | sha256sum);
|
||
$newImageId =~ m#^([0-9a-f]{64}).*$# or die "sha256sum not installed!";
|
||
$newImageId = $1;
|
||
|
||
my $newLayerdir = qx(sha256sum $imageid/layer.tar);
|
||
$newLayerdir =~ m#^([0-9a-f]{64}).*$# or die "sha256sum not installed!";
|
||
$newLayerdir = $1;
|
||
|
||
# new outerjson is computed later, as we first have to change its content
|
||
|
||
sub cautionWaiter {
|
||
# some file operations give the impression that they are not instant.
|
||
# Hence, we wait here a bit to see if that fixes stuff
|
||
#sleep 5; # seems not to be the reason
|
||
}
|
||
|
||
sub replaceInFile {
|
||
my ($filename, $replacer) = @_;
|
||
return unless -e $filename;
|
||
my $fh = undef;
|
||
open($fh, '<', $filename) or die "Could not read $filename, because: $!";
|
||
my $content = join '', <$fh>;
|
||
close $fh;
|
||
keys %$replacer;
|
||
while(my ($k,$v) = each %$replacer) {
|
||
$content=~s#\Q$k\E#$v#g;
|
||
}
|
||
my $wh = undef;
|
||
open($wh, '>', $filename) or die "Could not write $filename, because: $!";
|
||
print $wh $content;
|
||
close $wh;
|
||
}
|
||
|
||
my %replacer = (
|
||
$oldLayerdir => $newLayerdir,
|
||
$imageid => $newImageId,
|
||
);
|
||
|
||
replaceInFile("$imageid/json", \%replacer);
|
||
replaceInFile("$outerjson.json", \%replacer);
|
||
|
||
cautionWaiter();
|
||
|
||
my $newOuterjson = qx(sha256sum '$outerjson.json');
|
||
$newOuterjson =~ m#^([0-9a-f]{64}).*$# or die "sha256sum not installed!";
|
||
$newOuterjson = $1;
|
||
|
||
cautionWaiter();
|
||
|
||
renameWithRights("$outerjson.json", "$newOuterjson.json");
|
||
$replacer{$outerjson} = $newOuterjson;
|
||
|
||
replaceInFile("manifest.json", \%replacer);
|
||
|
||
replaceInFile("repositories", \%replacer);
|
||
|
||
cautionWaiter();
|
||
renameWithRights($imageid, $newImageId);
|
||
|
||
cautionWaiter();
|
||
|
||
|
||
|
||
|
||
|
||
resetRights(".");
|
||
|
||
|
||
system("find");
|
||
|
||
unlink("uniworx.tar.gz");
|
||
|
||
system("tar czvf uniwox-rmnodejs.tar.gz *");
|
||
|
||
cautionWaiter();
|
||
print "Debug output, content of container:\n";
|
||
system("tar tzvf uniwox-rmnodejs.tar.gz");
|
||
|
||
cautionWaiter();
|
||
#unlink("../uniworx.tar.gz");
|
||
|
||
system("cp uniwox-rmnodejs.tar.gz ../uniworx-sanitized.tar.gz");
|
||
|