Added lookup Tables
Simplified Inode Data types & union Started work on decompression
This commit is contained in:
+3
-2
@@ -43,10 +43,11 @@ pub fn root(self: *Archive, alloc: std.mem.Allocator) !File {
|
||||
.data = self.map.memory,
|
||||
.super = self.super,
|
||||
|
||||
.inode = try .fromRef(
|
||||
.inode = try .readLocation(
|
||||
alloc,
|
||||
self.map.memory,
|
||||
self.root_inode_ref,
|
||||
self.root_inode_ref.start,
|
||||
self.root_inode_ref.offset,
|
||||
self.super,
|
||||
),
|
||||
.name = "",
|
||||
|
||||
+140
-103
@@ -11,9 +11,9 @@ const Inode = @This();
|
||||
header: Header,
|
||||
data: Data,
|
||||
|
||||
pub fn fromRef(alloc: std.mem.Allocator, data: []u8, ref: Reference, super: Super) !Inode {
|
||||
var meta: MetadataReader = .init(alloc, data[super.inode_table_start + ref.start ..], super.decomp_fn);
|
||||
try meta.interface.discardAll(ref.offset);
|
||||
pub fn readLocation(alloc: std.mem.Allocator, data: []u8, start: u32, offset: u16, super: Super) !Inode {
|
||||
var meta: MetadataReader = .init(alloc, data[super.inode_table_start + start ..], super.decomp_fn);
|
||||
try meta.interface.discardAll(offset);
|
||||
|
||||
return read(alloc, &meta.interface, super.block_size);
|
||||
}
|
||||
@@ -23,20 +23,15 @@ pub fn read(alloc: std.mem.Allocator, rdr: *Io.Reader, block_size: u32) !Inode {
|
||||
return .{
|
||||
.header = hdr,
|
||||
.data = switch (hdr.type) {
|
||||
.dir => .{ .dir = try .read(rdr) },
|
||||
.file => .{ .file = try .read(rdr, alloc, block_size) },
|
||||
.symlink => .{ .symlink = try .read(rdr, alloc) },
|
||||
.block_dev => .{ .block_dev = try .read(rdr) },
|
||||
.char_dev => .{ .char_dev = try .read(rdr) },
|
||||
.fifo => .{ .fifo = try .read(rdr) },
|
||||
.socket => .{ .socket = try .read(rdr) },
|
||||
.ext_dir => .{ .ext_dir = try .read(rdr) },
|
||||
.ext_file => .{ .ext_file = try .read(rdr, alloc, block_size) },
|
||||
.ext_symlink => .{ .ext_symlink = try .read(rdr, alloc) },
|
||||
.ext_block_dev => .{ .ext_block_dev = try .read(rdr) },
|
||||
.ext_char_dev => .{ .ext_char_dev = try .read(rdr) },
|
||||
.ext_fifo => .{ .ext_fifo = try .read(rdr) },
|
||||
.ext_socket => .{ .ext_socket = try .read(rdr) },
|
||||
.dir => .{ .dir = try .readBasic(rdr) },
|
||||
.ext_dir => .{ .dir = try .readExt(rdr) },
|
||||
.file => .{ .file = try .readBasic(rdr, alloc, block_size) },
|
||||
.ext_file => .{ .file = try .readExt(rdr, alloc, block_size) },
|
||||
.symlink, .ext_symlink => .{ .symlink = try .read(rdr, alloc) },
|
||||
.block_dev, .char_dev => .{ .dev = try .readBasic(rdr) },
|
||||
.ext_block_dev, .ext_char_dev => .{ .dev = try .readExt(rdr) },
|
||||
.fifo, .socket => .{ .fifo = try .readBasic(rdr) },
|
||||
.ext_fifo, .ext_socket => .{ .fifo = try .readExt(rdr) },
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -56,9 +51,7 @@ pub fn copy(self: Inode, alloc: std.mem.Allocator) !Inode {
|
||||
pub fn deinit(self: Inode, alloc: std.mem.Allocator) void {
|
||||
switch (self.data) {
|
||||
.file => |f| alloc.free(f.blocks),
|
||||
.ext_file => |f| alloc.free(f.blocks),
|
||||
.symlink => |s| alloc.free(s.target),
|
||||
.ext_symlink => |s| alloc.free(s.target),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@@ -103,111 +96,135 @@ pub const Header = extern struct {
|
||||
inode_num: u32,
|
||||
};
|
||||
|
||||
pub const Data = union(Type) {
|
||||
pub const Data = union(enum) {
|
||||
dir: Dir,
|
||||
file: File,
|
||||
symlink: Symlink,
|
||||
block_dev: Dev,
|
||||
char_dev: Dev,
|
||||
dev: Dev,
|
||||
fifo: Fifo,
|
||||
socket: Fifo,
|
||||
ext_dir: ExtDir,
|
||||
ext_file: ExtFile,
|
||||
ext_symlink: Symlink,
|
||||
ext_block_dev: ExtDev,
|
||||
ext_char_dev: ExtDev,
|
||||
ext_fifo: ExtFifo,
|
||||
ext_socket: ExtFifo,
|
||||
};
|
||||
|
||||
// Inode data types
|
||||
|
||||
pub const Dir = extern struct {
|
||||
start: u32,
|
||||
hard_links: u32,
|
||||
size: u16,
|
||||
offset: u16,
|
||||
parent_inode_num: u32,
|
||||
pub const Dir = struct {
|
||||
//RegularDir structure:
|
||||
// start: u32,
|
||||
// hard_links: u32,
|
||||
// size: u16,
|
||||
// offset: u16,
|
||||
// parent_inode_num: u32,
|
||||
// ExtDir structure
|
||||
// hard_links: u32,
|
||||
// size: u32,
|
||||
// start: u32,
|
||||
// parent_inode_num: u32,
|
||||
// idx_count: u16,
|
||||
// offset: u16,
|
||||
// xattr_idx: u32,
|
||||
// dir_indexes: []DirIndex,
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !Dir {
|
||||
return util.readValueRdr(Dir, rdr);
|
||||
}
|
||||
};
|
||||
pub const ExtDir = extern struct {
|
||||
hard_links: u32,
|
||||
size: u32,
|
||||
start: u32,
|
||||
parent_inode_num: u32,
|
||||
idx_count: u16,
|
||||
offset: u16,
|
||||
xattr_idx: u32,
|
||||
xattr_idx: ?u32,
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !ExtDir {
|
||||
return util.readValueRdr(ExtDir, rdr);
|
||||
pub fn readBasic(rdr: *Io.Reader) !Dir {
|
||||
var raw: [12]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
return .{
|
||||
.start = util.readValue(u32, raw[0..4]),
|
||||
.hard_links = util.readValue(u32, raw[4..8]),
|
||||
.size = util.readValue(u16, raw[8..10]),
|
||||
.offset = util.readValue(u16, raw[10..12]),
|
||||
.xattr_idx = null,
|
||||
};
|
||||
}
|
||||
pub fn readExt(rdr: *Io.Reader) !Dir {
|
||||
var raw: [24]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
return .{
|
||||
.hard_links = util.readValue(u32, raw[0..4]),
|
||||
.size = util.readValue(u32, raw[4..8]),
|
||||
.start = util.readValue(u32, raw[8..12]),
|
||||
.offset = util.readValue(u16, raw[18..20]),
|
||||
.xattr_idx = util.readValue(u32, raw[20..24]),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const File = struct {
|
||||
start: u32,
|
||||
//RegularFile structure:
|
||||
// start: u32,
|
||||
// frag_idx: u32,
|
||||
// frag_offset: u32,
|
||||
// size: u32,
|
||||
// block_sizes: []BlockSize,
|
||||
//ExtFile structure:
|
||||
// start: u64,
|
||||
// size: u64,
|
||||
// sparse: u64,
|
||||
// hard_links: u32,
|
||||
// frag_idx: u32,
|
||||
// frag_offset: u32,
|
||||
// xattr_idx: u32,
|
||||
// block_sizes: []BlockSize,
|
||||
|
||||
start: u64,
|
||||
frag_idx: u32,
|
||||
frag_offset: u32,
|
||||
size: u32,
|
||||
size: u64,
|
||||
blocks: []BlockSize,
|
||||
xattr_idx: ?u32,
|
||||
|
||||
pub fn read(rdr: *Io.Reader, alloc: std.mem.Allocator, block_size: u32) !File {
|
||||
pub fn readBasic(rdr: *Io.Reader, alloc: std.mem.Allocator, block_size: u32) !File {
|
||||
var raw: [16]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
const frag_idx = std.mem.readInt(u32, raw[4..8], .little);
|
||||
const size = std.mem.readInt(u32, raw[12..16], .little);
|
||||
const frag_idx = util.readValue(u32, raw[4..8]);
|
||||
const size = util.readValue(u32, raw[12..16]);
|
||||
|
||||
var num = size / block_size;
|
||||
if (frag_idx == 0xFFFFFFFF and size % block_size > 0)
|
||||
num += 1;
|
||||
const block_num = if (frag_idx == 0xFFFFFFFF)
|
||||
try std.math.divCeil(usize, size, block_size)
|
||||
else
|
||||
size / block_size;
|
||||
|
||||
const blocks = try alloc.alloc(BlockSize, num);
|
||||
try rdr.readSliceEndian(BlockSize, blocks, .little);
|
||||
const sizes = try alloc.alloc(BlockSize, block_num);
|
||||
try rdr.readSliceEndian(BlockSize, sizes, .little);
|
||||
|
||||
return .{
|
||||
.start = std.mem.readInt(u32, raw[0..4], .little),
|
||||
.start = util.readValue(u32, raw[0..4]),
|
||||
.frag_idx = frag_idx,
|
||||
.frag_offset = std.mem.readInt(u32, raw[8..12], .little),
|
||||
.frag_offset = util.readValue(u32, raw[8..12]),
|
||||
.size = size,
|
||||
.blocks = blocks,
|
||||
.blocks = sizes,
|
||||
.xattr_idx = null,
|
||||
};
|
||||
}
|
||||
};
|
||||
pub const ExtFile = struct {
|
||||
start: u64,
|
||||
size: u64,
|
||||
hard_links: u32,
|
||||
frag_idx: u32,
|
||||
frag_offset: u32,
|
||||
xattr_idx: u32,
|
||||
blocks: []BlockSize,
|
||||
|
||||
pub fn read(rdr: *Io.Reader, alloc: std.mem.Allocator, block_size: u32) !ExtFile {
|
||||
pub fn readExt(rdr: *Io.Reader, alloc: std.mem.Allocator, block_size: u32) !File {
|
||||
var raw: [40]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
const frag_idx = std.mem.readInt(u32, raw[28..32], .little);
|
||||
const size = std.mem.readInt(u64, raw[8..16], .little);
|
||||
const frag_idx = util.readValue(u32, raw[28..32]);
|
||||
const size = util.readValue(u64, raw[8..16]);
|
||||
|
||||
var num = size / block_size;
|
||||
if (frag_idx == 0xFFFFFFFF and size % block_size > 0)
|
||||
num += 1;
|
||||
const block_num = if (frag_idx == 0xFFFFFFFF)
|
||||
try std.math.divCeil(usize, size, block_size)
|
||||
else
|
||||
size / block_size;
|
||||
|
||||
const blocks = try alloc.alloc(BlockSize, num);
|
||||
try rdr.readSliceEndian(BlockSize, blocks, .little);
|
||||
const sizes = try alloc.alloc(BlockSize, block_num);
|
||||
try rdr.readSliceEndian(BlockSize, sizes, .little);
|
||||
|
||||
return .{
|
||||
.start = std.mem.readInt(u64, raw[0..8], .little),
|
||||
.start = util.readValue(u64, raw[0..8]),
|
||||
.size = size,
|
||||
.hard_links = std.mem.readInt(u32, raw[24..28], .little),
|
||||
.frag_idx = frag_idx,
|
||||
.frag_offset = std.mem.readInt(u32, raw[32..36], .little),
|
||||
.xattr_idx = std.mem.readInt(u32, raw[36..], .little),
|
||||
.blocks = blocks,
|
||||
.frag_offset = util.readValue(u32, raw[32..36]),
|
||||
.blocks = sizes,
|
||||
.xattr_idx = util.readValue(u32, raw[36..40]),
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -215,6 +232,7 @@ pub const ExtFile = struct {
|
||||
pub const Symlink = struct {
|
||||
hard_links: u32,
|
||||
target: []const u8,
|
||||
// xattr_idx is ignored on extended symlinks as you can't apply them to symlinks anyway.
|
||||
|
||||
pub fn read(rdr: *Io.Reader, alloc: std.mem.Allocator) !Symlink {
|
||||
var raw: [8]u8 = undefined;
|
||||
@@ -232,36 +250,55 @@ pub const Symlink = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Dev = extern struct {
|
||||
pub const Dev = struct {
|
||||
hard_links: u32,
|
||||
device: u32,
|
||||
// xattr_idx omitted on basic device inodes.
|
||||
xattr_idx: ?u32,
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !Dev {
|
||||
return util.readValueRdr(Dev, rdr);
|
||||
pub fn readBasic(rdr: *Io.Reader) !Dev {
|
||||
var raw: [8]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
return .{
|
||||
.hard_links = util.readValue(u32, raw[0..4]),
|
||||
.device = util.readValue(u32, raw[4..8]),
|
||||
.xattr_idx = null,
|
||||
};
|
||||
}
|
||||
pub fn readExt(rdr: *Io.Reader) !Dev {
|
||||
var raw: [12]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
return .{
|
||||
.hard_links = util.readValue(u32, raw[0..4]),
|
||||
.device = util.readValue(u32, raw[4..8]),
|
||||
.xattr_idx = util.readValue(u32, raw[8..12]),
|
||||
};
|
||||
}
|
||||
};
|
||||
pub const ExtDev = extern struct {
|
||||
|
||||
pub const Fifo = struct {
|
||||
hard_links: u32,
|
||||
device: u32,
|
||||
xattr_idx: u32,
|
||||
// Xattr_idx omitted on basic fifo inodes.
|
||||
xattr_idx: ?u32,
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !ExtDev {
|
||||
return util.readValueRdr(ExtDev, rdr);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Fifo = extern struct {
|
||||
hard_links: u32,
|
||||
pub fn readBasic(rdr: *Io.Reader) !Fifo {
|
||||
var raw: [4]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !Fifo {
|
||||
return util.readValueRdr(Fifo, rdr);
|
||||
return .{
|
||||
.hard_links = util.readValue(u32, raw[0..4]),
|
||||
.xattr_idx = null,
|
||||
};
|
||||
}
|
||||
};
|
||||
pub const ExtFifo = extern struct {
|
||||
hard_links: u32,
|
||||
xattr_idx: u32,
|
||||
pub fn readExt(rdr: *Io.Reader) !Fifo {
|
||||
var raw: [8]u8 = undefined;
|
||||
try rdr.readSliceAll(&raw);
|
||||
|
||||
pub fn read(rdr: *Io.Reader) !ExtFifo {
|
||||
return util.readValueRdr(ExtFifo, rdr);
|
||||
return .{
|
||||
.hard_links = util.readValue(u32, raw[0..4]),
|
||||
.xattr_idx = util.readValue(u32, raw[4..8]),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const util = @import("utils/util.zig");
|
||||
|
||||
const MetadataReader = @import("utils/meta.zig");
|
||||
const Decomp = @import("decomp.zig");
|
||||
|
||||
pub fn Table(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
const ITEMS_PER_BLOCK = 8192 / @sizeOf(T);
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
data: []u8,
|
||||
decomp: Decomp.Fn,
|
||||
|
||||
start: u64,
|
||||
count: u32,
|
||||
block_count: u32,
|
||||
|
||||
table: std.hash_map.AutoHashMapUnmanaged(u32, []T) = .empty,
|
||||
mut: Io.Mutex = .init,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, start: u64, count: u32) !Self {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
|
||||
.data = data,
|
||||
.decomp = decomp,
|
||||
|
||||
.start = start,
|
||||
.count = count,
|
||||
.block_count = std.math.divCeil(u32, count, ITEMS_PER_BLOCK),
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: *Self) void {
|
||||
var iter = self.table.valueIterator();
|
||||
while (iter.next()) |block|
|
||||
self.alloc.free(block);
|
||||
|
||||
self.table.deinit(self.alloc);
|
||||
}
|
||||
|
||||
fn getBlock(self: *Self, io: Io, idx: u32) ![]T {
|
||||
const init_get = self.table.get(idx);
|
||||
if (init_get != null) return init_get.?;
|
||||
|
||||
self.mut.lock(io);
|
||||
defer self.mut.unlock(io);
|
||||
|
||||
const start = util.readValue(u64, self.data[self.start + (idx * 8) ..][0..8]);
|
||||
|
||||
const len = if (idx == self.block_count - 1) self.count % ITEMS_PER_BLOCK else ITEMS_PER_BLOCK;
|
||||
|
||||
const new_block = try self.alloc.alloc(T, len);
|
||||
errdefer self.alloc.free(new_block);
|
||||
|
||||
var meta: MetadataReader = .init(self.alloc, self.data[start..], self.decomp);
|
||||
|
||||
try meta.interface.readSliceEndian(T, new_block, .little);
|
||||
|
||||
try self.table.put(self.alloc, idx, new_block);
|
||||
|
||||
return new_block;
|
||||
}
|
||||
|
||||
pub fn get(self: *Self, io: Io, idx: u32) !T {
|
||||
if (idx >= self.count) return error.InvalidIndex;
|
||||
|
||||
const block_idx = idx / ITEMS_PER_BLOCK;
|
||||
|
||||
const block = self.getBlock(io, block_idx);
|
||||
|
||||
return block[idx % ITEMS_PER_BLOCK];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -31,11 +31,11 @@ interface: Io.Reader = .{
|
||||
},
|
||||
},
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, block_size: u32, start: u64, size: u64, blocks: []BlockSize) DataReader {
|
||||
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, block_size: u32, size: u64, blocks: []BlockSize) DataReader {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
|
||||
.data = data[start..],
|
||||
.data = data,
|
||||
.decomp = decomp,
|
||||
.block_size = block_size,
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const Options = @import("../options.zig");
|
||||
const Inode = @import("../inode.zig");
|
||||
const Decomp = @import("../decomp.zig");
|
||||
const Directory = @import("../dir.zig");
|
||||
const MetadataReader = @import("meta.zig");
|
||||
const DataReader = @import("data_reader.zig");
|
||||
const Super = @import("../archive.zig").Super;
|
||||
|
||||
pub fn single(alloc: std.mem.Allocator, io: Io, data: []const u8, decomp: Decomp.Fn, super: Super, inode: Inode, filepath: []const u8, options: Options) !void {
|
||||
const path = std.mem.trim(u8, filepath, "/");
|
||||
|
||||
var pool: std.ArrayList(InodeAndPath) = .initBuffer(&.{.{ .inode = inode, .path = path }});
|
||||
defer {
|
||||
while (pool.pop()) |in|
|
||||
in.deinit(in);
|
||||
pool.deinit(alloc);
|
||||
}
|
||||
|
||||
var dirs: std.ArrayList(InodeAndPath) = .empty;
|
||||
defer {
|
||||
while (dirs.pop()) |dir|
|
||||
alloc.free(dir.path);
|
||||
dirs.deinit(alloc);
|
||||
}
|
||||
|
||||
// TODO: Use options
|
||||
_ = options;
|
||||
|
||||
while (pool.pop()) |in| {
|
||||
switch (in.inode.data) {
|
||||
.dir => |d| {
|
||||
try Io.Dir.cwd().createDirPath(io, in.path);
|
||||
|
||||
if (d.size <= 3) {
|
||||
defer if (in.path.len != path.len)
|
||||
in.deinit(alloc);
|
||||
// TODO: apply permissions & xattrs immediately.
|
||||
continue;
|
||||
}
|
||||
|
||||
var meta: MetadataReader = .init(alloc, data[d.start], decomp);
|
||||
try meta.interface.discardAll(d.offset);
|
||||
|
||||
var dir: Directory = .read(alloc, &meta.interface, d.size);
|
||||
defer dir.deinit(alloc);
|
||||
|
||||
for (dir.entries) |entry| {
|
||||
const new_inode: Inode = try .readLocation(alloc, data, entry.start, entry.offset, super);
|
||||
|
||||
const new_path = std.mem.concat(alloc, u8, &.{ in.path, "/", entry.name }) catch |err| {
|
||||
new_inode.deinit(alloc);
|
||||
return err;
|
||||
};
|
||||
|
||||
try pool.append(alloc, .{ .inode = new_inode, .path = new_path });
|
||||
}
|
||||
|
||||
try dirs.append(alloc, in);
|
||||
},
|
||||
.file => |f| {
|
||||
defer if (in.path.len != path.len)
|
||||
in.deinit(alloc);
|
||||
|
||||
var atomic = try Io.Dir.cwd().createFileAtomic(io, in.path, .{});
|
||||
defer atomic.deinit(io);
|
||||
|
||||
var rdr: DataReader = .init(alloc, data[f.start..], decomp, super.block_size, f.size, f.blocks);
|
||||
defer rdr.deinit();
|
||||
|
||||
if (f.frag_idx != 0xFFFFFFFF) {
|
||||
//TODO: fragment
|
||||
}
|
||||
|
||||
var writer = atomic.file.writer(io, &[0]u8{}); // TODO: find a resonable buffer size.
|
||||
try rdr.interface.streamRemaining(&writer.interface);
|
||||
|
||||
// TODO: apply permissions & xattrs
|
||||
|
||||
try atomic.link(io);
|
||||
},
|
||||
.symlink => |s| {
|
||||
defer if (in.path.len != path.len)
|
||||
in.deinit(alloc);
|
||||
|
||||
try Io.Dir.cwd().symLink(io, s.target, in.path, .{});
|
||||
},
|
||||
.dev => |d| {
|
||||
defer if (in.path.len != path.len)
|
||||
in.deinit(alloc);
|
||||
|
||||
const mode = switch (in.inode.header.type) {
|
||||
.char_dev, .ext_char_dev => std.os.linux.DT.CHR,
|
||||
.block_dev, .ext_block_dev => std.os.linux.DT.BLK,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const sent_path = try alloc.dupeSentinel(u8, in.path, 0);
|
||||
|
||||
const res = std.os.linux.mknod(sent_path, mode, d.device);
|
||||
alloc.free(sent_path);
|
||||
if (res != 0)
|
||||
return error.MkNodError;
|
||||
|
||||
// TODO: apply permissions & xattrs
|
||||
},
|
||||
.fifo => |f| {
|
||||
_ = f;
|
||||
|
||||
defer if (in.path.len != path.len)
|
||||
in.deinit(alloc);
|
||||
|
||||
const mode = switch (in.inode.header.type) {
|
||||
.fifo, .ext_fifo => std.os.linux.DT.FIFO,
|
||||
.socket, .ext_socket => std.os.linux.DT.SOCK,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const sent_path = try alloc.dupeSentinel(u8, in.path, 0);
|
||||
|
||||
const res = std.os.linux.mknod(sent_path, mode, 0);
|
||||
alloc.free(sent_path);
|
||||
if (res != 0)
|
||||
return error.MkNodError;
|
||||
|
||||
// TODO: apply permissions & xattrs
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
while (dirs.pop()) |dir| {
|
||||
defer if (dir.path.len != path.len)
|
||||
alloc.free(dir.path);
|
||||
// TODO: apply permissions & xattrs
|
||||
}
|
||||
}
|
||||
const InodeAndPath = struct {
|
||||
inode: Inode,
|
||||
path: []const u8,
|
||||
|
||||
fn deinit(self: InodeAndPath, alloc: std.mem.Allocator) void {
|
||||
self.inode.deinit(alloc);
|
||||
alloc.free(self.path);
|
||||
}
|
||||
};
|
||||
pub fn multi() !void {}
|
||||
Reference in New Issue
Block a user