Coverage Report

Created: 2025-08-28 07:10

/src/libfsntfs/libfsntfs/libfsntfs_compression_unit_descriptor.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Compression unit descriptor functions
3
 *
4
 * Copyright (C) 2010-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 "libfsntfs_cluster_block_data.h"
27
#include "libfsntfs_compression_unit_descriptor.h"
28
#include "libfsntfs_libcerror.h"
29
#include "libfsntfs_libcnotify.h"
30
#include "libfsntfs_libfdata.h"
31
32
/* Creates a compression unit descriptor
33
 * Make sure the value compression_unit_descriptor is referencing, is set to NULL
34
 * Returns 1 if successful or -1 on error
35
 */
36
int libfsntfs_compression_unit_descriptor_initialize(
37
     libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor,
38
     libcerror_error_t **error )
39
121k
{
40
121k
  static char *function = "libfsntfs_compression_unit_descriptor_initialize";
41
42
121k
  if( compression_unit_descriptor == NULL )
43
0
  {
44
0
    libcerror_error_set(
45
0
     error,
46
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
47
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
48
0
     "%s: invalid compression unit descriptor.",
49
0
     function );
50
51
0
    return( -1 );
52
0
  }
53
121k
  if( *compression_unit_descriptor != NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
58
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
59
0
     "%s: invalid compression unit descriptor value already set.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
121k
  *compression_unit_descriptor = memory_allocate_structure(
65
121k
                                  libfsntfs_compression_unit_descriptor_t );
66
67
121k
  if( *compression_unit_descriptor == NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
72
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
73
0
     "%s: unable to create compression unit descriptor.",
74
0
     function );
75
76
0
    goto on_error;
77
0
  }
78
121k
  if( memory_set(
79
121k
       *compression_unit_descriptor,
80
121k
       0,
81
121k
       sizeof( libfsntfs_compression_unit_descriptor_t ) ) == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
87
0
     "%s: unable to clear compression unit descriptor.",
88
0
     function );
89
90
0
    memory_free(
91
0
     *compression_unit_descriptor );
92
93
0
    *compression_unit_descriptor = NULL;
94
95
0
    return( -1 );
96
0
  }
97
121k
  if( libfdata_stream_initialize(
98
121k
       &( ( *compression_unit_descriptor )->data_stream ),
99
121k
       NULL,
100
121k
       NULL,
101
121k
       NULL,
102
121k
       NULL,
103
121k
       (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_read_segment_data,
104
121k
       NULL,
105
121k
       (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_seek_segment_offset,
106
121k
       0,
107
121k
       error ) != 1 )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
112
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
113
0
     "%s: unable to create data stream.",
114
0
     function );
115
116
0
    goto on_error;
117
0
  }
118
121k
  return( 1 );
119
120
0
on_error:
121
0
  if( *compression_unit_descriptor != NULL )
122
0
  {
123
0
    memory_free(
124
0
     *compression_unit_descriptor );
125
126
0
    *compression_unit_descriptor = NULL;
127
0
  }
128
0
  return( -1 );
129
121k
}
130
131
/* Frees a compression unit descriptor
132
 * Returns 1 if successful or -1 on error
133
 */
134
int libfsntfs_compression_unit_descriptor_free(
135
     libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor,
136
     libcerror_error_t **error )
137
121k
{
138
121k
  static char *function = "libfsntfs_compression_unit_descriptor_free";
139
121k
  int result            = 1;
140
141
121k
  if( compression_unit_descriptor == NULL )
142
0
  {
143
0
    libcerror_error_set(
144
0
     error,
145
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
146
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
147
0
     "%s: invalid compression unit descriptor.",
148
0
     function );
149
150
0
    return( -1 );
151
0
  }
152
121k
  if( *compression_unit_descriptor != NULL )
153
121k
  {
154
121k
    if( libfdata_stream_free(
155
121k
         &( ( *compression_unit_descriptor )->data_stream ),
156
121k
         error ) != 1 )
157
0
    {
158
0
      libcerror_error_set(
159
0
       error,
160
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
161
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
162
0
       "%s: unable to free data stream.",
163
0
       function );
164
165
0
      result = -1;
166
0
    }
167
121k
    memory_free(
168
121k
     *compression_unit_descriptor );
169
170
121k
    *compression_unit_descriptor = NULL;
171
121k
  }
172
121k
  return( result );
173
121k
}
174
175
/* Appends a data segment
176
 * Returns 1 if successful or -1 on error
177
 */
178
int libfsntfs_compression_unit_descriptor_append_data_segment(
179
     libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor,
180
     off64_t segment_offset,
181
     size64_t segment_size,
182
     uint32_t segment_flags,
183
     libcerror_error_t **error )
