1 Description: link extraction fix
2 tar (1.26+dfsg-6) unstable; urgency=low
4 * cherry-pick upstream commit at Paul Eggert's suggestion to address link
5 extraction issue, closes: #452365
6 Author: Bdale Garbee <bdale@gag.com>
7 Bug-Debian: http://bugs.debian.org/452365
9 --- tar-1.26+dfsg.orig/src/extract.c
10 +++ tar-1.26+dfsg/src/extract.c
11 @@ -110,12 +110,15 @@ struct delayed_link
12 /* The next delayed link in the list. */
13 struct delayed_link *next;
15 - /* The device, inode number and ctime of the placeholder. Use
16 - ctime, not mtime, to make false matches less likely if some
17 - other process removes the placeholder. */
18 + /* The device, inode number and birthtime of the placeholder.
19 + birthtime.tv_nsec is negative if the birthtime is not available.
20 + Don't use mtime as this would allow for false matches if some
21 + other process removes the placeholder. Don't use ctime as
22 + this would cause race conditions and other screwups, e.g.,
23 + when restoring hard-linked symlinks. */
26 - struct timespec ctime;
27 + struct timespec birthtime;
29 /* True if the link is symbolic. */
31 @@ -268,6 +271,15 @@ set_mode (char const *file_name,
35 +/* Return true if A and B are the same birthtimes.
36 + Unavailable birthtimes, which have negative tv_nsec members,
37 + all compare equal to each other. */
39 +same_birthtime (struct timespec a, struct timespec b)
41 + return (a.tv_nsec == b.tv_nsec && (a.tv_nsec < 0 || a.tv_sec == b.tv_sec));
44 /* Check time after successfully setting FILE_NAME's time stamp to T. */
46 check_time (char const *file_name, struct timespec t)
47 @@ -1076,7 +1088,7 @@ create_placeholder_file (char *file_name
48 delayed_link_head = p;
51 - p->ctime = get_stat_ctime (&st);
52 + p->birthtime = get_stat_birthtime (&st);
53 p->is_symlink = is_symlink;
56 @@ -1134,7 +1146,7 @@ extract_link (char *file_name, int typef
57 if (ds->change_dir == chdir_current
58 && ds->dev == st1.st_dev
59 && ds->ino == st1.st_ino
60 - && timespec_cmp (ds->ctime, get_stat_ctime (&st1)) == 0)
61 + && same_birthtime (ds->birthtime, get_stat_birthtime (&st1)))
63 struct string_list *p = xmalloc (offsetof (struct string_list, string)
64 + strlen (file_name) + 1);
65 @@ -1500,7 +1512,7 @@ apply_delayed_links (void)
66 if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
67 && st.st_dev == ds->dev
68 && st.st_ino == ds->ino
69 - && timespec_cmp (get_stat_ctime (&st), ds->ctime) == 0)
70 + && same_birthtime (get_stat_birthtime (&st), ds->birthtime))
72 /* Unlink the placeholder, then create a hard link if possible,
73 a symbolic link otherwise. */