Coverage Report

Created: 2025-07-01 06:59

/src/sleuthkit/tsk/pool/pool_open.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The Sleuth Kit
3
 *
4
 * Brian Carrier [carrier <at> sleuthkit [dot] org]
5
 * Copyright (c) 2018-2019 BlackBag Technologies.  All Rights reserved
6
 * Copyright (c) 2022 Joachim Metz <joachim.metz@gmail.com>
7
 *
8
 * This software is distributed under the Common Public License 1.0
9
 */
10
#include "tsk/base/tsk_base_i.h"
11
12
#include "apfs_pool_compat.hpp"
13
#include "lvm_pool_compat.hpp"
14
#include "pool_compat.hpp"
15
16
#include "tsk/fs/tsk_apfs.hpp"
17
#include "tsk/img/tsk_img.h"
18
#include "tsk/vs/tsk_vs.h"
19
20
const TSK_POOL_INFO *tsk_pool_open_sing(const TSK_VS_PART_INFO *part,
21
0
                                        TSK_POOL_TYPE_ENUM type) {
22
0
  tsk_error_reset();
23
24
0
  if (part == nullptr) {
25
0
    tsk_error_set_errno(TSK_ERR_POOL_ARG);
26
0
    tsk_error_set_errstr("tsk_pool_open_sing: Null vpart handle");
27
0
    return nullptr;
28
0
  }
29
30
0
  if ((part->vs == nullptr) || (part->vs->tag != TSK_VS_INFO_TAG)) {
31
0
    tsk_error_set_errno(TSK_ERR_POOL_ARG);
32
0
    tsk_error_set_errstr("tsk_pool_open_sing: Null vs handle");
33
0
    return nullptr;
34
0
  }
35
36
0
  const auto offset = part->start * part->vs->block_size + part->vs->offset;
37
38
0
  return tsk_pool_open_img_sing(part->vs->img_info, offset, type);
39
0
}
40
41
42
/**
43
 * @param num_vols Number of volumes in parts array
44
 * @param parts List of Volume partitions to review
45
 * @type Type of pool to open (or auto detect)
46
 * @returns Pool structure
47
 */
48
const TSK_POOL_INFO *tsk_pool_open(int num_vols,
49
                                   const TSK_VS_PART_INFO *const parts[],
50
0
                                   TSK_POOL_TYPE_ENUM type) {
51
0
  tsk_error_reset();
52
53
0
  if (num_vols <= 0) {
54
0
    tsk_error_set_errno(TSK_ERR_POOL_ARG);
55
0
    tsk_error_set_errstr("tsk_pool_open_: Invalid num_vols");
56
0
    return nullptr;
57
0
  }
58
59
0
  if (parts == nullptr) {
60
0
    tsk_error_set_errno(TSK_ERR_POOL_ARG);
61
0
    tsk_error_set_errstr("tsk_pool_open_sing: Null parts");
62
0
    return nullptr;
63
0
  }
64
65
  // Make arrays of equal size to store the volume offset and IMG_INFO
66
0
  auto imgs = std::make_unique<TSK_IMG_INFO *[]>(num_vols);
67
0
  auto offsets = std::make_unique<TSK_OFF_T[]>(num_vols);
68
69
0
  for (auto i = 0; i < num_vols; i++) {
70
0
    const auto &part = parts[i];
71
72
0
    if ((part->vs == nullptr) || (part->vs->tag != TSK_VS_INFO_TAG)) {
73
0
      tsk_error_set_errno(TSK_ERR_POOL_ARG);
74
0
      tsk_error_set_errstr("tsk_pool_open: Null vs handle");
75
0
      return nullptr;
76
0
    }
77
78
0
    const auto offset = part->start * part->vs->block_size + part->vs->offset;
79
80
0
    imgs[i] = part->vs->img_info;
81
0
    offsets[i] = offset;
82
0
  }
83
84
0
  return tsk_pool_open_img(num_vols, imgs.get(), offsets.get(), type);
85
0
}
86
87
/**
88
 * Open a pool at the given offset in the given image.
89
 */
