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);