77 lines
2.8 KiB
Zig
77 lines
2.8 KiB
Zig
const std = @import("std");
|
|
const Reader = std.Io.Reader;
|
|
|
|
pub const BlockSize = packed struct {
|
|
size: u24,
|
|
uncompressed: bool,
|
|
_: u7,
|
|
};
|
|
|
|
pub const File = struct {
|
|
block_start: u32, // bytes 0-3
|
|
frag_idx: u32, // bytes 4-7
|
|
frag_block_offset: u32, // bytes 8-11
|
|
size: u32, // bytes 12-15
|
|
block_sizes: []BlockSize,
|
|
|
|
pub fn read(alloc: std.mem.Allocator, rdr: *Reader, block_size: u32) !File {
|
|
var start: [16]u8 = undefined;
|
|
try rdr.readSliceAll(&start);
|
|
const frag_idx: u32 = std.mem.readInt(u32, start[4..8], .little);
|
|
const size: u32 = std.mem.readInt(u32, start[12..16], .little);
|
|
var num_blocks: u32 = size / block_size;
|
|
if (size % block_size != 0 and frag_idx == 0xFFFFFFFF) num_blocks += 1;
|
|
const sizes = try alloc.alloc(BlockSize, num_blocks);
|
|
errdefer alloc.free(sizes);
|
|
try rdr.readSliceEndian(BlockSize, sizes, .little);
|
|
return .{
|
|
.block_start = std.mem.readInt(u32, start[0..4], .little),
|
|
.frag_idx = frag_idx,
|
|
.frag_block_offset = std.mem.readInt(u32, start[8..12], .little),
|
|
.size = size,
|
|
.block_sizes = sizes,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: File, alloc: std.mem.Allocator) void {
|
|
alloc.free(self.block_sizes);
|
|
}
|
|
};
|
|
|
|
pub const ExtFile = struct {
|
|
block_start: u64, // bytes 0-7
|
|
size: u64, // bytes 8-15
|
|
sparse: u64, // bytes 16-23
|
|
hard_links: u32, // bytes 24-27
|
|
frag_idx: u32, // bytes 28-31
|
|
frag_block_offset: u32, // bytes 32-35
|
|
xattr_idx: u32, // bytes 36-39
|
|
block_sizes: []BlockSize,
|
|
|
|
pub fn read(alloc: std.mem.Allocator, rdr: *Reader, block_size: u32) !ExtFile {
|
|
var start: [40]u8 = undefined;
|
|
try rdr.readSliceAll(&start);
|
|
const frag_idx: u32 = std.mem.readInt(u32, start[28..32], .little);
|
|
const size: u64 = std.mem.readInt(u64, start[8..16], .little);
|
|
var num_blocks: u32 = @truncate(size / block_size);
|
|
if (size % block_size != 0 and frag_idx == 0xFFFFFFFF) num_blocks += 1;
|
|
const sizes = try alloc.alloc(BlockSize, num_blocks);
|
|
errdefer alloc.free(sizes);
|
|
try rdr.readSliceEndian(BlockSize, sizes, .little);
|
|
return .{
|
|
.block_start = std.mem.readInt(u64, start[0..8], .little),
|
|
.size = size,
|
|
.sparse = std.mem.readInt(u64, start[16..24], .little),
|
|
.hard_links = std.mem.readInt(u32, start[24..28], .little),
|
|
.frag_idx = frag_idx,
|
|
.frag_block_offset = std.mem.readInt(u32, start[32..36], .little),
|
|
.xattr_idx = std.mem.readInt(u32, start[36..40], .little),
|
|
.block_sizes = sizes,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: ExtFile, alloc: std.mem.Allocator) void {
|
|
alloc.free(self.block_sizes);
|
|
}
|
|
};
|