Attached a patch without the duplicated '-l $sourcefile'

And some tests:

$ mkdir --parents config/normal_file config/absolute_in-tree_symlink 
config/absolute_out-of-tree_symlink config/etc/relative_in-tree_symlink 
config/etc/relative_out-of-tree_symlink
$ echo '{%PATH%}' > config/normal_file/DEFAULT
$ ln -s /normal_file config/absolute_in-tree_symlink/DEFAULT
$ ln -s /tmp/fai/fai.log config/absolute_out-of-tree_symlink/DEFAULT
$ ln -s ../normal_file config/etc/relative_in-tree_symlink/DEFAULT
$ ln -s ../etc/debian_version config/etc/relative_out-of-tree_symlink/DEFAULT

Without patch:
$ fcopy.orig -s config -t target -c DEFAULT -rHS /
fcopy: config/absolute_in-tree_symlink/DEFAULT is a broken symlink
# Even though normal_file will be copied later, at this point the symlink is 
broken (and later it would still be, because -t is not /)

fcopy: config/etc/relative_in-tree_symlink/DEFAULT is a broken symlink
# In the target tree ../normal_file will be fine, but 
config/etc/relative_in-tree_symlink/../normal_file doesn't resolve

fcopy: config/absolute_out-of-tree_symlink/DEFAULT is a broken symlink
# This would only work during installation

fcopy: copied config/normal_file/DEFAULT to target/normal_file
# Ok

fcopy: config/etc/relative_out-of-tree_symlink/DEFAULT is a broken symlink
# Similar reason to relative_in-tree_symlink

$ cat target/normal_file 
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
# substitution worked

With patch:
$ fcopy -s config -t target -c DEFAULT -rHS /
fcopy: symlinked config/absolute_out-of-tree_symlink/DEFAULT -> 
/tmp/fai/fai.log to target/absolute_out-of-tree_symlink
fcopy: copied config/normal_file/DEFAULT to target/normal_file
fcopy: symlinked config/etc/relative_out-of-tree_symlink/DEFAULT -> 
../etc/debian_version to target/etc/relative_out-of-tree_symlink
fcopy: symlinked config/etc/relative_in-tree_symlink/DEFAULT -> ../normal_file 
to target/etc/relative_in-tree_symlink
fcopy: symlinked config/absolute_in-tree_symlink/DEFAULT -> /normal_file to 
target/absolute_in-tree_symlink

$ cat target/normal_file 
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

With patch and without -H still as expected:
$ mkdir --parents config/some_file target
$ echo '{%PATH%}' > config/some_file/OTHER_CLASS
$ ln -s OTHER_CLASS config/some_file/DEFAULT
$ fcopy -s config -t target -c DEFAULT -r /
fcopy: copied config/some_file/DEFAULT to target/some_file
$ cat target/some_file 
{%PATH%}

With -S too:
$ cat target/some_file 
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
diff --git a/bin/fcopy b/bin/fcopy
index 595bd1ec..87653be1 100755
--- a/bin/fcopy
+++ b/bin/fcopy
@@ -128,19 +128,18 @@ sub copy_one {
   warn "using class: $class\n" if $debug;
   $tmpfile = $sourcefile = "$ps/$class";
 
-  # read symlink
-  if ($opt_H and -l $sourcefile) {
-    $sourcelink = readlink($sourcefile);
-    if (!defined($sourcelink)) {
-      ewarn("reading symlink $sourcefile failed. $!") ;
-      return;
-    }
-  }
-
-  # handle broken symlink
-  unless (stat($sourcefile)) {
-    ewarn("$sourcefile is a broken symlink\n");
-    return;
+  if (-l $sourcefile) {
+      if ($opt_H) {
+	  # read symlink
+	  $sourcelink = readlink($sourcefile);
+	  if (!defined($sourcelink)) {
+	      ewarn("reading symlink $sourcefile failed. $!");
+	      return;
+	  }
+      } elsif (!stat($sourcefile)) {
+	  ewarn("$sourcefile is a broken symlink\n");
+	  return;
+      }
   }
 
   # do we need a tmpfile
@@ -149,7 +148,7 @@ sub copy_one {
     $preinst = 1;        # a tmpfile is used because of preinst script
   }
 
-  if ($substitute or -f "$ps/_substitute") {
+  if (!defined($sourcelink) and ($substitute or -f "$ps/_substitute")) { # substitution, but not when installing symlinks as is with -H
     warn "Enable substitution. Copying $sourcefile to $tmpfile" if $debug;
 
     do_substitution($sourcefile,$tmpfh);

Reply via email to