From d303b53f2ced75703bf022a5d337ee3ba530b288 Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Mon, 25 Apr 2022 05:09:55 +0300 Subject: Initial commit --- libs/libarchive/libarchive.zig | 135 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 libs/libarchive/libarchive.zig (limited to 'libs/libarchive') 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 @@ +pub const c = @cImport({ + @cInclude("archive.h"); + @cInclude("archive_entry.h"); +}); + +const std = @import("std"); + +pub const Entry = struct { + raw: *c.archive_entry, + + pub fn pathname(self: Entry) [:0]const u8 { + return std.mem.span(c.archive_entry_pathname(self.raw)); + } + + pub fn setPathname(self: *Entry, new_pathname: [:0]const u8) void { + c.archive_entry_set_pathname(self.raw, new_pathname.ptr); + } +}; + +pub const Read = struct { + raw: *c.archive, + + pub fn init() !Read { + if (c.archive_read_new()) |raw| { + return Read{ .raw = raw }; + } else { + std.log.err("archive_read_new failed", .{}); + return error.LibArchiveError; + } + } + + pub fn deinit(self: *Read) void { + if (c.archive_read_free(self.raw) != c.ARCHIVE_OK) { + std.log.warn("archive_read_free failed", .{}); + } + } + + pub const Filter = enum { + all, + bzip2, + compress, + grzip, + gzip, + lrzip, + lz4, + lzma, + lzop, + none, + rpm, + uu, + xz, + zstd, + }; + + pub fn supportFilter(self: *Read, comptime filter: Filter) !void { + const fn_name = comptime "archive_read_support_filter_" ++ @tagName(filter); + const f = comptime @field(c, fn_name); + if (f(self.raw) != c.ARCHIVE_OK) { + std.log.err(fn_name ++ ": {s}", .{c.archive_error_string(self.raw)}); + return error.LibArchiveError; + } + } + + pub const Format = enum { + @"7zip", + all, + ar, + cab, + cpio, + empty, + iso9660, + lha, + mtree, + rar, + raw, + tar, + xar, + zip, + }; + + pub fn supportFormat(self: *Read, comptime format: Format) !void { + const fn_name = comptime "archive_read_support_format_" ++ @tagName(format); + const f = comptime @field(c, fn_name); + if (f(self.raw) != c.ARCHIVE_OK) { + std.log.err(fn_name ++ ": {s}", .{c.archive_error_string(self.raw)}); + return error.LibArchiveError; + } + } + + pub fn openFilename(self: *Read, filename: [:0]const u8, block_size: usize) !void { + if (c.archive_read_open_filename(self.raw, filename.ptr, block_size) != c.ARCHIVE_OK) { + std.log.err("archive_read_open_filename: {s}", .{c.archive_error_string(self.raw)}); + return error.LibArchiveError; + } + } + + pub fn nextHeader(self: *Read) !?Entry { + var header_raw: ?*c.archive_entry = undefined; + var r = c.ARCHIVE_RETRY; + while (r == c.ARCHIVE_RETRY) { + r = c.archive_read_next_header(self.raw, &header_raw); + } + + if (r == c.ARCHIVE_WARN) { + std.log.warn("archive_read_next_header: {s}", .{c.archive_error_string(self.raw)}); + r = c.ARCHIVE_OK; + } + + if (r == c.ARCHIVE_EOF) { + return null; + } + + if (r != c.ARCHIVE_OK or header_raw == null) { + std.log.err("archive_read_next_header: {s}", .{c.archive_error_string(self.raw)}); + return error.LibArchiveError; + } + + return Entry{ .raw = header_raw.? }; + } + + // TODO: Replace flags with enum + pub fn extract(self: *Read, entry: Entry, flags: c_int) !void { + var r = c.ARCHIVE_RETRY; + while (r == c.ARCHIVE_RETRY) { + r = c.archive_read_extract(self.raw, entry.raw, flags); + } + + if (r == c.ARCHIVE_WARN) { + std.log.warn("archive_read_extract: {s}", .{c.archive_error_string(self.raw)}); + } else if (r != c.ARCHIVE_OK) { + std.log.err("archive_read_extract: {s}", .{c.archive_error_string(self.raw)}); + return error.LibArchiveError; + } + } +}; -- cgit v1.2.3