Blame SOURCES/tar-1.26-fix-symlink-eating-bug.patch

b77676
diff --git a/gnu/stat-time.h b/gnu/stat-time.h
b77676
index 1dc4098..7b8428e 100644
b77676
--- a/gnu/stat-time.h
b77676
+++ b/gnu/stat-time.h
b77676
@@ -144,7 +144,7 @@ get_stat_mtime (struct stat const *st)
b77676
 }
b77676
 
b77676
 /* Return *ST's birth time, if available; otherwise return a value
b77676
-   with negative tv_nsec.  */
b77676
+   with tv_sec and tv_nsec both equal to -1.  */
b77676
 static inline struct timespec
b77676
 get_stat_birthtime (struct stat const *st)
b77676
 {
b77676
@@ -163,7 +163,7 @@ get_stat_birthtime (struct stat const *st)
b77676
   t.tv_sec = st->st_ctime;
b77676
   t.tv_nsec = 0;
b77676
 #else
b77676
-  /* Birth time is not supported.  Set tv_sec to avoid undefined behavior.  */
b77676
+  /* Birth time is not supported.  */
b77676
   t.tv_sec = -1;
b77676
   t.tv_nsec = -1;
b77676
   /* Avoid a "parameter unused" warning.  */
b77676
@@ -177,10 +177,12 @@ get_stat_birthtime (struct stat const *st)
b77676
      using zero.  Attempt to work around this problem.  Alas, this can
b77676
      report failure even for valid time stamps.  Also, NetBSD
b77676
      sometimes returns junk in the birth time fields; work around this
b77676
-     bug if it it is detected.  There's no need to detect negative
b77676
-     tv_nsec junk as negative tv_nsec already indicates an error.  */
b77676
-  if (t.tv_sec == 0 || 1000000000 <= t.tv_nsec)
b77676
-    t.tv_nsec = -1;
b77676
+     bug if it is detected.  */
b77676
+  if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
b77676
+    {
b77676
+      t.tv_sec = -1;
b77676
+      t.tv_nsec = -1;
b77676
+    }
b77676
 #endif
b77676
 
b77676
   return t;
b77676
diff --git a/src/extract.c b/src/extract.c
b77676
index 340beea..3afb95d 100644
b77676
--- a/src/extract.c
b77676
+++ b/src/extract.c
b77676
@@ -119,12 +119,15 @@ struct delayed_link
b77676
     /* The next delayed link in the list.  */
b77676
     struct delayed_link *next;
b77676
 
b77676
-    /* The device, inode number and ctime of the placeholder.  Use
b77676
-       ctime, not mtime, to make false matches less likely if some
b77676
-       other process removes the placeholder.  */
b77676
+    /* The device, inode number and birthtime of the placeholder.
b77676
+       birthtime.tv_nsec is negative if the birthtime is not available.
b77676
+       Don't use mtime as this would allow for false matches if some
b77676
+       other process removes the placeholder.  Don't use ctime as
b77676
+       this would cause race conditions and other screwups, e.g.,
b77676
+       when restoring hard-linked symlinks.  */
b77676
     dev_t dev;
b77676
     ino_t ino;
b77676
-    struct timespec ctime;
b77676
+    struct timespec birthtime;
b77676
 
b77676
     /* True if the link is symbolic.  */
b77676
     bool is_symlink;
b77676
@@ -1200,7 +1203,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
b77676
       delayed_link_head = p;
b77676
       p->dev = st.st_dev;
b77676
       p->ino = st.st_ino;
b77676
-      p->ctime = get_stat_ctime (&st);
b77676
+      p->birthtime = get_stat_birthtime (&st);
b77676
       p->is_symlink = is_symlink;
b77676
       if (is_symlink)
b77676
 	{
b77676
@@ -1265,7 +1268,8 @@ extract_link (char *file_name, int typeflag)
b77676
 	      if (ds->change_dir == chdir_current
b77676
 		  && ds->dev == st1.st_dev
b77676
 		  && ds->ino == st1.st_ino
b77676
-		  && timespec_cmp (ds->ctime, get_stat_ctime (&st1)) == 0)
b77676
+		  && (timespec_cmp (ds->birthtime, get_stat_birthtime (&st1))
b77676
+		      == 0))
b77676
 		{
b77676
 		  struct string_list *p =  xmalloc (offsetof (struct string_list, string)
b77676
 						    + strlen (file_name) + 1);
b77676
@@ -1638,7 +1642,7 @@ apply_delayed_links (void)
b77676
 	  if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
b77676
 	      && st.st_dev == ds->dev
b77676
 	      && st.st_ino == ds->ino
b77676
-	      && timespec_cmp (get_stat_ctime (&st), ds->ctime) == 0)
b77676
+	      && timespec_cmp (get_stat_birthtime (&st), ds->birthtime) == 0)
b77676
 	    {
b77676
 	      /* Unlink the placeholder, then create a hard link if possible,
b77676
 		 a symbolic link otherwise.  */