authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-05-07 20:44:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:29-07:00
logd603121dc355fee44b86a7fdf3666dce6e3ab677
treec4821a2aaa16861003b419182fca53b2c9d2ff52
parent01b580e75d2d57e315545f63cbea51ebdaaa54d4

std.crypto.Certificate.Bundle.macos: rework

- use ArrayList strategically to reduce allocations - use a BufferedReader to avoid unnecessary memcpy of the certs - use for loops - skip certs with invalid magic instead of asserting

10 files changed, 142 insertions(+), 106 deletions(-)

lib/std/crypto/Certificate/Bundle/macos.zig+34-34
...@@ -16,64 +16,64 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {...@@ -16,64 +16,64 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {
16 "/Library/Keychains/System.keychain",16 "/Library/Keychains/System.keychain",
17 };17 };
1818
19 for (keychainPaths) |keychainPath| {19 const now_sec = std.time.timestamp();
20 const file = try fs.openFileAbsolute(keychainPath, .{});
21 defer file.close();
2220
23 const bytes = try file.readToEndAlloc(gpa, std.math.maxInt(u32));21 var records: std.ArrayListUnmanaged(u32) = .empty;
24 defer gpa.free(bytes);22 defer records.deinit(gpa);
2523
26 var stream = std.io.fixedBufferStream(bytes);24 var tables: std.ArrayListUnmanaged(u32) = .empty;
27 const reader = stream.reader();25 defer tables.deinit(gpa);
2826
29 const db_header = try reader.readStructEndian(ApplDbHeader, .big);27 for (keychainPaths) |keychainPath| {
30 assert(mem.eql(u8, &db_header.signature, "kych"));28 const file = try fs.openFileAbsolute(keychainPath, .{});
29 defer file.close();
3130
32 try stream.seekTo(db_header.schema_offset);31 var in_buffer: [256]u8 = undefined;
32 comptime assert(in_buffer.len > @sizeOf(ApplDbHeader));
33 comptime assert(in_buffer.len > @sizeOf(ApplDbSchema));
34 comptime assert(in_buffer.len > @sizeOf(TableHeader));
35 comptime assert(in_buffer.len > @sizeOf(X509CertHeader));
36 var file_reader = file.reader();
37 var br = file_reader.interface().buffered(&in_buffer);
3338
34 const db_schema = try reader.readStructEndian(ApplDbSchema, .big);39 const db_header = try br.takeStructEndian(ApplDbHeader, .big);
40 if (!mem.eql(u8, &db_header.signature, "kych")) continue;
3541
36 var table_list = try gpa.alloc(u32, db_schema.table_count);42 try file_reader.seekTo(db_header.schema_offset);
37 defer gpa.free(table_list);43 br = file_reader.interface().buffered(&in_buffer);
3844
39 var table_idx: u32 = 0;45 const db_schema = try br.takeStructEndian(ApplDbSchema, .big);
40 while (table_idx < table_list.len) : (table_idx += 1) {
41 table_list[table_idx] = try reader.readInt(u32, .big);
42 }
4346
44 const now_sec = std.time.timestamp();47 try tables.resize(db_schema.table_count);
48 for (tables.items) |*offset| offset.* = try br.takeInt(u32, .big);
4549
46 for (table_list) |table_offset| {50 for (tables.items) |table_offset| {
47 try stream.seekTo(db_header.schema_offset + table_offset);51 try file_reader.seekTo(db_header.schema_offset + table_offset);
52 br = file_reader.interface().buffered(&in_buffer);
4853
49 const table_header = try reader.readStructEndian(TableHeader, .big);54 const table_header = try br.takeStructEndian(TableHeader, .big);
5055
51 if (@as(std.c.DB_RECORDTYPE, @enumFromInt(table_header.table_id)) != .X509_CERTIFICATE) {56 if (@as(std.c.DB_RECORDTYPE, @enumFromInt(table_header.table_id)) != .X509_CERTIFICATE) {
52 continue;57 continue;
53 }58 }
5459
55 var record_list = try gpa.alloc(u32, table_header.record_count);60 try records.resize(gpa, table_header.record_count);
56 defer gpa.free(record_list);61 for (records.items) |*offset| offset.* = try br.takeInt(u32, .big);
5762
58 var record_idx: u32 = 0;63 for (records.items) |record_offset| {
59 while (record_idx < record_list.len) : (record_idx += 1) {
60 record_list[record_idx] = try reader.readInt(u32, .big);
61 }
62
63 for (record_list) |record_offset| {
64 // An offset of zero means that the record is not present.64 // An offset of zero means that the record is not present.
65 // An offset that is not 4-byte-aligned is invalid.65 // An offset that is not 4-byte-aligned is invalid.
66 if (record_offset == 0 or record_offset % 4 != 0) continue;66 if (record_offset == 0 or record_offset % 4 != 0) continue;
6767
68 try stream.seekTo(db_header.schema_offset + table_offset + record_offset);68 try file_reader.seekTo(db_header.schema_offset + table_offset + record_offset);
6969 br = file_reader.interface().buffered(&in_buffer);
70 const cert_header = try reader.readStructEndian(X509CertHeader, .big);
7170
71 const cert_header = try br.takeStructEndian(X509CertHeader, .big);
72 if (cert_header.cert_size == 0) continue;72 if (cert_header.cert_size == 0) continue;
7373
74 const cert_start = @as(u32, @intCast(cb.bytes.items.len));74 const cert_start: u32 = @intCast(cb.bytes.items.len);
75 const dest_buf = try cb.bytes.addManyAsSlice(gpa, cert_header.cert_size);75 const dest_buf = try cb.bytes.addManyAsSlice(gpa, cert_header.cert_size);
76 try reader.readNoEof(dest_buf);76 try br.readSlice(dest_buf);
7777
78 try cb.parseCert(gpa, cert_start, now_sec);78 try cb.parseCert(gpa, cert_start, now_sec);
79 }79 }
lib/std/crypto/phc_encoding.zig+5-4
...@@ -188,9 +188,10 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult...@@ -188,9 +188,10 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
188///188///
189/// `params` can also include any additional parameters.189/// `params` can also include any additional parameters.
190pub fn serialize(params: anytype, str: []u8) Error![]const u8 {190pub fn serialize(params: anytype, str: []u8) Error![]const u8 {
191 var buf = io.fixedBufferStream(str);191 var bw: std.io.BufferedWriter = undefined;
192 try serializeTo(params, buf.writer());192 bw.initFixed(str);
193 return buf.getWritten();193 try serializeTo(params, &bw);
194 return bw.getWritten();
194}195}
195196
196/// Compute the number of bytes required to serialize `params`197/// Compute the number of bytes required to serialize `params`
...@@ -200,7 +201,7 @@ pub fn calcSize(params: anytype) usize {...@@ -200,7 +201,7 @@ pub fn calcSize(params: anytype) usize {
200 return @as(usize, @intCast(buf.bytes_written));201 return @as(usize, @intCast(buf.bytes_written));
201}202}
202203
203fn serializeTo(params: anytype, out: anytype) !void {204fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {
204 const HashResult = @TypeOf(params);205 const HashResult = @TypeOf(params);
205206
206 if (@hasField(HashResult, version_param_name)) {207 if (@hasField(HashResult, version_param_name)) {
lib/std/crypto/scrypt.zig+16-11
...@@ -304,30 +304,35 @@ const crypt_format = struct {...@@ -304,30 +304,35 @@ const crypt_format = struct {
304304
305 /// Serialize parameters into a string in modular crypt format.305 /// Serialize parameters into a string in modular crypt format.
306 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {306 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {
307 var buf = io.fixedBufferStream(str);307 var bw: std.io.BufferedWriter = undefined;
308 try serializeTo(params, buf.writer());308 bw.initFixed(str);
309 return buf.getWritten();309 try serializeTo(params, &bw);
310 return bw.getWritten();
310 }311 }
311312
312 /// Compute the number of bytes required to serialize `params`313 /// Compute the number of bytes required to serialize `params`
313 pub fn calcSize(params: anytype) usize {314 pub fn calcSize(params: anytype) usize {
314 var buf = io.countingWriter(io.null_writer);315 var null_writer: std.io.Writer.Null = .{};
315 serializeTo(params, buf.writer()) catch unreachable;316 var trash: [64]u8 = undefined;
316 return @as(usize, @intCast(buf.bytes_written));317 var bw = null_writer.writer().buffered(&trash);
318 serializeTo(params, &bw) catch |err| switch (err) {
319 error.WriteFailed => unreachable,
320 };
321 return bw.count;
317 }322 }
318323
319 fn serializeTo(params: anytype, out: anytype) !void {324 fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {
320 var header: [14]u8 = undefined;325 var header: [14]u8 = undefined;
321 header[0..3].* = prefix.*;326 header[0..3].* = prefix.*;
322 Codec.intEncode(header[3..4], params.ln);327 Codec.intEncode(header[3..4], params.ln);
323 Codec.intEncode(header[4..9], params.r);328 Codec.intEncode(header[4..9], params.r);
324 Codec.intEncode(header[9..14], params.p);329 Codec.intEncode(header[9..14], params.p);
325 try out.writeAll(&header);330
326 try out.writeAll(params.salt);
327 try out.writeAll("$");
328 var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined;331 var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined;
329 const hash_str = try params.hash.toB64(&buf);332 const hash_str = try params.hash.toB64(&buf);
330 try out.writeAll(hash_str);333
334 var vecs: [4][]const u8 = .{ &header, params.salt, "$", hash_str };
335 try out.writeVecAll(&vecs);
331 }336 }
332337
333 /// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet,338 /// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet,
lib/std/fs/File.zig+18-2
...@@ -947,6 +947,22 @@ pub const Reader = struct {...@@ -947,6 +947,22 @@ pub const Reader = struct {
947 };947 };
948 }948 }
949949
950 pub fn seekTo(r: *Reader, offset: u64) SeekError!void {
951 // TODO if the offset is after the current offset, seek by discarding.
952 if (r.seek_err) |err| return err;
953 switch (r.mode) {
954 .positional, .positional_reading => {
955 r.pos = offset;
956 },
957 .streaming, .streaming_reading => {
958 posix.lseek_SET(r.file.handle, offset) catch |err| {
959 r.seek_err = err;
960 return err;
961 };
962 },
963 }
964 }
965
950 /// Number of slices to store on the stack, when trying to send as many byte966 /// Number of slices to store on the stack, when trying to send as many byte
951 /// vectors through the underlying read calls as possible.967 /// vectors through the underlying read calls as possible.
952 const max_buffers_len = 16;968 const max_buffers_len = 16;
...@@ -975,7 +991,7 @@ pub const Reader = struct {...@@ -975,7 +991,7 @@ pub const Reader = struct {
975 error.WriteFailed => return error.WriteFailed,991 error.WriteFailed => return error.WriteFailed,
976 error.Unseekable => {992 error.Unseekable => {
977 r.mode = .streaming;993 r.mode = .streaming;
978 assert(pos == 0);994 if (pos != 0) @panic("TODO need to seek here");
979 return 0;995 return 0;
980 },996 },
981 error.Unimplemented => {997 error.Unimplemented => {
...@@ -1011,7 +1027,7 @@ pub const Reader = struct {...@@ -1011,7 +1027,7 @@ pub const Reader = struct {
1011 const n = file.pread(dest, pos) catch |err| switch (err) {1027 const n = file.pread(dest, pos) catch |err| switch (err) {
1012 error.Unseekable => {1028 error.Unseekable => {
1013 r.mode = .streaming_reading;1029 r.mode = .streaming_reading;
1014 assert(pos == 0);1030 if (pos != 0) @panic("TODO need to seek here");
1015 return 0;1031 return 0;
1016 },1032 },
1017 else => |e| {1033 else => |e| {
lib/std/math.zig+4
...@@ -579,6 +579,10 @@ pub fn addAny(comptime Result: type, a: anytype, b: anytype) ?Result {...@@ -579,6 +579,10 @@ pub fn addAny(comptime Result: type, a: anytype, b: anytype) ?Result {
579 return cast(Result, @as(O, a) + @as(O, b));579 return cast(Result, @as(O, a) + @as(O, b));
580}580}
581581
582test addAny {
583 return error.Unimplemented;
584}
585
582/// Returns a - b, or an error on overflow.586/// Returns a - b, or an error on overflow.
583pub fn sub(comptime T: type, a: T, b: T) (error{Overflow}!T) {587pub fn sub(comptime T: type, a: T, b: T) (error{Overflow}!T) {
584 if (T == comptime_int) return a - b;588 if (T == comptime_int) return a - b;
lib/std/tar.zig+24-23
...@@ -955,13 +955,14 @@ test Iterator {...@@ -955,13 +955,14 @@ test Iterator {
955 // example/empty/955 // example/empty/
956956
957 const data = @embedFile("tar/testdata/example.tar");957 const data = @embedFile("tar/testdata/example.tar");
958 var fbs = std.io.fixedBufferStream(data);958 var br: std.io.BufferedReader = undefined;
959 br.initFixed(data);
959960
960 // User provided buffers to the iterator961 // User provided buffers to the iterator
961 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;962 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
962 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;963 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
963 // Create iterator964 // Create iterator
964 var iter: Iterator = .init(fbs.reader(), .{965 var iter: Iterator = .init(&br, .{
965 .file_name_buffer = &file_name_buffer,966 .file_name_buffer = &file_name_buffer,
966 .link_name_buffer = &link_name_buffer,967 .link_name_buffer = &link_name_buffer,
967 });968 });
...@@ -1014,15 +1015,15 @@ test pipeToFileSystem {...@@ -1014,15 +1015,15 @@ test pipeToFileSystem {
1014 // example/empty/1015 // example/empty/
10151016
1016 const data = @embedFile("tar/testdata/example.tar");1017 const data = @embedFile("tar/testdata/example.tar");
1017 var fbs = std.io.fixedBufferStream(data);1018 var br: std.io.BufferedReader = undefined;
1018 const reader = fbs.reader();1019 br.initFixed(data);
10191020
1020 var tmp = testing.tmpDir(.{ .no_follow = true });1021 var tmp = testing.tmpDir(.{ .no_follow = true });
1021 defer tmp.cleanup();1022 defer tmp.cleanup();
1022 const dir = tmp.dir;1023 const dir = tmp.dir;
10231024
1024 // Save tar from `reader` to the file system `dir`1025 // Save tar from reader to the file system `dir`
1025 pipeToFileSystem(dir, reader, .{1026 pipeToFileSystem(dir, &br, .{
1026 .mode_mode = .ignore,1027 .mode_mode = .ignore,
1027 .strip_components = 1,1028 .strip_components = 1,
1028 .exclude_empty_directories = true,1029 .exclude_empty_directories = true,
...@@ -1046,8 +1047,8 @@ test pipeToFileSystem {...@@ -1046,8 +1047,8 @@ test pipeToFileSystem {
10461047
1047test "pipeToFileSystem root_dir" {1048test "pipeToFileSystem root_dir" {
1048 const data = @embedFile("tar/testdata/example.tar");1049 const data = @embedFile("tar/testdata/example.tar");
1049 var fbs = std.io.fixedBufferStream(data);1050 var br: std.io.BufferedReader = undefined;
1050 const reader = fbs.reader();1051 br.initFixed(data);
10511052
1052 // with strip_components = 11053 // with strip_components = 1
1053 {1054 {
...@@ -1056,7 +1057,7 @@ test "pipeToFileSystem root_dir" {...@@ -1056,7 +1057,7 @@ test "pipeToFileSystem root_dir" {
1056 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1057 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1057 defer diagnostics.deinit();1058 defer diagnostics.deinit();
10581059
1059 pipeToFileSystem(tmp.dir, reader, .{1060 pipeToFileSystem(tmp.dir, &br, .{
1060 .strip_components = 1,1061 .strip_components = 1,
1061 .diagnostics = &diagnostics,1062 .diagnostics = &diagnostics,
1062 }) catch |err| {1063 }) catch |err| {
...@@ -1072,13 +1073,13 @@ test "pipeToFileSystem root_dir" {...@@ -1072,13 +1073,13 @@ test "pipeToFileSystem root_dir" {
10721073
1073 // with strip_components = 01074 // with strip_components = 0
1074 {1075 {
1075 fbs.reset();1076 br.initFixed(data);
1076 var tmp = testing.tmpDir(.{ .no_follow = true });1077 var tmp = testing.tmpDir(.{ .no_follow = true });
1077 defer tmp.cleanup();1078 defer tmp.cleanup();
1078 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1079 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1079 defer diagnostics.deinit();1080 defer diagnostics.deinit();
10801081
1081 pipeToFileSystem(tmp.dir, reader, .{1082 pipeToFileSystem(tmp.dir, &br, .{
1082 .strip_components = 0,1083 .strip_components = 0,
1083 .diagnostics = &diagnostics,1084 .diagnostics = &diagnostics,
1084 }) catch |err| {1085 }) catch |err| {
...@@ -1095,45 +1096,45 @@ test "pipeToFileSystem root_dir" {...@@ -1095,45 +1096,45 @@ test "pipeToFileSystem root_dir" {
10951096
1096test "findRoot with single file archive" {1097test "findRoot with single file archive" {
1097 const data = @embedFile("tar/testdata/22752.tar");1098 const data = @embedFile("tar/testdata/22752.tar");
1098 var fbs = std.io.fixedBufferStream(data);1099 var br: std.io.BufferedReader = undefined;
1099 const reader = fbs.reader();1100 br.initFixed(data);
11001101
1101 var tmp = testing.tmpDir(.{});1102 var tmp = testing.tmpDir(.{});
1102 defer tmp.cleanup();1103 defer tmp.cleanup();
11031104
1104 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1105 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1105 defer diagnostics.deinit();1106 defer diagnostics.deinit();
1106 try pipeToFileSystem(tmp.dir, reader, .{ .diagnostics = &diagnostics });1107 try pipeToFileSystem(tmp.dir, &br, .{ .diagnostics = &diagnostics });
11071108
1108 try testing.expectEqualStrings("", diagnostics.root_dir);1109 try testing.expectEqualStrings("", diagnostics.root_dir);
1109}1110}
11101111
1111test "findRoot without explicit root dir" {1112test "findRoot without explicit root dir" {
1112 const data = @embedFile("tar/testdata/19820.tar");1113 const data = @embedFile("tar/testdata/19820.tar");
1113 var fbs = std.io.fixedBufferStream(data);1114 var br: std.io.BufferedReader = undefined;
1114 const reader = fbs.reader();1115 br.initFixed(data);
11151116
1116 var tmp = testing.tmpDir(.{});1117 var tmp = testing.tmpDir(.{});
1117 defer tmp.cleanup();1118 defer tmp.cleanup();
11181119
1119 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1120 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1120 defer diagnostics.deinit();1121 defer diagnostics.deinit();
1121 try pipeToFileSystem(tmp.dir, reader, .{ .diagnostics = &diagnostics });1122 try pipeToFileSystem(tmp.dir, &br, .{ .diagnostics = &diagnostics });
11221123
1123 try testing.expectEqualStrings("root", diagnostics.root_dir);1124 try testing.expectEqualStrings("root", diagnostics.root_dir);
1124}1125}
11251126
1126test "pipeToFileSystem strip_components" {1127test "pipeToFileSystem strip_components" {
1127 const data = @embedFile("tar/testdata/example.tar");1128 const data = @embedFile("tar/testdata/example.tar");
1128 var fbs = std.io.fixedBufferStream(data);1129 var br: std.io.BufferedReader = undefined;
1129 const reader = fbs.reader();1130 br.initFixed(data);
11301131
1131 var tmp = testing.tmpDir(.{ .no_follow = true });1132 var tmp = testing.tmpDir(.{ .no_follow = true });
1132 defer tmp.cleanup();1133 defer tmp.cleanup();
1133 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1134 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1134 defer diagnostics.deinit();1135 defer diagnostics.deinit();
11351136
1136 pipeToFileSystem(tmp.dir, reader, .{1137 pipeToFileSystem(tmp.dir, &br, .{
1137 .strip_components = 3,1138 .strip_components = 3,
1138 .diagnostics = &diagnostics,1139 .diagnostics = &diagnostics,
1139 }) catch |err| {1140 }) catch |err| {
...@@ -1187,13 +1188,13 @@ test "executable bit" {...@@ -1187,13 +1188,13 @@ test "executable bit" {
1187 const data = @embedFile("tar/testdata/example.tar");1188 const data = @embedFile("tar/testdata/example.tar");
11881189
1189 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {1190 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {
1190 var fbs = std.io.fixedBufferStream(data);1191 var br: std.io.BufferedReader = undefined;
1191 const reader = fbs.reader();1192 br.initFixed(data);
11921193
1193 var tmp = testing.tmpDir(.{ .no_follow = true });1194 var tmp = testing.tmpDir(.{ .no_follow = true });
1194 //defer tmp.cleanup();1195 //defer tmp.cleanup();
11951196
1196 pipeToFileSystem(tmp.dir, reader, .{1197 pipeToFileSystem(tmp.dir, &br, .{
1197 .strip_components = 1,1198 .strip_components = 1,
1198 .exclude_empty_directories = true,1199 .exclude_empty_directories = true,
1199 .mode_mode = opt,1200 .mode_mode = opt,
lib/std/tar/Writer.zig+15-12
...@@ -441,11 +441,12 @@ test "write files" {...@@ -441,11 +441,12 @@ test "write files" {
441 for (files) |file|441 for (files) |file|
442 try wrt.writeFileBytes(file.path, file.content, .{});442 try wrt.writeFileBytes(file.path, file.content, .{});
443443
444 var input: std.io.FixedBufferStream = .{ .buffer = output.getWritten() };444 var input: std.io.BufferedReader = undefined;
445 var iter = std.tar.iterator(445 input.initFixed(output.getWritten());
446 input.reader(),446 var iter = std.tar.iterator(&input, .{
447 .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer },447 .file_name_buffer = &file_name_buffer,
448 );448 .link_name_buffer = &link_name_buffer,
449 });
449450
450 // first entry is directory with prefix451 // first entry is directory with prefix
451 {452 {
...@@ -475,15 +476,17 @@ test "write files" {...@@ -475,15 +476,17 @@ test "write files" {
475 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };476 var wrt: Writer = .{ .underlying_writer = &output.buffered_writer };
476 defer output.deinit();477 defer output.deinit();
477 for (files) |file| {478 for (files) |file| {
478 var content = std.io.fixedBufferStream(file.content);479 var content: std.io.BufferedReader = undefined;
479 try wrt.writeFileStream(file.path, file.content.len, content.reader(), .{});480 content.initFixed(file.content);
481 try wrt.writeFileStream(file.path, file.content.len, &content, .{});
480 }482 }
481483
482 var input: std.io.FixedBufferStream = .{ .buffer = output.getWritten() };484 var input: std.io.BufferedReader = undefined;
483 var iter = std.tar.iterator(485 input.initFixed(output.getWritten());
484 input.reader(),486 var iter = std.tar.iterator(&input, .{
485 .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer },487 .file_name_buffer = &file_name_buffer,
486 );488 .link_name_buffer = &link_name_buffer,
489 });
487490
488 var i: usize = 0;491 var i: usize = 0;
489 while (try iter.next()) |actual| {492 while (try iter.next()) |actual| {
lib/std/tar/test.zig+17-12
...@@ -346,8 +346,9 @@ test "run test cases" {...@@ -346,8 +346,9 @@ test "run test cases" {
346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
347347
348 for (cases) |case| {348 for (cases) |case| {
349 var fsb = std.io.fixedBufferStream(case.data);349 var br: std.io.BufferedReader = undefined;
350 var iter = tar.iterator(fsb.reader(), .{350 br.initFixed(case.data);
351 var iter = tar.iterator(&br, .{
351 .file_name_buffer = &file_name_buffer,352 .file_name_buffer = &file_name_buffer,
352 .link_name_buffer = &link_name_buffer,353 .link_name_buffer = &link_name_buffer,
353 });354 });
...@@ -390,8 +391,9 @@ test "pax/gnu long names with small buffer" {...@@ -390,8 +391,9 @@ test "pax/gnu long names with small buffer" {
390 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };391 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };
391392
392 for (long_name_cases) |case| {393 for (long_name_cases) |case| {
393 var fsb = std.io.fixedBufferStream(case.data);394 var br: std.io.BufferedReader = undefined;
394 var iter = tar.iterator(fsb.reader(), .{395 br.initFixed(case.data);
396 var iter = tar.iterator(&br, .{
395 .file_name_buffer = &min_file_name_buffer,397 .file_name_buffer = &min_file_name_buffer,
396 .link_name_buffer = &min_link_name_buffer,398 .link_name_buffer = &min_link_name_buffer,
397 });399 });
...@@ -411,8 +413,9 @@ test "insufficient buffer in Header name filed" {...@@ -411,8 +413,9 @@ test "insufficient buffer in Header name filed" {
411 var min_file_name_buffer: [9]u8 = undefined;413 var min_file_name_buffer: [9]u8 = undefined;
412 var min_link_name_buffer: [100]u8 = undefined;414 var min_link_name_buffer: [100]u8 = undefined;
413415
414 var fsb = std.io.fixedBufferStream(cases[0].data);416 var br: std.io.BufferedReader = undefined;
415 var iter = tar.iterator(fsb.reader(), .{417 br.initFixed(cases[0].data);
418 var iter = tar.iterator(&br, .{
416 .file_name_buffer = &min_file_name_buffer,419 .file_name_buffer = &min_file_name_buffer,
417 .link_name_buffer = &min_link_name_buffer,420 .link_name_buffer = &min_link_name_buffer,
418 });421 });
...@@ -466,21 +469,22 @@ test "should not overwrite existing file" {...@@ -466,21 +469,22 @@ test "should not overwrite existing file" {
466 // This ensures that file is not overwritten.469 // This ensures that file is not overwritten.
467 //470 //
468 const data = @embedFile("testdata/overwrite_file.tar");471 const data = @embedFile("testdata/overwrite_file.tar");
469 var fsb = std.io.fixedBufferStream(data);472 var br: std.io.BufferedReader = undefined;
473 br.initFixed(data);
470474
471 // Unpack with strip_components = 1 should fail475 // Unpack with strip_components = 1 should fail
472 var root = std.testing.tmpDir(.{});476 var root = std.testing.tmpDir(.{});
473 defer root.cleanup();477 defer root.cleanup();
474 try testing.expectError(478 try testing.expectError(
475 error.PathAlreadyExists,479 error.PathAlreadyExists,
476 tar.pipeToFileSystem(root.dir, fsb.reader(), .{ .mode_mode = .ignore, .strip_components = 1 }),480 tar.pipeToFileSystem(root.dir, &br, .{ .mode_mode = .ignore, .strip_components = 1 }),
477 );481 );
478482
479 // Unpack with strip_components = 0 should pass483 // Unpack with strip_components = 0 should pass
480 fsb.reset();484 br.initFixed(data);
481 var root2 = std.testing.tmpDir(.{});485 var root2 = std.testing.tmpDir(.{});
482 defer root2.cleanup();486 defer root2.cleanup();
483 try tar.pipeToFileSystem(root2.dir, fsb.reader(), .{ .mode_mode = .ignore, .strip_components = 0 });487 try tar.pipeToFileSystem(root2.dir, &br, .{ .mode_mode = .ignore, .strip_components = 0 });
484}488}
485489
486test "case sensitivity" {490test "case sensitivity" {
...@@ -494,12 +498,13 @@ test "case sensitivity" {...@@ -494,12 +498,13 @@ test "case sensitivity" {
494 // 18089/alacritty/Darkermatrix.yml498 // 18089/alacritty/Darkermatrix.yml
495 //499 //
496 const data = @embedFile("testdata/18089.tar");500 const data = @embedFile("testdata/18089.tar");
497 var fsb = std.io.fixedBufferStream(data);501 var br: std.io.BufferedReader = undefined;
502 br.initFixed(data);
498503
499 var root = std.testing.tmpDir(.{});504 var root = std.testing.tmpDir(.{});
500 defer root.cleanup();505 defer root.cleanup();
501506
502 tar.pipeToFileSystem(root.dir, fsb.reader(), .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {507 tar.pipeToFileSystem(root.dir, &br, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
503 // on case insensitive fs we fail on overwrite existing file508 // on case insensitive fs we fail on overwrite existing file
504 try testing.expectEqual(error.PathAlreadyExists, err);509 try testing.expectEqual(error.PathAlreadyExists, err);
505 return;510 return;
lib/std/zig/WindowsSdk.zig+6-6
...@@ -759,14 +759,14 @@ const MsvcLibDir = struct {...@@ -759,14 +759,14 @@ const MsvcLibDir = struct {
759 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {759 while (instances_dir_it.next() catch return error.PathNotFound) |entry| {
760 if (entry.kind != .directory) continue;760 if (entry.kind != .directory) continue;
761761
762 var fbs = std.io.fixedBufferStream(&state_subpath_buf);762 var bw: std.io.BufferedWriter = undefined;
763 const writer = fbs.writer();763 bw.initFixed(&state_subpath_buf);
764764
765 writer.writeAll(entry.name) catch unreachable;765 bw.writeAll(entry.name) catch unreachable;
766 writer.writeByte(std.fs.path.sep) catch unreachable;766 bw.writeByte(std.fs.path.sep) catch unreachable;
767 writer.writeAll("state.json") catch unreachable;767 bw.writeAll("state.json") catch unreachable;
768768
769 const json_contents = instances_dir.readFileAlloc(allocator, fbs.getWritten(), std.math.maxInt(usize)) catch continue;769 const json_contents = instances_dir.readFileAlloc(allocator, bw.getWritten(), std.math.maxInt(usize)) catch continue;
770 defer allocator.free(json_contents);770 defer allocator.free(json_contents);
771771
772 var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;772 var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue;
lib/std/zig/system/linux.zig+3-2
...@@ -342,8 +342,9 @@ fn testParser(...@@ -342,8 +342,9 @@ fn testParser(
342 expected_model: *const Target.Cpu.Model,342 expected_model: *const Target.Cpu.Model,
343 input: []const u8,343 input: []const u8,
344) !void {344) !void {
345 var fbs = io.fixedBufferStream(input);345 var br: std.io.BufferedReader = undefined;
346 const result = try parser.parse(arch, fbs.reader());346 br.initFixed(@constCast(input));
347 const result = try parser.parse(arch, &br);
347 try testing.expectEqual(expected_model, result.?.model);348 try testing.expectEqual(expected_model, result.?.model);
348 try testing.expect(expected_model.features.eql(result.?.features));349 try testing.expect(expected_model.features.eql(result.?.features));
349}350}