]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_tar.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
10 #include <string_view>
14 #include <boost/optional.hpp>
15 #include <boost/range/adaptor/reversed.hpp>
20 static constexpr size_t BLOCK_SIZE
= 512;
23 static inline std::pair
<class StatusIndicator
,
24 boost::optional
<class HeaderView
>>
25 interpret_block(const StatusIndicator
& status
, ceph::bufferlist
& bl
);
28 class StatusIndicator
{
29 friend std::pair
<class StatusIndicator
,
30 boost::optional
<class HeaderView
>>
31 interpret_block(const StatusIndicator
& status
, ceph::bufferlist
& bl
);
41 StatusIndicator(const StatusIndicator
& prev_status
,
44 is_eof(is_empty
&& prev_status
.empty()) {
56 static StatusIndicator
create() {
57 return StatusIndicator();
59 } /* class StatusIndicator */;
62 enum class FileType
: char {
65 /* The tar format uses ASCII encoding. */
68 }; /* enum class FileType */
72 /* Everythng is char here (ASCII encoding), so we don't need to worry about
73 * the struct padding. */
74 const struct header_t
{
86 static_assert(sizeof(*header
) == BLOCK_SIZE
,
87 "The TAR header must be exactly BLOCK_SIZE length");
89 /* The label is far more imporant from what the code really does. */
90 static size_t pos2len(const size_t pos
) {
95 explicit HeaderView(const char (&header
)[BLOCK_SIZE
])
96 : header(reinterpret_cast<const header_t
*>(header
)) {
99 FileType
get_filetype() const {
100 switch (header
->filetype
) {
101 case static_cast<char>(FileType::NORMAL_FILE
):
102 return FileType::NORMAL_FILE
;
103 case static_cast<char>(FileType::DIRECTORY
):
104 return FileType::DIRECTORY
;
106 return FileType::UNKNOWN
;
110 std::string_view
get_filename() const {
111 return std::string_view(header
->filename
,
112 std::min(sizeof(header
->filename
),
113 strlen(header
->filename
)));
116 size_t get_filesize() const {
117 /* The string_ref is pretty suitable here because tar encodes its
118 * metadata in ASCII. */
119 const std::string_view
raw(header
->filesize
, sizeof(header
->filesize
));
121 /* We need to find where the padding ends. */
122 const auto pad_ends_at
= std::min(raw
.find_last_not_of('\0'),
123 raw
.find_last_not_of(' '));
124 const auto trimmed
= raw
.substr(0,
125 pad_ends_at
== std::string_view::npos
? std::string_view::npos
126 : pos2len(pad_ends_at
));
128 size_t sum
= 0, mul
= 1;
129 for (const char c
: boost::adaptors::reverse(trimmed
)) {
130 sum
+= (c
- '0') * mul
;
136 }; /* class Header */
139 static inline std::pair
<StatusIndicator
,
140 boost::optional
<HeaderView
>>
141 interpret_block(const StatusIndicator
& status
, ceph::bufferlist
& bl
) {
142 static constexpr std::array
<char, BLOCK_SIZE
> zero_block
= {0, };
143 const char (&block
)[BLOCK_SIZE
] = \
144 reinterpret_cast<const char (&)[BLOCK_SIZE
]>(*bl
.c_str());
146 if (std::memcmp(zero_block
.data(), block
, BLOCK_SIZE
) == 0) {
147 return std::make_pair(StatusIndicator(status
, true), boost::none
);
149 return std::make_pair(StatusIndicator(status
, false), HeaderView(block
));
153 } /* namespace tar */
154 } /* namespace rgw */
156 #endif /* CEPH_RGW_TAR_H */