diff options
Diffstat (limited to 'lib/tar/read_sparse_map.c')
-rw-r--r-- | lib/tar/read_sparse_map.c | 47 |
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; +} |