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