| 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 <liezhi.yang@windriver.com> |
| Signed-off-by: Mark Hatle <mark.hatle@windriver.com> |
| |
| --- |
| 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 |
| |