summaryrefslogtreecommitdiff
path: root/libs/libarchive
diff options
context:
space:
mode:
authorGravatar Uko Kokņevičs2022-04-25 05:09:55 +0300
committerGravatar Uko Kokņevičs2022-04-25 23:34:05 +0300
commitd303b53f2ced75703bf022a5d337ee3ba530b288 (patch)
treef2e64057120d01ee8a821596ea01b8fc37c53c2c /libs/libarchive
downloadzup-0.1.0.tar.gz
zup-0.1.0.tar.xz
zup-0.1.0.zip
Initial commit0.1.0
Diffstat (limited to 'libs/libarchive')
-rw-r--r--libs/libarchive/libarchive.zig135
1 files changed, 135 insertions, 0 deletions
diff --git a/libs/libarchive/libarchive.zig b/libs/libarchive/libarchive.zig
new file mode 100644
index 0000000..dab205e
--- /dev/null
+++ b/libs/libarchive/libarchive.zig
@@ -0,0 +1,135 @@
1pub const c = @cImport({
2 @cInclude("archive.h");
3 @cInclude("archive_entry.h");
4});
5
6const std = @import("std");
7
8pub const Entry = struct {
9 raw: *c.archive_entry,
10
11 pub fn pathname(self: Entry) [:0]const u8 {
12 return std.mem.span(c.archive_entry_pathname(self.raw));
13 }
14
15 pub fn setPathname(self: *Entry, new_pathname: [:0]const u8) void {
16 c.archive_entry_set_pathname(self.raw, new_pathname.ptr);
17 }
18};
19
20pub const Read = struct {
21 raw: *c.archive,
22
23 pub fn init() !Read {
24 if (c.archive_read_new()) |raw| {
25 return Read{ .raw = raw };
26 } else {
27 std.log.err("archive_read_new failed", .{});
28 return error.LibArchiveError;
29 }
30 }
31
32 pub fn deinit(self: *Read) void {
33 if (c.archive_read_free(self.raw) != c.ARCHIVE_OK) {
34 std.log.warn("archive_read_free failed", .{});
35 }
36 }
37
38 pub const Filter = enum {
39 all,
40 bzip2,
41 compress,
42 grzip,
43 gzip,
44 lrzip,
45 lz4,
46 lzma,
47 lzop,
48 none,
49 rpm,
50 uu,
51 xz,
52 zstd,
53 };
54
55 pub fn supportFilter(self: *Read, comptime filter: Filter) !void {
56 const fn_name = comptime "archive_read_support_filter_" ++ @tagName(filter);
57 const f = comptime @field(c, fn_name);
58 if (f(self.raw) != c.ARCHIVE_OK) {
59 std.log.err(fn_name ++ ": {s}", .{c.archive_error_string(self.raw)});
60 return error.LibArchiveError;
61 }
62 }
63
64 pub const Format = enum {
65 @"7zip",
66 all,
67 ar,
68 cab,
69 cpio,
70 empty,
71 iso9660,
72 lha,
73 mtree,
74 rar,
75 raw,
76 tar,
77 xar,
78 zip,
79 };
80
81 pub fn supportFormat(self: *Read, comptime format: Format) !void {
82 const fn_name = comptime "archive_read_support_format_" ++ @tagName(format);
83 const f = comptime @field(c, fn_name);
84 if (f(self.raw) != c.ARCHIVE_OK) {
85 std.log.err(fn_name ++ ": {s}", .{c.archive_error_string(self.raw)});
86 return error.LibArchiveError;
87 }
88 }
89
90 pub fn openFilename(self: *Read, filename: [:0]const u8, block_size: usize) !void {
91 if (c.archive_read_open_filename(self.raw, filename.ptr, block_size) != c.ARCHIVE_OK) {
92 std.log.err("archive_read_open_filename: {s}", .{c.archive_error_string(self.raw)});
93 return error.LibArchiveError;
94 }
95 }
96
97 pub fn nextHeader(self: *Read) !?Entry {
98 var header_raw: ?*c.archive_entry = undefined;
99 var r = c.ARCHIVE_RETRY;
100 while (r == c.ARCHIVE_RETRY) {
101 r = c.archive_read_next_header(self.raw, &header_raw);
102 }
103
104 if (r == c.ARCHIVE_WARN) {
105 std.log.warn("archive_read_next_header: {s}", .{c.archive_error_string(self.raw)});
106 r = c.ARCHIVE_OK;
107 }
108
109 if (r == c.ARCHIVE_EOF) {
110 return null;
111 }
112
113 if (r != c.ARCHIVE_OK or header_raw == null) {
114 std.log.err("archive_read_next_header: {s}", .{c.archive_error_string(self.raw)});
115 return error.LibArchiveError;
116 }
117
118 return Entry{ .raw = header_raw.? };
119 }
120
121 // TODO: Replace flags with enum
122 pub fn extract(self: *Read, entry: Entry, flags: c_int) !void {
123 var r = c.ARCHIVE_RETRY;
124 while (r == c.ARCHIVE_RETRY) {
125 r = c.archive_read_extract(self.raw, entry.raw, flags);
126 }
127
128 if (r == c.ARCHIVE_WARN) {
129 std.log.warn("archive_read_extract: {s}", .{c.archive_error_string(self.raw)});
130 } else if (r != c.ARCHIVE_OK) {
131 std.log.err("archive_read_extract: {s}", .{c.archive_error_string(self.raw)});
132 return error.LibArchiveError;
133 }
134 }
135};