Coverage Report

Created: 2024-02-25 07:20

/src/libvmdk/libvmdk/libvmdk_grain_table.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Grain table functions
3
 *
4
 * Copyright (C) 2009-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libvmdk_definitions.h"
28
#include "libvmdk_extent_table.h"
29
#include "libvmdk_grain_data.h"
30
#include "libvmdk_grain_table.h"
31
#include "libvmdk_io_handle.h"
32
#include "libvmdk_libbfio.h"
33
#include "libvmdk_libcerror.h"
34
#include "libvmdk_libcnotify.h"
35
#include "libvmdk_libfcache.h"
36
#include "libvmdk_libfdata.h"
37
#include "libvmdk_unused.h"
38
39
/* Creates a grain table
40
 * Make sure the value grain_table is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libvmdk_grain_table_initialize(
44
     libvmdk_grain_table_t **grain_table,
45
     libvmdk_io_handle_t *io_handle,
46
     libcerror_error_t **error )
47
0
{
48
0
  static char *function = "libvmdk_grain_table_initialize";
49
50
0
  if( grain_table == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid grain table.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
0
  if( *grain_table != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid grain table value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
0
  if( io_handle == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
78
0
     "%s: invalid IO handle.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
0
  *grain_table = memory_allocate_structure(
84
0
                  libvmdk_grain_table_t );
85
86
0
  if( *grain_table == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
92
0
     "%s: unable to create grain table.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
0
  if( memory_set(
98
0
       *grain_table,
99
0
       0,
100
0
       sizeof( libvmdk_grain_table_t ) ) == NULL )
101
0
  {
102
0
    libcerror_error_set(
103
0
     error,
104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
105
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
106
0
     "%s: unable to clear grain table.",
107
0
     function );
108
109
0
    goto on_error;
110
0
  }
111
0
  ( *grain_table )->io_handle = io_handle;
112
113
0
  return( 1 );
114
115
0
on_error:
116
0
  if( *grain_table != NULL )
117
0
  {
118
0
    memory_free(
119
0
     *grain_table );
120
121
0
    *grain_table = NULL;
122
0
  }
123
0
  return( -1 );
124
0
}
125
126
/* Frees a grain table
127
 * Returns 1 if successful or -1 on error
128
 */
129
int libvmdk_grain_table_free(
130
     libvmdk_grain_table_t **grain_table,
131
     libcerror_error_t **error )
132
0
{
133
0
  static char *function = "libvmdk_grain_table_free";
134
135
0
  if( grain_table == NULL )
136
0
  {
137
0
    libcerror_error_set(
138
0
     error,
139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
141
0
     "%s: invalid grain table.",
142
0
     function );
143
144
0
    return( -1 );
145
0
  }
146
0
  if( *grain_table != NULL )
147
0
  {
148
    /* The IO handle reference is freed elsewhere
149
     */
150
0
    memory_free(
151
0
     *grain_table );
152
153
0
    *grain_table = NULL;
154
0
  }
155
0
  return( 1 );
156
0
}
157
158
/* Determines if the grain at a specific offset is sparse
159
 * Returns 1 if the grain is sparse, 0 if not or -1 on error
160
 */
161
int libvmdk_grain_table_grain_is_sparse_at_offset(
162
     libvmdk_grain_table_t *grain_table,
163
     uint64_t grain_index,
164
     libbfio_pool_t *file_io_pool,
165
     libvmdk_extent_table_t *extent_table,
166
     off64_t offset,
167
     libcerror_error_t **error )
168
0
{
169
0
  libvmdk_extent_file_t *extent_file = NULL;
170
0
  libfdata_list_t *grains_list       = NULL;
171
0
  static char *function              = "libvmdk_grain_table_grain_is_sparse_at_offset";
172
0
  off64_t extent_file_data_offset    = 0;
173
0
  off64_t grain_data_offset          = 0;
174
0
  off64_t grain_group_data_offset    = 0;
175
0
  off64_t grain_offset               = 0;
176
0
  size64_t grain_size                = 0;
177
0
  uint32_t grain_flags               = 0;
178
0
  int extent_number                  = 0;
179
0
  int grain_file_index               = 0;
180
0
  int grain_groups_list_index        = 0;
181
0
  int grains_list_index              = 0;
182
0
  int result                         = 0;
183
184
0
  if( grain_table == NULL )
185
0
  {
186
0
    libcerror_error_set(
187
0
     error,
188
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
189
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
190
0
     "%s: invalid grain table.",
191
0
     function );
192
193
0
    return( -1 );
194
0
  }
195
0
  if( libvmdk_extent_table_get_extent_file_at_offset(
196
0
       extent_table,
197
0
       offset,
198
0
       file_io_pool,
199
0
       &extent_number,
200
0
       &extent_file_data_offset,
201
0
       &extent_file,
202
0
       error ) != 1 )
203
0
  {
204
0
    libcerror_error_set(
205
0
     error,
206
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
207
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
208
0
     "%s: unable to retrieve extent file at offset: %" PRIi64 " (0x%08" PRIx64 ") from extent table.",
209
0
     function,
210
0
     offset,
211
0
     offset );
212
213
0
    return( -1 );
214
0
  }
215
0
  result = libvmdk_extent_file_grain_group_is_sparse_at_offset(
216
0
            extent_file,
217
0
            extent_file_data_offset,
218
0
            &grain_groups_list_index,
219
0
            &grain_group_data_offset,
220
0
            error );
221
222
0
  if( result == -1 )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
227
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
228
0
     "%s: unable to retrieve grain group from extent file: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
229
0
     function,
230
0
     extent_number,
231
0
     extent_file_data_offset,
232
0
     extent_file_data_offset );
