]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
(copy_internal): Don't use alloca, as it can mess up
authorJim Meyering <jim@meyering.net>
Tue, 1 Jun 2004 13:29:36 +0000 (13:29 +0000)
committerJim Meyering <jim@meyering.net>
Tue, 1 Jun 2004 13:29:36 +0000 (13:29 +0000)
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.

src/copy.c

index 395803d9dcffa73e2267f446b491b6f275ffd645..ac03d85f0e826a7da7392435b6e76147b6293138 100644 (file)
@@ -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);