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 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,
|
||||
@@ -25,15 +26,24 @@ pub fn newReader(filename: []const u8) !Reader {
|
||||
errdefer _ = alloc.deinit();
|
||||
const super = try file.reader().readStruct(Superblock);
|
||||
try super.valid();
|
||||
try file.seekTo(super.inode_table + super.root_inode.block_start);
|
||||
var root_reader: MetadataReader = try .init(super.comp, file.reader().any(), alloc.allocator());
|
||||
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);
|
||||
const root_inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator());
|
||||
return Reader{
|
||||
var out: Reader = undefined;
|
||||
out = Reader{
|
||||
.super = super,
|
||||
.rdr = file,
|
||||
.root = root_inode,
|
||||
.root = .{
|
||||
.inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator()),
|
||||
.name = "",
|
||||
.rdr = &out,
|
||||
},
|
||||
.alloc = alloc,
|
||||
};
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user