Upstream-Status: Inappropriate [legacy version] The install command doesn't over write the dangling symlink, for example: $ install fileA /tmp/fileA If /tmp/fileA is a dangling symlink, there would be an error: install: cannot create regular file '/tmp/fileA': File exists This is because of the following code in copy.c: if (!new_dst) { if (XSTAT (x, dst_name, &dst_sb) != 0) { if (errno != ENOENT) { error (0, errno, _("cannot stat %s"), quote (dst_name)); return false; } else { new_dst = true; } } XSTAT() use stat() for dst_name(the dangling symlink /tmp/fileA) when install.c invokes it, and stat will set errno to ENOENT, and then new_dst will be set to true which means that /tmp/fileA doesn't exist, then we will create /tmp/fileA without remove it first, so the error comes. This is fixed in a way which adds the member cmd_install in struct cp_options to make sure my change only affected to the install command and use lstat to fix the problem. Signed-off-by: Robert Yang Signed-off-by: Mark Hatle --- src/copy.c | 10 +++++++++- src/copy.h | 3 +++ src/install.c | 1 + 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/src/copy.c b/src/copy.c --- a/src/copy.c +++ b/src/copy.c @@ -1029,6 +1029,7 @@ copy_internal (char const *src_name, char const *dst_name, bool delayed_ok; bool copied_as_regular = false; bool preserve_metadata; + int dst_stat_result; if (x->move_mode && rename_succeeded) *rename_succeeded = false; @@ -1069,7 +1070,14 @@ copy_internal (char const *src_name, char const *dst_name, if (!new_dst) { - if (XSTAT (x, dst_name, &dst_sb) != 0) + if ( x->cmd_install && ( x->backup_type == no_backups)) + dst_stat_result = lstat (dst_name, &dst_sb); + else + { + dst_stat_result = XSTAT (x, dst_name, &dst_sb); + } + + if (dst_stat_result != 0) { if (errno != ENOENT) { diff --git a/src/copy.h b/src/copy.h --- a/src/copy.h +++ b/src/copy.h @@ -114,6 +114,9 @@ struct cp_options If that fails, then resort to copying. */ bool move_mode; + /* For the install command */ + bool cmd_install; + /* Whether this process has appropriate privileges to chown a file whose owner is not the effective user ID. */ bool chown_privileges; diff --git a/src/install.c b/src/install.c --- a/src/install.c +++ b/src/install.c @@ -149,6 +149,7 @@ cp_option_init (struct cp_options *x) x->hard_link = false; x->interactive = I_UNSPECIFIED; x->move_mode = false; + x->cmd_install = true; x->chown_privileges = chown_privileges (); x->one_file_system = false; x->preserve_ownership = false; -- 1.7.0.1