diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-01 13:23:36 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-01 13:23:36 +0200 |
commit | 8aea2d1dc437b5b497170ef9c1b6854aee8f5dcf (patch) | |
tree | 0999ed4664c74cf90896d8b11f7f4a9dc06e8d48 /lib/tar/read_sparse_map_old.c | |
parent | f0d18050d832498c8e230c04084675455fef391f (diff) |
cleanup: split tar code up, remove some duplications
This commit attempts to split some of the monolitic tar parsing code up
into multiple functions in seperate files. Also, some code duplication
(like reading a record into memory which was implemented twice) is
removed.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/tar/read_sparse_map_old.c')
-rw-r--r-- | lib/tar/read_sparse_map_old.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/tar/read_sparse_map_old.c b/lib/tar/read_sparse_map_old.c new file mode 100644 index 0000000..c0b2d0d --- /dev/null +++ b/lib/tar/read_sparse_map_old.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "internal.h" + +sparse_map_t *read_gnu_old_sparse(int fd, tar_header_t *hdr) +{ + sparse_map_t *list = NULL, *end = NULL, *node; + gnu_sparse_t sph; + uint64_t off, sz; + ssize_t ret; + int i; + + for (i = 0; i < 4; ++i) { + if (!isdigit(hdr->tail.gnu.sparse[i].offset[0])) + break; + if (!isdigit(hdr->tail.gnu.sparse[i].numbytes[0])) + break; + + if (read_octal(hdr->tail.gnu.sparse[i].offset, + sizeof(hdr->tail.gnu.sparse[i].offset), &off)) + goto fail; + if (read_octal(hdr->tail.gnu.sparse[i].numbytes, + sizeof(hdr->tail.gnu.sparse[i].numbytes), &sz)) + goto fail; + + node = calloc(1, sizeof(*node)); + if (node == NULL) + goto fail_errno; + + node->offset = off; + node->count = sz; + + if (list == NULL) { + list = end = node; + } else { + end->next = node; + end = node; + } + } + + if (hdr->tail.gnu.isextended == 0) + return list; + + do { + ret = read_retry(fd, &sph, sizeof(sph)); + if (ret < 0) + goto fail_errno; + if ((size_t)ret < sizeof(sph)) + goto fail_eof; + + for (i = 0; i < 21; ++i) { + if (!isdigit(sph.sparse[i].offset[0])) + break; + if (!isdigit(sph.sparse[i].numbytes[0])) + break; + + if (read_octal(sph.sparse[i].offset, + sizeof(sph.sparse[i].offset), &off)) + goto fail; + if (read_octal(sph.sparse[i].numbytes, + sizeof(sph.sparse[i].numbytes), &sz)) + goto fail; + + node = calloc(1, sizeof(*node)); + if (node == NULL) + goto fail_errno; + + node->offset = off; + node->count = sz; + + if (list == NULL) { + list = end = node; + } else { + end->next = node; + end = node; + } + } + } while (sph.isextended != 0); + + return list; +fail_eof: + fputs("parsing GNU sparse header: unexpected end of file", stderr); + goto fail; +fail_errno: + perror("parsing GNU sparse header"); + goto fail; +fail: + free_sparse_list(list); + return NULL; +} |