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);