tar (1.23-3) direct (non packaging) changes

Summary

 rmt/rmt.c            |   81 +++++++++++++++++++++++++---------------
 src/create.c         |    4 +-
 src/extract.c        |  101 +++++++++++++++++++++++++++++++++------------------
 src/list.c           |    8 ++++
 tests/incremental.at |    2 -
 5 files changed, 128 insertions(+), 68 deletions(-)

    
download this patch

Patch contents

--- tar-1.23.orig/tests/incremental.at
+++ tar-1.23/tests/incremental.at
@@ -39,7 +39,7 @@
 # command, behaviour of tar becomes variable, depending whether the system
 # clock ticked over to the next second between creating the file and
 # backing it up.
-sleep 1
+sleep 2
 
 tar cf archive --listed=list structure
 tar cfv archive --listed=list structure
--- tar-1.23.orig/src/list.c
+++ tar-1.23/src/list.c
@@ -144,9 +144,17 @@
 	                            read_header_auto);
 	      if (status == HEADER_ZERO_BLOCK)
 		break;
+	      /* 
+	       * According to POSIX tar specs, this is wrong, but on the web
+	       * there are some tar specs that can trigger this, and some tar
+	       * implementations create tars according to that spec.  For now,
+	       * let's not be pedantic about issuing the warning.
+	       */
+#if 0	       
 	      WARNOPT (WARN_ALONE_ZERO_BLOCK,
 		       (0, 0, _("A lone zero block at %s"),
 			STRINGIFY_BIGINT (current_block_ordinal (), buf)));
+#endif
 	      break;
 	    }
 	  status = prev_status;
--- tar-1.23.orig/src/extract.c
+++ tar-1.23/src/extract.c
@@ -888,12 +888,22 @@
   struct stat st;
 
   while ((fd = open (file_name, O_WRONLY | O_CREAT | O_EXCL, 0)) < 0)
-    if (! maybe_recoverable (file_name, interdir_made))
-      break;
+    {
+      switch (maybe_recoverable (file_name, interdir_made))
+	{
+	case RECOVER_OK:
+	  continue;
+	  
+	case RECOVER_SKIP:
+	  return 0;
+	  
+	case RECOVER_NO:
+	  open_error (file_name);
+	  return -1;
+	}
+      }
 
-  if (fd < 0)
-    open_error (file_name);
-  else if (fstat (fd, &st) != 0)
+  if (fstat (fd, &st) != 0)
     {
       stat_error (file_name);
       close (fd);
@@ -956,7 +966,8 @@
 {
   int interdir_made = 0;
   char const *link_name;
-
+  int rc;
+  
   link_name = current_stat_info.link_name;
   
   if (! absolute_names_option && contains_dot_dot (link_name))
@@ -996,8 +1007,10 @@
 
       errno = e;
     }
-  while (maybe_recoverable (file_name, &interdir_made));
+  while ((rc = maybe_recoverable (file_name, &interdir_made)) == RECOVER_OK);
 
+  if (rc == RECOVER_SKIP)
+    return 0;
   if (!(incremental_option && errno == EEXIST))
     {
       link_error (link_name, file_name);
@@ -1010,7 +1023,6 @@
 extract_symlink (char *file_name, int typeflag)
 {
 #ifdef HAVE_SYMLINK
-  int status;
   int interdir_made = 0;
 
   if (! absolute_names_option
@@ -1018,15 +1030,22 @@
 	  || contains_dot_dot (current_stat_info.link_name)))
     return create_placeholder_file (file_name, true, &interdir_made);
 
-  while ((status = symlink (current_stat_info.link_name, file_name)))
-    if (!maybe_recoverable (file_name, &interdir_made))
-      break;
-
-  if (status == 0)
-    set_stat (file_name, &current_stat_info, NULL, 0, 0, SYMTYPE);
-  else
-    symlink_error (current_stat_info.link_name, file_name);
-  return status;
+  while (symlink (current_stat_info.link_name, file_name))
+    switch (maybe_recoverable (file_name, &interdir_made))
+      {
+      case RECOVER_OK:
+	continue;
+	
+      case RECOVER_SKIP:
+	return 0;
+	
+      case RECOVER_NO:
+	symlink_error (current_stat_info.link_name, file_name);
+	return -1;
+      }
+  
+  set_stat (file_name, &current_stat_info, NULL, 0, 0, SYMTYPE);
+  return 0;
 
 #else
   static int warned_once;
@@ -1052,16 +1071,23 @@
   mode_t invert_permissions =
     0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
 
-  do
-    status = mknod (file_name, mode ^ invert_permissions,
-		    current_stat_info.stat.st_rdev);
-  while (status && maybe_recoverable (file_name, &interdir_made));
+  while (mknod (file_name, mode ^ invert_permissions,
+		current_stat_info.stat.st_rdev))
+    switch (maybe_recoverable (file_name, &interdir_made))
+      {
+      case RECOVER_OK:
+	continue;
+	
+      case RECOVER_SKIP:
+	return 0;
+	
+      case RECOVER_NO:
+	mknod_error (file_name);
+	return -1;
+      }
 
-  if (status != 0)
-    mknod_error (file_name);
-  else
-    set_stat (file_name, &current_stat_info, NULL, invert_permissions,
-	      ARCHIVED_PERMSTATUS, typeflag);
+  set_stat (file_name, &current_stat_info, NULL, invert_permissions,
+	    ARCHIVED_PERMSTATUS, typeflag);
   return status;
 }
 #endif
@@ -1077,15 +1103,22 @@
     0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
 
   while ((status = mkfifo (file_name, mode)) != 0)
-    if (!maybe_recoverable (file_name, &interdir_made))
-      break;
+    switch (maybe_recoverable (file_name, &interdir_made))
+      {
+      case RECOVER_OK:
+	continue;
+	
+      case RECOVER_SKIP:
+	return 0;
+	
+      case RECOVER_NO:
+	mkfifo_error (file_name);
+	return -1;
+      }
 
-  if (status == 0)
-    set_stat (file_name, &current_stat_info, NULL, invert_permissions,
-	      ARCHIVED_PERMSTATUS, typeflag);
-  else
-    mkfifo_error (file_name);
-  return status;
+  set_stat (file_name, &current_stat_info, NULL, invert_permissions,
+	    ARCHIVED_PERMSTATUS, typeflag);
+  return 0;
 }
 #endif
 
