Coverage Report

Created: 2025-07-04 07:01

/src/libvshadow/libvshadow/libvshadow_block_tree_node.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Block tree node functions
3
 *
4
 * Copyright (C) 2011-2024, 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 <memory.h>
24
#include <types.h>
25
26
#include "libvshadow_block_tree_node.h"
27
#include "libvshadow_definitions.h"
28
#include "libvshadow_libcerror.h"
29
30
/* Creates a block tree node
31
 * Make sure the value block_tree_node is referencing, is set to NULL
32
 * Returns 1 if successful or -1 on error
33
 */
34
int libvshadow_block_tree_node_initialize(
35
     libvshadow_block_tree_node_t **block_tree_node,
36
     off64_t offset,
37
     size64_t size,
38
     size64_t leaf_value_size,
39
     libcerror_error_t **error )
40
811
{
41
811
  static char *function  = "libvshadow_block_tree_node_initialize";
42
811
  size64_t sub_node_size = 0;
43
44
811
  if( block_tree_node == NULL )
45
0
  {
46
0
    libcerror_error_set(
47
0
     error,
48
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50
0
     "%s: invalid block tree node.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
811
  if( *block_tree_node != NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61
0
     "%s: invalid block tree node value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
811
  if( offset < 0 )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
72
0
     "%s: invalid offset value out of bounds.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
811
  if( ( size == 0 )
78
811
   || ( size > (size64_t) ( INT64_MAX - offset ) ) )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
83
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
84
0
     "%s: invalid size value out of bounds.",
85
0
     function );
86
87
0
    return( -1 );
88
0
  }
89
811
  if( leaf_value_size == 0 )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
94
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
95
0
     "%s: invalid leaf value size value out of bounds.",
96
0
     function );
97
98
0
    return( -1 );
99
0
  }
100
811
  *block_tree_node = memory_allocate_structure(
101
811
                      libvshadow_block_tree_node_t );
102
103
811
  if( *block_tree_node == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
108
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
109
0
     "%s: unable to create block tree node.",
110
0
     function );
111
112
0
    goto on_error;
113
0
  }
114
811
  if( memory_set(
115
811
       *block_tree_node,
116
811
       0,
117
811
       sizeof( libvshadow_block_tree_node_t ) ) == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
122
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
123
0
     "%s: unable to clear block tree node.",
124
0
     function );
125
126
0
    memory_free(
127
0
     *block_tree_node );
128
129
0
    *block_tree_node = NULL;
130
131
0
    return( -1 );
132
0
  }
133
811
  if( libcdata_array_initialize(
134
811
       &( ( *block_tree_node )->sub_nodes_array ),
135
811
       LIBVSHADOW_BLOCK_TREE_NUMBER_OF_SUB_NODES,
136
811
       error ) != 1 )
137
0
  {
138
0
    libcerror_error_set(
139
0
     error,
140
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
141
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
142
0
     "%s: unable to create sub nodes array.",
143
0
     function );
144
145
0
    goto on_error;
146
0
  }
147
811
  sub_node_size = leaf_value_size;
148
149
811
  while( ( size / sub_node_size ) > LIBVSHADOW_BLOCK_TREE_NUMBER_OF_SUB_NODES )
150
0
  {
151
0
    sub_node_size *= LIBVSHADOW_BLOCK_TREE_NUMBER_OF_SUB_NODES;
152
0
  }
153
811
  ( *block_tree_node )->start_offset  = offset;
154
811
  ( *block_tree_node )->end_offset    = offset + size;
155
811
  ( *block_tree_node )->size          = size;
156
811
  ( *block_tree_node )->sub_node_size = sub_node_size;
157
158
811
  if( sub_node_size == leaf_value_size )
159
811
  {
160
811
    ( *block_tree_node )->is_leaf_node = 1;
161
811
  }
162
811
  return( 1 );
163
164
0
on_error:
165
0
  if( *block_tree_node != NULL )
166
0
  {
167
0
    memory_free(
168
0
     *block_tree_node );
169
170
0
    *block_tree_node = NULL;
171
0
  }
172
0
  return( -1 );
173
811
}
174
175
/* Frees a block tree node
176
 * Returns 1 if successful or -1 on error
177
 */
178
int libvshadow_block_tree_node_free(
179
     libvshadow_block_tree_node_t **block_tree_node,
180
     int (*value_free_function)(
181
            intptr_t **value,
182
            libcerror_error_t **error ),
183
     libcerror_error_t **error )
