Coverage Report

Created: 2026-01-13 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libewf/libewf/libewf_session_section.c
Line
Count
Source
1
/*
2
 * Session section functions
3
 *
4
 * Copyright (C) 2006-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 <narrow_string.h>
26
#include <types.h>
27
28
#include "libewf_checksum.h"
29
#include "libewf_definitions.h"
30
#include "libewf_hash_sections.h"
31
#include "libewf_io_handle.h"
32
#include "libewf_libbfio.h"
33
#include "libewf_libcdata.h"
34
#include "libewf_libcerror.h"
35
#include "libewf_libcnotify.h"
36
#include "libewf_section.h"
37
#include "libewf_section_descriptor.h"
38
#include "libewf_sector_range.h"
39
#include "libewf_sector_range_list.h"
40
#include "libewf_session_section.h"
41
42
#include "ewf_session.h"
43
44
/* Reads a version 1 session section or version 2 session table section
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libewf_session_section_read_data(
48
     const uint8_t *data,
49
     size_t data_size,
50
     uint8_t format_version,
51
     libewf_media_values_t *media_values,
52
     libcdata_array_t *sessions,
53
     libcdata_array_t *tracks,
54
     libcerror_error_t **error )
55
160
{
56
160
  const uint8_t *session_data        = NULL;
57
160
  const uint8_t *session_entry_data  = NULL;
58
160
  static char *function              = "libewf_session_section_read_data";
59
160
  size_t session_entries_data_size   = 0;
60
160
  size_t session_entry_data_size     = 0;
61
160
  size_t session_footer_data_size    = 0;
62
160
  size_t session_header_data_size    = 0;
63
160
  uint64_t number_of_sectors         = 0;
64
160
  uint64_t previous_start_sector     = 0;
65
160
  uint64_t session_start_sector      = 0;
66
160
  uint64_t start_sector              = 0;
67
160
  uint64_t track_start_sector        = 0;
68
160
  uint32_t calculated_checksum       = 0;
69
160
  uint32_t flags                     = 0;
70
160
  uint32_t number_of_session_entries = 0;
71
160
  uint32_t previous_flags            = 0;
72
160
  uint32_t session_entry_index       = 0;
73
160
  uint32_t stored_checksum           = 0;
74
75
160
  if( data == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
80
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
81
0
     "%s: missing data.",
82
0
     function );
83
84
0
    return( -1 );
85
0
  }
86
160
  if( format_version == 1 )
87
160
  {
88
160
    session_header_data_size = sizeof( ewf_session_header_v1_t );
89
160
    session_entry_data_size  = sizeof( ewf_session_entry_v1_t );
90
160
    session_footer_data_size = 4;
91
160
  }
92
0
  else if( format_version == 2 )
93
0
  {
94
0
    session_header_data_size = sizeof( ewf_session_header_v2_t );
95
0
    session_entry_data_size  = sizeof( ewf_session_entry_v2_t );
96
0
    session_footer_data_size = 16;
97
0
  }
98
0
  else
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
103
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
104
0
     "%s: unsupported format version.",
105
0
     function );
106
107
0
    return( -1 );
108
0
  }
109
160
  if( ( data_size < session_header_data_size )
110
159
   || ( data_size > (size_t) SSIZE_MAX ) )
111
1
  {
112
1
    libcerror_error_set(
113
1
     error,
114
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
115
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
116
1
     "%s: invalid data size value out of bounds.",
117
1
     function );
118
119
1
    return( -1 );
120
1
  }
121
159
  if( media_values == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
127
0
     "%s: invalid media values.",
128
0
     function );
129
130
0
    return( -1 );
131
0
  }
132
159
  session_data = data;
133
134
#if defined( HAVE_DEBUG_OUTPUT )
135
  if( libcnotify_verbose != 0 )
136
  {
137
    libcnotify_printf(
138
     "%s: session header data:\n",
139
     function );
140
    libcnotify_print_data(
141
     data,
142
     session_header_data_size,
143
     0 );
144
  }
145
#endif
146
159
  if( format_version == 1 )
147
159
  {
148
159
    byte_stream_copy_to_uint32_little_endian(
149
159
     ( (ewf_session_header_v1_t *) data )->number_of_entries,
150
159
     number_of_session_entries );
151
152
159
    byte_stream_copy_to_uint32_little_endian(
153
159
     ( (ewf_session_header_v1_t *) data )->checksum,
154
159
     stored_checksum );
155
159
  }
156
0
  else if( format_version == 2 )
157
0
  {
158
0
    byte_stream_copy_to_uint32_little_endian(
159
0
     ( (ewf_session_header_v2_t *) data )->number_of_entries,
160
0
     number_of_session_entries );
161
162
0
    byte_stream_copy_to_uint32_little_endian(
163
0
     ( (ewf_session_header_v2_t *) data )->checksum,
164
0
     stored_checksum );
165
0
  }
166
#if defined( HAVE_DEBUG_OUTPUT )
167
  if( libcnotify_verbose != 0 )
168
  {
169
    libcnotify_printf(
170
     "%s: number of entries\t\t\t: %" PRIu32 "\n",
171
     function,
172
     number_of_session_entries );
173
174
    libcnotify_printf(
175
     "%s: unknown1:\n",
176
     function );
177
178
    if( format_version == 1 )
179
    {
180
      libcnotify_print_data(
181
       ( (ewf_session_header_v1_t *) data )->unknown1,
182
       28,
183
       0 );
184
    }
185
    else if( format_version == 2 )
186
    {
187
      libcnotify_print_data(
188
       ( (ewf_session_header_v2_t *) data )->unknown1,
189
       12,
190
       0 );
191
    }
192
    libcnotify_printf(
193
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
194
     function,
195
     stored_checksum );
196
197
    if( format_version == 1 )
198
    {
199
      libcnotify_printf(
200
       "\n" );
201
    }
202
    else if( format_version == 2 )
203
    {
204
      libcnotify_printf(
205
       "%s: padding:\n",
206
       function );
207
      libcnotify_print_data(
208
       ( (ewf_session_header_v2_t *) data )->padding,
209
       12,
210
       0 );
211
    }
212
  }
213
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
214
215
159
  if( format_version == 2 )
216
0
  {
217
0
    session_header_data_size -= 12;
218
0
  }
219
159
  if( libewf_checksum_calculate_adler32(
220
159
       &calculated_checksum,
221
159
       data,
222
159
       session_header_data_size - 4,
223
159
       1,
224
159
       error ) != 1 )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
230
0
     "%s: unable to calculate header checksum.",
231
0
     function );
232
233
0
    goto on_error;
234
0
  }
235
159
  if( format_version == 2 )
236
0
  {
237
0
    session_header_data_size += 12;
238
0
  }
239
159
  session_data = &( data[ session_header_data_size ] );
240
159
  data_size   -= session_header_data_size;
241
242
159
  if( stored_checksum != calculated_checksum )
243
50
  {
244
50
    libcerror_error_set(
245
50
     error,
246
50
     LIBCERROR_ERROR_DOMAIN_INPUT,
247
50
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
248
50
     "%s: header checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
249
50
     function,
250
50
     stored_checksum,
251
50
     calculated_checksum );
252
253
50
    goto on_error;
254
50
  }
255
109
  if( number_of_session_entries > 0 )
256
108
  {
257
108
    session_entry_data = session_data;
258
259
108
    session_entries_data_size = number_of_session_entries * session_entry_data_size;
260
261
108
    if( session_entries_data_size > (size_t) SSIZE_MAX )
262
0
    {
263
0
      libcerror_error_set(
264
0
       error,
265
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
266
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
267
0
       "%s: invalid session entries data size value exceeds maximum.",
268
0
       function );
269
270
0
      goto on_error;
271
0
    }
272
108
    if( data_size < session_entries_data_size )
273
26
    {
274
26
      libcerror_error_set(
275
26
       error,
276
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
277
26
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
278
26
       "%s: invalid section size value out of bounds - insufficient space for entries.",
279
26
       function );
280
281
26
      goto on_error;
282
26
    }
283
#if defined( HAVE_DEBUG_OUTPUT )
284
    if( libcnotify_verbose != 0 )
285
    {
286
      libcnotify_printf(
287
       "%s: session entries data:\n",
288
       function );
289
      libcnotify_print_data(
290
       session_data,
291
       session_entries_data_size,
292
       0 );
293
    }
294
#endif
295
82
    if( libewf_checksum_calculate_adler32(
296
82
         &calculated_checksum,
297
82
         session_data,
298
82
         session_entries_data_size,
299
82
         1,
300
82
         error ) != 1 )
301
0
    {
302
0
      libcerror_error_set(
303
0
       error,
304
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
305
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
306
0
       "%s: unable to calculate entries checksum.",
307
0
       function );
308
309
0
      goto on_error;
310
0
    }
311
82
    session_data += session_entries_data_size;
312
82
    data_size    -= session_entries_data_size;
313
314
82
    if( data_size < session_footer_data_size )
315
1
    {
316
1
      libcerror_error_set(
317
1
       error,
318
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
319
1
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
320
1
       "%s: invalid section size value out of bounds - insufficient space for footer.",
321
1
       function );
322
323
1
      goto on_error;
324
1
    }
325
81
    byte_stream_copy_to_uint32_little_endian(
326
81
     session_data,
327
81
     stored_checksum );
328
329
#if defined( HAVE_DEBUG_OUTPUT )
330
    if( libcnotify_verbose != 0 )
331
    {
332
      libcnotify_printf(
333
       "%s: session entries checksum\t\t: 0x%08" PRIx32 "\n",
334
       function,
335
       stored_checksum );
336
337
      if( format_version == 1 )
338
      {
339
        libcnotify_printf(
340
         "\n" );
341
      }
342
      else if( format_version == 2 )
343
      {
344
        libcnotify_printf(
345
         "%s: padding:\n",
346
         function );
347
        libcnotify_print_data(
348
         &( session_data[ 4 ] ),
349
         12,
350
         0 );
351
      }
352
    }
353
#endif
354
81
    session_data      += session_footer_data_size;
355
81
    data_size -= session_footer_data_size;
356
357
81
    if( stored_checksum != calculated_checksum )
358
35
    {
359
35
      libcerror_error_set(
360
35
       error,
361
35
       LIBCERROR_ERROR_DOMAIN_INPUT,
362
35
       LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
363
35
       "%s: entries checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
364
35
       function,
365
35
       stored_checksum,
366
35
       calculated_checksum );
367
368
35
      goto on_error;
369
35
    }
370
#if defined( HAVE_VERBOSE_OUTPUT ) || defined( HAVE_DEBUG_OUTPUT )
371
    if( libcnotify_verbose != 0 )
372
    {
373
      if( data_size > 0 )
374
      {
375
#if defined( HAVE_DEBUG_OUTPUT )
376
        libcnotify_printf(
377
         "%s: trailing data:\n",
378
         function );
379
        libcnotify_print_data(
380
         session_data,
381
         data_size,
382
         0 );
383
384
#elif defined( HAVE_VERBOSE_OUTPUT )
385
        libcnotify_printf(
386
         "%s: section has trailing data.\n",
387
         function );
388
#endif
389
      }
390
    }
391
#endif
392
46
    if( libcdata_array_empty(
393
46
         sessions,
394
46
         (int (*)(intptr_t **, libcerror_error_t **)) &libewf_sector_range_free,
395
46
         error ) != 1 )
396
0
    {
397
0
      libcerror_error_set(
398
0
       error,
399
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
400
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
401
0
       "%s: unable to empty sessions array.",
402
0
       function );
403
404
0
      goto on_error;
405
0
    }
406
46
    if( format_version == 1 )
407
46
    {
408
46
      byte_stream_copy_to_uint32_little_endian(
409
46
       ( (ewf_session_entry_v1_t *) session_entry_data )->flags,
410
46
       previous_flags );
411
412
46
      byte_stream_copy_to_uint32_little_endian(
413
46
       ( (ewf_session_entry_v1_t *) session_entry_data )->start_sector,
414
46
       previous_start_sector );
415
46
    }
416
0
    else if( format_version == 2 )
417
0
    {
418
0
      byte_stream_copy_to_uint64_little_endian(
419
0
       ( (ewf_session_entry_v2_t *) session_entry_data )->start_sector,
420
0
       previous_start_sector );
421
422
0
      byte_stream_copy_to_uint32_little_endian(
423
0
       ( (ewf_session_entry_v2_t *) session_entry_data )->flags,
424
0
       previous_flags );
425
0
    }
426
#if defined( HAVE_DEBUG_OUTPUT )
427
    if( libcnotify_verbose != 0 )
428
    {
429
      if( format_version == 1 )
430
      {
431
        libcnotify_printf(
432
         "%s: entry: %02" PRIu32 " flags\t\t\t: 0x%08" PRIx32 "\n",
433
         function,
434
         session_entry_index,
435
         previous_flags );
436
437
        libcnotify_printf(
438
         "%s: entry: %02" PRIu32 " start sector\t\t: 0 (%" PRIu64 ")\n",
439
         function,
440
         session_entry_index,
441
         previous_start_sector );
442
      }
443
      else if( format_version == 2 )
444
      {
445
        libcnotify_printf(
446
         "%s: entry: %02" PRIu32 " start sector\t\t: 0 (%" PRIu64 ")\n",
447
         function,
448
         session_entry_index,
449
         previous_start_sector );
450
451
        libcnotify_printf(
452
         "%s: entry: %02" PRIu32 " flags\t\t\t: 0x%08" PRIx32 "\n",
453
         function,
454
         session_entry_index,
455
         previous_flags );
456
      }
457
      libcnotify_printf(
458
       "%s: entry: %02" PRIu32 " unknown1:\n",
459
       function,
460
       session_entry_index );
461
462
      if( format_version == 1 )
463
      {
464
        libcnotify_print_data(
465
         ( (ewf_session_entry_v1_t *) session_entry_data )->unknown1,
466
         24,
467
         0 );
468
      }
469
      else if( format_version == 2 )
470
      {
471
        libcnotify_print_data(
472
         ( (ewf_session_entry_v2_t *) session_entry_data )->unknown1,
473
         20,
474
         0 );
475
      }
476
    }
477
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
478
479
46
    session_entry_data += session_entry_data_size;
480
481
    /* Note that EnCase says the first session starts at session 16
482
     * This is either some EnCase specific behavior or the value is used for
483
     * other purposes.
484
     */
