Coverage Report

Created: 2025-06-13 07:22

/src/libfsapfs/libfsapfs/libfsapfs_container_data_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The container 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_definitions.h"
28
#include "libfsapfs_libbfio.h"
29
#include "libfsapfs_libcerror.h"
30
#include "libfsapfs_libfcache.h"
31
#include "libfsapfs_libfdata.h"
32
#include "libfsapfs_profiler.h"
33
#include "libfsapfs_unused.h"
34
#include "libfsapfs_container_data_handle.h"
35
36
/* Creates container data handle
37
 * Make sure the value container_data_handle is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsapfs_container_data_handle_initialize(
41
     libfsapfs_container_data_handle_t **container_data_handle,
42
     libfsapfs_io_handle_t *io_handle,
43
     libcerror_error_t **error )
44
14.3k
{
45
14.3k
  static char *function = "libfsapfs_container_data_handle_initialize";
46
47
14.3k
  if( container_data_handle == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid container data handle.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
14.3k
  if( *container_data_handle != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid container data handle value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
14.3k
  if( io_handle == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
75
0
     "%s: invalid IO handle.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
14.3k
  *container_data_handle = memory_allocate_structure(
81
14.3k
                            libfsapfs_container_data_handle_t );
82
83
14.3k
  if( *container_data_handle == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
88
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
89
0
     "%s: unable to create container data handle.",
90
0
     function );
91
92
0
    goto on_error;
93
0
  }
94
14.3k
  if( memory_set(
95
14.3k
       *container_data_handle,
96
14.3k
       0,
97
14.3k
       sizeof( libfsapfs_container_data_handle_t ) ) == NULL )
98
0
  {
99
0
    libcerror_error_set(
100
0
     error,
101
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
102
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
103
0
     "%s: unable to clear container data handle.",
104
0
     function );
105
106
0
    goto on_error;
107
0
  }
108
14.3k
  ( *container_data_handle )->io_handle = io_handle;
109
110
14.3k
  return( 1 );
111
112
0
on_error:
113
0
  if( *container_data_handle != NULL )
114
0
  {
115
0
    memory_free(
116
0
     *container_data_handle );
117
118
0
    *container_data_handle = NULL;
119
0
  }
120
0
  return( -1 );
121
14.3k
}
122
123
/* Frees container data handle
124
 * Returns 1 if successful or -1 on error
125
 */
126
int libfsapfs_container_data_handle_free(
127
     libfsapfs_container_data_handle_t **container_data_handle,
128
     libcerror_error_t **error )
129
14.3k
{
130
14.3k
  static char *function = "libfsapfs_container_data_handle_free";
131
132
14.3k
  if( container_data_handle == NULL )
133
0
  {
134
0
    libcerror_error_set(
135
0
     error,
136
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
137
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
138
0
     "%s: invalid container data handle.",
139
0
     function );
140
141
0
    return( -1 );
142
0
  }
143
14.3k
  if( *container_data_handle != NULL )
144
14.3k
  {
145
14.3k
    memory_free(
146
14.3k
     *container_data_handle );
147
148
14.3k
    *container_data_handle = NULL;
149
14.3k
  }
150
14.3k
  return( 1 );
151
14.3k
}
152
153
/* Reads a data block
154
 * Callback function for a data block vector
155
 * Returns 1 if successful or -1 on error
156
 */
157
int libfsapfs_container_data_handle_read_data_block(
158
     libfsapfs_container_data_handle_t *container_data_handle,
159
     libbfio_handle_t *file_io_handle,
160
     libfdata_vector_t *vector,
161
     libfcache_cache_t *cache,
162
     int element_index,
163
     int element_data_file_index LIBFSAPFS_ATTRIBUTE_UNUSED,
164
     off64_t element_data_offset,
165
     size64_t element_data_size,
166
     uint32_t element_data_flags LIBFSAPFS_ATTRIBUTE_UNUSED,
167
     uint8_t read_flags LIBFSAPFS_ATTRIBUTE_UNUSED,
168
     libcerror_error_t **error )
