summaryrefslogtreecommitdiff
path: root/archival/chksum_and_xwrite_tar_header.c
blob: f2d46b9ef010abaf0c2e2fda8b9a9ab0f4cd94a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Copyright (C) 2021 Denys Vlasenko <vda.linux@googlemail.com>
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */
//kbuild:lib-$(CONFIG_FEATURE_TAR_CREATE) += chksum_and_xwrite_tar_header.o
//kbuild:lib-$(CONFIG_SMEMCAP) += chksum_and_xwrite_tar_header.o

#include "libbb.h"
#include "bb_archive.h"

void FAST_FUNC chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp)
{
	/* POSIX says that checksum is done on unsigned bytes
	 * (Sun and HP-UX gets it wrong... more details in
	 * GNU tar source) */
	const unsigned char *cp;
	unsigned int chksum, size;

	strcpy(hp->magic, "ustar  ");

	/* Calculate and store the checksum (the sum of all of the bytes of
	 * the header).  The checksum field must be filled with blanks for the
	 * calculation.  The checksum field is formatted differently from the
	 * other fields: it has 6 digits, a NUL, then a space -- rather than
	 * digits, followed by a NUL like the other fields... */
	memset(hp->chksum, ' ', sizeof(hp->chksum));
	cp = (const unsigned char *) hp;
	chksum = 0;
	size = sizeof(*hp);
	do { chksum += *cp++; } while (--size);
	sprintf(hp->chksum, "%06o", chksum);

	xwrite(fd, hp, sizeof(*hp));
}