summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.zig76
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();