summaryrefslogtreecommitdiff
path: root/src/compare.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-07-13 09:46:17 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2015-07-13 09:53:56 -0700
commit3828942550fba1f88136ffbc018a72bdeb930902 (patch)
tree3208609270898f3cabf494a7ecb6394f7d6ee4cd /src/compare.c
parentd95457e0071f26b1e524c754adf211abdd53d0fa (diff)
downloadtar-3828942550fba1f88136ffbc018a72bdeb930902.tar.gz
tar: port -d to longer symlinks
* src/compare.c (diff_symlink): Don't use alloca on symlink length; it might be too big for the stack. Don't assume that readlinkat's return value fits in 'int'. Prefer memcmp to strncmp where either will do.
Diffstat (limited to 'src/compare.c')
-rw-r--r--src/compare.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/compare.c b/src/compare.c
index d29cfdd4..7ed45584 100644
--- a/src/compare.c
+++ b/src/compare.c
@@ -270,11 +270,12 @@ diff_link (void)
static void
diff_symlink (void)
{
+ char buf[1024];
size_t len = strlen (current_stat_info.link_name);
- char *linkbuf = alloca (len + 1);
+ char *linkbuf = len < sizeof buf ? buf : xmalloc (len + 1);
- int status = readlinkat (chdir_fd, current_stat_info.file_name,
- linkbuf, len + 1);
+ ssize_t status = readlinkat (chdir_fd, current_stat_info.file_name,
+ linkbuf, len + 1);
if (status < 0)
{
@@ -285,8 +286,11 @@ diff_symlink (void)
report_difference (&current_stat_info, NULL);
}
else if (status != len
- || strncmp (current_stat_info.link_name, linkbuf, len) != 0)
+ || memcmp (current_stat_info.link_name, linkbuf, len) != 0)
report_difference (&current_stat_info, _("Symlink differs"));
+
+ if (linkbuf != buf)
+ free (linkbuf);
}
#endif