233
234
0
    return( -1 );
235
0
  }
236
0
  else if( result != 0 )
237
0
  {
238
0
    return( 1 );
239
0
  }
240
0
  if( libvmdk_extent_file_get_grain_group_at_offset(
241
0
       extent_file,
242
0
       file_io_pool,
243
0
       extent_file_data_offset,
244
0
       &grain_groups_list_index,
245
0
       &grain_group_data_offset,
246
0
       &grains_list,
247
0
       error ) != 1 )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
252
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
253
0
     "%s: unable to retrieve grain group from extent file: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
254
0
     function,
255
0
     extent_number,
256
0
     extent_file_data_offset,
257
0
     extent_file_data_offset );
258
259
0
    return( -1 );
260
0
  }
261
0
  if( libfdata_list_get_element_at_offset(
262
0
       grains_list,
263
0
       grain_group_data_offset,
264
0
       &grains_list_index,
265
0
       &grain_data_offset,
266
0
       &grain_file_index,
267
0
       &grain_offset,
268
0
       &grain_size,
269
0
       &grain_flags,
270
0
       error ) != 1 )
271
0
  {
272
0
    libcerror_error_set(
273
0
     error,
274
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
275
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
276
0
     "%s: unable to retrieve grain: %" PRIu64 " from grain group: %d in extent file: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
277
0
     function,
278
0
     grain_index,
279
0
     grain_groups_list_index,
280
0
     extent_number,
281
0
     extent_file_data_offset,
282
0
     extent_file_data_offset );
283
284
0
    return( -1 );
285
0
  }
286
0
  if( ( grain_flags & LIBVMDK_RANGE_FLAG_IS_SPARSE ) != 0 )
287
0
  {
288
0
    return( 1 );
289
0
  }
290
0
  return( 0 );
291
0
}
292
293
/* Retrieves the grain data of a grain at a specific offset
294
 * Returns 1 if successful or -1 on error
295
 */
296
int libvmdk_grain_table_get_grain_data_at_offset(
297
     libvmdk_grain_table_t *grain_table,
298
     uint64_t grain_index,
299
     libbfio_pool_t *file_io_pool,
300
     libvmdk_extent_table_t *extent_table,
301
     libfcache_cache_t *grains_cache,
302
     off64_t offset,
303
     libvmdk_grain_data_t **grain_data,
304
     off64_t *grain_data_offset,
305
     libcerror_error_t **error )
306
0
{
307
0
  libvmdk_extent_file_t *extent_file = NULL;
308
0
  libfdata_list_t *grains_list       = NULL;
309
0
  static char *function              = "libvmdk_grain_table_get_grain_data_at_offset";
310
0
  off64_t grain_group_data_offset    = 0;
311
0
  off64_t extent_file_data_offset    = 0;
312
0
  int extent_number                  = 0;
313
0
  int grain_groups_list_index        = 0;
314
0
  int grains_list_index              = 0;
315
316
0
  if( grain_table == NULL )
317
0
  {
318
0
    libcerror_error_set(
319
0
     error,
320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
321
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
322
0
     "%s: invalid grain table.",
323
0
     function );
324
325
0
    return( -1 );
326
0
  }
327
0
  if( libvmdk_extent_table_get_extent_file_at_offset(
328
0
       extent_table,
329
0
       offset,
330
0
       file_io_pool,
331
0
       &extent_number,
332
0
       &extent_file_data_offset,
333
0
       &extent_file,
334
0
       error ) != 1 )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
340
0
     "%s: unable to retrieve extent file at offset: %" PRIi64 " (0x%08" PRIx64 ") from extent table.",
341
0
     function,
342
0
     offset,
343
0
     offset );
344
345
0
    return( -1 );
346
0
  }
347
0
  if( libvmdk_extent_file_get_grain_group_at_offset(
348
0
       extent_file,
349
0
       file_io_pool,
350
0
       extent_file_data_offset,
351
0
       &grain_groups_list_index,
352
0
       &grain_group_data_offset,
353
0
       &grains_list,
354
0
       error ) != 1 )
355
0
  {
356
0
    libcerror_error_set(
357
0
     error,
358
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
359
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
360
0
     "%s: unable to retrieve grain group from extent file: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
361
0
     function,
362
0
     extent_number,
363
0
     extent_file_data_offset,
364
0
     extent_file_data_offset );
365
366
0
    return( -1 );
367
0
  }
368
0
  if( libfdata_list_get_element_value_at_offset(
369
0
       grains_list,
370
0
       (intptr_t *) file_io_pool,
371
0
       (libfdata_cache_t *) grains_cache,
372
0
       grain_group_data_offset,
373
0
       &grains_list_index,
374
0
       grain_data_offset,
375
0
       (intptr_t **) grain_data,
376
0
       0,
377
0
       error ) != 1 )
378
0
  {
379
0
    libcerror_error_set(
380
0
     error,
381
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
382
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
383
0
     "%s: unable to retrieve grain: %" PRIu64 " data from grain group: %d in extent file: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
384
0
     function,
385
0
     grain_index,
386
0
     grain_groups_list_index,
387
0
     extent_number,
388
0
     extent_file_data_offset,
389
0
     extent_file_data_offset );
390
391
0
    return( -1 );
392
0
  }
393
0
  return( 1 );
394
0
}
395