[gnome-boxes] Add wrapper for Archive.Read
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes] Add wrapper for Archive.Read
- Date: Fri, 1 Aug 2014 10:45:18 +0000 (UTC)
commit b4f851f4eb23643f23fb34ce925ca93aafdde136
Author: Lasse Schuirmann <lasse schuirmann gmail com>
Date: Tue Jul 1 15:16:41 2014 +0200
Add wrapper for Archive.Read
The ArchiveReader is capable of reading archives through libarchive.
It primarily provides an file extraction functionality.
https://bugzilla.gnome.org/show_bug.cgi?id=730640
src/Makefile.am | 1 +
src/archive-reader.vala | 141 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 0bd6a1b..1ca4a7e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -96,6 +96,7 @@ gnome_boxes_SOURCES = \
$(BUILT_SOURCES) \
app.vala \
app-window.vala \
+ archive-reader.vala \
auth-notification.vala \
collection-view.vala \
collection.vala \
diff --git a/src/archive-reader.vala b/src/archive-reader.vala
new file mode 100644
index 0000000..e337f0e
--- /dev/null
+++ b/src/archive-reader.vala
@@ -0,0 +1,141 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+public class Boxes.ArchiveReader : GLib.Object {
+ // This is the block size used by example code on the libarchive website
+ private static const int BLOCK_SIZE = 10240;
+
+ public Archive.Read archive;
+
+ private string filename;
+ private Archive.Format? format;
+ private GLib.List<Archive.Filter>? filters;
+
+ public ArchiveReader (string filename,
+ Archive.Format? format = null,
+ GLib.List<Archive.Filter>? filters = null)
+ throws GLib.IOError {
+ this.filename = filename;
+ this.format = format;
+ if (filters != null)
+ this.filters = filters.copy ();
+
+ open_archive ();
+ }
+
+ public GLib.List<string> get_file_list () throws GLib.IOError {
+ var result = new GLib.List<string> ();
+ unowned Archive.Entry iterator;
+ while (get_next_header (archive, out iterator))
+ result.append (iterator.pathname ());
+
+ return result;
+ }
+
+ // convenience wrapper, don't use it for extracting more than one file for performance reasons!
+ public void extract_file (string src,
+ string dest,
+ bool override_if_necessary = false)
+ throws GLib.IOError {
+ extract_files_recursive ({src}, {dest}, override_if_necessary);
+ }
+
+ public void reset () throws GLib.IOError {
+ execute_libarchive_function (archive, archive.close);
+ open_archive ();
+ }
+
+ // src_dest is a hash table where the key is the relative path in the archive and the value the path to
extract to
+ private void extract_files (string[] src_list,
+ string[] dest_list,
+ bool override_if_necessary = false)
+ throws GLib.IOError {
+ extract_files_recursive (src_list, dest_list, override_if_necessary);
+ }
+
+ private void extract_files_recursive (string[] src_list,
+ string[] dest_list,
+ bool override_if_necessary = false,
+ bool follow_hardlinks = true)
+ throws GLib.IOError
+ requires (src_list.length == dest_list.length) {
+ if (src_list.length == 0)
+ return;
+
+ unowned Archive.Entry iterator;
+ uint i = 0;
+ string[] hardlink_src = {};
+ string[] hardlink_dest = {};
+ // FIXME: split out some things out of this ugly loop
+ while (get_next_header (archive, out iterator) && (i < src_list.length)) {
+ var dest = get_dest_file (src_list, dest_list, iterator.pathname ());
+
+ if (dest == null) {
+ // file is not to be extracted
+ execute_libarchive_function (archive, archive.read_data_skip);
+
+ continue;
+ }
+
+ if (iterator.hardlink () != null && iterator.size () == 0) {
+ debug ("Following hardlink of '%s' to '%s'.", iterator.pathname (), iterator.hardlink ());
+ hardlink_src += iterator.hardlink ();
+ hardlink_dest += dest;
+ i++;
+
+ continue;
+ }
+
+ if (!override_if_necessary && FileUtils.test (dest, FileTest.EXISTS))
+ throw new GLib.IOError.EXISTS ("Destination file '%s' already exists.", dest);
+
+ // read data into file
+ var fd = FileStream.open (dest, "w+");
+ execute_libarchive_function (archive, () => { return archive.read_data_into_fd (fd.fileno ());
});
+
+ debug ("Extracted file '%s' from archive '%s'.", dest, filename);
+ i++;
+ }
+
+ if (src_list.length != i)
+ throw new GLib.IOError.NOT_FOUND ("At least one specified file was not found in the archive.");
+
+ reset ();
+
+ if (hardlink_src.length > 0) {
+ if (follow_hardlinks) {
+ extract_files_recursive (hardlink_src, hardlink_dest, override_if_necessary, false);
+ } else {
+ var msg = "Maximum recursion depth exceeded. It is likely that a hardlink points to itself.";
+
+ throw new GLib.IOError.WOULD_RECURSE (msg);
+ }
+ }
+ }
+
+ private string? get_dest_file (string[] src_list, string[] dest_list, string src) {
+ for (uint j = 0; j < src_list.length; j++) {
+ if (src_list[j] == src)
+ return dest_list[j];
+ }
+
+ return null;
+ }
+
+ private void open_archive () throws GLib.IOError {
+ archive = new Archive.Read ();
+
+ if (format == null)
+ execute_libarchive_function (archive, archive.support_format_all);
+ else
+ execute_libarchive_function (archive, () => { return archive.set_format (format); });
+
+ if (filters == null) {
+ execute_libarchive_function (archive, archive.support_filter_all);
+ } else {
+ foreach (var filter in filters)
+ execute_libarchive_function (archive, () => { return archive.append_filter (filter); });
+ }
+
+ execute_libarchive_function (archive, () => { return archive.open_filename (filename, BLOCK_SIZE);
});
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]