Skip to content

Commit

Permalink
Refactoring and cleanup.
Browse files Browse the repository at this point in the history
Added support for setting uid/gid as requested and submitted by a-wai (#61).
Added utility for showing volumes in a container as requested by ogjelland (#36).
  • Loading branch information
sgan81 committed Mar 9, 2019
1 parent 8b11306 commit d9ae52c
Show file tree
Hide file tree
Showing 29 changed files with 717 additions and 350 deletions.
2 changes: 1 addition & 1 deletion ApfsDump/Apfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ constexpr size_t BLOCKSIZE = 0x1000;

volatile bool g_abort = 0;

void DumpBlockTrunc(std::ostream &os, const byte_t *data)
void DumpBlockTrunc(std::ostream &os, const uint8_t *data)
{
unsigned int sz = BLOCKSIZE - 1;

Expand Down
99 changes: 65 additions & 34 deletions ApfsLib/ApfsContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ ApfsContainer::~ApfsContainer()

bool ApfsContainer::Init()
{
std::vector<byte_t> blk;
std::vector<uint8_t> blk;

blk.resize(0x1000);

Expand Down Expand Up @@ -84,15 +84,15 @@ bool ApfsContainer::Init()

#if 1 // Scan container for most recent superblock (might fix segfaults)
uint64_t max_xid = 0;
uint64_t max_bid = 0;
paddr_t bid;
std::vector<byte_t> tmp;
paddr_t max_paddr = 0;
paddr_t paddr;
std::vector<uint8_t> tmp;

tmp.resize(m_nx.nx_block_size);

for (bid = m_nx.nx_xp_desc_base; bid < (m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_blocks); bid++)
for (paddr = m_nx.nx_xp_desc_base; paddr < (m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_blocks); paddr++)
{
if (!ReadBlocks(tmp.data(), bid, 1))
if (!ReadBlocks(tmp.data(), paddr, 1))
return false;

if (!VerifyBlock(tmp.data(), tmp.size()))
Expand All @@ -105,7 +105,7 @@ bool ApfsContainer::Init()
if (sb->nx_o.o_xid > max_xid)
{
max_xid = sb->nx_o.o_xid;
max_bid = bid;
max_paddr = paddr;
}
}

Expand All @@ -114,7 +114,7 @@ bool ApfsContainer::Init()
if (g_debug & Dbg_Errors)
std::cout << "Found more recent xid " << max_xid << " than superblock 0 contained (" << m_nx.nx_o.o_xid << ")." << std::endl;

ReadBlocks(tmp.data(), max_bid, 1);
ReadBlocks(tmp.data(), max_paddr, 1);

memcpy(&m_nx, tmp.data(), sizeof(nx_superblock_t));
}
Expand All @@ -138,15 +138,15 @@ bool ApfsContainer::Init()
return false;
}

node_info_t ni;
if (!m_cpm.GetBlockID(ni, m_nx.nx_spaceman_oid, m_nx.nx_o.o_xid))
omap_res_t omr;
if (!m_cpm.Lookup(omr, m_nx.nx_spaceman_oid, m_nx.nx_o.o_xid))
{
std::cerr << "Failed to map spaceman oid" << std::endl;
return false;
}

m_sm_data.resize(GetBlocksize());
ReadBlocks(m_sm_data.data(), ni.bid, 1);
ReadBlocks(m_sm_data.data(), omr.paddr, 1);
m_sm = reinterpret_cast<const spaceman_phys_t *>(m_sm_data.data());

if ((m_sm->sm_o.o_type & OBJECT_TYPE_MASK) != OBJECT_TYPE_SPACEMAN)
Expand Down Expand Up @@ -177,33 +177,33 @@ bool ApfsContainer::Init()
return true;
}

ApfsVolume *ApfsContainer::GetVolume(int index, const std::string &passphrase)
ApfsVolume *ApfsContainer::GetVolume(unsigned int index, const std::string &passphrase)
{
ApfsVolume *vol = nullptr;
uint64_t nodeid;
node_info_t ni;
oid_t oid;
omap_res_t omr;
bool rc;

if (index >= 100)
return nullptr;

m_passphrase = passphrase;

nodeid = m_nx.nx_fs_oid[index];
oid = m_nx.nx_fs_oid[index];

if (nodeid == 0)
if (oid == 0)
return nullptr;

if (!m_omap.GetBlockID(ni, nodeid, m_nx.nx_o.o_xid))
if (!m_omap.Lookup(omr, oid, m_nx.nx_o.o_xid))
return nullptr;

// std::cout << std::hex << "Loading Volume " << index << ", nodeid = " << nodeid << ", version = " << m_sb.hdr.version << ", blkid = " << blkid << std::endl;

if (ni.bid == 0)
if (omr.paddr == 0)
return nullptr;

vol = new ApfsVolume(*this);
rc = vol->Init(ni.bid);
rc = vol->Init(omr.paddr);

if (rc == false)
{
Expand All @@ -214,9 +214,9 @@ ApfsVolume *ApfsContainer::GetVolume(int index, const std::string &passphrase)
return vol;
}

int ApfsContainer::GetVolumeCnt() const
unsigned int ApfsContainer::GetVolumeCnt() const
{
int k;
unsigned int k;

for (k = 0; k < 100; k++)
{
Expand All @@ -227,15 +227,46 @@ int ApfsContainer::GetVolumeCnt() const
return k;
}

bool ApfsContainer::ReadBlocks(byte_t * data, uint64_t blkid, uint64_t blkcnt) const
bool ApfsContainer::GetVolumeInfo(unsigned int fsid, apfs_superblock_t& apsb)
{
oid_t oid;
omap_res_t omr;
std::vector<uint8_t> apsb_raw;

if (fsid >= 100)
return false;

oid = m_nx.nx_fs_oid[fsid];

if (oid == 0)
return false;

if (!m_omap.Lookup(omr, oid, m_nx.nx_o.o_xid))
return false;

if (omr.paddr == 0)
return false;

apsb_raw.resize(GetBlocksize());

if (!ReadAndVerifyHeaderBlock(apsb_raw.data(), omr.paddr))
return false;

memcpy(&apsb, apsb_raw.data(), sizeof(apfs_superblock_t));

return true;
}


bool ApfsContainer::ReadBlocks(uint8_t * data, paddr_t paddr, uint64_t blkcnt) const
{
uint64_t offs;
uint64_t size;

//if ((blkid + blkcnt) > m_nx.nx_block_count)
//if ((paddr + blkcnt) > m_nx.nx_block_count)
// return false;

offs = m_nx.nx_block_size * blkid;
offs = m_nx.nx_block_size * paddr;
size = m_nx.nx_block_size * blkcnt;

if (offs & FUSION_TIER2_DEVICE_BYTE_ADDR)
Expand All @@ -256,9 +287,9 @@ bool ApfsContainer::ReadBlocks(byte_t * data, uint64_t blkid, uint64_t blkcnt) c
}
}

bool ApfsContainer::ReadAndVerifyHeaderBlock(byte_t * data, uint64_t blkid) const
bool ApfsContainer::ReadAndVerifyHeaderBlock(uint8_t * data, paddr_t paddr) const
{
if (!ReadBlocks(data, blkid))
if (!ReadBlocks(data, paddr))
return false;

if (!VerifyBlock(data, m_nx.nx_block_size))
Expand Down Expand Up @@ -292,8 +323,8 @@ bool ApfsContainer::GetPasswordHint(std::string & hint, const apfs_uuid_t & vol_

void ApfsContainer::dump(BlockDumper& bd)
{
std::vector<byte_t> blk;
uint64_t blkid;
std::vector<uint8_t> blk;
paddr_t paddr;

bd.st() << "Dumping Container" << std::endl;
bd.st() << "-----------------" << std::endl;
Expand Down Expand Up @@ -331,17 +362,17 @@ void ApfsContainer::dump(BlockDumper& bd)

#if 1
bd.st() << std::endl << "Dumping XP desc area (current SB):" << std::endl;
for (blkid = m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_index; blkid < (m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_index + m_nx.nx_xp_desc_len); blkid++)
for (paddr = m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_index; paddr < (m_nx.nx_xp_desc_base + m_nx.nx_xp_desc_index + m_nx.nx_xp_desc_len); paddr++)
{
ReadAndVerifyHeaderBlock(blk.data(), blkid);
bd.DumpNode(blk.data(), blkid);
ReadAndVerifyHeaderBlock(blk.data(), paddr);
bd.DumpNode(blk.data(), paddr);
}

bd.st() << std::endl << "Dumping XP data area (current SB):" << std::endl;
for (blkid = m_nx.nx_xp_data_base + m_nx.nx_xp_data_index; blkid < (m_nx.nx_xp_data_base + m_nx.nx_xp_data_index + m_nx.nx_xp_data_len); blkid++)
for (paddr = m_nx.nx_xp_data_base + m_nx.nx_xp_data_index; paddr < (m_nx.nx_xp_data_base + m_nx.nx_xp_data_index + m_nx.nx_xp_data_len); paddr++)
{
ReadAndVerifyHeaderBlock(blk.data(), blkid);
bd.DumpNode(blk.data(), blkid);
ReadAndVerifyHeaderBlock(blk.data(), paddr);
bd.DumpNode(blk.data(), paddr);
}
#endif

Expand Down
11 changes: 7 additions & 4 deletions ApfsLib/ApfsContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,16 @@ class ApfsContainer

bool Init();

ApfsVolume *GetVolume(int index, const std::string &passphrase = std::string());
int GetVolumeCnt() const;
ApfsVolume *GetVolume(unsigned int index, const std::string &passphrase = std::string());
unsigned int GetVolumeCnt() const;
bool GetVolumeInfo(unsigned int fsid, apfs_superblock_t &apsb);

bool ReadBlocks(byte_t *data, uint64_t blkid, uint64_t blkcnt = 1) const;
bool ReadAndVerifyHeaderBlock(byte_t *data, uint64_t blkid) const;
bool ReadBlocks(uint8_t *data, paddr_t paddr, uint64_t blkcnt = 1) const;
bool ReadAndVerifyHeaderBlock(uint8_t *data, paddr_t paddr) const;

uint32_t GetBlocksize() const { return m_nx.nx_block_size; }
uint64_t GetBlockCount() const { return m_nx.nx_block_count; }
uint64_t GetFreeBlocks() const { return m_sm->sm_dev[SD_MAIN].sm_free_count + m_sm->sm_dev[SD_TIER2].sm_free_count; }

bool GetVolumeKey(uint8_t *key, const apfs_uuid_t &vol_uuid, const char *password = nullptr);
bool GetPasswordHint(std::string &hint, const apfs_uuid_t &vol_uuid);
Expand Down
4 changes: 2 additions & 2 deletions ApfsLib/ApfsDir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,14 +540,14 @@ bool ApfsDir::ReadFile(void* data, uint64_t inode, uint64_t offs, size_t size)
{
if (g_debug & Dbg_Dir)
std::cout << "Full read blk " << ext_val->phys_block_num + blk_idx << " cnt " << (cur_size >> m_blksize_sh) << std::endl;
m_vol.ReadBlocks(bdata, ext_val->phys_block_num + blk_idx, cur_size >> m_blksize_sh, true, ext_val->crypto_id + blk_idx);
m_vol.ReadBlocks(bdata, ext_val->phys_block_num + blk_idx, cur_size >> m_blksize_sh, ext_val->crypto_id + blk_idx);
}
else
{
if (g_debug & Dbg_Dir)
std::cout << "Partial read blk " << ext_val->phys_block_num + blk_idx << " cnt 1" << std::endl;

m_vol.ReadBlocks(m_tmp_blk.data(), ext_val->phys_block_num + blk_idx, 1, true, ext_val->crypto_id + blk_idx);
m_vol.ReadBlocks(m_tmp_blk.data(), ext_val->phys_block_num + blk_idx, 1, ext_val->crypto_id + blk_idx);

if (blk_offs + cur_size > m_blksize)
cur_size = m_blksize - blk_offs;
Expand Down
8 changes: 4 additions & 4 deletions ApfsLib/ApfsNodeMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@

#pragma once

#include <cstdint>
#include "ApfsTypes.h"

struct node_info_t
struct omap_res_t
{
uint32_t flags;
uint32_t size;
uint64_t bid;
paddr_t paddr;
};

class ApfsNodeMapper
Expand All @@ -34,5 +34,5 @@ class ApfsNodeMapper
ApfsNodeMapper();
virtual ~ApfsNodeMapper();

virtual bool GetBlockID(node_info_t &res, uint64_t nid, uint64_t xid) = 0;
virtual bool Lookup(omap_res_t &res, oid_t oid, xid_t xid) = 0;
};
34 changes: 17 additions & 17 deletions ApfsLib/ApfsNodeMapperBTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "ApfsNodeMapperBTree.h"
#include "ApfsContainer.h"

static int CompareNodeMapKey(const void *skey, size_t skey_len, const void *ekey, size_t ekey_len, void *context)
static int CompareOMapKey(const void *skey, size_t skey_len, const void *ekey, size_t ekey_len, void *context)
{
(void)context;
(void)skey_len;
Expand Down Expand Up @@ -57,30 +57,30 @@ ApfsNodeMapperBTree::~ApfsNodeMapperBTree()
{
}

bool ApfsNodeMapperBTree::Init(uint64_t bid_root, uint64_t xid)
bool ApfsNodeMapperBTree::Init(oid_t omap_oid, xid_t xid)
{
std::vector<byte_t> blk;
std::vector<uint8_t> blk;

blk.resize(m_container.GetBlocksize());

if (!m_container.ReadAndVerifyHeaderBlock(blk.data(), bid_root))
if (!m_container.ReadAndVerifyHeaderBlock(blk.data(), omap_oid))
{
std::cerr << "ERROR: Invalid header block 0x" << std::hex << bid_root << std::endl;
std::cerr << "ERROR: Invalid omap block @ oid 0x" << std::hex << omap_oid << std::endl;
return false;
}

memcpy(&m_root_ptr, blk.data(), sizeof(omap_phys_t));
memcpy(&m_omap, blk.data(), sizeof(omap_phys_t));

if ((m_root_ptr.om_o.o_type & OBJECT_TYPE_MASK) == OBJECT_TYPE_BTREE)
if ((m_omap.om_o.o_type & OBJECT_TYPE_MASK) == OBJECT_TYPE_BTREE)
{
std::cerr << "ERROR: Wrong header type 0x" << std::hex << m_root_ptr.om_o.o_type << std::endl;
std::cerr << "ERROR: Wrong omap type 0x" << std::hex << m_omap.om_o.o_type << std::endl;
return false;
}

return m_tree.Init(m_root_ptr.om_tree_oid, xid);
return m_tree.Init(m_omap.om_tree_oid, xid);
}

bool ApfsNodeMapperBTree::GetBlockID(node_info_t &info, uint64_t nid, uint64_t xid)
bool ApfsNodeMapperBTree::Lookup(omap_res_t &omr, oid_t oid, xid_t xid)
{
omap_key_t key;

Expand All @@ -89,15 +89,15 @@ bool ApfsNodeMapperBTree::GetBlockID(node_info_t &info, uint64_t nid, uint64_t x

BTreeEntry res;

key.ok_oid = nid;
key.ok_oid = oid;
key.ok_xid = xid;

// std::cout << std::hex << "GetBlockID: nodeid = " << nodeid << ", version = " << version << " => blockid = ";

if (!m_tree.Lookup(res, &key, sizeof(key), CompareNodeMapKey, this, false))
if (!m_tree.Lookup(res, &key, sizeof(key), CompareOMapKey, this, false))
{
// std::cout << "NOT FOUND" << std::endl;
std::cerr << std::hex << "nid " << nid << " xid " << xid << " NOT FOUND!!!" << std::endl;
std::cerr << std::hex << "oid " << oid << " xid " << xid << " NOT FOUND!!!" << std::endl;
return false;
}

Expand All @@ -109,15 +109,15 @@ bool ApfsNodeMapperBTree::GetBlockID(node_info_t &info, uint64_t nid, uint64_t x
if (key.ok_oid != res_key->ok_oid)
{
// std::cout << "NOT FOUND" << std::endl;
std::cerr << std::hex << "nid " << nid << " xid " << xid << " NOT FOUND!!!" << std::endl;
std::cerr << std::hex << "oid " << oid << " xid " << xid << " NOT FOUND!!!" << std::endl;
return false;
}

// std::cout << val->blockid << std::endl;

info.flags = res_val->ov_flags;
info.size = res_val->ov_size;
info.bid = res_val->ov_paddr;
omr.flags = res_val->ov_flags;
omr.size = res_val->ov_size;
omr.paddr = res_val->ov_paddr;

return true;
}
6 changes: 3 additions & 3 deletions ApfsLib/ApfsNodeMapperBTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class ApfsNodeMapperBTree : public ApfsNodeMapper
ApfsNodeMapperBTree(ApfsContainer &container);
virtual ~ApfsNodeMapperBTree();

bool Init(uint64_t bid_root, uint64_t xid);
bool GetBlockID(node_info_t &info, uint64_t nid, uint64_t xid) override;
bool Init(oid_t omap_oid, xid_t xid);
bool Lookup(omap_res_t & omr, oid_t oid, xid_t xid) override;

void dump(BlockDumper &bd) { m_tree.dump(bd); }

private:
omap_phys_t m_root_ptr;
omap_phys_t m_omap;
BTree m_tree;

ApfsContainer &m_container;
Expand Down
Loading

0 comments on commit d9ae52c

Please sign in to comment.