]> Dogcows Code - chaz/tar/commitdiff
(to_oct): Prepend leading zeros, not spaces.
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 19 Jun 1999 06:19:27 +0000 (06:19 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 19 Jun 1999 06:19:27 +0000 (06:19 +0000)
Output a trailing NUL unless the value won't fit without it;
this is backward compatible with Unix tar (and with GNU Emacs).
(finish_header): No need to append NUL to chksum, now that
to_oct is doing it.

src/create.c

index 0d7e67e0a719cde68a42949e6ba28b4c958e9637..3a7e56a4645dfb694d753f9fd49af4ab3e2a111f 100644 (file)
@@ -65,9 +65,11 @@ struct link *linklist = NULL;        /* points to first link in list */
 | fact is used by start_header and finish_header, so don't change it!     |
 `------------------------------------------------------------------------*/
 
-/* This should be equivalent to: sprintf (WHERE, "%*lo", SIZE, VALUE);
-   except that we don't assume VALUE fits in an unsigned long, and
-   except that sprintf fills in the trailing NUL and we don't.  */
+/* Output VALUE in octal, using SUBSTITUTE if value won't fit.
+   Output to buffer WHERE with size SIZE.
+   TYPE is the kind of value being output (useful for diagnostics).
+   Prefer SIZE - 1 octal digits (with leading '0's), followed by '\0';
+   but if SIZE octal digits would fit, omit the '\0'.  */
 
 static void
 to_oct (uintmax_t value, uintmax_t substitute, char *where, size_t size, const char *type)
@@ -75,6 +77,15 @@ to_oct (uintmax_t value, uintmax_t substitute, char *where, size_t size, const c
   uintmax_t v = value;
   size_t i = size;
 
+# define MAX_OCTAL_VAL_WITH_DIGITS(digits) \
+    ((digits) * 3 < sizeof (uintmax_t) * CHAR_BIT \
+     ? ((uintmax_t) 1 << ((digits) * 3)) - 1 \
+     : (uintmax_t) -1)
+
+  /* Output a trailing NUL unless the value is too large.  */
+  if (value <= MAX_OCTAL_VAL_WITH_DIGITS (size - 1))
+    where[--i] = '\0';
+
   /* Produce the digits -- at least one.  */
 
   do
@@ -84,16 +95,13 @@ to_oct (uintmax_t value, uintmax_t substitute, char *where, size_t size, const c
     }
   while (i != 0 && v != 0);
 
-  /* Leading spaces, if necessary.  */
+  /* Leading zeros, if necessary.  */
   while (i != 0)
-    where[--i] = ' ';
+    where[--i] = '0';
 
   if (v != 0)
     {
-      int bits = size * 3;
-      uintmax_t maxval = (bits < sizeof (uintmax_t) * CHAR_BIT
-                         ? ((uintmax_t) 1 << bits) - 1
-                         : (uintmax_t) -1);
+      uintmax_t maxval = MAX_OCTAL_VAL_WITH_DIGITS (size);
       char buf1[UINTMAX_STRSIZE_BOUND];
       char buf2[UINTMAX_STRSIZE_BOUND];
       char buf3[UINTMAX_STRSIZE_BOUND];
@@ -395,7 +403,7 @@ finish_header (union block *header)
 
   /* Fill in the checksum field.  It's formatted differently from the
      other fields: it has [6] digits, a null, then a space -- rather than
-     digits, then a null.  We use to_oct then write the null.
+     digits, then a null.  We use to_oct.
      The final space is already there, from checksumming,
      and to_oct doesn't modify it.
 
@@ -403,8 +411,7 @@ finish_header (union block *header)
 
      sprintf(header->header.chksum, "%6o", sum);  */
 
-  uintmax_to_oct ((uintmax_t) sum, header->header.chksum, 6);
-  header->header.chksum[6] = '\0';
+  uintmax_to_oct ((uintmax_t) sum, header->header.chksum, 7);
 
   set_next_block_after (header);
 
This page took 0.031118 seconds and 4 git commands to generate.