summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..d5345f0
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,204 @@
+const std = @import("std");
+const testing = std.testing;
+
+const ZipFile = struct {
+ // [local file header 1]
+ // [encryption header 1]
+ // [file data 1]
+ // [data descriptor 1]
+ // .
+ // .
+ // .
+ // [local file header n]
+ // [encryption header n]
+ // [file data n]
+ // [data descriptor n]
+ // [archive decryption header]
+ // [archive extra data record]
+ // [central directory header 1]
+ // .
+ // .
+ // .
+ // [central directory header n]
+ // [zip64 end of central directory record]
+ // [zip64 end of central directory locator]
+ // [end of central directory record]
+};
+
+const LocalFileHeader = packed struct {
+ const GPBF = packed struct(u16) {
+ encrypted: bool = false,
+ };
+ const SIG: u32 = 0x04034b50;
+ sig: u32 = SIG,
+ // version needed to extract 2 bytes
+ general_purpose_bit_flag: GPBF,
+ // compression method 2 bytes
+ // last mod file time 2 bytes
+ // last mod file date 2 bytes
+ // crc-32 4 bytes
+ // compressed size 4 bytes
+ // uncompressed size 4 bytes
+ // file name length 2 bytes
+ // extra field length 2 bytes
+ // file name (variable size)
+ // extra field (variable size)
+};
+
+const DataDescriptor = struct {
+ const SIG: u32 = 0x08074b50;
+ sig: u32 = SIG,
+ // crc-32 4 bytes
+ // compressed size 4 bytes
+ // uncompressed size 4 bytes
+};
+
+const ArchiveExtraDataRecord = struct {
+ const SIG: u32 = 0x08064b50;
+ sig: u32 = SIG,
+ // extra field length 4 bytes
+ // extra field data (variable size)
+
+};
+
+const CentralDirectoryHeader = packed struct {
+ const SIG: u32 = 0x02014b50;
+ // central file header signature 4 bytes ()
+ sig: u32 = SIG,
+ // version made by 2 bytes
+ version_made_by: u16,
+ // version needed to extract 2 bytes
+ version_needed_to_extract: u16,
+ // general purpose bit flag 2 bytes
+ general_purpose_bit_flag: u16,
+ // compression method 2 bytes
+ compression_method: u16,
+ // last mod file time 2 bytes
+ last_mod_file_time: u16,
+ // last mod file date 2 bytes
+ last_mod_file_date: u16,
+ // crc-32 4 bytes
+ crc32: u32,
+ // compressed size 4 bytes
+ compressed_size: u32,
+ // uncompressed size 4 bytes
+ uncompressed_size: u32,
+ // file name length 2 bytes
+ file_name_length: u16,
+ // extra field length 2 bytes
+ extra_field_length: u16,
+ // file comment length 2 bytes
+ file_comment_length: u16,
+ // disk number start 2 bytes
+ disk_number_start: u16,
+ // internal file attributes 2 bytes
+ internal_file_attributes: u16,
+ // external file attributes 4 bytes
+ external_file_attributes: u32,
+ // relative offset of local header 4 bytes
+ relative_offset_of_local_header: u16,
+
+ // file name (variable size)
+ // extra field (variable size)
+ // file comment (variable size)
+};
+
+const DigitalSignature = struct {
+ const SIG: u32 = 0x05054b50;
+ sig: u32 = SIG,
+ // size of data 2 bytes
+ // signature data (variable size)
+};
+
+const Zip64EndOfCentralDirectoryRecord = struct {
+ const SIG: u32 = 0x06064b50;
+ sig: u32 = SIG,
+ // size of zip64 end of central
+ // directory record 8 bytes
+ // version made by 2 bytes
+ // version needed to extract 2 bytes
+ // number of this disk 4 bytes
+ // number of the disk with the
+ // start of the central directory 4 bytes
+ // total number of entries in the
+ // central directory on this disk 8 bytes
+ // total number of entries in the
+ // central directory 8 bytes
+ // size of the central directory 8 bytes
+ // offset of start of central
+ // directory with respect to
+ // the starting disk number 8 bytes
+ // zip64 extensible data sector (variable size)
+};
+
+const Zip64EndOfCentralDirectoryLocator = struct {
+ const SIG: u32 = 0x07064b50;
+ sig: u32 = SIG,
+ // number of the disk with the
+ // start of the zip64 end of
+ // central directory 4 bytes
+ // relative offset of the zip64
+ // end of central directory record 8 bytes
+ // total number of disks 4 bytes
+};
+
+const EndOfCentralDirectoryRecord = packed struct {
+ const SIG: u32 = 0x06054b50;
+ // end of central dir signature 4 bytes (0x06054b50)
+ sig: u32 = SIG,
+ // number of this disk 2 bytes
+ disk_number_this: u16,
+ // number of the disk with the
+ // start of the central directory 2 bytes
+ disk_number_central_dir_start: u16,
+ // total number of entries in the
+ // central directory on this disk 2 bytes
+ total_central_dir_entries_on_this_disk: u16,
+ // total number of entries in
+ // the central directory 2 bytes
+ total_central_dir_entries: u16,
+ // size of the central directory 4 bytes
+ size_of_central_dir: u32,
+ // offset of start of central
+ // directory with respect to
+ // the starting disk number 4 bytes
+ central_dir_offset: u32,
+ // .ZIP file comment length 2 bytes
+ comment_length: u16,
+ // .ZIP file comment (variable size)
+ // comment: [*]u8,
+
+ // fn comment_slice(self: EndOfCentralDirectoryRecord) []u8 {
+ // return self.comment[0..self.comment_length];
+ // }
+};
+
+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])});
+}