summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--archival/chksum_and_xwrite_tar_header.c35
-rw-r--r--archival/tar.c31
-rw-r--r--include/bb_archive.h1
-rw-r--r--procps/smemcap.c16
4 files changed, 39 insertions, 44 deletions
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 <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));
+}
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<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) {
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)