Coverage Report

Created: 2026-02-19 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsxfs/libfsxfs/libfsxfs_extended_attribute.c
Line
Count
Source
1
/*
2
 * Extended attribute 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_attribute_values.h"
27
#include "libfsxfs_attributes.h"
28
#include "libfsxfs_extended_attribute.h"
29
#include "libfsxfs_extent.h"
30
#include "libfsxfs_file_system.h"
31
#include "libfsxfs_inode.h"
32
#include "libfsxfs_io_handle.h"
33
#include "libfsxfs_libbfio.h"
34
#include "libfsxfs_libcerror.h"
35
#include "libfsxfs_libcnotify.h"
36
#include "libfsxfs_libcthreads.h"
37
#include "libfsxfs_libfdata.h"
38
#include "libfsxfs_types.h"
39
40
/* Creates an extended_attribute
41
 * Make sure the value extended_attribute is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libfsxfs_extended_attribute_initialize(
45
     libfsxfs_extended_attribute_t **extended_attribute,
46
     libfsxfs_io_handle_t *io_handle,
47
     libbfio_handle_t *file_io_handle,
48
     libfsxfs_file_system_t *file_system,
49
     libfsxfs_inode_t *inode,
50
     libfsxfs_attribute_values_t *attribute_values,
51
     libcerror_error_t **error )
52
0
{
53
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
54
0
  static char *function                                               = "libfsxfs_extended_attribute_initialize";
55
56
0
  if( extended_attribute == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid extended attribute.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
0
  if( *extended_attribute != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid extended attribute value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
0
  internal_extended_attribute = memory_allocate_structure(
79
0
                                 libfsxfs_internal_extended_attribute_t );
80
81
0
  if( internal_extended_attribute == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87
0
     "%s: unable to create extended attribute.",
88
0
     function );
89
90
0
    goto on_error;
91
0
  }
92
0
  if( memory_set(
93
0
       internal_extended_attribute,
94
0
       0,
95
0
       sizeof( libfsxfs_internal_extended_attribute_t ) ) == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
100
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
101
0
     "%s: unable to clear extended attribute.",
102
0
     function );
103
104
0
    memory_free(
105
0
     internal_extended_attribute );
106
107
0
    return( -1 );
108
0
  }
109
0
  internal_extended_attribute->io_handle        = io_handle;
110
0
  internal_extended_attribute->file_io_handle   = file_io_handle;
111
0
  internal_extended_attribute->file_system      = file_system;
112
0
  internal_extended_attribute->inode            = inode;
113
0
  internal_extended_attribute->attribute_values = attribute_values;
114
115
0
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSXFS )
116
0
  if( libcthreads_read_write_lock_initialize(
117
0
       &( internal_extended_attribute->read_write_lock ),
118
0
       error ) != 1 )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
123
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
124
0
     "%s: unable to initialize read/write lock.",
125
0
     function );
126
127
0
    goto on_error;
128
0
  }
129
0
#endif
130
0
  *extended_attribute = (libfsxfs_extended_attribute_t *) internal_extended_attribute;
131
132
0
  return( 1 );
133
134
0
on_error:
135
0
  if( internal_extended_attribute != NULL )
136
0
  {
137
0
    memory_free(
138
0
     internal_extended_attribute );
139
0
  }
140
0
  return( -1 );
141
0
}
142
143
/* Frees an extended attribute
144
 * Returns 1 if successful or -1 on error
145
 */
146
int libfsxfs_extended_attribute_free(
147
     libfsxfs_extended_attribute_t **extended_attribute,
148
     libcerror_error_t **error )
149
0
{
150
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
151
0
  static char *function                                               = "libfsxfs_extended_attribute_free";
152
0
  int result                                                          = 1;
153
154
0
  if( extended_attribute == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid extended attribute.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
0
  if( *extended_attribute != NULL )
166
0
  {
167
0
    internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) *extended_attribute;
168
0
    *extended_attribute         = NULL;
169
170
0
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSXFS )
171
0
    if( libcthreads_read_write_lock_free(
172
0
         &( internal_extended_attribute->read_write_lock ),
173
0
         error ) != 1 )
174
0
    {
175
0
      libcerror_error_set(
176
0
       error,
177
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
178
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
179
0
       "%s: unable to free read/write lock.",
180
0
       function );
181
182
0
      result = -1;
183
0
    }
184
0
#endif
185
0
    if( internal_extended_attribute->data_stream != NULL )
186
0
    {
187
0
      if( libfdata_stream_free(
188
0
           &( internal_extended_attribute->data_stream ),
189
0
           error ) != 1 )
190
0
      {
191
0
        libcerror_error_set(
192
0
         error,
193
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
194
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
195
0
         "%s: unable to free data stream.",
196
0
         function );
197
198
0
        result = -1;
199
0
      }
200
0
    }
201
0
    memory_free(
202
0
     internal_extended_attribute );
203
0
  }
