From edfb930d8314fc6704723520089bf47ac7668316 Mon Sep 17 00:00:00 2001 From: bnuuydev Date: Thu, 16 Oct 2025 21:22:08 +0100 Subject: [PATCH 01/12] wip: upgrade to zig-master the main breakage here is caused by writergate. there's some weirdness going on to do with file paths and the build system too though, so that should be dealt with before merging. also the new writer and reader don't provide any error specificity, so we don't know why a read or a write failed now. this should also be considered: perhaps creating a custom interface is warranted? --- src/BuildInterface.zig | 2 +- src/Parser.zig | 26 +++++++++++---------- src/components/FillData.zig | 6 +++-- src/components/fs/common.zig | 28 ++++++++++++----------- src/dim.zig | 44 ++++++++++++++++++++++++++++++++---- 5 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/BuildInterface.zig b/src/BuildInterface.zig index c1aedc5..de08494 100644 --- a/src/BuildInterface.zig +++ b/src/BuildInterface.zig @@ -439,7 +439,7 @@ pub const FatFs = struct { pub const FileSystemBuilder = struct { b: *std.Build, - list: std.ArrayListUnmanaged(FileSystem.Item), + list: std.ArrayList(FileSystem.Item), pub fn init(b: *std.Build) FileSystemBuilder { return FileSystemBuilder{ diff --git a/src/Parser.zig b/src/Parser.zig index edfdc13..e38fa6b 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -208,10 +208,12 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co if (!has_includes) return content_slice; - var unescaped: std.array_list.Managed(u8) = .init(parser.arena.allocator()); - defer unescaped.deinit(); + const allocator = parser.arena.allocator(); - try unescaped.ensureTotalCapacityPrecise(content_slice.len); + var unescaped = std.ArrayList(u8).empty; + defer unescaped.deinit(allocator); + + try unescaped.ensureTotalCapacityPrecise(allocator, content_slice.len); { var i: usize = 0; @@ -220,7 +222,7 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co i += 1; if (c != '\\') { - try unescaped.append(c); + try unescaped.append(allocator, c); continue; } @@ -233,20 +235,20 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co errdefer std.log.err("invalid escape sequence: \\{s}", .{[_]u8{esc_code}}); switch (esc_code) { - 'r' => try unescaped.append('\r'), - 'n' => try unescaped.append('\n'), - 't' => try unescaped.append('\t'), - '\\' => try unescaped.append('\\'), - '\"' => try unescaped.append('\"'), - '\'' => try unescaped.append('\''), - 'e' => try unescaped.append('\x1B'), + 'r' => try unescaped.append(allocator, '\r'), + 'n' => try unescaped.append(allocator, '\n'), + 't' => try unescaped.append(allocator, '\t'), + '\\' => try unescaped.append(allocator, '\\'), + '\"' => try unescaped.append(allocator, '\"'), + '\'' => try unescaped.append(allocator, '\''), + 'e' => try unescaped.append(allocator, '\x1B'), else => return error.InvalidEscapeSequence, } } } - return try unescaped.toOwnedSlice(); + return try unescaped.toOwnedSlice(allocator); }, .comment, .directive, .whitespace => unreachable, diff --git a/src/components/FillData.zig b/src/components/FillData.zig index 82b8cb4..e5f0458 100644 --- a/src/components/FillData.zig +++ b/src/components/FillData.zig @@ -20,8 +20,10 @@ pub fn parse(ctx: dim.Context) !dim.Content { } fn render(self: *FillData, stream: *dim.BinaryStream) dim.Content.RenderError!void { - try stream.writer().writeByteNTimes( + var writer = stream.writer(); + writer.interface.splatByteAll( self.fill_value, stream.length, - ); + ) catch return error.Overflow; // TODO FIX we don't know actually why this failed. + // std.Io.Writer only returns error.WriteFailed. } diff --git a/src/components/fs/common.zig b/src/components/fs/common.zig index 0efdc7b..0faa8a0 100644 --- a/src/components/fs/common.zig +++ b/src/components/fs/common.zig @@ -159,24 +159,26 @@ fn Executor(comptime T: type) type { fn walk_err(err: (std.fs.Dir.OpenError || std.mem.Allocator.Error)) dim.Content.RenderError { return switch (err) { - error.InvalidUtf8 => error.InvalidPath, - error.InvalidWtf8 => error.InvalidPath, - error.BadPathName => error.InvalidPath, + error.InvalidUtf8, + error.InvalidWtf8, + error.BadPathName, error.NameTooLong => error.InvalidPath, error.OutOfMemory => error.OutOfMemory, error.FileNotFound => error.FileNotFound, - error.DeviceBusy => error.IoError, - error.AccessDenied => error.IoError, - error.SystemResources => error.IoError, - error.NoDevice => error.IoError, - error.Unexpected => error.IoError, - error.NetworkNotFound => error.IoError, - error.SymLinkLoop => error.IoError, - error.ProcessFdQuotaExceeded => error.IoError, - error.SystemFdQuotaExceeded => error.IoError, - error.NotDir => error.IoError, + error.DeviceBusy, + error.AccessDenied, + error.SystemResources, + error.NoDevice, + error.Unexpected, + error.NetworkNotFound, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + error.NotDir, + error.ProcessNotFound, + error.PermissionDenied, => error.IoError, error.ProcessNotFound, error.PermissionDenied, => error.IoError, diff --git a/src/dim.zig b/src/dim.zig index d96260d..0ebcaec 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -117,7 +117,7 @@ pub fn main() !u8 { var current_dir = try std.fs.cwd().openDir(".", .{}); defer current_dir.close(); - const script_source = try current_dir.readFileAlloc(gpa, script_path, max_script_size); + const script_source = try current_dir.readFileAlloc(script_path, gpa, .limited(max_script_size)); defer gpa.free(script_source); if (options.@"deps-file") |deps_file_path| { @@ -415,7 +415,7 @@ const Environment = struct { fn fetch_file(io: *const Parser.IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8 { const env: *const Environment = @fieldParentPtr("io", io); - const contents = env.include_base.readFileAlloc(allocator, path, max_script_size) catch |err| switch (err) { + const contents = env.include_base.readFileAlloc(path, allocator, .limited(max_script_size)) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.FileNotFound => { const ctx = Context{ .env = @constCast(env) }; @@ -664,6 +664,7 @@ pub const FileHandle = struct { pub const BinaryStream = struct { pub const WriteError = error{ Overflow, IoError }; + pub const WriterError = std.Io.Writer.Error; pub const ReadError = error{ Overflow, IoError }; pub const Writer = std.io.GenericWriter(*BinaryStream, WriteError, write_some); @@ -754,15 +755,48 @@ pub const BinaryStream = struct { } pub fn writer(bs: *BinaryStream) Writer { - return .{ .context = bs }; + return .{ + .interface = .{ + .vtable = &.{ + .drain = Writer.drain, + }, + .buffer = &.{}, + }, + .stream = bs, + }; } - fn write_some(stream: *BinaryStream, data: []const u8) WriteError!usize { + pub const Writer = struct { + interface: std.Io.Writer, + stream: *BinaryStream, + + pub fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); + + var written: usize = 0; + + for (data[0..data.len - 1]) |bytes| { + written += try w.stream.write_some(bytes); + } + + const pattern = data[data.len - 1]; + switch (pattern.len) { + 0 => {}, + else => for (0..splat) |_| { + written += try w.stream.write_some(pattern); + }, + } + + return written; + } + }; + + fn write_some(stream: *BinaryStream, data: []const u8) std.Io.Writer.Error!usize { const remaining_len = stream.length - stream.virtual_offset; const written_len: usize = @intCast(@min(remaining_len, data.len)); - try stream.write(stream.virtual_offset, data[0..written_len]); + stream.write(stream.virtual_offset, data[0..written_len]) catch return error.WriteFailed; stream.virtual_offset += written_len; return written_len; From f29ac60d3584ba29e8e5cc7d9ec2f43d9c72ed21 Mon Sep 17 00:00:00 2001 From: bnuuydev Date: Sun, 19 Oct 2025 19:22:29 +0100 Subject: [PATCH 02/12] fix build interface we set the cwd of dimmer to the script directory such that the run step passes the correct relative paths. this caused weirdness in zig's dependency file handling - zig expects relative paths to be relative to the project root instead of the cwd of the run step. changing paths to be absolute is a suitable workaround. --- src/BuildInterface.zig | 2 ++ src/dim.zig | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/BuildInterface.zig b/src/BuildInterface.zig index de08494..9cef777 100644 --- a/src/BuildInterface.zig +++ b/src/BuildInterface.zig @@ -32,6 +32,8 @@ pub fn createDisk(dimmer: Interface, size: u64, content: Content) std.Build.Lazy const compile_script = b.addRunArtifact(dimmer.dimmer_exe); + compile_script.setCwd(script_file.dirname()); + _ = compile_script.addPrefixedDepFileOutputArg("--deps-file=", "image.d"); compile_script.addArg(b.fmt("--size={d}", .{size})); diff --git a/src/dim.zig b/src/dim.zig index 0ebcaec..fd781bd 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -672,7 +672,7 @@ pub const BinaryStream = struct { virtual_offset: u64 = 0, - /// Max number of bytes that an be written + /// Max number of bytes that can be written length: u64, /// Constructs a BinaryStream from a slice. From d38468e5046e34e97c05e3edb41055c048c2792e Mon Sep 17 00:00:00 2001 From: Khitiara Date: Sat, 27 Dec 2025 20:37:55 -0500 Subject: [PATCH 03/12] Compiles on december zig master, untested --- build.zig.zon | 5 ++- src/Parser.zig | 5 ++- src/components/EmptyData.zig | 3 +- src/components/FillData.zig | 3 +- src/components/PasteFile.zig | 4 +- src/components/fs/FatFileSystem.zig | 17 ++++--- src/components/fs/common.zig | 24 +++++----- src/components/part/GptPartitionTable.zig | 6 +-- src/components/part/MbrPartitionTable.zig | 6 +-- src/dim.zig | 55 +++++++++++------------ 10 files changed, 65 insertions(+), 63 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index c710cf7..348fcc3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -4,8 +4,9 @@ .fingerprint = 0x9947018c924eecb2, .dependencies = .{ .zfat = .{ - .url = "git+https://github.com/ZigEmbeddedGroup/zfat.git#0571b0d8c8cc4fcb037a1d5e7ea5666cb2f83ddf", - .hash = "zfat-0.15.0-SNNK9RRqcgCLQ5mjXghbB6mokzcHORsGnY7GtbfOt2k3", + // .url = "git+https://github.com/CascadeOS/zfat#2806bfd983dd810c9c74b0ea6a63f783208518b5", + // .hash = "zfat-0.16.0-SNNK9fKtTgASssfmCblZwRMLU4pndVtwxTNhYCegBOyA", + .path = "../zfat" }, .args = .{ .url = "git+https://github.com/ikskuh/zig-args.git#8ae26b44a884ff20dca98ee84c098e8f8e94902f", diff --git a/src/Parser.zig b/src/Parser.zig index e38fa6b..734333f 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -18,13 +18,14 @@ pub const Error = Tokenizer.Error || error{ UnknownDirective, OutOfMemory, InvalidEscapeSequence, + Canceled, }; pub const IO = struct { - fetch_file_fn: *const fn (io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8, + fetch_file_fn: *const fn (io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8, resolve_variable_fn: *const fn (io: *const IO, name: []const u8) error{UnknownVariable}![]const u8, - pub fn fetch_file(io: *const IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8 { + pub fn fetch_file(io: *const IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { return io.fetch_file_fn(io, allocator, path); } diff --git a/src/components/EmptyData.zig b/src/components/EmptyData.zig index da335f0..c5ef15a 100644 --- a/src/components/EmptyData.zig +++ b/src/components/EmptyData.zig @@ -15,7 +15,8 @@ pub fn parse(ctx: dim.Context) !dim.Content { })); } -fn render(self: *EmptyData, stream: *dim.BinaryStream) dim.Content.RenderError!void { +fn render(self: *EmptyData, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { _ = self; _ = stream; + _ = io; } diff --git a/src/components/FillData.zig b/src/components/FillData.zig index e5f0458..a087cd7 100644 --- a/src/components/FillData.zig +++ b/src/components/FillData.zig @@ -19,7 +19,8 @@ pub fn parse(ctx: dim.Context) !dim.Content { })); } -fn render(self: *FillData, stream: *dim.BinaryStream) dim.Content.RenderError!void { +fn render(self: *FillData, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { + _ = io; var writer = stream.writer(); writer.interface.splatByteAll( self.fill_value, diff --git a/src/components/PasteFile.zig b/src/components/PasteFile.zig index 3cbd9e7..80e8b68 100644 --- a/src/components/PasteFile.zig +++ b/src/components/PasteFile.zig @@ -15,6 +15,6 @@ pub fn parse(ctx: dim.Context) !dim.Content { })); } -fn render(self: *PasteFile, stream: *dim.BinaryStream) dim.Content.RenderError!void { - try self.file_handle.copy_to(stream); +fn render(self: *PasteFile, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { + try self.file_handle.copy_to(io, stream); } diff --git a/src/components/fs/FatFileSystem.zig b/src/components/fs/FatFileSystem.zig index 4c35085..80a4e21 100644 --- a/src/components/fs/FatFileSystem.zig +++ b/src/components/fs/FatFileSystem.zig @@ -81,7 +81,8 @@ const Appender = struct { } }; -fn render(self: *FAT, stream: *dim.BinaryStream) dim.Content.RenderError!void { +fn render(self: *FAT, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { + fatfs.io = io; var bsd: BinaryStreamDisk = .{ .stream = stream }; const min_size, const max_size = self.format_as.get_size_limits(); @@ -154,7 +155,7 @@ fn render(self: *FAT, stream: *dim.BinaryStream) dim.Content.RenderError!void { const wrapper = AtomicOps{}; for (self.ops.items) |op| { - try op.execute(wrapper); + try op.execute(io, wrapper); } } @@ -241,7 +242,7 @@ const AtomicOps = struct { defer fs_file.close(); var fs_file_buffer: [1024]u8 = undefined; - var adapter = fs_file.writer(&fs_file_buffer); + var adapter = fs_file.writer(io, &fs_file_buffer); _ = try reader.streamRemaining(&adapter.writer); @@ -273,16 +274,17 @@ const BinaryStreamDisk = struct { return disk_getStatus(intf); } - fn disk_read(intf: *fatfs.Disk, buff: [*]u8, sector: fatfs.LBA, count: c_uint) fatfs.Disk.Error!void { + fn disk_read(intf: *fatfs.Disk, io: std.Io, buff: [*]u8, sector: fatfs.LBA, count: c_uint) fatfs.Disk.Error!void { const bsd: *BinaryStreamDisk = @fieldParentPtr("disk", intf); - bsd.stream.read(block_size * sector, buff[0 .. count * block_size]) catch |err| { + bsd.stream.read(io, block_size * sector, buff[0 .. count * block_size]) catch |err| { bsd.disk_error = err; return error.IoError; }; } - fn disk_write(intf: *fatfs.Disk, buff: [*]const u8, sector: fatfs.LBA, count: c_uint) fatfs.Disk.Error!void { + fn disk_write(intf: *fatfs.Disk, io: std.Io, buff: [*]const u8, sector: fatfs.LBA, count: c_uint) fatfs.Disk.Error!void { + _ = io; const bsd: *BinaryStreamDisk = @fieldParentPtr("disk", intf); bsd.stream.write(block_size * sector, buff[0 .. count * block_size]) catch |err| { @@ -291,7 +293,8 @@ const BinaryStreamDisk = struct { }; } - fn disk_ioctl(intf: *fatfs.Disk, cmd: fatfs.IoCtl, buff: [*]u8) fatfs.Disk.Error!void { + fn disk_ioctl(intf: *fatfs.Disk, io: std.Io, cmd: fatfs.IoCtl, buff: [*]u8) fatfs.Disk.Error!void { + _ = io; const bsd: *BinaryStreamDisk = @fieldParentPtr("disk", intf); switch (cmd) { diff --git a/src/components/fs/common.zig b/src/components/fs/common.zig index 0faa8a0..ccee9e4 100644 --- a/src/components/fs/common.zig +++ b/src/components/fs/common.zig @@ -26,9 +26,9 @@ pub const FsOperation = union(enum) { contents: dim.Content, }, - pub fn execute(op: FsOperation, executor: anytype) !void { + pub fn execute(op: FsOperation, io: std.Io, executor: anytype) !void { const exec: Executor(@TypeOf(executor)) = .init(executor); - try exec.execute(op); + try exec.execute(io, op); } }; @@ -42,7 +42,7 @@ fn Executor(comptime T: type) type { return .{ .inner = wrapped }; } - fn execute(exec: Exec, op: FsOperation) dim.Content.RenderError!void { + fn execute(exec: Exec, io: std.Io, op: FsOperation) dim.Content.RenderError!void { switch (op) { .make_dir => |data| { try exec.recursive_mkdir(data.path); @@ -53,10 +53,10 @@ fn Executor(comptime T: type) type { error.FileNotFound => return, // open() already reported the error else => |e| return e, }; - defer handle.close(); + defer handle.close(io); var buffer: [1024]u8 = undefined; - var adapter = handle.reader(&buffer); + var adapter = handle.reader(io, &buffer); try exec.add_file(data.path, &adapter.interface); }, @@ -92,10 +92,10 @@ fn Executor(comptime T: type) type { }; var file = try fname.open(); - defer file.close(); + defer file.close(io); var buffer: [1024]u8 = undefined; - var adapter = file.reader(&buffer); + var adapter = file.reader(io, &buffer); try exec.add_file(path, &adapter.interface); }, @@ -121,7 +121,7 @@ fn Executor(comptime T: type) type { var bs: dim.BinaryStream = .init_buffer(buffer); - try data.contents.render(&bs); + try data.contents.render(io, &bs); var reader: std.Io.Reader = .fixed(buffer); @@ -159,14 +159,14 @@ fn Executor(comptime T: type) type { fn walk_err(err: (std.fs.Dir.OpenError || std.mem.Allocator.Error)) dim.Content.RenderError { return switch (err) { - error.InvalidUtf8, - error.InvalidWtf8, error.BadPathName, error.NameTooLong => error.InvalidPath, error.OutOfMemory => error.OutOfMemory, error.FileNotFound => error.FileNotFound, + error.Canceled => error.Canceled, + error.DeviceBusy, error.AccessDenied, error.SystemResources, @@ -177,11 +177,7 @@ fn Executor(comptime T: type) type { error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, error.NotDir, - error.ProcessNotFound, error.PermissionDenied, => error.IoError, - error.ProcessNotFound, - error.PermissionDenied, - => error.IoError, }; } }; diff --git a/src/components/part/GptPartitionTable.zig b/src/components/part/GptPartitionTable.zig index daff951..ddeea71 100644 --- a/src/components/part/GptPartitionTable.zig +++ b/src/components/part/GptPartitionTable.zig @@ -148,7 +148,7 @@ fn parsePartition(ctx: dim.Context) !Partition { return part; } -pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderError!void { +pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { const random = std.crypto.random; const lba_len = stream.length / block_size; @@ -211,7 +211,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr try stream.write(block_size * secondary_pe_array_lba + pe_ofs, &pe_block); var sub_view = try stream.slice(offset, size); - try partition.contains.render(&sub_view); + try partition.contains.render(io, &sub_view); pe_ofs += 0x80; } @@ -273,7 +273,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr std.mem.writeInt(u32, backup_gpt_header[0x10..0x14], backup_gpt_header_crc32, .little); // CRC32 of backup header // write everything we generated to disk - try mbr.render(stream); + try mbr.render(io, stream); try stream.write(block_size, &gpt_header_block); try stream.write(block_size * secondary_pth_lba, &backup_gpt_header_block); } diff --git a/src/components/part/MbrPartitionTable.zig b/src/components/part/MbrPartitionTable.zig index 2245de4..00ecc39 100644 --- a/src/components/part/MbrPartitionTable.zig +++ b/src/components/part/MbrPartitionTable.zig @@ -137,7 +137,7 @@ fn parse_partition(ctx: dim.Context) !Partition { return part; } -pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderError!void { +pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { const last_part_id = blk: { var last: usize = 0; for (table.partitions, 0..) |p, i| { @@ -161,7 +161,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr if (table.bootloader) |bootloader| { var sector: dim.BinaryStream = .init_buffer(&boot_sector); - try bootloader.render(§or); + try bootloader.render(io, §or); const upper_limit: u64 = if (table.disk_id != null) 0x01B8 @@ -247,7 +247,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr var sub_view = try stream.slice(info.offset, info.size); - try part.contains.render(&sub_view); + try part.contains.render(io, &sub_view); } } diff --git a/src/dim.zig b/src/dim.zig index fd781bd..3aebeba 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -72,6 +72,8 @@ pub fn main() !u8 { const gpa = gpa_impl.allocator(); + var io: std.Io.Threaded = .init(gpa); + const opts = try args.parseForCurrentProcess(Options, gpa, .print); defer opts.deinit(); @@ -187,7 +189,7 @@ pub fn main() !u8 { var stream: BinaryStream = .init_file(output_file, size_limit); - try root_content.render(&stream); + try root_content.render(io.io(), &stream); } if (global_deps_file != null) { @@ -412,7 +414,7 @@ const Environment = struct { } } - fn fetch_file(io: *const Parser.IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8 { + fn fetch_file(io: *const Parser.IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { const env: *const Environment = @fieldParentPtr("io", io); const contents = env.include_base.readFileAlloc(path, allocator, .limited(max_script_size)) catch |err| switch (err) { @@ -455,8 +457,6 @@ pub const Content = struct { ConfigurationError, OutOfBounds, OutOfMemory, - ReadFailed, - WriteFailed, }; pub const GuessError = FileName.GetSizeError; @@ -470,23 +470,24 @@ pub const Content = struct { } /// Emits the content into a binary stream. - pub fn render(content: Content, stream: *BinaryStream) RenderError!void { - try content.vtable.render_fn(content.obj, stream); + pub fn render(content: Content, io: std.Io, stream: *BinaryStream) RenderError!void { + try content.vtable.render_fn(content.obj, io, stream); } pub const VTable = struct { - render_fn: *const fn (*anyopaque, *BinaryStream) RenderError!void, + render_fn: *const fn (*anyopaque, std.Io, *BinaryStream) RenderError!void, pub fn create( comptime Container: type, comptime funcs: struct { - render_fn: *const fn (*Container, *BinaryStream) RenderError!void, + render_fn: *const fn (*Container, std.Io, *BinaryStream) RenderError!void, }, ) *const VTable { const Wrap = struct { - fn render(self: *anyopaque, stream: *BinaryStream) RenderError!void { + fn render(self: *anyopaque, io: std.Io, stream: *BinaryStream) RenderError!void { return funcs.render_fn( @ptrCast(@alignCast(self)), + io, stream, ); } @@ -503,7 +504,7 @@ pub const FileName = struct { root_dir: std.fs.Dir, rel_path: []const u8, - pub const OpenError = error{ FileNotFound, InvalidPath, IoError }; + pub const OpenError = error{ FileNotFound, InvalidPath, IoError, Canceled }; pub fn open(name: FileName) OpenError!FileHandle { const file = name.root_dir.openFile(name.rel_path, .{}) catch |err| switch (err) { @@ -516,10 +517,10 @@ pub const FileName = struct { return error.FileNotFound; }, + error.Canceled => return error.Canceled, + error.NameTooLong, - error.InvalidWtf8, error.BadPathName, - error.InvalidUtf8, => return error.InvalidPath, error.NoSpaceLeft, @@ -563,10 +564,10 @@ pub const FileName = struct { return error.FileNotFound; }, + error.Canceled => return error.Canceled, + error.NameTooLong, - error.InvalidWtf8, error.BadPathName, - error.InvalidUtf8, => return error.InvalidPath, error.DeviceBusy, @@ -579,7 +580,6 @@ pub const FileName = struct { error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, error.NotDir, - error.ProcessNotFound, error.PermissionDenied, => return error.IoError, }; @@ -605,9 +605,7 @@ pub const FileName = struct { error.FileNotFound => return error.FileNotFound, error.NameTooLong, - error.InvalidWtf8, error.BadPathName, - error.InvalidUtf8, => return error.InvalidPath, error.NoSpaceLeft, @@ -636,11 +634,11 @@ pub const FileName = struct { return stat.size; } - pub fn copy_to(file: FileName, stream: *BinaryStream) (OpenError || error{ ReadFailed, WriteFailed })!void { + pub fn copy_to(file: FileName, io: std.Io, stream: *BinaryStream) (OpenError || error{ ReadFailed, WriteFailed })!void { var handle = try file.open(); - defer handle.close(); + defer handle.close(io); - var file_reader = handle.file.reader(&.{}); + var file_reader = handle.file.reader(io, &.{}); var buffer: [8192]u8 = undefined; var writer = stream.writer().adaptToNewApi(&buffer); @@ -652,20 +650,21 @@ pub const FileName = struct { pub const FileHandle = struct { file: std.fs.File, - pub fn close(fd: *FileHandle) void { + pub fn close(fd: *FileHandle, io: std.Io) void { + _ = io; fd.file.close(); fd.* = undefined; } - pub fn reader(fd: FileHandle, buffer: []u8) std.fs.File.Reader { - return fd.file.reader(buffer); + pub fn reader(fd: FileHandle, io: std.Io, buffer: []u8) std.fs.File.Reader { + return fd.file.reader(io, buffer); } }; pub const BinaryStream = struct { - pub const WriteError = error{ Overflow, IoError }; + pub const WriteError = error{ Overflow, IoError, Canceled }; pub const WriterError = std.Io.Writer.Error; - pub const ReadError = error{ Overflow, IoError }; + pub const ReadError = error{ Overflow, IoError, Canceled }; pub const Writer = std.io.GenericWriter(*BinaryStream, WriteError, write_some); backing: Backing, @@ -718,7 +717,7 @@ pub const BinaryStream = struct { }; } - pub fn read(bs: *BinaryStream, offset: u64, data: []u8) ReadError!void { + pub fn read(bs: *BinaryStream, io: std.Io, offset: u64, data: []u8) ReadError!void { const end_pos = offset + data.len; if (end_pos > bs.length) return error.Overflow; @@ -775,7 +774,7 @@ pub const BinaryStream = struct { var written: usize = 0; - for (data[0..data.len - 1]) |bytes| { + for (data[0 .. data.len - 1]) |bytes| { written += try w.stream.write_some(bytes); } @@ -882,7 +881,7 @@ pub const DiskSize = enum(u64) { const prefix, const suffix = .{ divided[0 .. divided.len - 3], - std.mem.trimRight(u8, divided[divided.len - 3 ..], "0"), + std.mem.trimEnd(u8, divided[divided.len - 3 ..], "0"), }; if (suffix.len > 0) { From 129c66e2acdab50c107218e3ec35cc2f584f80b1 Mon Sep 17 00:00:00 2001 From: Khitiara Date: Thu, 8 Jan 2026 12:52:50 -0500 Subject: [PATCH 04/12] Now works on 12/28 master --- build.zig.zon | 7 +- src/Parser.zig | 32 ++--- src/components/EmptyData.zig | 3 +- src/components/FillData.zig | 7 +- src/components/PasteFile.zig | 4 +- src/components/fs/FatFileSystem.zig | 21 ++-- src/components/fs/common.zig | 48 ++++---- src/components/part/GptPartitionTable.zig | 36 +++--- src/components/part/MbrPartitionTable.zig | 22 ++-- src/dim.zig | 136 +++++++++++----------- 10 files changed, 159 insertions(+), 157 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 348fcc3..0a7f9fe 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,11 +6,12 @@ .zfat = .{ // .url = "git+https://github.com/CascadeOS/zfat#2806bfd983dd810c9c74b0ea6a63f783208518b5", // .hash = "zfat-0.16.0-SNNK9fKtTgASssfmCblZwRMLU4pndVtwxTNhYCegBOyA", - .path = "../zfat" + .path = "../zfat", }, .args = .{ - .url = "git+https://github.com/ikskuh/zig-args.git#8ae26b44a884ff20dca98ee84c098e8f8e94902f", - .hash = "args-0.0.0-CiLiqojRAACGzDRO7A9dw7kWSchNk29caJZkXuMCb0Cn", + .path = "../zig-args", + // .url = "git+https://github.com/ikskuh/zig-args.git#8ae26b44a884ff20dca98ee84c098e8f8e94902f", + // .hash = "args-0.0.0-CiLiqojRAACGzDRO7A9dw7kWSchNk29caJZkXuMCb0Cn", }, }, .paths = .{ diff --git a/src/Parser.zig b/src/Parser.zig index 734333f..d656f73 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -22,15 +22,15 @@ pub const Error = Tokenizer.Error || error{ }; pub const IO = struct { - fetch_file_fn: *const fn (io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8, - resolve_variable_fn: *const fn (io: *const IO, name: []const u8) error{UnknownVariable}![]const u8, + fetch_file_fn: *const fn (stdio: std.Io, io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8, + resolve_variable_fn: *const fn (stdio: std.Io, io: *const IO, name: []const u8) error{UnknownVariable}![]const u8, - pub fn fetch_file(io: *const IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { - return io.fetch_file_fn(io, allocator, path); + pub fn fetch_file(io: *const IO, stdio: std.Io, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { + return io.fetch_file_fn(stdio,io, allocator, path); } - pub fn resolve_variable(io: *const IO, name: []const u8) error{UnknownVariable}![]const u8 { - return io.resolve_variable_fn(io, name); + pub fn resolve_variable(io: *const IO, stdio: std.Io, name: []const u8) error{UnknownVariable}![]const u8 { + return io.resolve_variable_fn(stdio,io, name); } }; @@ -85,10 +85,10 @@ pub fn push_source(parser: *Parser, options: struct { }; } -pub fn push_file(parser: *Parser, include_path: []const u8) !void { +pub fn push_file(parser: *Parser, stdio: std.Io, include_path: []const u8) !void { const abs_include_path = try parser.get_include_path(parser.arena.allocator(), include_path); - const file_contents = try parser.io.fetch_file(parser.arena.allocator(), abs_include_path); + const file_contents = try parser.io.fetch_file(stdio , parser.arena.allocator(), abs_include_path); const index = parser.file_stack.len; parser.file_stack.len += 1; @@ -121,14 +121,14 @@ pub fn get_include_path(parser: Parser, allocator: std.mem.Allocator, rel_includ return abs_include_path; } -pub fn next(parser: *Parser) (Error || error{UnexpectedEndOfFile})![]const u8 { - return if (try parser.next_or_eof()) |word| +pub fn next(parser: *Parser, stdio: std.Io) (Error || error{UnexpectedEndOfFile})![]const u8 { + return if (try parser.next_or_eof(stdio)) |word| word else error.UnexpectedEndOfFile; } -pub fn next_or_eof(parser: *Parser) Error!?[]const u8 { +pub fn next_or_eof(parser: *Parser, stdio: std.Io) Error!?[]const u8 { fetch_loop: while (parser.file_stack.len > 0) { const top = &parser.file_stack[parser.file_stack.len - 1]; @@ -142,7 +142,7 @@ pub fn next_or_eof(parser: *Parser) Error!?[]const u8 { switch (token.type) { .whitespace, .comment => unreachable, - .word, .variable, .string => return try parser.resolve_value( + .word, .variable, .string => return try parser.resolve_value(stdio, token.type, top.tokenizer.get_text(token), ), @@ -153,14 +153,14 @@ pub fn next_or_eof(parser: *Parser) Error!?[]const u8 { if (std.mem.eql(u8, directive, "!include")) { if (try fetch_token(&top.tokenizer)) |path_token| { const rel_include_path = switch (path_token.type) { - .word, .variable, .string => try parser.resolve_value( + .word, .variable, .string => try parser.resolve_value(stdio, path_token.type, top.tokenizer.get_text(path_token), ), .comment, .directive, .whitespace => return error.BadDirective, }; - try parser.push_file(rel_include_path); + try parser.push_file(stdio, rel_include_path); } else { return error.ExpectedIncludePath; } @@ -190,11 +190,11 @@ fn fetch_token(tok: *Tokenizer) Tokenizer.Error!?Token { } } -fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]const u8 { +fn resolve_value(parser: *Parser, stdio: std.Io, token_type: TokenType, text: []const u8) ![]const u8 { return switch (token_type) { .word => text, - .variable => try parser.io.resolve_variable( + .variable => try parser.io.resolve_variable(stdio, text[1..], ), diff --git a/src/components/EmptyData.zig b/src/components/EmptyData.zig index c5ef15a..6393a1f 100644 --- a/src/components/EmptyData.zig +++ b/src/components/EmptyData.zig @@ -8,8 +8,9 @@ const dim = @import("../dim.zig"); const EmptyData = @This(); -pub fn parse(ctx: dim.Context) !dim.Content { +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { _ = ctx; + _ = stdio; return .create_handle(undefined, .create(@This(), .{ .render_fn = render, })); diff --git a/src/components/FillData.zig b/src/components/FillData.zig index a087cd7..da01ef4 100644 --- a/src/components/FillData.zig +++ b/src/components/FillData.zig @@ -9,10 +9,10 @@ const FillData = @This(); fill_value: u8, -pub fn parse(ctx: dim.Context) !dim.Content { +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { const pf = try ctx.alloc_object(FillData); pf.* = .{ - .fill_value = try ctx.parse_integer(u8, 0), + .fill_value = try ctx.parse_integer(stdio, u8, 0), }; return .create_handle(pf, .create(@This(), .{ .render_fn = render, @@ -20,8 +20,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { } fn render(self: *FillData, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { - _ = io; - var writer = stream.writer(); + var writer = stream.writer(io); writer.interface.splatByteAll( self.fill_value, stream.length, diff --git a/src/components/PasteFile.zig b/src/components/PasteFile.zig index 80e8b68..fec4b8a 100644 --- a/src/components/PasteFile.zig +++ b/src/components/PasteFile.zig @@ -5,10 +5,10 @@ const PasteFile = @This(); file_handle: dim.FileName, -pub fn parse(ctx: dim.Context) !dim.Content { +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { const pf = try ctx.alloc_object(PasteFile); pf.* = .{ - .file_handle = try ctx.parse_file_name(), + .file_handle = try ctx.parse_file_name(stdio), }; return .create_handle(pf, .create(@This(), .{ .render_fn = render, diff --git a/src/components/fs/FatFileSystem.zig b/src/components/fs/FatFileSystem.zig index 80a4e21..c65ef3c 100644 --- a/src/components/fs/FatFileSystem.zig +++ b/src/components/fs/FatFileSystem.zig @@ -18,8 +18,8 @@ ops: std.array_list.Managed(common.FsOperation), sector_align: ?c_uint = null, cluster_size: ?u32 = null, -pub fn parse(ctx: dim.Context) !dim.Content { - const fat_type = try ctx.parse_enum(FatType); +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { + const fat_type = try ctx.parse_enum(stdio,FatType); const pf = try ctx.alloc_object(FAT); pf.* = .{ @@ -32,7 +32,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { .updater = .init(ctx, pf), }; - try common.parse_ops(ctx, "endfat", &appender); + try common.parse_ops(ctx, stdio, "endfat", &appender); try appender.updater.validate(); @@ -59,7 +59,7 @@ const Appender = struct { try self.fat.ops.append(op); } - pub fn parse_custom_op(self: *@This(), ctx: dim.Context, str_op: []const u8) !void { + pub fn parse_custom_op(self: *@This(), stdio: std.Io, ctx: dim.Context, str_op: []const u8) !void { const Op = enum { label, fats, @@ -72,11 +72,11 @@ const Appender = struct { .{str_op}, ); switch (op) { - .label => try self.updater.set(.label, try ctx.parse_string()), - .fats => try self.updater.set(.fats, try ctx.parse_enum(fatfs.FatTables)), - .@"root-size" => try self.updater.set(.rootdir_size, try ctx.parse_integer(c_uint, 0)), - .@"sector-align" => try self.updater.set(.sector_align, try ctx.parse_integer(c_uint, 0)), - .@"cluster-size" => try self.updater.set(.cluster_size, try ctx.parse_integer(u32, 0)), + .label => try self.updater.set(.label, try ctx.parse_string(stdio)), + .fats => try self.updater.set(.fats, try ctx.parse_enum(stdio, fatfs.FatTables)), + .@"root-size" => try self.updater.set(.rootdir_size, try ctx.parse_integer(stdio,c_uint, 0)), + .@"sector-align" => try self.updater.set(.sector_align, try ctx.parse_integer(stdio, c_uint, 0)), + .@"cluster-size" => try self.updater.set(.cluster_size, try ctx.parse_integer(stdio, u32, 0)), } } }; @@ -284,10 +284,9 @@ const BinaryStreamDisk = struct { } fn disk_write(intf: *fatfs.Disk, io: std.Io, buff: [*]const u8, sector: fatfs.LBA, count: c_uint) fatfs.Disk.Error!void { - _ = io; const bsd: *BinaryStreamDisk = @fieldParentPtr("disk", intf); - bsd.stream.write(block_size * sector, buff[0 .. count * block_size]) catch |err| { + bsd.stream.write(io, block_size * sector, buff[0 .. count * block_size]) catch |err| { bsd.disk_error = err; return error.IoError; }; diff --git a/src/components/fs/common.zig b/src/components/fs/common.zig index ccee9e4..71058c3 100644 --- a/src/components/fs/common.zig +++ b/src/components/fs/common.zig @@ -49,7 +49,7 @@ fn Executor(comptime T: type) type { }, .copy_file => |data| { - var handle = data.source.open() catch |err| switch (err) { + var handle = data.source.open(io) catch |err| switch (err) { error.FileNotFound => return, // open() already reported the error else => |e| return e, }; @@ -61,11 +61,11 @@ fn Executor(comptime T: type) type { try exec.add_file(data.path, &adapter.interface); }, .copy_dir => |data| { - var iter_dir = data.source.open_dir() catch |err| switch (err) { + var iter_dir = data.source.open_dir(io) catch |err| switch (err) { error.FileNotFound => return, // open() already reported the error else => |e| return e, }; - defer iter_dir.close(); + defer iter_dir.close(io); var walker_memory: [16384]u8 = undefined; var temp_allocator: std.heap.FixedBufferAllocator = .init(&walker_memory); @@ -75,7 +75,7 @@ fn Executor(comptime T: type) type { var walker = try iter_dir.walk(temp_allocator.allocator()); defer walker.deinit(); - while (walker.next() catch |err| return walk_err(err)) |entry| { + while (walker.next(io) catch |err| return walk_err(err)) |entry| { const path = std.fmt.bufPrintZ(&path_memory, "{s}/{s}", .{ data.path, entry.path, @@ -91,7 +91,7 @@ fn Executor(comptime T: type) type { .rel_path = entry.basename, }; - var file = try fname.open(); + var file = try fname.open(io); defer file.close(io); var buffer: [1024]u8 = undefined; @@ -106,8 +106,8 @@ fn Executor(comptime T: type) type { else => { var realpath_buffer: [std.fs.max_path_bytes]u8 = undefined; - std.log.warn("cannot copy file {!s}: {s} is not a supported file type!", .{ - entry.dir.realpath(entry.path, &realpath_buffer), + std.log.warn("cannot copy file {s}: {s} is not a supported file type!", .{ + if (entry.dir.realPathFile(io,entry.path, &realpath_buffer)) |l| realpath_buffer[0..l] else |e| @errorName(e), @tagName(entry.kind), }); }, @@ -157,10 +157,9 @@ fn Executor(comptime T: type) type { try exec.inner.mkdir(path); } - fn walk_err(err: (std.fs.Dir.OpenError || std.mem.Allocator.Error)) dim.Content.RenderError { + fn walk_err(err: (std.Io.Dir.OpenError || std.mem.Allocator.Error)) dim.Content.RenderError { return switch (err) { - error.BadPathName, - error.NameTooLong => error.InvalidPath, + error.BadPathName, error.NameTooLong => error.InvalidPath, error.OutOfMemory => error.OutOfMemory, error.FileNotFound => error.FileNotFound, @@ -177,14 +176,15 @@ fn Executor(comptime T: type) type { error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, error.NotDir, - error.PermissionDenied, => error.IoError, + error.PermissionDenied, + => error.IoError, }; } }; } -fn parse_path(ctx: dim.Context) ![:0]const u8 { - const path = try ctx.parse_string(); +fn parse_path(ctx: dim.Context, stdio: std.Io) ![:0]const u8 { + const path = try ctx.parse_string(stdio); if (path.len == 0) { try ctx.report_nonfatal_error("Path cannot be empty!", .{}); @@ -216,41 +216,41 @@ fn parse_path(ctx: dim.Context) ![:0]const u8 { return try normalize(ctx.get_arena(), path); } -pub fn parse_ops(ctx: dim.Context, end_seq: []const u8, handler: anytype) !void { +pub fn parse_ops(ctx: dim.Context, stdio: std.Io, end_seq: []const u8, handler: anytype) !void { while (true) { - const opsel = try ctx.parse_string(); + const opsel = try ctx.parse_string(stdio); if (std.mem.eql(u8, opsel, end_seq)) return; if (std.mem.eql(u8, opsel, "mkdir")) { - const path = try parse_path(ctx); + const path = try parse_path(ctx, stdio); try handler.append_common_op(FsOperation{ .make_dir = .{ .path = path }, }); } else if (std.mem.eql(u8, opsel, "copy-dir")) { - const path = try parse_path(ctx); - const src = try ctx.parse_file_name(); + const path = try parse_path(ctx, stdio); + const src = try ctx.parse_file_name(stdio); try handler.append_common_op(FsOperation{ .copy_dir = .{ .path = path, .source = src }, }); } else if (std.mem.eql(u8, opsel, "copy-file")) { - const path = try parse_path(ctx); - const src = try ctx.parse_file_name(); + const path = try parse_path(ctx, stdio); + const src = try ctx.parse_file_name(stdio); try handler.append_common_op(FsOperation{ .copy_file = .{ .path = path, .source = src }, }); } else if (std.mem.eql(u8, opsel, "create-file")) { - const path = try parse_path(ctx); - const size = try ctx.parse_mem_size(); - const contents = try ctx.parse_content(); + const path = try parse_path(ctx, stdio); + const size = try ctx.parse_mem_size(stdio); + const contents = try ctx.parse_content(stdio); try handler.append_common_op(FsOperation{ .create_file = .{ .path = path, .size = size, .contents = contents }, }); } else { - try handler.parse_custom_op(ctx, opsel); + try handler.parse_custom_op(stdio, ctx, opsel); } } } diff --git a/src/components/part/GptPartitionTable.zig b/src/components/part/GptPartitionTable.zig index ddeea71..0811c9d 100644 --- a/src/components/part/GptPartitionTable.zig +++ b/src/components/part/GptPartitionTable.zig @@ -10,7 +10,7 @@ disk_id: ?Guid, legacy_bootable: bool = false, partitions: []Partition, -pub fn parse(ctx: dim.Context) !dim.Content { +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { const pt = try ctx.alloc_object(PartTable); pt.* = .{ .disk_id = null, @@ -19,7 +19,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { var partitions: std.ArrayList(Partition) = .empty; loop: while (true) { - const kw = try ctx.parse_enum(enum { + const kw = try ctx.parse_enum(stdio, enum { guid, part, endgpt, @@ -27,14 +27,14 @@ pub fn parse(ctx: dim.Context) !dim.Content { }); switch (kw) { .guid => { - const guid_str = try ctx.parse_string(); + const guid_str = try ctx.parse_string(stdio); if (guid_str.len != 36) return ctx.report_fatal_error("Invalid disk GUID: wrong length", .{}); pt.disk_id = Guid.parse(guid_str[0..36].*) catch |err| return ctx.report_fatal_error("Invalid disk GUID: {}", .{err}); }, - .part => (try partitions.addOne(ctx.get_arena())).* = try parsePartition(ctx), + .part => (try partitions.addOne(ctx.get_arena())).* = try parsePartition(ctx, stdio), .@"legacy-bootable" => pt.legacy_bootable = true, .endgpt => break :loop, } @@ -74,7 +74,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { })); } -fn parsePartition(ctx: dim.Context) !Partition { +fn parsePartition(ctx: dim.Context, stdio: std.Io) !Partition { var part: Partition = .{ .type = undefined, .part_id = null, @@ -98,7 +98,7 @@ fn parsePartition(ctx: dim.Context) !Partition { }) = .init(ctx, &part); parse_loop: while (true) { - const kw = try ctx.parse_enum(enum { + const kw = try ctx.parse_enum(stdio, enum { type, name, guid, @@ -109,7 +109,7 @@ fn parsePartition(ctx: dim.Context) !Partition { }); switch (kw) { .type => { - const type_name = try ctx.parse_string(); + const type_name = try ctx.parse_string(stdio); const type_guid = known_types.get(type_name) orelse blk: { if (type_name.len == 36) if (Guid.parse(type_name[0..36].*)) |guid| break :blk guid else |_| {}; @@ -122,13 +122,13 @@ fn parsePartition(ctx: dim.Context) !Partition { try updater.set(.type, type_guid); }, .name => { - const string = try ctx.parse_string(); + const string = try ctx.parse_string(stdio); const name = stringToName(string) catch return error.BadStringLiteral; try updater.set(.name, name); }, .guid => { - const string = try ctx.parse_string(); + const string = try ctx.parse_string(stdio); if (string.len != 36) return ctx.report_fatal_error("Invalid partition GUID: wrong length", .{}); @@ -136,9 +136,9 @@ fn parsePartition(ctx: dim.Context) !Partition { return ctx.report_fatal_error("Invalid partition GUID: {}", .{err}); }); }, - .size => try updater.set(.size, try ctx.parse_mem_size()), - .offset => try updater.set(.offset, try ctx.parse_mem_size()), - .contains => try updater.set(.contains, try ctx.parse_content()), + .size => try updater.set(.size, try ctx.parse_mem_size(stdio)), + .offset => try updater.set(.offset, try ctx.parse_mem_size(stdio)), + .contains => try updater.set(.contains, try ctx.parse_content(stdio)), .endpart => break :parse_loop, } } @@ -207,8 +207,8 @@ pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Cont pe_block[0x38..].* = @bitCast(partition.name); pe_crc.update(&pe_block); - try stream.write(block_size * 2 + pe_ofs, &pe_block); - try stream.write(block_size * secondary_pe_array_lba + pe_ofs, &pe_block); + try stream.write(io, block_size * 2 + pe_ofs, &pe_block); + try stream.write(io, block_size * secondary_pe_array_lba + pe_ofs, &pe_block); var sub_view = try stream.slice(offset, size); try partition.contains.render(io, &sub_view); @@ -220,8 +220,8 @@ pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Cont @memset(&pe_block, 0); for (table.partitions.len..0x80) |_| { pe_crc.update(&pe_block); - try stream.write(block_size * 2 + pe_ofs, &pe_block); - try stream.write(block_size * secondary_pe_array_lba + pe_ofs, &pe_block); + try stream.write(io, block_size * 2 + pe_ofs, &pe_block); + try stream.write(io, block_size * secondary_pe_array_lba + pe_ofs, &pe_block); pe_ofs += 0x80; } } @@ -274,8 +274,8 @@ pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Cont // write everything we generated to disk try mbr.render(io, stream); - try stream.write(block_size, &gpt_header_block); - try stream.write(block_size * secondary_pth_lba, &backup_gpt_header_block); + try stream.write(io, block_size, &gpt_header_block); + try stream.write(io, block_size * secondary_pth_lba, &backup_gpt_header_block); } pub const Guid = extern struct { diff --git a/src/components/part/MbrPartitionTable.zig b/src/components/part/MbrPartitionTable.zig index 00ecc39..a0b7009 100644 --- a/src/components/part/MbrPartitionTable.zig +++ b/src/components/part/MbrPartitionTable.zig @@ -13,7 +13,7 @@ bootloader: ?dim.Content, disk_id: ?u32, partitions: [4]?Partition, -pub fn parse(ctx: dim.Context) !dim.Content { +pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { const pf = try ctx.alloc_object(PartTable); pf.* = .{ .bootloader = null, @@ -29,14 +29,14 @@ pub fn parse(ctx: dim.Context) !dim.Content { var next_part_id: usize = 0; var last_part_id: ?usize = null; while (next_part_id < pf.partitions.len) { - const kw = try ctx.parse_enum(enum { + const kw = try ctx.parse_enum(stdio, enum { bootloader, part, ignore, }); switch (kw) { .bootloader => { - const bootloader_content = try ctx.parse_content(); + const bootloader_content = try ctx.parse_content(stdio); if (pf.bootloader != null) { try ctx.report_nonfatal_error("mbr-part.bootloader specified twice!", .{}); } @@ -47,7 +47,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { next_part_id += 1; }, .part => { - pf.partitions[next_part_id] = try parse_partition(ctx); + pf.partitions[next_part_id] = try parse_partition(ctx, stdio); last_part_id = next_part_id; next_part_id += 1; }, @@ -83,7 +83,7 @@ pub fn parse(ctx: dim.Context) !dim.Content { })); } -fn parse_partition(ctx: dim.Context) !Partition { +fn parse_partition(ctx: dim.Context, stdio: std.Io) !Partition { var part: Partition = .{ .offset = null, .size = null, @@ -99,7 +99,7 @@ fn parse_partition(ctx: dim.Context) !Partition { }) = .init(ctx, &part); parse_loop: while (true) { - const kw = try ctx.parse_enum(enum { + const kw = try ctx.parse_enum(stdio, enum { type, bootable, size, @@ -109,7 +109,7 @@ fn parse_partition(ctx: dim.Context) !Partition { }); try switch (kw) { .type => { - const part_name = try ctx.parse_string(); + const part_name = try ctx.parse_string(stdio); const encoded = if (std.fmt.parseInt(u8, part_name, 0)) |value| value @@ -125,9 +125,9 @@ fn parse_partition(ctx: dim.Context) !Partition { try updater.set(.type, encoded); }, .bootable => updater.set(.bootable, true), - .size => updater.set(.size, try ctx.parse_mem_size()), - .offset => updater.set(.offset, try ctx.parse_mem_size()), - .contains => updater.set(.contains, try ctx.parse_content()), + .size => updater.set(.size, try ctx.parse_mem_size(stdio)), + .offset => updater.set(.offset, try ctx.parse_mem_size(stdio)), + .contains => updater.set(.contains, try ctx.parse_content(stdio)), .endpart => break :parse_loop, }; } @@ -238,7 +238,7 @@ pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Cont boot_sector[0x01FE] = 0x55; boot_sector[0x01FF] = 0xAA; - try stream.write(0, &boot_sector); + try stream.write(io,0, &boot_sector); } for (part_infos, table.partitions) |maybe_info, maybe_part| { diff --git a/src/dim.zig b/src/dim.zig index 3aebeba..2c0ea69 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -61,7 +61,7 @@ const usage = const VariableMap = std.StringArrayHashMapUnmanaged([]const u8); -var global_deps_file: ?std.fs.File = null; +var global_deps_file: ?std.Io.File = null; var global_deps_buffer: []u8 = undefined; var global_deps_file_writer: std.fs.File.Writer = undefined; var global_deps_writer: *std.Io.Writer = undefined; @@ -72,7 +72,8 @@ pub fn main() !u8 { const gpa = gpa_impl.allocator(); - var io: std.Io.Threaded = .init(gpa); + var io: std.Io.Threaded = .init(gpa, .{}); + const io_iface = io.ioBasic(); const opts = try args.parseForCurrentProcess(Options, gpa, .print); defer opts.deinit(); @@ -116,17 +117,17 @@ pub fn main() !u8 { return fatal("--size must be given!"); } - var current_dir = try std.fs.cwd().openDir(".", .{}); - defer current_dir.close(); + var current_dir = try std.Io.Dir.cwd().openDir(io_iface, ".", .{}); + defer current_dir.close(io_iface); - const script_source = try current_dir.readFileAlloc(script_path, gpa, .limited(max_script_size)); + const script_source = try current_dir.readFileAlloc(io_iface, script_path, gpa, .limited(max_script_size)); defer gpa.free(script_source); if (options.@"deps-file") |deps_file_path| { - global_deps_file = try std.fs.cwd().createFile(deps_file_path, .{}); + global_deps_file = try std.Io.Dir.cwd().createFile(io_iface, deps_file_path, .{}); global_deps_buffer = try gpa.alloc(u8, 1024); - global_deps_file_writer = global_deps_file.?.writer(global_deps_buffer); + global_deps_file_writer = global_deps_file.?.writer(io_iface, global_deps_buffer); global_deps_writer = &global_deps_file_writer.interface; try global_deps_writer.print( @@ -138,7 +139,7 @@ pub fn main() !u8 { } defer if (global_deps_file) |deps_file| { global_deps_file_writer.end() catch {}; - deps_file.close(); + deps_file.close(io_iface); gpa.free(global_deps_buffer); }; @@ -169,7 +170,7 @@ pub fn main() !u8 { .contents = script_source, }); - const root_content: Content = env.parse_content() catch |err| switch (err) { + const root_content: Content = env.parse_content(io_iface) catch |err| switch (err) { error.FatalConfigError => return 1, else => |e| return e, @@ -182,14 +183,14 @@ pub fn main() !u8 { env.mode = .execute; { - var output_file = try current_dir.createFile(output_path, .{ .read = true }); - defer output_file.close(); + var output_file = try current_dir.createFile(io_iface, output_path, .{ .read = true }); + defer output_file.close(io_iface); - try output_file.setEndPos(size_limit); + try output_file.setLength(io_iface, size_limit); var stream: BinaryStream = .init_file(output_file, size_limit); - try root_content.render(io.io(), &stream); + try root_content.render(io_iface, &stream); } if (global_deps_file != null) { @@ -203,10 +204,10 @@ pub fn main() !u8 { return 0; } -pub fn declare_file_dependency(path: []const u8) !void { +pub fn declare_file_dependency(stdio: std.Io, path: []const u8) !void { if (global_deps_file == null) return; - const stat = std.fs.cwd().statFile(path) catch |err| switch (err) { + const stat = std.Io.Dir.cwd().statFile(stdio, path, .{}) catch |err| switch (err) { error.IsDir => return, else => |e| return e, }; @@ -251,14 +252,14 @@ pub const Context = struct { return error.FatalConfigError; } - pub fn parse_string(ctx: Context) Environment.ParseError![]const u8 { - const str = try ctx.env.parser.next(); + pub fn parse_string(ctx: Context, stdio: std.Io) Environment.ParseError![]const u8 { + const str = try ctx.env.parser.next(stdio); // std.debug.print("token: '{f}'\n", .{std.zig.fmtString(str)}); return str; } - pub fn parse_file_name(ctx: Context) Environment.ParseError!FileName { - const rel_path = try ctx.parse_string(); + pub fn parse_file_name(ctx: Context, stdio: std.Io) Environment.ParseError!FileName { + const rel_path = try ctx.parse_string(stdio); const abs_path = try ctx.env.parser.get_include_path(ctx.env.arena, rel_path); @@ -269,10 +270,10 @@ pub const Context = struct { }; } - pub fn parse_enum(ctx: Context, comptime E: type) Environment.ParseError!E { + pub fn parse_enum(ctx: Context, stdio: std.Io, comptime E: type) Environment.ParseError!E { if (@typeInfo(E) != .@"enum") @compileError("parse_enum requires an enum type!"); - const tag_name = try ctx.parse_string(); + const tag_name = try ctx.parse_string(stdio); const converted = std.meta.stringToEnum( E, tag_name, @@ -292,32 +293,32 @@ pub const Context = struct { return error.InvalidEnumTag; } - pub fn parse_integer(ctx: Context, comptime I: type, base: u8) Environment.ParseError!I { + pub fn parse_integer(ctx: Context, stdio: std.Io, comptime I: type, base: u8) Environment.ParseError!I { if (@typeInfo(I) != .int) @compileError("parse_integer requires an integer type!"); return std.fmt.parseInt( I, - try ctx.parse_string(), + try ctx.parse_string(stdio), base, ) catch return error.InvalidNumber; } - pub fn parse_mem_size(ctx: Context) Environment.ParseError!u64 { - const str = try ctx.parse_string(); + pub fn parse_mem_size(ctx: Context, stdio: std.Io) Environment.ParseError!u64 { + const str = try ctx.parse_string(stdio); const ds: DiskSize = try .parse(str); return ds.size_in_bytes(); } - pub fn parse_content(ctx: Context) Environment.ParseError!Content { - const content_type_str = try ctx.env.parser.next(); + pub fn parse_content(ctx: Context, stdio: std.Io) Environment.ParseError!Content { + const content_type_str = try ctx.env.parser.next(stdio); inline for (content_types) |tn| { const name, const impl = tn; if (std.mem.eql(u8, name, content_type_str)) { - const content: Content = try impl.parse(ctx); + const content: Content = try impl.parse(ctx, stdio); return content; } @@ -390,7 +391,7 @@ const Environment = struct { arena: std.mem.Allocator, allocator: std.mem.Allocator, parser: *Parser, - include_base: std.fs.Dir, + include_base: std.Io.Dir, vars: *const VariableMap, error_flag: bool = false, mode: enum { parse, execute } = .parse, @@ -400,10 +401,10 @@ const Environment = struct { .resolve_variable_fn = resolve_var, }, - fn parse_content(env: *Environment) ParseError!Content { + fn parse_content(env: *Environment, stdio: std.Io) ParseError!Content { var ctx = Context{ .env = env }; - return try ctx.parse_content(); + return try ctx.parse_content(stdio); } fn report_error(env: *Environment, comptime fmt: []const u8, params: anytype) error{OutOfMemory}!void { @@ -414,16 +415,16 @@ const Environment = struct { } } - fn fetch_file(io: *const Parser.IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { + fn fetch_file(stdio: std.Io, io: *const Parser.IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 { const env: *const Environment = @fieldParentPtr("io", io); - const contents = env.include_base.readFileAlloc(path, allocator, .limited(max_script_size)) catch |err| switch (err) { + const contents = env.include_base.readFileAlloc(stdio, path, allocator, .limited(max_script_size)) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.FileNotFound => { const ctx = Context{ .env = @constCast(env) }; var buffer: [std.fs.max_path_bytes]u8 = undefined; try ctx.report_nonfatal_error("failed to open file: \"{f}/{f}\"", .{ - std.zig.fmtString(env.include_base.realpath(".", &buffer) catch return error.FileNotFound), + std.zig.fmtString(buffer[0 .. env.include_base.realPath(stdio, &buffer) catch return error.FileNotFound]), std.zig.fmtString(path), }); return error.FileNotFound; @@ -437,12 +438,13 @@ const Environment = struct { .root_dir = env.include_base, .rel_path = path, }; - try name.declare_dependency(); + try name.declare_dependency(stdio); return contents; } - fn resolve_var(io: *const Parser.IO, name: []const u8) error{UnknownVariable}![]const u8 { + fn resolve_var(stdio: std.Io, io: *const Parser.IO, name: []const u8) error{UnknownVariable}![]const u8 { + _ = stdio; const env: *const Environment = @fieldParentPtr("io", io); return env.vars.get(name) orelse return error.UnknownVariable; } @@ -457,13 +459,14 @@ pub const Content = struct { ConfigurationError, OutOfBounds, OutOfMemory, + Canceled, }; pub const GuessError = FileName.GetSizeError; obj: *anyopaque, vtable: *const VTable, - pub const empty: Content = @import("components/EmptyData.zig").parse(undefined) catch unreachable; + pub const empty: Content = @import("components/EmptyData.zig").parse(undefined, undefined) catch unreachable; pub fn create_handle(obj: *anyopaque, vtable: *const VTable) Content { return .{ .obj = obj, .vtable = vtable }; @@ -501,18 +504,17 @@ pub const Content = struct { pub const FileName = struct { env: *Environment, - root_dir: std.fs.Dir, + root_dir: std.Io.Dir, rel_path: []const u8, pub const OpenError = error{ FileNotFound, InvalidPath, IoError, Canceled }; - pub fn open(name: FileName) OpenError!FileHandle { - const file = name.root_dir.openFile(name.rel_path, .{}) catch |err| switch (err) { + pub fn open(name: FileName, stdio: std.Io) OpenError!FileHandle { + const file = name.root_dir.openFile(stdio, name.rel_path, .{}) catch |err| switch (err) { error.FileNotFound => { var buffer: [std.fs.max_path_bytes]u8 = undefined; name.env.report_error("failed to open \"{f}/{f}\": not found", .{ - std.zig.fmtString(name.root_dir.realpath(".", &buffer) catch |e| @errorName(e)), - std.zig.fmtString(name.rel_path), + std.zig.fmtString(if (name.root_dir.realPath(stdio, &buffer)) |l| buffer[0..l] else |e| @errorName(e)), }) catch |e| std.debug.assert(e == error.OutOfMemory); return error.FileNotFound; }, @@ -541,24 +543,23 @@ pub const FileName = struct { error.SystemFdQuotaExceeded, error.IsDir, error.NotDir, - error.FileLocksNotSupported, + error.FileLocksUnsupported, error.FileBusy, - error.ProcessNotFound, error.PermissionDenied, => return error.IoError, }; - try name.declare_dependency(); + try name.declare_dependency(stdio); return .{ .file = file }; } - pub fn open_dir(name: FileName) OpenError!std.fs.Dir { - const dir = name.root_dir.openDir(name.rel_path, .{ .iterate = true }) catch |err| switch (err) { + pub fn open_dir(name: FileName, stdio: std.Io) OpenError!std.Io.Dir { + const dir = name.root_dir.openDir(stdio, name.rel_path, .{ .iterate = true }) catch |err| switch (err) { error.FileNotFound => { var buffer: [std.fs.max_path_bytes]u8 = undefined; name.env.report_error("failed to open \"{f}/{f}\": not found", .{ - std.zig.fmtString(name.root_dir.realpath(".", &buffer) catch |e| @errorName(e)), + std.zig.fmtString(if (name.root_dir.realPath(stdio, &buffer)) |l| buffer[0..l] else |e| @errorName(e)), std.zig.fmtString(name.rel_path), }) catch |e| std.debug.assert(e == error.OutOfMemory); return error.FileNotFound; @@ -584,19 +585,20 @@ pub const FileName = struct { => return error.IoError, }; - try name.declare_dependency(); + try name.declare_dependency(stdio); return dir; } - pub fn declare_dependency(name: FileName) OpenError!void { + pub fn declare_dependency(name: FileName, stdio: std.Io) OpenError!void { var buffer: [std.fs.max_path_bytes]u8 = undefined; - const realpath = name.root_dir.realpath( + const realpath = name.root_dir.realPathFile( + stdio, name.rel_path, &buffer, ) catch |e| std.debug.panic("failed to determine real path for dependency file: {s}", .{@errorName(e)}); - declare_file_dependency(realpath) catch |e| std.debug.panic("Failed to write to deps file: {s}", .{@errorName(e)}); + declare_file_dependency(stdio, buffer[0..realpath]) catch |e| std.debug.panic("Failed to write to deps file: {s}", .{@errorName(e)}); } pub const GetSizeError = error{ FileNotFound, InvalidPath, IoError }; @@ -635,24 +637,23 @@ pub const FileName = struct { } pub fn copy_to(file: FileName, io: std.Io, stream: *BinaryStream) (OpenError || error{ ReadFailed, WriteFailed })!void { - var handle = try file.open(); + var handle = try file.open(io); defer handle.close(io); var file_reader = handle.file.reader(io, &.{}); var buffer: [8192]u8 = undefined; - var writer = stream.writer().adaptToNewApi(&buffer); + var writer = stream.writer(io).adaptToNewApi(&buffer); _ = try file_reader.interface.streamRemaining(&writer.new_interface); } }; pub const FileHandle = struct { - file: std.fs.File, + file: std.Io.File, pub fn close(fd: *FileHandle, io: std.Io) void { - _ = io; - fd.file.close(); + fd.file.close(io); fd.* = undefined; } @@ -662,10 +663,9 @@ pub const FileHandle = struct { }; pub const BinaryStream = struct { - pub const WriteError = error{ Overflow, IoError, Canceled }; + pub const WriteError = error{ Overflow, IoError }; pub const WriterError = std.Io.Writer.Error; pub const ReadError = error{ Overflow, IoError, Canceled }; - pub const Writer = std.io.GenericWriter(*BinaryStream, WriteError, write_some); backing: Backing, @@ -683,7 +683,7 @@ pub const BinaryStream = struct { } /// Constructs a BinaryStream from a file. - pub fn init_file(file: std.fs.File, max_len: u64) BinaryStream { + pub fn init_file(file: std.Io.File, max_len: u64) BinaryStream { return .{ .backing = .{ .file = .{ @@ -732,7 +732,7 @@ pub const BinaryStream = struct { } } - pub fn write(bs: *BinaryStream, offset: u64, data: []const u8) WriteError!void { + pub fn write(bs: *BinaryStream, io: std.Io, offset: u64, data: []const u8) WriteError!void { const end_pos = offset + data.len; if (end_pos > bs.length) return error.Overflow; @@ -753,7 +753,7 @@ pub const BinaryStream = struct { bs.virtual_offset = offset; } - pub fn writer(bs: *BinaryStream) Writer { + pub fn writer(bs: *BinaryStream, stdio: std.Io) Writer { return .{ .interface = .{ .vtable = &.{ @@ -762,12 +762,14 @@ pub const BinaryStream = struct { .buffer = &.{}, }, .stream = bs, + .stdio = stdio, }; } pub const Writer = struct { interface: std.Io.Writer, stream: *BinaryStream, + stdio: std.Io, pub fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); @@ -775,14 +777,14 @@ pub const BinaryStream = struct { var written: usize = 0; for (data[0 .. data.len - 1]) |bytes| { - written += try w.stream.write_some(bytes); + written += try w.stream.write_some(w.stdio, bytes); } const pattern = data[data.len - 1]; switch (pattern.len) { 0 => {}, else => for (0..splat) |_| { - written += try w.stream.write_some(pattern); + written += try w.stream.write_some(w.stdio, pattern); }, } @@ -790,12 +792,12 @@ pub const BinaryStream = struct { } }; - fn write_some(stream: *BinaryStream, data: []const u8) std.Io.Writer.Error!usize { + fn write_some(stream: *BinaryStream, stdio: std.Io, data: []const u8) std.Io.Writer.Error!usize { const remaining_len = stream.length - stream.virtual_offset; const written_len: usize = @intCast(@min(remaining_len, data.len)); - stream.write(stream.virtual_offset, data[0..written_len]) catch return error.WriteFailed; + stream.write(stdio, stream.virtual_offset, data[0..written_len]) catch return error.WriteFailed; stream.virtual_offset += written_len; return written_len; @@ -803,7 +805,7 @@ pub const BinaryStream = struct { pub const Backing = union(enum) { file: struct { - file: std.fs.File, + file: std.Io.File, base: u64, }, buffer: [*]u8, From f7f9e3d2771cb27c07ee3a101f36e1c98f94d976 Mon Sep 17 00:00:00 2001 From: Khitiara Date: Fri, 9 Jan 2026 18:56:25 -0500 Subject: [PATCH 05/12] rich main and IoSource rng --- src/components/fs/common.zig | 2 +- src/components/part/GptPartitionTable.zig | 3 ++- src/dim.zig | 12 +++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/fs/common.zig b/src/components/fs/common.zig index 71058c3..fe7048e 100644 --- a/src/components/fs/common.zig +++ b/src/components/fs/common.zig @@ -166,7 +166,7 @@ fn Executor(comptime T: type) type { error.Canceled => error.Canceled, - error.DeviceBusy, + // error.DeviceBusy, error.AccessDenied, error.SystemResources, error.NoDevice, diff --git a/src/components/part/GptPartitionTable.zig b/src/components/part/GptPartitionTable.zig index 0811c9d..9656baa 100644 --- a/src/components/part/GptPartitionTable.zig +++ b/src/components/part/GptPartitionTable.zig @@ -149,7 +149,8 @@ fn parsePartition(ctx: dim.Context, stdio: std.Io) !Partition { } pub fn render(table: *PartTable, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { - const random = std.crypto.random; + var r: std.Random.IoSource = .{ .io = io }; + const random = r.interface(); const lba_len = stream.length / block_size; const secondary_pth_lba = lba_len - 1; diff --git a/src/dim.zig b/src/dim.zig index 2c0ea69..0506064 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -66,16 +66,15 @@ var global_deps_buffer: []u8 = undefined; var global_deps_file_writer: std.fs.File.Writer = undefined; var global_deps_writer: *std.Io.Writer = undefined; -pub fn main() !u8 { +pub fn main(init: std.process.Init) !u8 { var gpa_impl: std.heap.DebugAllocator(.{}) = .init; defer _ = gpa_impl.deinit(); const gpa = gpa_impl.allocator(); - var io: std.Io.Threaded = .init(gpa, .{}); - const io_iface = io.ioBasic(); + const io_iface = init.io; - const opts = try args.parseForCurrentProcess(Options, gpa, .print); + const opts = try args.parseForCurrentProcess(Options, gpa, init.minimal.args, .print); defer opts.deinit(); const options = opts.options; @@ -86,8 +85,7 @@ pub fn main() !u8 { var var_map: VariableMap = .empty; defer var_map.deinit(gpa); - var env_map = try std.process.getEnvMap(gpa); - defer env_map.deinit(); + var env_map = init.environ_map; if (options.@"import-env") { var iter = env_map.iterator(); @@ -571,7 +569,7 @@ pub const FileName = struct { error.BadPathName, => return error.InvalidPath, - error.DeviceBusy, + // error.DeviceBusy, error.AccessDenied, error.SystemResources, error.NoDevice, From 1d667b1daa3c6b4bc3870ff763a29ec58d8a20db Mon Sep 17 00:00:00 2001 From: Khitiara Date: Mon, 19 Jan 2026 16:40:19 -0500 Subject: [PATCH 06/12] support setting part GUID --- src/BuildInterface.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/BuildInterface.zig b/src/BuildInterface.zig index 9cef777..6a69f04 100644 --- a/src/BuildInterface.zig +++ b/src/BuildInterface.zig @@ -185,6 +185,9 @@ const ContentWriter = struct { if (part.name) |name| { try cw.code.print(" name \"{f}\"\n", .{std.zig.fmtString(name)}); } + if (part.part_guid) |pg| { + try cw.code.print(" guid \"{s}\"", .{&pg}); + } if (part.offset) |offset| { try cw.code.print(" offset {d}\n", .{offset}); } @@ -416,6 +419,7 @@ pub const GptPartTable = struct { guid: [36]u8, }, name: ?[]const u8 = null, + part_guid: ?[36]u8 = null, size: ?u64 = null, offset: ?u64 = null, data: Content, From 0235548fe736d8be7cfd27a8143e291a4b3784df Mon Sep 17 00:00:00 2001 From: Khitiara Date: Tue, 3 Feb 2026 22:19:37 -0500 Subject: [PATCH 07/12] fixup compile errors after rebase --- src/BuildInterface.zig | 38 +++++++++++++++-------------- src/components/FillData.zig | 2 +- src/components/fs/FatFileSystem.zig | 6 ++--- src/dim.zig | 22 ++++++++--------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/BuildInterface.zig b/src/BuildInterface.zig index 6a69f04..83e3b44 100644 --- a/src/BuildInterface.zig +++ b/src/BuildInterface.zig @@ -26,7 +26,7 @@ pub fn createDisk(dimmer: Interface, size: u64, content: Content) std.Build.Lazy const write_files = b.addWriteFiles(); - const script_source, const variables = renderContent(write_files, b.allocator, content); + const script_source, const variables = renderContent(write_files, b.allocator, content, dimmer.builder.graph.io); const script_file = write_files.add("image.dis", script_source); @@ -69,6 +69,7 @@ fn renderContent( wfs: *std.Build.Step.WriteFile, allocator: std.mem.Allocator, content: Content, + io: std.Io, ) struct { []const u8, ContentWriter.VariableMap } { var code: std.Io.Writer.Allocating = .init(allocator); defer code.deinit(); @@ -81,7 +82,7 @@ fn renderContent( .vars = &variables, }; - cw.render(content) catch @panic("out of memory"); + cw.render(content, io) catch @panic("out of memory"); const source = std.mem.trim( u8, @@ -109,7 +110,7 @@ const ContentWriter = struct { code: *std.Io.Writer, vars: *VariableMap, - fn render(cw: ContentWriter, content: Content) !void { + fn render(cw: ContentWriter, content: Content, io: std.Io) !void { // Always insert some padding before and after: try cw.code.writeAll(" "); errdefer cw.code.writeAll(" ") catch {}; @@ -124,7 +125,7 @@ const ContentWriter = struct { }, .paste_file => |data| { - try cw.code.print("paste-file {f}", .{cw.fmtLazyPath(data, .file)}); + try cw.code.print("paste-file {f}", .{cw.fmtLazyPath(data, .file, io)}); }, .mbr_part_table => |data| { @@ -132,7 +133,7 @@ const ContentWriter = struct { if (data.bootloader) |loader| { try cw.code.writeAll(" bootloader "); - try cw.render(loader.*); + try cw.render(loader.*, io); try cw.code.writeAll("\n"); } @@ -153,7 +154,7 @@ const ContentWriter = struct { try cw.code.print(" size {d}\n", .{size}); } try cw.code.writeAll(" contains"); - try cw.render(part.data); + try cw.render(part.data, io); try cw.code.writeAll("\n"); try cw.code.writeAll(" endpart\n"); } else { @@ -195,7 +196,7 @@ const ContentWriter = struct { try cw.code.print(" size {d}\n", .{size}); } try cw.code.writeAll(" contains"); - try cw.render(part.data); + try cw.render(part.data, io); try cw.code.writeAll("\n"); try cw.code.writeAll(" endpart\n"); } @@ -213,14 +214,14 @@ const ContentWriter = struct { }); } - try cw.renderFileSystemTree(data.tree); + try cw.renderFileSystemTree(data.tree, io); try cw.code.writeAll("endfat\n"); }, } } - fn renderFileSystemTree(cw: ContentWriter, fs: FileSystem) !void { + fn renderFileSystemTree(cw: ContentWriter, fs: FileSystem, io: std.Io) !void { for (fs.items) |item| { switch (item) { .empty_dir => |dir| try cw.code.print("mkdir {f}\n", .{ @@ -229,16 +230,16 @@ const ContentWriter = struct { .copy_dir => |copy| try cw.code.print("copy-dir {f} {f}\n", .{ fmtPath(copy.destination), - cw.fmtLazyPath(copy.source, .directory), + cw.fmtLazyPath(copy.source, .directory, io), }), .copy_file => |copy| try cw.code.print("copy-file {f} {f}\n", .{ fmtPath(copy.destination), - cw.fmtLazyPath(copy.source, .file), + cw.fmtLazyPath(copy.source, .file, io), }), .include_script => |script| try cw.code.print("!include {f}\n", .{ - cw.fmtLazyPath(script, .file), + cw.fmtLazyPath(script, .file, io), }), } } @@ -285,7 +286,7 @@ const ContentWriter = struct { } }; const LazyPathFormatter = std.fmt.Alt( - struct { ContentWriter, std.Build.LazyPath, UsageHint }, + struct { ContentWriter, std.Build.LazyPath, UsageHint, std.Io }, formatLazyPath, ); const UsageHint = enum { file, directory }; @@ -294,8 +295,9 @@ const ContentWriter = struct { cw: ContentWriter, path: std.Build.LazyPath, hint: UsageHint, + io: std.Io, ) LazyPathFormatter { - return .{ .data = .{ cw, path, hint } }; + return .{ .data = .{ cw, path, hint, io } }; } fn fmtPath(path: []const u8) PathFormatter { @@ -303,10 +305,10 @@ const ContentWriter = struct { } fn formatLazyPath( - data: struct { ContentWriter, std.Build.LazyPath, UsageHint }, + data: struct { ContentWriter, std.Build.LazyPath, UsageHint, std.Io }, writer: *std.Io.Writer, ) std.Io.Writer.Error!void { - const cw, const path, const hint = data; + const cw, const path, const hint, const io = data; switch (path) { .cwd_relative, @@ -319,12 +321,12 @@ const ContentWriter = struct { const rel_path = path.getPath2(cw.wfs.step.owner, &cw.wfs.step); const full_path = if (!std.fs.path.isAbsolute(rel_path)) - std.fs.cwd().realpathAlloc(cw.wfs.step.owner.allocator, rel_path) catch @panic("oom") + std.Io.Dir.cwd().realPathFileAlloc(io, rel_path, cw.wfs.step.owner.allocator) catch @panic("oom") else rel_path; if (!std.fs.path.isAbsolute(full_path)) { - const cwd = std.fs.cwd().realpathAlloc(cw.wfs.step.owner.allocator, ".") catch @panic("oom"); + const cwd = std.Io.Dir.cwd().realPathFileAlloc(io, ".", cw.wfs.step.owner.allocator) catch @panic("oom"); std.debug.print("non-absolute path detected for {t}: cwd=\"{f}\" path=\"{f}\"\n", .{ path, std.zig.fmtString(cwd), diff --git a/src/components/FillData.zig b/src/components/FillData.zig index da01ef4..f902471 100644 --- a/src/components/FillData.zig +++ b/src/components/FillData.zig @@ -20,7 +20,7 @@ pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content { } fn render(self: *FillData, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void { - var writer = stream.writer(io); + var writer = stream.writer(io, &.{}); writer.interface.splatByteAll( self.fill_value, stream.length, diff --git a/src/components/fs/FatFileSystem.zig b/src/components/fs/FatFileSystem.zig index c65ef3c..3149bee 100644 --- a/src/components/fs/FatFileSystem.zig +++ b/src/components/fs/FatFileSystem.zig @@ -242,11 +242,11 @@ const AtomicOps = struct { defer fs_file.close(); var fs_file_buffer: [1024]u8 = undefined; - var adapter = fs_file.writer(io, &fs_file_buffer); + var adapter = fs_file.writer( &fs_file_buffer); - _ = try reader.streamRemaining(&adapter.writer); + _ = try reader.streamRemaining(&adapter.interface); - try adapter.writer.flush(); + try adapter.interface.flush(); } }; diff --git a/src/dim.zig b/src/dim.zig index 0506064..88e5c9f 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -63,7 +63,7 @@ const VariableMap = std.StringArrayHashMapUnmanaged([]const u8); var global_deps_file: ?std.Io.File = null; var global_deps_buffer: []u8 = undefined; -var global_deps_file_writer: std.fs.File.Writer = undefined; +var global_deps_file_writer: std.Io.File.Writer = undefined; var global_deps_writer: *std.Io.Writer = undefined; pub fn main(init: std.process.Init) !u8 { @@ -453,7 +453,7 @@ const Environment = struct { /// /// pub const Content = struct { - pub const RenderError = FileName.OpenError || std.Io.Reader.Error || BinaryStream.WriteError || error{ + pub const RenderError = FileName.OpenError || std.Io.Reader.Error || std.Io.Writer.Error || BinaryStream.WriteError || error{ ConfigurationError, OutOfBounds, OutOfMemory, @@ -511,7 +511,7 @@ pub const FileName = struct { const file = name.root_dir.openFile(stdio, name.rel_path, .{}) catch |err| switch (err) { error.FileNotFound => { var buffer: [std.fs.max_path_bytes]u8 = undefined; - name.env.report_error("failed to open \"{f}/{f}\": not found", .{ + name.env.report_error("failed to open \"{f}\": not found", .{ std.zig.fmtString(if (name.root_dir.realPath(stdio, &buffer)) |l| buffer[0..l] else |e| @errorName(e)), }) catch |e| std.debug.assert(e == error.OutOfMemory); return error.FileNotFound; @@ -641,9 +641,9 @@ pub const FileName = struct { var file_reader = handle.file.reader(io, &.{}); var buffer: [8192]u8 = undefined; - var writer = stream.writer(io).adaptToNewApi(&buffer); + var writer = stream.writer(io,&buffer); - _ = try file_reader.interface.streamRemaining(&writer.new_interface); + _ = try file_reader.interface.streamRemaining(&writer.interface); } }; @@ -655,7 +655,7 @@ pub const FileHandle = struct { fd.* = undefined; } - pub fn reader(fd: FileHandle, io: std.Io, buffer: []u8) std.fs.File.Reader { + pub fn reader(fd: FileHandle, io: std.Io, buffer: []u8) std.Io.File.Reader { return fd.file.reader(io, buffer); } }; @@ -723,7 +723,7 @@ pub const BinaryStream = struct { switch (bs.backing) { .buffer => |ptr| @memcpy(data, ptr[@intCast(offset)..][0..data.len]), .file => |state| { - const len = state.file.pread(data, state.base + offset) catch return error.IoError; + const len = state.file.readPositionalAll(io, data, state.base + offset) catch return error.IoError; if (len != data.len) return error.Overflow; }, @@ -738,9 +738,7 @@ pub const BinaryStream = struct { switch (bs.backing) { .buffer => |ptr| @memcpy(ptr[@intCast(offset)..][0..data.len], data), .file => |state| { - const len = state.file.pwrite(data, state.base + offset) catch return error.IoError; - if (len != data.len) - return error.Overflow; + state.file.writePositionalAll(io,data, state.base + offset) catch return error.IoError; }, } } @@ -751,13 +749,13 @@ pub const BinaryStream = struct { bs.virtual_offset = offset; } - pub fn writer(bs: *BinaryStream, stdio: std.Io) Writer { + pub fn writer(bs: *BinaryStream, stdio: std.Io, buffer: []u8) Writer { return .{ .interface = .{ .vtable = &.{ .drain = Writer.drain, }, - .buffer = &.{}, + .buffer = buffer, }, .stream = bs, .stdio = stdio, From a88dc6c98da266e21f29d7714fbba5cbea403687 Mon Sep 17 00:00:00 2001 From: Khitiara Date: Tue, 3 Feb 2026 22:34:06 -0500 Subject: [PATCH 08/12] dependencies fixed to not be local --- build.zig.zon | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 0a7f9fe..9961fd3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -4,14 +4,12 @@ .fingerprint = 0x9947018c924eecb2, .dependencies = .{ .zfat = .{ - // .url = "git+https://github.com/CascadeOS/zfat#2806bfd983dd810c9c74b0ea6a63f783208518b5", - // .hash = "zfat-0.16.0-SNNK9fKtTgASssfmCblZwRMLU4pndVtwxTNhYCegBOyA", - .path = "../zfat", + .url = "git+https://github.com/khitiara/zfat?ref=0.15#4ce2a6a95d4410573dcc1c159085f554465aea04", + .hash = "zfat-0.15.0-SNNK9QCZcgBdWwpwf_lzSuKP12w2HZQnIQwT4qn8TfZi", }, .args = .{ - .path = "../zig-args", - // .url = "git+https://github.com/ikskuh/zig-args.git#8ae26b44a884ff20dca98ee84c098e8f8e94902f", - // .hash = "args-0.0.0-CiLiqojRAACGzDRO7A9dw7kWSchNk29caJZkXuMCb0Cn", + .url = "git+https://github.com/khitiara/zig-args#4085c9be55dfd2eeb6893694510a2ce97e89f9fe", + .hash = "args-0.0.0-CiLiqiLSAAArS0NVwnYLAarU-u1csj8zAkg5-q4pa1n8", }, }, .paths = .{ From b57c14312be53810263f459035bc382cc4ea79de Mon Sep 17 00:00:00 2001 From: Khitiara Date: Tue, 3 Feb 2026 22:35:02 -0500 Subject: [PATCH 09/12] missed a bit --- src/components/fs/FatFileSystem.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/fs/FatFileSystem.zig b/src/components/fs/FatFileSystem.zig index 3149bee..13b3490 100644 --- a/src/components/fs/FatFileSystem.zig +++ b/src/components/fs/FatFileSystem.zig @@ -244,9 +244,9 @@ const AtomicOps = struct { var fs_file_buffer: [1024]u8 = undefined; var adapter = fs_file.writer( &fs_file_buffer); - _ = try reader.streamRemaining(&adapter.interface); + _ = try reader.streamRemaining(&adapter.writer); - try adapter.interface.flush(); + try adapter.writer.flush(); } }; From f609bc9e35308e83cfb96f0e02ea1d211d0f1386 Mon Sep 17 00:00:00 2001 From: Khitiara Date: Thu, 5 Feb 2026 12:48:48 -0500 Subject: [PATCH 10/12] I hate this -_- --- src/dim.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/dim.zig b/src/dim.zig index 88e5c9f..880e4e0 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -128,11 +128,14 @@ pub fn main(init: std.process.Init) !u8 { global_deps_file_writer = global_deps_file.?.writer(io_iface, global_deps_buffer); global_deps_writer = &global_deps_file_writer.interface; + const script_realpath = current_dir.realPathFileAlloc(io_iface, script_path, gpa) catch |e| std.debug.panic("failed to determine real path for dependency file: {s}", .{@errorName(e)}); + defer gpa.free(script_realpath); + try global_deps_writer.print( \\{s}: {s} , .{ output_path, - script_path, + script_realpath, }); } defer if (global_deps_file) |deps_file| { @@ -641,7 +644,7 @@ pub const FileName = struct { var file_reader = handle.file.reader(io, &.{}); var buffer: [8192]u8 = undefined; - var writer = stream.writer(io,&buffer); + var writer = stream.writer(io, &buffer); _ = try file_reader.interface.streamRemaining(&writer.interface); } @@ -738,7 +741,7 @@ pub const BinaryStream = struct { switch (bs.backing) { .buffer => |ptr| @memcpy(ptr[@intCast(offset)..][0..data.len], data), .file => |state| { - state.file.writePositionalAll(io,data, state.base + offset) catch return error.IoError; + state.file.writePositionalAll(io, data, state.base + offset) catch return error.IoError; }, } } From eb19d8483a922ef756a1f3e99cb08205af9bbc2f Mon Sep 17 00:00:00 2001 From: Khitiara Date: Mon, 9 Feb 2026 22:10:07 -0500 Subject: [PATCH 11/12] make it work on windows --- src/BuildInterface.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BuildInterface.zig b/src/BuildInterface.zig index 83e3b44..feee4d4 100644 --- a/src/BuildInterface.zig +++ b/src/BuildInterface.zig @@ -39,7 +39,7 @@ pub fn createDisk(dimmer: Interface, size: u64, content: Content) std.Build.Lazy compile_script.addArg(b.fmt("--size={d}", .{size})); compile_script.addPrefixedFileArg("--script=", script_file); - compile_script.addPrefixedDirectoryArg("--script-root=", .{ .cwd_relative = "." }); + // compile_script.addPrefixedDirectoryArg("--script-root=", .{ .cwd_relative = "." }); const result_file = compile_script.addPrefixedOutputFileArg("--output=", "disk.img"); From 33195eb4ad7054221115d29ff4c5021e4e805a8b Mon Sep 17 00:00:00 2001 From: Khitiara Date: Sat, 14 Feb 2026 22:26:38 -0500 Subject: [PATCH 12/12] zig-master 2026-02-13 updates --- .gitignore | 1 + src/dim.zig | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dfe5b37..7599683 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .zig-cache/ zig-out/ +zig-pkg/ .vscode/ .dim-out/ \ No newline at end of file diff --git a/src/dim.zig b/src/dim.zig index 880e4e0..ea31ae1 100644 --- a/src/dim.zig +++ b/src/dim.zig @@ -534,7 +534,6 @@ pub const FileName = struct { error.WouldBlock, error.NoDevice, error.Unexpected, - error.SharingViolation, error.PathAlreadyExists, error.PipeBusy, error.NetworkNotFound,