Coverage Report

Created: 2026-02-19 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsxfs/libfsxfs/libfsxfs_extent_list.c
Line
Count
Source
1
/*
2
 * Extent list functions
3
 *
4
 * Copyright (C) 2020-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 <memory.h>
24
#include <types.h>
25
26
#include "libfsxfs_definitions.h"
27
#include "libfsxfs_extent.h"
28
#include "libfsxfs_extent_list.h"
29
#include "libfsxfs_extents.h"
30
#include "libfsxfs_libcdata.h"
31
#include "libfsxfs_libcerror.h"
32
#include "libfsxfs_libcnotify.h"
33
34
/* Reads the extent list data
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libfsxfs_extent_list_read_data(
38
     libcdata_array_t *extents_array,
39
     uint64_t number_of_blocks,
40
     uint32_t number_of_extents,
41
     const uint8_t *data,
42
     size_t data_size,
43
     uint8_t add_sparse_extents,
44
     libcerror_error_t **error )
45
1.40k
{
46
1.40k
  libfsxfs_extent_t *last_extent   = NULL;
47
1.40k
  libfsxfs_extent_t *sparse_extent = NULL;
48
1.40k
  static char *function            = "libfsxfs_extent_list_read_data";
49
1.40k
  uint64_t logical_block_number    = 0;
50
1.40k
  int entry_index                  = 0;
51
52
1.40k
  if( libfsxfs_extents_read_data(
53
1.40k
       extents_array,
54
1.40k
       number_of_extents,
55
1.40k
       data,
56
1.40k
       data_size,
57
1.40k
       add_sparse_extents,
58
1.40k
       error ) != 1 )
59
63
  {
60
63
    libcerror_error_set(
61
63
     error,
62
63
     LIBCERROR_ERROR_DOMAIN_IO,
63
63
     LIBCERROR_IO_ERROR_READ_FAILED,
64
63
     "%s: unable to read data extents.",
65
63
     function );
66
67
63
    goto on_error;
68
63
  }
69
1.34k
  if( libfsxfs_extents_get_last_extent(
70
1.34k
       extents_array,
71
1.34k
       &last_extent,
72
1.34k
       error ) != 1 )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
77
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
78
0
     "%s: unable to retrieve last extent.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
1.34k
  if( last_extent != NULL )
84
1.30k
  {
85
1.30k
    logical_block_number = last_extent->logical_block_number + last_extent->number_of_blocks;
86
1.30k
  }
87
1.34k
  if( ( add_sparse_extents != 0 )
88
464
   && ( logical_block_number < number_of_blocks ) )
89
135
  {
90
135
    if( ( last_extent == NULL )
91
99
     || ( ( last_extent->range_flags & LIBFSXFS_EXTENT_FLAG_IS_SPARSE ) == 0 ) )
92
110
    {
93
110
      if( libfsxfs_extent_initialize(
94
110
           &sparse_extent,
95
110
           error ) != 1 )
96
0
      {
97
0
        libcerror_error_set(
98
0
         error,
99
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
100
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
101
0
         "%s: unable to create sparse extent.",
102
0
         function );
103
104
0
        goto on_error;
105
0
      }
106
110
      sparse_extent->logical_block_number = logical_block_number;
107
110
      sparse_extent->range_flags          = LIBFSXFS_EXTENT_FLAG_IS_SPARSE;
108
109
110
      if( libcdata_array_append_entry(
110
110
           extents_array,
111
110
           &entry_index,
112
110
           (intptr_t *) sparse_extent,
113
110
           error ) != 1 )
114
0
      {
115
0
        libcerror_error_set(
116
0
         error,
117
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
118
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
119
0
         "%s: unable to append sparse extent to array.",
120
0
         function );
121
122
0
        goto on_error;
123
0
      }
124
110
      last_extent   = sparse_extent;
125
110
      sparse_extent = NULL;
126
110
    }
127
135
    last_extent->number_of_blocks += number_of_blocks - logical_block_number;
128
129
#if defined( HAVE_DEBUG_OUTPUT )
130
    if( libcnotify_verbose != 0 )
131
    {
132
      libcnotify_printf(
133
       "%s: logical block number\t\t\t: %" PRIu64 "\n",
134
       function,
135
       last_extent->logical_block_number );
136
137
      libcnotify_printf(
138
       "%s: physical block number\t\t\t: %" PRIu64 "\n",
139
       function,
140
       last_extent->physical_block_number );
141
142
      libcnotify_printf(
143
       "%s: number of blocks\t\t\t: %" PRIu64 "\n",
144
       function,
145
       last_extent->number_of_blocks );
146
147
      libcnotify_printf(
148
       "\n" );
149
    }
150
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
151
135
  }
152
1.34k
  return( 1 );
153
154
63
on_error:
155
63
  if( sparse_extent != NULL )
156
0
  {
157
0
    libfsxfs_extent_free(
158
0
     &sparse_extent,
159
0
     NULL );
160
0
  }
161
63
  libcdata_array_empty(
162
63
   extents_array,
163
63
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsxfs_extent_free,
164
63
   NULL );
165
166
63
  return( -1 );
167
1.34k
}
168