184
811
{
185
811
  libvshadow_block_tree_node_t *sub_block_tree_node = NULL;
186
811
  static char *function                             = "libvshadow_block_tree_node_free";
187
811
  int result                                        = 1;
188
811
  int sub_node_index                                = 0;
189
190
811
  if( block_tree_node == NULL )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
195
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
196
0
     "%s: invalid block tree node.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
811
  if( *block_tree_node != NULL )
202
811
  {
203
811
    if( ( *block_tree_node )->is_leaf_node != 0 )
204
811
    {
205
811
      if( libcdata_array_free(
206
811
           &( ( *block_tree_node )->sub_nodes_array ),
207
811
           value_free_function,
208
811
           error ) != 1 )
209
0
      {
210
0
        libcerror_error_set(
211
0
         error,
212
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
213
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
214
0
         "%s: unable to free sub nodes array.",
215
0
         function );
216
217
0
        result = -1;
218
0
      }
219
811
    }
220
0
    else
221
0
    {
222
0
      for( sub_node_index = 0;
223
0
           sub_node_index < LIBVSHADOW_BLOCK_TREE_NUMBER_OF_SUB_NODES;
224
0
           sub_node_index++ )
225
0
      {
226
0
        if( libcdata_array_get_entry_by_index(
227
0
             ( *block_tree_node )->sub_nodes_array,
228
0
             sub_node_index,
229
0
             (intptr_t **) &sub_block_tree_node,
230
0
             error ) != 1 )
231
0
        {
232
0
          libcerror_error_set(
233
0
           error,
234
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
235
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
236
0
           "%s: unable to retrieve sub node: %d.",
237
0
           function,
238
0
           sub_node_index );
239
240
0
          result = -1;
241
0
        }
242
0
        if( libvshadow_block_tree_node_free(
243
0
             &sub_block_tree_node,
244
0
             value_free_function,
245
0
             error ) != 1 )
246
0
        {
247
0
          libcerror_error_set(
248
0
           error,
249
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
251
0
           "%s: unable to free sub node: %d.",
252
0
           function,
253
0
           sub_node_index );
254
255
0
          result = -1;
256
0
        }
257
0
      }
258
0
      if( libcdata_array_free(
259
0
           &( ( *block_tree_node )->sub_nodes_array ),
260
0
           NULL,
261
0
           error ) != 1 )
262
0
      {
263
0
        libcerror_error_set(
264
0
         error,
265
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
266
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
267
0
         "%s: unable to free sub nodes array.",
268
0
         function );
269
270
0
        result = -1;
271
0
      }
272
0
    }
273
811
    memory_free(
274
811
     *block_tree_node );
275
276
811
    *block_tree_node = NULL;
277
811
  }
278
811
  return( result );
279
811
}
280
281
/* Retrieves the sub node for a specific offset
282
 * Returns 1 if successful or -1 on error
283
 */
284
int libvshadow_block_tree_node_get_sub_node_at_offset(
285
     libvshadow_block_tree_node_t *block_tree_node,
286
     off64_t offset,
287
     libvshadow_block_tree_node_t **sub_block_tree_node,
288
     libcerror_error_t **error )
289
0
{
290
0
  static char *function  = "libvshadow_block_tree_node_get_sub_node_at_offset";
291
0
  off64_t sub_node_index = 0;
292
293
0
  if( block_tree_node == NULL )
294
0
  {
295
0
    libcerror_error_set(
296
0
     error,
297
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
298
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
299
0
     "%s: invalid block tree node.",
300
0
     function );
301
302
0
    return( -1 );
303
0
  }
304
0
  if( block_tree_node->is_leaf_node != 0 )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
310
0
     "%s: invalid block tree node - not a branch node.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
0
  if( ( offset < block_tree_node->start_offset )
316
0
   || ( offset >= block_tree_node->end_offset ) )
317
0
  {
318
0
    libcerror_error_set(
319
0
     error,
320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
321
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
322
0
     "%s: invalid offset value out of bounds.",
323
0
     function );
324
325
0
    return( -1 );
326
0
  }
327
0
  sub_node_index = ( offset - block_tree_node->start_offset ) / block_tree_node->sub_node_size;
328
329
0
  if( ( sub_node_index < 0 )
330
0
   || ( sub_node_index > (off64_t) INT_MAX ) )
331
0
  {
332
0
    libcerror_error_set(
333
0
     error,
334
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
335
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
336
0
     "%s: invalid sub node index value out of bounds.",
337
0
     function );
338
339
0
    return( -1 );
340
0
  }
341
0
  if( libcdata_array_get_entry_by_index(
342
0
       block_tree_node->sub_nodes_array,
343
0
       (int) sub_node_index,
344
0
       (intptr_t **) sub_block_tree_node,
345
0
       error ) != 1 )
346
0
  {
347
0
    libcerror_error_set(
348
0
     error,
349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
350
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
351
0
     "%s: unable to retrieve sub node: %" PRIi64 ".",
352
0
     function,
353
0
     sub_node_index );
354
355
0
    return( -1 );
356
0
  }
357
0
  return( 1 );
358
0
}
359
360
/* Sets the sub node for a specific offset
361
 * Returns 1 if successful or -1 on error
362
 */
