From 942d3dc641df588367c8ac482dfaacfed2ab66ac Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 19 Oct 2023 12:12:45 -0700 Subject: [PATCH 1/4] basic thing working --- lib/std/tar.zig | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/std/tar.zig b/lib/std/tar.zig index bdbec87e39be..9c550137f60d 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -127,6 +127,11 @@ pub const Header = struct { return result; } + pub fn mode(header: Header) []const u8 { + // The mode is stored in bytes 100-107 + return str(header, 100, 100 + 7); + } + fn str(header: Header, start: usize, end: usize) []const u8 { var i: usize = start; while (i < end) : (i += 1) { @@ -175,15 +180,14 @@ const Buffer = struct { }; pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !void { + var should_exec: bool = false; switch (options.mode_mode) { .ignore => {}, .executable_bit_only => { - // This code does not look at the mode bits yet. To implement this feature, - // the implementation must be adjusted to look at the mode, and check the - // user executable bit, then call fchmod on newly created files when - // the executable bit is supposed to be set. - // It also needs to properly deal with ACLs on Windows. - @panic("TODO: unimplemented: tar ModeMode.executable_bit_only"); + // Make sure the OS supports executable bit. + if (std.fs.has_executable_bit) { + should_exec = true; + } }, } var file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; @@ -217,7 +221,6 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi .normal => { if (file_size == 0 and unstripped_file_name.len == 0) return; const file_name = try stripComponents(unstripped_file_name, options.strip_components); - var file = dir.createFile(file_name, .{}) catch |err| switch (err) { error.FileNotFound => again: { const code = code: { @@ -241,6 +244,17 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi defer if (file) |f| f.close(); var file_off: usize = 0; + + const mode = header.mode(); + var modebits = std.StaticBitSet(32){ + .mask = @intCast(try std.fmt.parseInt(u32, mode, 8)), + }; + + const has_owner_exe_bit = modebits.isSet(6); + modebits.setValue(3, has_owner_exe_bit); + modebits.setValue(0, has_owner_exe_bit); + try file.?.chmod(modebits.mask); + while (true) { const temp = try buffer.readChunk(reader, @intCast(rounded_file_size + 512 - file_off)); if (temp.len == 0) return error.UnexpectedEndOfStream; From a1ce0ac60bcd2a5063af328f151a1cebafd317d6 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 19 Oct 2023 12:18:34 -0700 Subject: [PATCH 2/4] added actual choice logic --- lib/std/tar.zig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/std/tar.zig b/lib/std/tar.zig index 9c550137f60d..c95d308ec93e 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -245,15 +245,17 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi var file_off: usize = 0; - const mode = header.mode(); - var modebits = std.StaticBitSet(32){ - .mask = @intCast(try std.fmt.parseInt(u32, mode, 8)), - }; + if (should_exec) { + const mode = header.mode(); + var modebits = std.StaticBitSet(32){ + .mask = @intCast(try std.fmt.parseInt(u32, mode, 8)), + }; - const has_owner_exe_bit = modebits.isSet(6); - modebits.setValue(3, has_owner_exe_bit); - modebits.setValue(0, has_owner_exe_bit); - try file.?.chmod(modebits.mask); + const has_owner_exe_bit = modebits.isSet(6); + modebits.setValue(3, has_owner_exe_bit); + modebits.setValue(0, has_owner_exe_bit); + try file.?.chmod(modebits.mask); + } while (true) { const temp = try buffer.readChunk(reader, @intCast(rounded_file_size + 512 - file_off)); From 1f78e043644f9aa9efaad341c89b29d1a5ca19c2 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 19 Oct 2023 13:12:44 -0700 Subject: [PATCH 3/4] fix windows thing --- lib/std/tar.zig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/std/tar.zig b/lib/std/tar.zig index c95d308ec93e..0a8507920ae0 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -254,7 +254,13 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi const has_owner_exe_bit = modebits.isSet(6); modebits.setValue(3, has_owner_exe_bit); modebits.setValue(0, has_owner_exe_bit); - try file.?.chmod(modebits.mask); + + // Needed for comptime fix, as should_exec is runtime, and + // the compiler requires chmod take a u0 on windows. + // mask is a u32, so it would fail on windows. + if (builtin.os.tag != .windows and builtin.os.tag != .wasi) { + try file.?.chmod(modebits.mask); + } } while (true) { @@ -411,3 +417,4 @@ test parsePaxAttribute { const std = @import("std.zig"); const assert = std.debug.assert; +const builtin = @import("builtin"); From 68f8a239e732eaad2e4bb656e9605c8a9f8b7077 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 19 Oct 2023 13:32:15 -0700 Subject: [PATCH 4/4] follow the syntax in file --- lib/std/tar.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/tar.zig b/lib/std/tar.zig index 0a8507920ae0..03b3ef70d767 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -259,7 +259,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi // the compiler requires chmod take a u0 on windows. // mask is a u32, so it would fail on windows. if (builtin.os.tag != .windows and builtin.os.tag != .wasi) { - try file.?.chmod(modebits.mask); + if (file) |f| try f.chmod(modebits.mask); } }