204
0
  return( result );
205
0
}
206
207
/* Retrieves the size of the UTF-8 encoded name
208
 * The returned size includes the end of string character
209
 * Returns 1 if successful or -1 on error
210
 */
211
int libfsxfs_extended_attribute_get_utf8_name_size(
212
     libfsxfs_extended_attribute_t *extended_attribute,
213
     size_t *utf8_string_size,
214
     libcerror_error_t **error )
215
0
{
216
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
217
0
  static char *function                                               = "libfsxfs_extended_attribute_get_utf8_name_size";
218
0
  int result                                                          = 1;
219
220
0
  if( extended_attribute == NULL )
221
0
  {
222
0
    libcerror_error_set(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
225
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
226
0
     "%s: invalid extended attribute.",
227
0
     function );
228
229
0
    return( -1 );
230
0
  }
231
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
232
233
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
234
0
  if( libcthreads_read_write_lock_grab_for_read(
235
0
       internal_extended_attribute->read_write_lock,
236
0
       error ) != 1 )
237
0
  {
238
0
    libcerror_error_set(
239
0
     error,
240
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
241
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
242
0
     "%s: unable to grab read/write lock for reading.",
243
0
     function );
244
245
0
    return( -1 );
246
0
  }
247
0
#endif
248
0
  if( libfsxfs_attribute_values_get_utf8_name_size(
249
0
       internal_extended_attribute->attribute_values,
250
0
       utf8_string_size,
251
0
       error ) != 1 )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
257
0
     "%s: unable to retrieve size of UTF-8 formatted name.",
258
0
     function );
259
260
0
    result = -1;
261
0
  }
262
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
263
0
  if( libcthreads_read_write_lock_release_for_read(
264
0
       internal_extended_attribute->read_write_lock,
265
0
       error ) != 1 )
266
0
  {
267
0
    libcerror_error_set(
268
0
     error,
269
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
270
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
271
0
     "%s: unable to release read/write lock for reading.",
272
0
     function );
273
274
0
    return( -1 );
275
0
  }
276
0
#endif
277
0
  return( result );
278
0
}
279
280
/* Retrieves the UTF-8 encoded name
281
 * The size should include the end of string character
282
 * Returns 1 if successful or -1 on error
283
 */
284
int libfsxfs_extended_attribute_get_utf8_name(
285
     libfsxfs_extended_attribute_t *extended_attribute,
286
     uint8_t *utf8_string,
287
     size_t utf8_string_size,
288
     libcerror_error_t **error )
289
0
{
290
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
291
0
  static char *function                                               = "libfsxfs_extended_attribute_get_utf8_name";
292
0
  int result                                                          = 1;
293
294
0
  if( extended_attribute == NULL )
295
0
  {
296
0
    libcerror_error_set(
297
0
     error,
298
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
299
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
300
0
     "%s: invalid extended attribute.",
301
0
     function );
302
303
0
    return( -1 );
304
0
  }
305
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
306
307
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
308
0
  if( libcthreads_read_write_lock_grab_for_read(
309
0
       internal_extended_attribute->read_write_lock,
310
0
       error ) != 1 )
311
0
  {
312
0
    libcerror_error_set(
313
0
     error,
314
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
316
0
     "%s: unable to grab read/write lock for reading.",
317
0
     function );
318
319
0
    return( -1 );
320
0
  }
321
0
#endif
322
0
  if( libfsxfs_attribute_values_get_utf8_name(
323
0
       internal_extended_attribute->attribute_values,
324
0
       utf8_string,
325
0
       utf8_string_size,
326
0
       error ) != 1 )
327
0
  {
328
0
    libcerror_error_set(
329
0
     error,
330
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
331
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
332
0
     "%s: unable to retrieve UTF-8 formatted name.",
333
0
     function );
334
335
0
    result = -1;
336
0
  }
337
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
338
0
  if( libcthreads_read_write_lock_release_for_read(
339
0
       internal_extended_attribute->read_write_lock,
340
0
       error ) != 1 )
341
0
  {
342
0
    libcerror_error_set(
343
0
     error,
344
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
345
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
346
0
     "%s: unable to release read/write lock for reading.",
347
0
     function );
348
349
0
    return( -1 );
350
0
  }
351
0
#endif
352
0
  return( result );
353
0
}
354
355
/* Retrieves the size of the UTF-16 encoded name
356
 * The returned size includes the end of string character
357
 * Returns 1 if successful or -1 on error
358
 */
