Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsxfs/libfsxfs/libfsxfs_file_system_block.c
Line
Count
Source
1
/*
2
 * File system block functions
3
 *
4
 * Copyright (C) 2020-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 "libfsxfs_file_system_block.h"
27
#include "libfsxfs_file_system_block_header.h"
28
#include "libfsxfs_io_handle.h"
29
#include "libfsxfs_libbfio.h"
30
#include "libfsxfs_libcerror.h"
31
#include "libfsxfs_libcnotify.h"
32
33
#include "fsxfs_file_system_block.h"
34
35
/* Creates a file system block
36
 * Make sure the value file_system_block is referencing, is set to NULL
37
 * Returns 1 if successful or -1 on error
38
 */
39
int libfsxfs_file_system_block_initialize(
40
     libfsxfs_file_system_block_t **file_system_block,
41
     size_t block_size,
42
     libcerror_error_t **error )
43
542
{
44
542
  static char *function = "libfsxfs_file_system_block_initialize";
45
46
542
  if( file_system_block == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid file system block.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
542
  if( *file_system_block != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid file system block value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
542
  if( ( block_size == 0 )
69
542
   || ( block_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
75
0
     "%s: invalid block size value out of bounds.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
542
  *file_system_block = memory_allocate_structure(
81
542
                        libfsxfs_file_system_block_t );
82
83
542
  if( *file_system_block == 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 file system block.",
90
0
     function );
91
92
0
    goto on_error;
93
0
  }
94
542
  if( memory_set(
95
542
       *file_system_block,
96
542
       0,
97
542
       sizeof( libfsxfs_file_system_block_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 file system block.",
104
0
     function );
105
106
0
    memory_free(
107
0
     *file_system_block );
108
109
0
    *file_system_block = NULL;
110
111
0
    return( -1 );
112
0
  }
113
542
  ( *file_system_block )->data = (uint8_t *) memory_allocate(
114
542
                                              sizeof( uint8_t ) * block_size );
115
116
542
  if( ( *file_system_block )->data == NULL )
117
0
  {
118
0
    libcerror_error_set(
119
0
     error,
120
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
121
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
122
0
     "%s: unable to create file system block data.",
123
0
     function );
124
125
0
    goto on_error;
126
0
  }
127
542
  ( *file_system_block )->data_size = block_size;
128
129
542
  return( 1 );
130
131
0
on_error:
132
0
  if( *file_system_block != NULL )
133
0
  {
134
0
    memory_free(
135
0
     *file_system_block );
136
137
0
    *file_system_block = NULL;
138
0
  }
139
0
  return( -1 );
140
542
}
141
142
/* Frees a file system block
143
 * Returns 1 if successful or -1 on error
144
 */
145
int libfsxfs_file_system_block_free(
146
     libfsxfs_file_system_block_t **file_system_block,
147
     libcerror_error_t **error )
148
542
{
149
542
  static char *function = "libfsxfs_file_system_block_free";
150
542
  int result            = 1;
151
152
542
  if( file_system_block == NULL )
153
0
  {
154
0
    libcerror_error_set(
155
0
     error,
156
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
157
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
158
0
     "%s: invalid file system block.",
159
0
     function );
160
161
0
    return( -1 );
162
0
  }
163
542
  if( *file_system_block != NULL )
164
542
  {
165
542
    if( ( *file_system_block )->header != NULL )
166
481
    {
167
481
      if( libfsxfs_file_system_block_header_free(
168
481
           &( ( *file_system_block )->header ),
169
481
           error ) != 1 )
170
0
      {
171
0
        libcerror_error_set(
172
0
         error,
173
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
175
0
         "%s: unable to free file system block header.",
176
0
         function );
177
178
0
        result = -1;
179
0
      }
180
481
    }
181
542
    memory_free(
182
542
     ( *file_system_block )->data );
183
184
542
    memory_free(
185
542
     *file_system_block );
186
187
542
    *file_system_block = NULL;
188
542
  }
189
542
  return( result );
190
542
}
191
192
/* Reads the file system block data
193
 * Returns 1 if successful or -1 on error
194
 */
195
int libfsxfs_file_system_block_read_data(
196
     libfsxfs_file_system_block_t *file_system_block,
197
     libfsxfs_io_handle_t *io_handle,
198
     const uint8_t *data,
199
     size_t data_size,
200
     libcerror_error_t **error )
201
481
{
202
481
  static char *function   = "libfsxfs_file_system_block_read_data";
203
481
  size_t header_data_size = 0;
204
205
481
  if( file_system_block == NULL )
206
0
  {
207
0
    libcerror_error_set(
208
0
     error,
209
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
210
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
211
0
     "%s: invalid file system block.",
212
0
     function );
213
214
0
    return( -1 );
215
0
  }
216
481
  if( file_system_block->header != NULL )
217
0
  {
218
0
    libcerror_error_set(
219
0
     error,
220
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
221
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
222
0
     "%s: invalid file system block - header value already set.",
223
0
     function );
224
225
0
    return( -1 );
226
0
  }
227
481
  if( io_handle == NULL )
228
0
  {
229
0
    libcerror_error_set(
230
0
     error,
231
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
233
0
     "%s: invalid IO handle.",
234
0
     function );
235
236
0
    return( -1 );
237
0
  }
238
481
  if( io_handle->format_version == 5 )
239
28
  {
240
28
    header_data_size = sizeof( fsxfs_file_system_block_header_v3_t );
241
28
  }
242
453
  else
243
453
  {
244
453
    header_data_size = sizeof( fsxfs_file_system_block_header_v1_t );
245
453
  }
246
481
  if( data == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252
0
     "%s: invalid data.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
481
  if( ( data_size < header_data_size )
258
481
   || ( data_size > (size_t) SSIZE_MAX ) )
259
0
  {
260
0
    libcerror_error_set(
261
0
     error,
262
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
263
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
264
0
     "%s: invalid data size value out of bounds.",
265
0
     function );
266
267
0
    return( -1 );
268
0
  }
269
481
  if( libfsxfs_file_system_block_header_initialize(
270
481
       &( file_system_block->header ),
271
481
       error ) != 1 )
272
0
  {
273
0
    libcerror_error_set(
274
0
     error,
275
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
276
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
277
0
     "%s: unable to create file system block header.",
278
0
     function );
279
280
0
    goto on_error;
281
0
  }
282
481
  if( libfsxfs_file_system_block_header_read_data(
283
481
       file_system_block->header,
284
481
       io_handle,
285
481
       data,
286
481
       header_data_size,
287
481
       error ) != 1 )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_IO,
292
0
     LIBCERROR_IO_ERROR_READ_FAILED,
293
0
     "%s: unable to read file system block header.",
294
0
     function );
295
296
0
    goto on_error;
297
0
  }
298
481
  return( 1 );
299
300
0
on_error:
301
0
  if( file_system_block->header != NULL )
302
0
  {
303
0
    libfsxfs_file_system_block_header_free(
304
0
     &( file_system_block->header ),
305
0
     NULL );
306
0
  }
307
0
  return( -1 );
308
481
}
309
310
/* Reads the file system block from a Basic File IO (bfio) handle
311
 * Returns 1 if successful or -1 on error
312
 */
313
int libfsxfs_file_system_block_read_file_io_handle(
314
     libfsxfs_file_system_block_t *file_system_block,
315
     libfsxfs_io_handle_t *io_handle,
316
     libbfio_handle_t *file_io_handle,
317
     off64_t file_offset,
318
     libcerror_error_t **error )
319
542
{
320
542
  static char *function = "libfsxfs_file_system_block_read_file_io_handle";
321
542
  ssize_t read_count    = 0;
322
323
542
  if( file_system_block == NULL )
324
0
  {
325
0
    libcerror_error_set(
326
0
     error,
327
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
328
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
329
0
     "%s: invalid file system block.",
330
0
     function );
331
332
0
    return( -1 );
333
0
  }
334
542
  if( file_system_block->header != NULL )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
340
0
     "%s: invalid file system block - header value already set.",
341
0
     function );
342
343
0
    return( -1 );
344
0
  }
345
#if defined( HAVE_DEBUG_OUTPUT )
346
  if( libcnotify_verbose != 0 )
347
  {
348
    libcnotify_printf(
349
     "%s: reading file system block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
350
     function,
351
     file_offset,
352
     file_offset );
353
  }
354
#endif
355
542
  read_count = libbfio_handle_read_buffer_at_offset(
356
542
                file_io_handle,
357
542
                file_system_block->data,
358
542
                file_system_block->data_size,
359
542
                file_offset,
360
542
                error );
361
362
542
  if( read_count != (ssize_t) file_system_block->data_size )
363
61
  {
364
61
    libcerror_error_set(
365
61
     error,
366
61
     LIBCERROR_ERROR_DOMAIN_IO,
367
61
     LIBCERROR_IO_ERROR_READ_FAILED,
368
61
     "%s: unable to read file system block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
369
61
     function,
370
61
     file_offset,
371
61
     file_offset );
372
373
61
    return( -1 );
374
61
  }
375
481
  if( libfsxfs_file_system_block_read_data(
376
481
       file_system_block,
377
481
       io_handle,
378
481
       file_system_block->data,
379
481
       file_system_block->data_size,
380
481
       error ) != 1 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_IO,
385
0
     LIBCERROR_IO_ERROR_READ_FAILED,
386
0
     "%s: unable to read file system block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
387
0
     function,
388
0
     file_offset,
389
0
     file_offset );
390
391
0
    return( -1 );
392
0
  }
393
481
  return( 1 );
394
481
}
395