diff options
author | Robin Gareus <robin@gareus.org> | 2016-09-19 11:29:11 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-09-19 11:33:07 +0200 |
commit | b6c80153c3b0306514673202bc6dd611b8a02b3e (patch) | |
tree | 3f84fc9a4cb93ba1426dba344fa52a3f665bb815 /libs/pbd | |
parent | 02b7db03bd11de67c8e5d981d6075ce9f0ca8963 (diff) |
add API to create [tar.xz] archives
Diffstat (limited to 'libs/pbd')
-rw-r--r-- | libs/pbd/file_archive.cc | 105 | ||||
-rw-r--r-- | libs/pbd/pbd/file_archive.h | 3 |
2 files changed, 108 insertions, 0 deletions
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 <stdlib.h> #include <string.h> #include <cstdio> +#include <fcntl.h> +#include <sys/stat.h> +#include <glib.h> #include "pbd/gstdio_compat.h" #include <glibmm.h> @@ -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<std::string> files; + find_files_matching_pattern (files, sp, "*"); + + std::map<std::string, std::string> filemap; + + for (std::vector<std::string>::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<std::string, std::string>& filemap) +{ + struct archive *a; + struct archive_entry *entry; + + size_t read_bytes = 0; + size_t total_bytes = 0; + + for (std::map<std::string, std::string>::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<std::string, std::string>::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<std::string> contents (); + int create (const std::string& srcdir); + int create (const std::map <std::string, std::string>& filemap); + PBD::Signal2<void, size_t, size_t> progress; // TODO struct MemPipe { |