--- /dev/null
+#!/usr/bin/perl
+
+use POSIX;
+
+$action=0;
+defined($umask=umask) or die $!;
+$home= $ENV{'HOME'}.'/';
+
+while (@ARGV =~ m/^-/) {
+ $_= shift(@ARGV);
+ last if m/^--$/;
+ while (m/^-./) {
+ if (s/^-y/-/) {
+ $action=1;
+ } elsif (s/^-u([0-7]{3})/-/) {
+ $umask= oct $1;
+ } elsif (s/^-h/-/) {
+ $home= $';
+ } else {
+ die;
+ }
+ }
+}
+
+stat $home or die $!;
+-d _ or die;
+
+sub read_prep ($) {
+ my ($inputfile) = @_;
+ defined($c= open P, "-|") or die $!;
+ if (!$c) { exec './gpt','config',$inputfile; die $!; }
+}
+sub fin_prep () {
+ $!=0; close P; die "$! $?" if $! or $?;
+}
+
+read_prep('perms');
+for (;;) {
+ $!=0; defined($_=<P>) or die $!;
+ chomp; s/^\s+//; s/\s+$//;
+ next if m/^\#/; next unless m/\S/;
+ last if m/^\.$/;
+ m/^(.*\S)\s+([0-7]+)$/ or die;
+ ($of,$pe)=($1,oct $2);
+ $isdir= $of =~ s,/$,,;
+ ($isdir ? $dirperms{$of} : $fileperms{$of}) = $pe;
+}
+fin_prep();
+
+sub mkparents ($) {
+ my ($parent) = @_;
+ $parent =~ s,/[^/]+$,, or return;
+ ensuredir($parent);
+}
+
+sub maybe_chmod ($$$) {
+ my ($nowperms,$perms,$obj) = @_;
+ return if $nowperms==$perms;
+ if ($doing) {
+ chmod $perms, $home.$obj or die $!;
+ } else {
+ would($obj, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
+ }
+}
+
+sub ensuredir ($) {
+ my ($dir) = @_;
+ mkparents($dir);
+ $perms= exists $dirperms{$dir} ? $dirperms{$dir} : 02777&~$umask;
+ if (stat $home.$dir) {
+ -d _ or die "$dir is not a directory!";
+ $nowperms= (stat _)[2] & 07777;
+ maybe_chmod($nowperms,$perms,$dir);
+ } else {
+ die $! unless $!==&ENOENT;
+ if ($doing) {
+ mkdir $home.$dir, $perms or die $!;
+ } else {
+ would($dir, sprintf 'mkdir %04o', $perms);
+ }
+ }
+}
+
+-d 'new' or mkdir 'new', 02700 or die $!;
+
+opendir D, "files" or die $!;
+while ($if=readdir D) {
+ next unless $if =~ m/^[:a-z0-9]/;
+ $of= $if;
+ $of =~ s,\:,/,g;
+ $of =~ s,^/,,;
+ $of =~ s,\\\;,:,g;
+ $of =~ s:\\([0-9a-f][0-9a-f]): sprintf '%c', hex $1 :ge;
+
+ $newf= 'new/'.$if;
+ mkparents($of);
+ defined($c= fork) or die $!;
+ if (!$c) {
+ unlink $newf;
+ open STDOUT, "> $newf" or die "$of $newf $!";
+ exec './gpt','config','files/'.$if; die $!;
+ }
+ $!=0; waitpid($c,0)==$c or die $!;
+ $? and die $?;
+
+ $perms= exists $fileperms{$of} ? $fileperms{$of} : 00666&~$umask;
+ chmod $perms, $newf or die $!;
+
+ if (stat $home.$of) {
+ -f _ or die "$of is not a file!";
+ $nowperms= (stat _)[2] & 07777;
+ if (!$action) {
+ if ($nowperms != $perms) {
+ would($of, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
+ }
+ system 'diff','-u',$home.$of,$newf;
+ $?==0 or $?==256 or die $?;
+ }
+ } else {
+ would($of, sprintf 'create %04o', $perms);
+ }
+ if ($action) {
+ rename $newf,$home.$of or die $!;
+ }
+
+ delete $fileperms{$of};
+}
+closedir D or die $!;
+
+die join(', ', keys %fileperms) if %fileperms;
+
+foreach $dir (keys %dirperms) {
+ ensuredir($dir);
+}
+
+sub would ($$) {
+ my ($obj,$what) = @_;
+ return if $would_done{$obj}++;
+ print STDOUT "*** $what $obj\n" or die $!;
+}
+
+close STDOUT or die $!;