Außer uns scheint niemand fcopy -H zu benutzen. Weil zusätzlich nicht 
abgefangen wird, wenn stat() schiefgeht, hatten wir plötzlich Files auf Mode 
000. Sehr lustige Effekte, weil es teilweise bei einem softupdate geht und beim 
nächsten nicht (je nachdem, ob das Link-Ziel bereits existiert).

Leider ist lchmod() nicht POSIX (und auf Linux auch offenbar nicht vorhanden).

Man braucht jetzt zusätzlich libfile-lchown-perl.

Der Patch ist nicht sehr ausgiebig getestet, da sollte nochmal jemand 
drübersehen, ob ich irgendwelchen Unsinn gemacht habe.
--- fcopy.1     2017-01-11 16:14:10.000000000 +0100
+++ fcopy.2     2017-01-12 11:54:29.000000000 +0100
@@ -36,6 +36,7 @@
 use File::Basename;
 use File::Spec;
 use File::Temp qw/tempfile/;
+use File::lchown qw/lchown lutimes/;
 use Getopt::Std;
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -298,11 +299,20 @@
     $stime = (stat("$sourcefile/$class"))[9];
   } else {
     # get mtime,uid,gid,mode from source file
-    ($stime,@defmodes) = (stat("$sourcefile/$class"))[9,4,5,2];
+    if ($opt_H) {
+      ($stime,@defmodes) = (lstat("$sourcefile/$class"))[9,4,5,2];
+    } else {
+      ($stime,@defmodes) = (stat("$sourcefile/$class"))[9,4,5,2];
+    }
   }
 
   # get mtime,uid,gid,mode from destination file
-  my ($dtime,@ddefmodes) = (stat("$destfile"))[9,4,5,2];
+  my ($dtime,@ddefmodes);
+  if ($opt_H) {
+    ($dtime,@ddefmodes) = (lstat("$destfile"))[9,4,5,2];
+  } else {
+    ($dtime,@ddefmodes) = (stat("$destfile"))[9,4,5,2];
+  }
   # compare time,uid,gid and mode of source file and target file
 
   if ($modeset) { # use -m values
@@ -314,15 +324,22 @@
   }
 
   # if different: change the values
+  # setting modes on a symlink is not portable, so ignore it
+  my $issymlink = $opt_H && -l $destfile;
   return if ($stime == $dtime && (($ddefmodes[0] == $owner) &&
-      ($ddefmodes[1] == $group) && ($ddefmodes[2] == $mode)));
+      ($ddefmodes[1] == $group) && ($issymlink || ($ddefmodes[2] == $mode))));
 
   ($uid,$gid) = name2num($owner,$group);
   warn "chown/chmod u:$uid g:$gid m:$mode $destfile\n" if $debug;
   return if $dryrun; # do not execute if -n or FCOPY_DRYRUN was given
-  chown ($uid,$gid,     $destfile) || ewarn("chown $owner $group $destfile 
failed. $!");
-  chmod ($mode,         $destfile) || ewarn("chmod $mode $destfile failed. 
$!");
-  utime ($stime,$stime, $destfile) || ewarn("utime for $destfile failed. $!");
+  if ($issymlink) {
+    lchown  ($uid,$gid,     $destfile) || ewarn("lchown $owner $group 
$destfile failed. $!");
+    lutimes ($stime,$stime, $destfile) || ewarn("lutime for $destfile failed. 
$!");
+  } else {
+    chown ($uid,$gid,     $destfile) || ewarn("chown $owner $group $destfile 
failed. $!");
+    chmod ($mode,         $destfile) || ewarn("chmod $mode $destfile failed. 
$!");
+    utime ($stime,$stime, $destfile) || ewarn("utime for $destfile failed. 
$!");
+  }
 }
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 sub check_mopt {

Reply via email to