pm

barely a pack manager
git clone git://z3bra.org/pm
Log | Files | Refs | README | LICENSE

commit bb81e744a877d4cc21bc2ddee1e15a9da906d058
parent 3520ebda244371812dd12b04da00df4fc986df18
Author: z3bra <willyatmailoodotorg>
Date:   Thu Jan  7 23:04:39 2016

Make unpack() more solid regarding file types

Use archive_write(3) to construct objects on disk, so handling of
symlinks, hardlink, and other types become transparent.

Diffstat:
 pm.c | 43 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/pm.c b/pm.c @@ -294,6 +294,28 @@ metadata(char *datadir, struct pack *pack) return 0; } +int +write_on_disk(struct archive *a, struct archive *w) +{ + int r; + const void *buf; + size_t len; + off_t off; + + for (;;) { + r = archive_read_data_block(a, &buf, &len, &off); + switch (r) { + case ARCHIVE_EOF: return 0; + case ARCHIVE_OK: break; + default: return r; + } + + r = archive_write_data_block(w, buf, len, off); + if (r != ARCHIVE_OK) + return r; + } +} + /* * Extract files into the given directory */ @@ -301,6 +323,7 @@ int unpack(char *root, char *in) { struct archive *a; + struct archive *disk; struct archive_entry *e; int r; int mask = ARCHIVE_EXTRACT_PERM @@ -311,6 +334,9 @@ unpack(char *root, char *in) archive_read_support_filter_bzip2(a); archive_read_support_format_tar(a); + disk = archive_write_disk_new(); + archive_write_disk_set_options(disk, mask); + r = archive_read_open_filename(a, in, 0); if (r != ARCHIVE_OK) return r; @@ -321,17 +347,21 @@ unpack(char *root, char *in) return -1; } - while (archive_read_next_header(a, &e) != ARCHIVE_EOF) { + while ((r = archive_read_next_header(a, &e)) != ARCHIVE_EOF) { if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(a)); return r; } - if (archive_entry_size(e) > 0) - r = archive_read_extract(a, e, mask); - if (r < 0) + printf("+ %s\n", archive_entry_pathname(e)); + r = archive_write_header(disk, e); + if (r != ARCHIVE_OK) return r; - } + write_on_disk(a, disk); + r = archive_write_finish_entry(disk); + if (r != 0) + return r; + } archive_read_close(a); archive_read_free(a); @@ -528,8 +558,7 @@ main (int argc, char **argv) while (*argv) { if ((p = pack_load(*(argv++)))) { metadata(PACKAGE_DATA, p); - if (unpack(PACKAGE_ROOT, p->path) > 0) { - fprintf(stderr, "error unpacking %s\n", p->name); + if (unpack(PACKAGE_ROOT, p->path) != 0) { delete(PACKAGE_DATA, PACKAGE_ROOT, p->name); } pack_unload(p);