Coverage Report

Created: 2026-01-20 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvshadow/libvshadow/libvshadow_store_block.c
Line
Count
Source
1
/*
2
 * Store block functions
3
 *
4
 * Copyright (C) 2011-2025, 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 "libvshadow_debug.h"
28
#include "libvshadow_libbfio.h"
29
#include "libvshadow_libcerror.h"
30
#include "libvshadow_libcnotify.h"
31
#include "libvshadow_libfguid.h"
32
#include "libvshadow_io_handle.h"
33
#include "libvshadow_store_block.h"
34
35
#include "vshadow_store.h"
36
37
/* Creates a store block
38
 * Make sure the value store_block is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libvshadow_store_block_initialize(
42
     libvshadow_store_block_t **store_block,
43
     size_t block_size,
44
     libcerror_error_t **error )
45
265
{
46
265
  static char *function = "libvshadow_store_block_initialize";
47
48
265
  if( store_block == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid store block.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
265
  if( *store_block != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid store block value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
265
  if( ( block_size == 0 )
71
265
   || ( block_size > (size_t) SSIZE_MAX ) )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
76
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
77
0
     "%s: invalid block size value out of bounds.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
265
  *store_block = memory_allocate_structure(
83
265
                  libvshadow_store_block_t );
84
85
265
  if( *store_block == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
91
0
     "%s: unable to create store block.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
265
  if( memory_set(
97
265
       *store_block,
98
265
       0,
99
265
       sizeof( libvshadow_store_block_t ) ) == NULL )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
104
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
105
0
     "%s: unable to clear store block.",
106
0
     function );
107
108
0
    memory_free(
109
0
     *store_block );
110
111
0
    *store_block = NULL;
112
113
0
    return( -1 );
114
0
  }
115
265
  ( *store_block )->data = (uint8_t *) memory_allocate(
116
265
                                        sizeof( uint8_t ) * block_size );
117
118
265
  if( ( *store_block )->data == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
123
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
124
0
     "%s: unable to create store block data.",
125
0
     function );
126
127
0
    goto on_error;
128
0
  }
129
265
  ( *store_block )->data_size = block_size;
130
131
265
  return( 1 );
132
133
0
on_error:
134
0
  if( *store_block != NULL )
135
0
  {
136
0
    memory_free(
137
0
     *store_block );
138
139
0
    *store_block = NULL;
140
0
  }
141
0
  return( -1 );
142
265
}
143
144
/* Frees a store block
145
 * Returns 1 if successful or -1 on error
146
 */
147
int libvshadow_store_block_free(
148
     libvshadow_store_block_t **store_block,
149
     libcerror_error_t **error )
150
265
{
151
265
  static char *function = "libvshadow_store_block_free";
152
153
265
  if( store_block == NULL )
154
0
  {
155
0
    libcerror_error_set(
156
0
     error,
157
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
158
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
159
0
     "%s: invalid store block.",
160
0
     function );
161
162
0
    return( -1 );
163
0
  }
164
265
  if( *store_block != NULL )
165
265
  {
166
265
    memory_free(
167
265
     ( *store_block )->data );
168
265
    memory_free(
169
265
     *store_block );
170
171
265
    *store_block = NULL;
172
265
  }
173
265
  return( 1 );
174
265
}
175
176
/* Reads the store block
177
 * Returns 1 if successful or -1 on error
178
 */
179
int libvshadow_store_block_read(
180
     libvshadow_store_block_t *store_block,
181
     libbfio_handle_t *file_io_handle,
182
     off64_t file_offset,
183
     libcerror_error_t **error )
184
265
{
185
265
  static char *function = "libvshadow_store_block_read";
186
265
  ssize_t read_count    = 0;
187
188
265
  if( store_block == NULL )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
194
0
     "%s: invalid store block.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
265
  if( store_block->data == NULL )
200
0
  {
201
0
    libcerror_error_set(
202
0
     error,
203
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
205
0
     "%s: invalid store block - missing data.",
206
0
     function );
207
208
0
    return( -1 );
209
0
  }
210
#if defined( HAVE_DEBUG_OUTPUT )
211
  if( libcnotify_verbose != 0 )
212
  {
213
    libcnotify_printf(
214
     "%s: reading store block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
215
     function,
216
     file_offset,
217
     file_offset );
218
  }
219
#endif
220
265
  read_count = libbfio_handle_read_buffer_at_offset(
221
265
                file_io_handle,
222
265
                store_block->data,
223
265
                store_block->data_size,
224
265
                file_offset,
225
265
                error );
226
227
265
  if( read_count != (ssize_t) store_block->data_size )
228
42
  {
229
42
    libcerror_error_set(
230
42
     error,
231
42
     LIBCERROR_ERROR_DOMAIN_IO,
232
42
     LIBCERROR_IO_ERROR_READ_FAILED,
233
42
     "%s: unable to read store block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
234
42
     function,
235
42
     file_offset,
236
42
     file_offset );
237
238
42
    return( -1 );
239
42
  }
240
223
  if( libvshadow_store_block_read_header_data(
241
223
       store_block,
242
223
       store_block->data,
243
223
       store_block->data_size,
244
223
       error ) != 1 )
245
61
  {
246
61
    libcerror_error_set(
247
61
     error,
248
61
     LIBCERROR_ERROR_DOMAIN_IO,
249
61
     LIBCERROR_IO_ERROR_READ_FAILED,
250
61
     "%s: unable to read store block header.",
251
61
     function );
252
253
61
    return( -1 );
254
61
  }
255
162
  return( 1 );
256
223
}
257
258
/* Reads the store block header
259
 * Returns 1 if successful or -1 on error
260
 */
