Proper zig project organization
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const lib_mod = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/root.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
const lib = b.addLibrary(.{
|
||||||
|
.linkage = .static,
|
||||||
|
.name = "zig_squashfs",
|
||||||
|
.root_module = lib_mod,
|
||||||
|
});
|
||||||
|
b.installArtifact(lib);
|
||||||
|
const lib_unit_tests = b.addTest(.{
|
||||||
|
.root_module = lib_mod,
|
||||||
|
});
|
||||||
|
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||||
|
const test_step = b.step("test", "Run unit tests");
|
||||||
|
test_step.dependOn(&run_lib_unit_tests.step);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
.{
|
||||||
|
.name = .zig_squashfs,
|
||||||
|
.version = "0.0.0",
|
||||||
|
.fingerprint = 0x527960c72c03ffe3, // Changing this has security and trust implications.
|
||||||
|
|
||||||
|
.minimum_zig_version = "0.14.0",
|
||||||
|
|
||||||
|
// This field is optional.
|
||||||
|
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||||
|
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
||||||
|
// Once all dependencies are fetched, `zig build` no longer requires
|
||||||
|
// internet connectivity.
|
||||||
|
.dependencies = .{
|
||||||
|
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
||||||
|
//.example = .{
|
||||||
|
// // When updating this field to a new URL, be sure to delete the corresponding
|
||||||
|
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
||||||
|
// // the new URL. If the contents of a URL change this will result in a hash mismatch
|
||||||
|
// // which will prevent zig from using it.
|
||||||
|
// .url = "https://example.com/foo.tar.gz",
|
||||||
|
//
|
||||||
|
// // This is computed from the file contents of the directory of files that is
|
||||||
|
// // obtained after fetching `url` and applying the inclusion rules given by
|
||||||
|
// // `paths`.
|
||||||
|
// //
|
||||||
|
// // This field is the source of truth; packages do not come from a `url`; they
|
||||||
|
// // come from a `hash`. `url` is just one of many possible mirrors for how to
|
||||||
|
// // obtain a package matching this `hash`.
|
||||||
|
// //
|
||||||
|
// // Uses the [multihash](https://multiformats.io/multihash/) format.
|
||||||
|
// .hash = "...",
|
||||||
|
//
|
||||||
|
// // When this is provided, the package is found in a directory relative to the
|
||||||
|
// // build root. In this case the package's hash is irrelevant and therefore not
|
||||||
|
// // computed. This field and `url` are mutually exclusive.
|
||||||
|
// .path = "foo",
|
||||||
|
//
|
||||||
|
// // When this is set to `true`, a package is declared to be lazily
|
||||||
|
// // fetched. This makes the dependency only get fetched if it is
|
||||||
|
// // actually used.
|
||||||
|
// .lazy = false,
|
||||||
|
//},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Specifies the set of files and directories that are included in this package.
|
||||||
|
// Only files and directories listed here are included in the `hash` that
|
||||||
|
// is computed for this package. Only files listed here will remain on disk
|
||||||
|
// when using the zig package manager. As a rule of thumb, one should list
|
||||||
|
// files required for compilation plus any license(s).
|
||||||
|
// Paths are relative to the build root. Use the empty string (`""`) to refer to
|
||||||
|
// the build root itself.
|
||||||
|
// A directory listed here means that all files within, recursively, are included.
|
||||||
|
.paths = .{
|
||||||
|
"build.zig",
|
||||||
|
"build.zig.zon",
|
||||||
|
"src",
|
||||||
|
// For example...
|
||||||
|
//"LICENSE",
|
||||||
|
//"README.md",
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
const inode = @import("inode.zig");
|
|
||||||
const Reader = @import("squashfs.zig").Reader;
|
|
||||||
const MetadataReader = @import("metadata_reader.zig").MetadataReader;
|
|
||||||
|
|
||||||
pub const File = struct {
|
|
||||||
rdr: *Reader,
|
|
||||||
inode: inode.Inode,
|
|
||||||
name: []const u8,
|
|
||||||
dir_entries: []const void = undefined, //TODO
|
|
||||||
|
|
||||||
pub fn fromRef(ref: inode.InodeRef, rdr: *Reader) !File {
|
|
||||||
var meta_rdr: MetadataReader = .init(rdr.super.comp, rdr: io.AnyReader, alloc: std.mem.Allocator)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const FileOffsetReader = struct {
|
|
||||||
file: std.fs.File,
|
|
||||||
|
|
||||||
pub fn any(self: *FileOffsetReader) !std.io.AnyReader {}
|
|
||||||
};
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -5,6 +5,7 @@ const Superblock = @import("superblock.zig").Superblock;
|
|||||||
const inode = @import("inode.zig");
|
const inode = @import("inode.zig");
|
||||||
const MetadataReader = @import("metadata_reader.zig").MetadataReader;
|
const MetadataReader = @import("metadata_reader.zig").MetadataReader;
|
||||||
const File = @import("file.zig").File;
|
const File = @import("file.zig").File;
|
||||||
|
const FileOffsetReader = @import("file_offset_reader.zig").FileOffsetReader;
|
||||||
|
|
||||||
pub const Reader = struct {
|
pub const Reader = struct {
|
||||||
super: Superblock,
|
super: Superblock,
|
||||||
@@ -25,15 +26,24 @@ pub fn newReader(filename: []const u8) !Reader {
|
|||||||
errdefer _ = alloc.deinit();
|
errdefer _ = alloc.deinit();
|
||||||
const super = try file.reader().readStruct(Superblock);
|
const super = try file.reader().readStruct(Superblock);
|
||||||
try super.valid();
|
try super.valid();
|
||||||
try file.seekTo(super.inode_table + super.root_inode.block_start);
|
var offset_rdr: FileOffsetReader = .init(file, super.inode_table + super.root_inode.block_start);
|
||||||
var root_reader: MetadataReader = try .init(super.comp, file.reader().any(), alloc.allocator());
|
var root_reader: MetadataReader = try .init(
|
||||||
|
super.comp,
|
||||||
|
offset_rdr.any(),
|
||||||
|
alloc.allocator(),
|
||||||
|
);
|
||||||
defer root_reader.deinit();
|
defer root_reader.deinit();
|
||||||
try root_reader.skip(super.root_inode.offset);
|
try root_reader.skip(super.root_inode.offset);
|
||||||
const root_inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator());
|
var out: Reader = undefined;
|
||||||
return Reader{
|
out = Reader{
|
||||||
.super = super,
|
.super = super,
|
||||||
.rdr = file,
|
.rdr = file,
|
||||||
.root = root_inode,
|
.root = .{
|
||||||
|
.inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator()),
|
||||||
|
.name = "",
|
||||||
|
.rdr = &out,
|
||||||
|
},
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
};
|
};
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user