363
int libvshadow_block_tree_node_set_sub_node_at_offset(
364
     libvshadow_block_tree_node_t *block_tree_node,
365
     off64_t offset,
366
     libvshadow_block_tree_node_t *sub_block_tree_node,
367
     libcerror_error_t **error )
368
0
{
369
0
  static char *function  = "libvshadow_block_tree_node_set_sub_node_at_offset";
370
0
  off64_t sub_node_index = 0;
371
372
0
  if( block_tree_node == NULL )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
378
0
     "%s: invalid block tree node.",
379
0
     function );
380
381
0
    return( -1 );
382
0
  }
383
0
  if( block_tree_node->is_leaf_node != 0 )
384
0
  {
385
0
    libcerror_error_set(
386
0
     error,
387
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
389
0
     "%s: invalid block tree node - not a branch node.",
390
0
     function );
391
392
0
    return( -1 );
393
0
  }
394
0
  if( ( offset < block_tree_node->start_offset )
395
0
   || ( offset >= block_tree_node->end_offset ) )
396
0
  {
397
0
    libcerror_error_set(
398
0
     error,
399
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
400
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
401
0
     "%s: invalid offset value out of bounds.",
402
0
     function );
403
404
0
    return( -1 );
405
0
  }
406
0
  sub_node_index = ( offset - block_tree_node->start_offset ) / block_tree_node->sub_node_size;
407
408
0
  if( ( sub_node_index < 0 )
409
0
   || ( sub_node_index > (off64_t) INT_MAX ) )
410
0
  {
411
0
    libcerror_error_set(
412
0
     error,
413
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
414
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
415
0
     "%s: invalid sub node index value out of bounds.",
416
0
     function );
417
418
0
    return( -1 );
419
0
  }
420
0
  if( libcdata_array_set_entry_by_index(
421
0
       block_tree_node->sub_nodes_array,
422
0
       (int) sub_node_index,
423
0
       (intptr_t *) sub_block_tree_node,
424
0
       error ) != 1 )
425
0
  {
426
0
    libcerror_error_set(
427
0
     error,
428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
429
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
430
0
     "%s: unable to set sub node: %" PRIi64 ".",
431
0
     function,
432
0
     sub_node_index );
433
434
0
    return( -1 );
435
0
  }
436
0
  return( 1 );
437
0
}
438
439
/* Retrieves the leaf value for a specific offset
440
 * Returns 1 if successful or -1 on error
441
 */
442
int libvshadow_block_tree_node_get_leaf_value_at_offset(
443
     libvshadow_block_tree_node_t *block_tree_node,
444
     off64_t offset,
445
     libvshadow_block_descriptor_t **block_descriptor,
446
     off64_t *block_offset,
447
     libcerror_error_t **error )