485
46
    session_start_sector = 0;
486
46
    track_start_sector   = 0;
487
488
46
    for( session_entry_index = 1;
489
155
         session_entry_index < number_of_session_entries;
490
109
         session_entry_index++ )
491
125
    {
492
125
      if( format_version == 1 )
493
125
      {
494
125
        byte_stream_copy_to_uint32_little_endian(
495
125
         ( (ewf_session_entry_v1_t *) session_entry_data )->flags,
496
125
         flags );
497
498
125
        byte_stream_copy_to_uint32_little_endian(
499
125
         ( (ewf_session_entry_v1_t *) session_entry_data )->start_sector,
500
125
         start_sector );
501
125
      }
502
0
      else if( format_version == 2 )
503
0
      {
504
0
        byte_stream_copy_to_uint64_little_endian(
505
0
         ( (ewf_session_entry_v2_t *) session_entry_data )->start_sector,
506
0
         start_sector );
507
508
0
        byte_stream_copy_to_uint32_little_endian(
509
0
         ( (ewf_session_entry_v2_t *) session_entry_data )->flags,
510
0
         flags );
511
0
      }
512
#if defined( HAVE_DEBUG_OUTPUT )
513
      if( libcnotify_verbose != 0 )
514
      {
515
        if( format_version == 1 )
516
        {
517
          libcnotify_printf(
518
           "%s: entry: %02" PRIu32 " flags\t\t\t: 0x%08" PRIx32 "\n",
519
           function,
520
           session_entry_index,
521
           flags );
522
523
          libcnotify_printf(
524
           "%s: entry: %02" PRIu32 " start sector\t\t: %" PRIu64 "\n",
525
           function,
526
           session_entry_index,
527
           start_sector );
528
        }
529
        else if( format_version == 2 )
530
        {
531
          libcnotify_printf(
532
           "%s: entry: %02" PRIu32 " start sector\t\t: %" PRIu64 "\n",
533
           function,
534
           session_entry_index,
535
           start_sector );
536
537
          libcnotify_printf(
538
           "%s: entry: %02" PRIu32 " flags\t\t\t: 0x%08" PRIx32 "\n",
539
           function,
540
           session_entry_index,
541
           flags );
542
        }
543
        libcnotify_printf(
544
         "%s: entry: %02" PRIu32 " unknown1:\n",
545
         function,
546
         session_entry_index );
547
548
        if( format_version == 1 )
549
        {
550
          libcnotify_print_data(
551
           ( (ewf_session_entry_v1_t *) session_entry_data )->unknown1,
552
           24,
553
           0 );
554
        }
555
        else if( format_version == 2 )
556
        {
557
          libcnotify_print_data(
558
           ( (ewf_session_entry_v2_t *) session_entry_data )->unknown1,
559
           20,
560
           0 );
561
        }
562
      }
563
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
564
565
125
      session_entry_data += session_entry_data_size;
566
567
125
      if( start_sector < previous_start_sector )
568
16
      {
569
16
        libcerror_error_set(
570
16
         error,
571
16
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
572
16
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
573
16
         "%s: invalid start sector: %" PRIu32 " value out of bounds.",
574
16
         function,
575
16
         start_sector );
576
577
16
        goto on_error;
578
16
      }
579
109
      if( ( flags & LIBEWF_SESSION_ENTRY_FLAGS_IS_AUDIO_TRACK ) == 0 )
580
54
      {
581
/* TODO bounds check */
582
54
        number_of_sectors = start_sector - session_start_sector;
583
584
54
        if( libewf_sector_range_list_append_range(
585
54
             sessions,
586
54
             session_start_sector,
587
54
             (uint64_t) number_of_sectors,
588
54
             error ) != 1 )
589
0
        {
590
0
          libcerror_error_set(
591
0
           error,
592
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
593
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
594
0
           "%s: unable to append session sector range.",
595
0
           function );
596
597
0
          goto on_error;
598
0
        }
599
54
        session_start_sector = start_sector;
600
54
      }
601
109
      if( ( previous_flags & LIBEWF_SESSION_ENTRY_FLAGS_IS_AUDIO_TRACK ) != 0 )
602
66
      {
603
/* TODO bounds check */
604
66
        number_of_sectors = start_sector - track_start_sector;
605
606
66
        if( libewf_sector_range_list_append_range(
607
66
             tracks,
608
66
             track_start_sector,
609
66
             (uint64_t) number_of_sectors,
610
66
             error ) != 1 )
611
0
        {
612
0
          libcerror_error_set(
613
0
           error,
614
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
615
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
616
0
           "%s: unable to append track sector range.",
617
0
           function );
618
619
0
          goto on_error;
620
0
        }
621
66
        track_start_sector = start_sector;
622
66
      }
623
109
      previous_start_sector = start_sector;
624
109
      previous_flags        = flags;
625
109
    }
626
30
    if( media_values->number_of_sectors > session_start_sector )
627
0
    {
628
0
      number_of_sectors = (uint32_t) ( media_values->number_of_sectors - session_start_sector );
629
0
    }
630
30
    else
631
30
    {
632
30
      number_of_sectors = 0;
633
30
    }
634
30
    if( libewf_sector_range_list_append_range(
635
30
         sessions,
636
30
         session_start_sector,
637
30
         (uint64_t) number_of_sectors,
638
30
         error ) != 1 )
639
0
    {
640
0
      libcerror_error_set(
641
0
       error,
642
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
643
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
644
0
       "%s: unable to append session sector range.",
645
0
       function );
646
647
0
      goto on_error;
648
0
    }
649
30
    if( ( flags & LIBEWF_SESSION_ENTRY_FLAGS_IS_AUDIO_TRACK ) != 0 )
650
19
    {
651
19
      if( media_values->number_of_sectors > track_start_sector )
652
0
      {
653
0
        number_of_sectors = (uint32_t) ( media_values->number_of_sectors - track_start_sector );
654
0
      }
655
19
      else
656
19
      {
657
19
        number_of_sectors = 0;
658
19
      }
659
19
      if( libewf_sector_range_list_append_range(
660
19
           tracks,
661
19
           track_start_sector,
662
19
           (uint64_t) number_of_sectors,
663
19
           error ) != 1 )
664
0
      {
665
0
        libcerror_error_set(
666
0
         error,
667
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
668
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
669
0
         "%s: unable to append track sector range.",
670
0
         function );
671
672
0
        goto on_error;
673
0
      }
674
19
    }
