From b30642a86ae59f9cfe73c8a9ed6e79c3cb5aaa36 Mon Sep 17 00:00:00 2001 From: Cassidy Dingenskirchen Date: Tue, 16 Jun 2020 19:07:55 +0200 Subject: [PATCH 1/3] Fix zig fmt clobbering a file's mode --- src-self-hosted/main.zig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index eda9dcfc31..4db98c60dc 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -684,7 +684,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { if (fmt.seen.exists(real_path)) return; try fmt.seen.put(real_path); - const source_code = fs.cwd().readFileAlloc(fmt.gpa, real_path, max_src_size) catch |err| switch (err) { + const source_file = fs.cwd().openFile(real_path, .{}) catch |err| switch (err) { error.IsDir, error.AccessDenied => { var dir = try fs.cwd().openDir(file_path, .{ .iterate = true }); defer dir.close(); @@ -705,6 +705,13 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { return; }, }; + defer source_file.close(); + + const source_code = source_file.reader().readAllAlloc(fmt.gpa, max_src_size) catch |err| { + std.debug.warn("unable to read '{}': {}\n", .{ file_path, err }); + fmt.any_error = true; + return; + }; defer fmt.gpa.free(source_code); const tree = std.zig.parse(fmt.gpa, source_code) catch |err| { @@ -729,7 +736,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { fmt.any_error = true; } } else { - const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{}); + const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = try source_file.mode() }); defer baf.destroy(); const anything_changed = try std.zig.render(fmt.gpa, baf.stream(), tree); From 8b49487c3345d6e203d8c72695e639b42a93c119 Mon Sep 17 00:00:00 2001 From: Cassidy Dingenskirchen Date: Thu, 18 Jun 2020 18:27:42 +0200 Subject: [PATCH 2/3] Fix fs.File.mode() not returning mode_t on windows --- lib/std/fs/file.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index d950a1cfa4..ec4059b9c7 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -209,7 +209,7 @@ pub const File = struct { /// TODO: integrate with async I/O pub fn mode(self: File) ModeError!Mode { if (builtin.os.tag == .windows) { - return {}; + return 0; } return (try self.stat()).mode; } From f7bcc8e04087e2308582d8b6f068e2e71b65bef9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Jun 2020 21:08:30 -0400 Subject: [PATCH 3/3] rework zig fmt to only make one allocation taking advantage of the fstat size --- lib/std/fs.zig | 9 ++------- lib/std/fs/file.zig | 27 +++++++++++++++++++++++++++ src-self-hosted/main.zig | 10 ++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 262aa4872d..3ff4819ac5 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1229,14 +1229,9 @@ pub const Dir = struct { var file = try self.openFile(file_path, .{}); defer file.close(); - const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize); - if (size > max_bytes) return error.FileTooBig; + const stat_size = try file.getEndPos(); - const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel); - errdefer allocator.free(buf); - - try file.inStream().readNoEof(buf); - return buf; + return file.readAllAllocOptions(allocator, stat_size, max_bytes, alignment, optional_sentinel); } pub const DeleteTreeError = error{ diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index ec4059b9c7..0a3c1b5ab7 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -306,6 +306,33 @@ pub const File = struct { try os.futimens(self.handle, ×); } + /// On success, caller owns returned buffer. + /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. + pub fn readAllAlloc(self: File, allocator: *mem.Allocator, stat_size: u64, max_bytes: usize) ![]u8 { + return self.readAllAllocOptions(allocator, stat_size, max_bytes, @alignOf(u8), null); + } + + /// On success, caller owns returned buffer. + /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. + /// Allows specifying alignment and a sentinel value. + pub fn readAllAllocOptions( + self: File, + allocator: *mem.Allocator, + stat_size: u64, + max_bytes: usize, + comptime alignment: u29, + comptime optional_sentinel: ?u8, + ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) { + const size = math.cast(usize, stat_size) catch math.maxInt(usize); + if (size > max_bytes) return error.FileTooBig; + + const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel); + errdefer allocator.free(buf); + + try self.inStream().readNoEof(buf); + return buf; + } + pub const ReadError = os.ReadError; pub const PReadError = os.PReadError; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 4db98c60dc..6c13f8ab00 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -707,7 +707,13 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { }; defer source_file.close(); - const source_code = source_file.reader().readAllAlloc(fmt.gpa, max_src_size) catch |err| { + const stat = source_file.stat() catch |err| { + std.debug.warn("unable to stat '{}': {}\n", .{ file_path, err }); + fmt.any_error = true; + return; + }; + + const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| { std.debug.warn("unable to read '{}': {}\n", .{ file_path, err }); fmt.any_error = true; return; @@ -736,7 +742,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { fmt.any_error = true; } } else { - const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = try source_file.mode() }); + const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = stat.mode }); defer baf.destroy(); const anything_changed = try std.zig.render(fmt.gpa, baf.stream(), tree);