summaryrefslogtreecommitdiff
path: root/src/copy.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2004-06-01 13:29:36 +0000
committerJim Meyering <jim@meyering.net>2004-06-01 13:29:36 +0000
commitbd62a6597a5c1f6dc218bb1ef007fb308c4fb89f (patch)
tree664ef16f768268df1c507a960a6642b7cde13660 /src/copy.c
parent6992440dfb25579962c17e875cbf4aff7b83b9c4 (diff)
downloadcoreutils-bd62a6597a5c1f6dc218bb1ef007fb308c4fb89f.tar.xz
(copy_internal): Don't use alloca, as it can mess up
royally if the link length is long (e.g., GNU/Hurd). Use xreadlink instead, it's safer. Don't bother to read the link if it's the wrong size. Add a FIXME because this area is a bit murky and undocumented.
Diffstat (limited to 'src/copy.c')
-rw-r--r--src/copy.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/src/copy.c b/src/copy.c
index 395803d9d..ac03d85f0 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1475,7 +1475,7 @@ copy_internal (const char *src_path, const char *dst_path,
#ifdef S_ISLNK
if (S_ISLNK (src_type))
{
- char *src_link_val = xreadlink (src_path);
+ char *src_link_val = xreadlink (src_path, src_sb.st_size);
if (src_link_val == NULL)
{
error (0, errno, _("cannot read symbolic link %s"), quote (src_path));
@@ -1487,17 +1487,18 @@ copy_internal (const char *src_path, const char *dst_path,
else
{
int saved_errno = errno;
- int same_link = 0;
- if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode))
+ bool same_link = false;
+ if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode)
+ && dst_sb.st_size == strlen (src_link_val))
{
- /* See if the destination is already the desired symlink. */
- size_t src_link_len = strlen (src_link_val);
- char *dest_link_val = alloca (src_link_len + 1);
- int dest_link_len = readlink (dst_path, dest_link_val,
- src_link_len + 1);
- if ((size_t) dest_link_len == src_link_len
- && strncmp (dest_link_val, src_link_val, src_link_len) == 0)
- same_link = 1;
+ /* See if the destination is already the desired symlink.
+ FIXME: This behavior isn't documented, and seems wrong
+ in some cases, e.g., if the destination symlink has the
+ wrong ownership, permissions, or time stamps. */
+ char *dest_link_val = xreadlink (dst_path, dst_sb.st_size);
+ if (STREQ (dest_link_val, src_link_val))
+ same_link = true;
+ free (dest_link_val);
}
free (src_link_val);