From b6c80153c3b0306514673202bc6dd611b8a02b3e Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 19 Sep 2016 11:29:11 +0200 Subject: [PATCH] add API to create [tar.xz] archives --- libs/pbd/file_archive.cc | 105 ++++++++++++++++++++++++++++++++++++ libs/pbd/pbd/file_archive.h | 3 ++ 2 files changed, 108 insertions(+) diff --git a/libs/pbd/file_archive.cc b/libs/pbd/file_archive.cc index 4afc9abad9..95cdbf61cf 100644 --- a/libs/pbd/file_archive.cc +++ b/libs/pbd/file_archive.cc @@ -19,7 +19,10 @@ #include #include #include +#include +#include +#include #include "pbd/gstdio_compat.h" #include @@ -29,6 +32,7 @@ #include "pbd/failed_constructor.h" #include "pbd/file_archive.h" +#include "pbd/file_utils.h" using namespace PBD; @@ -330,3 +334,104 @@ FileArchive::do_extract (struct archive* a) archive_write_free(ext); return rv; } + + +int +FileArchive::create (const std::string& srcdir) +{ + if (_req.is_remote ()) { + return -1; + } + + std::string parent = Glib::path_get_dirname (srcdir); + size_t p_len = parent.size () + 1; + + Searchpath sp (srcdir); + std::vector files; + find_files_matching_pattern (files, sp, "*"); + + std::map filemap; + + for (std::vector::const_iterator f = files.begin (); f != files.end (); ++f) { + assert (f->size () > p_len); + filemap[*f] = f->substr (p_len); + } + + return create (filemap); +} + +int +FileArchive::create (const std::map& filemap) +{ + struct archive *a; + struct archive_entry *entry; + + size_t read_bytes = 0; + size_t total_bytes = 0; + + for (std::map::const_iterator f = filemap.begin (); f != filemap.end (); ++f) { + GStatBuf statbuf; + if (g_stat (f->first.c_str(), &statbuf)) { + continue; + } + total_bytes += statbuf.st_size; + } + + if (total_bytes == 0) { + return -1; + } + + progress (0, total_bytes); + + a = archive_write_new (); + archive_write_set_format_pax_restricted (a); + archive_write_add_filter_lzma (a); + archive_write_open_filename (a, _req.url); + entry = archive_entry_new (); + + for (std::map::const_iterator f = filemap.begin (); f != filemap.end (); ++f) { + char buf[8192]; + const char* filepath = f->first.c_str (); + const char* filename = f->second.c_str (); + + GStatBuf statbuf; + if (g_stat (filepath, &statbuf)) { + continue; + } + + archive_entry_clear (entry); + +#ifdef PLATFORM_WINDOWS + archive_entry_set_size (entry, statbuf.st_size); + archive_entry_set_atime (entry, statbuf.st_atime, 0); + archive_entry_set_ctime (entry, statbuf.st_ctime, 0); + archive_entry_set_mtime (entry, statbuf.st_mtime, 0); +#else + archive_entry_copy_stat (entry, &statbuf); +#endif + + archive_entry_set_pathname (entry, filename); + archive_entry_set_filetype (entry, AE_IFREG); + archive_entry_set_perm (entry, 0644); + + archive_write_header (a, entry); + + int fd = g_open (filepath, O_RDONLY, 0444); + assert (fd >= 0); + + ssize_t len = read (fd, buf, sizeof (buf)); + while (len > 0) { + read_bytes += len; + archive_write_data (a, buf, len); + progress (read_bytes, total_bytes); + len = read (fd, buf, sizeof (buf)); + } + close (fd); + } + + archive_entry_free (entry); + archive_write_close (a); + archive_write_free (a); + + return 0; +} diff --git a/libs/pbd/pbd/file_archive.h b/libs/pbd/pbd/file_archive.h index 9fc11fc464..3708f3bbf4 100644 --- a/libs/pbd/pbd/file_archive.h +++ b/libs/pbd/pbd/file_archive.h @@ -38,6 +38,9 @@ class LIBPBD_API FileArchive int inflate (const std::string& destdir); std::vector contents (); + int create (const std::string& srcdir); + int create (const std::map & filemap); + PBD::Signal2 progress; // TODO struct MemPipe { -- 2.30.2