浏览代码

(gid_to_chars, major_to_chars, minor_to_chars)
(mode_to_chars, off_to_chars, size_to_chars, time_to_chars)
(uid_to_chars, uintmax_to_chars): Return bool
(to_chars): Return bool
(start_header): Check return values of convertion routines. Fail
if unable to store data in the header.

Sergey Poznyakoff 19 年之前
父节点
当前提交
a169d65b94
共有 1 个文件被更改,包括 132 次插入105 次删除
  1. 132 105
      src/create.c

+ 132 - 105
src/create.c

@@ -108,6 +108,68 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
   while (i);
   while (i);
 }
 }
 
 
+
+static bool
+to_chars (int negative, uintmax_t value, size_t valsize,
+	  uintmax_t (*substitute) (int *),
+	  char *where, size_t size, const char *type);
+
+static bool
+to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
+		uintmax_t (*substitute) (int *),
+		char *where, size_t size, const char *type)
+{
+  uintmax_t maxval = (gnu_format
+		      ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
+		      : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
+  char valbuf[UINTMAX_STRSIZE_BOUND + 1];
+  char maxbuf[UINTMAX_STRSIZE_BOUND];
+  char minbuf[UINTMAX_STRSIZE_BOUND + 1];
+  char const *minval_string;
+  char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
+  char const *value_string;
+  char *p;
+    
+  if (gnu_format)
+    {
+      uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
+      char *p = STRINGIFY_BIGINT (m, minbuf + 1);
+      *--p = '-';
+      minval_string = p;
+    }
+  else
+    minval_string = "0";
+  
+  if (negative)
+    {
+      char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
+      *--p = '-';
+      value_string = p;
+    }
+  else
+    value_string = STRINGIFY_BIGINT (value, valbuf);
+	  
+  if (substitute)
+    {
+      int negsub;
+      uintmax_t sub = substitute (&negsub) & maxval;
+      /* FIXME: This is the only place where GNU_FORMAT differs from
+	 OLDGNU_FORMAT. Apart from this they are completely identical. */
+      uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
+      char subbuf[UINTMAX_STRSIZE_BOUND + 1];
+      char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
+      if (negsub)
+	*--sub_string = '-';
+      WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
+	     value_string, type, minval_string, maxval_string,
+	     sub_string));
+      to_chars (negsub, s, valsize, 0, where, size, type);
+    }
+  else
+    ERROR ((0, 0, _("value %s out of %s range %s..%s"),
+	    value_string, type, minval_string, maxval_string));
+}
+
 /* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
 /* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
    external form, using SUBSTITUTE (...) if VALUE won't fit.  Output
    external form, using SUBSTITUTE (...) if VALUE won't fit.  Output
    to buffer WHERE with size SIZE.  NEGATIVE is 1 iff VALUE was
    to buffer WHERE with size SIZE.  NEGATIVE is 1 iff VALUE was
@@ -122,103 +184,61 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
    SUBSTITUTE the address of an 0-or-1 flag recording whether the
    SUBSTITUTE the address of an 0-or-1 flag recording whether the
    substitute value is negative.  */
    substitute value is negative.  */
 
 
