diff options
-rw-r--r-- | src/main.zig | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/src/main.zig b/src/main.zig index cb116b9..d154c8c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -121,6 +121,9 @@ pub fn file_name(self: @This(), index: usize) []const u8 { pub fn file_comment(self: @This(), index: usize) []const u8 { return self.central_directory_headers[index].file_comment; } +pub fn is_dir(self: *@This(), index: usize) bool { + return std.mem.endsWith(u8, self.central_directory_headers[index].file_name, "/"); // This is what the java stdlib does +} pub fn extract(self: @This(), index: usize, stream_or_file_in: anytype, writer: anytype) !void { const cdh = self.central_directory_headers[index]; try stream_or_file_in.seekTo(cdh.relative_offset_of_local_header); @@ -246,7 +249,7 @@ const LocalFileHeader = struct { // directories can't have a size, this is very likely wrong. return error.InvalidFileName; } - return; // Do nothing here. If we were definitely writing to the filesystem we could make an empty dir I guess. + return; // Do nothing here. If we were definitely writing to a filesystem we could make an empty dir I guess. } var lr = std.io.limitedReader(reader, self.compressed_size); @@ -335,6 +338,41 @@ fn read2( return t; } +pub const Options = struct { + allocator: std.mem.Allocator, +}; +// tar.zig compatibility, ish. It manages a forwards-only read of the filesystem anyway +pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !void { + const allocator = options.allocator; + // var peek_stream = std.io.peekStream(4, reader); + // var peek_reader = peek_stream.reader(); + var i: u32 = 0; + while (true) { + std.log.err("reading file {}", .{i}); + var lfh = LocalFileHeader.read(allocator, reader) catch |e| switch (e) { + error.InvalidSignature => return, // done + else => return e, + }; + defer lfh.deinit(allocator); + if (std.fs.path.dirname(lfh.file_name)) |dn| { + try dir.makePath(dn); + } + if (!lfh.is_dir()) { + var f = try dir.createFile(lfh.file_name, .{}); + defer f.close(); + var writer = f.writer(); + try lfh.extract(allocator, reader, writer); + } + i+=1; + // try reader.skipBytes(12, .{}); // Data descriptor signature. + // _ = read_to_sig(peek_reader, LocalFileHeader.SIG) catch |e| switch (e) { + // error.EndOfStream => return, + // else => return e, + // }; + // try peek_stream.putBack(&@as([4]u8, @bitCast(LocalFileHeader.SIG))); + } +} + test "open stream" { const test_zip = @embedFile("hello.zip"); var fbs = std.io.fixedBufferStream(test_zip); @@ -387,40 +425,10 @@ test "subdir" { var fbs = std.io.fixedBufferStream(test_zip); var zf = try @This().from(std.testing.allocator, &fbs); defer zf.deinit(); - for (0..zf.count_files()) |i| { - _ = i; - // std.log.err("cdh {any}", .{zf.central_directory_headers[i]}); - } -} -pub const Options = struct { - allocator: std.mem.Allocator, -}; -// tar.zig compatibility, ish. It manages a forwards-only read of the filesystem anyway -pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !void { - const allocator = options.allocator; - // var peek_stream = std.io.peekStream(4, reader); - // var peek_reader = peek_stream.reader(); - while (true) { - var lfh = try LocalFileHeader.read(allocator, reader); - defer lfh.deinit(allocator); - if (std.fs.path.dirname(lfh.file_name)) |dn| { - try dir.makePath(dn); - } - if (!lfh.is_dir()) { - var f = try dir.createFile(lfh.file_name, .{}); - defer f.close(); - var writer = f.writer(); - try lfh.extract(allocator, reader, writer); - } - try reader.skipBytes(12, .{}); // Data descriptor signature. - // _ = read_to_sig(peek_reader, LocalFileHeader.SIG) catch |e| switch (e) { - // error.EndOfStream => return, - // else => return e, - // }; - // try peek_stream.putBack(&@as([4]u8, @bitCast(LocalFileHeader.SIG))); - } + try std.testing.expectEqual(true, zf.is_dir(0)); + try std.testing.expectEqual(false, zf.is_dir(1)); + } - test "filesystem" { var f = try std.fs.cwd().openFile("src/subfolder.zip", .{}); defer f.close(); |