URI: 
       tMake unpack() more solid regarding file types - pm - barely a pack manager
  HTML git clone git://z3bra.org/pm
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit bb81e744a877d4cc21bc2ddee1e15a9da906d058
   DIR parent 3520ebda244371812dd12b04da00df4fc986df18
  HTML Author: z3bra <willyatmailoodotorg>
       Date:   Thu,  7 Jan 2016 23:04:39 +0100
       
       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:
         M pm.c                                |      43 ++++++++++++++++++++++++++-----
       
       1 file changed, 36 insertions(+), 7 deletions(-)
       ---
   DIR diff --git a/pm.c b/pm.c
       t@@ -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
         */
       t@@ -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
       t@@ -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;
       t@@ -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);
        
       t@@ -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);