Serenity Operating System
1/*
2 * Copyright (c) 2020, Peter Elliott <pelliott@serenityos.org>
3 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include "Tar.h"
9
10namespace Archive {
11
12unsigned TarFileHeader::expected_checksum() const
13{
14 auto checksum = 0u;
15 u8 const* u8_this = reinterpret_cast<u8 const*>(this);
16 u8 const* u8_m_checksum = reinterpret_cast<u8 const*>(&m_checksum);
17 for (auto i = 0u; i < sizeof(TarFileHeader); ++i) {
18 if (u8_this + i >= u8_m_checksum && u8_this + i < u8_m_checksum + sizeof(m_checksum)) {
19 checksum += ' ';
20 } else {
21 checksum += u8_this[i];
22 }
23 }
24 return checksum;
25}
26
27ErrorOr<void> TarFileHeader::calculate_checksum()
28{
29 memset(m_checksum, ' ', sizeof(m_checksum));
30 bool copy_successful = TRY(String::formatted("{:06o}", expected_checksum())).bytes_as_string_view().copy_characters_to_buffer(m_checksum, sizeof(m_checksum));
31 VERIFY(copy_successful);
32 return {};
33}
34
35bool TarFileHeader::is_zero_block() const
36{
37 u8 const* buffer = reinterpret_cast<u8 const*>(this);
38 for (size_t i = 0; i < sizeof(TarFileHeader); ++i) {
39 if (buffer[i] != 0)
40 return false;
41 }
42 return true;
43}
44
45bool TarFileHeader::content_is_like_extended_header() const
46{
47 return type_flag() == TarFileType::ExtendedHeader || type_flag() == TarFileType::GlobalExtendedHeader;
48}
49
50void TarFileHeader::set_filename_and_prefix(StringView filename)
51{
52 // FIXME: Add support for extended tar headers for longer filenames.
53 VERIFY(filename.length() <= sizeof(m_filename) + sizeof(m_prefix));
54
55 if (filename.length() <= sizeof(m_filename)) {
56 set_prefix(""sv);
57 set_filename(filename);
58 return;
59 }
60
61 Optional<size_t> slash = filename.find('/', filename.length() - sizeof(m_filename));
62
63 VERIFY(slash.has_value());
64 set_prefix(filename.substring_view(0, slash.value() + 1));
65 set_filename(filename.substring_view(slash.value() + 1));
66}
67
68}