Coverage Report

Created: 2024-10-02 06:58

/src/libfsapfs/libfsapfs/libfsapfs_data_block_data_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The data block data handle functions
3
 *
4
 * Copyright (C) 2018-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 "libfsapfs_data_block.h"
27
#include "libfsapfs_data_block_data_handle.h"
28
#include "libfsapfs_data_block_vector.h"
29
#include "libfsapfs_definitions.h"
30
#include "libfsapfs_encryption_context.h"
31
#include "libfsapfs_file_system_data_handle.h"
32
#include "libfsapfs_libbfio.h"
33
#include "libfsapfs_libcdata.h"
34
#include "libfsapfs_libcerror.h"
35
#include "libfsapfs_libfcache.h"
36
#include "libfsapfs_libfdata.h"
37
#include "libfsapfs_unused.h"
38
39
/* Creates a data block data handle
40
 * Make sure the value data_handle is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfsapfs_data_block_data_handle_initialize(
44
     libfsapfs_data_block_data_handle_t **data_handle,
45
     libfsapfs_io_handle_t *io_handle,
46
     libfsapfs_encryption_context_t *encryption_context,
47
     libcdata_array_t *file_extents,
48
     uint8_t is_sparse,
49
     libcerror_error_t **error )
50
455
{
51
455
  static char *function = "libfsapfs_data_block_data_handle_initialize";
52
53
455
  if( data_handle == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid data handle.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
455
  if( *data_handle != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid data handle value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
455
  if( io_handle == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
80
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
81
0
     "%s: invalid IO handle.",
82
0
     function );
83
84
0
    return( -1 );
85
0
  }
86
455
  *data_handle = memory_allocate_structure(
87
455
                  libfsapfs_data_block_data_handle_t );
88
89
455
  if( *data_handle == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
95
0
     "%s: unable to create data handle.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
455
  if( memory_set(
101
455
       *data_handle,
102
455
       0,
103
455
       sizeof( libfsapfs_data_block_data_handle_t ) ) == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
108
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
109
0
     "%s: unable to clear data handle.",
110
0
     function );
111
112
0
    memory_free(
113
0
     *data_handle );
114
115
0
    *data_handle = NULL;
116
117
0
    return( -1 );
118
0
  }
119
455
  if( libfsapfs_file_system_data_handle_initialize(
120
455
       &( ( *data_handle )->file_system_data_handle ),
121
455
       io_handle,
122
455
       encryption_context,
123
455
       file_extents,
124
455
       error ) != 1 )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
129
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
130
0
     "%s: unable to create file system data handle.",
131
0
     function );
132
133
0
    goto on_error;
134
0
  }
135
455
  if( libfsapfs_data_block_vector_initialize(
136
455
       &( ( *data_handle )->data_block_vector ),
137
455
       io_handle,
138
455
       ( *data_handle )->file_system_data_handle,
139
455
       file_extents,
140
455
       is_sparse,
141
455
       error ) != 1 )
142
185
  {
143
185
    libcerror_error_set(
144
185
     error,
145
185
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
146
185
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
147
185
     "%s: unable to create data block vector.",
148
185
     function );
149
150
185
    goto on_error;
151
185
  }
152
270
  if( libfdata_vector_get_size(
153
270
       ( *data_handle )->data_block_vector,
154
270
       &( ( *data_handle )->data_size ),
155
270
       error ) != 1 )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
160
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
161
0
     "%s: unable to retrieve size of data block vector.",
162
0
     function );
163
164
0
    goto on_error;
165
0
  }
166
270
  if( libfcache_cache_initialize(
167
270
       &( ( *data_handle )->data_block_cache ),
168
270
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
169
270
       error ) != 1 )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
175
0
     "%s: unable to create data block cache.",
176
0
     function );
177
178
0
    goto on_error;
179
0
  }
180
270
  return( 1 );
181
182
185
on_error:
183
185
  if( *data_handle != NULL )
184
185
  {
185
185
    if( ( *data_handle )->data_block_vector != NULL )
186
0
    {
187
0
      libfdata_vector_free(
188
0
       &( ( *data_handle )->data_block_vector ),
189
0
       NULL );
190
0
    }
191
185
    if( ( *data_handle )->file_system_data_handle != NULL )
192
185
    {
193
185
      libfsapfs_file_system_data_handle_free(
194
185
       &( ( *data_handle )->file_system_data_handle ),
195
185
       NULL );
196
185
    }
197
185
    memory_free(
198
185
     *data_handle );
199
200
185
    *data_handle = NULL;
201
185
  }
202
185
  return( -1 );
203
270
}
204
205
/* Frees a data block data handle
206
 * Returns 1 if successful or -1 on error
207
 */