359
int libfsxfs_extended_attribute_get_utf16_name_size(
360
     libfsxfs_extended_attribute_t *extended_attribute,
361
     size_t *utf16_string_size,
362
     libcerror_error_t **error )
363
0
{
364
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
365
0
  static char *function                                               = "libfsxfs_extended_attribute_get_utf16_name_size";
366
0
  int result                                                          = 1;
367
368
0
  if( extended_attribute == NULL )
369
0
  {
370
0
    libcerror_error_set(
371
0
     error,
372
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
373
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
374
0
     "%s: invalid extended attribute.",
375
0
     function );
376
377
0
    return( -1 );
378
0
  }
379
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
380
381
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
382
0
  if( libcthreads_read_write_lock_grab_for_read(
383
0
       internal_extended_attribute->read_write_lock,
384
0
       error ) != 1 )
385
0
  {
386
0
    libcerror_error_set(
387
0
     error,
388
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
389
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
390
0
     "%s: unable to grab read/write lock for reading.",
391
0
     function );
392
393
0
    return( -1 );
394
0
  }
395
0
#endif
396
0
  if( libfsxfs_attribute_values_get_utf16_name_size(
397
0
       internal_extended_attribute->attribute_values,
398
0
       utf16_string_size,
399
0
       error ) != 1 )
400
0
  {
401
0
    libcerror_error_set(
402
0
     error,
403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
404
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
405
0
     "%s: unable to retrieve size of UTF-16 formatted name.",
406
0
     function );
407
408
0
    result = -1;
409
0
  }
410
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
411
0
  if( libcthreads_read_write_lock_release_for_read(
412
0
       internal_extended_attribute->read_write_lock,
413
0
       error ) != 1 )
414
0
  {
415
0
    libcerror_error_set(
416
0
     error,
417
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
419
0
     "%s: unable to release read/write lock for reading.",
420
0
     function );
421
422
0
    return( -1 );
423
0
  }
424
0
#endif
425
0
  return( result );
426
0
}
427
428
/* Retrieves the UTF-16 encoded name
429
 * The size should include the end of string character
430
 * Returns 1 if successful or -1 on error
431
 */
432
int libfsxfs_extended_attribute_get_utf16_name(
433
     libfsxfs_extended_attribute_t *extended_attribute,
434
     uint16_t *utf16_string,
435
     size_t utf16_string_size,
436
     libcerror_error_t **error )
437
0
{
438
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
439
0
  static char *function                                               = "libfsxfs_extended_attribute_get_utf16_name";
440
0
  int result                                                          = 1;
441
442
0
  if( extended_attribute == NULL )
443
0
  {
444
0
    libcerror_error_set(
445
0
     error,
446
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
447
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
448
0
     "%s: invalid extended attribute.",
449
0
     function );
450
451
0
    return( -1 );
452
0
  }
453
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
454
455
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
456
0
  if( libcthreads_read_write_lock_grab_for_read(
457
0
       internal_extended_attribute->read_write_lock,
458
0
       error ) != 1 )
459
0
  {
460
0
    libcerror_error_set(
461
0
     error,
462
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
463
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
464
0
     "%s: unable to grab read/write lock for reading.",
465
0
     function );
466
467
0
    return( -1 );
468
0
  }
469
0
#endif
470
0
  if( libfsxfs_attribute_values_get_utf16_name(
471
0
       internal_extended_attribute->attribute_values,
472
0
       utf16_string,
473
0
       utf16_string_size,
474
0
       error ) != 1 )
475
0
  {
476
0
    libcerror_error_set(
477
0
     error,
478
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
479
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
480
0
     "%s: unable to retrieve UTF-16 formatted name.",
481
0
     function );
482
483
0
    result = -1;
484
0
  }
485
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
486
0
  if( libcthreads_read_write_lock_release_for_read(
487
0
       internal_extended_attribute->read_write_lock,
488
0
       error ) != 1 )
489
0
  {
490
0
    libcerror_error_set(
491
0
     error,
492
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
493
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
494
0
     "%s: unable to release read/write lock for reading.",
495
0
     function );
496
497
0
    return( -1 );
498
0
  }
499
0
#endif
500
0
  return( result );
501
0
}
502
503
/* Determines the data stream
504
 * Returns 1 if successful or -1 on error
505
 */