261
int libvshadow_store_block_read_header_data(
262
     libvshadow_store_block_t *store_block,
263
     const uint8_t *data,
264
     size_t data_size,
265
     libcerror_error_t **error )
266
223
{
267
223
  static char *function         = "libvshadow_store_block_read_header_data";
268
223
  uint64_t safe_next_offset     = 0;
269
223
  uint64_t safe_offset          = 0;
270
223
  uint64_t safe_relative_offset = 0;
271
272
#if defined( HAVE_DEBUG_OUTPUT )
273
  uint64_t value_64bit          = 0;
274
#endif
275
276
223
  if( store_block == NULL )
277
0
  {
278
0
    libcerror_error_set(
279
0
     error,
280
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
281
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
282
0
     "%s: invalid store block.",
283
0
     function );
284
285
0
    return( -1 );
286
0
  }
287
223
  if( data == NULL )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
292
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
293
0
     "%s: invalid data.",
294
0
     function );
295
296
0
    return( -1 );
297
0
  }
298
223
  if( ( data_size < sizeof( vshadow_store_block_header_t ) )
299
223
   || ( data_size > (size_t) SSIZE_MAX ) )
300
0
  {
301
0
    libcerror_error_set(
302
0
     error,
303
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
305
0
     "%s: invalid data size value out of bounds.",
306
0
     function );
307
308
0
    return( -1 );
309
0
  }
310
#if defined( HAVE_DEBUG_OUTPUT )
311
  if( libcnotify_verbose != 0 )
312
  {
313
    libcnotify_printf(
314
     "%s: store block header data:\n",
315
     function );
316
    libcnotify_print_data(
317
     store_block->data,
318
     sizeof( vshadow_store_block_header_t ),
319
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
320
  }
321
#endif
322
223
  if( memory_compare(
323
223
       ( (vshadow_store_block_header_t *) data )->identifier,
324
223
       vshadow_vss_identifier,
325
223
       16 ) != 0 )
326
16
  {
327
16
    libcerror_error_set(
328
16
     error,
329
16
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
16
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
331
16
     "%s: invalid store block list header identifier.",
332
16
     function );
333
334
16
    return( -1 );
335
16
  }
336
207
  byte_stream_copy_to_uint32_little_endian(
337
207
   ( (vshadow_store_block_header_t *) data )->version,
338
207
   store_block->version );
339
340
207
  byte_stream_copy_to_uint32_little_endian(
341
207
   ( (vshadow_store_block_header_t *) data )->record_type,
342
207
   store_block->record_type );
343
344
207
  byte_stream_copy_to_uint64_little_endian(
345
207
   ( (vshadow_store_block_header_t *) data )->relative_offset,
346
207
   safe_relative_offset );
347
348
207
  byte_stream_copy_to_uint64_little_endian(
349
207
   ( (vshadow_store_block_header_t *) data )->offset,
350
207
   safe_offset );
351
352
207
  byte_stream_copy_to_uint64_little_endian(
353
207
   ( (vshadow_store_block_header_t *) data )->next_offset,
354
207
   safe_next_offset );
355
356
#if defined( HAVE_DEBUG_OUTPUT )
357
  if( libcnotify_verbose != 0 )
358
  {
359
    if( libvshadow_debug_print_guid_value(
360
         function,
361
         "identifier\t\t\t",
362
         ( (vshadow_store_block_header_t *) data )->identifier,
363
         16,
364
         LIBFGUID_ENDIAN_LITTLE,
365
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
366
         error ) != 1 )
367
    {
368
      libcerror_error_set(
369
       error,
370
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
371
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
372
       "%s: unable to print GUID value.",
373
       function );
374
375
      return( -1 );
376
    }
377
    libcnotify_printf(
378
     "%s: version\t\t\t: %" PRIu32 "\n",
379
     function,
380
     store_block->version );
381
382
    libcnotify_printf(
383
     "%s: record type\t\t\t: %" PRIu32 "\n",
384
     function,
385
     store_block->record_type );
386
387
    libcnotify_printf(
388
     "%s: relative offset\t\t: 0x%08" PRIx64 "\n",
389
     function,
390
     store_block->relative_offset );
391
392
    libcnotify_printf(
393
     "%s: offset\t\t\t\t: 0x%08" PRIx64 "\n",
394
     function,
395
     store_block->offset );
396
397
    libcnotify_printf(
398
     "%s: next offset\t\t\t: 0x%08" PRIx64 "\n",
399
     function,
400
     store_block->next_offset );
401
402
    byte_stream_copy_to_uint64_little_endian(
403
     ( (vshadow_store_block_header_t *) data )->unknown1,
404
     value_64bit );
405
    libcnotify_printf(
406
     "%s: unknown1\t\t\t: %" PRIu64 "\n",
407
     function,
408
     value_64bit );
409
410
    libcnotify_printf(
411
     "%s: unknown2:\n",
412
     function );
413
    libcnotify_print_data(
414
     ( (vshadow_store_block_header_t *) data )->unknown2,
415
     72,
416
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
417
  }
418
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
419
420
207
  if( store_block->version != 1 )
421
45
  {
422
45
    libcerror_error_set(
423
45
     error,
424
45
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
425
45
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
426
45
     "%s: unsupported version: %" PRIu32 ".",
427
45
     function,
428
45
     store_block->version );
429
430
45
    return( -1 );
431
45
  }
432
162
  store_block->relative_offset = (off64_t) safe_relative_offset;
433
162
  store_block->offset          = (off64_t) safe_offset;
434
162
  store_block->next_offset     = (off64_t) safe_next_offset;
435
436
162
  return( 1 );
437
207
}
438