| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | const Allocator = std.mem.Allocator; |
| 4 | const assert = std.debug.assert; |
| 4 | 5 | |
| 5 | 6 | pub fn main() !void { |
| 6 | 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 | 141 | }, |
| 141 | 142 | }); |
| 142 | 143 | const w = response.writer(); |
| 143 | | try w.writeAll("tar header"); |
| 144 | 144 | |
| 145 | 145 | var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); |
| 146 | 146 | defer std_dir.close(); |
| ... | ... | @@ -159,13 +159,27 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { |
| 159 | 159 | else => continue, |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | | try w.writeAll(entry.path); |
| 163 | | |
| 164 | 162 | var file = try std_dir.openFile(entry.path, .{}); |
| 165 | 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 | 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 | 183 | try response.end(); |
| 170 | 184 | } |
| 171 | 185 | |
| ... | ... | @@ -369,3 +383,77 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { |
| 369 | 383 | try child.spawn(); |
| 370 | 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 | }; |