diff options
author | Jim Meyering <jim@meyering.net> | 2004-06-01 13:29:36 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2004-06-01 13:29:36 +0000 |
commit | bd62a6597a5c1f6dc218bb1ef007fb308c4fb89f (patch) | |
tree | 664ef16f768268df1c507a960a6642b7cde13660 /src/copy.c | |
parent | 6992440dfb25579962c17e875cbf4aff7b83b9c4 (diff) | |
download | coreutils-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.c | 23 |
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); |