90
const TSK_POOL_INFO *tsk_pool_open_img_sing(TSK_IMG_INFO *img, TSK_OFF_T offset,
91
46
                                            TSK_POOL_TYPE_ENUM type) {
92
46
  return tsk_pool_open_img(1, &img, &offset, type);
93
46
}
94
95
96
/**
97
 * Open a pool at the set of image offsets
98
 * @param num_imgs Size of imgs array
99
 * @param imgs List of IMG_INFO to look for pool
100
 * @param offsets List of offsets to look for pool in the img at the same array index
101
 * @param type Pool type to open
102
 */
103
const TSK_POOL_INFO *tsk_pool_open_img(int num_imgs, TSK_IMG_INFO *const imgs[],
104
                                       const TSK_OFF_T offsets[],
105
46
                                       TSK_POOL_TYPE_ENUM type) {
106
46
  std::vector<APFSPool::img_t> apfs_v{};
107
46
  apfs_v.reserve(num_imgs);
108
109
92
  for (auto i = 0; i < num_imgs; i++) {
110
46
    apfs_v.emplace_back(imgs[i], offsets[i]);
111
46
  }
112
#ifdef HAVE_LIBVSLVM
113
  std::vector<LVMPool::img_t> lvm_v{};
114
115
  lvm_v.reserve(num_imgs);
116
117
  for (auto i = 0; i < num_imgs; i++) {
118
    lvm_v.emplace_back(imgs[i], offsets[i]);
119
  }
120
#endif
121
122
46
  const char *error_string = NULL;
123
124
46
  switch (type) {
125
0
    case TSK_POOL_TYPE_DETECT:
126
0
      try {
127
0
        auto apfs = new APFSPoolCompat(std::move(apfs_v), APFS_POOL_NX_BLOCK_LATEST);
128
129
0
        return &apfs->pool_info();
130
0
      } catch (std::runtime_error &e) {
131
0
        error_string = e.what();
132
0
      }
133
#ifdef HAVE_LIBVSLVM
134
      try {
135
        auto lvm = new LVMPoolCompat(std::move(lvm_v));
136
137
        return &lvm->pool_info();
138
      } catch (std::runtime_error &e) {
139
        error_string = e.what();
140
      }
141
#endif
142
0
      if (tsk_verbose) {
143
0
        tsk_fprintf(stderr, "tsk_pool_open_img: pool type detection failed: %s\n",
144
0
                    error_string);
145
0
      }
146
0
      break;
147
46
    case TSK_POOL_TYPE_APFS:
148
46
      try {
149
46
        auto apfs = new APFSPoolCompat(std::move(apfs_v), APFS_POOL_NX_BLOCK_LATEST);
150
151
46
        return &apfs->pool_info();
152
46
      } catch (std::runtime_error &e) {
153
44
        tsk_error_reset();
154
44
        tsk_error_set_errno(TSK_ERR_POOL_UNKTYPE);
155
44
        tsk_error_set_errstr("%s", e.what());
156
44
      }
157
44
      return nullptr;
158
159
    // Will fallthrough to TSK_POOL_TYPE_UNSUPP if libvslvm is not available.
160
0
    case TSK_POOL_TYPE_LVM:
161
#ifdef HAVE_LIBVSLVM
162
      try {
163
        auto lvm = new LVMPoolCompat(std::move(lvm_v));
164
165
        return &lvm->pool_info();
166
      } catch (std::runtime_error &e) {
167
        tsk_error_reset();
168
        tsk_error_set_errno(TSK_ERR_POOL_UNKTYPE);
169
        tsk_error_set_errstr("%s", e.what());
170
      }
171
      return nullptr;
172
#endif
173
0
    case TSK_POOL_TYPE_UNSUPP:
174
      // All other pool types are unsupported
175
0
      tsk_error_reset();
176
0
      tsk_error_set_errno(TSK_ERR_POOL_UNSUPTYPE);
177
0
      tsk_error_set_errstr("%d", type);
178
0
      return nullptr;
179
46
  }
180
181
  // All other pool types are unsupported
182
0
  tsk_error_reset();
183
0
  tsk_error_set_errno(TSK_ERR_POOL_UNSUPTYPE);
184
0
  tsk_error_set_errstr("%d", type);
185
0
  return nullptr;
186
46
}
187
188
2
void tsk_pool_close(const TSK_POOL_INFO *pool) {
189
  // sanity checks
190
2
  if ((pool == nullptr) || (pool->tag != TSK_POOL_INFO_TAG)) return;
191
192
  // each pool container is supposed to free the struct
193
2
  pool->close(pool);
194
2
}