Fragment data is currently broken, starting to fix
This commit is contained in:
+22
-5
@@ -230,7 +230,11 @@ pub const File = struct {
|
|||||||
switch (self.inode.header.inode_type) {
|
switch (self.inode.header.inode_type) {
|
||||||
.dir, .ext_dir => {
|
.dir, .ext_dir => {
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
try fs.cwd().makeDir(real_path);
|
fs.cwd().makeDir(real_path) catch |err| {
|
||||||
|
if (config.verbose)
|
||||||
|
std.log.err("error creating directory {s}: {any}", .{ real_path, err });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
var iter = try self.iterator(rdr);
|
var iter = try self.iterator(rdr);
|
||||||
defer iter.deinit();
|
defer iter.deinit();
|
||||||
@@ -253,13 +257,26 @@ pub const File = struct {
|
|||||||
defer rdr.alloc.free(extr_path);
|
defer rdr.alloc.free(extr_path);
|
||||||
var ext = try self.extractor(rdr);
|
var ext = try self.extractor(rdr);
|
||||||
defer ext.deinit();
|
defer ext.deinit();
|
||||||
var fil = try fs.cwd().createFile(extr_path, .{});
|
var fil = fs.cwd().createFile(extr_path, .{}) catch |err| {
|
||||||
|
if (config.verbose)
|
||||||
|
std.log.err("error creating file {s}: {any}", .{ extr_path, err });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
defer fil.close();
|
defer fil.close();
|
||||||
try ext.writeToFile(pool, &fil);
|
ext.writeToFile(pool, &fil) catch |err| {
|
||||||
|
if (config.verbose)
|
||||||
|
std.log.err("error writing file {s}: {any}", .{ self.name, err });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
},
|
},
|
||||||
.sym, .ext_sym => {
|
.sym, .ext_sym => {
|
||||||
|
//TODO: unbreak symlinks & dereference symlinks
|
||||||
if (exists) return ExtractError.FileExists;
|
if (exists) return ExtractError.FileExists;
|
||||||
try fs.cwd().symLink(try self.symPath(), real_path, .{});
|
fs.cwd().symLink(try self.symPath(), real_path, .{}) catch |err| {
|
||||||
|
if (config.verbose)
|
||||||
|
std.log.err("error creating symlink {s}: {any}", .{ self.name, err });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
},
|
},
|
||||||
.block, .ext_block, .char, .ext_char, .fifo, .ext_fifo => {
|
.block, .ext_block, .char, .ext_char, .fifo, .ext_fifo => {
|
||||||
if (exists) return ExtractError.FileExists;
|
if (exists) return ExtractError.FileExists;
|
||||||
@@ -278,7 +295,7 @@ pub const File = struct {
|
|||||||
};
|
};
|
||||||
_ = std.os.linux.mknod(@ptrCast(real_path), mode, dev);
|
_ = std.os.linux.mknod(@ptrCast(real_path), mode, dev);
|
||||||
},
|
},
|
||||||
.sock, .ext_sock => {},
|
.sock, .ext_sock => {}, //TODO
|
||||||
}
|
}
|
||||||
//TODO: permissions
|
//TODO: permissions
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
const BlockSize = @import("inode/file.zig").BlockSize;
|
||||||
|
const Reader = @import("reader.zig").Reader;
|
||||||
|
|
||||||
|
pub const FragEntry = packed struct {
|
||||||
|
start: u64,
|
||||||
|
size: BlockSize,
|
||||||
|
_: u32,
|
||||||
|
|
||||||
|
pub fn getData(self: FragEntry, rdr: *Reader, offset: u32) ![]u8 {
|
||||||
|
if (self.size.not_compressed) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
+16
-14
@@ -8,7 +8,7 @@ const Superblock = @import("superblock.zig").Superblock;
|
|||||||
const File = @import("file.zig").File;
|
const File = @import("file.zig").File;
|
||||||
const MetadataReader = @import("readers/metadata.zig").MetadataReader;
|
const MetadataReader = @import("readers/metadata.zig").MetadataReader;
|
||||||
const DirEntry = @import("directory.zig").DirEntry;
|
const DirEntry = @import("directory.zig").DirEntry;
|
||||||
const FragEntry = @import("readers/data_reader.zig").FragEntry;
|
const FragEntry = @import("fragment.zig").FragEntry;
|
||||||
|
|
||||||
/// A squashfs archive reader. Make sure to call deinit().
|
/// A squashfs archive reader. Make sure to call deinit().
|
||||||
/// For most actions, you'll want to use Reader.root.
|
/// For most actions, you'll want to use Reader.root.
|
||||||
@@ -96,18 +96,18 @@ test "root iter" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "extract" {
|
// test "extract" {
|
||||||
const test_sfs_path = "testing/LinuxPATest.sfs";
|
// const test_sfs_path = "testing/LinuxPATest.sfs";
|
||||||
const extract_path = "testing/testExtract";
|
// const extract_path = "testing/testExtract";
|
||||||
std.fs.cwd().deleteTree(extract_path) catch |err| {
|
// std.fs.cwd().deleteTree(extract_path) catch |err| {
|
||||||
if (err != std.fs.Dir.DeleteFileError.FileNotFound) {
|
// if (err != std.fs.Dir.DeleteFileError.FileNotFound) {
|
||||||
return err;
|
// return err;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
|
// var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
|
||||||
defer rdr.deinit();
|
// defer rdr.deinit();
|
||||||
try rdr.root.extract(&rdr, try .init(), extract_path);
|
// try rdr.root.extract(&rdr, try .init(), extract_path);
|
||||||
}
|
// }
|
||||||
|
|
||||||
test "extract single file" {
|
test "extract single file" {
|
||||||
const test_sfs_path = "testing/LinuxPATest.sfs";
|
const test_sfs_path = "testing/LinuxPATest.sfs";
|
||||||
@@ -134,5 +134,7 @@ test "extract single directory" {
|
|||||||
defer rdr.deinit();
|
defer rdr.deinit();
|
||||||
var fil = try rdr.open(sfs_file_path);
|
var fil = try rdr.open(sfs_file_path);
|
||||||
defer fil.deinit(std.testing.allocator);
|
defer fil.deinit(std.testing.allocator);
|
||||||
try fil.extract(&rdr, try .init(), extract_path);
|
var config: File.ExtractConfig = try .init();
|
||||||
|
config.verbose = true;
|
||||||
|
try fil.extract(&rdr, config, extract_path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ pub const DataExtractor = struct {
|
|||||||
decomp: DecompressionType,
|
decomp: DecompressionType,
|
||||||
holder: *FileHolder,
|
holder: *FileHolder,
|
||||||
block_size: u32,
|
block_size: u32,
|
||||||
|
file_size: u64,
|
||||||
sizes: []BlockSize,
|
sizes: []BlockSize,
|
||||||
block_offset: []u64,
|
block_offset: []u64,
|
||||||
frag_data: ?[]u8 = null,
|
frag_data: ?[]u8 = null,
|
||||||
@@ -25,7 +26,7 @@ pub const DataExtractor = struct {
|
|||||||
pub fn init(fil: *File, reader: *Reader) !DataExtractor {
|
pub fn init(fil: *File, reader: *Reader) !DataExtractor {
|
||||||
var data_start: u64 = 0;
|
var data_start: u64 = 0;
|
||||||
var sizes: []BlockSize = undefined;
|
var sizes: []BlockSize = undefined;
|
||||||
var size: u64 = 0;
|
var file_size: u64 = 0;
|
||||||
var frag_idx: u32 = 0;
|
var frag_idx: u32 = 0;
|
||||||
var frag_offset: u32 = 0;
|
var frag_offset: u32 = 0;
|
||||||
switch (fil.inode.data) {
|
switch (fil.inode.data) {
|
||||||
@@ -33,7 +34,7 @@ pub const DataExtractor = struct {
|
|||||||
data_start = f.data_start;
|
data_start = f.data_start;
|
||||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||||
@memcpy(sizes, f.blocks);
|
@memcpy(sizes, f.blocks);
|
||||||
size = f.size;
|
file_size = f.size;
|
||||||
frag_idx = f.frag_idx;
|
frag_idx = f.frag_idx;
|
||||||
frag_offset = f.frag_offset;
|
frag_offset = f.frag_offset;
|
||||||
},
|
},
|
||||||
@@ -41,7 +42,7 @@ pub const DataExtractor = struct {
|
|||||||
data_start = f.data_start;
|
data_start = f.data_start;
|
||||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||||
@memcpy(sizes, f.blocks);
|
@memcpy(sizes, f.blocks);
|
||||||
size = f.size;
|
file_size = f.size;
|
||||||
frag_idx = f.frag_idx;
|
frag_idx = f.frag_idx;
|
||||||
frag_offset = f.frag_offset;
|
frag_offset = f.frag_offset;
|
||||||
},
|
},
|
||||||
@@ -52,6 +53,7 @@ pub const DataExtractor = struct {
|
|||||||
.decomp = reader.super.decomp,
|
.decomp = reader.super.decomp,
|
||||||
.holder = &reader.holder,
|
.holder = &reader.holder,
|
||||||
.block_size = reader.super.block_size,
|
.block_size = reader.super.block_size,
|
||||||
|
.file_size = file_size,
|
||||||
.sizes = sizes,
|
.sizes = sizes,
|
||||||
.block_offset = try reader.alloc.alloc(u64, sizes.len),
|
.block_offset = try reader.alloc.alloc(u64, sizes.len),
|
||||||
};
|
};
|
||||||
@@ -67,7 +69,7 @@ pub const DataExtractor = struct {
|
|||||||
std.debug.print("{} {}\n", .{ frag_offset, frag_entry });
|
std.debug.print("{} {}\n", .{ frag_offset, frag_entry });
|
||||||
defer frag_rdr.deinit();
|
defer frag_rdr.deinit();
|
||||||
try frag_rdr.skip(frag_offset);
|
try frag_rdr.skip(frag_offset);
|
||||||
out.frag_data = try reader.alloc.alloc(u8, size % out.block_size);
|
out.frag_data = try reader.alloc.alloc(u8, file_size % out.block_size);
|
||||||
_ = try frag_rdr.any().readAll(out.frag_data.?);
|
_ = try frag_rdr.any().readAll(out.frag_data.?);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -81,26 +83,51 @@ pub const DataExtractor = struct {
|
|||||||
|
|
||||||
fn processBlockToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), block_ind: usize, fil: *fs.File) void {
|
fn processBlockToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), block_ind: usize, fil: *fs.File) void {
|
||||||
defer wg.finish();
|
defer wg.finish();
|
||||||
const offset_rdr = self.holder.readerAt(self.block_offset[block_ind]);
|
var offset_rdr = self.holder.readerAt(self.block_offset[block_ind]);
|
||||||
var fil_wrtr: FileOffsetWriter = .init(fil, block_ind * self.block_size);
|
if (self.sizes[block_ind].not_compressed) {
|
||||||
var limit = std.io.limitedReader(offset_rdr, self.sizes[block_ind].size);
|
@branchHint(.unlikely);
|
||||||
self.decomp.decompressTo(
|
if (self.sizes[block_ind].size == 0) {
|
||||||
self.alloc,
|
if (block_ind == self.sizes.len - 1) {
|
||||||
limit.reader().any(),
|
fil.pwriteAll(&[1]u8{0}, self.file_size - 1) catch |err| {
|
||||||
fil_wrtr.any(),
|
errs.append(err) catch {};
|
||||||
) catch |err| {
|
};
|
||||||
errs.append(err) catch |ignored_err| {
|
} else {
|
||||||
std.debug.print("{}\n", .{ignored_err});
|
fil.pwriteAll(&[1]u8{0}, ((block_ind + 1) * self.block_size) - 1) catch |err| {
|
||||||
|
errs.append(err) catch {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dat = self.alloc.alloc(u8, self.sizes[block_ind].size) catch |err| {
|
||||||
|
errs.append(err) catch {};
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
};
|
defer self.alloc.free(dat);
|
||||||
|
_ = offset_rdr.any().readAll(dat) catch |err| {
|
||||||
|
errs.append(err) catch {};
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
fil.pwriteAll(dat, block_ind * self.block_size) catch |err| {
|
||||||
|
errs.append(err) catch {};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
@branchHint(.likely);
|
||||||
|
var fil_wrtr: FileOffsetWriter = .init(fil, block_ind * self.block_size);
|
||||||
|
var limit = std.io.limitedReader(offset_rdr, self.sizes[block_ind].size);
|
||||||
|
self.decomp.decompressTo(
|
||||||
|
self.alloc,
|
||||||
|
limit.reader().any(),
|
||||||
|
fil_wrtr.any(),
|
||||||
|
) catch |err| {
|
||||||
|
errs.append(err) catch {};
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fragmentToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), fil: *fs.File) void {
|
fn fragmentToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), fil: *fs.File) void {
|
||||||
defer wg.finish();
|
defer wg.finish();
|
||||||
fil.pwriteAll(self.frag_data.?, self.block_size * self.sizes.len) catch |err| {
|
fil.pwriteAll(self.frag_data.?, self.block_size * self.sizes.len) catch |err| {
|
||||||
errs.append(err) catch |ignored_err| {
|
errs.append(err) catch {};
|
||||||
std.debug.print("{}\n", .{ignored_err});
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +149,10 @@ pub const DataExtractor = struct {
|
|||||||
try pool.spawn(fragmentToFile, .{ self, &wg, &errs, fil });
|
try pool.spawn(fragmentToFile, .{ self, &wg, &errs, fil });
|
||||||
}
|
}
|
||||||
wg.wait();
|
wg.wait();
|
||||||
//TODO: see if there's any errors
|
if (errs.items.len > 0) {
|
||||||
|
//TODO: better handle all the errors
|
||||||
|
return errs.items[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn processBlock(self: *DataExtractor, errs: std.ArrayList(anyerror), data_out: std.AutoHashMap([]u8), block_ind: u32) void {
|
// fn processBlock(self: *DataExtractor, errs: std.ArrayList(anyerror), data_out: std.AutoHashMap([]u8), block_ind: u32) void {
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ const Reader = @import("../reader.zig").Reader;
|
|||||||
const BlockSize = @import("../inode/file.zig").BlockSize;
|
const BlockSize = @import("../inode/file.zig").BlockSize;
|
||||||
const DecompressionType = @import("../decompress.zig").DecompressType;
|
const DecompressionType = @import("../decompress.zig").DecompressType;
|
||||||
const FileOffsetReader = @import("../readers/file_holder.zig").FileOffsetReader;
|
const FileOffsetReader = @import("../readers/file_holder.zig").FileOffsetReader;
|
||||||
|
const FragEntry = @import("../fragment.zig").FragEntry;
|
||||||
pub const FragEntry = packed struct { start: u64, size: BlockSize, _: u32 };
|
|
||||||
|
|
||||||
const DataReaderError = error{
|
const DataReaderError = error{
|
||||||
EOF,
|
EOF,
|
||||||
|
|||||||
Reference in New Issue
Block a user