2011-05-12 03:13:55 +00:00
|
|
|
Upstream-Status: Inappropriate [legacy version]
|
|
|
|
|
2011-02-04 02:40:40 +00:00
|
|
|
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
|
|
|
|
|