1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 08:47:44 +00:00

LibArchive+Utilities: Stop using DeprecatedString

This also slightly improves error propagation in tar, unzip and zip.
This commit is contained in:
implicitfield 2022-12-22 16:21:13 +02:00 committed by Sam Atkins
parent 8377adfde0
commit 28c99e7a1f
10 changed files with 57 additions and 57 deletions

View file

@ -24,10 +24,12 @@ unsigned TarFileHeader::expected_checksum() const
return checksum;
}
void TarFileHeader::calculate_checksum()
ErrorOr<void> TarFileHeader::calculate_checksum()
{
memset(m_checksum, ' ', sizeof(m_checksum));
VERIFY(DeprecatedString::formatted("{:06o}", expected_checksum()).copy_characters_to_buffer(m_checksum, sizeof(m_checksum)));
bool copy_successful = TRY(String::formatted("{:06o}", expected_checksum())).bytes_as_string_view().copy_characters_to_buffer(m_checksum, sizeof(m_checksum));
VERIFY(copy_successful);
return {};
}
bool TarFileHeader::is_zero_block() const

View file

@ -8,7 +8,7 @@
#pragma once
#include <AK/DeprecatedString.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <string.h>
#include <sys/types.h>
@ -82,9 +82,10 @@ static void set_field(char (&field)[N], TSource&& source)
}
template<class TSource, size_t N>
static void set_octal_field(char (&field)[N], TSource&& source)
static ErrorOr<void> set_octal_field(char (&field)[N], TSource&& source)
{
set_field(field, DeprecatedString::formatted("{:o}", forward<TSource>(source)));
set_field(field, TRY(String::formatted("{:o}", forward<TSource>(source))).bytes_as_string_view());
return {};
}
class [[gnu::packed]] TarFileHeader {
@ -109,11 +110,11 @@ public:
StringView prefix() const { return get_field_as_string_view(m_prefix); }
void set_filename(StringView filename) { set_field(m_filename, filename); }
void set_mode(mode_t mode) { set_octal_field(m_mode, mode); }
void set_uid(uid_t uid) { set_octal_field(m_uid, uid); }
void set_gid(gid_t gid) { set_octal_field(m_gid, gid); }
void set_size(size_t size) { set_octal_field(m_size, size); }
void set_timestamp(time_t timestamp) { set_octal_field(m_timestamp, timestamp); }
ErrorOr<void> set_mode(mode_t mode) { return set_octal_field(m_mode, mode); }
ErrorOr<void> set_uid(uid_t uid) { return set_octal_field(m_uid, uid); }
ErrorOr<void> set_gid(gid_t gid) { return set_octal_field(m_gid, gid); }
ErrorOr<void> set_size(size_t size) { return set_octal_field(m_size, size); }
ErrorOr<void> set_timestamp(time_t timestamp) { return set_octal_field(m_timestamp, timestamp); }
void set_type_flag(TarFileType type) { m_type_flag = to_underlying(type); }
void set_link_name(StringView link_name) { set_field(m_link_name, link_name); }
// magic doesn't necessarily include a null byte
@ -122,12 +123,12 @@ public:
void set_version(StringView version) { set_field(m_version, version); }
void set_owner_name(StringView owner_name) { set_field(m_owner_name, owner_name); }
void set_group_name(StringView group_name) { set_field(m_group_name, group_name); }
void set_major(int major) { set_octal_field(m_major, major); }
void set_minor(int minor) { set_octal_field(m_minor, minor); }
ErrorOr<void> set_major(int major) { return set_octal_field(m_major, major); }
ErrorOr<void> set_minor(int minor) { return set_octal_field(m_minor, minor); }
void set_prefix(StringView prefix) { set_field(m_prefix, prefix); }
unsigned expected_checksum() const;
void calculate_checksum();
ErrorOr<void> calculate_checksum();
bool is_zero_block() const;
bool content_is_like_extended_header() const;

View file

@ -142,34 +142,34 @@ TarOutputStream::TarOutputStream(Core::Stream::Handle<Core::Stream::Stream> stre
{
}
ErrorOr<void> TarOutputStream::add_directory(DeprecatedString const& path, mode_t mode)
ErrorOr<void> TarOutputStream::add_directory(StringView path, mode_t mode)
{
VERIFY(!m_finished);
TarFileHeader header {};
header.set_size(0);
header.set_filename_and_prefix(DeprecatedString::formatted("{}/", path)); // Old tar implementations assume directory names end with a /
TRY(header.set_size(0));
header.set_filename_and_prefix(TRY(String::formatted("{}/", path))); // Old tar implementations assume directory names end with a /
header.set_type_flag(TarFileType::Directory);
header.set_mode(mode);
TRY(header.set_mode(mode));
header.set_magic(gnu_magic);
header.set_version(gnu_version);
header.calculate_checksum();
TRY(header.calculate_checksum());
TRY(m_stream->write_entire_buffer(Bytes { &header, sizeof(header) }));
u8 padding[block_size] = { 0 };
TRY(m_stream->write_entire_buffer(Bytes { &padding, block_size - sizeof(header) }));
return {};
}
ErrorOr<void> TarOutputStream::add_file(DeprecatedString const& path, mode_t mode, ReadonlyBytes bytes)
ErrorOr<void> TarOutputStream::add_file(StringView path, mode_t mode, ReadonlyBytes bytes)
{
VERIFY(!m_finished);
TarFileHeader header {};
header.set_size(bytes.size());
TRY(header.set_size(bytes.size()));
header.set_filename_and_prefix(path);
header.set_type_flag(TarFileType::NormalFile);
header.set_mode(mode);
TRY(header.set_mode(mode));
header.set_magic(gnu_magic);
header.set_version(gnu_version);
header.calculate_checksum();
TRY(header.calculate_checksum());
TRY(m_stream->write_entire_buffer(ReadonlyBytes { &header, sizeof(header) }));
constexpr Array<u8, block_size> padding { 0 };
TRY(m_stream->write_entire_buffer(ReadonlyBytes { &padding, block_size - sizeof(header) }));
@ -181,18 +181,18 @@ ErrorOr<void> TarOutputStream::add_file(DeprecatedString const& path, mode_t mod
return {};
}
ErrorOr<void> TarOutputStream::add_link(DeprecatedString const& path, mode_t mode, StringView link_name)
ErrorOr<void> TarOutputStream::add_link(StringView path, mode_t mode, StringView link_name)
{
VERIFY(!m_finished);
TarFileHeader header {};
header.set_size(0);
TRY(header.set_size(0));
header.set_filename_and_prefix(path);
header.set_type_flag(TarFileType::SymLink);
header.set_mode(mode);
TRY(header.set_mode(mode));
header.set_magic(gnu_magic);
header.set_version(gnu_version);
header.set_link_name(link_name);
header.calculate_checksum();
TRY(header.calculate_checksum());
TRY(m_stream->write_entire_buffer(Bytes { &header, sizeof(header) }));
u8 padding[block_size] = { 0 };
TRY(m_stream->write_entire_buffer(Bytes { &padding, block_size - sizeof(header) }));

View file

@ -59,9 +59,9 @@ private:
class TarOutputStream {
public:
TarOutputStream(Core::Stream::Handle<Core::Stream::Stream>);
ErrorOr<void> add_file(DeprecatedString const& path, mode_t, ReadonlyBytes);
ErrorOr<void> add_link(DeprecatedString const& path, mode_t, StringView);
ErrorOr<void> add_directory(DeprecatedString const& path, mode_t);
ErrorOr<void> add_file(StringView path, mode_t, ReadonlyBytes);
ErrorOr<void> add_link(StringView path, mode_t, StringView);
ErrorOr<void> add_directory(StringView path, mode_t);
ErrorOr<void> finish();
private:

View file

@ -75,7 +75,7 @@ Optional<Zip> Zip::try_create(ReadonlyBytes buffer)
};
}
bool Zip::for_each_member(Function<IterationDecision(ZipMember const&)> callback)
ErrorOr<bool> Zip::for_each_member(Function<IterationDecision(ZipMember const&)> callback)
{
size_t member_offset = m_members_start_offset;
for (size_t i = 0; i < m_member_count; i++) {
@ -85,15 +85,12 @@ bool Zip::for_each_member(Function<IterationDecision(ZipMember const&)> callback
VERIFY(local_file_header.read(m_input_data.slice(central_directory_record.local_file_header_offset)));
ZipMember member;
char null_terminated_name[central_directory_record.name_length + 1];
memcpy(null_terminated_name, central_directory_record.name, central_directory_record.name_length);
null_terminated_name[central_directory_record.name_length] = 0;
member.name = DeprecatedString { null_terminated_name };
member.name = TRY(String::from_utf8({ central_directory_record.name, central_directory_record.name_length }));
member.compressed_data = { local_file_header.compressed_data, central_directory_record.compressed_size };
member.compression_method = central_directory_record.compression_method;
member.uncompressed_size = central_directory_record.uncompressed_size;
member.crc32 = central_directory_record.crc32;
member.is_directory = central_directory_record.external_attributes & zip_directory_external_attribute || member.name.ends_with('/'); // FIXME: better directory detection
member.is_directory = central_directory_record.external_attributes & zip_directory_external_attribute || member.name.bytes_as_string_view().ends_with('/'); // FIXME: better directory detection
if (callback(member) == IterationDecision::Break)
return false;
@ -117,7 +114,7 @@ static u16 minimum_version_needed(ZipCompressionMethod method)
ErrorOr<void> ZipOutputStream::add_member(ZipMember const& member)
{
VERIFY(!m_finished);
VERIFY(member.name.length() <= UINT16_MAX);
VERIFY(member.name.bytes_as_string_view().length() <= UINT16_MAX);
VERIFY(member.compressed_data.size() <= UINT32_MAX);
TRY(m_members.try_append(member));
@ -130,9 +127,9 @@ ErrorOr<void> ZipOutputStream::add_member(ZipMember const& member)
.crc32 = member.crc32,
.compressed_size = static_cast<u32>(member.compressed_data.size()),
.uncompressed_size = member.uncompressed_size,
.name_length = static_cast<u16>(member.name.length()),
.name_length = static_cast<u16>(member.name.bytes_as_string_view().length()),
.extra_data_length = 0,
.name = reinterpret_cast<u8 const*>(member.name.characters()),
.name = reinterpret_cast<u8 const*>(member.name.bytes_as_string_view().characters_without_null_termination()),
.extra_data = nullptr,
.compressed_data = member.compressed_data.data(),
};
@ -158,18 +155,18 @@ ErrorOr<void> ZipOutputStream::finish()
.crc32 = member.crc32,
.compressed_size = static_cast<u32>(member.compressed_data.size()),
.uncompressed_size = member.uncompressed_size,
.name_length = static_cast<u16>(member.name.length()),
.name_length = static_cast<u16>(member.name.bytes_as_string_view().length()),
.extra_data_length = 0,
.comment_length = 0,
.start_disk = 0,
.internal_attributes = 0,
.external_attributes = member.is_directory ? zip_directory_external_attribute : 0,
.local_file_header_offset = file_header_offset, // FIXME: we assume the wrapped output stream was never written to before us
.name = reinterpret_cast<u8 const*>(member.name.characters()),
.name = reinterpret_cast<u8 const*>(member.name.bytes_as_string_view().characters_without_null_termination()),
.extra_data = nullptr,
.comment = nullptr,
};
file_header_offset += sizeof(LocalFileHeader::signature) + (sizeof(LocalFileHeader) - (sizeof(u8*) * 3)) + member.name.length() + member.compressed_data.size();
file_header_offset += sizeof(LocalFileHeader::signature) + (sizeof(LocalFileHeader) - (sizeof(u8*) * 3)) + member.name.bytes_as_string_view().length() + member.compressed_data.size();
TRY(central_directory_record.write(*m_stream));
central_directory_size += central_directory_record.size();
}

View file

@ -8,9 +8,9 @@
#pragma once
#include <AK/Array.h>
#include <AK/DeprecatedString.h>
#include <AK/Function.h>
#include <AK/IterationDecision.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibCore/Stream.h>
#include <string.h>
@ -238,7 +238,7 @@ struct [[gnu::packed]] LocalFileHeader {
};
struct ZipMember {
DeprecatedString name;
String name;
ReadonlyBytes compressed_data; // TODO: maybe the decompression/compression should be handled by LibArchive instead of the user?
ZipCompressionMethod compression_method;
u32 uncompressed_size;
@ -249,7 +249,7 @@ struct ZipMember {
class Zip {
public:
static Optional<Zip> try_create(ReadonlyBytes buffer);
bool for_each_member(Function<IterationDecision(ZipMember const&)>);
ErrorOr<bool> for_each_member(Function<IterationDecision(ZipMember const&)>);
private:
static bool find_end_of_central_directory_offset(ReadonlyBytes, size_t& offset);