#!/usr/bin/perl -w ######################################################################## # # prtsweep # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # This is a script for removing rubbish from a CRUX port tree. # Distributed under the terms of the GPL license. # # ChangeLog and author information available in the prt-utils tarball. # ######################################################################## use strict; use Cwd qw(cwd getcwd); use File::Path; our $version = "1.2.1"; our %options = ( auto => 0, dryrun => 0, rmdir => 0, pkgtoo => 0, quiet => 0 ); our @portdirs; our $argports; ######################### main routine ################################ 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); } } } else { foreach my $port (@portdirs) { do_sweep($port); } } ######################### subroutines ################################# sub print_usage { print <) { if (/^SHA256 \(.+\) =.*$/) { $_ =~ s/^SHA256 \((.+)\) =.*$/$1/; push (@signed, $_) } } close (FILE); return @signed ; } sub sweep { my $port = 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 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); } 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; } } } 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); } } 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)); } 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 ; }