Browse Source

tar,smemcap: commonalyze checksumming code for tar header

function                                             old     new   delta
chksum_and_xwrite_tar_header                           -      99     +99
writeheader                                          280     199     -81
chksum_and_xwrite                                    102       -    -102
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 0/1 up/down: 99/-183)           Total: -84 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Denys Vlasenko 2 years ago
parent
commit
62d5a1e56f
4 changed files with 39 additions and 44 deletions
  1. 35 0
      archival/chksum_and_xwrite_tar_header.c
  2. 2 29
      archival/tar.c
  3. 1 0
      include/bb_archive.h
  4. 1 15
      procps/smemcap.c

+ 35 - 0
archival/chksum_and_xwrite_tar_header.c

@@ -0,0 +1,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;
+	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));
+}

+ 2 - 29
archival/tar.c

@@ -254,32 +254,6 @@ static void putOctal(char *cp, int len, off_t value)
 }
 #define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b))
 
-static void chksum_and_xwrite(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;
-	int chksum, size;
-
-	strcpy(hp->magic, "ustar  ");
-
-	/* Calculate and store the checksum (i.e., 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 null, then a space -- rather than
-	 * digits, followed by a null 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);
-	putOctal(hp->chksum, sizeof(hp->chksum)-1, chksum);
-
-	/* Now write the header out to disk */
-	xwrite(fd, hp, sizeof(*hp));
-}
-
 # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 static void writeLongname(int fd, int type, const char *name, int dir)
 {
@@ -310,7 +284,7 @@ static void writeLongname(int fd, int type, const char *name, int dir)
 	/* + dir: account for possible '/' */
 
 	PUT_OCTAL(header.size, size);
-	chksum_and_xwrite(fd, &header);
+	chksum_and_xwrite_tar_header(fd, &header);
 
 	/* Write filename[/] and pad the block. */
 	/* dir=0: writes 'name<NUL>', pads */
@@ -441,8 +415,7 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
 				header_name, S_ISDIR(statbuf->st_mode));
 # endif
 
-	/* Now write the header out to disk */
-	chksum_and_xwrite(tbInfo->tarFd, &header);
+	chksum_and_xwrite_tar_header(tbInfo->tarFd, &header);
 
 	/* Now do the verbose thing (or not) */
 	if (tbInfo->verboseFlag) {

+ 1 - 0
include/bb_archive.h

@@ -167,6 +167,7 @@ typedef struct tar_header_t {     /* byte offset */
 struct BUG_tar_header {
 	char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1];
 };
+void chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp) FAST_FUNC;
 
 
 extern const char cpio_TRAILER[];

+ 1 - 15
procps/smemcap.c

@@ -29,7 +29,6 @@ struct fileblock {
 static void writeheader(const char *path, struct stat *sb, int type)
 {
 	struct tar_header_t header;
-	int i, sum;
 
 	memset(&header, 0, TAR_BLOCK_SIZE);
 	strcpy(header.name, path);
@@ -40,20 +39,7 @@ static void writeheader(const char *path, struct stat *sb, int type)
 	sprintf(header.size, "%o", (unsigned)sb->st_size);
 	sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
 	header.typeflag = type;
-	strcpy(header.magic, "ustar  "); /* like GNU tar */
-
-	/* 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... */
-	header.chksum[7] = ' ';
-	sum = ' ' * 7;
-	for (i = 0; i < TAR_BLOCK_SIZE; i++)
-		sum += ((unsigned char*)&header)[i];
-	sprintf(header.chksum, "%06o", sum);
-
-	xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
+	chksum_and_xwrite_tar_header(STDOUT_FILENO, &header);
 }
 
 static void archivefile(const char *path)