Coverage Report

Created: 2026-01-13 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsext/libfsext/libfsext_extent_index.c
Line
Count
Source
1
/*
2
 * Extent index functions
3
 *
4
 * Copyright (C) 2010-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 "libfsext_extent_index.h"
28
#include "libfsext_libcerror.h"
29
#include "libfsext_libcnotify.h"
30
31
#include "fsext_extents.h"
32
33
/* Creates an extent index
34
 * Make sure the value extent_index is referencing, is set to NULL
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libfsext_extent_index_initialize(
38
     libfsext_extent_index_t **extent_index,
39
     libcerror_error_t **error )
40
6.97k
{
41
6.97k
  static char *function = "libfsext_extent_index_initialize";
42
43
6.97k
  if( extent_index == NULL )
44
0
  {
45
0
    libcerror_error_set(
46
0
     error,
47
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49
0
     "%s: invalid extent index.",
50
0
     function );
51
52
0
    return( -1 );
53
0
  }
54
6.97k
  if( *extent_index != NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
59
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
60
0
     "%s: invalid extent index value already set.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
6.97k
  *extent_index = memory_allocate_structure(
66
6.97k
                   libfsext_extent_index_t );
67
68
6.97k
  if( *extent_index == NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
73
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
74
0
     "%s: unable to create extent index.",
75
0
     function );
76
77
0
    goto on_error;
78
0
  }
79
6.97k
  if( memory_set(
80
6.97k
       *extent_index,
81
6.97k
       0,
82
6.97k
       sizeof( libfsext_extent_index_t ) ) == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
88
0
     "%s: unable to clear extent index.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
6.97k
  return( 1 );
94
95
0
on_error:
96
0
  if( *extent_index != NULL )
97
0
  {
98
0
    memory_free(
99
0
     *extent_index );
100
101
0
    *extent_index = NULL;
102
0
  }
103
0
  return( -1 );
104
6.97k
}
105
106
/* Frees an extent index
107
 * Returns 1 if successful or -1 on error
108
 */
109
int libfsext_extent_index_free(
110
     libfsext_extent_index_t **extent_index,
111
     libcerror_error_t **error )
112
6.97k
{
113
6.97k
  static char *function = "libfsext_extent_index_free";
114
115
6.97k
  if( extent_index == NULL )
116
0
  {
117
0
    libcerror_error_set(
118
0
     error,
119
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
120
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
121
0
     "%s: invalid extent index.",
122
0
     function );
123
124
0
    return( -1 );
125
0
  }
126
6.97k
  if( *extent_index != NULL )
127
6.97k
  {
128
6.97k
    memory_free(
129
6.97k
     *extent_index );
130
131
6.97k
    *extent_index = NULL;
132
6.97k
  }
133
6.97k
  return( 1 );
134
6.97k
}
135
136
/* Reads the extent index data
137
 * Returns 1 if successful or -1 on error
138
 */
139
int libfsext_extent_index_read_data(
140
     libfsext_extent_index_t *extent_index,
141
     const uint8_t *data,
142
     size_t data_size,
143
     libcerror_error_t **error )
144
6.97k
{
145
6.97k
  static char *function                = "libfsext_extent_index_read_data";
146
6.97k
  uint32_t physical_block_number_lower = 0;
147
6.97k
  uint16_t physical_block_number_upper = 0;
148
149
#if defined( HAVE_DEBUG_OUTPUT )
150
  uint16_t value_16bit                 = 0;
151
#endif
152
153
6.97k
  if( extent_index == 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 extent index.",
160
0
     function );
161
162
0
    return( -1 );
163
0
  }
164
6.97k
  if( data == NULL )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170
0
     "%s: invalid data.",
171
0
     function );
172
173
0
    return( -1 );
174
0
  }
175
6.97k
  if( ( data_size < sizeof( fsext_extent_index_ext4_t ) )
176
6.97k
   || ( data_size > (size_t) SSIZE_MAX ) )
177
0
  {
178
0
    libcerror_error_set(
179
0
     error,
180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
181
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
182
0
     "%s: invalid data size value out of bounds.",
183
0
     function );
184
185
0
    return( -1 );
186
0
  }
187
#if defined( HAVE_DEBUG_OUTPUT )
188
  if( libcnotify_verbose != 0 )
189
  {
190
    libcnotify_printf(
191
     "%s: extent index data:\n",
192
     function );
193
    libcnotify_print_data(
194
     data,
195
     data_size,
196
     0 );
197
  }
198
#endif
199
6.97k
  byte_stream_copy_to_uint32_little_endian(
200
6.97k
   ( (fsext_extent_index_ext4_t *) data )->logical_block_number,
201
6.97k
   extent_index->logical_block_number );
202
203
6.97k
  byte_stream_copy_to_uint32_little_endian(
204
6.97k
   ( (fsext_extent_index_ext4_t *) data )->physical_block_number_lower,
205
6.97k
   physical_block_number_lower );
206
207
6.97k
  byte_stream_copy_to_uint16_little_endian(
208
6.97k
   ( (fsext_extent_index_ext4_t *) data )->physical_block_number_upper,
209
6.97k
   physical_block_number_upper );
210
211
#if defined( HAVE_DEBUG_OUTPUT )
212
  if( libcnotify_verbose != 0 )
213
  {
214
    libcnotify_printf(
215
     "%s: logical block number\t\t\t: %" PRIu32 "\n",
216
     function,
217
     extent_index->logical_block_number );
218
219
    libcnotify_printf(
220
     "%s: physical block number (lower)\t\t: %" PRIu32 "\n",
221
     function,
222
     physical_block_number_lower );
223
224
    libcnotify_printf(
225
     "%s: physical block number (upper)\t\t: %" PRIu16 "\n",
226
     function,
227
     physical_block_number_upper );
228
229
    byte_stream_copy_to_uint16_little_endian(
230
     ( (fsext_extent_index_ext4_t *) data )->unknown1,
231
     value_16bit );
232
    libcnotify_printf(
233
     "%s: unknown1\t\t\t\t: 0x%04" PRIx16 "\n",
234
     function,
235
     value_16bit );
236
  }
237
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
238
239
6.97k
  extent_index->physical_block_number = ( (uint64_t) physical_block_number_upper << 32 ) | physical_block_number_lower;
240
241
#if defined( HAVE_DEBUG_OUTPUT )
242
  if( libcnotify_verbose != 0 )
243
  {
244
    libcnotify_printf(
245
     "%s: physical block number\t\t\t: %" PRIu32 "\n",
246
     function,
247
     extent_index->physical_block_number );
248
249
    libcnotify_printf(
250
     "\n" );
251
  }
252
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
253
254
6.97k
  return( 1 );
255
6.97k
}
256