Compare commits
No commits in common. "1769342e234361f3de5c40f5e64c777b5cee7164" and "2ae8d3048d06c02df5e3b8053ccb0b598eec8899" have entirely different histories.
1769342e23
...
2ae8d3048d
2 changed files with 5 additions and 62 deletions
|
|
@ -1610,37 +1610,14 @@ pub fn store_to_existing_file_const(self: *const Self, file_path_: []const u8) S
|
||||||
file_path = link;
|
file_path = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
var write_buffer: [4096]u8 = undefined;
|
|
||||||
|
|
||||||
if (builtin.os.tag == .windows) {
|
|
||||||
// windows uses ACLs for ownership so we preserve mode only
|
|
||||||
var atomic = blk: {
|
var atomic = blk: {
|
||||||
|
var write_buffer: [4096]u8 = undefined;
|
||||||
const stat = cwd().statFile(file_path) catch
|
const stat = cwd().statFile(file_path) catch
|
||||||
break :blk try cwd().atomicFile(file_path, .{ .write_buffer = &write_buffer });
|
break :blk try cwd().atomicFile(file_path, .{ .write_buffer = &write_buffer });
|
||||||
break :blk try cwd().atomicFile(file_path, .{ .mode = stat.mode, .write_buffer = &write_buffer });
|
break :blk try cwd().atomicFile(file_path, .{ .mode = stat.mode, .write_buffer = &write_buffer });
|
||||||
};
|
};
|
||||||
defer atomic.deinit();
|
defer atomic.deinit();
|
||||||
try self.store_to_file_const(&atomic.file_writer.interface);
|
try self.store_to_file_const(&atomic.file_writer.interface);
|
||||||
return atomic.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
// use fstat to get uid/gid, which std.fs.File.Stat omits.
|
|
||||||
const orig_stat: ?std.posix.Stat = blk: {
|
|
||||||
const f = cwd().openFile(file_path, .{}) catch break :blk null;
|
|
||||||
defer f.close();
|
|
||||||
break :blk std.posix.fstat(f.handle) catch null;
|
|
||||||
};
|
|
||||||
const mode: std.fs.File.Mode = if (orig_stat) |s| s.mode else std.fs.File.default_mode;
|
|
||||||
var atomic = try cwd().atomicFile(file_path, .{ .mode = mode, .write_buffer = &write_buffer });
|
|
||||||
defer atomic.deinit();
|
|
||||||
try self.store_to_file_const(&atomic.file_writer.interface);
|
|
||||||
// fchmod bypasses the process umask preserving the exact original mode
|
|
||||||
// fchown restores original owner/group
|
|
||||||
// EPERM is silently ignored when we lack sufficient privileges
|
|
||||||
if (orig_stat) |s| {
|
|
||||||
atomic.file_writer.file.chmod(s.mode) catch {};
|
|
||||||
std.posix.fchown(atomic.file_writer.file.handle, s.uid, s.gid) catch {};
|
|
||||||
}
|
|
||||||
try atomic.finish();
|
try atomic.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const Buffer = @import("Buffer");
|
const Buffer = @import("Buffer");
|
||||||
|
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
|
|
@ -100,39 +99,6 @@ test "buffer.store_to_file_and_clean" {
|
||||||
try std.testing.expectEqualStrings(input, output);
|
try std.testing.expectEqualStrings(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "buffer.store_to_file_and_clean preserves file mode" {
|
|
||||||
if (comptime builtin.os.tag == .windows) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const tmp_path = "test/tmp_mode_test.txt";
|
|
||||||
{
|
|
||||||
const f = try std.fs.cwd().createFile(tmp_path, .{});
|
|
||||||
defer f.close();
|
|
||||||
try f.writeAll("hello\n");
|
|
||||||
try f.chmod(0o644);
|
|
||||||
}
|
|
||||||
defer std.fs.cwd().deleteFile(tmp_path) catch {};
|
|
||||||
|
|
||||||
// Set a umask that would strip group/other read bits (0o644 -> 0o600 without the fix)
|
|
||||||
// to verify that fchmod bypasses the process umask on save.
|
|
||||||
const prev_umask = if (comptime builtin.os.tag == .linux)
|
|
||||||
std.os.linux.syscall1(.umask, 0o077)
|
|
||||||
else
|
|
||||||
@as(usize, 0);
|
|
||||||
defer if (comptime builtin.os.tag == .linux) {
|
|
||||||
_ = std.os.linux.syscall1(.umask, prev_umask);
|
|
||||||
};
|
|
||||||
|
|
||||||
const buffer = try Buffer.create(a);
|
|
||||||
defer buffer.deinit();
|
|
||||||
try buffer.load_from_file_and_update(tmp_path);
|
|
||||||
try buffer.store_to_file_and_clean(tmp_path);
|
|
||||||
|
|
||||||
const f = try std.fs.cwd().openFile(tmp_path, .{});
|
|
||||||
defer f.close();
|
|
||||||
const stat = try std.posix.fstat(f.handle);
|
|
||||||
try std.testing.expectEqual(@as(std.posix.mode_t, 0o644), stat.mode & 0o777);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_line(buf: *const Buffer, line: usize) ![]const u8 {
|
fn get_line(buf: *const Buffer, line: usize) ![]const u8 {
|
||||||
var result: std.Io.Writer.Allocating = .init(a);
|
var result: std.Io.Writer.Allocating = .init(a);
|
||||||
try buf.root.get_line(line, &result.writer, metrics());
|
try buf.root.get_line(line, &result.writer, metrics());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue