Coverage Report

Created: 2026-10-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsext/libfsext/libfsext_buffer_data_handle.c
Line
Count
Source
1
/*
2
 * The buffer data handle functions
3
 *
4
 * Copyright (C) 2010-2026, 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 "libfsext_buffer_data_handle.h"
27
#include "libfsext_definitions.h"
28
#include "libfsext_libcerror.h"
29
#include "libfsext_unused.h"
30
31
/* Creates a buffer data handle
32
 * Make sure the value data_handle is referencing, is set to NULL
33
 * Returns 1 if successful or -1 on error
34
 */
35
int libfsext_buffer_data_handle_initialize(
36
     libfsext_buffer_data_handle_t **data_handle,
37
     size64_t size,
38
     const uint8_t *data,
39
     size_t data_size,
40
     libcerror_error_t **error )
41
143
{
42
143
  static char *function = "libfsext_buffer_data_handle_initialize";
43
44
143
  if( data_handle == 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 data handle.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
143
  if( *data_handle != 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 data handle value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
143
  if( data_size > 0 )
67
137
  {
68
137
    if( data == NULL )
69
0
    {
70
0
      libcerror_error_set(
71
0
       error,
72
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74
0
       "%s: invalid data.",
75
0
       function );
76
77
0
      return( -1 );
78
0
    }
79
137
  }
80
143
  if( data_size > (size_t) SSIZE_MAX )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
85
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
86
0
     "%s: invalid data size value exceeds maximum.",
87
0
     function );
88
89
0
    return( -1 );
90
0
  }
91
143
  *data_handle = memory_allocate_structure(
92
143
                  libfsext_buffer_data_handle_t );
93
94
143
  if( *data_handle == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
100
0
     "%s: unable to create data handle.",
101
0
     function );
102
103
0
    goto on_error;
104
0
  }
105
143
  if( memory_set(
106
143
       *data_handle,
107
143
       0,
108
143
       sizeof( libfsext_buffer_data_handle_t ) ) == NULL )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
113
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
114
0
     "%s: unable to clear data handle.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
143
  ( *data_handle )->size      = size;
120
143
  ( *data_handle )->data      = data;
121
143
  ( *data_handle )->data_size = data_size;
122
123
143
  return( 1 );
124
125
0
on_error:
126
0
  if( *data_handle != NULL )
127
0
  {
128
0
    memory_free(
129
0
     *data_handle );
130
131
0
    *data_handle = NULL;
132
0
  }
133
0
  return( -1 );
134
143
}
135
136
/* Frees a buffer data handle
137
 * Returns 1 if successful or -1 on error
138
 */
139
int libfsext_buffer_data_handle_free(
140
     libfsext_buffer_data_handle_t **data_handle,
141
     libcerror_error_t **error )
142
143
{
143
143
  static char *function = "libfsext_buffer_data_handle_free";
144
145
143
  if( data_handle == NULL )
146
0
  {
147
0
    libcerror_error_set(
148
0
     error,
149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
151
0
     "%s: invalid data handle.",
152
0
     function );
153
154
0
    return( -1 );
155
0
  }
156
143
  if( *data_handle != NULL )
157
143
  {
158
143
    memory_free(
159
143
     *data_handle );
160
161
143
    *data_handle = NULL;
162
143
  }
163
143
  return( 1 );
164
143
}
165
166
/* Reads data from the current offset into a buffer
167
 * Callback for the data stream
168
 * Returns the number of bytes read or -1 on error
169
 */
170
ssize_t libfsext_buffer_data_handle_read_segment_data(
171
         libfsext_buffer_data_handle_t *data_handle,
172
         intptr_t *file_io_handle LIBFSEXT_ATTRIBUTE_UNUSED,
173
         int segment_index,
174
         int segment_file_index LIBFSEXT_ATTRIBUTE_UNUSED,
175
         uint8_t *segment_data,
176
         size_t segment_data_size,
177
         uint32_t segment_flags,
178
         uint8_t read_flags LIBFSEXT_ATTRIBUTE_UNUSED,
179
         libcerror_error_t **error )