506
int libfsxfs_internal_extended_attribute_get_data_stream(
507
     libfsxfs_internal_extended_attribute_t *internal_extended_attribute,
508
     libcerror_error_t **error )
509
0
{
510
0
  static char *function = "libfsxfs_internal_extended_attribute_get_data_stream";
511
512
0
  if( internal_extended_attribute == NULL )
513
0
  {
514
0
    libcerror_error_set(
515
0
     error,
516
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
517
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
518
0
     "%s: invalid extended attribute.",
519
0
     function );
520
521
0
    return( -1 );
522
0
  }
523
0
  if( internal_extended_attribute->data_stream != NULL )
524
0
  {
525
0
    libcerror_error_set(
526
0
     error,
527
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
528
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
529
0
     "%s: invalid extended attribute - data stream value already set.",
530
0
     function );
531
532
0
    return( -1 );
533
0
  }
534
0
  if( libfsxfs_attributes_get_value_data_stream(
535
0
       internal_extended_attribute->io_handle,
536
0
       internal_extended_attribute->inode,
537
0
       internal_extended_attribute->attribute_values,
538
0
       &( internal_extended_attribute->data_stream ),
539
0
       error ) != 1 )
540
0
  {
541
0
    libcerror_error_set(
542
0
     error,
543
0
     LIBCERROR_ERROR_DOMAIN_IO,
544
0
     LIBCERROR_IO_ERROR_READ_FAILED,
545
0
     "%s: unable to retrieve value data stream.",
546
0
     function );
547
548
0
    return( -1 );
549
0
  }
550
0
  return( 1 );
551
0
}
552
553
/* Reads data at the current offset into a buffer
554
 * Returns the number of bytes read or -1 on error
555
 */
556
ssize_t libfsxfs_extended_attribute_read_buffer(
557
         libfsxfs_extended_attribute_t *extended_attribute,
558
         void *buffer,
559
         size_t buffer_size,
560
         libcerror_error_t **error )
561
0
{
562
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
563
0
  static char *function                                               = "libfsxfs_extended_attribute_read_buffer";
564
0
  ssize_t read_count                                                  = 0;
565
566
0
  if( extended_attribute == NULL )
567
0
  {
568
0
    libcerror_error_set(
569
0
     error,
570
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
571
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
572
0
     "%s: invalid extended attribute.",
573
0
     function );
574
575
0
    return( -1 );
576
0
  }
577
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
578
579
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
580
0
  if( libcthreads_read_write_lock_grab_for_write(
581
0
       internal_extended_attribute->read_write_lock,
582
0
       error ) != 1 )
583
0
  {
584
0
    libcerror_error_set(
585
0
     error,
586
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
587
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
588
0
     "%s: unable to grab read/write lock for writing.",
589
0
     function );
590
591
0
    return( -1 );
592
0
  }
593
0
#endif
594
0
  if( internal_extended_attribute->data_stream == NULL )
595
0
  {
596
0
    if( libfsxfs_internal_extended_attribute_get_data_stream(
597
0
         internal_extended_attribute,
598
0
         error ) != 1 )
599
0
    {
600
0
      libcerror_error_set(
601
0
       error,
602
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
603
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
604
0
       "%s: unable to determine data stream.",
605
0
       function );
606
607
0
      read_count = -1;
608
0
    }
609
0
  }
610
0
  if( internal_extended_attribute->data_stream != NULL )
611
0
  {
612
0
    read_count = libfdata_stream_read_buffer(
613
0
                  internal_extended_attribute->data_stream,
614
0
                  (intptr_t *) internal_extended_attribute->file_io_handle,
615
0
                  (uint8_t *) buffer,
616
0
                  buffer_size,
617
0
                  0,
618
0
                  error );
619
620
0
    if( read_count < 0 )
621
0
    {
622
0
      libcerror_error_set(
623
0
       error,
624
0
       LIBCERROR_ERROR_DOMAIN_IO,
625
0
       LIBCERROR_IO_ERROR_READ_FAILED,
626
0
       "%s: unable to read buffer from data stream.",
627
0
       function );
628
629
0
      read_count = -1;
630
0
    }
631
0
  }
632
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
633
0
  if( libcthreads_read_write_lock_release_for_write(
634
0
       internal_extended_attribute->read_write_lock,
635
0
       error ) != 1 )
636
0
  {
637
0
    libcerror_error_set(
638
0
     error,
639
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
640
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
641
0
     "%s: unable to release read/write lock for writing.",
642
0
     function );
643
644
0
    return( -1 );
645
0
  }
646
0
#endif
647
0
  return( read_count );
648
0
}
649
650
/* Reads data at a specific offset
651
 * Returns the number of bytes read or -1 on error
652
 */