675
30
  }
676
#if defined( HAVE_VERBOSE_OUTPUT )
677
  else if( libcnotify_verbose != 0 )
678
  {
679
    libcnotify_printf(
680
     "%s: session section contains no entries.\n",
681
     function );
682
  }
683
#endif
684
31
  return( 1 );
685
686
128
on_error:
687
128
  libcdata_array_empty(
688
128
   tracks,
689
128
   (int (*)(intptr_t **, libcerror_error_t **)) &libewf_sector_range_free,
690
128
   error );
691
692
128
  libcdata_array_empty(
693
128
   sessions,
694
128
   (int (*)(intptr_t **, libcerror_error_t **)) &libewf_sector_range_free,
695
128
   error );
696
697
128
  return( -1 );
698
109
}
699
700
/* Reads a version 1 session section or version 2 session table section
701
 * Returns the number of bytes read or -1 on error
702
 */
703
ssize_t libewf_session_section_read_file_io_pool(
704
         libewf_section_descriptor_t *section_descriptor,
705
         libewf_io_handle_t *io_handle,
706
         libbfio_pool_t *file_io_pool,
707
         int file_io_pool_entry,
708
         uint8_t format_version,
709
         libewf_media_values_t *media_values,
710
         libcdata_array_t *sessions,
711
         libcdata_array_t *tracks,
712
         libcerror_error_t **error )
713
163
{
714
163
  uint8_t *section_data    = NULL;
715
163
  static char *function    = "libewf_session_section_read_file_io_pool";
716
163
  size_t section_data_size = 0;
717
163
  ssize_t read_count       = 0;
718
719
163
  if( section_descriptor == NULL )
720
0
  {
721
0
    libcerror_error_set(
722
0
     error,
723
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
724
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
725
0
     "%s: invalid section descriptor.",
726
0
     function );
727
728
0
    return( -1 );
729
0
  }
730
163
  read_count = libewf_section_read_data(
731
163
                section_descriptor,
732
163
                io_handle,
733
163
                file_io_pool,
734
163
                file_io_pool_entry,
735
163
                &section_data,
736
163
                &section_data_size,
737
163
                error );
738
739
163
  if( read_count == -1 )
740
3
  {
741
3
    libcerror_error_set(
742
3
     error,
743
3
     LIBCERROR_ERROR_DOMAIN_IO,
744
3
     LIBCERROR_IO_ERROR_READ_FAILED,
745
3
     "%s: unable to read section data.",
746
3
     function );
747
748
3
    goto on_error;
749
3
  }
750
160
  else if( read_count != 0 )
751
160
  {
752
160
    if( libewf_session_section_read_data(
753
160
         section_data,
754
160
         section_data_size,
755
160
         format_version,
756
160
         media_values,
757
160
         sessions,
758
160
         tracks,
759
160
         error ) != 1 )
760
129
    {
761
129
      libcerror_error_set(
762
129
       error,
763
129
       LIBCERROR_ERROR_DOMAIN_IO,
764
129
       LIBCERROR_IO_ERROR_READ_FAILED,
765
129
       "%s: unable to read section data.",
766
129
       function );
767
768
129
      goto on_error;
769
129
    }
770
31
    memory_free(
771
31
     section_data );
772
31
  }
773
31
  return( read_count );
774
775
132
on_error:
776
132
  if( section_data != NULL )
777
129
  {
778
129
    memory_free(
779
129
     section_data );
780
129
  }
781
132
  return( -1 );
782
163
}
783
784
/* Writes a session section
785
 * Returns 1 if successful or -1 on error
786
 */
787
int libewf_session_section_write_data(
788
     uint8_t *data,
789
     size_t data_size,
790
     uint8_t format_version,
791
     libcdata_array_t *sessions,
792
     libcdata_array_t *tracks,
793
     int number_of_session_entries,
794
     libcerror_error_t **error )
