summaryrefslogtreecommitdiff
path: root/lib/tar/read_sparse_map.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tar/read_sparse_map.c')
-rw-r--r--lib/tar/read_sparse_map.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/tar/read_sparse_map.c b/lib/tar/read_sparse_map.c
new file mode 100644
index 0000000..77876f5
--- /dev/null
+++ b/lib/tar/read_sparse_map.c
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#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;
+}