]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Prefer function to COPY_STRING macro
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 18 Aug 2024 16:44:25 +0000 (09:44 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 19 Aug 2024 16:57:13 +0000 (09:57 -0700)
* src/sparse.c (struct block_ptr):
New type, to allow a functional style.
(dump_str_nl, floorlog10): New static functions.
(COPY_STRING): Remove.  All uses replaced by dump_str_nl.
(pax_dump_header_1): Use floorlog10 instead of creating a string.
Simplify size calculation.

src/sparse.c

index 80a1ff59174d237681b9edcbfdee3e64f9aa494b..c79e69972708369d424e31c18d7b75e5b77ea57f 100644 (file)
@@ -1159,48 +1159,65 @@ pax_dump_header_0 (struct tar_sparse_file *file)
   return true;
 }
 
+/* An output block BLOCK, and a pointer PTR into it.  */
+struct block_ptr
+{
+  union block *block;
+  char *ptr;
+};
+
+/* Append to BP the contents of the string SRC, followed by a newline.
+   If the string doesn’t fit, put any overflow into the succeeding blocks.
+   Return the updated BP.  */
+static struct block_ptr
+dump_str_nl (struct block_ptr bp, char const *str)
+{
+  char *endp = bp.block->buffer + BLOCKSIZE;
+  char c;
+  do
+    {
+      c = *str++;
+      if (bp.ptr == endp)
+       {
+         set_next_block_after (bp.block);
+         bp.block = find_next_block ();
+         bp.ptr = bp.block->buffer;
+         endp = bp.block->buffer + BLOCKSIZE;
+       }
+      *bp.ptr++ = c ? c : '\n';
+    }
+  while (c);
+
+  return bp;
+}
+
+/* Return the floor of the log base 10 of N.  If N is 0, return 0.  */
+static int
+floorlog10 (uintmax_t n)
+{
+  for (int f = 0; ; f++)
+    if ((n /= 10) == 0)
+      return f;
+}
+
 static bool
 pax_dump_header_1 (struct tar_sparse_file *file)
 {
   off_t block_ordinal = current_block_ordinal ();
-  union block *blk;
-  char *p, *q;
-  size_t i;
   char nbuf[UINTMAX_STRSIZE_BOUND];
-  off_t size = 0;
   struct sp_array *map = file->stat_info->sparse_map;
   char *save_file_name = file->stat_info->file_name;
 
-#define COPY_STRING(b,dst,src) do                \
- {                                               \
-   char *endp = b->buffer + BLOCKSIZE;           \
-   char const *srcp = src;                       \
-   while (*srcp)                                 \
-     {                                           \
-       if (dst == endp)                          \
-        {                                       \
-          set_next_block_after (b);             \
-          b = find_next_block ();               \
-           dst = b->buffer;                      \
-          endp = b->buffer + BLOCKSIZE;         \
-        }                                       \
-       *dst++ = *srcp++;                         \
-     }                                           \
-   } while (0)
-
   /* Compute stored file size */
-  p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
-  size += strlen (p) + 1;
-  for (i = 0; i < file->stat_info->sparse_map_avail; i++)
+  off_t size = floorlog10 (file->stat_info->sparse_map_avail) + 2;
+  for (idx_t i = 0; i < file->stat_info->sparse_map_avail; i++)
     {
-      p = umaxtostr (map[i].offset, nbuf);
-      size += strlen (p) + 1;
-      p = umaxtostr (map[i].numbytes, nbuf);
-      size += strlen (p) + 1;
+      size += floorlog10 (map[i].offset) + 2;
+      size += floorlog10 (map[i].numbytes) + 2;
     }
-  size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
-  file->stat_info->archive_file_size += size * BLOCKSIZE;
-  file->dumped_size += size * BLOCKSIZE;
+  size = (size + BLOCKSIZE - 1) / BLOCKSIZE * BLOCKSIZE;
+  file->stat_info->archive_file_size += size;
+  file->dumped_size += size;
 
   /* Store sparse file identification */
   xheader_store ("GNU.sparse.major", file->stat_info, NULL);
@@ -1214,27 +1231,22 @@ pax_dump_header_1 (struct tar_sparse_file *file)
   if (strlen (file->stat_info->file_name) > NAME_FIELD_SIZE)
     file->stat_info->file_name[NAME_FIELD_SIZE] = 0;
 
-  blk = pax_start_header (file->stat_info);
-  finish_header (file->stat_info, blk, block_ordinal);
+  struct block_ptr bp;
+  bp.block = pax_start_header (file->stat_info);
+  finish_header (file->stat_info, bp.block, block_ordinal);
   free (file->stat_info->file_name);
   file->stat_info->file_name = save_file_name;
 
-  blk = find_next_block ();
-  q = blk->buffer;
-  p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
-  COPY_STRING (blk, q, p);
-  COPY_STRING (blk, q, "\n");
-  for (i = 0; i < file->stat_info->sparse_map_avail; i++)
+  bp.block = find_next_block ();
+  bp.ptr = bp.block->buffer;
+  bp = dump_str_nl (bp, umaxtostr (file->stat_info->sparse_map_avail, nbuf));
+  for (idx_t i = 0; i < file->stat_info->sparse_map_avail; i++)
     {
-      p = umaxtostr (map[i].offset, nbuf);
-      COPY_STRING (blk, q, p);
-      COPY_STRING (blk, q, "\n");
-      p = umaxtostr (map[i].numbytes, nbuf);
-      COPY_STRING (blk, q, p);
-      COPY_STRING (blk, q, "\n");
+      bp = dump_str_nl (bp, umaxtostr (map[i].offset, nbuf));
+      bp = dump_str_nl (bp, umaxtostr (map[i].numbytes, nbuf));
     }
-  memset (q, 0, BLOCKSIZE - (q - blk->buffer));
-  set_next_block_after (blk);
+  memset (bp.ptr, 0, BLOCKSIZE - (bp.ptr - bp.block->buffer));
+  set_next_block_after (bp.block);
   return true;
 }