bool cpio_file::try_read_new_ascii_file_entry()

in src/native/archives/cpio_archives/cpio_file.cpp [262:346]


bool cpio_file::try_read_new_ascii_file_entry(const io::reader &reader)
{
	char header[NEW_ASCII_HEADER_SIZE];
	cpio_format format;

	auto header_amount_read = reader.read_some(0, std::span<char>{header, sizeof(header)});
	if (header_amount_read != sizeof(header))
	{
		return false;
	}

	if (0 == memcmp(header, NEW_ASCII_MAGIC, sizeof(NEW_ASCII_MAGIC)))
	{
		format = cpio_format::new_ascii;
	}
	else if (0 == memcmp(header, NEWC_ASCII_MAGIC, sizeof(NEWC_ASCII_MAGIC)))
	{
		format = cpio_format::newc_ascii;
	}
	else
	{
		return false;
	}

	struct
	{
		uint32_t *value;
		size_t offset;
		size_t length;
	} values[] = {
		{&m_ino, NEW_ASCII_HEADER_INO_OFFSET, NEW_ASCII_HEADER_INO_LENGTH},
		{&m_mode, NEW_ASCII_HEADER_MODE_OFFSET, NEW_ASCII_HEADER_MODE_LENGTH},
		{&m_uid, NEW_ASCII_HEADER_UID_OFFSET, NEW_ASCII_HEADER_UID_LENGTH},
		{&m_gid, NEW_ASCII_HEADER_GID_OFFSET, NEW_ASCII_HEADER_GID_LENGTH},
		{&m_nlink, NEW_ASCII_HEADER_NLINK_OFFSET, NEW_ASCII_HEADER_NLINK_LENGTH},
		{&m_mtime, NEW_ASCII_HEADER_MTIME_OFFSET, NEW_ASCII_HEADER_MTIME_LENGTH},
		{&m_filesize, NEW_ASCII_HEADER_FILESIZE_OFFSET, NEW_ASCII_HEADER_FILESIZE_LENGTH},
		{&m_dev_major, NEW_ASCII_HEADER_DEV_MAJOR_OFFSET, NEW_ASCII_HEADER_DEV_MAJOR_LENGTH},
		{&m_dev_minor, NEW_ASCII_HEADER_DEV_MINOR_OFFSET, NEW_ASCII_HEADER_DEV_MINOR_LENGTH},
		{&m_rdev_major, NEW_ASCII_HEADER_RDEV_MAJOR_OFFSET, NEW_ASCII_HEADER_RDEV_MAJOR_LENGTH},
		{&m_rdev_minor, NEW_ASCII_HEADER_RDEV_MINOR_OFFSET, NEW_ASCII_HEADER_RDEV_MINOR_LENGTH},
		{&m_namesize, NEW_ASCII_HEADER_NAMESIZE_OFFSET, NEW_ASCII_HEADER_NAMESIZE_LENGTH},
		{&m_check, NEW_ASCII_HEADER_CHECK_OFFSET, NEW_ASCII_HEADER_CHECK_LENGTH},
	};

	for (const auto &value : values)
	{
		*value.value = hexadecimal_characters_to_uint32(header, value.offset, value.length);
	}

	std::vector<char> name_buffer;
	name_buffer.reserve(m_namesize);

	if (reader.read_some(NEW_ASCII_HEADER_NAME_OFFSET, std::span<char>{name_buffer.data(), m_namesize}) != m_namesize)
	{
		return false;
	}

	m_name = string_from_nul_padded_string(std::string_view{name_buffer.data(), m_namesize});

	size_t header_total_size   = NEW_ASCII_HEADER_SIZE + m_namesize;
	size_t header_padding_size = get_padding_needed(header_total_size, 4);

	size_t file_data_start_offset = header_total_size + header_padding_size;
	size_t file_data_end_offset   = file_data_start_offset + m_filesize;
	size_t payload_padding_size   = get_padding_needed(file_data_end_offset, 4);

	m_header_reader         = reader.slice(0, header_total_size);
	m_header_padding_reader = reader.slice(header_total_size, header_padding_size);
	m_payload_reader        = reader.slice(file_data_start_offset, m_filesize);

	// if this is the end, just interpret the rest of the file as padding.
	if (is_end_marker())
	{
		m_payload_padding_reader = reader.slice_at(file_data_end_offset);
	}
	else
	{
		m_payload_padding_reader = reader.slice(file_data_end_offset, payload_padding_size);
	}

	m_format = format;

	return true;
}