| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const Allocator = std.mem.Allocator; | 3 | const Allocator = std.mem.Allocator; |
| | 4 | const assert = std.debug.assert; |
| 4 | | 5 | |
| 5 | pub fn main() !void { | 6 | pub fn main() !void { |
| 6 | var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 7 | 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 { | ... | @@ -140,7 +141,6 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { |
| 140 | }, | 141 | }, |
| 141 | }); | 142 | }); |
| 142 | const w = response.writer(); | 143 | const w = response.writer(); |
| 143 | try w.writeAll("tar header"); | | |
| 144 | | 144 | |
| 145 | var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); | 145 | var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); |
| 146 | defer std_dir.close(); | 146 | defer std_dir.close(); |
| ... | @@ -159,13 +159,27 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { | ... | @@ -159,13 +159,27 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { |
| 159 | else => continue, | 159 | else => continue, |
| 160 | } | 160 | } |
| 161 | | 161 | |
| 162 | try w.writeAll(entry.path); | | |
| 163 | | | |
| 164 | var file = try std_dir.openFile(entry.path, .{}); | 162 | var file = try std_dir.openFile(entry.path, .{}); |
| 165 | defer file.close(); | 163 | defer file.close(); |
| 166 | | 164 | |
| | 165 | const stat = try file.stat(); |
| | 166 | const padding = p: { |
| | 167 | const remainder = stat.size % 512; |
| | 168 | break :p if (remainder > 0) 512 - remainder else 0; |
| | 169 | }; |
| | 170 | comptime assert(@sizeOf(TarHeader) == 512); |
| | 171 | |
| | 172 | var file_header = TarHeader.init(); |
| | 173 | file_header.typeflag = .regular; |
| | 174 | try file_header.setPath("std", entry.path); |
| | 175 | try file_header.setSize(stat.size); |
| | 176 | try file_header.updateChecksum(); |
| | 177 | try w.writeAll(std.mem.asBytes(&file_header)); |
| 167 | try w.writeFile(file); | 178 | try w.writeFile(file); |
| | 179 | try w.writeByteNTimes(0, padding); |
| 168 | } | 180 | } |
| | 181 | // intentionally omitting the pointless trailer |
| | 182 | //try w.writeByteNTimes(0, 512 * 2); |
| 169 | try response.end(); | 183 | try response.end(); |
| 170 | } | 184 | } |
| 171 | | 185 | |
| ... | @@ -369,3 +383,77 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { | ... | @@ -369,3 +383,77 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { |
| 369 | try child.spawn(); | 383 | try child.spawn(); |
| 370 | _ = try child.wait(); | 384 | _ = try child.wait(); |
| 371 | } | 385 | } |
| | 386 | |
| | 387 | /// Forked from https://github.com/mattnite/tar/blob/main/src/main.zig which is |
| | 388 | /// MIT licensed. |
| | 389 | pub const TarHeader = extern struct { |
| | 390 | name: [100]u8, |
| | 391 | mode: [7:0]u8, |
| | 392 | uid: [7:0]u8, |
| | 393 | gid: [7:0]u8, |
| | 394 | size: [11:0]u8, |
| | 395 | mtime: [11:0]u8, |
| | 396 | checksum: [7:0]u8, |
| | 397 | typeflag: FileType, |
| | 398 | linkname: [100]u8, |
| | 399 | magic: [5:0]u8, |
| | 400 | version: [2]u8, |
| | 401 | uname: [31:0]u8, |
| | 402 | gname: [31:0]u8, |
| | 403 | devmajor: [7:0]u8, |
| | 404 | devminor: [7:0]u8, |
| | 405 | prefix: [155]u8, |
| | 406 | pad: [12]u8, |
| | 407 | |
| | 408 | const FileType = enum(u8) { |
| | 409 | regular = '0', |
| | 410 | hard_link = '1', |
| | 411 | symbolic_link = '2', |
| | 412 | character = '3', |
| | 413 | block = '4', |
| | 414 | directory = '5', |
| | 415 | fifo = '6', |
| | 416 | reserved = '7', |
| | 417 | pax_global = 'g', |
| | 418 | extended = 'x', |
| | 419 | _, |
| | 420 | }; |
| | 421 | |
| | 422 | fn init() TarHeader { |
| | 423 | var ret = std.mem.zeroes(TarHeader); |
| | 424 | ret.magic = [_:0]u8{ 'u', 's', 't', 'a', 'r' }; |
| | 425 | ret.version = [_:0]u8{ '0', '0' }; |
| | 426 | return ret; |
| | 427 | } |
| | 428 | |
| | 429 | fn setPath(self: *TarHeader, prefix: []const u8, path: []const u8) !void { |
| | 430 | if (prefix.len + 1 + path.len > 100) { |
| | 431 | var i: usize = 0; |
| | 432 | while (i < path.len and path.len - i > 100) { |
| | 433 | while (path[i] != '/') : (i += 1) {} |
| | 434 | } |
| | 435 | |
| | 436 | _ = try std.fmt.bufPrint(&self.prefix, "{s}/{s}", .{ prefix, path[0..i] }); |
| | 437 | _ = try std.fmt.bufPrint(&self.name, "{s}", .{path[i + 1 ..]}); |
| | 438 | } else { |
| | 439 | _ = try std.fmt.bufPrint(&self.name, "{s}/{s}", .{ prefix, path }); |
| | 440 | } |
| | 441 | } |
| | 442 | |
| | 443 | fn setSize(self: *TarHeader, size: u64) !void { |
| | 444 | _ = try std.fmt.bufPrint(&self.size, "{o:0>11}", .{size}); |
| | 445 | } |
| | 446 | |
| | 447 | fn updateChecksum(self: *TarHeader) !void { |
| | 448 | const offset = @offsetOf(TarHeader, "checksum"); |
| | 449 | var checksum: usize = 0; |
| | 450 | for (std.mem.asBytes(self), 0..) |val, i| { |
| | 451 | checksum += if (i >= offset and i < offset + @sizeOf(@TypeOf(self.checksum))) |
| | 452 | ' ' |
| | 453 | else |
| | 454 | val; |
| | 455 | } |
| | 456 | |
| | 457 | _ = try std.fmt.bufPrint(&self.checksum, "{o:0>7}", .{checksum}); |
| | 458 | } |
| | 459 | }; |