Coverage Report

Created: 2023-06-07 06:53

/src/libewf/libewf/libewf_filename.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Filename functions
3
 *
4
 * Copyright (C) 2006-2023, 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 <narrow_string.h>
25
#include <system_string.h>
26
#include <types.h>
27
#include <wide_string.h>
28
29
#include "libewf_definitions.h"
30
#include "libewf_filename.h"
31
#include "libewf_libcerror.h"
32
33
/* Sets the extension for a certain segment file
34
 * Using the format specific naming schema
35
 * Returns 1 on success or -1 on error
36
 */
37
int libewf_filename_set_extension(
38
     char *filename,
39
     size_t filename_size,
40
     size_t *filename_index,
41
     uint32_t segment_number,
42
     uint32_t maximum_number_of_segments,
43
     uint8_t segment_file_type,
44
     uint8_t format,
45
     libcerror_error_t **error )
46
0
{
47
0
  static char *function           = "libewf_filename_set_extension";
48
0
  size_t minimum_filename_size    = 0;
49
0
  size_t string_index             = 0;
50
0
  uint32_t maximum_segment_number = 0;
51
0
  char additional_characters      = 0;
52
0
  char first_character            = 0;
53
54
0
  if( filename == NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60
0
     "%s: invalid filename.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
0
  if( ( filename_size == 0 )
66
0
   || ( filename_size > (size_t) SSIZE_MAX ) )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
72
0
     "%s: invalid filename size value out of bounds.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
0
  if( filename_index == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
83
0
     "%s: invalid filename index.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
0
  string_index = *filename_index;
89
90
0
  if( ( segment_number == 0 )
91
0
   || ( segment_number > maximum_number_of_segments ) )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
96
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
97
0
     "%s: segment number: %" PRIu32 " is out of bounds.",
98
0
     function,
99
0
     segment_number );
100
101
0
    return( -1 );
102
0
  }
103
0
  if( ( format == LIBEWF_FORMAT_EWF )
104
0
   || ( format == LIBEWF_FORMAT_EWFX ) )
105
0
  {
106
0
    first_character       = 'e';
107
0
    additional_characters = 'a';
108
0
  }
109
0
  else if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1 )
110
0
        || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 ) )
111
0
  {
112
0
    first_character       = 'E';
113
0
    additional_characters = 'A';
114
0
  }
115
0
  else if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_LOGICAL )
116
0
        || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
117
0
  {
118
0
    first_character       = 'L';
119
0
    additional_characters = 'A';
120
0
  }
121
0
  else if( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_SMART )
122
0
  {
123
0
    first_character       = 's';
124
0
    additional_characters = 'a';
125
0
  }
126
0
  else
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
131
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
132
0
     "%s: unsupported segment file type.",
133
0
     function );
134
135
0
    return( -1 );
136
0
  }
137
0
  if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 )
138
0
   || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
139
0
  {
140
0
    minimum_filename_size  = 6;
141
0
    maximum_segment_number = 3;
142
0
  }
143
0
  else
144
0
  {
145
0
    minimum_filename_size  = 5;
146
0
    maximum_segment_number = 25;
147
0
  }
148
0
  if( filename_size < minimum_filename_size )
149
0
  {
150
0
    libcerror_error_set(
151
0
     error,
152
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
153
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
154
0
     "%s: invalid filename size value out of bounds.",
155
0
     function );
156
157
0
    return( -1 );
158
0
  }
159
0
  minimum_filename_size -= 1;
160
161
0
  if( string_index > ( filename_size - minimum_filename_size ) )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
166
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
167
0
     "%s: filename index value is out of bounds.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
0
  filename[ string_index ] = first_character;
173
174
0
  if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 )
175
0
   || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
176
0
  {
177
0
    filename[ ++string_index ] = 'x';
178
0
  }
179
0
  if( segment_number <= 99 )
180
0
  {
181
0
    filename[ string_index + 2 ] = '0' + (char) ( segment_number % 10 );
182
0
    filename[ string_index + 1 ] = '0' + (char) ( segment_number / 10 );
183
0
  }
184
0
  else if( segment_number >= 100 )
185
0
  {
186
0
    segment_number -= 100;
187
188
0
    filename[ string_index + 2 ] = additional_characters + (char) ( segment_number % 26 );
189
0
    segment_number              /= 26;
190
191
0
    filename[ string_index + 1 ] = additional_characters + (char) ( segment_number % 26 );
192
0
    segment_number              /= 26;
193
194
0
    if( segment_number > maximum_segment_number )
195
0
    {
196
0
      libcerror_error_set(
197
0
       error,
198
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
199
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
200
0
       "%s: unable to support for more segment files.",
201
0
       function );
202
203
0
      return( -1 );
204
0
    }
205
0
    filename[ string_index ] += (char) segment_number;
206
0
  }
207
  /* Safety check
208
   */
209
0
  if( ( filename[ string_index ] > 'z' )
210
0
   || ( ( filename[ string_index ] > 'Z' )
211
0
    &&  ( filename[ string_index ] < 'a' ) ) )
