1 /*
2  * List element functions
3  *
4  * Copyright (C) 2006-2020, 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 "libcdata_libcerror.h"
27 #include "libcdata_libcthreads.h"
28 #include "libcdata_list_element.h"
29 #include "libcdata_types.h"
30 
31 /* Creates a list element
32  * Make sure the value element is referencing, is set to NULL
33  * Returns 1 if successful or -1 on error
34  */
libcdata_list_element_initialize(libcdata_list_element_t ** element,libcerror_error_t ** error)35 int libcdata_list_element_initialize(
36      libcdata_list_element_t **element,
37      libcerror_error_t **error )
38 {
39 	libcdata_internal_list_element_t *internal_element = NULL;
40 	static char *function                              = "libcdata_list_element_initialize";
41 
42 	if( element == NULL )
43 	{
44 		libcerror_error_set(
45 		 error,
46 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
47 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
48 		 "%s: invalid list element.",
49 		 function );
50 
51 		return( -1 );
52 	}
53 	if( *element != NULL )
54 	{
55 		libcerror_error_set(
56 		 error,
57 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
58 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
59 		 "%s: invalid element value already set.",
60 		 function );
61 
62 		return( -1 );
63 	}
64 	internal_element = memory_allocate_structure(
65 	                    libcdata_internal_list_element_t );
66 
67 	if( internal_element == NULL )
68 	{
69 		libcerror_error_set(
70 		 error,
71 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
72 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
73 		 "%s: unable to create list element.",
74 		 function );
75 
76 		goto on_error;
77 	}
78 	if( memory_set(
79 	     internal_element,
80 	     0,
81 	     sizeof( libcdata_internal_list_element_t ) ) == NULL )
82 	{
83 		libcerror_error_set(
84 		 error,
85 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
86 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
87 		 "%s: unable to clear list element.",
88 		 function );
89 
90 		memory_free(
91 		 internal_element );
92 
93 		return( -1 );
94 	}
95 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
96 	if( libcthreads_read_write_lock_initialize(
97 	     &( internal_element->read_write_lock ),
98 	     error ) != 1 )
99 	{
100 		libcerror_error_set(
101 		 error,
102 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
103 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
104 		 "%s: unable to initialize read/write lock.",
105 		 function );
106 
107 		goto on_error;
108 	}
109 #endif
110 	*element = (libcdata_list_element_t *) internal_element;
111 
112 	return( 1 );
113 
114 on_error:
115 	if( internal_element != NULL )
116 	{
117 		memory_free(
118 		 internal_element );
119 	}
120 	return( -1 );
121 }
122 
123 /* Frees a list element
124  * Uses the value_free_function to free the element value
125  * Returns 1 if successful or -1 on error
126  */
libcdata_list_element_free(libcdata_list_element_t ** element,int (* value_free_function)(intptr_t ** value,libcerror_error_t ** error),libcerror_error_t ** error)127 int libcdata_list_element_free(
128      libcdata_list_element_t **element,
129      int (*value_free_function)(
130             intptr_t **value,
131             libcerror_error_t **error ),
132      libcerror_error_t **error )
133 {
134 	libcdata_internal_list_element_t *internal_element = NULL;
135 	static char *function                              = "libcdata_list_element_free";
136 	int result                                         = 1;
137 
138 	if( element == NULL )
139 	{
140 		libcerror_error_set(
141 		 error,
142 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
144 		 "%s: invalid list element.",
145 		 function );
146 
147 		return( -1 );
148 	}
149 	if( *element != NULL )
150 	{
151 		internal_element = (libcdata_internal_list_element_t *) *element;
152 
153 		if( ( internal_element->previous_element != NULL )
154 		 || ( internal_element->next_element != NULL ) )
155 		{
156 			libcerror_error_set(
157 			 error,
158 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
159 			 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
160 			 "%s: list element part of a list.",
161 			 function );
162 
163 			return( -1 );
164 		}
165 		*element = NULL;
166 
167 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
168 		if( libcthreads_read_write_lock_free(
169 		     &( internal_element->read_write_lock ),
170 		     error ) != 1 )
171 		{
172 			libcerror_error_set(
173 			 error,
174 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
175 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
176 			 "%s: unable to free read/write lock.",
177 			 function );
178 
179 			result = -1;
180 		}
181 #endif
182 		if( value_free_function != NULL )
183 		{
184 			if( value_free_function(
185 			     &( internal_element->value ),
186 			     error ) != 1 )
187 			{
188 				libcerror_error_set(
189 				 error,
190 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
191 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
192 				 "%s: unable to free value.",
193 				 function );
194 
195 				result = -1;
196 			}
197 		}
198 		memory_free(
199 		 internal_element );
200 	}
201 	return( result );
202 }
203 
204 /* Retrieves the parent list from the list element
205  * Returns 1 if successful or -1 on error
206  */
libcdata_list_element_get_parent_list(libcdata_list_element_t * element,intptr_t ** parent_list,libcerror_error_t ** error)207 int libcdata_list_element_get_parent_list(
208      libcdata_list_element_t *element,
209      intptr_t **parent_list,
210      libcerror_error_t **error )
211 {
212 	libcdata_internal_list_element_t *internal_element = NULL;
213 	static char *function                              = "libcdata_list_element_get_parent_list";
214 
215 	if( element == NULL )
216 	{
217 		libcerror_error_set(
218 		 error,
219 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
221 		 "%s: invalid list element.",
222 		 function );
223 
224 		return( -1 );
225 	}
226 	internal_element = (libcdata_internal_list_element_t *) element;
227 
228 	if( parent_list == NULL )
229 	{
230 		libcerror_error_set(
231 		 error,
232 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
233 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
234 		 "%s: invalid parent list.",
235 		 function );
236 
237 		return( -1 );
238 	}
239 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
240 	if( libcthreads_read_write_lock_grab_for_read(
241 	     internal_element->read_write_lock,
242 	     error ) != 1 )
243 	{
244 		libcerror_error_set(
245 		 error,
246 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
247 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
248 		 "%s: unable to grab read/write lock for reading.",
249 		 function );
250 
251 		return( -1 );
252 	}
253 #endif
254 	*parent_list = internal_element->parent_list;
255 
256 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
257 	if( libcthreads_read_write_lock_release_for_read(
258 	     internal_element->read_write_lock,
259 	     error ) != 1 )
260 	{
261 		libcerror_error_set(
262 		 error,
263 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
264 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
265 		 "%s: unable to release read/write lock for reading.",
266 		 function );
267 
268 		return( -1 );
269 	}
270 #endif
271 	return( 1 );
272 }
273 
274 /* Sets the parent list in the list element
275  * Returns 1 if successful or -1 on error
276  */
libcdata_list_element_set_parent_list(libcdata_list_element_t * element,intptr_t * parent_list,libcerror_error_t ** error)277 int libcdata_list_element_set_parent_list(
278      libcdata_list_element_t *element,
279      intptr_t *parent_list,
280      libcerror_error_t **error )
281 {
282 	libcdata_internal_list_element_t *internal_element = NULL;
283 	static char *function                              = "libcdata_list_element_set_parent_list";
284 
285 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
286 	intptr_t *backup_parent_list                       = NULL;
287 #endif
288 
289 	if( element == NULL )
290 	{
291 		libcerror_error_set(
292 		 error,
293 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
294 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
295 		 "%s: invalid list element.",
296 		 function );
297 
298 		return( -1 );
299 	}
300 	internal_element = (libcdata_internal_list_element_t *) element;
301 
302 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
303 	if( libcthreads_read_write_lock_grab_for_write(
304 	     internal_element->read_write_lock,
305 	     error ) != 1 )
306 	{
307 		libcerror_error_set(
308 		 error,
309 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
310 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
311 		 "%s: unable to grab read/write lock for writing.",
312 		 function );
313 
314 		return( -1 );
315 	}
316 	backup_parent_list = internal_element->parent_list;
317 #endif
318 	internal_element->parent_list = parent_list;
319 
320 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
321 	if( libcthreads_read_write_lock_release_for_write(
322 	     internal_element->read_write_lock,
323 	     error ) != 1 )
324 	{
325 		libcerror_error_set(
326 		 error,
327 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
328 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
329 		 "%s: unable to release read/write lock for writing.",
330 		 function );
331 
332 		goto on_error;
333 	}
334 #endif
335 	return( 1 );
336 
337 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
338 on_error:
339 	internal_element->parent_list = backup_parent_list;
340 
341 	return( -1 );
342 #endif
343 }
344 
345 /* Retrieves the previous element from the list element
346  * Returns 1 if successful or -1 on error
347  */
libcdata_list_element_get_previous_element(libcdata_list_element_t * element,libcdata_list_element_t ** previous_element,libcerror_error_t ** error)348 int libcdata_list_element_get_previous_element(
349      libcdata_list_element_t *element,
350      libcdata_list_element_t **previous_element,
351      libcerror_error_t **error )
352 {
353 	libcdata_internal_list_element_t *internal_element = NULL;
354 	static char *function                              = "libcdata_list_element_get_previous_element";
355 
356 	if( element == NULL )
357 	{
358 		libcerror_error_set(
359 		 error,
360 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
361 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
362 		 "%s: invalid list element.",
363 		 function );
364 
365 		return( -1 );
366 	}
367 	internal_element = (libcdata_internal_list_element_t *) element;
368 
369 	if( previous_element == NULL )
370 	{
371 		libcerror_error_set(
372 		 error,
373 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
374 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
375 		 "%s: invalid previous element.",
376 		 function );
377 
378 		return( -1 );
379 	}
380 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
381 	if( libcthreads_read_write_lock_grab_for_read(
382 	     internal_element->read_write_lock,
383 	     error ) != 1 )
384 	{
385 		libcerror_error_set(
386 		 error,
387 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
388 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
389 		 "%s: unable to grab read/write lock for reading.",
390 		 function );
391 
392 		return( -1 );
393 	}
394 #endif
395 	*previous_element = internal_element->previous_element;
396 
397 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
398 	if( libcthreads_read_write_lock_release_for_read(
399 	     internal_element->read_write_lock,
400 	     error ) != 1 )
401 	{
402 		libcerror_error_set(
403 		 error,
404 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
405 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
406 		 "%s: unable to release read/write lock for reading.",
407 		 function );
408 
409 		return( -1 );
410 	}
411 #endif
412 	return( 1 );
413 }
414 
415 /* Sets the previous element in the list element
416  * Returns 1 if successful or -1 on error
417  */
libcdata_list_element_set_previous_element(libcdata_list_element_t * element,libcdata_list_element_t * previous_element,libcerror_error_t ** error)418 int libcdata_list_element_set_previous_element(
419      libcdata_list_element_t *element,
420      libcdata_list_element_t *previous_element,
421      libcerror_error_t **error )
422 {
423 	libcdata_internal_list_element_t *internal_element = NULL;
424 	static char *function                              = "libcdata_list_element_set_previous_element";
425 
426 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
427 	libcdata_list_element_t *backup_previous_element   = NULL;
428 #endif
429 
430 	if( element == NULL )
431 	{
432 		libcerror_error_set(
433 		 error,
434 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
435 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
436 		 "%s: invalid list element.",
437 		 function );
438 
439 		return( -1 );
440 	}
441 	internal_element = (libcdata_internal_list_element_t *) element;
442 
443 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
444 	if( libcthreads_read_write_lock_grab_for_write(
445 	     internal_element->read_write_lock,
446 	     error ) != 1 )
447 	{
448 		libcerror_error_set(
449 		 error,
450 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
451 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
452 		 "%s: unable to grab read/write lock for writing.",
453 		 function );
454 
455 		return( -1 );
456 	}
457 	backup_previous_element = internal_element->previous_element;
458 #endif
459 	internal_element->previous_element = previous_element;
460 
461 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
462 	if( libcthreads_read_write_lock_release_for_write(
463 	     internal_element->read_write_lock,
464 	     error ) != 1 )
465 	{
466 		libcerror_error_set(
467 		 error,
468 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
469 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
470 		 "%s: unable to release read/write lock for writing.",
471 		 function );
472 
473 		goto on_error;
474 	}
475 #endif
476 	return( 1 );
477 
478 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
479 on_error:
480 	internal_element->previous_element = backup_previous_element;
481 
482 	return( -1 );
483 #endif
484 }
485 
486 /* Retrieves the next element from the list element
487  * Returns 1 if successful or -1 on error
488  */
libcdata_list_element_get_next_element(libcdata_list_element_t * element,libcdata_list_element_t ** next_element,libcerror_error_t ** error)489 int libcdata_list_element_get_next_element(
490      libcdata_list_element_t *element,
491      libcdata_list_element_t **next_element,
492      libcerror_error_t **error )
493 {
494 	libcdata_internal_list_element_t *internal_element = NULL;
495 	static char *function                              = "libcdata_list_element_get_next_element";
496 
497 	if( element == NULL )
498 	{
499 		libcerror_error_set(
500 		 error,
501 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
502 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
503 		 "%s: invalid list element.",
504 		 function );
505 
506 		return( -1 );
507 	}
508 	internal_element = (libcdata_internal_list_element_t *) element;
509 
510 	if( next_element == NULL )
511 	{
512 		libcerror_error_set(
513 		 error,
514 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
515 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
516 		 "%s: invalid next element.",
517 		 function );
518 
519 		return( -1 );
520 	}
521 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
522 	if( libcthreads_read_write_lock_grab_for_read(
523 	     internal_element->read_write_lock,
524 	     error ) != 1 )
525 	{
526 		libcerror_error_set(
527 		 error,
528 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
529 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
530 		 "%s: unable to grab read/write lock for reading.",
531 		 function );
532 
533 		return( -1 );
534 	}
535 #endif
536 	*next_element = internal_element->next_element;
537 
538 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
539 	if( libcthreads_read_write_lock_release_for_read(
540 	     internal_element->read_write_lock,
541 	     error ) != 1 )
542 	{
543 		libcerror_error_set(
544 		 error,
545 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
546 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
547 		 "%s: unable to release read/write lock for reading.",
548 		 function );
549 
550 		return( -1 );
551 	}
552 #endif
553 	return( 1 );
554 }
555 
556 /* Sets the next element in the list element
557  * Returns 1 if successful or -1 on error
558  */
libcdata_list_element_set_next_element(libcdata_list_element_t * element,libcdata_list_element_t * next_element,libcerror_error_t ** error)559 int libcdata_list_element_set_next_element(
560      libcdata_list_element_t *element,
561      libcdata_list_element_t *next_element,
562      libcerror_error_t **error )
563 {
564 	libcdata_internal_list_element_t *internal_element = NULL;
565 	static char *function                              = "libcdata_list_element_set_next_element";
566 
567 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
568 	libcdata_list_element_t *backup_next_element       = NULL;
569 #endif
570 
571 	if( element == NULL )
572 	{
573 		libcerror_error_set(
574 		 error,
575 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
576 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
577 		 "%s: invalid list element.",
578 		 function );
579 
580 		return( -1 );
581 	}
582 	internal_element = (libcdata_internal_list_element_t *) element;
583 
584 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
585 	if( libcthreads_read_write_lock_grab_for_write(
586 	     internal_element->read_write_lock,
587 	     error ) != 1 )
588 	{
589 		libcerror_error_set(
590 		 error,
591 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
592 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
593 		 "%s: unable to grab read/write lock for writing.",
594 		 function );
595 
596 		return( -1 );
597 	}
598 	backup_next_element = internal_element->next_element;
599 #endif
600 	internal_element->next_element = next_element;
601 
602 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
603 	if( libcthreads_read_write_lock_release_for_write(
604 	     internal_element->read_write_lock,
605 	     error ) != 1 )
606 	{
607 		libcerror_error_set(
608 		 error,
609 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
610 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
611 		 "%s: unable to release read/write lock for writing.",
612 		 function );
613 
614 		goto on_error;
615 	}
616 #endif
617 	return( 1 );
618 
619 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
620 on_error:
621 	internal_element->next_element = backup_next_element;
622 
623 	return( -1 );
624 #endif
625 }
626 
627 /* Retrieves the previous and next element from the list element
628  * Returns 1 if successful or -1 on error
629  */
libcdata_list_element_get_elements(libcdata_list_element_t * element,libcdata_list_element_t ** previous_element,libcdata_list_element_t ** next_element,libcerror_error_t ** error)630 int libcdata_list_element_get_elements(
631      libcdata_list_element_t *element,
632      libcdata_list_element_t **previous_element,
633      libcdata_list_element_t **next_element,
634      libcerror_error_t **error )
635 {
636 	libcdata_internal_list_element_t *internal_element = NULL;
637 	static char *function                              = "libcdata_list_element_get_elements";
638 
639 	if( element == NULL )
640 	{
641 		libcerror_error_set(
642 		 error,
643 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
644 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
645 		 "%s: invalid list element.",
646 		 function );
647 
648 		return( -1 );
649 	}
650 	internal_element = (libcdata_internal_list_element_t *) element;
651 
652 	if( previous_element == NULL )
653 	{
654 		libcerror_error_set(
655 		 error,
656 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
657 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
658 		 "%s: invalid previous element.",
659 		 function );
660 
661 		return( -1 );
662 	}
663 	if( next_element == NULL )
664 	{
665 		libcerror_error_set(
666 		 error,
667 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
668 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
669 		 "%s: invalid next element.",
670 		 function );
671 
672 		return( -1 );
673 	}
674 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
675 	if( libcthreads_read_write_lock_grab_for_read(
676 	     internal_element->read_write_lock,
677 	     error ) != 1 )
678 	{
679 		libcerror_error_set(
680 		 error,
681 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
682 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
683 		 "%s: unable to grab read/write lock for reading.",
684 		 function );
685 
686 		return( -1 );
687 	}
688 #endif
689 	*previous_element = internal_element->previous_element;
690 	*next_element     = internal_element->next_element;
691 
692 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
693 	if( libcthreads_read_write_lock_release_for_read(
694 	     internal_element->read_write_lock,
695 	     error ) != 1 )
696 	{
697 		libcerror_error_set(
698 		 error,
699 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
700 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
701 		 "%s: unable to release read/write lock for reading.",
702 		 function );
703 
704 		return( -1 );
705 	}
706 #endif
707 	return( 1 );
708 }
709 
710 /* Sets the previous and next element in the list element
711  * Returns 1 if successful or -1 on error
712  */
libcdata_list_element_set_elements(libcdata_list_element_t * element,libcdata_list_element_t * previous_element,libcdata_list_element_t * next_element,libcerror_error_t ** error)713 int libcdata_list_element_set_elements(
714      libcdata_list_element_t *element,
715      libcdata_list_element_t *previous_element,
716      libcdata_list_element_t *next_element,
717      libcerror_error_t **error )
718 {
719 	libcdata_internal_list_element_t *internal_element = NULL;
720 	static char *function                              = "libcdata_list_element_set_elements";
721 
722 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
723 	libcdata_list_element_t *backup_next_element       = NULL;
724 	libcdata_list_element_t *backup_previous_element   = NULL;
725 #endif
726 
727 	if( element == NULL )
728 	{
729 		libcerror_error_set(
730 		 error,
731 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
732 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
733 		 "%s: invalid list element.",
734 		 function );
735 
736 		return( -1 );
737 	}
738 	internal_element = (libcdata_internal_list_element_t *) element;
739 
740 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
741 	if( libcthreads_read_write_lock_grab_for_write(
742 	     internal_element->read_write_lock,
743 	     error ) != 1 )
744 	{
745 		libcerror_error_set(
746 		 error,
747 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
748 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
749 		 "%s: unable to grab read/write lock for writing.",
750 		 function );
751 
752 		return( -1 );
753 	}
754 	backup_previous_element = internal_element->previous_element;
755 	backup_next_element     = internal_element->next_element;
756 #endif
757 	internal_element->previous_element = previous_element;
758 	internal_element->next_element     = next_element;
759 
760 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
761 	if( libcthreads_read_write_lock_release_for_write(
762 	     internal_element->read_write_lock,
763 	     error ) != 1 )
764 	{
765 		libcerror_error_set(
766 		 error,
767 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
768 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
769 		 "%s: unable to release read/write lock for writing.",
770 		 function );
771 
772 		goto on_error;
773 	}
774 #endif
775 	return( 1 );
776 
777 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
778 on_error:
779 	internal_element->previous_element = backup_previous_element;
780 	internal_element->next_element     = backup_next_element;
781 
782 	return( -1 );
783 #endif
784 }
785 
786 /* Retrieves the value from the list element
787  * Returns 1 if successful or -1 on error
788  */
libcdata_list_element_get_value(libcdata_list_element_t * element,intptr_t ** value,libcerror_error_t ** error)789 int libcdata_list_element_get_value(
790      libcdata_list_element_t *element,
791      intptr_t **value,
792      libcerror_error_t **error )
793 {
794 	libcdata_internal_list_element_t *internal_element = NULL;
795 	static char *function                              = "libcdata_list_element_get_value";
796 
797 	if( element == NULL )
798 	{
799 		libcerror_error_set(
800 		 error,
801 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
802 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
803 		 "%s: invalid list element.",
804 		 function );
805 
806 		return( -1 );
807 	}
808 	internal_element = (libcdata_internal_list_element_t *) element;
809 
810 	if( value == NULL )
811 	{
812 		libcerror_error_set(
813 		 error,
814 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
815 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
816 		 "%s: invalid value.",
817 		 function );
818 
819 		return( -1 );
820 	}
821 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
822 	if( libcthreads_read_write_lock_grab_for_read(
823 	     internal_element->read_write_lock,
824 	     error ) != 1 )
825 	{
826 		libcerror_error_set(
827 		 error,
828 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
829 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
830 		 "%s: unable to grab read/write lock for reading.",
831 		 function );
832 
833 		return( -1 );
834 	}
835 #endif
836 	*value = internal_element->value;
837 
838 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
839 	if( libcthreads_read_write_lock_release_for_read(
840 	     internal_element->read_write_lock,
841 	     error ) != 1 )
842 	{
843 		libcerror_error_set(
844 		 error,
845 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
846 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
847 		 "%s: unable to release read/write lock for reading.",
848 		 function );
849 
850 		return( -1 );
851 	}
852 #endif
853 	return( 1 );
854 }
855 
856 /* Sets the value in the list element
857  * Returns 1 if successful or -1 on error
858  */
libcdata_list_element_set_value(libcdata_list_element_t * element,intptr_t * value,libcerror_error_t ** error)859 int libcdata_list_element_set_value(
860      libcdata_list_element_t *element,
861      intptr_t *value,
862      libcerror_error_t **error )
863 {
864 	libcdata_internal_list_element_t *internal_element = NULL;
865 	static char *function                              = "libcdata_list_element_set_value";
866 
867 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
868 	intptr_t *backup_value                             = NULL;
869 #endif
870 
871 	if( element == NULL )
872 	{
873 		libcerror_error_set(
874 		 error,
875 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
876 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
877 		 "%s: invalid list element.",
878 		 function );
879 
880 		return( -1 );
881 	}
882 	internal_element = (libcdata_internal_list_element_t *) element;
883 
884 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
885 	if( libcthreads_read_write_lock_grab_for_write(
886 	     internal_element->read_write_lock,
887 	     error ) != 1 )
888 	{
889 		libcerror_error_set(
890 		 error,
891 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
892 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
893 		 "%s: unable to grab read/write lock for writing.",
894 		 function );
895 
896 		return( -1 );
897 	}
898 	backup_value = internal_element->value;
899 #endif
900 	internal_element->value = value;
901 
902 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
903 	if( libcthreads_read_write_lock_release_for_write(
904 	     internal_element->read_write_lock,
905 	     error ) != 1 )
906 	{
907 		libcerror_error_set(
908 		 error,
909 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
910 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
911 		 "%s: unable to release read/write lock for writing.",
912 		 function );
913 
914 		goto on_error;
915 	}
916 #endif
917 	return( 1 );
918 
919 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
920 on_error:
921 	internal_element->value = backup_value;
922 
923 	return( -1 );
924 #endif
925 }
926 
927