184
189k
{
185
189k
  static char *function = "libfsntfs_compression_unit_descriptor_append_data_segment";
186
189k
  int segment_index     = 0;
187
188
189k
  if( compression_unit_descriptor == NULL )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
194
0
     "%s: invalid compression unit descriptor.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
189k
  if( libfdata_stream_append_segment(
200
189k
       compression_unit_descriptor->data_stream,
201
189k
       &segment_index,
202
189k
       0,
203
189k
       segment_offset,
204
189k
       segment_size,
205
189k
       segment_flags,
206
189k
       error ) != 1 )
207
166
  {
208
166
    libcerror_error_set(
209
166
     error,
210
166
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
211
166
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
212
166
     "%s: unable to append data run to array.",
213
166
     function );
214
215
166
    return( -1 );
216
166
  }
217
189k
  compression_unit_descriptor->data_size += segment_size;
218
219
189k
  return( 1 );
220
189k
}
221
222
#if defined( HAVE_DEBUG_OUTPUT )
223
224
/* Debug prints the compression unit descriptor
225
 * Returns 1 if successful or -1 on error
226
 */
227
int libfsntfs_compression_unit_descriptor_print(
228
     libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor,
229
     libfsntfs_io_handle_t *io_handle,
230
     int compression_unit_descriptor_index,
231
     libcerror_error_t **error )
232
{
233
  char *compression_unit_data_type = NULL;
234
  static char *function            = "libfsntfs_compression_unit_descriptor_print";
235
  size64_t segment_size            = 0;
236
  off64_t segment_offset           = 0;
237
  uint32_t segment_flags           = 0;
238
  int number_of_segments           = 0;
239
  int segment_file_index           = 0;
240
  int segment_index                = 0;
241
242
  if( compression_unit_descriptor == NULL )
243
  {
244
    libcerror_error_set(
245
     error,
246
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
247
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
248
     "%s: invalid compression unit descriptor.",
249
     function );
250
251
    return( -1 );
252
  }
253
  if( io_handle == NULL )
254
  {
255
    libcerror_error_set(
256
     error,
257
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
258
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
259
     "%s: invalid IO handle.",
260
     function );
261
262
    return( -1 );
263
  }
264
  if( ( compression_unit_descriptor->data_range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 )
265
  {
266
    compression_unit_data_type = "compressed";
267
  }
268
  else if( ( compression_unit_descriptor->data_range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
269
  {
270
    compression_unit_data_type = "sparse";
271
  }
272
  else
273
  {
274
    compression_unit_data_type = "uncompressed";
275
  }
276
  libcnotify_printf(
277
   "%s: %" PRIu64 " blocks %s compression unit: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
278
   function,
279
   compression_unit_descriptor->data_size / io_handle->cluster_block_size,
280
   compression_unit_data_type,
281
   compression_unit_descriptor_index,
282
   compression_unit_descriptor->data_offset,
283
   compression_unit_descriptor->data_offset );
284
285
  if( libfdata_stream_get_number_of_segments(
286
       compression_unit_descriptor->data_stream,
287
       &number_of_segments,
288
       error ) != 1 )
289
  {
290
    libcerror_error_set(
291
     error,
292
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
293
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
294
     "%s: unable to retrieve number of segments.",
295
     function );
296
297
    return( -1 );
298
  }
299
  for( segment_index = 0;
300
       segment_index < number_of_segments;
301
       segment_index++ )
302
  {
303
    if( libfdata_stream_get_segment_by_index(
304
         compression_unit_descriptor->data_stream,
305
         segment_index,
306
         &segment_file_index,
307
         &segment_offset,
308
         &segment_size,
309
         &segment_flags,
310
         error ) != 1 )
311
    {
312
      libcerror_error_set(
313
       error,
314
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
316
       "%s: unable to retrieve segment: %d.",
317
       function,
318
       segment_index );
319
320
      return( -1 );
321
    }
322
    if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
323
    {
324
      libcnotify_printf(
325
       "%s: segment: %d sparse of size: %" PRIu64 "\n",
326
       function,
327
       segment_index,
328
       segment_size );
329
    }
330
    else
331
    {
332
      libcnotify_printf(
333
       "%s: segment: %d at offset: 0x%08" PRIx64 " of size: %" PRIu64 "\n",
334
       function,
335
       segment_index,
336
       segment_offset,
337
       segment_size );
338
    }
339
  }
340
  libcnotify_printf(
341
   "\n" );
342
343
  return( 1 );
344
}
345
346
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
347