Prefer function to COPY_STRING macro

* 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.
This commit is contained in:
Paul Eggert
2024-08-18 09:44:25 -07:00
parent f1e4947992
commit f25dd56e83

View 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 doesnt 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;
}