169
16.2k
{
170
16.2k
  libfsapfs_data_block_t *data_block = NULL;
171
16.2k
  static char *function              = "libfsapfs_container_data_handle_read_data_block";
172
173
#if defined( HAVE_PROFILER )
174
  int64_t profiler_start_timestamp   = 0;
175
#endif
176
177
16.2k
  LIBFSAPFS_UNREFERENCED_PARAMETER( element_data_file_index );
178
16.2k
  LIBFSAPFS_UNREFERENCED_PARAMETER( element_data_flags );
179
16.2k
  LIBFSAPFS_UNREFERENCED_PARAMETER( read_flags );
180
181
16.2k
  if( container_data_handle == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187
0
     "%s: invalid container data handle.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
16.2k
  if( container_data_handle->io_handle == NULL )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
198
0
     "%s: invalid container data handle - missing IO handle.",
199
0
     function );
200
201
0
    return( -1 );
202
0
  }
203
16.2k
  if( element_data_size > (size64_t) SSIZE_MAX )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
208
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
209
0
     "%s: invalid element data size value exceeds maximum.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
16.2k
  if( libfsapfs_data_block_initialize(
215
16.2k
       &data_block,
216
16.2k
       (size_t) element_data_size,
217
16.2k
       error ) != 1 )
218
0
  {
219
0
    libcerror_error_set(
220
0
     error,
221
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
223
0
     "%s: unable to create data block.",
224
0
     function );
225
226
0
    goto on_error;
227
0
  }
228
#if defined( HAVE_PROFILER )
229
  if( container_data_handle->io_handle->profiler != NULL )
230
  {
231
    if( libfsapfs_profiler_start_timing(
232
         container_data_handle->io_handle->profiler,
233
         &profiler_start_timestamp,
234
         error ) != 1 )
235
    {
236
      libcerror_error_set(
237
       error,
238
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
239
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
240
       "%s: unable to start timing.",
241
       function );
242
243
      goto on_error;
244
    }
245
  }
246
#endif /* defined( HAVE_PROFILER ) */
247
248
16.2k
  if( libfsapfs_data_block_read(
249
16.2k
       data_block,
250
16.2k
       container_data_handle->io_handle,
251
16.2k
       NULL,
252
16.2k
       file_io_handle,
253
16.2k
       element_data_offset,
254
16.2k
       0,
255
16.2k
       error ) != 1 )
256
252
  {
257
252
    libcerror_error_set(
258
252
     error,
259
252
     LIBCERROR_ERROR_DOMAIN_IO,
260
252
     LIBCERROR_IO_ERROR_READ_FAILED,
261
252
     "%s: unable to read data block.",
262
252
     function );
263
264
252
    goto on_error;
265
252
  }
266
#if defined( HAVE_PROFILER )
267
  if( container_data_handle->io_handle->profiler != NULL )
268
  {
269
    if( libfsapfs_profiler_stop_timing(
270
         container_data_handle->io_handle->profiler,
271
         profiler_start_timestamp,
272
         function,
273
         element_data_offset,
274
         element_data_size,
275
         error ) != 1 )
276
    {
277
      libcerror_error_set(
278
       error,
279
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
280
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
281
       "%s: unable to stop timing.",
282
       function );
283
284
      goto on_error;
285
    }
286
  }
287
#endif /* defined( HAVE_PROFILER ) */
288
289
15.9k
  if( libfdata_vector_set_element_value_by_index(
290
15.9k
       vector,
291
15.9k
       (intptr_t *) file_io_handle,
292
15.9k
       (libfdata_cache_t *) cache,
293
15.9k
       element_index,
294
15.9k
       (intptr_t *) data_block,
295
15.9k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_data_block_free,
296
15.9k
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
297
15.9k
       error ) != 1 )
298
0
  {
299
0
    libcerror_error_set(
300
0
     error,
301
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
302
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
303
0
     "%s: unable to set data block as element value.",
304
0
     function );
305
306
0
    goto on_error;
307
0
  }
308
15.9k
  return( 1 );
309
310
252
on_error:
311
252
  if( data_block != NULL )
312
252
  {
313
252
    libfsapfs_data_block_free(
314
252
     &data_block,
315
252
     NULL );
316
252
  }
317
252
  return( -1 );
318
15.9k
}
319