Coverage Report

Created: 2025-11-09 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sleuthkit/tsk/fs/apfs_fs.hpp
Line
Count
Source
1
/*
2
 * The Sleuth Kit
3
 *
4
 * Brian Carrier [carrier <at> sleuthkit [dot] org]
5
 * Copyright (c) 2019-2020 Brian Carrier.  All Rights reserved
6
 * Copyright (c) 2018-2019 BlackBag Technologies.  All Rights reserved
7
 *
8
 * This software is distributed under the Common Public License 1.0
9
 */
10
#pragma once
11
12
#if HAVE_CONFIG_H
13
#include "tsk/tsk_config.h"
14
#endif
15
16
#include "tsk/util/crypto.hpp"
17
#include "apfs_fs.h"
18
#include "tsk_apfs.hpp"
19
20
class APFSJObject {
21
  using jit = APFSJObjBtreeNode::iterator;
22
  using child_entry = struct {
23
    std::string name;
24
    apfs_dir_record rec;
25
  };
26
  using extent = struct {
27
    uint64_t offset;
28
    uint64_t phys;
29
    uint64_t len;
30
    uint64_t crypto_id;
31
  };
32
33
  using inline_xattr = struct {
34
    std::string name;
35
    std::string data;
36
  };
37
38
  using nonres_xattr = struct {
39
    std::string name;
40
    uint64_t oid;
41
    uint64_t size;
42
    uint64_t allocated_size;
43
    uint64_t crypto_id;
44
  };
45
46
  apfs_inode _inode{};
47
  std::vector<child_entry> _children{};
48
  std::vector<extent> _extents{};
49
  std::vector<inline_xattr> _inline_xattrs{};
50
  std::vector<nonres_xattr> _nonres_xattrs{};
51
52
  std::string _name{};
53
  uint64_t _size{};
54
  uint64_t _size_on_disk{};
55
  bool _is_clone{};
56
57
  void add_entry(const jit::value_type &);
58
59
 public:
60
  using key_type = APFSJObjKey;
61
62
0
  APFSJObject() = default;
63
64
  APFSJObject(const std::pair<jit, jit> &);
65
  APFSJObject(const jit &, const jit &);
66
67
  APFSJObject(const APFSJObject &) = default;
68
  APFSJObject &operator=(const APFSJObject &) = default;
69
70
  APFSJObject(APFSJObject &&) = default;
71
0
  APFSJObject &operator=(APFSJObject &&) = default;
72
73
1
  inline bool valid() const noexcept {
74
1
    return _inode.private_id != 0 || !_extents.empty();
75
1
  }
76
77
0
  inline auto child_count() const noexcept { return _children.size(); }
78
79
0
  inline const apfs_inode &inode() const noexcept { return _inode; }
80
81
0
  inline const std::string &name() const noexcept { return _name; }
82
83
0
  inline const std::vector<extent> &extents() const noexcept {
84
0
    return _extents;
85
0
  }
86
87
0
  inline const std::vector<inline_xattr> &inline_xattrs() const noexcept {
88
0
    return _inline_xattrs;
89
0
  }
90
91
0
  inline const std::vector<nonres_xattr> &nonres_xattrs() const noexcept {
92
0
    return _nonres_xattrs;
93
0
  }
94
95
0
  inline const std::vector<child_entry> &children() const noexcept {
96
0
    return _children;
97
0
  }
98
99
0
  inline uint64_t size() const noexcept { return _size; }
100
101
0
  inline uint64_t size_on_disk() const noexcept { return _size_on_disk; }
102
103
0
  inline bool is_clone() const noexcept { return _is_clone; }
104
};
105
106
class APFSJObjTree {
107
  using jit = APFSJObjBtreeNode::iterator;
108
109
 protected:
110
  struct crypto {
111
#ifdef HAVE_LIBCRYPTO
112
    std::unique_ptr<aes_xts_decryptor> decryptor{};
113
#endif
114
    std::unique_ptr<uint8_t[]> key{};
115
    std::string password{};
116
    crypto(const APFSFileSystem::crypto_info_t &crypto);
117
  } _crypto;
118
  APFSObjectBtreeNode _obj_root;
119
  APFSJObjBtreeNode _jobj_root;
120
  uint64_t _root_tree_oid;
121
122
1
  inline auto jobjs(uint64_t oid) const {
123
1
    return _jobj_root.find_range(
124
1
        oid, [](const auto &key, const auto &b) noexcept->int64_t {
125
0
          const auto akey = key.template as<APFSJObject::key_type>();
126
127
0
          return akey->oid() - b;
128
0
        });
129
1
  }
130
131
  APFSJObjTree(const APFSFileSystem &vol);
132
133
 public:
134
  APFSJObjTree(const APFSPool &pool, apfs_block_num obj_omap,
135
               uint64_t root_tree_oid,
136
               const APFSFileSystem::crypto_info_t &crypto);
137
138
  APFSJObjTree(APFSJObjTree &&) = default;
139
140
1
  inline APFSJObject obj(uint64_t oid) const { return {jobjs(oid)}; }
141
142
  void set_snapshot(uint64_t snap_xid);
143
144
  // iterator stuff
145
  class iterator;
146
147
  iterator begin() const;
148
  iterator end() const;
149
};
150
151
class APFSJObjTree::iterator {
152
 public:
153
  using iterator_category = std::forward_iterator_tag;
154
  using difference_type = uint32_t;
155
  using value_type = APFSJObject;
156
  using reference = const value_type &;
157
  using pointer = const value_type *;
158
159
 protected:
160
  const APFSJObjTree *_tree;
161
  jit _next;
162
  APFSJObject _jobj;
163
164
  iterator(const APFSJObjTree *tree) noexcept;
165
  iterator(const APFSJObjTree *tree, uint64_t oid);
166
167
 public:
168
  iterator() = default;
169
170
  iterator(const iterator &) = default;
171
  iterator &operator=(const iterator &) = default;
172
173
  iterator(iterator &&) = default;
174
  iterator &operator=(iterator &&) = default;
175
176
0
  inline reference operator*() const noexcept { return _jobj; }
177
178
0
  inline pointer operator->() const noexcept { return &_jobj; }
179
180
  iterator &operator++();
181
182
0
  inline value_type operator++(int) {
183
0
    value_type copy{_jobj};
184
0
    this->operator++();
185
0
    return copy;
186
0
  }
187
188
0
  inline bool operator==(const iterator &rhs) const noexcept {
189
0
    return (_tree == rhs._tree && _next == rhs._next);
190
0
  }
191
192
0
  inline bool operator!=(const iterator &rhs) const noexcept {
193
0
    return !this->operator==(rhs);
194
0
  }
195
196
  friend APFSJObjTree;
197
};