180
75
{
181
75
  static char *function = "libfsext_buffer_data_handle_read_segment_data";
182
75
  size_t read_size      = 0;
183
184
75
  LIBFSEXT_UNREFERENCED_PARAMETER( file_io_handle )
185
75
  LIBFSEXT_UNREFERENCED_PARAMETER( segment_file_index )
186
75
  LIBFSEXT_UNREFERENCED_PARAMETER( segment_flags )
187
75
  LIBFSEXT_UNREFERENCED_PARAMETER( read_flags )
188
189
75
  if( data_handle == NULL )
190
0
  {
191
0
    libcerror_error_set(
192
0
     error,
193
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
194
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
195
0
     "%s: invalid data handle.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
75
  if( data_handle->current_offset < 0 )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
205
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
206
0
     "%s: invalid data handle - current offset value out of bounds.",
207
0
     function );
208
209
0
    return( -1 );
210
0
  }
211
75
  if( segment_index > 1 )
212
0
  {
213
0
    libcerror_error_set(
214
0
     error,
215
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
216
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
217
0
     "%s: invalid segment index value out of bounds.",
218
0
     function );
219
220
0
    return( -1 );
221
0
  }
222
75
  if( segment_data == NULL )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
228
0
     "%s: invalid segment data.",
229
0
     function );
230
231
0
    return( -1 );
232
0
  }
233
75
  if( segment_data_size > (size_t) SSIZE_MAX )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
238
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
239
0
     "%s: invalid segment data size value exceeds maximum.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
75
  if( ( segment_flags & LIBFSEXT_EXTENT_FLAG_IS_SPARSE ) != 0 )
245
37
  {
246
37
    if( data_handle->current_offset >= (off64_t) data_handle->size )
247
0
    {
248
0
      return( 0 );
249
0
    }
250
37
    read_size = data_handle->size - (size_t) data_handle->current_offset;
251
252
37
    if( read_size > segment_data_size )
253
37
    {
254
37
      read_size = segment_data_size;
255
37
    }
256
37
    if( memory_set(
257
37
         segment_data,
258
37
         0,
259
37
         read_size ) == NULL )
260
0
    {
261
0
      libcerror_error_set(
262
0
       error,
263
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
264
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
265
0
       "%s: unable to clear segment data.",
266
0
       function );
267
268
0
      return( -1 );
269
0
    }
270
37
  }
271
38
  else
272
38
  {
273
38
    if( data_handle->current_offset >= (off64_t) data_handle->data_size )
274
0
    {
275
0
      return( 0 );
276
0
    }
277
38
    read_size = data_handle->data_size - (size_t) data_handle->current_offset;
278
279
38
    if( read_size > segment_data_size )
280
0
    {
281
0
      read_size = segment_data_size;
282
0
    }
283
38
    if( memory_copy(
284
38
         segment_data,
285
38
         &( data_handle->data[ data_handle->current_offset ] ),
286
38
         read_size ) == NULL )
287
0
    {
288
0
      libcerror_error_set(
289
0
       error,
290
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
291
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
292
0
       "%s: unable to copy data.",
293
0
       function );
294
295
0
      return( -1 );
296
0
    }
297
38
  }
298
75
  data_handle->current_offset += read_size;
299
300
75
  return( (ssize_t) read_size );
301
75
}
302
303
/* Seeks a certain offset of the data
304
 * Callback for the data stream
305
 * Returns the offset if seek is successful or -1 on error
306
 */
307
off64_t libfsext_buffer_data_handle_seek_segment_offset(
308
         libfsext_buffer_data_handle_t *data_handle,
309
         intptr_t *file_io_handle LIBFSEXT_ATTRIBUTE_UNUSED,
310
         int segment_index,
311
         int segment_file_index LIBFSEXT_ATTRIBUTE_UNUSED,
312
         off64_t segment_offset,
313
         libcerror_error_t **error )
314
75
{
315
75
  static char *function = "libfsext_buffer_data_handle_seek_segment_offset";
316
317
75
  LIBFSEXT_UNREFERENCED_PARAMETER( file_io_handle )
318
75
  LIBFSEXT_UNREFERENCED_PARAMETER( segment_file_index )
319
320
75
  if( data_handle == NULL )
321
0
  {
322
0
    libcerror_error_set(
323
0
     error,
324
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
325
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
326
0
     "%s: invalid data handle.",
327
0
     function );
328
329
0
    return( -1 );
330
0
  }
331
75
  if( segment_index > 1 )
332
0
  {
333
0
    libcerror_error_set(
334
0
     error,
335
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
336
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
337
0
     "%s: invalid segment index value out of bounds.",
338
0
     function );
339
340
0
    return( -1 );
341
0
  }
342
75
  if( segment_offset < 0 )
343
0
  {
344
0
    libcerror_error_set(
345
0
     error,
346
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
347
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
348
0
     "%s: invalid segment offset value out of bounds.",
349
0
     function );
350
351
0
    return( -1 );
352
0
  }
353
75
  data_handle->current_offset = segment_offset;
354
355
75
  return( segment_offset );
356
75
}
357