795
0
{
796
0
  uint8_t *session_data              = NULL;
797
0
  uint8_t *session_entry_data        = NULL;
798
0
  static char *function              = "libewf_session_section_write_data";
799
0
  size_t required_data_size          = 0;
800
0
  size_t session_entries_data_size   = 0;
801
0
  size_t session_entry_data_size     = 0;
802
0
  size_t session_footer_data_size    = 0;
803
0
  size_t session_header_data_size    = 0;
804
0
  uint64_t current_sector            = 0;
805
0
  uint64_t session_last_sector       = 0;
806
0
  uint64_t session_number_of_sectors = 0;
807
0
  uint64_t session_start_sector      = 0;
808
0
  uint64_t track_last_sector         = 0;
809
0
  uint64_t track_number_of_sectors   = 0;
810
0
  uint64_t track_start_sector        = 0;
811
0
  uint32_t calculated_checksum       = 0;
812
0
  uint32_t session_entry_index       = 0;
813
0
  int number_of_sessions             = 0;
814
0
  int number_of_tracks               = 0;
815
0
  int session_index                  = 0;
816
0
  int track_index                    = 0;
817
818
0
  if( data == NULL )
819
0
  {
820
0
    libcerror_error_set(
821
0
     error,
822
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
823
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
824
0
     "%s: missing data.",
825
0
     function );
826
827
0
    return( -1 );
828
0
  }
829
0
  if( format_version == 1 )
830
0
  {
831
0
    session_header_data_size = sizeof( ewf_session_header_v1_t );
832
0
    session_entry_data_size  = sizeof( ewf_session_entry_v1_t );
833
0
    session_footer_data_size = 4;
834
0
  }
835
0
  else if( format_version == 2 )
836
0
  {
837
0
    session_header_data_size = sizeof( ewf_session_header_v2_t );
838
0
    session_entry_data_size  = sizeof( ewf_session_entry_v2_t );
839
0
    session_footer_data_size = 16;
840
0
  }
841
0
  else
842
0
  {
843
0
    libcerror_error_set(
844
0
     error,
845
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
846
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
847
0
     "%s: unsupported format version.",
848
0
     function );
849
850
0
    return( -1 );
851
0
  }
852
0
  session_entries_data_size = number_of_session_entries * session_entry_data_size;
853
854
0
  required_data_size = session_header_data_size
855
0
                     + session_entries_data_size
856
0
                     + session_footer_data_size;
857
858
0
  if( ( data_size < required_data_size )
859
0
   || ( data_size > (size_t) SSIZE_MAX ) )
860
0
  {
861
0
    libcerror_error_set(
862
0
     error,
863
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
864
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
865
0
     "%s: invalid data size value out of bounds.",
866
0
     function );
867
868
0
    return( -1 );
869
0
  }
870
0
  if( memory_set(
871
0
       data,
872
0
       0,
873
0
       data_size ) == NULL )
874
0
  {
875
0
    libcerror_error_set(
876
0
     error,
877
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
878
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
879
0
     "%s: unable to clear data.",
880
0
     function );
881
882
0
    return( -1 );
883
0
  }
884
0
  session_data = data;
885
886
/* TODO check if number_of_session_entries is in bounds */
887
0
  if( format_version == 1 )
888
0
  {
889
0
    byte_stream_copy_from_uint32_little_endian(
890
0
     ( (ewf_session_header_v1_t *) session_data )->number_of_entries,
891
0
     (uint32_t) number_of_session_entries );
892
0
  }
893
0
  else if( format_version == 2 )
894
0
  {
895
0
    byte_stream_copy_from_uint32_little_endian(
896
0
     ( (ewf_session_header_v2_t *) session_data )->number_of_entries,
897
0
     (uint32_t) number_of_session_entries );
898
899
0
    session_header_data_size -= 12;
900
0
  }
901
0
  if( libewf_checksum_calculate_adler32(
902
0
       &calculated_checksum,
903
0
       session_data,
904
0
       session_header_data_size - 4,
905
0
       1,
906
0
       error ) != 1 )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
911
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
912
0
     "%s: unable to calculate header checksum.",
913
0
     function );
914
915
0
    return( -1 );
916
0
  }
917
0
  if( format_version == 1 )
918
0
  {
919
0
    byte_stream_copy_from_uint32_little_endian(
920
0
     ( (ewf_session_header_v1_t *) session_data )->checksum,
921
0
     calculated_checksum );
922
0
  }
923
0
  else if( format_version == 2 )
924
0
  {
925
0
    byte_stream_copy_from_uint32_little_endian(
926
0
     ( (ewf_session_header_v2_t *) session_data )->checksum,
927
0
     calculated_checksum );
928
929
0
    session_header_data_size += 12;
930
0
  }
931
#if defined( HAVE_DEBUG_OUTPUT )
932
  if( libcnotify_verbose != 0 )
933
  {
934
    libcnotify_printf(
935
     "%s: session header data:\n",
936
     function );
937
    libcnotify_print_data(
938
     session_data,
939
     session_header_data_size,
940
     0 );
941
  }
942
#endif
943
0
  session_data += session_header_data_size;
944
945
0
  session_entry_data   = session_data;
946
0
  current_sector       = 0;
947
0
  session_start_sector = 0;
948
0
  session_index        = 0;
949
0
  session_last_sector  = 0;
950
0
  track_start_sector   = 0;
951
0
  track_index          = 0;
952
0
  track_last_sector    = 0;
953
954
0
  if( libcdata_array_get_number_of_entries(
955
0
       sessions,
956
0
       &number_of_sessions,
957
0
       error ) != 1 )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
962
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
963
0
     "%s: unable to retrieve number of entries from sessions array.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
0
  if( libcdata_array_get_number_of_entries(
969
0
       tracks,
970
0
       &number_of_tracks,
971
0
       error ) != 1 )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
976
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
977
0
     "%s: unable to retrieve number of entries from tracks array.",
978
0
     function );
979
980
0
    return( -1 );
981
0
  }
982
0
  do
