#!/usr/bin/perl -w # use strict; use IO::Handle; my ($passwd,$dashuid,$chown,$phase) = @ARGV; my $offset = 20000; my $find = "find -xdev"; warn "strips setuid bits!"; our %undomap; # construct array mapping # new_id -> old_id my $re = '^(\w[^:]*)\:[^:]+\:(\d+)\:'; sub find_did ($$) { my ($xname,$xid) = @_; # returns the actual uid that source uid xid was (perhaps mistakenly) # mapped to open D, "$passwd-dst" or die $!; while () { m/$re/o or die "$_ $!"; my ($dname,$did) = ($1,$2); return $did if $dname eq $xname; } die $! if D->error; return $xid; } open S, "$passwd-src" or die $!; while () { m/$re/o or die "$_ $!"; my ($sname,$sid) = ($1,$2); my $did = find_did($sname,$sid); push @{ $undomap{$did} }, $sid; } die $! if S->error; sub mkmap ($$) { my ($in,$out) = @_; printf "$find $dashuid $in -print0 | xargs -0r $chown -- $out\n" or die $!; } our @ambigs; foreach my $sid (keys %undomap) { my @dids = @{ $undomap{$sid} }; next if @dids==1 && $dids[0]==$sid; if ($phase eq '1') { mkmap($sid,$sid+$offset); } elsif ($phase eq '2') { if (@dids==1) { mkmap($sid+$offset,$dids[0]); } else { print "# ambiguous $sid->@dids\n"; print "$find $dashuid ".($sid+$offset)." -ls\n" or die $!; } } elsif ($phase eq '0') { next if @dids==1; push @ambigs, $sid; } else { die "$phase ?"; } } if ($phase eq '0' && @ambigs) { print "$find \\( ". (join " -o ", map { "$dashuid $_" } @ambigs). " \\) -ls\n" or die $!; } close STDOUT or die $!;