From: Michael Schroeder Date: Thu, 28 Nov 2024 12:08:39 +0000 (+0100) Subject: Move tar handling from repo_arch into its own file X-Git-Tag: 0.7.32~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=224cab32cb08bfbc430a5775ed840b71fcb4e496;p=thirdparty%2Flibsolv.git Move tar handling from repo_arch into its own file We'll need it for apk packages. --- diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 589fa946..2cf62423 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -144,6 +144,11 @@ IF (ENABLE_ZCHUNK_COMPRESSION) solv_zchunk.c) ENDIF (ENABLE_ZCHUNK_COMPRESSION) +IF (ENABLE_ARCHREPO) + SET (libsolvext_SRCS ${libsolvext_SRCS} + tarhead.c) +ENDIF (ENABLE_ARCHREPO) + IF (NOT MSVC) SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ENDIF (NOT MSVC) diff --git a/ext/repo_arch.c b/ext/repo_arch.c index 698d5063..4221b058 100644 --- a/ext/repo_arch.c +++ b/ext/repo_arch.c @@ -20,273 +20,9 @@ #include "util.h" #include "chksum.h" #include "solv_xfopen.h" +#include "tarhead.h" #include "repo_arch.h" -static long long parsenum(unsigned char *p, int cnt) -{ - long long x = 0; - if (!cnt) - return -1; - if (*p & 0x80) - { - /* binary format */ - x = *p & 0x40 ? (-1 << 8 | *p) : (*p ^ 0x80); - while (--cnt > 0) - x = (x << 8) | *p++; - return x; - } - while (cnt > 0 && (*p == ' ' || *p == '\t')) - cnt--, p++; - if (*p == '-') - return -1; - for (; cnt > 0 && *p >= '0' && *p < '8'; cnt--, p++) - x = (x << 3) | (*p - '0'); - return x; -} - -static int readblock(FILE *fp, unsigned char *blk) -{ - int r, l = 0; - while (l < 512) - { - r = fread(blk + l, 1, 512 - l, fp); - if (r <= 0) - return -1; - l += r; - } - return 0; -} - -struct tarhead { - FILE *fp; - unsigned char blk[512]; - int type; - long long length; - char *path; - int eof; - int ispax; - int off; - int end; -}; - -static char *getsentry(struct tarhead *th, char *s, int size) -{ - char *os = s; - if (th->eof || size <= 1) - return 0; - size--; /* terminating 0 */ - for (;;) - { - int i; - for (i = th->off; i < th->end; i++) - { - *s++ = th->blk[i]; - size--; - if (!size || th->blk[i] == '\n') - { - th->off = i + 1; - *s = 0; - return os; - } - } - th->off = i; - if (!th->path) - { - /* fake entry */ - th->end = fread(th->blk, 1, 512, th->fp); - if (th->end <= 0) - { - th->eof = 1; - return 0; - } - th->off = 0; - continue; - } - if (th->length <= 0) - return 0; - if (readblock(th->fp, th->blk)) - { - th->eof = 1; - return 0; - } - th->off = 0; - th->end = th->length > 512 ? 512 : th->length; - th->length -= th->end; - } -} - -static void skipentry(struct tarhead *th) -{ - for (; th->length > 0; th->length -= 512) - { - if (readblock(th->fp, th->blk)) - { - th->eof = 1; - th->length = 0; - return; - } - } - th->length = 0; - th->off = th->end = 0; -} - -static void inittarhead(struct tarhead *th, FILE *fp) -{ - memset(th, 0, sizeof(*th)); - th->fp = fp; -} - -static void freetarhead(struct tarhead *th) -{ - solv_free(th->path); -} - -static int gettarhead(struct tarhead *th) -{ - int l, type; - long long length; - - th->path = solv_free(th->path); - th->ispax = 0; - th->type = 0; - th->length = 0; - th->off = 0; - th->end = 0; - if (th->eof) - return 0; - for (;;) - { - int r = readblock(th->fp, th->blk); - if (r) - { - if (feof(th->fp)) - { - th->eof = 1; - return 0; - } - return -1; - } - if (th->blk[0] == 0) - { - th->eof = 1; - return 0; - } - length = parsenum(th->blk + 124, 12); - if (length < 0) - return -1; - type = 0; - switch (th->blk[156]) - { - case 'S': case '0': - type = 1; /* file */ - break; - case '1': - /* hard link, special length magic... */ - if (!th->ispax) - length = 0; - break; - case '5': - type = 2; /* dir */ - break; - case '2': case '3': case '4': case '6': - length = 0; - break; - case 'X': case 'x': case 'L': - { - char *data, *pp; - if (length < 1 || length >= 1024 * 1024) - return -1; - data = pp = solv_malloc(length + 512); - for (l = length; l > 0; l -= 512, pp += 512) - if (readblock(th->fp, (unsigned char *)pp)) - { - solv_free(data); - return -1; - } - data[length] = 0; - type = 3; /* extension */ - if (th->blk[156] == 'L') - { - solv_free(th->path); - th->path = data; - length = 0; - break; - } - pp = data; - while (length > 0) - { - int ll = 0; - for (l = 0; l < length && pp[l] >= '0' && pp[l] <= '9'; l++) - ll = ll * 10 + (pp[l] - '0'); - if (l == length || pp[l] != ' ' || ll < 1 || ll > length || pp[ll - 1] != '\n') - { - solv_free(data); - return -1; - } - length -= ll; - pp += l + 1; - ll -= l + 1; - pp[ll - 1] = 0; - if (!strncmp(pp, "path=", 5)) - { - solv_free(th->path); - th->path = solv_strdup(pp + 5); - } - pp += ll; - } - solv_free(data); - th->ispax = 1; - length = 0; - break; - } - default: - type = 3; /* extension */ - break; - } - if ((type == 1 || type == 2) && !th->path) - { - char path[157]; - memcpy(path, th->blk, 156); - path[156] = 0; - if (!memcmp(th->blk + 257, "ustar\0\060\060", 8) && !th->path && th->blk[345]) - { - /* POSIX ustar with prefix */ - char prefix[156]; - memcpy(prefix, th->blk + 345, 155); - prefix[155] = 0; - l = strlen(prefix); - if (l && prefix[l - 1] == '/') - prefix[l - 1] = 0; - th->path = solv_dupjoin(prefix, "/", path); - } - else - th->path = solv_dupjoin(path, 0, 0); - } - if (type == 1 || type == 2) - { - l = strlen(th->path); - if (l && th->path[l - 1] == '/') - { - if (l > 1) - th->path[l - 1] = 0; - type = 2; - } - } - if (type != 3) - break; - while (length > 0) - { - r = readblock(th->fp, th->blk); - if (r) - return r; - length -= 512; - } - } - th->type = type; - th->length = length; - return 1; -} - static Offset adddep(Repo *repo, Offset olddeps, char *line) { @@ -333,10 +69,10 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags) Repodata *data; FILE *fp; struct tarhead th; - char line[4096]; - int ignoreline; + char *line = 0; + size_t line_alloc = 0, l; Solvable *s; - int l, fd; + int fd; struct stat stb; Chksum *pkgidchk = 0; @@ -359,36 +95,24 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags) return 0; } s = 0; - inittarhead(&th, fp); - while (gettarhead(&th) > 0) + tarhead_init(&th, fp); + while (tarhead_next(&th) > 0) { if (th.type != 1 || strcmp(th.path, ".PKGINFO") != 0) { - skipentry(&th); + tarhead_skip(&th); continue; } - ignoreline = 0; s = pool_id2solvable(pool, repo_add_solvable(repo)); if (flags & ARCH_ADD_WITH_PKGID) pkgidchk = solv_chksum_create(REPOKEY_TYPE_MD5); - while (getsentry(&th, line, sizeof(line))) + while ((l = tarhead_gets(&th, &line, &line_alloc)) > 0) { - l = strlen(line); - if (l == 0) - continue; if (pkgidchk) solv_chksum_add(pkgidchk, line, l); - if (line[l - 1] != '\n') - { - ignoreline = 1; - continue; - } - if (ignoreline) - { - ignoreline = 0; - continue; - } - line[--l] = 0; + l = strlen(line); /* no NULs please */ + if (l && line[l - 1] == '\n') + line[--l] = 0; if (l == 0 || line[0] == '#') continue; if (!strncmp(line, "pkgname = ", 10)) @@ -432,7 +156,8 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags) } break; } - freetarhead(&th); + solv_free(line); + tarhead_free(&th); fclose(fp); if (!s) { @@ -472,32 +197,6 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags) return s ? s - pool->solvables : 0; } -static char *getsentrynl(struct tarhead *th, char *s, int size) -{ - int l; - if (!getsentry(th, s, size)) - { - *s = 0; /* eof */ - return 0; - } - l = strlen(s); - if (!l) - return 0; - if (l && s[l - 1] == '\n') - { - s[l - 1] = 0; - return s; - } - while (getsentry(th, s, size)) - { - l = strlen(s); - if (!l || s[l - 1] == '\n') - return 0; - } - *s = 0; /* eof */ - return 0; -} - static Hashtable joinhash_init(Repo *repo, Hashval *hmp) { @@ -557,41 +256,50 @@ joinhash_lookup(Repo *repo, Hashtable ht, Hashval hm, const char *fn) return 0; } +static int getsentrynl(struct tarhead *th, char **linep, size_t *line_allocp) +{ + size_t l = tarhead_gets(th, linep, line_allocp); + if (l) + l = strlen(*linep); + if (l && (*linep)[l - 1] == '\n') + (*linep)[--l] = 0; + return l ? 1 : 0; +} + static void adddata(Repodata *data, Solvable *s, struct tarhead *th) { Repo *repo = data->repo; Pool *pool = repo->pool; - char line[4096]; - int l; + char *line = 0; + size_t l, line_alloc = 0; int havesha256 = 0; - while (getsentry(th, line, sizeof(line))) + while ((l = tarhead_gets(th, &line, &line_alloc)) > 0) { l = strlen(line); - if (l == 0 || line[l - 1] != '\n') - continue; - line[--l] = 0; + if (l && line[l - 1] == '\n') + line[--l] = 0; if (l <= 2 || line[0] != '%' || line[l - 1] != '%') continue; if (!strcmp(line, "%FILENAME%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_location(data, s - pool->solvables, 0, 0, line); } else if (!strcmp(line, "%NAME%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) s->name = pool_str2id(pool, line, 1); } else if (!strcmp(line, "%VERSION%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) s->evr = pool_str2id(pool, line, 1); } else if (!strcmp(line, "%DESC%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) { repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line); repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line); @@ -599,27 +307,27 @@ adddata(Repodata *data, Solvable *s, struct tarhead *th) } else if (!strcmp(line, "%GROUPS%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_add_poolstr_array(data, s - pool->solvables, SOLVABLE_GROUP, line); } else if (!strcmp(line, "%CSIZE%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, strtoull(line, 0, 10)); } else if (!strcmp(line, "%ISIZE%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line, 0, 10)); } else if (!strcmp(line, "%MD5SUM%")) { - if (getsentrynl(th, line, sizeof(line)) && !havesha256) + if (getsentrynl(th, &line, &line_alloc) && !havesha256) repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, REPOKEY_TYPE_MD5, line); } else if (!strcmp(line, "%SHA256SUM%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) { repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, line); havesha256 = 1; @@ -627,52 +335,52 @@ adddata(Repodata *data, Solvable *s, struct tarhead *th) } else if (!strcmp(line, "%URL%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line); } else if (!strcmp(line, "%LICENSE%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_add_poolstr_array(data, s - pool->solvables, SOLVABLE_LICENSE, line); } else if (!strcmp(line, "%ARCH%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) s->arch = pool_str2id(pool, line, 1); } else if (!strcmp(line, "%BUILDDATE%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line, 0, 10)); } else if (!strcmp(line, "%PACKAGER%")) { - if (getsentrynl(th, line, sizeof(line))) + if (getsentrynl(th, &line, &line_alloc)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line); } else if (!strcmp(line, "%REPLACES%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) s->obsoletes = adddep(repo, s->obsoletes, line); } else if (!strcmp(line, "%DEPENDS%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) s->requires = adddep(repo, s->requires, line); } else if (!strcmp(line, "%CONFLICTS%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) s->conflicts = adddep(repo, s->conflicts, line); } else if (!strcmp(line, "%PROVIDES%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) s->provides = adddep(repo, s->provides, line); } else if (!strcmp(line, "%OPTDEPENDS%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) { char *p = strchr(line, ':'); if (p && p > line) @@ -682,7 +390,7 @@ adddata(Repodata *data, Solvable *s, struct tarhead *th) } else if (!strcmp(line, "%FILES%")) { - while (getsentrynl(th, line, sizeof(line)) && *line) + while (getsentrynl(th, &line, &line_alloc) && *line) { char *p; Id id; @@ -714,9 +422,10 @@ adddata(Repodata *data, Solvable *s, struct tarhead *th) repodata_add_dirstr(data, s - pool->solvables, SOLVABLE_FILELIST, id, p); } } - while (*line) - getsentrynl(th, line, sizeof(line)); + while (*line && getsentrynl(th, &line, &line_alloc)) + ; } + solv_free(line); } static void @@ -754,24 +463,24 @@ repo_add_arch_repo(Repo *repo, FILE *fp, int flags) if (flags & REPO_EXTEND_SOLVABLES) joinhash = joinhash_init(repo, &joinhashmask); - inittarhead(&th, fp); - while (gettarhead(&th) > 0) + tarhead_init(&th, fp); + while (tarhead_next(&th) > 0) { char *bn; if (th.type != 1) { - skipentry(&th); + tarhead_skip(&th); continue; } bn = strrchr(th.path, '/'); if (!bn || (strcmp(bn + 1, "desc") != 0 && strcmp(bn + 1, "depends") != 0 && strcmp(bn + 1, "files") != 0)) { - skipentry(&th); + tarhead_skip(&th); continue; } if ((flags & REPO_EXTEND_SOLVABLES) != 0 && (!strcmp(bn + 1, "desc") || !strcmp(bn + 1, "depends"))) { - skipentry(&th); + tarhead_skip(&th); continue; /* skip those when we're extending */ } if (!lastdn || (bn - th.path) != lastdnlen || strncmp(lastdn, th.path, lastdnlen) != 0) @@ -786,7 +495,7 @@ repo_add_arch_repo(Repo *repo, FILE *fp, int flags) s = joinhash_lookup(repo, joinhash, joinhashmask, lastdn); if (!s) { - skipentry(&th); + tarhead_skip(&th); continue; } } @@ -831,17 +540,17 @@ repo_add_arch_local(Repo *repo, const char *dir, int flags) if ((fp = fopen(file, "r")) != 0) { struct tarhead th; - inittarhead(&th, fp); + tarhead_init(&th, fp); s = pool_id2solvable(pool, repo_add_solvable(repo)); adddata(data, s, &th); - freetarhead(&th); + tarhead_free(&th); fclose(fp); file = pool_tmpjoin(repo->pool, entrydir, "/files", 0); if ((fp = fopen(file, "r")) != 0) { - inittarhead(&th, fp); + tarhead_init(&th, fp); adddata(data, s, &th); - freetarhead(&th); + tarhead_free(&th); fclose(fp); } } diff --git a/ext/tarhead.c b/ext/tarhead.c new file mode 100644 index 00000000..e229b43d --- /dev/null +++ b/ext/tarhead.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2012, SUSE LLC + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +#include +#include +#include + +#include "util.h" +#include "tarhead.h" + +static long long parsenum(unsigned char *p, int cnt) +{ + long long x = 0; + if (!cnt) + return -1; + if (*p & 0x80) + { + /* binary format */ + x = *p & 0x40 ? (-1 << 8 | *p) : (*p ^ 0x80); + while (--cnt > 0) + x = (x << 8) | *p++; + return x; + } + while (cnt > 0 && (*p == ' ' || *p == '\t')) + cnt--, p++; + if (*p == '-') + return -1; + for (; cnt > 0 && *p >= '0' && *p < '8'; cnt--, p++) + x = (x << 3) | (*p - '0'); + return x; +} + +static int readblock(FILE *fp, unsigned char *blk) +{ + int r, l = 0; + while (l < 512) + { + r = fread(blk + l, 1, 512 - l, fp); + if (r <= 0) + return -1; + l += r; + } + return 0; +} + +void tarhead_skip(struct tarhead *th) +{ + for (; th->length > 0; th->length -= 512) + { + if (readblock(th->fp, th->blk)) + { + th->eof = 1; + th->length = 0; + return; + } + } + th->length = 0; + th->off = th->end = 0; +} + +void tarhead_init(struct tarhead *th, FILE *fp) +{ + memset(th, 0, sizeof(*th)); + th->fp = fp; +} + +void tarhead_free(struct tarhead *th) +{ + solv_free(th->path); +} + +int tarhead_next(struct tarhead *th) +{ + int l, type; + long long length; + + th->path = solv_free(th->path); + th->ispax = 0; + th->type = 0; + th->length = 0; + th->off = 0; + th->end = 0; + if (th->eof) + return 0; + for (;;) + { + int r = readblock(th->fp, th->blk); + if (r) + { + if (feof(th->fp)) + { + th->eof = 1; + return 0; + } + return -1; + } + if (th->blk[0] == 0) + { + th->eof = 1; + return 0; + } + length = parsenum(th->blk + 124, 12); + if (length < 0) + return -1; + type = 0; + switch (th->blk[156]) + { + case 'S': case '0': + type = 1; /* file */ + break; + case '1': + /* hard link, special length magic... */ + if (!th->ispax) + length = 0; + break; + case '5': + type = 2; /* dir */ + break; + case '2': case '3': case '4': case '6': + length = 0; + break; + case 'X': case 'x': case 'L': + { + char *data, *pp; + if (length < 1 || length >= 1024 * 1024) + return -1; + data = pp = solv_malloc(length + 512); + for (l = length; l > 0; l -= 512, pp += 512) + if (readblock(th->fp, (unsigned char *)pp)) + { + solv_free(data); + return -1; + } + data[length] = 0; + type = 3; /* extension */ + if (th->blk[156] == 'L') + { + solv_free(th->path); + th->path = data; + length = 0; + break; + } + pp = data; + while (length > 0) + { + int ll = 0; + for (l = 0; l < length && pp[l] >= '0' && pp[l] <= '9'; l++) + ll = ll * 10 + (pp[l] - '0'); + if (l == length || pp[l] != ' ' || ll < 1 || ll > length || pp[ll - 1] != '\n') + { + solv_free(data); + return -1; + } + length -= ll; + pp += l + 1; + ll -= l + 1; + pp[ll - 1] = 0; + if (!strncmp(pp, "path=", 5)) + { + solv_free(th->path); + th->path = solv_strdup(pp + 5); + } + pp += ll; + } + solv_free(data); + th->ispax = 1; + length = 0; + break; + } + default: + type = 3; /* extension */ + break; + } + if ((type == 1 || type == 2) && !th->path) + { + char path[157]; + memcpy(path, th->blk, 156); + path[156] = 0; + if (!memcmp(th->blk + 257, "ustar\0\060\060", 8) && !th->path && th->blk[345]) + { + /* POSIX ustar with prefix */ + char prefix[156]; + memcpy(prefix, th->blk + 345, 155); + prefix[155] = 0; + l = strlen(prefix); + if (l && prefix[l - 1] == '/') + prefix[l - 1] = 0; + th->path = solv_dupjoin(prefix, "/", path); + } + else + th->path = solv_dupjoin(path, 0, 0); + } + if (type == 1 || type == 2) + { + l = strlen(th->path); + if (l && th->path[l - 1] == '/') + { + if (l > 1) + th->path[l - 1] = 0; + type = 2; + } + } + if (type != 3) + break; + while (length > 0) + { + r = readblock(th->fp, th->blk); + if (r) + return r; + length -= 512; + } + } + th->type = type; + th->length = length; + return 1; +} + +size_t tarhead_gets(struct tarhead *th, char **linep , size_t *allocsizep) +{ + char *line = *linep; + size_t lsize = allocsizep ? *allocsizep : 0, size = 0; + int i; + + if (th->eof) + return 0; + for (;;) + { + size_t fsize = lsize - size; + if (fsize < 2) + { + line = *linep = solv_realloc(line, lsize += 1024); + fsize = lsize - size; + } + for (i = th->off; i < th->end && fsize > 1;) + { + fsize--; + if ((line[size++] = th->blk[i++]) == '\n') + { + th->off = i; + line[size] = 0; + return size; + } + } + /* end of block reached, read next block */ + th->off = i; + if (th->off < th->end) + continue; + if (!th->path) + { + /* fake entry */ + th->off = 0; + th->end = fread(th->blk, 1, 512, th->fp); + if (th->end <= 0) + { + th->eof = 1; + if (th->end < 0) + return 0; + break; + } + continue; + } + if (th->length <= 0) + break; /* reached end of entry */ + if (readblock(th->fp, th->blk)) + { + th->eof = 1; + return 0; + } + th->off = 0; + th->end = th->length > 512 ? 512 : th->length; + th->length -= th->end; + } + line[size] = 0; + return size; +} + diff --git a/ext/tarhead.h b/ext/tarhead.h new file mode 100644 index 00000000..a5ba48e0 --- /dev/null +++ b/ext/tarhead.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012, SUSE LLC + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +struct tarhead { + FILE *fp; + unsigned char blk[512]; + int type; + long long length; + char *path; + int eof; + int ispax; + + int off; + int end; +}; + +extern void tarhead_init(struct tarhead *th, FILE *fp); +extern void tarhead_free(struct tarhead *th); +extern int tarhead_next(struct tarhead *th); +extern void tarhead_skip(struct tarhead *th); +extern size_t tarhead_gets(struct tarhead *th, char **line, size_t *allocp);