208
int libfsapfs_data_block_data_handle_free(
209
     libfsapfs_data_block_data_handle_t **data_handle,
210
     libcerror_error_t **error )
211
270
{
212
270
  static char *function = "libfsapfs_data_block_data_handle_free";
213
270
  int result            = 1;
214
215
270
  if( data_handle == NULL )
216
0
  {
217
0
    libcerror_error_set(
218
0
     error,
219
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
221
0
     "%s: invalid data handle.",
222
0
     function );
223
224
0
    return( -1 );
225
0
  }
226
270
  if( *data_handle != NULL )
227
270
  {
228
270
    if( libfcache_cache_free(
229
270
         &( ( *data_handle )->data_block_cache ),
230
270
         error ) != 1 )
231
0
    {
232
0
      libcerror_error_set(
233
0
       error,
234
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
235
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
236
0
       "%s: unable to free data block cache.",
237
0
       function );
238
239
0
      result = -1;
240
0
    }
241
270
    if( libfdata_vector_free(
242
270
         &( ( *data_handle )->data_block_vector ),
243
270
         error ) != 1 )
244
0
    {
245
0
      libcerror_error_set(
246
0
       error,
247
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
249
0
       "%s: unable to free data block vector.",
250
0
       function );
251
252
0
      result = -1;
253
0
    }
254
270
    if( libfsapfs_file_system_data_handle_free(
255
270
         &( ( *data_handle )->file_system_data_handle ),
256
270
         error ) != 1 )
257
0
    {
258
0
      libcerror_error_set(
259
0
       error,
260
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
262
0
       "%s: unable to free file system data handle.",
263
0
       function );
264
265
0
      result = -1;
266
0
    }
267
270
    memory_free(
268
270
     *data_handle );
269
270
270
    *data_handle = NULL;
271
270
  }
272
270
  return( result );
273
270
}
274
275
/* Reads data from the current offset into a buffer
276
 * Callback for the data stream
277
 * Returns the number of bytes read or -1 on error
278
 */
279
ssize_t libfsapfs_data_block_data_handle_read_segment_data(
280
         libfsapfs_data_block_data_handle_t *data_handle,
281
         libbfio_handle_t *file_io_handle,
282
         int segment_index,
283
         int segment_file_index LIBFSAPFS_ATTRIBUTE_UNUSED,
284
         uint8_t *segment_data,
285
         size_t segment_data_size,
286
         uint32_t segment_flags LIBFSAPFS_ATTRIBUTE_UNUSED,
287
         uint8_t read_flags LIBFSAPFS_ATTRIBUTE_UNUSED,
288
         libcerror_error_t **error )
