zig/lib/std/tar/output.zig
Andrew Kelley ffd53a459e -femit-docs: creating sources.tar
It's always a good day when you get to use File.writeFileAll 😎
2024-03-10 17:51:07 -07:00

86 lines
2.4 KiB
Zig

/// A struct that is exactly 512 bytes and matches tar file format. This is
/// intended to be used for outputting tar files; for parsing there is
/// `std.tar.Header`.
pub const Header = extern struct {
// This struct was originally copied from
// https://github.com/mattnite/tar/blob/main/src/main.zig which is MIT
// licensed.
name: [100]u8,
mode: [7:0]u8,
uid: [7:0]u8,
gid: [7:0]u8,
size: [11:0]u8,
mtime: [11:0]u8,
checksum: [7:0]u8,
typeflag: FileType,
linkname: [100]u8,
magic: [5:0]u8,
version: [2]u8,
uname: [31:0]u8,
gname: [31:0]u8,
devmajor: [7:0]u8,
devminor: [7:0]u8,
prefix: [155]u8,
pad: [12]u8,
pub const FileType = enum(u8) {
regular = '0',
hard_link = '1',
symbolic_link = '2',
character = '3',
block = '4',
directory = '5',
fifo = '6',
reserved = '7',
pax_global = 'g',
extended = 'x',
_,
};
pub fn init() Header {
var ret = std.mem.zeroes(Header);
ret.magic = [_:0]u8{ 'u', 's', 't', 'a', 'r' };
ret.version = [_:0]u8{ '0', '0' };
return ret;
}
pub fn setPath(self: *Header, prefix: []const u8, path: []const u8) !void {
if (prefix.len + 1 + path.len > 100) {
var i: usize = 0;
while (i < path.len and path.len - i > 100) {
while (path[i] != '/') : (i += 1) {}
}
_ = try std.fmt.bufPrint(&self.prefix, "{s}/{s}", .{ prefix, path[0..i] });
_ = try std.fmt.bufPrint(&self.name, "{s}", .{path[i + 1 ..]});
} else {
_ = try std.fmt.bufPrint(&self.name, "{s}/{s}", .{ prefix, path });
}
}
pub fn setSize(self: *Header, size: u64) !void {
_ = try std.fmt.bufPrint(&self.size, "{o:0>11}", .{size});
}
pub fn updateChecksum(self: *Header) !void {
const offset = @offsetOf(Header, "checksum");
var checksum: usize = 0;
for (std.mem.asBytes(self), 0..) |val, i| {
checksum += if (i >= offset and i < offset + @sizeOf(@TypeOf(self.checksum)))
' '
else
val;
}
_ = try std.fmt.bufPrint(&self.checksum, "{o:0>7}", .{checksum});
}
comptime {
assert(@sizeOf(Header) == 512);
}
};
const std = @import("../std.zig");
const assert = std.debug.assert;