229 lines
5.7 KiB
C++
229 lines
5.7 KiB
C++
#include <mercury/kernel/fs/tarfs.hpp>
|
|
|
|
//in fs::tarfs_instance, storage::node_id_t refers to the number
|
|
//of bytes into the block device that the info sector is located
|
|
|
|
namespace mercury::kernel::fs {
|
|
|
|
storage::io_result tarfs_mounter(
|
|
storage::block_device *bd, storage::file_system_instance *&fs_out
|
|
) {
|
|
fs_out = new tarfs_instance(bd);
|
|
return storage::io_result::success;
|
|
}
|
|
|
|
tarfs_instance::tarfs_instance(storage::block_device *bd) : bd(bd) {}
|
|
|
|
storage::io_result tarfs_instance::next_node(storage::node_id_t &node) {
|
|
uint64_t file_length;
|
|
storage::io_result result = read_num(node + 124, 12, file_length);
|
|
if (result != storage::io_result::success)
|
|
return result;
|
|
node += ((file_length - 1) / 512 + 2) * 512;
|
|
return storage::io_result::success;
|
|
}
|
|
|
|
storage::io_result tarfs_instance::read_name(
|
|
storage::node_id_t node, char *name_buf, size_t &name_len_out
|
|
) {
|
|
name_len_out = 0;
|
|
storage::io_result result = bd->read_bytes(node + 345, 155, name_buf);
|
|
if (result != storage::io_result::success)
|
|
return result;
|
|
while (name_buf[name_len_out] && name_len_out < 155)
|
|
++name_len_out;
|
|
result = bd->read_bytes(node, 100, name_buf + name_len_out);
|
|
if (result != storage::io_result::success)
|
|
return result;
|
|
size_t new_limit = name_len_out + 100;
|
|
while (name_buf[name_len_out] && name_len_out < new_limit)
|
|
++name_len_out;
|
|
return storage::io_result::success;
|
|
}
|
|
|
|
storage::io_result tarfs_instance::read_num(
|
|
uint64_t offset, size_t len, uint64_t &out
|
|
) {
|
|
|
|
//len <= 12
|
|
char buffer[12];
|
|
storage::io_result result = bd->read_bytes(offset, len, buffer);
|
|
if (result != storage::io_result::success)
|
|
return result;
|
|
out = 0;
|
|
|
|
for (size_t i = 0; i < len; ++i) {
|
|
if (!buffer[i])
|
|
return i == 0 ? storage::io_result::fs_corrupt
|
|
: storage::io_result::success;
|
|
if (buffer[i] < '0' || buffer[i] > '7')
|
|
return storage::io_result::fs_corrupt;
|
|
out = out * 8 + buffer[i] - '0';
|
|
}
|
|
|
|
return storage::io_result::success;
|
|
|
|
}
|
|
|
|
#define RETURN_MAYBE_NOT_FOUND(expr) \
|
|
{ \
|
|
storage::io_result _result = expr; \
|
|
if (_result == storage::io_result::out_of_bounds) \
|
|
return storage::io_result::not_found; \
|
|
if (_result != storage::io_result::success) \
|
|
return _result; \
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_root_node(storage::node_id_t &out) {
|
|
out = 0;
|
|
while (true) {
|
|
char name_buf[255];
|
|
size_t name_len;
|
|
RETURN_MAYBE_NOT_FOUND(read_name(out, name_buf, name_len))
|
|
if (name_len == 2 && name_buf[0] == '.' && name_buf[1] == '/')
|
|
return storage::io_result::success;
|
|
RETURN_MAYBE_NOT_FOUND(next_node(out))
|
|
}
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_first_child(storage::node_id_t node,
|
|
storage::node_id_t &out, storage::directory_iter_t &iter_out
|
|
) {
|
|
|
|
out = 0;
|
|
while (true) {
|
|
|
|
char name_buf[255];
|
|
size_t name_len;
|
|
RETURN_MAYBE_NOT_FOUND(read_name(out, name_buf, name_len))
|
|
|
|
//TODO
|
|
while (1)
|
|
;
|
|
|
|
RETURN_MAYBE_NOT_FOUND(next_node(out))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_next_child(storage::node_id_t node,
|
|
storage::node_id_t &out, storage::directory_iter_t &iter
|
|
) {
|
|
|
|
out = iter;
|
|
while (true) {
|
|
|
|
char name_buf[255];
|
|
size_t name_len;
|
|
RETURN_MAYBE_NOT_FOUND(read_name(out, name_buf, name_len))
|
|
|
|
//TODO
|
|
//NOTE: before return, do iter = out.
|
|
while (1)
|
|
;
|
|
|
|
|
|
RETURN_MAYBE_NOT_FOUND(next_node(out))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_child(storage::node_id_t node,
|
|
storage::node_id_t &out, const char *name, size_t name_len
|
|
) {
|
|
|
|
char full_name[255];
|
|
size_t full_name_len;
|
|
RETURN_MAYBE_NOT_FOUND(read_name(node, full_name, full_name_len))
|
|
|
|
if (full_name_len + name_len > 255)
|
|
return storage::io_result::not_supported;
|
|
|
|
for (size_t i = 0; i < name_len; ++i)
|
|
full_name[full_name_len + i] = name[i];
|
|
full_name_len += name_len;
|
|
|
|
out = 0;
|
|
while (true) {
|
|
|
|
char cand_name[255];
|
|
size_t cand_name_len;
|
|
RETURN_MAYBE_NOT_FOUND(read_name(out, cand_name, cand_name_len))
|
|
|
|
if (cand_name_len != full_name_len && cand_name_len != full_name_len + 1)
|
|
goto next_iter;
|
|
for (size_t i = 0; i < full_name_len; ++i)
|
|
if (cand_name[i] != full_name[i])
|
|
goto next_iter;
|
|
if (cand_name_len == full_name_len + 1 &&
|
|
cand_name[full_name_len] != '/')
|
|
goto next_iter;
|
|
|
|
return storage::io_result::success;
|
|
|
|
next_iter:
|
|
RETURN_MAYBE_NOT_FOUND(next_node(out))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_name_length(
|
|
storage::node_id_t node, size_t &length_out
|
|
) {
|
|
|
|
//TODO
|
|
while (1)
|
|
;
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_name(
|
|
storage::node_id_t node, char *buffer, size_t &length_out
|
|
) {
|
|
|
|
//TODO
|
|
while (1)
|
|
;
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_file_length(
|
|
storage::node_id_t node, uint64_t &length_out
|
|
) {
|
|
|
|
//TODO
|
|
while (1)
|
|
;
|
|
|
|
}
|
|
|
|
storage::io_result tarfs_instance::get_file_type(
|
|
storage::node_id_t node, storage::file_type &out
|
|
) {
|
|
|
|
uint64_t ft;
|
|
storage::io_result result = read_num(node + 156, 1, ft);
|
|
if (result != storage::io_result::success)
|
|
return result;
|
|
|
|
switch (ft) {
|
|
case 0:
|
|
out = storage::file_type::regular_file;
|
|
return storage::io_result::success;
|
|
case 2:
|
|
out = storage::file_type::symlink;
|
|
return storage::io_result::success;
|
|
case 5:
|
|
out = storage::file_type::directory;
|
|
return storage::io_result::success;
|
|
default:
|
|
return storage::io_result::not_supported;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|