653
ssize_t libfsxfs_extended_attribute_read_buffer_at_offset(
654
         libfsxfs_extended_attribute_t *extended_attribute,
655
         void *buffer,
656
         size_t buffer_size,
657
         off64_t offset,
658
         libcerror_error_t **error )
659
0
{
660
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
661
0
  static char *function                                               = "libfsxfs_extended_attribute_read_buffer_at_offset";
662
0
  ssize_t read_count                                                  = 0;
663
664
0
  if( extended_attribute == NULL )
665
0
  {
666
0
    libcerror_error_set(
667
0
     error,
668
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
669
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
670
0
     "%s: invalid extended attribute.",
671
0
     function );
672
673
0
    return( -1 );
674
0
  }
675
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
676
677
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
678
0
  if( libcthreads_read_write_lock_grab_for_write(
679
0
       internal_extended_attribute->read_write_lock,
680
0
       error ) != 1 )
681
0
  {
682
0
    libcerror_error_set(
683
0
     error,
684
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
685
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
686
0
     "%s: unable to grab read/write lock for writing.",
687
0
     function );
688
689
0
    return( -1 );
690
0
  }
691
0
#endif
692
0
  if( internal_extended_attribute->data_stream == NULL )
693
0
  {
694
0
    if( libfsxfs_internal_extended_attribute_get_data_stream(
695
0
         internal_extended_attribute,
696
0
         error ) != 1 )
697
0
    {
698
0
      libcerror_error_set(
699
0
       error,
700
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
701
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
702
0
       "%s: unable to determine data stream.",
703
0
       function );
704
705
0
      read_count = -1;
706
0
    }
707
0
  }
708
0
  if( internal_extended_attribute->data_stream != NULL )
709
0
  {
710
0
    read_count = libfdata_stream_read_buffer_at_offset(
711
0
                  internal_extended_attribute->data_stream,
712
0
                  (intptr_t *) internal_extended_attribute->file_io_handle,
713
0
                  (uint8_t *) buffer,
714
0
                  buffer_size,
715
0
                  offset,
716
0
                  0,
717
0
                  error );
718
719
0
    if( read_count < 0 )
720
0
    {
721
0
      libcerror_error_set(
722
0
       error,
723
0
       LIBCERROR_ERROR_DOMAIN_IO,
724
0
       LIBCERROR_IO_ERROR_READ_FAILED,
725
0
       "%s: unable to read buffer at offset from data stream.",
726
0
       function );
727
728
0
      read_count = -1;
729
0
    }
730
0
  }
731
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
732
0
  if( libcthreads_read_write_lock_release_for_write(
733
0
       internal_extended_attribute->read_write_lock,
734
0
       error ) != 1 )
735
0
  {
736
0
    libcerror_error_set(
737
0
     error,
738
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
739
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
740
0
     "%s: unable to release read/write lock for writing.",
741
0
     function );
742
743
0
    return( -1 );
744
0
  }
745
0
#endif
746
0
  return( read_count );
747
0
}
748
749
/* Seeks a certain offset
750
 * Returns the offset if seek is successful or -1 on error
751
 */
