34 if (data ==
nullptr || data_len < 4)
return false;
37 const uint8_t count = data[0];
38 const uint8_t i8count = data[1];
39 const bool use_8byte = (i8count != 0);
40 const uint32_t inumber_size = use_8byte ? 8u : 4u;
44 if (pos + inumber_size > data_len)
return false;
45 out.
parent_ino = use_8byte ? read_u64_be(data + pos)
46 : read_u32_be(data + pos);
51 for (uint8_t i = 0; i < count; ++i) {
52 if (pos + 1 > data_len)
return false;
53 const uint8_t namelen = data[pos];
57 if (pos + 2 > data_len)
return false;
61 if (pos + namelen > data_len)
return false;
63 e.
name.assign(
reinterpret_cast<const char*
>(data + pos), namelen);
69 if (namelen == 0)
return false;
70 if (e.
name.find(
'/') != std::string::npos) {
73 std::replace(e.
name.begin(), e.
name.end(),
'/',
'_');
78 if (pos + 1 > data_len)
return false;
85 if (pos + inumber_size > data_len)
return false;
86 e.
ino = use_8byte ? read_u64_be(data + pos)
87 :
static_cast<uint64_t
>(read_u32_be(data + pos));
92 if (e.
name ==
"." || e.
name ==
"..")
continue;
94 out.
entries.push_back(std::move(e));
126 bool accept_block_magic,
127 bool accept_data_magic,
128 std::vector<DirEntry>& out) {
129 if (block_buf ==
nullptr || block_size < 64)
return false;
131 const uint32_t magic =
be32(block_buf + 0x00);
132 bool magic_ok =
false;
140 if (!magic_ok)
return false;
142 const uint32_t header_size = is_v5 ? DATA_HDR_SIZE_V5 : DATA_HDR_SIZE_V4;
143 if (block_size <= header_size)
return false;
155 uint32_t stop_offset = block_size;
160 if (block_size >= 8) {
161 const uint32_t bt_count =
be32(block_buf + block_size - 8);
162 const uint32_t leaf_table_bytes = bt_count * 8u;
163 if (8u + leaf_table_bytes <= block_size) {
164 stop_offset = block_size - 8u - leaf_table_bytes;
166 stop_offset = block_size > 8u ? block_size - 8u : 0u;
170 if (stop_offset <= header_size)
return false;
172 uint32_t pos = header_size;
173 while (pos + 4 <= stop_offset) {
178 const uint16_t first_word =
be16(block_buf + pos);
181 if (pos + 6 > stop_offset)
break;
182 const uint16_t freelen =
be16(block_buf + pos + 2);
183 if (freelen < 16 || pos + freelen > stop_offset) {
194 if (pos + 8 + 1 > stop_offset)
break;
195 const uint64_t inumber =
be64(block_buf + pos);
196 const uint8_t namelen = block_buf[pos + 8];
202 const uint32_t raw_entry_len = 8u + 1u + namelen +
203 (has_ftype ? 1u : 0u) + 2u;
204 const uint32_t entry_len = align8(raw_entry_len);
205 if (pos + entry_len > stop_offset) {
211 e.
name.assign(
reinterpret_cast<const char*
>(block_buf + pos + 9), namelen);
213 if (e.
name.find(
'/') != std::string::npos) {
214 std::replace(e.
name.begin(), e.
name.end(),
'/',
'_');
218 e.
ftype = block_buf[pos + 9 + namelen];
225 if (e.
name !=
"." && e.
name !=
"..") {
226 out.push_back(std::move(e));
bool parse_dir_data_block(const unsigned char *block_buf, uint32_t block_size, bool is_v5, bool has_ftype, bool accept_block_magic, bool accept_data_magic, std::vector< DirEntry > &out)