983
0
  {
984
0
    if( ( session_index < number_of_sessions )
985
0
     && ( current_sector >= session_last_sector ) )
986
0
    {
987
0
      if( libewf_sector_range_list_get_range(
988
0
           sessions,
989
0
           session_index,
990
0
           &session_start_sector,
991
0
           &session_number_of_sectors,
992
0
           error ) != 1 )
993
0
      {
994
0
        libcerror_error_set(
995
0
         error,
996
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
997
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
998
0
         "%s: unable to retrieve session: %d sector range.",
999
0
         function,
1000
0
         session_index );
1001
1002
0
        return( -1 );
1003
0
      }
1004
0
      session_last_sector = session_start_sector
1005
0
              + session_number_of_sectors;
1006
1007
0
      session_index++;
1008
0
    }
1009
0
    if( ( track_index < number_of_tracks )
1010
0
     && ( current_sector >= track_last_sector ) )
1011
0
    {
1012
0
      if( libewf_sector_range_list_get_range(
1013
0
           tracks,
1014
0
           track_index,
1015
0
           &track_start_sector,
1016
0
           &track_number_of_sectors,
1017
0
           error ) != 1 )
1018
0
      {
1019
0
        libcerror_error_set(
1020
0
         error,
1021
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1022
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1023
0
         "%s: unable to retrieve track: %d sector range.",
1024
0
         function,
1025
0
         track_index );
1026
1027
0
        return( -1 );
1028
0
      }
1029
0
      track_last_sector = track_start_sector
1030
0
            + track_number_of_sectors;
1031
1032
0
      track_index++;
1033
0
    }
1034
0
    if( ( number_of_tracks > 0 )
1035
0
     && ( current_sector >= track_start_sector )
1036
0
     && ( current_sector < track_last_sector ) )
1037
0
    {
1038
#if defined( HAVE_DEBUG_OUTPUT )
1039
      if( libcnotify_verbose != 0 )
1040
      {
1041
        libcnotify_printf(
1042
         "%s: entry: %02" PRIu32 " flags\t\t\t\t: 1\n",
1043
         function,
1044
         session_entry_index );
1045
1046
        libcnotify_printf(
1047
         "%s: entry: %02" PRIu32 " start sector\t\t\t: %" PRIu32 "\n",
1048
         function,
1049
         session_entry_index,
1050
         track_start_sector );
1051
1052
        libcnotify_printf(
1053
         "%s: entry: %02" PRIu32 " last sector\t\t\t: %" PRIu32 "\n",
1054
         function,
1055
         session_entry_index,
1056
         track_last_sector );
1057
1058
        libcnotify_printf(
1059
         "\n" );
1060
      }
1061
#endif
1062
      /* Note that EnCase says the first track starts at sector 16
1063
       * This is either some EnCase specific behavior or the value is used for
1064
       * other purposes.
1065
       */
1066
0
      if( ( session_entry_index == 0 )
1067
0
       && ( track_start_sector == 0 ) )
1068
0
      {
1069
0
        track_start_sector = 16;
1070
0
      }
1071
0
      if( format_version == 1 )
1072
0
      {
1073
0
        byte_stream_copy_from_uint32_little_endian(
1074
0
         ( (ewf_session_entry_v1_t *) session_entry_data )->flags,
1075
0
         LIBEWF_SESSION_ENTRY_FLAGS_IS_AUDIO_TRACK );
1076
1077
0
        byte_stream_copy_from_uint32_little_endian(
1078
0
         ( (ewf_session_entry_v1_t *) session_entry_data )->start_sector,
1079
0
         (uint32_t) track_start_sector );
1080
0
      }
1081
0
      else if( format_version == 2 )
1082
0
      {
1083
0
        byte_stream_copy_from_uint64_little_endian(
1084
0
         ( (ewf_session_entry_v2_t *) session_entry_data )->start_sector,
1085
0
         track_start_sector );
1086
1087
0
        byte_stream_copy_from_uint32_little_endian(
1088
0
         ( (ewf_session_entry_v2_t *) session_entry_data )->flags,
1089
0
         LIBEWF_SESSION_ENTRY_FLAGS_IS_AUDIO_TRACK );
1090
0
      }
1091
0
      session_entry_data += session_entry_data_size;
1092
1093
0
      session_entry_index++;
1094
1095
0
      current_sector = track_last_sector;
1096
0
    }
1097
0
    else if( ( number_of_sessions > 0 )
1098
0
          && ( current_sector >= session_start_sector )
1099
0
          && ( current_sector < session_last_sector ) )
1100
0
    {
1101
0
      if( ( track_last_sector == 0 )
1102
0
       || ( track_last_sector < session_start_sector ) )
1103
0
      {
1104
#if defined( HAVE_DEBUG_OUTPUT )
1105
        if( libcnotify_verbose != 0 )
1106
        {
1107
          libcnotify_printf(
1108
           "%s: entry: %02" PRIu32 " flags\t\t\t\t: 0\n",
1109
           function,
1110
           session_entry_index );
1111
1112
          libcnotify_printf(
1113
           "%s: entry: %02" PRIu32 " start sector\t\t\t: %" PRIu32 "\n",
1114
           function,
1115
           session_entry_index,
1116
           session_start_sector );
1117
1118
          libcnotify_printf(
1119
           "%s: entry: %02" PRIu32 " last sector\t\t\t: %" PRIu32 "\n",
1120
           function,
1121
           session_entry_index,
1122
           session_last_sector );
1123
1124
          libcnotify_printf(
1125
           "\n" );
1126
        }
1127
#endif
1128
        /* Note that EnCase says the first session starts at sector 16
1129
         * This is either some EnCase specific behavior or the value is used for
1130
         * other purposes.
1131
         */
1132
0
        if( ( session_entry_index == 0 )
1133
0
         && ( session_start_sector == 0 ) )
1134
0
        {
1135
0
          session_start_sector = 16;
1136
0
        }
1137
0
        if( format_version == 1 )
1138
0
        {
1139
0
          byte_stream_copy_from_uint32_little_endian(
1140
0
           ( (ewf_session_entry_v1_t *) session_entry_data )->start_sector,
1141
0
           (uint32_t) session_start_sector );
1142
0
        }
1143
0
        else if( format_version == 2 )
1144
0
        {
1145
0
          byte_stream_copy_from_uint64_little_endian(
1146
0
           ( (ewf_session_entry_v2_t *) session_entry_data )->start_sector,
1147
0
           session_start_sector );
1148
0
        }
1149
0
        session_entry_data += session_entry_data_size;
1150
1151
0
        session_entry_index++;
1152
0
      }
1153
0
      current_sector = session_last_sector;
1154
0
    }
1155
0
    if( session_entry_index >= (uint32_t) number_of_session_entries )
1156
0
    {
1157
0
      break;
1158
0
    }
1159
0
  }
1160
0
  while( ( session_index < number_of_sessions )
1161
0
      || ( track_index < number_of_tracks ) );
1162
1163
#if defined( HAVE_DEBUG_OUTPUT )
1164
  if( libcnotify_verbose != 0 )
1165
  {
1166
    libcnotify_printf(
1167
     "%s: session entries data:\n",
1168
     function );
1169
    libcnotify_print_data(
1170
     session_data,
1171
     session_entries_data_size,
1172
     0 );
1173
  }
1174
#endif
1175
0
  if( libewf_checksum_calculate_adler32(
1176
0
       &calculated_checksum,
1177
0
       session_data,
1178
0
       session_entries_data_size,
1179
0
       1,
1180
0
       error ) != 1 )
1181
0
  {
1182
0
    libcerror_error_set(
1183
0
     error,
1184
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1185
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1186
0
     "%s: unable to calculate entries checksum.",
1187
0
     function );
1188
1189
0
    return( -1 );
1190
0
  }
1191
0
  session_data += session_entries_data_size;
1192
1193
0
  byte_stream_copy_from_uint32_little_endian(
1194
0
   session_data,
1195
0
   calculated_checksum );
1196
1197
#if defined( HAVE_DEBUG_OUTPUT )
1198
  if( libcnotify_verbose != 0 )
1199
  {
1200
    libcnotify_printf(
1201
     "%s: session footer data:\n",
1202
     function );
1203
    libcnotify_print_data(
1204
     session_data,
1205
     session_footer_data_size,
1206
     0 );
1207
  }
1208
#endif
1209
0
  return( 1 );
1210
0
}
1211
1212
/* Writes a session section
1213
 * Returns the number of bytes written or -1 on error
1214
 */