212
0
  {
213
0
    libcerror_error_set(
214
0
     error,
215
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
216
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
217
0
     "%s: unable to support for more segment files.",
218
0
     function );
219
220
0
    return( -1 );
221
0
  }
222
0
  string_index += 3;
223
224
0
  filename[ string_index++ ] = 0;
225
226
0
  *filename_index = string_index;
227
228
0
  return( 1 );
229
0
}
230
231
#if defined( HAVE_WIDE_CHARACTER_TYPE )
232
233
/* Sets the extension for a certain segment file
234
 * Using the format specific naming schema
235
 * Returns 1 on success or -1 on error
236
 */
237
int libewf_filename_set_extension_wide(
238
     wchar_t *filename,
239
     size_t filename_size,
240
     size_t *filename_index,
241
     uint32_t segment_number,
242
     uint32_t maximum_number_of_segments,
243
     uint8_t segment_file_type,
244
     uint8_t format,
245
     libcerror_error_t **error )
246
{
247
  static char *function           = "libewf_filename_set_extension_wide";
248
  size_t minimum_filename_size    = 0;
249
  size_t string_index             = 0;
250
  uint32_t maximum_segment_number = 0;
251
  wchar_t additional_characters   = 0;
252
  wchar_t first_character         = 0;
253
254
  if( filename == NULL )
255
  {
256
    libcerror_error_set(
257
     error,
258
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
259
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
260
     "%s: invalid filename.",
261
     function );
262
263
    return( -1 );
264
  }
265
  if( filename_size > (size_t) SSIZE_MAX )
266
  {
267
    libcerror_error_set(
268
     error,
269
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
270
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
271
     "%s: invalid filename size value exceeds maximum.",
272
     function );
273
274
    return( -1 );
275
  }
276
  if( filename_index == NULL )
277
  {
278
    libcerror_error_set(
279
     error,
280
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
281
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
282
     "%s: invalid filename index.",
283
     function );
284
285
    return( -1 );
286
  }
287
  string_index = *filename_index;
288
289
  if( ( segment_number == 0 )
290
   || ( segment_number > maximum_number_of_segments ) )
291
  {
292
    libcerror_error_set(
293
     error,
294
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
295
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
296
     "%s: segment number: %" PRIu32 " is out of bounds.",
297
     function,
298
     segment_number );
299
300
    return( -1 );
301
  }
302
  if( ( format == LIBEWF_FORMAT_EWF )
303
   || ( format == LIBEWF_FORMAT_EWFX ) )
304
  {
305
    first_character       = (wchar_t) 'e';
306
    additional_characters = (wchar_t) 'a';
307
  }
308
  else if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1 )
309
        || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 ) )
310
  {
311
    first_character       = (wchar_t) 'E';
312
    additional_characters = (wchar_t) 'A';
313
  }
314
  else if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_LOGICAL )
315
        || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
316
  {
317
    first_character       = (wchar_t) 'L';
318
    additional_characters = (wchar_t) 'A';
319
  }
320
  else if( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_SMART )
321
  {
322
    first_character       = (wchar_t) 's';
323
    additional_characters = (wchar_t) 'a';
324
  }
325
  else
326
  {
327
    libcerror_error_set(
328
     error,
329
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
330
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
331
     "%s: unsupported segment file type.",
332
     function );
333
334
    return( -1 );
335
  }
336
  if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 )
337
   || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
338
  {
339
    minimum_filename_size  = 6;
340
    maximum_segment_number = 3;
341
  }
342
  else
343
  {
344
    minimum_filename_size  = 5;
345
    maximum_segment_number = 25;
346
  }
347
  if( filename_size < minimum_filename_size )
348
  {
349
    libcerror_error_set(
350
     error,
351
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
353
     "%s: invalid filename size value out of bounds.",
354
     function );
355
356
    return( -1 );
357
  }
358
  minimum_filename_size -= 1;
359
360
  if( string_index > ( filename_size - minimum_filename_size ) )
361
  {
362
    libcerror_error_set(
363
     error,
364
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
365
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
366
     "%s: filename index value is out of bounds.",
367
     function );
368
369
    return( -1 );
370
  }
371
  filename[ string_index ] = first_character;
372
373
  if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 )
374
   || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
375
  {
376
    filename[ ++string_index ] = 'x';
377
  }
378
  if( segment_number <= 99 )
379
  {
380
    filename[ string_index + 2 ] = (wchar_t) '0' + (wchar_t) ( segment_number % 10 );
381
    filename[ string_index + 1 ] = (wchar_t) '0' + (wchar_t) ( segment_number / 10 );
382
  }
383
  else if( segment_number >= 100 )
384
  {
385
    segment_number -= 100;
386
387
    filename[ string_index + 2 ] = additional_characters + (wchar_t) ( segment_number % 26 );
388
    segment_number              /= 26;
389
390
    filename[ string_index + 1 ] = additional_characters + (wchar_t) ( segment_number % 26 );
391
    segment_number              /= 26;
392
393
    if( segment_number >= maximum_segment_number )
394
    {
395
      libcerror_error_set(
396
       error,
397
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
399
       "%s: unable to support for more segment files.",
400
       function );
401
402
      return( -1 );
403
    }
404
    filename[ string_index ] += (wchar_t) segment_number;
405
  }