-static void
+static bool
 to_chars (int negative, uintmax_t value, size_t valsize,
 to_chars (int negative, uintmax_t value, size_t valsize,
 	  uintmax_t (*substitute) (int *),
 	  uintmax_t (*substitute) (int *),
 	  char *where, size_t size, const char *type)
 	  char *where, size_t size, const char *type)
 {
 {
-  int base256_allowed = (archive_format == GNU_FORMAT
-			 || archive_format == OLDGNU_FORMAT);
+  int gnu_format = (archive_format == GNU_FORMAT
+		    || archive_format == OLDGNU_FORMAT);
 
 
   /* Generate the POSIX octal representation if the number fits.  */
   /* Generate the POSIX octal representation if the number fits.  */
   if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
   if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
     {
     {
       where[size - 1] = '\0';
       where[size - 1] = '\0';
       to_octal (value, where, size - 1);
       to_octal (value, where, size - 1);
+      return true;
     }
     }
-
-  /* Otherwise, generate the base-256 representation if we are
-     generating an old or new GNU format and if the number fits.  */
-  else if (((negative ? -1 - value : value)
-	    <= MAX_VAL_WITH_DIGITS (size - 1, LG_256))
-	   && base256_allowed)
-    {
-      where[0] = negative ? -1 : 1 << (LG_256 - 1);
-      to_base256 (negative, value, where + 1, size - 1);
-    }
-
-  /* Otherwise, if the number is negative, and if it would not cause
-     ambiguity on this host by confusing positive with negative
-     values, then generate the POSIX octal representation of the value
-     modulo 2**(field bits).  The resulting tar file is
-     machine-dependent, since it depends on the host word size.  Yuck!
-     But this is the traditional behavior.  */
-  else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
-    {
-      static int warned_once;
-      if (! warned_once)
-	{
-	  warned_once = 1;
-	  WARN ((0, 0, _("Generating negative octal headers")));
-	}
-      where[size - 1] = '\0';
-      to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
-		where, size - 1);
-    }
-
-  /* Otherwise, output a substitute value if possible (with a
-     warning), and an error message if not.  */
-  else
+  else if (gnu_format)
     {
     {
-      uintmax_t maxval = (base256_allowed
-			  ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
-			  : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
-      char valbuf[UINTMAX_STRSIZE_BOUND + 1];
-      char maxbuf[UINTMAX_STRSIZE_BOUND];
-      char minbuf[UINTMAX_STRSIZE_BOUND + 1];
-      char const *minval_string;
-      char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
-      char const *value_string;
-
-      if (base256_allowed)
-	{
-	  uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
-	  char *p = STRINGIFY_BIGINT (m, minbuf + 1);
-	  *--p = '-';
-	  minval_string = p;
-	}
-      else
-	minval_string = "0";
+      /* Try to cope with the number by using traditional GNU format
+	 methods */
 
 
-      if (negative)
+      /* Generate the base-256 representation if the number fits.  */
+      if (((negative ? -1 - value : value)
+	   <= MAX_VAL_WITH_DIGITS (size - 1, LG_256)))
 	{
 	{
-	  char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
-	  *--p = '-';
-	  value_string = p;
+	  where[0] = negative ? -1 : 1 << (LG_256 - 1);
+	  to_base256 (negative, value, where + 1, size - 1);
+	  return true;
 	}
 	}
-      else
-	value_string = STRINGIFY_BIGINT (value, valbuf);
 
 
-      if (substitute)
+      /* Otherwise, if the number is negative, and if it would not cause
+	 ambiguity on this host by confusing positive with negative
+	 values, then generate the POSIX octal representation of the value
+	 modulo 2**(field bits).  The resulting tar file is
+	 machine-dependent, since it depends on the host word size.  Yuck!
+	 But this is the traditional behavior.  */
+      else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
 	{
 	{
-	  int negsub;
-	  uintmax_t sub = substitute (&negsub) & maxval;
-	  /* FIXME: This is the only place where GNU_FORMAT differs from
-             OLDGNU_FORMAT. Apart from this they are completely identical. */
-	  uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
-	  char subbuf[UINTMAX_STRSIZE_BOUND + 1];
-	  char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
-	  if (negsub)
-	    *--sub_string = '-';
-	  WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
-		 value_string, type, minval_string, maxval_string,
-		 sub_string));
-	  to_chars (negsub, s, valsize, 0, where, size, type);
+	  static int warned_once;
+	  if (! warned_once)
+	    {
+	      warned_once = 1;
+	      WARN ((0, 0, _("Generating negative octal headers")));
+	    }
+	  where[size - 1] = '\0';
+	  to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
+		    where, size - 1);
+	  return true;
 	}
 	}
-      else
-	ERROR ((0, 0, _("value %s out of %s range %s..%s"),
-		value_string, type, minval_string, maxval_string));
+      /* Otherwise fall back to substitution, if possible: */
     }
     }
+  else
+    substitute = NULL; /* No substitution for formats, other than GNU */
+  
+  return to_chars_subst (negative, gnu_format, value, valsize, substitute,
+			 where, size, type);
 }
 }
 
 
 static uintmax_t
 static uintmax_t
@@ -237,25 +257,25 @@ gid_substitute (int *negative)
   return r;
   return r;
 }
 }
 
 
-void
+bool
 gid_to_chars (gid_t v, char *p, size_t s)
 gid_to_chars (gid_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
 }
 }
 
 
-void
+bool
 major_to_chars (major_t v, char *p, size_t s)
 major_to_chars (major_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
 }
 }
 
 
-void
+bool
 minor_to_chars (minor_t v, char *p, size_t s)
 minor_to_chars (minor_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
 }
 }
 
 