1215
ssize_t libewf_session_section_write_file_io_pool(
1216
         libewf_section_descriptor_t *section_descriptor,
1217
         libewf_io_handle_t *io_handle,
1218
         libbfio_pool_t *file_io_pool,
1219
         int file_io_pool_entry,
1220
         uint8_t format_version,
1221
         off64_t section_offset,
1222
         libcdata_array_t *sessions,
1223
         libcdata_array_t *tracks,
1224
         libcerror_error_t **error )
1225
0
{
1226
0
  uint8_t *section_data               = NULL;
1227
0
  static char *function               = "libewf_session_section_write_file_io_pool";
1228
0
  size_t section_data_size            = 0;
1229
0
  size_t section_descriptor_data_size = 0;
1230
0
  size_t session_entries_data_size    = 0;
1231
0
  size_t session_entry_data_size      = 0;
1232
0
  size_t session_footer_data_size     = 0;
1233
0
  size_t session_header_data_size     = 0;
1234
0
  ssize_t total_write_count           = 0;
1235
0
  ssize_t write_count                 = 0;
1236
0
  uint64_t current_sector             = 0;
1237
0
  uint64_t session_last_sector        = 0;
1238
0
  uint64_t session_number_of_sectors  = 0;
1239
0
  uint64_t session_start_sector       = 0;
1240
0
  uint64_t track_last_sector          = 0;
1241
0
  uint64_t track_number_of_sectors    = 0;
1242
0
  uint64_t track_start_sector         = 0;
1243
0
  uint32_t section_padding_size       = 0;
1244
0
  int number_of_session_entries       = 0;
1245
0
  int number_of_sessions              = 0;
1246
0
  int number_of_tracks                = 0;
1247
0
  int session_index                   = 0;
1248
0
  int track_index                     = 0;
1249
1250
0
  if( section_descriptor == NULL )
1251
0
  {
1252
0
    libcerror_error_set(
1253
0
     error,
1254
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1255
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1256
0
     "%s: invalid section descriptor.",
1257
0
     function );
1258
1259
0
    return( -1 );
1260
0
  }
1261
0
  if( format_version == 1 )
1262
0
  {
1263
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v1_t );
1264
0
    session_header_data_size     = sizeof( ewf_session_header_v1_t );
1265
0
    session_entry_data_size      = sizeof( ewf_session_entry_v1_t );
1266
0
    session_footer_data_size     = 4;
1267
0
  }
1268
0
  else if( format_version == 2 )
1269
0
  {
1270
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v2_t );
1271
0
    session_header_data_size     = sizeof( ewf_session_header_v2_t );
1272
0
    session_entry_data_size      = sizeof( ewf_session_entry_v2_t );
1273
0
    session_footer_data_size     = 16;
1274
0
    section_padding_size         = 24;
1275
0
  }
1276
0
  else
1277
0
  {
1278
0
    libcerror_error_set(
1279
0
     error,
1280
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1281
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1282
0
     "%s: unsupported format version.",
1283
0
     function );
1284
1285
0
    return( -1 );
1286
0
  }
1287
0
  if( libcdata_array_get_number_of_entries(
1288
0
       sessions,
1289
0
       &number_of_sessions,
1290
0
       error ) != 1 )
1291
0
  {
1292
0
    libcerror_error_set(
1293
0
     error,
1294
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1295
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1296
0
     "%s: unable to retrieve number of entries from sessions array.",
1297
0
     function );
1298
1299
0
    goto on_error;
1300
0
  }
1301
0
  if( number_of_sessions < 0 )
1302
0
  {
1303
0
    libcerror_error_set(
1304
0
     error,
1305
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1307
0
     "%s: invalid number of sessions value out of bounds.",
1308
0
     function );
1309
1310
0
    goto on_error;
1311
0
  }
1312
0
  if( libcdata_array_get_number_of_entries(
1313
0
       tracks,
1314
0
       &number_of_tracks,
1315
0
       error ) != 1 )
1316
0
  {
1317
0
    libcerror_error_set(
1318
0
     error,
1319
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1320
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1321
0
     "%s: unable to retrieve number of entries from tracks array.",
1322
0
     function );
1323
1324
0
    goto on_error;
1325
0
  }
1326
0
  if( number_of_tracks < 0 )
1327
0
  {
1328
0
    libcerror_error_set(
1329
0
     error,
1330
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1332
0
     "%s: invalid number of tracks value out of bounds.",
1333
0
     function );
1334
1335
0
    goto on_error;
1336
0
  }
1337
0
  if( ( number_of_sessions != 0 )
1338
0
   && ( number_of_tracks == 0 ) )
1339
0
  {
1340
0
    number_of_session_entries = number_of_sessions;
1341
0
  }
1342
0
  else if( ( number_of_sessions == 0 )
1343
0
        && ( number_of_tracks != 0 ) )
1344
0
  {
1345
0
    number_of_session_entries = number_of_tracks;
1346
0
  }
1347
0
  else if( ( number_of_sessions != 0 )
1348
0
        && ( number_of_tracks != 0 ) )
1349
0
  {
1350
    /* Encase does not store sessions containing tracks
1351
     * therefore the number of sessions entries needs to be determined
1352
     * from the run-time tracks and session information
1353
     */
1354
0
    do
1355
0
    {
1356
0
      if( ( session_index < number_of_sessions )
1357
0
       && ( current_sector >= session_last_sector ) )
1358
0
      {
1359
0
        if( libewf_sector_range_list_get_range(
1360
0
             sessions,
1361
0
             session_index,
1362
0
             &session_start_sector,
1363
0
             &session_number_of_sectors,
1364
0
             error ) != 1 )
1365
0
        {
1366
0
          libcerror_error_set(
1367
0
           error,
1368
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1369
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1370
0
           "%s: unable to retrieve session: %d sector range.",
1371
0
           function,
1372
0
           session_index );
1373
1374
0
          goto on_error;
1375
0
        }
1376
0
        session_last_sector = session_start_sector
1377
0
                + session_number_of_sectors;
1378
1379
0
        session_index++;
1380
0
      }
1381
0
      if( ( track_index < number_of_tracks )
1382
0
       && ( current_sector >= track_last_sector ) )
1383
0
      {
1384
0
        if( libewf_sector_range_list_get_range(
1385
0
             tracks,
1386
0
             track_index,
1387
0
             &track_start_sector,
1388
0
             &track_number_of_sectors,
1389
0
             error ) != 1 )
1390
0
        {
1391
0
          libcerror_error_set(
1392
0
           error,
1393
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1394
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1395
0
           "%s: unable to retrieve track: %d sector range.",
1396
0
           function,
1397
0
           track_index );
1398
1399
0
          goto on_error;
1400
0
        }
1401
0
        track_last_sector = track_start_sector
1402
0
              + track_number_of_sectors;
1403
1404
0
        track_index++;
1405
0
      }
1406
0
      if( ( number_of_tracks > 0 )
1407
0
       && ( current_sector >= track_start_sector )
1408
0
       && ( current_sector < track_last_sector ) )
1409
0
      {
1410
0
        number_of_session_entries++;
1411
1412
0
        current_sector = track_last_sector;
1413
0
      }
1414
0
      else if( ( number_of_sessions > 0 )
1415
0
            && ( current_sector >= session_start_sector )
1416
0
            && ( current_sector < session_last_sector ) )
1417
0
      {
1418
0
        if( ( track_last_sector == 0 )
1419
0
         || ( track_last_sector < session_start_sector ) )
1420
0
        {
1421
0
          number_of_session_entries++;
1422
0
        }
1423
0
        current_sector = session_last_sector;
1424
0
      }
1425
0
    }
1426
0
    while( ( session_index < number_of_sessions )
1427
0
        || ( track_index < number_of_tracks ) );
1428
0
  }