406
  /* Safety check
407
   */
408
  if( ( filename[ string_index ] > (wchar_t) 'z' )
409
   || ( ( filename[ string_index ] > (wchar_t) 'Z' )
410
    &&  ( filename[ string_index ] < (wchar_t) 'a' ) ) )
411
  {
412
    libcerror_error_set(
413
     error,
414
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
415
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
416
     "%s: unable to support for more segment files.",
417
     function );
418
419
    return( -1 );
420
  }
421
  string_index += 3;
422
423
  filename[ string_index++ ] = 0;
424
425
  *filename_index = string_index;
426
427
  return( 1 );
428
}
429
430
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
431
432
/* Creates a filename for a certain segment file
433
 * Returns 1 if successful or -1 on error
434
 */
435
int libewf_filename_create(
436
     system_character_t **filename,
437
     size_t *filename_size,
438
     system_character_t *basename,
439
     size_t basename_length,
440
     uint32_t segment_number,
441
     uint32_t maximum_number_of_segments,
442
     uint8_t segment_file_type,
443
     uint8_t format,
444
     libcerror_error_t **error )
445
0
{
446
0
  system_character_t *safe_filename = NULL;
447
0
  static char *function             = "libewf_filename_create";
448
0
  size_t safe_filename_size         = 0;
449
450
0
  if( filename == NULL )
451
0
  {
452
0
    libcerror_error_set(
453
0
     error,
454
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
455
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
456
0
     "%s: invalid filename.",
457
0
     function );
458
459
0
    return( -1 );
460
0
  }
461
0
  if( *filename != NULL )
462
0
  {
463
0
    libcerror_error_set(
464
0
     error,
465
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
466
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
467
0
     "%s: filename already set.",
468
0
     function );
469
470
0
    return( -1 );
471
0
  }
472
0
  if( filename_size == NULL )
473
0
  {
474
0
    libcerror_error_set(
475
0
     error,
476
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
477
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
478
0
     "%s: invalid filename size.",
479
0
     function );
480
481
0
    return( -1 );
482
0
  }
483
0
  if( basename == NULL )
484
0
  {
485
0
    libcerror_error_set(
486
0
     error,
487
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
488
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
489
0
     "%s: invalid basename.",
490
0
     function );
491
492
0
    return( -1 );
493
0
  }
494
0
  if( ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2 )
495
0
   || ( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF2_LOGICAL ) )
496
0
  {
497
    /* The actual filename also contains a '.', 4 character extension and a end of string byte
498
     */
499
0
    safe_filename_size = basename_length + 6;
500
0
  }
501
0
  else
502
0
  {
503
    /* The actual filename also contains a '.', 3 character extension and a end of string byte
504
     */
505
0
    safe_filename_size = basename_length + 5;
506
0
  }
507
0
  safe_filename = system_string_allocate(
508
0
                   safe_filename_size );
509
510
0
  if( safe_filename == NULL )
511
0
  {
512
0
    libcerror_error_set(
513
0
     error,
514
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
515
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
516
0
     "%s: unable to create filename.",
517
0
     function );
518
519
0
    goto on_error;
520
0
  }
521
0
  if( system_string_copy(
522
0
       safe_filename,
523
0
       basename,
524
0
       basename_length ) == NULL )
525
0
  {
526
0
    libcerror_error_set(
527
0
     error,
528
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
529
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
530
0
     "%s: unable to set basename.",
531
0
     function );
532
533
0
    goto on_error;
534
0
  }
535
0
  safe_filename[ basename_length++ ] = (system_character_t) '.';
536
537
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
538
  if( libewf_filename_set_extension_wide(
539
       safe_filename,
540
       safe_filename_size,
541
       &basename_length,
542
       segment_number,
543
       maximum_number_of_segments,
544
       segment_file_type,
545
       format,
546
       error ) != 1 )
547
#else
548
0
  if( libewf_filename_set_extension(
549
0
       safe_filename,
550
0
       safe_filename_size,
551
0
       &basename_length,
552
0
       segment_number,
553
0
       maximum_number_of_segments,
554
0
       segment_file_type,
555
0
       format,
556
0
       error ) != 1 )
557
0
#endif
558
0
  {
559
0
    libcerror_error_set(
560
0
     error,
561
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
563
0
     "%s: unable to set extension.",
564
0
     function );
565
566
0
    goto on_error;
567
0
  }
568
0
  *filename      = safe_filename;
569
0
  *filename_size = safe_filename_size;
570
571
0
  return( 1 );
572
573
0
on_error:
574
0
  if( safe_filename != NULL )
575
0
  {
576
0
    memory_free(
577
0
     safe_filename );
578
0
  }
579
0
  return( -1 );
580
0
}
581