aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/lib.c23
-rw-r--r--lib/lib.h2
-rw-r--r--toys/posix/file.c9
-rw-r--r--toys/posix/tar.c26
4 files changed, 33 insertions, 27 deletions
diff --git a/lib/lib.c b/lib/lib.c
index b5825fd2..ffb24f65 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1416,3 +1416,26 @@ void loggit(int priority, char *format, ...)
va_end(va);
closelog();
}
+
+// Calculate tar packet checksum, with cksum field treated as 8 spaces
+unsigned tar_cksum(void *data)
+{
+ unsigned i, cksum = 8*' ';
+
+ for (i = 0; i<500; i += (i==147) ? 9 : 1) cksum += ((char *)data)[i];
+
+ return cksum;
+}
+
+// is this a valid tar header?
+int is_tar_header(void *pkt)
+{
+ char *p = pkt;
+ int i = 0;
+
+ if (p[257] && memcmp("ustar", p+257, 5)) return 0;
+ if (p[148] != '0') return 0;
+ sscanf(p+148, "%8o", &i);
+
+ return i && tar_cksum(pkt) == i;
+}
diff --git a/lib/lib.h b/lib/lib.h
index 5ce29380..080c533f 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -265,6 +265,8 @@ long long millitime(void);
char *format_iso_time(char *buf, size_t len, struct timespec *ts);
void reset_env(struct passwd *p, int clear);
void loggit(int priority, char *format, ...);
+unsigned tar_cksum(void *data);
+int is_tar_header(void *pkt);
#define HR_SPACE 1 // Space between number and units
#define HR_B 2 // Use "B" for single byte units
diff --git a/toys/posix/file.c b/toys/posix/file.c
index 567c68d2..6b8c6779 100644
--- a/toys/posix/file.c
+++ b/toys/posix/file.c
@@ -269,9 +269,10 @@ static void do_regular_file(int fd, char *name)
} else if (len>33 && (magic=peek(&s,2), magic==0143561 || magic==070707)) {
if (magic == 0143561) printf("byte-swapped ");
xprintf("cpio archive\n");
- // tar archive (ustar/pax or gnu)
- } else if (len>500 && !strncmp(s+257, "ustar", 5))
- xprintf("POSIX tar archive%s\n", strncmp(s+262," ",2)?"":" (GNU)");
+ // tar archive (old, ustar/pax, or gnu)
+ } else if (len>500 && is_tar_header(s))
+ xprintf("%s tar archive%s\n", s[257] ? "POSIX" : "old",
+ strncmp(s+262," ",2)?"":" (GNU)");
// zip/jar/apk archive, ODF/OOXML document, or such
else if (len>5 && strstart(&s, "PK\03\04")) {
int ver = toybuf[4];
@@ -281,6 +282,8 @@ static void do_regular_file(int fd, char *name)
xputc('\n');
} else if (len>4 && strstart(&s, "BZh") && isdigit(*s))
xprintf("bzip2 compressed data, block size = %c00k\n", *s);
+ else if (len > 31 && peek_be(s, 7) == 0xfd377a585a0000)
+ xprintf("xz compressed data");
else if (len>10 && strstart(&s, "\x1f\x8b")) xputs("gzip compressed data");
else if (len>32 && !memcmp(s+1, "\xfa\xed\xfe", 3)) {
int bit = s[0]=='\xce'?32:64;
diff --git a/toys/posix/tar.c b/toys/posix/tar.c
index 17d382d5..2819a355 100644
--- a/toys/posix/tar.c
+++ b/toys/posix/tar.c
@@ -83,28 +83,6 @@ struct tar_hdr {
prefix[155], padd[12];
};
-// Calculate packet checksum, with cksum field treated as 8 spaces
-unsigned tar_cksum(void *data)
-{
- unsigned i, cksum = 8*' ';
-
- for (i = 0; i<500; i += (i==147) ? 9 : 1) cksum += ((char *)data)[i];
-
- return cksum;
-}
-
-static int is_tar(void *pkt)
-{
- char *p = pkt;
- int i = 0;
-
- if (p[257] && memcmp("ustar", p+257, 5)) return 0;
- if (p[148] != '0') return 0;
- sscanf(p+148, "%8o", &i);
-
- return i && tar_cksum(pkt) == i;
-}
-
// convert from int to octal (or base-256)
static void itoo(char *str, int len, unsigned long long val)
{
@@ -594,7 +572,7 @@ static void unpack_tar(char *first)
tar.padd[0] = and = 0;
// Is this a valid TAR header?
- if (!is_tar(&tar)) error_exit("bad header");
+ if (!is_tar_header(&tar)) error_exit("bad header");
TT.hdr.size = OTOI(tar.size);
// If this header isn't writing something to the filesystem
@@ -856,7 +834,7 @@ void tar_main(void)
// autodetect compression type when not specified
if (!(FLAG(j)||FLAG(z)||FLAG(J))) {
len = xread(TT.fd, hdr = toybuf+sizeof(toybuf)-512, 512);
- if (len!=512 || !is_tar(hdr)) {
+ if (len!=512 || !is_tar_header(hdr)) {
// detect gzip and bzip signatures
if (SWAP_BE16(*(short *)hdr)==0x1f8b) toys.optflags |= FLAG_z;
else if (!memcmp(hdr, "BZh", 3)) toys.optflags |= FLAG_j;