Skip to content
API Documentation
BastionGuard™
hfs::anonymous_namespace{hfs_fork_io.cpp} Namespace Reference

Functions

bool read_one_extent (DiskReader &reader, uint64_t volume_offset, uint32_t block_size, const ForkExtent &e, uint64_t want_bytes, std::vector< unsigned char > &out)
size_t collect_overflow_extents (const std::vector< unsigned char > &btree_buf, const HeaderRec &hdr, uint8_t forkType, uint32_t fileID, std::vector< ForkExtent > &out, std::vector< std::string > &logs)

Function Documentation

◆ collect_overflow_extents()

size_t hfs::anonymous_namespace{hfs_fork_io.cpp}::collect_overflow_extents ( const std::vector< unsigned char > & btree_buf,
const HeaderRec & hdr,
uint8_t forkType,
uint32_t fileID,
std::vector< ForkExtent > & out,
std::vector< std::string > & logs )

Definition at line 138 of file hfs_fork_io.cpp.

143 {
144 auto node_reader = [&](uint32_t node_index,
145 std::vector<unsigned char>& nodebuf) -> bool {
146 const uint64_t off = static_cast<uint64_t>(node_index) * hdr.nodeSize;
147 if (off + hdr.nodeSize > btree_buf.size()) return false;
148 nodebuf.assign(btree_buf.begin() + off,
149 btree_buf.begin() + off + hdr.nodeSize);
150 return true;
151 };
152
153 size_t found = 0;
154 auto on_leaf = [&](const unsigned char* rec, uint16_t rec_len) -> bool {
155 // Extents Overflow KEY layout:
156 // __be16 keyLength
157 // __u8 forkType
158 // __u8 pad
159 // __be32 fileID
160 // __be32 startBlock
161 if (rec_len < 12) return true;
162 const uint16_t keyLength = be16(rec + 0);
163 if (keyLength < 10 || 2u + keyLength > rec_len) return true;
164 const uint8_t rec_forkType = rec[2];
165 // pad at +3
166 const uint32_t rec_fileID = be32(rec + 4);
167 // const uint32_t rec_startBlock = be32(rec + 8); // not used here
168 if (rec_forkType != forkType || rec_fileID != fileID) {
169 return true; // not for us, skip
170 }
171 // Body: 64 bytes of HFSPlusExtentRecord = 8 extents.
172 // Body starts after the 2+keyLength key, aligned to 2 bytes.
173 const uint32_t key_total = 2u + keyLength;
174 const uint32_t body_off = (key_total + 1u) & ~1u;
175 if (body_off + 64 > rec_len) return true;
176 const unsigned char* body = rec + body_off;
177 for (int i = 0; i < 8; ++i) {
178 ForkExtent e;
179 e.start_block = be32(body + i * 8 + 0);
180 e.block_count = be32(body + i * 8 + 4);
181 if (e.block_count == 0) break; // first zero terminates the run
182 out.push_back(e);
183 ++found;
184 }
185 return true;
186 };
187
188 std::vector<std::string> walk_logs;
189 std::string walk_err;
190 walk_btree(hdr, node_reader, on_leaf, walk_logs, walk_err);
191 for (auto& l : walk_logs) logs.push_back(std::move(l));
192 if (!walk_err.empty()) {
193 logs.push_back("HFS+ extents-overflow walk: " + walk_err);
194 }
195 return found;
196}
uint32_t be32(const unsigned char *p)
bool walk_btree(const HeaderRec &header, const NodeReader &read_node, const LeafRecordCallback &on_leaf, std::vector< std::string > &logs, std::string &error)
uint16_t be16(const unsigned char *p)
uint16_t nodeSize
Definition hfs_btree.hpp:69

References hfs::be16(), hfs::be32(), hfs::ForkExtent::block_count, collect_overflow_extents(), hfs::HeaderRec::nodeSize, hfs::ForkExtent::start_block, and hfs::walk_btree().

Referenced by collect_overflow_extents().

◆ read_one_extent()

bool hfs::anonymous_namespace{hfs_fork_io.cpp}::read_one_extent ( DiskReader & reader,
uint64_t volume_offset,
uint32_t block_size,
const ForkExtent & e,
uint64_t want_bytes,
std::vector< unsigned char > & out )

Definition at line 112 of file hfs_fork_io.cpp.

115 {
116 if (e.block_count == 0 || want_bytes == 0) return true;
117 const uint64_t off = volume_offset
118 + static_cast<uint64_t>(e.start_block) * block_size;
119 const uint64_t ext_bytes =
120 static_cast<uint64_t>(e.block_count) * block_size;
121 const uint64_t copy = std::min<uint64_t>(ext_bytes, want_bytes);
122 const size_t before = out.size();
123 out.resize(before + static_cast<size_t>(copy));
124 if (!reader.read_at(off, out.data() + before, copy)) {
125 out.resize(before);
126 return false;
127 }
128 return true;
129}
bool read_at(uint64_t offset, void *buffer, size_t len)
uint32_t block_count
uint32_t start_block

References hfs::ForkExtent::block_count, DiskReader::read_at(), read_one_extent(), and hfs::ForkExtent::start_block.

Referenced by read_one_extent().