Proper zig project organization
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
const std = @import("std");
|
||||
const compress = std.compress;
|
||||
|
||||
const DecompressError = error{
|
||||
LzoNotSupported,
|
||||
Lz4NotSupported,
|
||||
};
|
||||
|
||||
pub const CompressionType = enum(u16) {
|
||||
gzip = 1,
|
||||
lzma,
|
||||
lzo,
|
||||
xz,
|
||||
lz4,
|
||||
zstd,
|
||||
|
||||
pub fn Decompress(self: CompressionType, alloc: std.mem.Allocator, rdr: std.io.AnyReader) ![]u8 {
|
||||
var out = std.ArrayList(u8).init(alloc);
|
||||
defer out.deinit();
|
||||
switch (self) {
|
||||
.gzip => try compress.zlib.decompress(rdr, out.writer()),
|
||||
.lzma => {
|
||||
var decomp = try compress.lzma.decompress(alloc, rdr);
|
||||
defer decomp.deinit();
|
||||
try decomp.reader().readAllArrayList(&out, 1024 * 1024);
|
||||
},
|
||||
.lzo => return DecompressError.LzoNotSupported,
|
||||
.xz => {
|
||||
var decomp = try compress.xz.decompress(alloc, rdr);
|
||||
defer decomp.deinit();
|
||||
try decomp.reader().readAllArrayList(&out, 1024 * 1024);
|
||||
},
|
||||
.lz4 => return DecompressError.Lz4NotSupported,
|
||||
.zstd => {
|
||||
const buf = try alloc.alloc(u8, compress.zstd.DecompressorOptions.default_window_buffer_len);
|
||||
defer alloc.free(buf);
|
||||
var decomp = compress.zstd.decompressor(rdr, .{
|
||||
.window_buffer = buf,
|
||||
});
|
||||
try decomp.reader().readAllArrayList(&out, 1024 * 1024);
|
||||
},
|
||||
}
|
||||
return try out.toOwnedSlice();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
const std = @import("std");
|
||||
|
||||
const DirHeader = packed struct {
|
||||
count: u32,
|
||||
inode_block_start: u32,
|
||||
inode_num: u32,
|
||||
};
|
||||
|
||||
const RawDirEntry = struct {
|
||||
inode_offset: u16,
|
||||
inode_num_difference: i16,
|
||||
inode_type: u16,
|
||||
name_size: u16,
|
||||
name: []u8,
|
||||
|
||||
fn init(rdr: std.io.AnyReader, alloc: std.mem.Allocator) !DirEntry {
|
||||
var out: DirEntry = .{
|
||||
.inode_offset = try rdr.readInt(u16, std.builtin.Endian.little),
|
||||
.inode_num_difference = try rdr.readInt(i16, std.builtin.Endian.little),
|
||||
.inode_type = try rdr.readInt(u16, std.builtin.Endian.little),
|
||||
.name_size = try rdr.readInt(u16, std.builtin.Endian.little),
|
||||
.name = undefined,
|
||||
};
|
||||
out.name = try alloc.alloc(u8, out.name_size);
|
||||
_ = try rdr.readAll(out.name);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
pub const DirEntry = struct {
|
||||
inode_offset: u16,
|
||||
inode_block_start: u32,
|
||||
inode_num: u32,
|
||||
name: []u8,
|
||||
|
||||
fn init(raw: RawDirEntry, hdr: DirHeader) DirEntry {
|
||||
return .{
|
||||
.inode_offset = raw.inode_offset,
|
||||
.inode_block_start = hdr.inode_block_start,
|
||||
.inode_num = hdr.inode_num - raw.inode_num_difference,
|
||||
.name = raw.name,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
const inode = @import("inode.zig");
|
||||
const Reader = @import("squashfs.zig").Reader;
|
||||
const MetadataReader = @import("metadata_reader.zig").MetadataReader;
|
||||
const FileOffsetReader = @import("file_offset_reader.zig").FileOffsetReader;
|
||||
|
||||
pub const File = struct {
|
||||
rdr: *Reader,
|
||||
inode: inode.Inode,
|
||||
name: []const u8,
|
||||
dir_entries: []const void = undefined, //TODO
|
||||
|
||||
pub fn fromRef(ref: inode.InodeRef, name: []const u8, rdr: *Reader) !File {
|
||||
var offset_rdr: FileOffsetReader = .init(rdr.file, rdr.super.inode_table + ref.block_start);
|
||||
var meta_rdr: MetadataReader = .init(rdr.super.comp, offset_rdr.any(), rdr.alloc.allocator());
|
||||
try meta_rdr.skip(ref.offset);
|
||||
const in = try inode.readInode(meta_rdr, rdr.super.block_size, rdr.alloc.allocator());
|
||||
return .{
|
||||
.rdr = rdr,
|
||||
.inode = in,
|
||||
.name = name,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const FileOffsetReader = struct {
|
||||
file: std.fs.File,
|
||||
offset: u64,
|
||||
|
||||
pub fn init(file: std.fs.File, initial_offset: u64) FileOffsetReader {
|
||||
return .{
|
||||
.file = file,
|
||||
.offset = initial_offset,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn read(self: *FileOffsetReader, bytes: []u8) anyerror!usize {
|
||||
const red = try self.file.preadAll(bytes, self.offset);
|
||||
self.offset += @intCast(red);
|
||||
return red;
|
||||
}
|
||||
|
||||
pub fn any(self: *FileOffsetReader) std.io.AnyReader {
|
||||
return .{
|
||||
.context = @ptrCast(self),
|
||||
.readFn = readOpaque,
|
||||
};
|
||||
}
|
||||
|
||||
fn readOpaque(context: *const anyopaque, buf: []u8) anyerror!usize {
|
||||
var self: *FileOffsetReader = @constCast(@ptrCast(@alignCast(context)));
|
||||
return self.read(buf);
|
||||
}
|
||||
};
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const InodeRef = packed struct {
|
||||
offset: u16,
|
||||
block_start: u32,
|
||||
_: u16,
|
||||
};
|
||||
|
||||
pub const InodeType = enum(u16) {
|
||||
dir = 1,
|
||||
file,
|
||||
symlink,
|
||||
block_device,
|
||||
char_device,
|
||||
fifo,
|
||||
socket,
|
||||
ext_dir,
|
||||
ext_file,
|
||||
ext_symlink,
|
||||
ext_block_device,
|
||||
ext_char_device,
|
||||
ext_fifo,
|
||||
ext_socket,
|
||||
};
|
||||
|
||||
pub const InodeHeader = packed struct {
|
||||
inode_type: InodeType,
|
||||
perm: u16,
|
||||
uid_index: u16,
|
||||
gid_index: u16,
|
||||
mod_time: u32,
|
||||
inode_num: u32,
|
||||
};
|
||||
|
||||
pub const InodeData = union(enum) {
|
||||
dir: dir.DirInode,
|
||||
file: file.FileInode,
|
||||
symlink: sym.SymlinkInode,
|
||||
block_device: misc.DeviceInode,
|
||||
char_device: misc.DeviceInode,
|
||||
fifo: misc.IPCInode,
|
||||
socket: misc.IPCInode,
|
||||
ext_dir: dir.ExtDirInode,
|
||||
ext_file: file.ExtFileInode,
|
||||
ext_symlink: sym.ExtSymlinkInode,
|
||||
ext_block_device: misc.ExtDeviceInode,
|
||||
ext_char_device: misc.ExtDeviceInode,
|
||||
ext_fifo: misc.ExtIPCInode,
|
||||
ext_socket: misc.ExtIPCInode,
|
||||
};
|
||||
|
||||
const dir = @import("inode_types/dir.zig");
|
||||
const file = @import("inode_types/file.zig");
|
||||
const sym = @import("inode_types/sym.zig");
|
||||
const misc = @import("inode_types/misc.zig");
|
||||
|
||||
pub const Inode = struct {
|
||||
header: InodeHeader,
|
||||
data: InodeData,
|
||||
};
|
||||
|
||||
const io = @import("std").io;
|
||||
|
||||
pub fn readInode(rdr: io.AnyReader, block_size: u32, alloc: std.mem.Allocator) !Inode {
|
||||
const hdr = try rdr.readStruct(InodeHeader);
|
||||
return Inode{
|
||||
.header = hdr,
|
||||
.data = switch (hdr.inode_type) {
|
||||
.dir => .{
|
||||
.dir = try .init(rdr),
|
||||
},
|
||||
.ext_dir => .{
|
||||
.ext_dir = try .init(rdr, alloc),
|
||||
},
|
||||
.file => .{
|
||||
.file = try .init(rdr, block_size, alloc),
|
||||
},
|
||||
.ext_file => .{
|
||||
.ext_file = try .init(rdr, block_size, alloc),
|
||||
},
|
||||
.symlink => .{
|
||||
.symlink = try .init(rdr, alloc),
|
||||
},
|
||||
.ext_symlink => .{
|
||||
.ext_symlink = try .init(rdr, alloc),
|
||||
},
|
||||
.block_device => .{
|
||||
.block_device = try rdr.readStruct(misc.DeviceInode),
|
||||
},
|
||||
.ext_block_device => .{
|
||||
.ext_block_device = try rdr.readStruct(misc.ExtDeviceInode),
|
||||
},
|
||||
.char_device => .{
|
||||
.char_device = try rdr.readStruct(misc.DeviceInode),
|
||||
},
|
||||
.ext_char_device => .{
|
||||
.ext_char_device = try rdr.readStruct(misc.ExtDeviceInode),
|
||||
},
|
||||
.fifo => .{
|
||||
.fifo = try rdr.readStruct(misc.IPCInode),
|
||||
},
|
||||
.ext_fifo => .{
|
||||
.ext_fifo = try rdr.readStruct(misc.ExtIPCInode),
|
||||
},
|
||||
.socket => .{
|
||||
.socket = try rdr.readStruct(misc.IPCInode),
|
||||
},
|
||||
.ext_socket => .{
|
||||
.ext_socket = try rdr.readStruct(misc.ExtIPCInode),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
|
||||
pub const DirInode = packed struct {
|
||||
dir_block_start: u32,
|
||||
hard_links: u32,
|
||||
dir_table_size: u16,
|
||||
dir_block_offset: u16,
|
||||
parent_inode_num: u32,
|
||||
|
||||
pub fn init(rdr: io.AnyReader) !DirInode {
|
||||
return try rdr.readStruct(DirInode);
|
||||
}
|
||||
};
|
||||
|
||||
pub const DirIndex = struct {
|
||||
dir_header_offset: u32,
|
||||
dir_table_offset: u32,
|
||||
name_size: u32,
|
||||
name: []u8,
|
||||
|
||||
pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !DirIndex {
|
||||
var out = DirIndex{
|
||||
.dir_header_offset = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.dir_table_offset = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.name_size = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.name = undefined,
|
||||
};
|
||||
out.name = try alloc.alloc(u8, out.name_size);
|
||||
_ = try rdr.readAll(out.name);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
pub const ExtDirInode = struct {
|
||||
hard_links: u32,
|
||||
dir_table_size: u32,
|
||||
dir_block_start: u32,
|
||||
parent_inode_num: u32,
|
||||
dir_index_count: u16,
|
||||
dir_block_offset: u16,
|
||||
xattr_index: u32,
|
||||
indexes: []DirIndex,
|
||||
|
||||
pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !ExtDirInode {
|
||||
var out = ExtDirInode{
|
||||
.hard_links = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.dir_table_size = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.dir_block_start = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.parent_inode_num = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.dir_index_count = try rdr.readInt(u16, std.builtin.Endian.little),
|
||||
.dir_block_offset = try rdr.readInt(u16, std.builtin.Endian.little),
|
||||
.xattr_index = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.indexes = undefined,
|
||||
};
|
||||
out.indexes = try alloc.alloc(DirIndex, out.dir_index_count);
|
||||
var i: u16 = 0;
|
||||
while (i < out.dir_index_count) : (i += 1) {
|
||||
out.indexes[i] = try .init(rdr, alloc);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const FileInode = struct {
|
||||
start: u32,
|
||||
frag_index: u32,
|
||||
frag_block_offset: u32,
|
||||
size: u32,
|
||||
block_sizes: []const u32,
|
||||
|
||||
pub fn init(rdr: std.io.AnyReader, block_size: u32, alloc: std.mem.Allocator) !FileInode {
|
||||
var out = FileInode{
|
||||
.start = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.frag_index = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.frag_block_offset = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.size = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.block_sizes = undefined,
|
||||
};
|
||||
var block_num = out.size / block_size;
|
||||
if (out.frag_index != 0xFFFFFFFF) {
|
||||
block_num += 1;
|
||||
}
|
||||
out.block_sizes = try alloc.alloc(u32, block_num);
|
||||
_ = try rdr.readAll(std.mem.asBytes(&out.block_sizes));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
pub const ExtFileInode = struct {
|
||||
start: u64,
|
||||
size: u64,
|
||||
sparse: u64,
|
||||
hard_links: u32,
|
||||
frag_index: u32,
|
||||
frag_block_offset: u32,
|
||||
xattr_index: u32,
|
||||
block_sizes: []const u32,
|
||||
|
||||
pub fn init(rdr: std.io.AnyReader, block_size: u32, alloc: std.mem.Allocator) !ExtFileInode {
|
||||
var out = ExtFileInode{
|
||||
.start = try rdr.readInt(u64, std.builtin.Endian.little),
|
||||
.size = try rdr.readInt(u64, std.builtin.Endian.little),
|
||||
.sparse = try rdr.readInt(u64, std.builtin.Endian.little),
|
||||
.hard_links = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.frag_index = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.frag_block_offset = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.xattr_index = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.block_sizes = undefined,
|
||||
};
|
||||
var block_num = out.size / block_size;
|
||||
if (out.frag_index != 0xFFFFFFFF and out.size % block_size != 0) {
|
||||
block_num += 1;
|
||||
}
|
||||
out.block_sizes = try alloc.alloc(u32, block_num);
|
||||
_ = try rdr.readAll(std.mem.asBytes(&out.block_sizes));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
const io = @import("std").io;
|
||||
|
||||
pub const DeviceInode = packed struct {
|
||||
hard_links: u32,
|
||||
device: u32,
|
||||
};
|
||||
|
||||
pub const ExtDeviceInode = packed struct {
|
||||
hard_links: u32,
|
||||
device: u32,
|
||||
xattr_index: u32,
|
||||
};
|
||||
|
||||
pub const IPCInode = packed struct {
|
||||
hard_links: u32,
|
||||
};
|
||||
|
||||
pub const ExtIPCInode = packed struct {
|
||||
hard_links: u32,
|
||||
xattr_index: u32,
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
|
||||
pub const SymlinkInode = struct {
|
||||
hard_links: u32,
|
||||
target_size: u32,
|
||||
path: []u8,
|
||||
|
||||
pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !SymlinkInode {
|
||||
var out = SymlinkInode{
|
||||
.hard_links = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.target_size = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.path = undefined,
|
||||
};
|
||||
out.path = try alloc.alloc(u8, out.target_size + 1);
|
||||
_ = try rdr.readAll(out.path);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
pub const ExtSymlinkInode = struct {
|
||||
hard_links: u32,
|
||||
target_size: u32,
|
||||
path: []u8,
|
||||
xattr_index: u32,
|
||||
|
||||
pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !ExtSymlinkInode {
|
||||
var out = ExtSymlinkInode{
|
||||
.hard_links = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.target_size = try rdr.readInt(u32, std.builtin.Endian.little),
|
||||
.path = undefined,
|
||||
.xattr_index = undefined,
|
||||
};
|
||||
out.path = try alloc.alloc(u8, out.target_size + 1);
|
||||
_ = try rdr.readAll(out.path);
|
||||
out.xattr_index = try rdr.readInt(u32, std.builtin.Endian.little);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
|
||||
const CompressionType = @import("decompress.zig").CompressionType;
|
||||
|
||||
const MetadataHeader = packed struct {
|
||||
size: u15,
|
||||
not_compressed: bool,
|
||||
};
|
||||
|
||||
pub const MetadataReader = struct {
|
||||
rdr: std.io.AnyReader,
|
||||
alloc: std.mem.Allocator,
|
||||
decomp: CompressionType,
|
||||
curBlock: []u8,
|
||||
curOffset: u16,
|
||||
free: bool = false,
|
||||
|
||||
pub fn init(decomp: CompressionType, rdr: io.AnyReader, alloc: std.mem.Allocator) !MetadataReader {
|
||||
var out: MetadataReader = .{
|
||||
.rdr = rdr,
|
||||
.alloc = alloc,
|
||||
.decomp = decomp,
|
||||
.curBlock = &[_]u8{},
|
||||
.curOffset = 0,
|
||||
};
|
||||
try out.readNextBlock();
|
||||
return out;
|
||||
}
|
||||
pub fn deinit(self: *MetadataReader) void {
|
||||
self.alloc.free(self.curBlock);
|
||||
}
|
||||
pub fn any(self: *MetadataReader) io.AnyReader {
|
||||
return .{
|
||||
.context = @ptrCast(self),
|
||||
.readFn = readOpaque,
|
||||
};
|
||||
}
|
||||
pub fn skip(self: *MetadataReader, offset: u16) !void {
|
||||
var to_skip = offset;
|
||||
var cur_left = self.curBlock.len - self.curOffset;
|
||||
while (to_skip > cur_left) {
|
||||
to_skip -= @intCast(cur_left);
|
||||
try self.readNextBlock();
|
||||
cur_left = self.curBlock.len;
|
||||
}
|
||||
self.curOffset = to_skip;
|
||||
}
|
||||
|
||||
fn readNextBlock(self: *MetadataReader) !void {
|
||||
if (self.curBlock.len != 0) {
|
||||
self.alloc.free(self.curBlock);
|
||||
}
|
||||
self.curOffset = 0;
|
||||
const hdr = try self.rdr.readStruct(MetadataHeader);
|
||||
if (hdr.not_compressed) {
|
||||
self.curBlock = try self.alloc.alloc(u8, hdr.size);
|
||||
_ = try self.rdr.readAll(self.curBlock);
|
||||
} else {
|
||||
var limit_rdr = std.io.limitedReader(self.rdr, hdr.size);
|
||||
self.curBlock = try self.decomp.Decompress(self.alloc, limit_rdr.reader().any());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(self: *MetadataReader, bytes: []u8) anyerror!usize {
|
||||
var cur_read: usize = 0;
|
||||
var to_read: usize = 0;
|
||||
while (cur_read < bytes.len) {
|
||||
if (self.curOffset + 1 == self.curBlock.len) {
|
||||
try self.readNextBlock();
|
||||
}
|
||||
to_read = @min(bytes.len - cur_read, self.curBlock.len - self.curOffset);
|
||||
std.mem.copyForwards(u8, bytes[cur_read..], self.curBlock[self.curOffset .. self.curOffset + to_read]);
|
||||
self.curOffset += @truncate(to_read);
|
||||
cur_read += to_read;
|
||||
}
|
||||
return cur_read;
|
||||
}
|
||||
|
||||
fn readOpaque(context: *const anyopaque, bytes: []u8) anyerror!usize {
|
||||
var self: *MetadataReader = @constCast(@ptrCast(@alignCast(context)));
|
||||
return self.read(bytes);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
const std = @import("std");
|
||||
const fs = std.fs;
|
||||
|
||||
const Superblock = @import("superblock.zig").Superblock;
|
||||
const inode = @import("inode.zig");
|
||||
const MetadataReader = @import("metadata_reader.zig").MetadataReader;
|
||||
const File = @import("file.zig").File;
|
||||
const FileOffsetReader = @import("file_offset_reader.zig").FileOffsetReader;
|
||||
|
||||
pub const Reader = struct {
|
||||
super: Superblock,
|
||||
rdr: fs.File,
|
||||
root: File,
|
||||
alloc: std.heap.GeneralPurposeAllocator(.{}),
|
||||
|
||||
pub fn deinit(self: *Reader) void {
|
||||
self.rdr.close();
|
||||
// _ = self.alloc.deinit();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn newReader(filename: []const u8) !Reader {
|
||||
const file = try std.fs.cwd().openFile(filename, .{});
|
||||
errdefer file.close();
|
||||
var alloc: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
errdefer _ = alloc.deinit();
|
||||
const super = try file.reader().readStruct(Superblock);
|
||||
try super.valid();
|
||||
var offset_rdr: FileOffsetReader = .init(file, super.inode_table + super.root_inode.block_start);
|
||||
var root_reader: MetadataReader = try .init(
|
||||
super.comp,
|
||||
offset_rdr.any(),
|
||||
alloc.allocator(),
|
||||
);
|
||||
defer root_reader.deinit();
|
||||
try root_reader.skip(super.root_inode.offset);
|
||||
var out: Reader = undefined;
|
||||
out = Reader{
|
||||
.super = super,
|
||||
.rdr = file,
|
||||
.root = .{
|
||||
.inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator()),
|
||||
.name = "",
|
||||
.rdr = &out,
|
||||
},
|
||||
.alloc = alloc,
|
||||
};
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
const math = @import("std").math;
|
||||
const InodeRef = @import("inode.zig").InodeRef;
|
||||
const CompressionType = @import("decompress.zig").CompressionType;
|
||||
|
||||
pub const SuperblockError = error{
|
||||
InvalidMagic,
|
||||
InvalidLog,
|
||||
InvalidVersion,
|
||||
};
|
||||
|
||||
pub const Superblock = packed struct {
|
||||
magic: u32,
|
||||
count: u32,
|
||||
mod_time: u32,
|
||||
block_size: u32,
|
||||
frags: u32,
|
||||
comp: CompressionType,
|
||||
block_log: u16,
|
||||
flags: packed struct {
|
||||
inode_uncomp: bool,
|
||||
data_uncomp: bool,
|
||||
_unused: bool,
|
||||
frag_uncomp: bool,
|
||||
frag_always: bool,
|
||||
data_dedupe: bool,
|
||||
export_table: bool,
|
||||
xattr_uncomp: bool,
|
||||
no_xattr: bool,
|
||||
comp_options: bool,
|
||||
id_uncomp: bool,
|
||||
_padding: u5,
|
||||
},
|
||||
id_count: u16,
|
||||
ver_maj: u16,
|
||||
ver_min: u16,
|
||||
root_inode: InodeRef,
|
||||
size: u64,
|
||||
id_table: u64,
|
||||
xattr_table: u64,
|
||||
inode_table: u64,
|
||||
dir_table: u64,
|
||||
frag_table: u64,
|
||||
export_table: u64,
|
||||
|
||||
pub fn valid(self: Superblock) SuperblockError!void {
|
||||
if (self.magic != 0x73717368) {
|
||||
return SuperblockError.InvalidMagic;
|
||||
} else if (self.block_log != math.log2(self.block_size)) {
|
||||
return SuperblockError.InvalidLog;
|
||||
} else if (self.ver_maj != 4 or self.ver_min != 0) {
|
||||
return SuperblockError.InvalidVersion;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
const std = @import("std");
|
||||
const debug = std.debug;
|
||||
const squashfs = @import("squashfs.zig");
|
||||
const print = std.debug.print;
|
||||
|
||||
const testFileName = "testing/LinuxPATest.sfs";
|
||||
|
||||
test "open test file" {
|
||||
var reader = try squashfs.newReader(testFileName);
|
||||
defer reader.deinit();
|
||||
}
|
||||
Reference in New Issue
Block a user