752
off64_t libfsxfs_extended_attribute_seek_offset(
753
         libfsxfs_extended_attribute_t *extended_attribute,
754
         off64_t offset,
755
         int whence,
756
         libcerror_error_t **error )
757
0
{
758
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
759
0
  static char *function                                               = "libfsxfs_extended_attribute_seek_offset";
760
761
0
  if( extended_attribute == NULL )
762
0
  {
763
0
    libcerror_error_set(
764
0
     error,
765
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
766
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
767
0
     "%s: invalid extended attribute.",
768
0
     function );
769
770
0
    return( -1 );
771
0
  }
772
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
773
774
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
775
0
  if( libcthreads_read_write_lock_grab_for_write(
776
0
       internal_extended_attribute->read_write_lock,
777
0
       error ) != 1 )
778
0
  {
779
0
    libcerror_error_set(
780
0
     error,
781
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
782
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
783
0
     "%s: unable to grab read/write lock for writing.",
784
0
     function );
785
786
0
    return( -1 );
787
0
  }
788
0
#endif
789
0
  if( internal_extended_attribute->data_stream == NULL )
790
0
  {
791
0
    if( libfsxfs_internal_extended_attribute_get_data_stream(
792
0
         internal_extended_attribute,
793
0
         error ) != 1 )
794
0
    {
795
0
      libcerror_error_set(
796
0
       error,
797
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
798
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
799
0
       "%s: unable to determine data stream.",
800
0
       function );
801
802
0
      offset = -1;
803
0
    }
804
0
  }
805
0
  if( internal_extended_attribute->data_stream != NULL )
806
0
  {
807
0
    offset = libfdata_stream_seek_offset(
808
0
              internal_extended_attribute->data_stream,
809
0
              offset,
810
0
              whence,
811
0
              error );
812
813
0
    if( offset < 0 )
814
0
    {
815
0
      libcerror_error_set(
816
0
       error,
817
0
       LIBCERROR_ERROR_DOMAIN_IO,
818
0
       LIBCERROR_IO_ERROR_SEEK_FAILED,
819
0
       "%s: unable to seek offset in data stream.",
820
0
       function );
821
822
0
      offset = -1;
823
0
    }
824
0
  }
825
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
826
0
  if( libcthreads_read_write_lock_release_for_write(
827
0
       internal_extended_attribute->read_write_lock,
828
0
       error ) != 1 )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
834
0
     "%s: unable to release read/write lock for writing.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
0
#endif
840
0
  return( offset );
841
0
}
842
843
/* Retrieves the current offset
844
 * Returns the offset if successful or -1 on error
845
 */
846
int libfsxfs_extended_attribute_get_offset(
847
     libfsxfs_extended_attribute_t *extended_attribute,
848
     off64_t *offset,
849
     libcerror_error_t **error )
850
0
{
851
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
852
0
  static char *function                                               = "libfsxfs_extended_attribute_get_offset";
853
0
  int result                                                          = 1;
854
855
0
  if( extended_attribute == NULL )
856
0
  {
857
0
    libcerror_error_set(
858
0
     error,
859
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
860
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
861
0
     "%s: invalid extended attribute.",
862
0
     function );
863
864
0
    return( -1 );
865
0
  }
866
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
867
868
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
869
0
  if( libcthreads_read_write_lock_grab_for_write(
870
0
       internal_extended_attribute->read_write_lock,
871
0
       error ) != 1 )
872
0
  {
873
0
    libcerror_error_set(
874
0
     error,
875
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
876
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
877
0
     "%s: unable to grab read/write lock for writing.",
878
0
     function );
879
880
0
    return( -1 );
881
0
  }
882
0
#endif
883
0
  if( internal_extended_attribute->data_stream == NULL )
884
0
  {
885
0
    if( libfsxfs_internal_extended_attribute_get_data_stream(
886
0
         internal_extended_attribute,
887
0
         error ) != 1 )
888
0
    {
889
0
      libcerror_error_set(
890
0
       error,
891
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
892
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
893
0
       "%s: unable to determine data stream.",
894
0
       function );
895
896
0
      result = -1;
897
0
    }
898
0
  }
899
0
  if( internal_extended_attribute->data_stream != NULL )
900
0
  {
901
0
    if( libfdata_stream_get_offset(
902
0
         internal_extended_attribute->data_stream,
903
0
         offset,
904
0
         error ) != 1 )
905
0
    {
906
0
      libcerror_error_set(
907
0
       error,
908
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
909
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
910
0
       "%s: unable to retrieve offset from data stream.",
911
0
       function );
912
913
0
      result = -1;
914
0
    }
915
0
  }
916
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
917
0
  if( libcthreads_read_write_lock_release_for_write(
918
0
       internal_extended_attribute->read_write_lock,
919
0
       error ) != 1 )
920
0
  {
921
0
    libcerror_error_set(
922
0
     error,
923
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
924
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
925
0
     "%s: unable to release read/write lock for writing.",
926
0
     function );
927
928
0
    return( -1 );
929
0
  }
930
0
#endif
931
0
  return( result );
932
0
}
933
934
/* Retrieves the size of the data stream object
935
 * Returns 1 if successful or -1 on error
936
 */
