DoxigAlpha

init

Function parameters

Parameters

#
input:*File.Reader

Type definitions in this namespace

Types

#

Extract the zipped files to the given `dest` directory.

Functions

#
extract
Extract the zipped files to the given `dest` directory.

= [4]u8{ 'P', 'K', 1, 2 }

Values

#
central_file_header_sig
= [4]u8{ 'P', 'K', 1, 2 }
local_file_header_sig
= [4]u8{ 'P', 'K', 3, 4 }
end_record_sig
= [4]u8{ 'P', 'K', 5, 6 }
end_record64_sig
= [4]u8{ 'P', 'K', 6, 6 }
end_locator64_sig
= [4]u8{ 'P', 'K', 6, 7 }

Source

Implementation

#
pub fn init(input: *File.Reader) !Iterator {
    const end_record = try EndRecord.findFile(input);

    if (!isMaxInt(end_record.record_count_disk) and end_record.record_count_disk > end_record.record_count_total)
        return error.ZipDiskRecordCountTooLarge;

    if (end_record.disk_number != 0 or end_record.central_directory_disk_number != 0)
        return error.ZipMultiDiskUnsupported;

    {
        const counts_valid = !isMaxInt(end_record.record_count_disk) and !isMaxInt(end_record.record_count_total);
        if (counts_valid and end_record.record_count_disk != end_record.record_count_total)
            return error.ZipMultiDiskUnsupported;
    }

    var result: Iterator = .{
        .input = input,
        .cd_record_count = end_record.record_count_total,
        .cd_zip_offset = end_record.central_directory_offset,
        .cd_size = end_record.central_directory_size,
    };
    if (!end_record.need_zip64()) return result;

    const locator_end_offset: u64 = @as(u64, end_record.comment_len) + @sizeOf(EndRecord) + @sizeOf(EndLocator64);
    const stream_len = try input.getSize();

    if (locator_end_offset > stream_len)
        return error.ZipTruncated;
    try input.seekTo(stream_len - locator_end_offset);
    const locator = input.interface.takeStruct(EndLocator64, .little) catch |err| switch (err) {
        error.ReadFailed => return input.err.?,
        error.EndOfStream => return error.EndOfStream,
    };
    if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig))
        return error.ZipBadLocatorSig;
    if (locator.zip64_disk_count != 0)
        return error.ZipUnsupportedZip64DiskCount;
    if (locator.total_disk_count != 1)
        return error.ZipMultiDiskUnsupported;

    try input.seekTo(locator.record_file_offset);

    const record64 = input.interface.takeStruct(EndRecord64, .little) catch |err| switch (err) {
        error.ReadFailed => return input.err.?,
        error.EndOfStream => return error.EndOfStream,
    };

    if (!std.mem.eql(u8, &record64.signature, &end_record64_sig))
        return error.ZipBadEndRecord64Sig;

    if (record64.end_record_size < @sizeOf(EndRecord64) - 12)
        return error.ZipEndRecord64SizeTooSmall;
    if (record64.end_record_size > @sizeOf(EndRecord64) - 12)
        return error.ZipEndRecord64UnhandledExtraData;

    if (record64.version_needed_to_extract > 45)
        return error.ZipUnsupportedVersion;

    {
        const is_multidisk = record64.disk_number != 0 or
            record64.central_directory_disk_number != 0 or
            record64.record_count_disk != record64.record_count_total;
        if (is_multidisk)
            return error.ZipMultiDiskUnsupported;
    }

    if (isMaxInt(end_record.record_count_total)) {
        result.cd_record_count = record64.record_count_total;
    } else if (end_record.record_count_total != record64.record_count_total)
        return error.Zip64RecordCountTotalMismatch;

    if (isMaxInt(end_record.central_directory_offset)) {
        result.cd_zip_offset = record64.central_directory_offset;
    } else if (end_record.central_directory_offset != record64.central_directory_offset)
        return error.Zip64CentralDirectoryOffsetMismatch;

    if (isMaxInt(end_record.central_directory_size)) {
        result.cd_size = record64.central_directory_size;
    } else if (end_record.central_directory_size != record64.central_directory_size)
        return error.Zip64CentralDirectorySizeMismatch;

    return result;
}