summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.zig101
1 files changed, 62 insertions, 39 deletions
diff --git a/src/main.zig b/src/main.zig
index d5345f0..ed52f53 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,6 +1,8 @@
const std = @import("std");
const testing = std.testing;
+// https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.10.TXT
+
const ZipFile = struct {
// [local file header 1]
// [encryption header 1]
@@ -144,61 +146,82 @@ const Zip64EndOfCentralDirectoryLocator = struct {
const EndOfCentralDirectoryRecord = packed struct {
const SIG: u32 = 0x06054b50;
- // end of central dir signature 4 bytes (0x06054b50)
- sig: u32 = SIG,
+ // // end of central dir signa SIG: u32 = 0x06054b50;ure 4 bytes (0x06054b50)
+ sig: u32 = SIG, // 504b0506
// number of this disk 2 bytes
- disk_number_this: u16,
+ disk_number_this: u16, // 0000
// number of the disk with the
// start of the central directory 2 bytes
- disk_number_central_dir_start: u16,
+ disk_number_central_dir_start: u16, // 0000
// total number of entries in the
// central directory on this disk 2 bytes
- total_central_dir_entries_on_this_disk: u16,
+ total_central_dir_entries_on_this_disk: u16, // 0100
// total number of entries in
// the central directory 2 bytes
- total_central_dir_entries: u16,
+ total_central_dir_entries: u16, // 0100
// size of the central directory 4 bytes
- size_of_central_dir: u32,
+ size_of_central_dir: u32, // 4f000000
// offset of start of central
// directory with respect to
// the starting disk number 4 bytes
- central_dir_offset: u32,
+ central_dir_offset: u32, // 4e000000
// .ZIP file comment length 2 bytes
- comment_length: u16,
+ comment_length: u16, // 0000
// .ZIP file comment (variable size)
// comment: [*]u8,
- // fn comment_slice(self: EndOfCentralDirectoryRecord) []u8 {
- // return self.comment[0..self.comment_length];
- // }
+ fn from(bytes: []const u8) !EndOfCentralDirectoryRecord {
+ var fbs = std.io.fixedBufferStream(bytes);
+ var rr = fbs.reader();
+ return EndOfCentralDirectoryRecord{
+ .sig = try rr.readIntLittle(u32),
+ .disk_number_this = try rr.readIntLittle(u16),
+ .disk_number_central_dir_start = try rr.readIntLittle(u16),
+ .total_central_dir_entries_on_this_disk = try rr.readIntLittle(u16),
+ .total_central_dir_entries = try rr.readIntLittle(u16),
+ .size_of_central_dir = try rr.readIntLittle(u32),
+ .central_dir_offset = try rr.readIntLittle(u32),
+ .comment_length = try rr.readIntLittle(u16),
+ // .comment = rr.read()
+ };
+ }
};
test "foo" {
- var mapped_mem: ?[]align(std.mem.page_size) u8 = null;
- {
- var file = try std.fs.cwd().openFile("src/hello.zip", .{});
- errdefer file.close();
- const file_len = std.math.cast(usize, try file.getEndPos()) orelse std.math.maxInt(usize);
- mapped_mem = try std.os.mmap(
- null,
- file_len,
- std.os.PROT.READ,
- std.os.MAP.SHARED,
- file.handle,
- 0,
- );
- file.close();
- }
- var mm = mapped_mem orelse return error.MMapFailed;
- defer std.os.munmap(mm);
- const cdr_search_start = if (mm.len < 64_000) 0 else mm.len - 64_000;
- const needle: [4]u8 = @bitCast(CentralDirectoryHeader.SIG);
- const eocdr_start = std.mem.indexOf(u8, mm[cdr_search_start..], &needle) orelse return error.EocdrNotFound;
- const eocdr: *EndOfCentralDirectoryRecord = @ptrCast(@alignCast(mm[eocdr_start .. eocdr_start + @sizeOf(EndOfCentralDirectoryRecord)]));
- std.log.err("needle: {} eocdr_start {} comment_length {}", .{ std.fmt.fmtSliceHexLower(&needle), eocdr_start, eocdr.comment_length });
-
- const hh_p: *u32 = @ptrCast(mm[0..4].ptr);
- const hh = hh_p.*;
- try std.testing.expectEqual(LocalFileHeader.SIG, hh);
- // std.log.err("mapped_mem len {} first 5 bytes {}", .{mm.len, std.fmt.fmtSliceHexUpper(mm[0..5])});
+ const test_zip = @embedFile("hello.zip");
+ var fbs = std.io.fixedBufferStream(test_zip);
+
+ const eocdr_search_width_max: usize = 64_000;
+ var eocdr_search_buf: [eocdr_search_width_max]u8 = undefined;
+
+ const epos = try fbs.getEndPos();
+ const eocdr_search_width: usize = @min(epos, eocdr_search_width_max);
+ const eocdr_seek_start: usize = epos - eocdr_search_width;
+
+ std.log.err("epos {}", .{epos});
+ std.log.err("eocdr_search_width {}", .{eocdr_search_width});
+ std.log.err("eocdr_seek_start {}", .{eocdr_seek_start});
+
+ try fbs.seekTo(eocdr_seek_start);
+ const eocdr_did_read = try fbs.read(&eocdr_search_buf);
+ std.log.err("eocdr_did_read {}", .{eocdr_did_read});
+ const needle: [4]u8 = @bitCast(EndOfCentralDirectoryRecord.SIG);
+ const eocdr_start = std.mem.indexOf(u8, eocdr_search_buf[0..eocdr_search_width], &needle) orelse return error.NoEndOfCentralDirectoryRecord;
+ std.log.err("eocdr_start {}", .{eocdr_start});
+ try fbs.seekTo(eocdr_start);
+ const eocdr_pos = try fbs.getPos();
+ std.log.err("eocdr_pos {}", .{eocdr_pos});
+
+ // const eocdr = try fbs.reader().readStruct(EndOfCentralDirectoryRecord);
+ // _ = eocdr;
+ // _ = eocdr;
+ var rr = fbs.reader();
+ const eocdrb = try rr.readAllAlloc(std.testing.allocator, 10_000_000);
+ defer std.testing.allocator.free(eocdrb);
+ const eocdr = try EndOfCentralDirectoryRecord.from(eocdrb);
+ _ = eocdr;
+ // const comment = try rr.readAllAlloc(std.testing.allocator, eocdr.comment_length);
+ // defer std.testing.allocator.free(comment);
+ std.log.err("eocdrb {} len {}", .{ std.fmt.fmtSliceHexLower(eocdrb), eocdrb.len });
+ std.log.err("sz {}", .{@sizeOf(EndOfCentralDirectoryRecord)});
}