937
int libfsxfs_extended_attribute_get_size(
938
     libfsxfs_extended_attribute_t *extended_attribute,
939
     size64_t *size,
940
     libcerror_error_t **error )
941
0
{
942
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
943
0
  static char *function                                               = "libfsxfs_extended_attribute_get_size";
944
945
0
  if( extended_attribute == NULL )
946
0
  {
947
0
    libcerror_error_set(
948
0
     error,
949
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
950
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
951
0
     "%s: invalid extended attribute.",
952
0
     function );
953
954
0
    return( -1 );
955
0
  }
956
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
957
958
0
  if( internal_extended_attribute->attribute_values == NULL )
959
0
  {
960
0
    libcerror_error_set(
961
0
     error,
962
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
963
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
964
0
     "%s: invalid extended attribute - missing attribute values.",
965
0
     function );
966
967
0
    return( -1 );
968
0
  }
969
0
  if( size == NULL )
970
0
  {
971
0
    libcerror_error_set(
972
0
     error,
973
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
974
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
975
0
     "%s: invalid size.",
976
0
     function );
977
978
0
    return( -1 );
979
0
  }
980
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
981
0
  if( libcthreads_read_write_lock_grab_for_write(
982
0
       internal_extended_attribute->read_write_lock,
983
0
       error ) != 1 )
984
0
  {
985
0
    libcerror_error_set(
986
0
     error,
987
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
988
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
989
0
     "%s: unable to grab read/write lock for writing.",
990
0
     function );
991
992
0
    return( -1 );
993
0
  }
994
0
#endif
995
0
  *size = (size64_t) internal_extended_attribute->attribute_values->value_data_size;
996
997
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
998
0
  if( libcthreads_read_write_lock_release_for_write(
999
0
       internal_extended_attribute->read_write_lock,
1000
0
       error ) != 1 )
1001
0
  {
1002
0
    libcerror_error_set(
1003
0
     error,
1004
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1005
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1006
0
     "%s: unable to release read/write lock for writing.",
1007
0
     function );
1008
1009
0
    return( -1 );
1010
0
  }
1011
0
#endif
1012
0
  return( 1 );
1013
0
}
1014
1015
/* Retrieves the number of extents
1016
 * Returns 1 if successful or -1 on error
1017
 */
1018
int libfsxfs_extended_attribute_get_number_of_extents(
1019
     libfsxfs_extended_attribute_t *extended_attribute,
1020
     int *number_of_extents,
1021
     libcerror_error_t **error )