289
0
{
290
0
  libfsapfs_data_block_t *data_block = NULL;
291
0
  static char *function              = "libfsapfs_data_block_data_handle_read_segment_data";
292
0
  size_t read_size                   = 0;
293
0
  size_t segment_data_offset         = 0;
294
0
  off64_t data_block_offset          = 0;
295
296
0
  LIBFSAPFS_UNREFERENCED_PARAMETER( segment_file_index )
297
0
  LIBFSAPFS_UNREFERENCED_PARAMETER( segment_flags )
298
0
  LIBFSAPFS_UNREFERENCED_PARAMETER( read_flags )
299
300
0
  if( data_handle == NULL )
301
0
  {
302
0
    libcerror_error_set(
303
0
     error,
304
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
305
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
306
0
     "%s: invalid data handle.",
307
0
     function );
308
309
0
    return( -1 );
310
0
  }
311
0
  if( data_handle->current_offset < 0 )
312
0
  {
313
0
    libcerror_error_set(
314
0
     error,
315
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
316
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
317
0
     "%s: invalid data handle - current offset value out of bounds.",
318
0
     function );
319
320
0
    return( -1 );
321
0
  }
322
0
  if( segment_index < 0 )
323
0
  {
324
0
    libcerror_error_set(
325
0
     error,
326
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
327
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
328
0
     "%s: invalid segment index value out of bounds.",
329
0
     function );
330
331
0
    return( -1 );
332
0
  }
333
0
  if( segment_data == NULL )
334
0
  {
335
0
    libcerror_error_set(
336
0
     error,
337
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
338
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
339
0
     "%s: invalid segment data.",
340
0
     function );
341
342
0
    return( -1 );
343
0
  }
344
0
  if( segment_data_size > (size_t) SSIZE_MAX )
345
0
  {
346
0
    libcerror_error_set(
347
0
     error,
348
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
349
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
350
0
     "%s: invalid segment data size value exceeds maximum.",
351
0
     function );
352
353
0
    return( -1 );
354
0
  }
355
0
  if( (size64_t) data_handle->current_offset >= data_handle->data_size )
356
0
  {
357
0
    return( 0 );
358
0
  }
359
0
  while( segment_data_size > 0 )
360
0
  {
361
0
    if( libfdata_vector_get_element_value_at_offset(
362
0
         data_handle->data_block_vector,
363
0
         (intptr_t *) file_io_handle,
364
0
         (libfdata_cache_t *) data_handle->data_block_cache,
365
0
         data_handle->current_offset,
366
0
         &data_block_offset,
367
0
         (intptr_t **) &data_block,
368
0
         0,
369
0
         error ) != 1 )
370
0
    {
371
0
      libcerror_error_set(
372
0
       error,
373
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
374
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
375
0
       "%s: unable to retrieve data block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
376
0
       function,
377
0
       data_handle->current_offset,
378
0
       data_handle->current_offset );
379
380
0
      return( -1 );
381
0
    }
382
0
    if( data_block == NULL )
383
0
    {
384
0
      libcerror_error_set(
385
0
       error,
386
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
387
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
388
0
       "%s: invalid data block.",
389
0
       function );
390
391
0
      return( -1 );
392
0
    }
393
0
    if( data_block->data == NULL )
394
0
    {
395
0
      libcerror_error_set(
396
0
       error,
397
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
399
0
       "%s: invalid data block - missing data.",
400
0
       function );
401
402
0
      return( -1 );
403
0
    }
404
0
    if( ( data_block_offset < 0 )
405
0
     || ( (size64_t) data_block_offset >= data_block->data_size ) )
406
0
    {
407
0
      libcerror_error_set(
408
0
       error,
409
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
411
0
       "%s: invalid data block offset value out of bounds.",
412
0
       function );
413
414
0
      return( -1 );
415
0
    }
416
0
    read_size = (size_t) ( data_block->data_size - data_block_offset );
417
418
0
    if( read_size > segment_data_size )
419
0
    {
420
0
      read_size = segment_data_size;
421
0
    }
422
0
    if( memory_copy(
423
0
         &( segment_data[ segment_data_offset ] ),
424
0
         &( data_block->data[ data_block_offset ] ),
425
0
         read_size ) == NULL )
426
0
    {
427
0
      libcerror_error_set(
428
0
       error,
429
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
430
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
431
0
       "%s: unable to copy data block data.",
432
0
       function );
433
434
0
      return( -1 );
435
0
    }
436
0
    segment_data_offset += read_size;
437
0
    segment_data_size   -= read_size;
438
439
0
    data_handle->current_offset += read_size;
440
441
0
    if( (size64_t) data_handle->current_offset >= data_handle->data_size )
442
0
    {
443
0
      break;
444
0
    }
445
0
  }
446
0
  return( (ssize_t) segment_data_offset );
447
0
}
448
449
/* Seeks a certain offset of the data
450
 * Callback for the data stream
451
 * Returns the offset if seek is successful or -1 on error
452
 */
453
off64_t libfsapfs_data_block_data_handle_seek_segment_offset(
454
         libfsapfs_data_block_data_handle_t *data_handle,
455
         intptr_t *file_io_handle LIBFSAPFS_ATTRIBUTE_UNUSED,
456
         int segment_index,
457
         int segment_file_index LIBFSAPFS_ATTRIBUTE_UNUSED,
458
         off64_t segment_offset,
459
         libcerror_error_t **error )
460
0
{
461
0
  static char *function = "libfsapfs_data_block_data_handle_seek_segment_offset";
462
463
0
  LIBFSAPFS_UNREFERENCED_PARAMETER( file_io_handle )
464
0
  LIBFSAPFS_UNREFERENCED_PARAMETER( segment_file_index )
465
466
0
  if( data_handle == NULL )
467
0
  {
468
0
    libcerror_error_set(
469
0
     error,
470
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
471
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
472
0
     "%s: invalid data handle.",
473
0
     function );
474
475
0
    return( -1 );
476
0
  }
477
0
  if( segment_index < 0 )
478
0
  {
479
0
    libcerror_error_set(
480
0
     error,
481
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
482
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
483
0
     "%s: invalid segment index value out of bounds.",
484
0
     function );
485
486
0
    return( -1 );
487
0
  }
488
0
  if( segment_offset < 0 )
489
0
  {
490
0
    libcerror_error_set(
491
0
     error,
492
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
493
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
494
0
     "%s: invalid segment offset value out of bounds.",
495
0
     function );
496
497
0
    return( -1 );
498
0
  }
499
0
  data_handle->current_offset = segment_offset;
500
501
0
  return( segment_offset );
502
0
}
503