summaryrefslogtreecommitdiff
path: root/lib/tar
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tar')
-rw-r--r--lib/tar/Makemodule.am6
-rw-r--r--lib/tar/base64.c59
-rw-r--r--lib/tar/checksum.c4
-rw-r--r--lib/tar/cleanup.c2
-rw-r--r--lib/tar/internal.h36
-rw-r--r--lib/tar/number.c24
-rw-r--r--lib/tar/padd_file.c3
-rw-r--r--lib/tar/pax_header.c161
-rw-r--r--lib/tar/read_header.c2
-rw-r--r--lib/tar/read_sparse_map.c54
-rw-r--r--lib/tar/read_sparse_map_new.c5
-rw-r--r--lib/tar/read_sparse_map_old.c4
-rw-r--r--lib/tar/record_to_memory.c3
-rw-r--r--lib/tar/urldecode.c38
-rw-r--r--lib/tar/write_header.c1
15 files changed, 183 insertions, 219 deletions
diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am
index 414aca1..7f93d13 100644
--- a/lib/tar/Makemodule.am
+++ b/lib/tar/Makemodule.am
@@ -1,10 +1,10 @@
libtar_a_SOURCES = lib/tar/read_header.c lib/tar/write_header.c
libtar_a_SOURCES += lib/tar/number.c lib/tar/checksum.c lib/tar/cleanup.c
-libtar_a_SOURCES += lib/tar/read_sparse_map.c lib/tar/read_sparse_map_old.c
-libtar_a_SOURCES += lib/tar/base64.c lib/tar/urldecode.c lib/tar/internal.h
+libtar_a_SOURCES += lib/tar/read_sparse_map_old.c
+libtar_a_SOURCES += lib/tar/internal.h
libtar_a_SOURCES += lib/tar/padd_file.c lib/tar/record_to_memory.c
libtar_a_SOURCES += lib/tar/pax_header.c lib/tar/read_sparse_map_new.c
-libtar_a_SOURCES += include/tar.h
+libtar_a_SOURCES += include/tar/tar.h include/tar/format.h
libtar_a_CFLAGS = $(AM_CFLAGS)
libtar_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/lib/tar/base64.c b/lib/tar/base64.c
deleted file mode 100644
index f88444a..0000000
--- a/lib/tar/base64.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * base64.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "internal.h"
-
-static sqfs_u8 convert(char in)
-{
- if (isupper(in))
- return in - 'A';
- if (islower(in))
- return in - 'a' + 26;
- if (isdigit(in))
- return in - '0' + 52;
- if (in == '+')
- return 62;
- if (in == '/' || in == '-')
- return 63;
- return 0;
-}
-
-size_t base64_decode(sqfs_u8 *out, const char *in, size_t len)
-{
- sqfs_u8 *start = out;
-
- while (len > 0) {
- unsigned int diff = 0, value = 0;
-
- while (diff < 4 && len > 0) {
- if (*in == '=' || *in == '_' || *in == '\0') {
- len = 0;
- } else {
- value = (value << 6) | convert(*(in++));
- --len;
- ++diff;
- }
- }
-
- if (diff < 2)
- break;
-
- value <<= 6 * (4 - diff);
-
- switch (diff) {
- case 4: out[2] = value & 0xff; /* fall-through */
- case 3: out[1] = (value >> 8) & 0xff; /* fall-through */
- default: out[0] = (value >> 16) & 0xff;
- }
-
- out += (diff * 3) / 4;
- }
-
- *out = '\0';
- return out - start;
-}
diff --git a/lib/tar/checksum.c b/lib/tar/checksum.c
index 144ba43..6541373 100644
--- a/lib/tar/checksum.c
+++ b/lib/tar/checksum.c
@@ -6,7 +6,9 @@
*/
#include "config.h"
-#include "internal.h"
+#include "tar/format.h"
+
+#include <stdio.h>
static unsigned int get_checksum(const tar_header_t *hdr)
{
diff --git a/lib/tar/cleanup.c b/lib/tar/cleanup.c
index 2f814bf..9f33336 100644
--- a/lib/tar/cleanup.c
+++ b/lib/tar/cleanup.c
@@ -7,6 +7,8 @@
#include "config.h"
#include "internal.h"
+#include <stdlib.h>
+#include <string.h>
void free_sparse_list(sparse_map_t *sparse)
{
diff --git a/lib/tar/internal.h b/lib/tar/internal.h
index b7c4c34..cfbb938 100644
--- a/lib/tar/internal.h
+++ b/lib/tar/internal.h
@@ -9,13 +9,8 @@
#include "config.h"
-#include "tar.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <ctype.h>
-#include <stdio.h>
+#include "tar/tar.h"
+#include "tar/format.h"
enum {
PAX_SIZE = 0x001,
@@ -38,37 +33,10 @@ enum {
ETV_POSIX,
};
-
-#define TAR_MAX_SYMLINK_LEN (65536)
-#define TAR_MAX_PATH_LEN (65536)
-#define TAR_MAX_PAX_LEN (65536)
-#define TAR_MAX_SPARSE_ENT (65536)
-
-
-int read_octal(const char *str, int digits, sqfs_u64 *out);
-
-int read_binary(const char *str, int digits, sqfs_u64 *out);
-
-int read_number(const char *str, int digits, sqfs_u64 *out);
-
-int pax_read_decimal(const char *str, sqfs_u64 *out);
-
-void update_checksum(tar_header_t *hdr);
-
-bool is_checksum_valid(const tar_header_t *hdr);
-
-sparse_map_t *read_sparse_map(const char *line);
-
sparse_map_t *read_gnu_old_sparse(istream_t *fp, tar_header_t *hdr);
sparse_map_t *read_gnu_new_sparse(istream_t *fp, tar_header_decoded_t *out);
-void free_sparse_list(sparse_map_t *sparse);
-
-size_t base64_decode(sqfs_u8 *out, const char *in, size_t len);
-
-void urldecode(char *str);
-
char *record_to_memory(istream_t *fp, size_t size);
int read_pax_header(istream_t *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
diff --git a/lib/tar/number.c b/lib/tar/number.c
index 50cb658..2f179df 100644
--- a/lib/tar/number.c
+++ b/lib/tar/number.c
@@ -6,7 +6,10 @@
*/
#include "config.h"
-#include "internal.h"
+#include "tar/format.h"
+
+#include <ctype.h>
+#include <stdio.h>
int read_octal(const char *str, int digits, sqfs_u64 *out)
{
@@ -31,7 +34,7 @@ int read_octal(const char *str, int digits, sqfs_u64 *out)
return 0;
}
-int read_binary(const char *str, int digits, sqfs_u64 *out)
+static int read_binary(const char *str, int digits, sqfs_u64 *out)
{
sqfs_u64 x, ov, result = 0;
bool first = true;
@@ -74,20 +77,3 @@ int read_number(const char *str, int digits, sqfs_u64 *out)
return read_octal(str, digits, out);
}
-
-int pax_read_decimal(const char *str, sqfs_u64 *out)
-{
- sqfs_u64 result = 0;
-
- while (*str >= '0' && *str <= '9') {
- if (result > 0xFFFFFFFFFFFFFFFFUL / 10) {
- fputs("numeric overflow parsing pax header\n", stderr);
- return -1;
- }
-
- result = (result * 10) + (*(str++) - '0');
- }
-
- *out = result;
- return 0;
-}
diff --git a/lib/tar/padd_file.c b/lib/tar/padd_file.c
index 1173096..6a1ca05 100644
--- a/lib/tar/padd_file.c
+++ b/lib/tar/padd_file.c
@@ -5,7 +5,8 @@
* Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
*/
#include "config.h"
-#include "tar.h"
+#include "tar/tar.h"
+#include "tar/format.h"
#include <stdlib.h>
#include <stdio.h>
diff --git a/lib/tar/pax_header.c b/lib/tar/pax_header.c
index d24def0..8a1b077 100644
--- a/lib/tar/pax_header.c
+++ b/lib/tar/pax_header.c
@@ -7,6 +7,105 @@
#include "config.h"
#include "internal.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+static sqfs_u8 base64_convert(char in)
+{
+ if (isupper(in))
+ return in - 'A';
+ if (islower(in))
+ return in - 'a' + 26;
+ if (isdigit(in))
+ return in - '0' + 52;
+ if (in == '+')
+ return 62;
+ if (in == '/' || in == '-')
+ return 63;
+ return 0;
+}
+
+static int xdigit(int x)
+{
+ if (isupper(x))
+ return x - 'A' + 0x0A;
+ if (islower(x))
+ return x - 'a' + 0x0A;
+ return x - '0';
+}
+
+static size_t base64_decode(sqfs_u8 *out, const char *in, size_t len)
+{
+ sqfs_u8 *start = out;
+
+ while (len > 0) {
+ unsigned int diff = 0, value = 0;
+
+ while (diff < 4 && len > 0) {
+ if (*in == '=' || *in == '_' || *in == '\0') {
+ len = 0;
+ } else {
+ value = (value << 6) | base64_convert(*(in++));
+ --len;
+ ++diff;
+ }
+ }
+
+ if (diff < 2)
+ break;
+
+ value <<= 6 * (4 - diff);
+
+ switch (diff) {
+ case 4: out[2] = value & 0xff; /* fall-through */
+ case 3: out[1] = (value >> 8) & 0xff; /* fall-through */
+ default: out[0] = (value >> 16) & 0xff;
+ }
+
+ out += (diff * 3) / 4;
+ }
+
+ *out = '\0';
+ return out - start;
+}
+
+static int pax_read_decimal(const char *str, sqfs_u64 *out)
+{
+ sqfs_u64 result = 0;
+
+ while (*str >= '0' && *str <= '9') {
+ if (result > 0xFFFFFFFFFFFFFFFFUL / 10) {
+ fputs("numeric overflow parsing pax header\n", stderr);
+ return -1;
+ }
+
+ result = (result * 10) + (*(str++) - '0');
+ }
+
+ *out = result;
+ return 0;
+}
+
+static void urldecode(char *str)
+{
+ unsigned char *out = (unsigned char *)str;
+ char *in = str;
+ int x;
+
+ while (*in != '\0') {
+ x = *(in++);
+
+ if (x == '%' && isxdigit(in[0]) && isxdigit(in[1])) {
+ x = xdigit(*(in++)) << 4;
+ x |= xdigit(*(in++));
+ }
+
+ *(out++) = x;
+ }
+
+ *out = '\0';
+}
static int pax_uid(tar_header_decoded_t *out, sqfs_u64 id)
{
@@ -52,6 +151,55 @@ static int pax_slink(tar_header_decoded_t *out, char *path)
return 0;
}
+static int pax_sparse_map(tar_header_decoded_t *out, const char *line)
+{
+ sparse_map_t *last = NULL, *list = NULL, *ent = NULL;
+
+ free_sparse_list(out->sparse);
+ out->sparse = NULL;
+
+ do {
+ ent = calloc(1, sizeof(*ent));
+ if (ent == NULL)
+ goto fail_errno;
+
+ if (pax_read_decimal(line, &ent->offset))
+ goto fail_format;
+
+ while (isdigit(*line))
+ ++line;
+
+ if (*(line++) != ',')
+ goto fail_format;
+
+ if (pax_read_decimal(line, &ent->count))
+ goto fail_format;
+
+ while (isdigit(*line))
+ ++line;
+
+ if (last == NULL) {
+ list = last = ent;
+ } else {
+ last->next = ent;
+ last = ent;
+ }
+ } while (*(line++) == ',');
+
+ out->sparse = list;
+ return 0;
+fail_errno:
+ perror("parsing GNU pax sparse file record");
+ goto fail;
+fail_format:
+ fputs("malformed GNU pax sparse file record\n", stderr);
+ goto fail;
+fail:
+ free_sparse_list(list);
+ free(ent);
+ return -1;
+}
+
static int pax_xattr_schily(tar_header_decoded_t *out,
tar_xattr_t *xattr)
{
@@ -76,6 +224,7 @@ enum {
PAX_TYPE_SINT = 0,
PAX_TYPE_UINT,
PAX_TYPE_STRING,
+ PAX_TYPE_CONST_STRING,
PAX_TYPE_PREFIXED_XATTR,
PAX_TYPE_IGNORE,
};
@@ -88,6 +237,7 @@ static const struct pax_handler_t {
int (*sint)(tar_header_decoded_t *out, sqfs_s64 sval);
int (*uint)(tar_header_decoded_t *out, sqfs_u64 uval);
int (*str)(tar_header_decoded_t *out, char *str);
+ int (*cstr)(tar_header_decoded_t *out, const char *str);
int (*xattr)(tar_header_decoded_t *out, tar_xattr_t *xattr);
} cb;
} pax_fields[] = {
@@ -110,6 +260,8 @@ static const struct pax_handler_t {
{ .xattr = pax_xattr_schily } },
{ "LIBARCHIVE.xattr", 0, PAX_TYPE_PREFIXED_XATTR,
{ .xattr = pax_xattr_libarchive } },
+ { "GNU.sparse.map", 0, PAX_TYPE_CONST_STRING,
+ { .cstr = pax_sparse_map } },
};
static const struct pax_handler_t *find_handler(const char *key)
@@ -183,6 +335,8 @@ static int apply_handler(tar_header_decoded_t *out,
if (pax_read_decimal(value, &uval))
return -1;
return field->cb.uint(out, uval);
+ case PAX_TYPE_CONST_STRING:
+ return field->cb.cstr(out, value);
case PAX_TYPE_STRING:
copy = strdup(value);
if (copy == NULL) {
@@ -264,13 +418,6 @@ int read_pax_header(istream_t *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
}
*set_by_pax |= field->flag;
- } else if (!strcmp(key, "GNU.sparse.map")) {
- free_sparse_list(out->sparse);
- sparse_last = NULL;
-
- out->sparse = read_sparse_map(value);
- if (out->sparse == NULL)
- goto fail;
} else if (!strcmp(key, "GNU.sparse.offset")) {
if (pax_read_decimal(value, &offset))
goto fail;
diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c
index d1790de..ea4873b 100644
--- a/lib/tar/read_header.c
+++ b/lib/tar/read_header.c
@@ -7,6 +7,8 @@
#include "config.h"
#include "internal.h"
+#include <string.h>
+#include <stdlib.h>
static bool is_zero_block(const tar_header_t *hdr)
{
diff --git a/lib/tar/read_sparse_map.c b/lib/tar/read_sparse_map.c
deleted file mode 100644
index 0779b96..0000000
--- a/lib/tar/read_sparse_map.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * read_sparse_map.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "internal.h"
-
-sparse_map_t *read_sparse_map(const char *line)
-{
- sparse_map_t *last = NULL, *list = NULL, *ent = NULL;
-
- do {
- ent = calloc(1, sizeof(*ent));
- if (ent == NULL)
- goto fail_errno;
-
- if (pax_read_decimal(line, &ent->offset))
- goto fail_format;
-
- while (isdigit(*line))
- ++line;
-
- if (*(line++) != ',')
- goto fail_format;
-
- if (pax_read_decimal(line, &ent->count))
- goto fail_format;
-
- while (isdigit(*line))
- ++line;
-
- if (last == NULL) {
- list = last = ent;
- } else {
- last->next = ent;
- last = ent;
- }
- } while (*(line++) == ',');
-
- return list;
-fail_errno:
- perror("parsing GNU pax sparse file record");
- goto fail;
-fail_format:
- fputs("malformed GNU pax sparse file record\n", stderr);
- goto fail;
-fail:
- free_sparse_list(list);
- free(ent);
- return NULL;
-}
diff --git a/lib/tar/read_sparse_map_new.c b/lib/tar/read_sparse_map_new.c
index d9f6c6e..de1b6a4 100644
--- a/lib/tar/read_sparse_map_new.c
+++ b/lib/tar/read_sparse_map_new.c
@@ -5,9 +5,12 @@
* Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
*/
#include "config.h"
-
#include "internal.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
static int decode(const char *str, size_t len, size_t *out)
{
size_t count = 0;
diff --git a/lib/tar/read_sparse_map_old.c b/lib/tar/read_sparse_map_old.c
index cd7177d..3dd3300 100644
--- a/lib/tar/read_sparse_map_old.c
+++ b/lib/tar/read_sparse_map_old.c
@@ -5,9 +5,11 @@
* Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
*/
#include "config.h"
-
#include "internal.h"
+#include <ctype.h>
+#include <stdlib.h>
+
sparse_map_t *read_gnu_old_sparse(istream_t *fp, tar_header_t *hdr)
{
sparse_map_t *list = NULL, *end = NULL, *node;
diff --git a/lib/tar/record_to_memory.c b/lib/tar/record_to_memory.c
index 822608c..ba422de 100644
--- a/lib/tar/record_to_memory.c
+++ b/lib/tar/record_to_memory.c
@@ -6,8 +6,9 @@
*/
#include "config.h"
-#include "tar.h"
+#include "tar/tar.h"
#include "internal.h"
+#include <stdlib.h>
char *record_to_memory(istream_t *fp, size_t size)
{
diff --git a/lib/tar/urldecode.c b/lib/tar/urldecode.c
deleted file mode 100644
index 6fac4d3..0000000
--- a/lib/tar/urldecode.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * urldecode.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "internal.h"
-
-static int xdigit(int x)
-{
- if (isupper(x))
- return x - 'A' + 0x0A;
- if (islower(x))
- return x - 'a' + 0x0A;
- return x - '0';
-}
-
-void urldecode(char *str)
-{
- unsigned char *out = (unsigned char *)str;
- char *in = str;
- int x;
-
- while (*in != '\0') {
- x = *(in++);
-
- if (x == '%' && isxdigit(in[0]) && isxdigit(in[1])) {
- x = xdigit(*(in++)) << 4;
- x |= xdigit(*(in++));
- }
-
- *(out++) = x;
- }
-
- *out = '\0';
-}
diff --git a/lib/tar/write_header.c b/lib/tar/write_header.c
index a337b74..b0711b3 100644
--- a/lib/tar/write_header.c
+++ b/lib/tar/write_header.c
@@ -7,6 +7,7 @@
#include "config.h"
#include "internal.h"
+#include <string.h>
static void write_binary(char *dst, sqfs_u64 value, int digits)
{