1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <klib/rc.h>
28 #include <klib/namelist.h>
29 #include <klib/vector.h>
30 #include <klib/container.h>
31 #include <klib/sort.h>
32 #include <klib/log.h>
33 #include <klib/out.h>
34 #include <klib/status.h>
35 #include <klib/text.h>
36 #include <klib/printf.h>
37 #include <klib/time.h>
38 #include <sysalloc.h>
39 #include <kfs/directory.h>
40 #include <kfs/file.h>
41 #include <kfs/toc.h>
42 #include <kfs/sra.h>
43 #include <kfs/md5.h>
44
45 #include <kapp/main.h>
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <string.h>
51 #include <assert.h>
52 #include <time.h>
53 #include <endian.h>
54 #include <byteswap.h>
55
56 #include "kar+args.h"
57 #include "kar+.h"
58
59 /********************************************************************
60 ** copying string
61 ********************************************************************/
kar_stdp(const char ** Dst,const char * Src)62 rc_t CC kar_stdp ( const char ** Dst, const char * Src )
63 {
64 char * Ret;
65 size_t Size;
66
67 Ret = NULL;
68 Size = 0;
69
70 if ( Dst != NULL ) {
71 * Dst = NULL;
72 }
73
74 if ( Dst == NULL || Src == NULL ) {
75 return RC (rcExe, rcData, rcCopying, rcParam, rcNull);
76 }
77
78 Size = strlen ( Src );
79
80 Ret = ( char * ) calloc ( Size + 1, sizeof ( char ) );
81 if ( Ret == NULL ) {
82 return RC (rcExe, rcNode, rcAllocating, rcMemory, rcExhausted);
83 }
84
85 memmove ( Ret, Src, Size );
86 * Dst = Ret;
87
88 return 0;
89 } /* kar_stdp () */
90
91 rc_t CC
kar_stndp(const char ** Dst,const char * Src,size_t n)92 kar_stndp ( const char ** Dst, const char * Src, size_t n )
93 {
94 char * Ret;
95
96 Ret = NULL;
97
98 if ( Dst != NULL ) {
99 * Dst = NULL;
100 }
101
102 if ( Dst == NULL || Src == NULL || n == 0 ) {
103 return RC (rcExe, rcData, rcCopying, rcParam, rcNull);
104 }
105
106 Ret = ( char * ) calloc ( n + 1, sizeof ( char ) );
107 if ( Ret == NULL ) {
108 return RC (rcExe, rcNode, rcAllocating, rcMemory, rcExhausted);
109 }
110
111 memmove ( Ret, Src, n );
112 * Dst = Ret;
113
114 return 0;
115 } /* kar_stndp () */
116
117 /********************************************************************
118 ** composes path from top to node, allocates, result should be freed
119 ** JOJOBA : That is very poorly made method, need to reimplement
120 ********************************************************************/
kar_entry_path(const char ** Ret,KAREntry * Entry)121 rc_t CC kar_entry_path ( const char ** Ret, KAREntry * Entry )
122 {
123 char Bm [ 1024 ];
124 char Bs [ 1024 ];
125
126 if ( Ret != NULL ) {
127 * Ret = NULL;
128 }
129
130 if ( Ret == NULL || Entry == NULL ) {
131 return RC ( rcExe, rcPath, rcInitializing, rcParam, rcNull );
132 }
133
134 * Bm = 0;
135 * Bs = 0;
136 while ( Entry != NULL ) {
137 if ( Entry -> parentDir != NULL ) {
138 strcpy ( Bs, Entry -> name );
139 strcat ( Bs, "/" );
140 strcat ( Bs, Bm );
141 strcpy ( Bm, Bs );
142 }
143
144 Entry = ( KAREntry * ) Entry -> parentDir;
145 }
146
147 size_t Sz = strlen ( Bm );
148
149 if ( Sz == 0 ) {
150 return RC ( rcExe, rcPath, rcValidating, rcParam, rcInvalid );
151 }
152
153 if ( Bm [ Sz - 1 ] == '/' ) {
154 Bm [ Sz - 1 ] = 0;
155 }
156
157 return kar_stdp ( Ret, Bm );
158 } /* kar_entry_path () */
159
160 /********************************************************************
161 ** will cal 'Cb' function for node and all it's subnodes in following
162 ** order : first will call it for children, and last for node itself.
163 ** NOTE : it does not follow soft/hard links to directory
164 ********************************************************************/
165 typedef struct car_entry_for_each_pack car_entry_for_each_pack;
166 struct car_entry_for_each_pack {
167 void * data;
168 void ( CC * callback ) ( const KAREntry * Entry, void * data );
169 };
170
171 /* Forward */
172 void CC kar_entry_for_each (
173 const KAREntry * self,
174 void ( CC * Cb ) ( const KAREntry * Entry, void * Data),
175 void * Data
176 );
177
178 static
kar_entry_for_each_callback(BSTNode * Node,void * Data)179 void CC kar_entry_for_each_callback ( BSTNode * Node, void * Data )
180 {
181 if ( Node != NULL ) {
182 kar_entry_for_each (
183 ( const KAREntry * ) Node,
184 ( ( car_entry_for_each_pack * ) Data ) -> callback,
185 ( ( car_entry_for_each_pack * ) Data ) -> data
186 );
187 }
188 } /* kar_entry_for_each_callback () */
189
kar_entry_for_each(const KAREntry * self,void (CC * Cb)(const KAREntry * Entry,void * Data),void * Data)190 void CC kar_entry_for_each (
191 const KAREntry * self,
192 void ( CC * Cb ) ( const KAREntry * Entry, void * Data),
193 void * Data
194 )
195 {
196 if ( self == NULL ) {
197 return;
198 }
199
200 /* First children
201 */
202 if ( self -> eff_type == ktocentrytype_dir ) {
203 car_entry_for_each_pack pack;
204 pack . data = Data;
205 pack . callback = Cb;
206
207 BSTreeForEach (
208 & ( ( KARDir * ) self ) -> contents,
209 false,
210 kar_entry_for_each_callback,
211 & pack
212 );
213 }
214
215 /* Itself last
216 */
217 Cb ( self, Data );
218 } /* kar_entry_for_each () */
219
220 /********************************************************************
221 ** There are 'kar_p2e_XXX' things are stored.
222 **
223 **
224 ********************************************************************/
225 typedef struct kar_p2e_node kar_p2e_node;
226 struct kar_p2e_node {
227 BSTNode dad;
228
229 const char * path;
230 KAREntry * entry;
231 };
232
233 static
kar_p2e_node_dispose(kar_p2e_node * node)234 rc_t CC kar_p2e_node_dispose ( kar_p2e_node * node )
235 {
236 if ( node != NULL ) {
237 if ( node -> path != NULL ) {
238 free ( ( char * ) node -> path );
239 node -> path = NULL;
240 }
241
242 free ( node );
243 }
244
245 return 0;
246 } /* kar_p2e_node_dispose () */
247
248 static
kar_p2e_node_create(kar_p2e_node ** Node,KAREntry * Entry)249 rc_t CC kar_p2e_node_create ( kar_p2e_node ** Node, KAREntry * Entry )
250 {
251 rc_t rc;
252 kar_p2e_node * Ret;
253
254 rc = 0;
255 Ret = NULL;
256
257 if ( Node != NULL ) {
258 * Node = NULL;
259 }
260
261 if ( Node == NULL || Entry == NULL ) {
262 return RC ( rcExe, rcNode, rcAllocating, rcParam, rcNull );
263 }
264
265 Ret = calloc ( 1, sizeof ( kar_p2e_node ) );
266 if ( Ret == NULL ) {
267 rc = RC ( rcExe, rcNode, rcAllocating, rcMemory, rcExhausted );
268 }
269 else {
270 rc = kar_entry_path ( & ( Ret -> path ), Entry );
271 if ( rc == 0 ) {
272 Ret -> entry = Entry;
273
274 * Node = Ret;
275 }
276 }
277
278 if ( rc != 0 ) {
279 * Node = NULL;
280
281 if ( Ret != NULL ) {
282 kar_p2e_node_dispose ( Ret );
283 }
284 }
285
286 return rc;
287 } /* kar_p2e_node_create () */
288
kar_p2e_init(BSTree * p2e,KAREntry * Entry)289 rc_t CC kar_p2e_init ( BSTree * p2e, KAREntry * Entry )
290 {
291 BSTreeInit ( p2e );
292
293 return kar_p2e_scan ( p2e, Entry );
294 } /* kar_p2e_init () */
295
296 static
kar_p2e_whack_callback(BSTNode * node,void * data)297 void CC kar_p2e_whack_callback ( BSTNode * node, void * data )
298 {
299 kar_p2e_node_dispose ( ( struct kar_p2e_node * ) node );
300 } /* kar_p2e_whack_callback () */
301
kar_p2e_whack(BSTree * p2e)302 rc_t CC kar_p2e_whack ( BSTree * p2e )
303 {
304 BSTreeWhack ( p2e, kar_p2e_whack_callback, NULL );
305
306 return 0;
307 } /* kar_p2e_whack () */
308
309 static
kar_p2e_add_callback(const BSTNode * Item,const BSTNode * Node)310 int64_t CC kar_p2e_add_callback ( const BSTNode * Item, const BSTNode * Node )
311 {
312 /* JOJOBA ... dull
313 */
314 return strcmp (
315 ( ( kar_p2e_node * ) Item ) -> path,
316 ( ( kar_p2e_node * ) Node ) -> path
317 );
318 } /* kar_p2e_add_callback () */
319
kar_p2e_add(BSTree * p2e,KAREntry * Entry)320 rc_t CC kar_p2e_add ( BSTree * p2e, KAREntry * Entry )
321 {
322 rc_t rc;
323 kar_p2e_node * Node;
324
325 rc = 0;
326 Node = NULL;
327
328 rc = kar_p2e_node_create ( & Node, Entry );
329 if ( rc == 0 ) {
330 rc = BSTreeInsert (
331 p2e,
332 & ( Node -> dad ),
333 kar_p2e_add_callback
334 );
335 if ( rc != 0 ) {
336 kar_p2e_node_dispose ( Node );
337 }
338 }
339
340 return rc;
341 } /* kar_p2e_add () */
342
343
344 typedef struct kar_p2e_scan_struct kar_p2e_scan_struct;
345 struct kar_p2e_scan_struct {
346 BSTree * p2e;
347 rc_t rc;
348 };
349
350 static
kar_p2e_scan_callback(const KAREntry * Entry,void * Data)351 void CC kar_p2e_scan_callback ( const KAREntry * Entry, void * Data )
352 {
353 /* That is root node
354 */
355 if ( Entry -> name == NULL && Entry -> parentDir == NULL ) {
356 return;
357 }
358
359 kar_p2e_scan_struct * SC = ( struct kar_p2e_scan_struct * ) Data;
360 if ( SC -> rc == 0 ) {
361 SC -> rc = kar_p2e_add ( SC -> p2e, ( KAREntry * ) Entry );
362 }
363 } /* kar_p2e_scan_callback () */
364
kar_p2e_scan(BSTree * p2e,KAREntry * Entry)365 rc_t CC kar_p2e_scan ( BSTree * p2e, KAREntry * Entry )
366 {
367 struct kar_p2e_scan_struct SC;
368
369 SC . p2e = p2e;
370 SC . rc = 0;
371
372 kar_entry_for_each ( Entry, kar_p2e_scan_callback, ( void * ) & SC );
373 return SC . rc;
374 } /* kar_p2e_scan () */
375
376 static
kar_p2e_find_callback(const void * Item,const BSTNode * Node)377 int64_t CC kar_p2e_find_callback ( const void * Item, const BSTNode * Node )
378 {
379 return strcmp (
380 ( const char * ) Item,
381 ( ( kar_p2e_node * ) Node ) -> path
382 );
383 } /* path2etnry_find_callback() */
384
kar_p2e_find(BSTree * p2e,const char * Path)385 KAREntry * CC kar_p2e_find ( BSTree * p2e, const char * Path )
386 {
387 kar_p2e_node * Node = NULL;
388 if ( Path != NULL ) {
389 Node = ( kar_p2e_node * )
390 BSTreeFind ( p2e, Path, kar_p2e_find_callback );
391 }
392 return Node == NULL ? NULL : ( Node -> entry );
393 } /* kar_p2e_find () */
394
395 /********************************************************************
396 ** Misc TOC methods
397 **
398 **
399 ********************************************************************/
kar_entry_full_path(const KAREntry * entry,const char * root_dir,char * buffer,size_t bsize)400 size_t CC kar_entry_full_path ( const KAREntry * entry, const char * root_dir, char * buffer, size_t bsize )
401 {
402 size_t offset = 0;
403 if ( entry -> parentDir != NULL )
404 {
405 offset = kar_entry_full_path ( & entry -> parentDir -> dad, root_dir, buffer, bsize );
406 if ( offset < bsize )
407 buffer [ offset ++ ] = '/';
408 }
409 else if ( root_dir != NULL && root_dir [ 0 ] != 0 )
410 {
411 offset = string_copy_measure ( buffer, bsize, root_dir );
412 if ( buffer [ offset - 1 ] != '/' && offset < bsize )
413 buffer [ offset ++ ] = '/';
414 }
415
416 return string_copy_measure ( & buffer [ offset ], bsize - offset, entry -> name ) + offset;
417 } /* kar_entry_full_path () */
418
419 /********************************************************************
420 ** KARWek lives here
421 **
422 **
423 ********************************************************************/
424 struct KARWek {
425 void ** wektor;
426
427 size_t size;
428 size_t capacity;
429 size_t inc_size;
430
431 void ( CC * destructor ) ( void * i );
432 };
433
kar_wek_clean(KARWek * self)434 rc_t CC kar_wek_clean ( KARWek * self )
435 {
436 if ( self != NULL ) {
437 void ** Wek = self -> wektor;
438 if ( Wek != NULL && self -> size != 0 ) {
439 if ( self -> destructor != NULL ) {
440 for ( size_t llp = 0; llp < self -> size; llp ++ ) {
441 if ( Wek [ llp ] != NULL ) {
442 self -> destructor ( Wek [ llp ] );
443 }
444 }
445 }
446
447 memset ( Wek, 0, sizeof ( void * ) * self -> size );
448 self -> size = 0;
449 }
450 }
451 return 0;
452 } /* kar_wek_clean () */
453
454 static
kar_wek_whack(KARWek * self)455 rc_t CC kar_wek_whack ( KARWek * self )
456 {
457 if ( self != NULL ) {
458 kar_wek_clean ( self );
459
460 if ( self -> wektor != NULL ) {
461 free ( self -> wektor );
462
463 self -> wektor = NULL;
464 }
465
466 self -> size = 0;
467 self -> capacity = 0;
468 self -> inc_size = 0;
469 self -> destructor = NULL;
470 }
471
472 return 0;
473 } /* kar_wek_whack () */
474
kar_wek_dispose(KARWek * self)475 rc_t CC kar_wek_dispose ( KARWek * self )
476 {
477 if ( self != NULL ) {
478 kar_wek_whack ( self );
479
480 free ( self );
481 }
482
483 return 0;
484 } /* kar_wek_dispose () */
485
486 static
kar_wek_realloc(KARWek * self,size_t size)487 rc_t CC kar_wek_realloc ( KARWek * self, size_t size )
488 {
489 size_t NewCap;
490 size_t IncSize;
491
492 NewCap = 0;
493 IncSize = 16;
494
495 if ( self == NULL ) {
496 return RC ( rcExe, rcVector, rcAllocating, rcSelf, rcNull );
497 }
498
499 if ( size == 0 ) {
500 return 0;
501 }
502
503 IncSize = self -> inc_size == 0 ? 16 : self -> inc_size;
504
505 NewCap = ( ( size / IncSize ) + 1 ) * IncSize;
506 if ( self -> capacity < NewCap ) {
507 void ** NewWek = calloc ( NewCap, sizeof ( void * ) );
508 if ( NewWek == NULL ) {
509 return RC ( rcExe, rcVector, rcAllocating, rcMemory, rcExhausted );
510 }
511
512 if ( self -> wektor != NULL ) {
513 if ( self -> size != 0 ) {
514 memmove (
515 NewWek,
516 self -> wektor,
517 sizeof ( void * ) * self -> size
518 );
519 }
520
521 free ( self -> wektor );
522 self -> wektor = NULL;
523 }
524
525 self -> wektor = NewWek;
526 self -> capacity = NewCap;
527 }
528
529 return 0;
530 } /* kar_wek_realloc () */
531
532
533 static
kar_wek_init(KARWek * self,size_t initial_capacity,size_t increment_size,void (CC * destructor)(void * i))534 rc_t CC kar_wek_init (
535 KARWek * self,
536 size_t initial_capacity,
537 size_t increment_size,
538 void ( CC * destructor ) ( void * i )
539 )
540 {
541 rc_t rc = 0;
542
543 if ( self == NULL ) {
544 return RC ( rcExe, rcVector, rcAllocating, rcSelf, rcNull );
545 }
546
547
548 self -> wektor = NULL;
549 self -> size = 0;
550 self -> inc_size = increment_size == 0 ? 16 : increment_size;
551 self -> capacity = 0;
552 self -> destructor = destructor;
553
554 if ( initial_capacity != 0 ) {
555 rc = kar_wek_realloc ( self, initial_capacity );
556 }
557
558 return rc;
559 } /* kar_wek_init () */
560
kar_wek_make(KARWek ** Wek,size_t initial_capacity,size_t increment_size,void (CC * destructor)(void * i))561 rc_t CC kar_wek_make (
562 KARWek ** Wek,
563 size_t initial_capacity,
564 size_t increment_size,
565 void ( CC * destructor ) ( void * i )
566 )
567 {
568 rc_t rc;
569 KARWek * Ret;
570
571 rc = 0;
572 Ret = NULL;
573
574 if ( Wek != NULL ) {
575 * Wek = NULL;
576 }
577
578 if ( Wek == NULL ) {
579 return RC ( rcExe, rcVector, rcAllocating, rcParam, rcNull );
580 }
581
582 Ret = calloc ( 1, sizeof ( KARWek ) );
583 if ( Ret == NULL ) {
584 rc = RC ( rcExe, rcVector, rcAllocating, rcMemory, rcExhausted );
585 }
586 else {
587 rc = kar_wek_init (
588 Ret,
589 initial_capacity,
590 increment_size,
591 destructor
592 );
593 if ( rc == 0 ) {
594 * Wek = Ret;
595 }
596 }
597
598 return rc;
599 } /* kar_wek_make () */
600
kar_wek_make_def(KARWek ** Wek)601 rc_t CC kar_wek_make_def ( KARWek ** Wek )
602 {
603 return kar_wek_make ( Wek, 0, 0, NULL );
604 } /* kar_wek_make_def () */
605
kar_wek_append(KARWek * self,void * Item)606 rc_t CC kar_wek_append ( KARWek * self, void * Item )
607 {
608 rc_t rc = 0;
609
610 if ( self == 0 ) {
611 return RC ( rcExe, rcVector, rcAppending, rcSelf, rcNull );
612 }
613
614 /* Not sure about that check
615 if ( Item == 0 ) {
616 return RC ( rcExe, rcVector, rcAppending, rcParam, rcNull );
617 }
618 */
619
620 rc = kar_wek_realloc ( self, self -> size + 1 );
621 if ( rc == 0 ) {
622 self -> wektor [ self -> size ] = Item;
623 self -> size ++;
624 }
625
626 return rc;
627 } /* kar_wek_append () */
628
kar_wek_size(KARWek * self)629 size_t CC kar_wek_size ( KARWek * self )
630 {
631 return self == NULL ? 0 : self -> size;
632 } /* kar_wek_size () */
633
kar_wek_data(KARWek * self)634 void ** CC kar_wek_data ( KARWek * self )
635 {
636 return self == NULL ? 0 : self -> wektor;
637 } /* kar_wek_data () */
638
kar_wek_get(KARWek * self,size_t Idx)639 void * CC kar_wek_get ( KARWek * self, size_t Idx )
640 {
641 if ( self != NULL ) {
642 if ( 0 <= Idx && Idx < self -> size ) {
643 return self -> wektor [ Idx ];
644 }
645 }
646
647 return NULL;
648 } /* kar_wek_get () */
649
650 /********************************************************************
651 ** Misk methods
652 **
653 **
654 ********************************************************************/
655 static
list_files_callback(const KAREntry * Entry,void * Data)656 void CC list_files_callback ( const KAREntry * Entry, void * Data )
657 {
658 if ( Entry != NULL && Data != NULL ) {
659 if ( Entry -> eff_type == ktocentrytype_file
660 || Entry -> eff_type == ktocentrytype_chunked ) {
661 if ( ( ( KARFile * ) Entry ) -> byte_size != 0 ) {
662 kar_wek_append ( ( KARWek * ) Data, ( void * ) Entry );
663 }
664 }
665 }
666 } /* list_files_callback () */
667
kar_entry_list_files(const KAREntry * self,KARWek ** Files)668 rc_t CC kar_entry_list_files ( const KAREntry * self, KARWek ** Files )
669 {
670 rc_t rc;
671 KARWek * Wek;
672
673 rc = 0;
674 Wek = NULL;
675
676 if ( Files != NULL ) {
677 * Files = NULL;
678 }
679
680 if ( self == NULL ) {
681 return RC ( rcExe, rcVector, rcInitializing, rcSelf, rcNull );
682 }
683
684 if ( Files == NULL ) {
685 return RC ( rcExe, rcVector, rcInitializing, rcParam, rcNull );
686 }
687
688 rc = kar_wek_make_def ( & Wek );
689 if ( rc == 0 ) {
690 kar_entry_for_each ( self, list_files_callback, Wek );
691
692 * Files = Wek;
693 }
694
695 return rc;
696 } /* kar_entry_list_files () */
697
698 typedef struct D3D D3D;
699 struct D3D {
700 bool ( CC * filter ) ( const KAREntry * Entry, void * Data );
701 void * data;
702 KARWek * wek;
703 };
704
705 static
filter_files_callback(const KAREntry * Entry,void * Data)706 void CC filter_files_callback ( const KAREntry * Entry, void * Data )
707 {
708 if ( Entry != NULL && Data != NULL ) {
709 D3D * d3d = ( D3D * ) Data;
710 if ( d3d -> filter != NULL ) {
711 if ( d3d -> filter ( Entry, d3d -> data ) ) {
712 kar_wek_append ( d3d -> wek, ( void * ) Entry );
713
714 }
715 }
716 }
717 } /* filter_files_callback () */
718
kar_entry_filter_files(const KAREntry * self,KARWek ** Files,bool (CC * Filter)(const KAREntry * Entry,void * Data),void * Data)719 rc_t CC kar_entry_filter_files (
720 const KAREntry * self,
721 KARWek ** Files,
722 bool ( CC * Filter ) (
723 const KAREntry * Entry,
724 void * Data
725 ),
726 void * Data
727 )
728 {
729 rc_t rc;
730 KARWek * Wek;
731
732 rc = 0;
733 Wek = NULL;
734
735 if ( Files != NULL ) {
736 * Files = NULL;
737 }
738
739 if ( self == NULL ) {
740 return RC ( rcExe, rcVector, rcInitializing, rcSelf, rcNull );
741 }
742
743 if ( Files == NULL ) {
744 return RC ( rcExe, rcVector, rcInitializing, rcParam, rcNull );
745 }
746
747 rc = kar_wek_make_def ( & Wek );
748 if ( rc == 0 ) {
749 D3D d3d;
750 d3d . filter = Filter;
751 d3d . data = Data;
752 d3d . wek = Wek;
753
754 kar_entry_for_each (
755 self,
756 filter_files_callback,
757 ( void * ) & d3d
758 );
759
760 * Files = Wek;
761 }
762
763 return rc;
764 } /* kar_entry_filter_files () */
765
766
filter_flag_filter(const KAREntry * Entry,void * Data)767 bool CC filter_flag_filter ( const KAREntry * Entry, void * Data )
768 {
769 return ( Entry != NULL && Data != NULL )
770 ? ( Entry -> the_flag == * ( ( bool * ) Data ) )
771 : false
772 ;
773 } /* filter_flag_filter () */
774
kar_entry_filter_flag(const KAREntry * self,KARWek ** Files,bool FlagValue)775 rc_t CC kar_entry_filter_flag (
776 const KAREntry * self,
777 KARWek ** Files,
778 bool FlagValue
779 )
780 {
781 return kar_entry_filter_files (
782 self,
783 Files,
784 filter_flag_filter,
785 ( void * ) & FlagValue
786 );
787 } /* kar_entry_filter_flag () */
788
789 static
set_flag_callback(const KAREntry * Entry,void * Data)790 void CC set_flag_callback ( const KAREntry * Entry, void * Data )
791 {
792 if ( Entry != NULL && Data != NULL ) {
793 ( ( KAREntry * ) Entry ) -> the_flag = * ( ( bool * ) Data );
794 }
795 } /* set_flag_callback () */
796
kar_entry_set_flag(const KAREntry * self,bool Value)797 rc_t CC kar_entry_set_flag ( const KAREntry * self, bool Value )
798 {
799 rc_t rc;
800
801 rc = 0;
802
803 if ( self == NULL ) {
804 return RC ( rcExe, rcVector, rcAccessing, rcSelf, rcNull );
805 }
806
807 kar_entry_for_each ( self, set_flag_callback, & Value );
808
809 return rc;
810 } /* kar_entry_set_flag () */
811
812 #ifdef JOJOBA
813 Temporary removing it from here
814 /********************************************************************
815 ** General KAREntry methods are here
816 **
817 **
818 ********************************************************************/
kar_entry_whack(BSTNode * node,void * data)819 void kar_entry_whack ( BSTNode *node, void *data )
820 {
821 KAREntry *entry = ( KAREntry * ) node;
822
823 if ( entry -> type == kptDir ) {
824 BSTreeWhack (
825 & ( ( KARDir * ) entry ) -> contents,
826 kar_entry_whack,
827 NULL
828 );
829 }
830
831 /* do the cleanup */
832 switch ( entry -> type )
833 {
834 case kptAlias:
835 case kptFile | kptAlias:
836 case kptDir | kptAlias:
837 free ( ( void * ) ( ( KARAlias * ) entry ) -> link );
838 break;
839 }
840
841 free ( entry );
842 }
843
kar_entry_create(KAREntry ** rtn,size_t entry_size,const KDirectory * dir,const char * name,uint32_t type,uint8_t eff_type)844 rc_t kar_entry_create ( KAREntry ** rtn, size_t entry_size,
845 const KDirectory * dir, const char * name, uint32_t type,
846 uint8_t eff_type
847 )
848 {
849 rc_t rc;
850
851 size_t name_len = strlen ( name ) + 1;
852 KAREntry * entry = calloc ( 1, entry_size + name_len );
853 if ( entry == NULL )
854 {
855 rc = RC (rcExe, rcNode, rcAllocating, rcMemory, rcExhausted);
856 pLogErr ( klogErr, rc, "Failed to allocated memory for entry '$(name)'",
857 "name=%s", name );
858 }
859 else
860 {
861 /* location for string copy */
862 char * dst = & ( ( char * ) entry ) [ entry_size ];
863
864 /* sanity check */
865 assert ( entry_size >= sizeof * entry );
866
867 /* populate the name by copying to the end of structure */
868 memmove ( dst, name, name_len );
869 entry -> name = dst;
870
871 entry -> type = type;
872 entry -> eff_type = eff_type;
873
874 rc = KDirectoryAccess ( dir, & entry -> access_mode, "%s", entry -> name );
875 if ( rc != 0 )
876 {
877 pLogErr ( klogErr, rc, "Failed to get access mode for entry '$(name)'",
878 "name=%s", entry -> name );
879 }
880 else
881 {
882 rc = KDirectoryDate ( dir, &entry -> mod_time, "%s", entry -> name );
883 if ( rc != 0 )
884 {
885 pLogErr ( klogErr, rc, "Failed to get modification for entry '$(name)'",
886 "name=%s", entry -> name );
887 }
888 else
889 {
890 * rtn = entry;
891 return 0;
892 }
893 }
894
895 free ( entry );
896 }
897
898 * rtn = NULL;
899 return rc;
900 }
901 #endif /* JOJOBA */
902