448
819
{
449
819
  static char *function    = "libvshadow_block_tree_node_get_leaf_value_at_offset";
450
819
  off64_t leaf_value_index = 0;
451
452
819
  if( block_tree_node == NULL )
453
0
  {
454
0
    libcerror_error_set(
455
0
     error,
456
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458
0
     "%s: invalid block tree node.",
459
0
     function );
460
461
0
    return( -1 );
462
0
  }
463
819
  if( block_tree_node->is_leaf_node == 0 )
464
0
  {
465
0
    libcerror_error_set(
466
0
     error,
467
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
469
0
     "%s: invalid block tree node - not a leaf node.",
470
0
     function );
471
472
0
    return( -1 );
473
0
  }
474
819
  if( ( offset < block_tree_node->start_offset )
475
819
   || ( offset >= block_tree_node->end_offset ) )
476
60
  {
477
60
    libcerror_error_set(
478
60
     error,
479
60
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
480
60
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
481
60
     "%s: invalid offset value out of bounds.",
482
60
     function );
483
484
60
    return( -1 );
485
60
  }
486
759
  if( block_offset == NULL )
487
0
  {
488
0
    libcerror_error_set(
489
0
     error,
490
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
491
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
492
0
     "%s: invalid block offset.",
493
0
     function );
494
495
0
    return( -1 );
496
0
  }
497
759
  leaf_value_index = ( offset - block_tree_node->start_offset ) / block_tree_node->sub_node_size;
498
499
759
  if( ( leaf_value_index < 0 )
500
759
   || ( leaf_value_index > (off64_t) INT_MAX ) )
501
0
  {
502
0
    libcerror_error_set(
503
0
     error,
504
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
505
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
506
0
     "%s: invalid leaf value index value out of bounds.",
507
0
     function );
508
509
0
    return( -1 );
510
0
  }
511
759
  if( libcdata_array_get_entry_by_index(
512
759
       block_tree_node->sub_nodes_array,
513
759
       (int) leaf_value_index,
514
759
       (intptr_t **) block_descriptor,
515
759
       error ) != 1 )
516
0
  {
517
0
    libcerror_error_set(
518
0
     error,
519
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
521
0
     "%s: unable to retrieve leaf value: %" PRIi64 ".",
522
0
     function,
523
0
     leaf_value_index );
524
525
0
    return( -1 );
526
0
  }
527
759
  *block_offset = offset - ( leaf_value_index * block_tree_node->sub_node_size );
528
529
759
  return( 1 );
530
759
}
531
532
/* Sets the leaf value for a specific offset
533
 * Returns 1 if successful or -1 on error
534
 */
535
int libvshadow_block_tree_node_set_leaf_value_at_offset(
536
     libvshadow_block_tree_node_t *block_tree_node,
537
     off64_t offset,
538
     libvshadow_block_descriptor_t *block_descriptor,
539
     libcerror_error_t **error )
540
757
{
541
757
  static char *function    = "libvshadow_block_tree_node_set_leaf_value_at_offset";
542
757
  off64_t leaf_value_index = 0;
543
544
757
  if( block_tree_node == NULL )
545
0
  {
546
0
    libcerror_error_set(
547
0
     error,
548
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
549
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
550
0
     "%s: invalid block tree node.",
551
0
     function );
552
553
0
    return( -1 );
554
0
  }
555
757
  if( block_tree_node->is_leaf_node == 0 )
556
0
  {
557
0
    libcerror_error_set(
558
0
     error,
559
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
560
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
561
0
     "%s: invalid block tree node - not a leaf node.",
562
0
     function );
563
564
0
    return( -1 );
565
0
  }
566
757
  if( ( offset < block_tree_node->start_offset )
567
757
   || ( offset >= block_tree_node->end_offset ) )
568
0
  {
569
0
    libcerror_error_set(
570
0
     error,
571
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
572
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
573
0
     "%s: invalid offset value out of bounds.",
574
0
     function );
575
576
0
    return( -1 );
577
0
  }
578
757
  leaf_value_index = ( offset - block_tree_node->start_offset ) / block_tree_node->sub_node_size;
579
580
757
  if( ( leaf_value_index < 0 )
581
757
   || ( leaf_value_index > (off64_t) INT_MAX ) )
582
0
  {
583
0
    libcerror_error_set(
584
0
     error,
585
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
587
0
     "%s: invalid leaf value index value out of bounds.",
588
0
     function );
589
590
0
    return( -1 );
591
0
  }
592
757
  if( libcdata_array_set_entry_by_index(
593
757
       block_tree_node->sub_nodes_array,
594
757
       (int) leaf_value_index,
595
757
       (intptr_t *) block_descriptor,
596
757
       error ) != 1 )
597
0
  {
598
0
    libcerror_error_set(
599
0
     error,
600
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
601
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
602
0
     "%s: unable to set leaf value: %" PRIi64 ".",
603
0
     function,
604
0
     leaf_value_index );
605
606
0
    return( -1 );
607
0
  }
608
757
  return( 1 );
609
757
}
610