From 495ce0457f1b835757b89ad5d72dbb55858c7b61 Mon Sep 17 00:00:00 2001 From: John McQuah Date: Mon, 7 Aug 2023 08:50:12 -0400 Subject: [PATCH] prtsweep.pl: fall back to md5sums if signature file is not found --- man1/prtwash.1 | 4 +- scripts/prtsweep.pl | 282 ++++++++++++++++++++++---------------------- 2 files changed, 146 insertions(+), 140 deletions(-) diff --git a/man1/prtwash.1 b/man1/prtwash.1 index f794546..cb16b06 100644 --- a/man1/prtwash.1 +++ b/man1/prtwash.1 @@ -115,8 +115,8 @@ algorithm makes it easy to wash all your locally-curated repositories, in contra to the algorithm in \fBprtsweep\fP(1) which looks at the sup files used by \fBports\fP(8). .PP Another contrast between the two tools is that \fBprtwash\fP sources each Pkgfile to -generate its keep list, whereas \fBprtsweep\fP reads the signatures file. Spawning an -external bash shell for each port should in theory make \fBprtwash\fP slower +generate its keep list, whereas \fBprtsweep\fP reads the SHA256 or MD5 sums from a manifest. +Spawning an external bash shell for each port should in theory make \fBprtwash\fP slower than \fBprtsweep\fP (which does everything in native perl), but on modern hardware the difference is basically undetectable. .PP diff --git a/scripts/prtsweep.pl b/scripts/prtsweep.pl index 6f0c6fe..9ef4c82 100755 --- a/scripts/prtsweep.pl +++ b/scripts/prtsweep.pl @@ -24,22 +24,22 @@ parse_args(); print_usage() if ((2*$argports-1)*(1-2*$options{auto}) < 0); if ($options{auto} == 1) { - my @basedirs = getportdirs(); - foreach my $collection (@basedirs) { - print "====> Sweeping port collection $collection\n"; - foreach my $port (list_subdirs($collection)) { - do_sweep($port); - } - } + my @basedirs = getportdirs(); + foreach my $collection (@basedirs) { + print "====> Sweeping port collection $collection\n"; + foreach my $port (list_subdirs($collection)) { + do_sweep($port); + } + } } else { - foreach my $port (@portdirs) { - do_sweep($port); - } + foreach my $port (@portdirs) { + do_sweep($port); + } } ######################### subroutines ################################# sub print_usage { - print <) { - if (/^SHA256 \(.+\) =.*$/) { - $_ =~ s/^SHA256 \((.+)\) =.*$/$1/; - push (@signed, $_) - } - } - close (FILE); - return @signed ; +sub parse_manifest { + my $sigfile = shift; + my $sigtype = (split /\//, $sigfile)[-1]; + my @keeplist = ("Pkgfile",".footprint","README","README.md", + "pre-install","post-install",".32bit",".nostrip"); + push (@keeplist,$sigtype); + open (FILE, $sigfile) or return @keeplist; + while () { + if (($sigtype eq ".signature") and (/^SHA256 \((.+)\) =.*$/)) { + push (@keeplist, $1); + } elsif ($sigtype eq ".md5sum") { + my ($m, $f) = split /\s+/, $_; + push (@keeplist, $f); + } + } + close (FILE); + return @keeplist ; } sub sweep { - my $port = shift; - while ($port =~ s/\/\//\//g) {} - $port =~ s/\/$//; - my @path = split /\//, $port; + my $port = shift; my $sigtype = shift; + while ($port =~ s/\/\//\//g) {} + $port =~ s/\/$//; + my @path = split /\//, $port; - print "=======> $port\n" unless $options{quiet}==1; - my @wanted = parse_signature ("$port/.signature"); - my $builtpkg=$path[-1].'#.*pkg\.tar\.(bz2|gz|lz|xz)$'; - $builtpkg =~ s/\+/\\\+/; # plus sign in filenames interferes with regex search + print "=======> $port\n" unless $options{quiet}==1; + my %wanted = map { $_ => 1 } parse_manifest ("$port/.$sigtype"); + my $builtpkg=$path[-1].'#.*pkg\.tar\.(bz2|gz|lz|xz)$'; + $builtpkg =~ s/\+/\\\+/; # plus sign in filenames interferes with regex search - opendir (DIR, $port) or return; - foreach my $f (sort(readdir(DIR))) { - next if ( $f eq '.' or $f eq '..' ); - $f =~ s/\+/\\\+/; - if ((grep /$f/, @wanted) >= 1 or - ($f =~ /$builtpkg/)*($options{pkgtoo}==0)) { - print "... keeping file $port/$f.\n" unless $options{quiet} == 1; - } else { - remove ("$port/$f"); - } - } - closedir (DIR); + opendir (DIR, $port) or return; + foreach my $f (sort(readdir(DIR))) { + next if ( $f eq '.' or $f eq '..' ); + if (($wanted{$f}) or + ($f =~ /$builtpkg/)*($options{pkgtoo}==0)) { + print "... keeping file $port/$f.\n" unless $options{quiet} == 1; + } else { + remove ("$port/$f"); + } + } + closedir (DIR); } sub remove { - my $path=shift; - my $append = ($options{dryrun}==1) ? "(dry run)\n" : "\n"; - if (-d $path) { - print "+ removing directory $path $append"; - rmtree ($path,0,1) if ($options{dryrun}==0); - } else { - print "+ removing file $path $append"; - if ($options{dryrun}==0) { unlink "$path" or return; } - } + my $path=shift; + my $append = ($options{dryrun}==1) ? "(dry run)\n" : "\n"; + if (-d $path) { + print "+ removing directory $path $append"; + rmtree ($path,0,1) if ($options{dryrun}==0); + } else { + print "+ removing file $path $append"; + if ($options{dryrun}==0) { unlink "$path" or return; } + } } sub do_sweep { - # argument either a real directory (not symlink) or has a signature; - # this subroutine determines which condition was satisfied. - my $port = shift; my $nf = 0; - if (! -f "$port/.signature") { - opendir (PORTDIR,$port) or return; - foreach my $f (readdir PORTDIR) { - next if ($f eq '.' or $f eq '..'); - $nf += 1; - } - closedir (PORTDIR); - print "WARN: $port/.signature not found, invalid port directory."; - rm_emptydir($port,$nf); - } else { - sweep($port); - } + # argument either a real directory (not symlink) or has a manifest; + # this subroutine determines which condition was satisfied. + my $port = shift; my $nf = 0; + if ((! -f "$port/.signature") and (! -f "$port/.md5sum")) { + opendir (PORTDIR,$port) or return; + foreach my $f (readdir PORTDIR) { + next if ($f eq '.' or $f eq '..'); + $nf += 1; + } + closedir (PORTDIR); + print "WARN: no signature or md5sum found in directory $port, skipping.\n"; + rm_emptydir($port,$nf); + } elsif (-f "$port/.signature") { + sweep($port,"signature"); + } else { + sweep($port,"md5sum"); + } } sub rm_emptydir { - my $port = shift; my $nf = shift; - my $msg = ($options{rmdir}==1) ? "\n": - "\n Use -d to remove empty directories.\n"; - my $modal = ($options{dryrun}==0) ? "" : "would be"; - my $post = ($nf == 0) ? " Empty directory $port $modal deleted.\n" : - " Cannot remove $port: directory not empty\n"; - $msg = ($options{rmdir}==1) ? "$msg $post" : $msg ; - print $msg; - rmdir ($port) if (($nf == 0) and ($options{dryrun} == 0)); + my $port = shift; my $nf = shift; + my $msg = ($options{rmdir}==1) ? "\n": + "\n Use -d to remove empty directories.\n"; + my $modal = ($options{dryrun}==0) ? "" : "would be"; + my $post = ($nf == 0) ? " Empty directory $port $modal deleted.\n" : + " Cannot remove $port: directory not empty\n"; + $msg = ($options{rmdir}==1) ? "$msg $post" : $msg ; + print $msg; + rmdir ($port) if (($nf == 0) and ($options{dryrun} == 0)); } sub getportdirs { - my $collection; - my @basedirs; - my $portetc = "/etc/ports/"; - opendir (PORTS_DEFS,$portetc) or die "cannot open $portetc for reading"; - foreach (readdir PORTS_DEFS) { - next if ($_ eq '.' or $_ eq '..'); - if (/.*(rsync|httpup)$/) { - open SYNC, $portetc.$_ or die "cannot open $portetc.$_"; - while () { - $collection=$2 if /^(destination|ROOT_DIR)=(.+)$/; - } - close SYNC; - push (@basedirs , $collection); - } elsif (/.*git$/) { - open SYNC, $portetc.$_ or die "cannot open $portetc.$_"; - while () { - $collection="/usr/ports/$1" if /^NAME=(.+)$/; - } - close SYNC; - push (@basedirs , $collection); - } else {} - } - closedir PORTS_DEFS; - return @basedirs ; + my $collection; + my @basedirs; + my $portetc = "/etc/ports/"; + opendir (PORTS_DEFS,$portetc) or die "cannot open $portetc for reading"; + foreach (readdir PORTS_DEFS) { + next if ($_ eq '.' or $_ eq '..'); + if (/.*(rsync|httpup)$/) { + open SYNC, $portetc.$_ or die "cannot open $portetc.$_"; + while () { + $collection=$2 if /^(destination|ROOT_DIR)=(.+)$/; + } + close SYNC; + push (@basedirs , $collection); + } elsif (/.*git$/) { + open SYNC, $portetc.$_ or die "cannot open $portetc.$_"; + while () { + $collection="/usr/ports/$1" if /^NAME=(.+)$/; + } + close SYNC; + push (@basedirs , $collection); + } else {} + } + closedir PORTS_DEFS; + return @basedirs ; }