diff --git a/src/decompress.zig b/src/decompress.zig index b23a614..8937c54 100644 --- a/src/decompress.zig +++ b/src/decompress.zig @@ -1,5 +1,6 @@ const std = @import("std"); const io = std.io; +const compress = std.compress; const DecompressError = error{ LzoUnsupported, @@ -14,29 +15,29 @@ pub const DecompressType = enum(u16) { lz4, zstd, - pub fn decompress(self: DecompressType, alloc: std.mem.Allocator, in: io.AnyReader) !std.ArrayList(u8) { - const out: std.ArrayList(u8) = .init(alloc); + pub fn decompress(self: DecompressType, alloc: std.mem.Allocator, rdr: io.AnyReader) !std.ArrayList(u8) { + var out = std.ArrayList(u8).init(alloc); switch (self) { - .zlib => try std.compress.zlib.decompress(in, out), + .zlib => try compress.zlib.decompress(rdr, out.writer()), .lzma => { - const decomp = try std.compress.lzma.decompress(alloc, in); + var decomp = try compress.lzma.decompress(alloc, rdr); defer decomp.deinit(); - try decomp.reader().readAllArrayList(&out, 1048576); + try decomp.reader().readAllArrayList(&out, 1024 * 1024); }, .lzo => return DecompressError.LzoUnsupported, .xz => { - const decomp = try std.compress.xz.decompress(alloc, in); + var decomp = try compress.xz.decompress(alloc, rdr); defer decomp.deinit(); - try decomp.reader().readAllArrayList(&out, 1048576); + try decomp.reader().readAllArrayList(&out, 1024 * 1024); }, .lz4 => return DecompressError.Lz4Unsupported, .zstd => { - const buf = try alloc.alloc(u8, std.compress.zstd.DecompressorOptions.default_window_buffer_len); + const buf = try alloc.alloc(u8, compress.zstd.DecompressorOptions.default_window_buffer_len); defer alloc.free(buf); - const decomp = std.compress.zstd.decompressor(in, .{ + var decomp = compress.zstd.decompressor(rdr, .{ .window_buffer = buf, }); - try decomp.reader().readAllArrayList(&out, 1048576); + try decomp.reader().readAllArrayList(&out, 1024 * 1024); }, } return out; diff --git a/src/directory.zig b/src/directory.zig new file mode 100644 index 0000000..285f577 --- /dev/null +++ b/src/directory.zig @@ -0,0 +1,5 @@ +pub const DirHeader = packed struct {}; + +pub const RawDirEntry = struct {}; + +pub const DirEntry = struct {}; diff --git a/src/file.zig b/src/file.zig index 2a0e42d..2a2730f 100644 --- a/src/file.zig +++ b/src/file.zig @@ -1 +1,60 @@ -pub const File = struct {}; //TODO +const std = @import("std"); +const io = std.io; + +const inode = @import("inode/inode.zig"); + +const Reader = @import("reader.zig").Reader; +const DirEntry = @import("directory.zig").DirEntry; +const MetadataReader = @import("readers/metadata.zig").MetadataReader; + +const FileError = error{ + NotDirectory, + NotNormalFile, + NotSymlink, +}; + +pub const File = struct { + reader: *Reader, + name: []const u8, + inode: inode.Inode, + + pub fn fromRef(read: *Reader, ref: inode.InodeRef, name: []const u8) !File { + var meta_rdr: MetadataReader = try .init( + read.arena.allocator(), + read.holder.anyAt(ref.block_start + read.super.inode_table_start), + read.super.decomp, + ); + defer meta_rdr.deinit(); + try meta_rdr.skip(ref.offset); + return .{ + .reader = read, + .name = name, + .inode = try .init( + read.arena.allocator(), + meta_rdr.any(), + read.super.block_size, + ), + }; + } + + // pub fn fromDirEntry(read: Reader, ent: DirEntry) !File {} + + pub fn open(self: File, path: []const u8) !File { + if (path.len == 0 || std.mem.eql(u8, path, ".")) { + return self; + } + switch (inode.InodeHeader.inode_type) { + .dir, .ext_dir => {}, + else => return FileError.NotDirectory, + } + //TODO: read dir entries and find correct inode and file + } + + pub fn symPath(self: File) ![]const u8 { + return switch (self.inode.data) { + .sym => |s| s.target, + .ext_sym => |s| s.target, + else => FileError.NotSymlink, + }; + } +}; diff --git a/src/inode/file.zig b/src/inode/file.zig index 90b4a3f..41a1d12 100644 --- a/src/inode/file.zig +++ b/src/inode/file.zig @@ -1,7 +1,11 @@ const std = @import("std"); const io = std.io; -pub const BlockSize = packed struct { size: u23, not_compressed: bool, _: u8 }; +pub const BlockSize = packed struct { + size: u23, + not_compressed: bool, + _: u8, +}; pub const FileInode = struct { data_start: u32, @@ -11,8 +15,8 @@ pub const FileInode = struct { blocks: []const BlockSize, pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !FileInode { - const fixed_buf = [_]u8{0} ** 16; - _ = try rdr.readAll(&fixed_buf); + var fixed_buf = [_]u8{0} ** 16; + _ = try rdr.readAll(@ptrCast(&fixed_buf)); const frag_idx = std.mem.bytesToValue(u32, fixed_buf[4..8]); const size = std.mem.bytesToValue(u32, fixed_buf[12..16]); var block_num = size / block_size; @@ -20,7 +24,7 @@ pub const FileInode = struct { block_num += 1; } const blocks = try alloc.alloc(BlockSize, block_num); - _ = try rdr.readAll(std.mem.asBytes(blocks)); + _ = try rdr.readAll(@ptrCast(blocks)); return .{ .data_start = std.mem.bytesToValue(u32, fixed_buf[0..4]), .frag_idx = frag_idx, @@ -45,7 +49,7 @@ pub const ExtFileInode = struct { blocks: []const BlockSize, pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !ExtFileInode { - const fixed_buf = [_]u8{0} ** 40; + var fixed_buf = [_]u8{0} ** 40; _ = try rdr.readAll(&fixed_buf); const size = std.mem.bytesToValue(u64, fixed_buf[8..16]); const frag_idx = std.mem.bytesToValue(u32, fixed_buf[28..32]); @@ -54,7 +58,7 @@ pub const ExtFileInode = struct { block_num += 1; } const blocks = try alloc.alloc(BlockSize, block_num); - _ = try rdr.readAll(std.mem.asBytes(blocks)); + _ = try rdr.readAll(@ptrCast(blocks)); return .{ .data_start = std.mem.bytesToValue(u64, fixed_buf[0..8]), .size = size, diff --git a/src/inode/inode.zig b/src/inode/inode.zig index b704a35..8bf82d8 100644 --- a/src/inode/inode.zig +++ b/src/inode/inode.zig @@ -4,7 +4,14 @@ const io = std.io; pub const InodeRef = packed struct { offset: u16, block_start: u32, - _: u16, + _: u16 = 0, + + pub fn init(block_start: u32, offset: u16) InodeRef { + return .{ + .offset = offset, + .block_start = block_start, + }; + } }; pub const InodeType = enum(u16) { diff --git a/src/inode/sym.zig b/src/inode/sym.zig index 5c3bebf..8f68c85 100644 --- a/src/inode/sym.zig +++ b/src/inode/sym.zig @@ -7,8 +7,8 @@ pub const SymInode = struct { target: []const u8, pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader) !SymInode { - const fixed_buf = [_]u8{0} ** 8; - _ = try rdr.readAll(&fixed_buf); + var fixed_buf = [_]u8{0} ** 8; + _ = try rdr.readAll(@ptrCast(&fixed_buf)); const size = std.mem.bytesToValue(u32, fixed_buf[4..]); const target = try alloc.alloc(u8, size); _ = try rdr.readAll(target); @@ -30,7 +30,7 @@ pub const ExtSymInode = struct { xattr_idx: u32, pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader) !ExtSymInode { - const fixed_buf = [_]u8{0} ** 8; + var fixed_buf = [_]u8{0} ** 8; _ = try rdr.readAll(&fixed_buf); const size = std.mem.bytesToValue(u32, fixed_buf[4..]); const target = try alloc.alloc(u8, size); @@ -39,7 +39,7 @@ pub const ExtSymInode = struct { .hard_links = std.mem.bytesToValue(u32, fixed_buf[0..4]), .size = size, .target = target, - .xattr_idx = rdr.readInt(u32, std.builtin.Endian.little), + .xattr_idx = try rdr.readInt(u32, std.builtin.Endian.little), }; } pub fn deinit(self: ExtSymInode, alloc: std.mem.Allocator) void { diff --git a/src/reader.zig b/src/reader.zig index fc21dd6..1dc32ee 100644 --- a/src/reader.zig +++ b/src/reader.zig @@ -2,22 +2,27 @@ const std = @import("std"); const FileHolder = @import("readers/file_holder.zig").FileHolder; const Superblock = @import("superblock.zig").Superblock; +const File = @import("file.zig").File; pub const Reader = struct { arena: std.heap.ArenaAllocator, holder: FileHolder, super: Superblock, + root: File, pub fn init(alloc: std.mem.Allocator, filepath: []const u8, offset: u64) !Reader { var holder: FileHolder = try .init(filepath, offset); const super: Superblock = try holder.anyAt(0).readStruct(Superblock); try super.validate(); const arena: std.heap.ArenaAllocator = .init(alloc); - return .{ + var out: Reader = .{ .arena = arena, .holder = holder, .super = super, + .root = undefined, }; + out.root = try .fromRef(&out, super.root_ref, ""); + return out; } pub fn deinit(self: *const Reader) void { self.arena.deinit(); @@ -27,6 +32,7 @@ pub const Reader = struct { test "reader" { const test_file_path = "testing/LinuxPATest.sfs"; - const rdr: Reader = try .init(std.testing.allocator, test_file_path, 0); + var rdr: Reader = try .init(std.testing.allocator, test_file_path, 0); defer rdr.deinit(); + std.debug.print("{}\n", .{rdr.root}); } diff --git a/src/readers/file_holder.zig b/src/readers/file_holder.zig index da248b1..54b72a6 100644 --- a/src/readers/file_holder.zig +++ b/src/readers/file_holder.zig @@ -7,7 +7,7 @@ pub const FileHolder = struct { offset: u64, pub fn init(path: []const u8, offset: u64) !FileHolder { - const fil = try fs.cwd().openFile(path, .{}); + const fil = try fs.cwd().openFile(path, .{ .mode = .read_write }); return .{ .file = fil, .offset = offset, @@ -17,7 +17,7 @@ pub const FileHolder = struct { self.file.close(); } - pub fn anyAt(self: FileHolder, offset: u64) io.AnyReader { + pub fn anyAt(self: *FileHolder, offset: u64) io.AnyReader { var offsetRdr = FileOffsetReader{ .file = self.file, .offset = self.offset + offset, @@ -31,7 +31,8 @@ const FileOffsetReader = struct { offset: u64, fn read(self: *FileOffsetReader, bytes: []u8) !usize { - const red = try self.file.pread(bytes, self.offset); + std.debug.print("yo {}\n", .{self.file.open()}); + const red = try self.file.preadAll(bytes, self.offset); self.offset += red; return red; } diff --git a/src/readers/metadata.zig b/src/readers/metadata.zig index a7322a3..a3cf54b 100644 --- a/src/readers/metadata.zig +++ b/src/readers/metadata.zig @@ -30,6 +30,17 @@ pub const MetadataReader = struct { self.alloc.free(self.block); } + pub fn skip(self: *MetadataReader, offset: u16) !void { + var cur_skip: u32 = 0; + var to_skip: u32 = 0; + while (cur_skip < offset) { + if (self.offset >= self.block.len) try self.readNextBlock(); + to_skip = @min(offset - cur_skip, self.block.len - self.offset); + cur_skip += to_skip; + self.offset += to_skip; + } + } + fn readNextBlock(self: *MetadataReader) !void { self.offset = 0; if (self.block.len > 0) self.alloc.free(self.block); @@ -38,9 +49,9 @@ pub const MetadataReader = struct { self.block = try self.alloc.alloc(u8, hdr.size); _ = try self.reader.readAll(self.block); } else { - const limit = std.io.limitedReader(self.reader, hdr.size); - const dat = try self.decomp.decompress(self.alloc, limit.reader().any()); - self.block = dat.toOwnedSlice(); + var limit = std.io.limitedReader(self.reader, hdr.size); + var dat = try self.decomp.decompress(self.alloc, limit.reader().any()); + self.block = try dat.toOwnedSlice(); } }