diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-03-06 19:19:45 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-03-10 17:51:06 -0700 |
| commit | 6b84c8e04c9286d072367ae86807fd517c74c479 (patch) | |
| tree | 6c45f69b38d992699527db3c8cf976c6a8b0b72e /lib/compiler/std-docs.zig | |
| parent | c427685a13a2bb98ccc6944d18bb3e6ee17dcdff (diff) | |
| download | zig-6b84c8e04c9286d072367ae86807fd517c74c479.tar.gz zig-6b84c8e04c9286d072367ae86807fd517c74c479.zip | |
zig std: implement tar format
Diffstat (limited to 'lib/compiler/std-docs.zig')
| -rw-r--r-- | lib/compiler/std-docs.zig | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index b14d900901..2a856f100e 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -1,6 +1,7 @@ const builtin = @import("builtin"); const std = @import("std"); const Allocator = std.mem.Allocator; +const assert = std.debug.assert; pub fn main() !void { var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); @@ -140,7 +141,6 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { }, }); const w = response.writer(); - try w.writeAll("tar header"); var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); defer std_dir.close(); @@ -159,13 +159,27 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { else => continue, } - try w.writeAll(entry.path); - var file = try std_dir.openFile(entry.path, .{}); defer file.close(); + const stat = try file.stat(); + const padding = p: { + const remainder = stat.size % 512; + break :p if (remainder > 0) 512 - remainder else 0; + }; + comptime assert(@sizeOf(TarHeader) == 512); + + var file_header = TarHeader.init(); + file_header.typeflag = .regular; + try file_header.setPath("std", entry.path); + try file_header.setSize(stat.size); + try file_header.updateChecksum(); + try w.writeAll(std.mem.asBytes(&file_header)); try w.writeFile(file); + try w.writeByteNTimes(0, padding); } + // intentionally omitting the pointless trailer + //try w.writeByteNTimes(0, 512 * 2); try response.end(); } @@ -369,3 +383,77 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { try child.spawn(); _ = try child.wait(); } + +/// Forked from https://github.com/mattnite/tar/blob/main/src/main.zig which is +/// MIT licensed. +pub const TarHeader = extern struct { + name: [100]u8, + mode: [7:0]u8, + uid: [7:0]u8, + gid: [7:0]u8, + size: [11:0]u8, + mtime: [11:0]u8, + checksum: [7:0]u8, + typeflag: FileType, + linkname: [100]u8, + magic: [5:0]u8, + version: [2]u8, + uname: [31:0]u8, + gname: [31:0]u8, + devmajor: [7:0]u8, + devminor: [7:0]u8, + prefix: [155]u8, + pad: [12]u8, + + const FileType = enum(u8) { + regular = '0', + hard_link = '1', + symbolic_link = '2', + character = '3', + block = '4', + directory = '5', + fifo = '6', + reserved = '7', + pax_global = 'g', + extended = 'x', + _, + }; + + fn init() TarHeader { + var ret = std.mem.zeroes(TarHeader); + ret.magic = [_:0]u8{ 'u', 's', 't', 'a', 'r' }; + ret.version = [_:0]u8{ '0', '0' }; + return ret; + } + + fn setPath(self: *TarHeader, prefix: []const u8, path: []const u8) !void { + if (prefix.len + 1 + path.len > 100) { + var i: usize = 0; + while (i < path.len and path.len - i > 100) { + while (path[i] != '/') : (i += 1) {} + } + + _ = try std.fmt.bufPrint(&self.prefix, "{s}/{s}", .{ prefix, path[0..i] }); + _ = try std.fmt.bufPrint(&self.name, "{s}", .{path[i + 1 ..]}); + } else { + _ = try std.fmt.bufPrint(&self.name, "{s}/{s}", .{ prefix, path }); + } + } + + fn setSize(self: *TarHeader, size: u64) !void { + _ = try std.fmt.bufPrint(&self.size, "{o:0>11}", .{size}); + } + + fn updateChecksum(self: *TarHeader) !void { + const offset = @offsetOf(TarHeader, "checksum"); + var checksum: usize = 0; + for (std.mem.asBytes(self), 0..) |val, i| { + checksum += if (i >= offset and i < offset + @sizeOf(@TypeOf(self.checksum))) + ' ' + else + val; + } + + _ = try std.fmt.bufPrint(&self.checksum, "{o:0>7}", .{checksum}); + } +}; |
