[gnome-boxes] Add wrapper for Archive.Write
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes] Add wrapper for Archive.Write
- Date: Fri, 1 Aug 2014 10:45:23 +0000 (UTC)
commit 06aecbde8b3fc0bf52f1b803bdd774937bd7d276
Author: Lasse Schuirmann <lasse schuirmann gmail com>
Date: Tue Jul 1 15:29:29 2014 +0200
Add wrapper for Archive.Write
The ArchiveWriter provides the functionality of creating archives
(either from existing ones or new) and writing files to it.
https://bugzilla.gnome.org/show_bug.cgi?id=730640
src/Makefile.am | 1 +
src/archive-writer.vala | 142 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 1ca4a7e..2108512 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,6 +97,7 @@ gnome_boxes_SOURCES = \
app.vala \
app-window.vala \
archive-reader.vala \
+ archive-writer.vala \
auth-notification.vala \
collection-view.vala \
collection.vala \
diff --git a/src/archive-writer.vala b/src/archive-writer.vala
new file mode 100644
index 0000000..6d5ab8d
--- /dev/null
+++ b/src/archive-writer.vala
@@ -0,0 +1,142 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+// A non-threadsafe wrapper for libarchives write archive
+public class Boxes.ArchiveWriter : GLib.Object {
+ public Archive.Write archive;
+
+ private GLib.List<Archive.Filter>? filters;
+ private Archive.Format format;
+
+ public ArchiveWriter (string filename,
+ Archive.Format format,
+ GLib.List<Archive.Filter>? filters = null)
+ throws GLib.IOError {
+ archive = new Archive.Write ();
+ this.format = format;
+ this.filters = filters.copy ();
+
+ prepare_archive ();
+ execute_libarchive_function (archive, () => { return archive.open_filename (filename); });
+ }
+
+ public ArchiveWriter.from_archive_reader (ArchiveReader archive_reader,
+ string filename,
+ bool import_contents = true)
+ throws GLib.IOError {
+ unowned Archive.Entry iterator;
+ archive = new Archive.Write ();
+ if (!get_next_header (archive_reader.archive, out iterator)) {
+ var msg = "Error creating write archive for archive '%s'. It is probably empty.";
+ throw new GLib.IOError.FAILED (msg, filename);
+ }
+
+ format = archive_reader.archive.format ();
+ copy_filters_from_read_archive (archive_reader.archive);
+ prepare_archive ();
+ execute_libarchive_function (archive, () => { return archive.open_filename (filename); });
+
+ archive_reader.reset ();
+
+ if (import_contents)
+ import_read_archive (archive_reader);
+ }
+
+ // if omit_hardlinked_files is true a file body will be omitted if its on the list independently from it
having a
+ // hardlink pointing to it or not. If it is set to false a file body with a hardlink on the omittion
list will
+ // result in the file NOT being omitted.
+ public void import_read_archive (ArchiveReader archive_reader,
+ string[]? omit_files = null,
+ bool omit_hardlinked_files = false)
+ throws GLib.IOError {
+ unowned Archive.Entry iterator;
+ while (get_next_header (archive_reader.archive, out iterator)) {
+ var omit = false;
+ foreach (var file in omit_files) {
+ if (file == iterator.pathname ()) {
+ omit = true;
+
+ break;
+ }
+ }
+
+ if (omit) {
+ if (omit_hardlinked_files || iterator.nlink () == 1 || iterator.hardlink () != null)
+ // File is a hardlink jost pointing somewhere or there's no hardlink to this file
+ // (or !omit_hardlinked_files)
+ continue;
+ else
+ warning ("File '%s' cannot be omitted since a hardlink points to it.", iterator.pathname
());
+ }
+
+ var len = iterator.size ();
+ execute_libarchive_function (archive, () => { return archive.write_header (iterator); });
+ if (len > 0) {
+ var buf = new uint8[len];
+ insert_data (buf, archive_reader.archive.read_data (buf, (size_t) len));
+ }
+ }
+
+ archive_reader.reset ();
+ }
+
+ // convenience wrapper
+ public void insert_files (string[] src_list,
+ string[] dest_list)
+ throws GLib.IOError
+ requires (src_list.length == dest_list.length) {
+ for (uint i = 0; i < src_list.length; i++)
+ insert_file (src_list[i], dest_list[i]);
+ }
+
+ // while dest is the destination relative to archive root
+ public void insert_file (string src, string dest) throws GLib.IOError {
+ if (!FileUtils.test (src, FileTest.EXISTS))
+ throw new GLib.IOError.NOT_FOUND ("Source file '%s' cannot be injected. File not found.", src);
+
+ if (FileUtils.test (src, FileTest.IS_SYMLINK))
+ throw new GLib.IOError.NOT_SUPPORTED ("Inserting symlinks is currently not supported.");
+
+ var entry = get_entry_for_file (src, dest);
+ var len = entry.size ();
+ var buf = new uint8[len];
+
+ // get file info, read data into memory
+ var filestream = GLib.FileStream.open (src, "r");
+ filestream.read ((uint8[]) buf, (size_t) len);
+ execute_libarchive_function (archive, () => { return archive.write_header(entry); });
+ insert_data ((uint8[]) buf, len);
+ }
+
+ private void prepare_archive () throws GLib.IOError {
+ execute_libarchive_function (archive, () => { return archive.set_format (format); });
+
+ if (filters != null) {
+ foreach (var filter in filters)
+ execute_libarchive_function (archive, () => { return archive.add_filter (filter); });
+ }
+ }
+
+ private void copy_filters_from_read_archive (Archive.Read read_archive) {
+ filters = new GLib.List<Archive.Filter> ();
+ for (var i = read_archive.filter_count () - 1; i > 0; i--)
+ filters.append (read_archive.filter_code (i - 1));
+ }
+
+ private void insert_data (void* data, int64 len) throws GLib.IOError {
+ if (archive.write_data (data, (size_t) len) != len)
+ throw new GLib.IOError.FAILED ("Failed writing data to archive. Message: '%s'.",
+ archive.error_string ());
+ }
+
+ private Archive.Entry get_entry_for_file (string filename, string dest_name) {
+ Posix.Stat st;
+ var result = new Archive.Entry ();
+
+ Posix.stat (filename, out st);
+
+ result.copy_stat (st);
+ result.set_pathname (dest_name);
+
+ return result;
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]