From 62d5a1e56f4022002c5c55e02d7d29e1e68bc236 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Aug 2021 17:58:49 +0200 Subject: [PATCH] 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 --- archival/chksum_and_xwrite_tar_header.c | 35 +++++++++++++++++++++++++ archival/tar.c | 31 ++-------------------- include/bb_archive.h | 1 + procps/smemcap.c | 16 +---------- 4 files changed, 39 insertions(+), 44 deletions(-) create mode 100644 archival/chksum_and_xwrite_tar_header.c diff --git a/archival/chksum_and_xwrite_tar_header.c b/archival/chksum_and_xwrite_tar_header.c new file mode 100644 index 000000000..25934f898 --- /dev/null +++ b/archival/chksum_and_xwrite_tar_header.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Denys Vlasenko + * + * 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)); +} diff --git a/archival/tar.c b/archival/tar.c index 94fb61a29..9de37592e 100644 --- a/archival/tar.c +++ b/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', 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) { diff --git a/include/bb_archive.h b/include/bb_archive.h index 9b1db5b3e..dc5e55f0a 100644 --- a/include/bb_archive.h +++ b/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[]; diff --git a/procps/smemcap.c b/procps/smemcap.c index 2f8ab192e..2f1897dae 100644 --- a/procps/smemcap.c +++ b/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)