1022
0
{
1023
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1024
0
  static char *function                                               = "libfsxfs_extended_attribute_get_number_of_extents";
1025
0
  int result                                                          = 1;
1026
1027
0
  if( extended_attribute == NULL )
1028
0
  {
1029
0
    libcerror_error_set(
1030
0
     error,
1031
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1032
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1033
0
     "%s: invalid extended attribute.",
1034
0
     function );
1035
1036
0
    return( -1 );
1037
0
  }
1038
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
1039
1040
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
1041
0
  if( libcthreads_read_write_lock_grab_for_write(
1042
0
       internal_extended_attribute->read_write_lock,
1043
0
       error ) != 1 )
1044
0
  {
1045
0
    libcerror_error_set(
1046
0
     error,
1047
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1048
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1049
0
     "%s: unable to grab read/write lock for writing.",
1050
0
     function );
1051
1052
0
    return( -1 );
1053
0
  }
1054
0
#endif
1055
0
  if( libfsxfs_inode_get_number_of_attributes_extents(
1056
0
       internal_extended_attribute->inode,
1057
0
       number_of_extents,
1058
0
       error ) != 1 )
1059
0
  {
1060
0
    libcerror_error_set(
1061
0
     error,
1062
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1063
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1064
0
     "%s: unable to retrieve number of attribute extents.",
1065
0
     function );
1066
1067
0
    result = -1;
1068
0
  }
1069
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
1070
0
  if( libcthreads_read_write_lock_release_for_write(
1071
0
       internal_extended_attribute->read_write_lock,
1072
0
       error ) != 1 )
1073
0
  {
1074
0
    libcerror_error_set(
1075
0
     error,
1076
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1077
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1078
0
     "%s: unable to release read/write lock for writing.",
1079
0
     function );
1080
1081
0
    return( -1 );
1082
0
  }
1083
0
#endif
1084
0
  return( result );
1085
0
}
1086
1087
/* Retrieves a specific extent
1088
 * Returns 1 if successful or -1 on error
1089
 */
1090
int libfsxfs_extended_attribute_get_extent_by_index(
1091
     libfsxfs_extended_attribute_t *extended_attribute,
1092
     int extent_index,
1093
     off64_t *extent_offset,
1094
     size64_t *extent_size,
1095
     uint32_t *extent_flags,
1096
     libcerror_error_t **error )
1097
0
{
1098
0
  libfsxfs_extent_t *extent                                           = NULL;
1099
0
  libfsxfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1100
0
  static char *function                                               = "libfsxfs_extended_attribute_get_extent_by_index";
1101
0
  int result                                                          = 1;
1102
1103
0
  if( extended_attribute == NULL )
1104
0
  {
1105
0
    libcerror_error_set(
1106
0
     error,
1107
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1108
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1109
0
     "%s: invalid extended attribute.",
1110
0
     function );
1111
1112
0
    return( -1 );
1113
0
  }
1114
0
  internal_extended_attribute = (libfsxfs_internal_extended_attribute_t *) extended_attribute;
1115
1116
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
1117
0
  if( libcthreads_read_write_lock_grab_for_write(
1118
0
       internal_extended_attribute->read_write_lock,
1119
0
       error ) != 1 )
1120
0
  {
1121
0
    libcerror_error_set(
1122
0
     error,
1123
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1124
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1125
0
     "%s: unable to grab read/write lock for writing.",
1126
0
     function );
1127
1128
0
    return( -1 );
1129
0
  }
1130
0
#endif
1131
0
  if( libfsxfs_inode_get_attributes_extent_by_index(
1132
0
       internal_extended_attribute->inode,
1133
0
       extent_index,
1134
0
       &extent,
1135
0
       error ) != 1 )
1136
0
  {
1137
0
    libcerror_error_set(
1138
0
     error,
1139
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1140
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1141
0
     "%s: unable to retrieve attribute extent: %d.",
1142
0
     function,
1143
0
     extent_index );
1144
1145
0
    result = -1;
1146
0
  }
1147
0
  if( result == 1 )
1148
0
  {
1149
0
    if( libfsxfs_extent_get_values(
1150
0
         extent,
1151
0
         internal_extended_attribute->io_handle,
1152
0
         extent_offset,
1153
0
         extent_size,
1154
0
         extent_flags,
1155
0
         error ) != 1 )
1156
0
    {
1157
0
      libcerror_error_set(
1158
0
       error,
1159
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1160
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1161
0
       "%s: unable to retrieve extent: %d values.",
1162
0
       function,
1163
0
       extent_index );
1164
1165
0
      result = -1;
1166
0
    }
1167
0
  }
1168
0
#if defined( HAVE_LIBFSXFS_MULTI_THREAD_SUPPORT )
1169
0
  if( libcthreads_read_write_lock_release_for_write(
1170
0
       internal_extended_attribute->read_write_lock,
1171
0
       error ) != 1 )
1172
0
  {
1173
0
    libcerror_error_set(
1174
0
     error,
1175
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1177
0
     "%s: unable to release read/write lock for writing.",
1178
0
     function );
1179
1180
0
    return( -1 );
1181
0
  }
1182
0
#endif
1183
0
  return( result );
1184
0
}
1185