#!/afs/athena/contrib/perl/perl5
#
# Copies the acls for a principle from one directory tree in AFS
# to another.
#
# Usage:  copyacls.pl srcdir destdir principal
#

use File::Find;

$File::Find::dont_use_nlink = 1;

$srcdir; $destdir; $principal;  $do_setacls = 0;

sub afs_get_acl {
    # effects: Returns a hash containing a mapping from principles
    #          to afs acls for the directory $dir.  Returns 0 on failure.
    my ($dir) = @_;
    my (%acl);
    if (!(-d $dir)) { print "*** afs_get_acl: not a dir: $dir\n"; return 0; }
    open FSPIPE, "fs la $dir|" or do { 
	print "*** afs_get_acl: couldn't fs la $dir\n"; return 0; 
    };
    my $firstline = <FSPIPE>;
    if (!($firstline =~ /^Access list for/)) {
	print "*** afs_get_acl: got invalid first line \"$firstline\"\n";
	return 0;
    }
    foreach $cl (<FSPIPE>) {
	chop $cl;
	if ($cl =~ /^Normal rights:/) {
	} elsif ($cl =~ /^Negative rights:/) {
	    print "*** afs_get_acl: negative rights encountered on $dir\n";
	    return %acl;
	} elsif ($cl =~ /^\s+(\S+)\s+(\S+)$/) {
	    $acl{$1} = $2;
	} else {
	    print "*** afs_get_acl: bad format \"$cl\"\n";
	}	
    }
    close FSPIPE;
    return %acl;
}


#%dacl = afs_get_acl($ARGV[0]);
#foreach (keys %dacl) {
#    printf "<%s>\t<%s>\n", $_, $dacl{$_};
#}


sub dir_action {
    my (%acl, $dst);

    if (! -d ) { return; }
    #print "name: $File::Find::name\n";
    #print "dir:  $File::Find::dir\n";
    #print "file: $_\n";
    
    # get acl from source
    my %acl = afs_get_acl $File::Find::name;
    $dst = $File::Find::name;
    $dst =~ s/^$srcdir//;
    $dst = "$dstdir$dst";
    print "src: $File::Find::name\n";
    print "dst: $dst\n" if $do_setacls;
    if ($acl{$principal}) {
	print "acl: $acl{$principal} for $principal\n\n";
	system "fs sa $dst $principal $acl{$principal}" if $do_setacls;
    } else {
	print "acl: NONE for $principal\n\n";
	system "fs sa $dst $principal none"  if $do_setacls;
    }

}

sub print_usage {
    print "Usage:  $0 srcdir dstdir principal\n";
    print "\nCopies the acls for principal from the src tree to dst tree\n";
    print "If dstdir is \"-none\" then just prints acl listing.\n";
    exit -1;
}

$srcdir    = $ARGV[0] || print_usage;
$dstdir    = $ARGV[1] || print_usage;
$principal = $ARGV[2] || print_usage;
if ($dstdir ne "-none") { $do_setacls = 1; }

find (\&dir_action, $srcdir);


