Explorar el Código

(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 hace 19 años
padre
commit
a169d65b94
Se han modificado 1 ficheros con 132 adiciones y 105 borrados
  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);
 }
 
+
+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
    external form, using SUBSTITUTE (...) if VALUE won't fit.  Output
    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 value is negative.  */
 
-static void
+static bool
 to_chars (int negative, uintmax_t value, size_t valsize,
 	  uintmax_t (*substitute) (int *),
 	  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.  */
   if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
     {
       where[size - 1] = '\0';
       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
@@ -237,25 +257,25 @@ gid_substitute (int *negative)
   return r;
 }
 
-void
+bool
 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)
 {
-  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)
 {
-  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)
 {
   /* 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_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)
 {
-  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)
 {
-  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)
 {
-  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
@@ -329,16 +349,16 @@ uid_substitute (int *negative)
   return r;
 }
 
-void
+bool
 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)
 {
-  to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
+  return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
 }
 
 void
@@ -681,7 +701,8 @@ start_header (struct tar_stat_info *st)
 	xheader_store ("uid", st, NULL);
 	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);
 	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);
 	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)
 	  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 */
@@ -732,7 +756,8 @@ start_header (struct tar_stat_info *st)
 	  xheader_store ("devmajor", st, NULL);
 	  devmajor = 0;
 	}
-      MAJOR_TO_CHARS (devmajor, header->header.devmajor);
+      if (!MAJOR_TO_CHARS (devmajor, header->header.devmajor))
+	return NULL;
 
       if (archive_format == POSIX_FORMAT
 	  && MAX_OCTAL_VAL (header->header.devminor) < devminor)
@@ -740,12 +765,14 @@ start_header (struct tar_stat_info *st)
 	  xheader_store ("devminor", st, NULL);
 	  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)
     {
-      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)
@@ -1289,7 +1316,7 @@ dump_hard_link (struct tar_stat_info *st)
 	  st->stat.st_size = 0;
 	  blk = start_header (st);
 	  if (!blk)
-	    return true;
+	    return false;
 	  tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
 
 	  blk->header.typeflag = LNKTYPE;