-void
+bool
 mode_to_chars (mode_t v, char *p, size_t s)
 mode_to_chars (mode_t v, char *p, size_t s)
 {
 {
   /* In the common case where the internal and external mode bits are the same,
   /* In the common case where the internal and external mode bits are the same,
@@ -292,25 +312,25 @@ mode_to_chars (mode_t v, char *p, size_t s)
 	   | (v & S_IWOTH ? TOWRITE : 0)
 	   | (v & S_IWOTH ? TOWRITE : 0)
 	   | (v & S_IXOTH ? TOEXEC : 0));
 	   | (v & S_IXOTH ? TOEXEC : 0));
     }
     }
-  to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
+  return to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
 }
 }
 
 
-void
+bool
 off_to_chars (off_t v, char *p, size_t s)
 off_to_chars (off_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
 }
 }
 
 
-void
+bool
 size_to_chars (size_t v, char *p, size_t s)
 size_to_chars (size_t v, char *p, size_t s)
 {
 {
-  to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
+  return to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
 }
 }
 
 
-void
+bool
 time_to_chars (time_t v, char *p, size_t s)
 time_to_chars (time_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
 }
 }
 
 
 static uintmax_t
 static uintmax_t
@@ -329,16 +349,16 @@ uid_substitute (int *negative)
   return r;
   return r;
 }
 }
 
 
-void
+bool
 uid_to_chars (uid_t v, char *p, size_t s)
 uid_to_chars (uid_t v, char *p, size_t s)
 {
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
 }
 }
 
 
-void
+bool
 uintmax_to_chars (uintmax_t v, char *p, size_t s)
 uintmax_to_chars (uintmax_t v, char *p, size_t s)
 {
 {
-  to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
+  return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
 }
 }
 
 
 void
 void
@@ -681,7 +701,8 @@ start_header (struct tar_stat_info *st)
 	xheader_store ("uid", st, NULL);
 	xheader_store ("uid", st, NULL);
 	uid = 0;
 	uid = 0;
       }
       }
-    UID_TO_CHARS (uid, header->header.uid);
+    if (!UID_TO_CHARS (uid, header->header.uid))
+      return NULL;
   }
   }
 
 
   {
   {
@@ -692,7 +713,8 @@ start_header (struct tar_stat_info *st)
 	xheader_store ("gid", st, NULL);
 	xheader_store ("gid", st, NULL);
 	gid = 0;
 	gid = 0;
       }
       }
-    GID_TO_CHARS (gid, header->header.gid);
+    if (!GID_TO_CHARS (gid, header->header.gid))
+      return NULL;
   }
   }
 
 
   {
   {
@@ -703,7 +725,8 @@ start_header (struct tar_stat_info *st)
 	xheader_store ("size", st, NULL);
 	xheader_store ("size", st, NULL);
 	size = 0;
 	size = 0;
       }
       }
-    OFF_TO_CHARS (size, header->header.size);
+    if (!OFF_TO_CHARS (size, header->header.size))
+      return NULL;
   }
   }
 
 
   {
   {
@@ -716,7 +739,8 @@ start_header (struct tar_stat_info *st)
 	if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
 	if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
 	  mtime.tv_sec = 0;
 	  mtime.tv_sec = 0;
       }
       }
-    TIME_TO_CHARS (mtime.tv_sec, header->header.mtime);
+    if (!TIME_TO_CHARS (mtime.tv_sec, header->header.mtime))
+      return NULL;
   }
   }
 
 
   /* FIXME */
   /* FIXME */
@@ -732,7 +756,8 @@ start_header (struct tar_stat_info *st)
 	  xheader_store ("devmajor", st, NULL);
 	  xheader_store ("devmajor", st, NULL);
 	  devmajor = 0;
 	  devmajor = 0;
 	}
 	}
-      MAJOR_TO_CHARS (devmajor, header->header.devmajor);
+      if (!MAJOR_TO_CHARS (devmajor, header->header.devmajor))
+	return NULL;
 
 
       if (archive_format == POSIX_FORMAT
       if (archive_format == POSIX_FORMAT
 	  && MAX_OCTAL_VAL (header->header.devminor) < devminor)
 	  && MAX_OCTAL_VAL (header->header.devminor) < devminor)
@@ -740,12 +765,14 @@ start_header (struct tar_stat_info *st)
 	  xheader_store ("devminor", st, NULL);
 	  xheader_store ("devminor", st, NULL);
 	  devminor = 0;
 	  devminor = 0;
 	}
 	}
-      MINOR_TO_CHARS (devminor, header->header.devminor);
+      if (!MINOR_TO_CHARS (devminor, header->header.devminor))
+	return NULL;
     }
     }
   else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
   else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
     {
     {
-      MAJOR_TO_CHARS (0, header->header.devmajor);
-      MINOR_TO_CHARS (0, header->header.devminor);
+      if (!(MAJOR_TO_CHARS (0, header->header.devmajor)
+	    && MINOR_TO_CHARS (0, header->header.devminor)))
+	return NULL;
     }
     }
 
 
   if (archive_format == POSIX_FORMAT)
   if (archive_format == POSIX_FORMAT)
@@ -1289,7 +1316,7 @@ dump_hard_link (struct tar_stat_info *st)
 	  st->stat.st_size = 0;
 	  st->stat.st_size = 0;
 	  blk = start_header (st);
 	  blk = start_header (st);
 	  if (!blk)
 	  if (!blk)
-	    return true;
+	    return false;
 	  tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
 	  tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
 
 
 	  blk->header.typeflag = LNKTYPE;
 	  blk->header.typeflag = LNKTYPE;