1429
0
  if( number_of_session_entries == 0 )
1430
0
  {
1431
0
    libcerror_error_set(
1432
0
     error,
1433
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1434
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1435
0
     "%s: invalid number of sessions entries value out of bounds.",
1436
0
     function );
1437
1438
0
    goto on_error;
1439
0
  }
1440
#if defined( HAVE_DEBUG_OUTPUT )
1441
  if( libcnotify_verbose != 0 )
1442
  {
1443
    libcnotify_printf(
1444
     "%s: number of entries\t\t\t: %" PRIu32 "\n",
1445
     function,
1446
     number_of_session_entries );
1447
1448
    libcnotify_printf(
1449
     "\n" );
1450
  }
1451
#endif
1452
0
  session_entries_data_size = number_of_session_entries * session_entry_data_size;
1453
1454
0
  section_data_size = session_header_data_size
1455
0
                    + session_entries_data_size
1456
0
                    + session_footer_data_size;
1457
1458
0
  if( libewf_section_descriptor_set(
1459
0
       section_descriptor,
1460
0
       LIBEWF_SECTION_TYPE_SESSION_TABLE,
1461
0
       (uint8_t *) "session",
1462
0
       7,
1463
0
       section_offset,
1464
0
       section_descriptor_data_size + section_data_size,
1465
0
       section_data_size,
1466
0
       section_padding_size,
1467
0
       error ) != 1 )
1468
0
  {
1469
0
    libcerror_error_set(
1470
0
     error,
1471
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1472
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1473
0
     "%s: unable to set section descriptor.",
1474
0
     function );
1475
1476
0
    goto on_error;
1477
0
  }
1478
0
  if( format_version == 1 )
1479
0
  {
1480
0
    write_count = libewf_section_descriptor_write_file_io_pool(
1481
0
             section_descriptor,
1482
0
             file_io_pool,
1483
0
             file_io_pool_entry,
1484
0
             format_version,
1485
0
             error );
1486
1487
0
    if( write_count != (ssize_t) section_descriptor_data_size )
1488
0
    {
1489
0
      libcerror_error_set(
1490
0
       error,
1491
0
       LIBCERROR_ERROR_DOMAIN_IO,
1492
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
1493
0
       "%s: unable to write section descriptor data.",
1494
0
       function );
1495
1496
0
      goto on_error;
1497
0
    }
1498
0
    total_write_count += write_count;
1499
0
  }
1500
0
  if( ( section_data_size == 0 )
1501
0
   || ( section_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1502
0
  {
1503
0
    libcerror_error_set(
1504
0
     error,
1505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1506
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1507
0
     "%s: invalid section data size value out of bounds.",
1508
0
     function );
1509
1510
0
    goto on_error;
1511
0
  }
1512
0
  section_data = (uint8_t *) memory_allocate(
1513
0
                              section_data_size );
1514
1515
0
  if( section_data == NULL )
1516
0
  {
1517
0
    libcerror_error_set(
1518
0
     error,
1519
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1520
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1521
0
     "%s: unable to create section data.",
1522
0
     function );
1523
1524
0
    goto on_error;
1525
0
  }
1526
0
  if( libewf_session_section_write_data(
1527
0
       section_data,
1528
0
       section_data_size,
1529
0
       format_version,
1530
0
       sessions,
1531
0
       tracks,
1532
0
       number_of_session_entries,
1533
0
       error ) != 1 )
1534
0
  {
1535
0
    libcerror_error_set(
1536
0
     error,
1537
0
     LIBCERROR_ERROR_DOMAIN_IO,
1538
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1539
0
     "%s: unable to write section data.",
1540
0
     function );
1541
1542
0
    goto on_error;
1543
0
  }
1544
0
  write_count = libewf_section_write_data(
1545
0
                 section_descriptor,
1546
0
                 io_handle,
1547
0
                 file_io_pool,
1548
0
                 file_io_pool_entry,
1549
0
                 section_data,
1550
0
                 section_data_size,
1551
0
                 error );
1552
1553
0
  if( write_count == -1 )
1554
0
  {
1555
0
    libcerror_error_set(
1556
0
     error,
1557
0
     LIBCERROR_ERROR_DOMAIN_IO,
1558
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
1559
0
     "%s: unable to write section data.",
1560
0
     function );
1561
1562
0
    goto on_error;
1563
0
  }
1564
0
  total_write_count += write_count;
1565
1566
0
  memory_free(
1567
0
   section_data );
1568
1569
0
  section_data = NULL;
1570
1571
0
  if( format_version == 2 )
1572
0
  {
1573
0
    write_count = libewf_section_descriptor_write_file_io_pool(
1574
0
             section_descriptor,
1575
0
             file_io_pool,
1576
0
             file_io_pool_entry,
1577
0
             format_version,
1578
0
             error );
1579
1580
0
    if( write_count != (ssize_t) section_descriptor_data_size )
1581
0
    {
1582
0
      libcerror_error_set(
1583
0
       error,
1584
0
       LIBCERROR_ERROR_DOMAIN_IO,
1585
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
1586
0
       "%s: unable to write section descriptor data.",
1587
0
       function );
1588
1589
0
      goto on_error;
1590
0
    }
1591
0
    total_write_count += write_count;
1592
0
  }
1593
0
  return( total_write_count );
1594
1595
0
on_error:
1596
0
  if( section_data != NULL )
1597
0
  {
1598
0
    memory_free(
1599
0
     section_data );
1600
0
  }
1601
0
  return( -1 );
1602
0
}
1603