--- tar-1.23.orig/src/create.c
+++ tar-1.23/src/create.c
@@ -747,7 +747,7 @@
       return write_short_name (st);
     }
   else if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
-	   < strlen (st->file_name))
+	   <= strlen (st->file_name))
     return write_long_name (st);
   else
     return write_short_name (st);
@@ -1399,7 +1399,7 @@
 	  block_ordinal = current_block_ordinal ();
 	  assign_string (&st->link_name, link_name);
 	  if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
-	      < strlen (link_name))
+	      <= strlen (link_name))
 	    write_long_link (st);
 
 	  st->stat.st_size = 0;
--- tar-1.23.orig/rmt/rmt.c
+++ tar-1.23/rmt/rmt.c
@@ -100,6 +100,7 @@
   va_list ap;
   va_start (ap, fmt);
   vfprintf (stdout, fmt, ap);
+  fflush (stdout);
   VDEBUG (10, "S: ", fmt, ap);
 }
 
@@ -117,6 +118,7 @@
   DEBUG1 (10, "S: %s\n", msg);
   DEBUG1 (1, "error: %s\n", msg);
   fprintf (stdout, "E%d\n%s\n", code, msg);
+  fflush (stdout);
 }
 
 void
@@ -225,44 +227,57 @@
 int
 decode_open_flag (const char *mstr, int *pmode)
 {
+  int numeric_mode = 0;
   int mode = 0;
+  const char *p;
 
-  while (mstr)
+  mstr = skip_ws (mstr);
+  if (c_isdigit (*mstr))
     {
-      int v;
-      const char *p;
-
-      mstr = skip_ws (mstr);
-      if (*mstr == 0)
-	break;
-      else if (c_isdigit (*mstr))
-	v = strtol (mstr, (char**) &p, 10);
-      else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
-	{
-	  rmt_error_message (EINVAL, "invalid open mode");
-	  return 1;
-	}
-
-      mode |= v;
+      numeric_mode = strtol (mstr, (char**) &p, 10);
+      mstr = skip_ws (p);
+    }
       
-      if (*p && c_isblank (*p))
-	p = skip_ws (p);
-      if (*p == 0)
-	break;
-      else if (*p == '|')
-	{
-	  /* FIXMEL
-	     if (p[1] == 0)
-	       rmt_error_message (EINVAL, "invalid open mode");
-	  */
-	  mstr = p + 1;
-	}
-      else
+  if (*mstr)
+    {
+       while (mstr)
 	{
-	  rmt_error_message (EINVAL, "invalid open mode");
-	  return 1;
+          int v;
+        
+          mstr = skip_ws (mstr);
+          if (*mstr == 0)
+            break;
+          else if (c_isdigit (*mstr))
+            v = strtol (mstr, (char**) &p, 10);
+          else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
+            {
+              rmt_error_message (EINVAL, "invalid open mode");
+              return 1;
+            }
+  
+          mode |= v;
+        
+          if (*p && c_isblank (*p))
+            p = skip_ws (p);
+          if (*p == 0)
+            break;
+          else if (*p == '|')
+            {
+              /* FIXMEL
+                 if (p[1] == 0)
+                 rmt_error_message (EINVAL, "invalid open mode");
+              */
+              mstr = p + 1;
+            }
+          else
+            {
+              rmt_error_message (EINVAL, "invalid open mode");
+              return 1;
+            }
 	}
     }
+  else
+    mode = numeric_mode;
   *pmode = mode;
   return 0;
 }
@@ -288,6 +303,10 @@
       64|512
       CREAT|TRUNC
 
+   In addition, a compined form is also allowed, i.e. a decimal mode followed
+   by its symbolic representation.  In this case the symbolic representation
+   is given preference.
+
    Reply
    -----
    A0\n on success, E<errno>\n<msg>\n on error.