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 #include <klib/rc.h>
27 #include <klib/out.h>
28 #include <klib/text.h>
29 #include <klib/refcount.h>
30 #include <klib/printf.h>
31 #include <klib/log.h>
32 
33 #include <kfs/file.h>
34 #include <kfs/directory.h>
35 
36 #include <xfs/model.h>
37 #include <xfs/tree.h>
38 #include <xfs/node.h>
39 #include <xfs/path.h>
40 #include <xfs/editors.h>
41 #include <xfs/handle.h>
42 #include <xfs/perm.h>
43 
44 #include "mehr.h"
45 #include "schwarzschraube.h"
46 #include "ncon.h"
47 #include "teleport.h"
48 #include "common.h"
49 #include "xencws.h"
50 
51 #include <sysalloc.h>
52 
53 /*)))
54  |||    That file contains 'native' KFile and KDirectory based nodes
55  |||    Both nodes are implemented as _EncWsNode
56  |||    That kind of node represent real path which exists in system
57 (((*/
58 
59 /*)))
60  |||
61  +++    FileNode, and other simple containers
62  |||
63 (((*/
64 struct _EncWsNode {
65     struct XFSNode node;
66 
67     const struct KDirectory * workspace;
68     const char * path;      /* Path for object */
69     XFSNType type;          /* For optimizing goals only */
70 };
71 
72 struct _EncWsFileEditor {
73     struct XFSFileEditor Papahen;
74 
75     struct KFile * File;
76 };
77 
78 struct _EncWsAttrEditor {
79     struct XFSAttrEditor Papahen;
80 
81     char perm [ 16 ];     /* there we are storing 'const' object */
82 };
83 
84 /*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*/
85 /*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*/
86 /*_*                                                               *_*/
87 /*_* EncWsNode is living here                                      *_*/
88 /*_*                                                               *_*/
89 /*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*/
90 /*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*/
91 
92 /*)))
93  |||
94  +++    EncWsNode virtual table is Living here :lol:
95  |||
96 (((*/
97 static rc_t CC _EncWsNodeFlavor_v1 (
98                                 const struct XFSNode * self
99                                 );
100 static rc_t CC _EncWsNodeDispose_v1 (
101                                 const struct XFSNode * self
102                                 );
103 static rc_t CC _EncWsFileNodeFindNode_v1 (
104                                 const struct XFSNode * self,
105                                 const struct XFSPath * Path,
106                                 uint32_t PathIndex,
107                                 const struct XFSNode ** Node
108                                 );
109 static rc_t CC _EncWsDirNodeFindNode_v1 (
110                                 const struct XFSNode * self,
111                                 const struct XFSPath * Path,
112                                 uint32_t PathIndex,
113                                 const struct XFSNode ** Node
114                                 );
115 static rc_t CC _EncWsNodeDir_v1 (
116                                 const struct XFSNode * self,
117                                 const struct XFSDirEditor ** Dir
118                                 );
119 static rc_t CC _EncWsNodeFile_v1 (
120                                 const struct XFSNode * self,
121                                 const struct XFSFileEditor ** File
122                                 );
123 static rc_t CC _EncWsNodeAttr_v1 (
124                                 const struct XFSNode * self,
125                                 const struct XFSAttrEditor ** Attr
126                                 );
127 static rc_t CC _EncWsNodeDescribe_v1 (
128                                 const struct XFSNode * self,
129                                 char * Buffer,
130                                 size_t BufferSize
131                                 );
132 
133 static const struct XFSNode_vt_v1 _sEncWsFileNodeVT_v1 = {
134                                         1, 1,   /* nin naj */
135                                         _EncWsNodeFlavor_v1,
136                                         _EncWsNodeDispose_v1,
137                                         _EncWsFileNodeFindNode_v1,
138                                         NULL,   /* NO DIR */
139                                         _EncWsNodeFile_v1,
140                                         _EncWsNodeAttr_v1,
141                                         _EncWsNodeDescribe_v1
142                                         };
143 
144 static const struct XFSNode_vt_v1 _sEncWsDirNodeVT_v1 = {
145                                         1, 1,   /* nin naj */
146                                         _EncWsNodeFlavor_v1,
147                                         _EncWsNodeDispose_v1,
148                                         _EncWsDirNodeFindNode_v1,
149                                         _EncWsNodeDir_v1,
150                                         NULL,   /* NO FILE */
151                                         _EncWsNodeAttr_v1,
152                                         _EncWsNodeDescribe_v1
153                                         };
154 
155 static
156 rc_t CC
_EncWsNodeMake(struct _EncWsNode ** Node,const struct KDirectory * Workspace,const char * Name,const char * Path)157 _EncWsNodeMake (
158             struct _EncWsNode ** Node,
159             const struct KDirectory * Workspace,
160             const char * Name,
161             const char * Path
162 )
163 {
164     rc_t RCt;
165     struct _EncWsNode * TheNode;
166     uint32_t Type;
167 
168     RCt = 0;
169     TheNode = NULL;
170     Type = kptNotFound;
171 
172     XFS_CSAN ( Node )
173     XFS_CAN ( Node )
174     XFS_CAN ( Workspace )
175     XFS_CAN ( Name )
176 
177         /* First we should check that object exist and has valid type
178          */
179     Type = KDirectoryPathType ( Workspace, Path );
180     switch ( Type ) {
181         case kptFile :
182         case kptDir :
183             break;
184         case kptNotFound :
185             return XFS_RC ( rcNotFound );
186         default :
187             return XFS_RC ( rcInvalid );
188     }
189 
190     TheNode = calloc ( 1, sizeof ( struct _EncWsNode ) );
191     if ( TheNode == NULL ) {
192         RCt = XFS_RC ( rcExhausted );
193     }
194     else {
195         RCt = XFSNodeInitVT (
196                 & ( TheNode -> node),
197                 Name,
198                 ( const union XFSNode_vt * ) ( Type == kptDir
199                                         ? ( & _sEncWsDirNodeVT_v1 )
200                                         : ( & _sEncWsFileNodeVT_v1 )
201                 )
202                 );
203         if ( RCt == 0 ) {
204             RCt = KDirectoryAddRef ( Workspace );
205             if ( RCt == 0 ) {
206                 TheNode -> workspace = Workspace;
207 
208                 TheNode -> type = Type == kptDir ? kxfsDir : kxfsFile;
209 
210                     /* This is duplicate, but necessary one
211                      */
212                 TheNode -> node . vt = Type == kxfsDir
213                         ? ( ( const union XFSNode_vt * ) & _sEncWsDirNodeVT_v1 )
214                         : ( ( const union XFSNode_vt * ) & _sEncWsFileNodeVT_v1 )
215                         ;
216 
217                 RCt = XFS_StrDup ( Path, & ( TheNode -> path ) );
218                 if ( RCt == 0 ) {
219                     * Node = TheNode;
220                 }
221             }
222         }
223     }
224 
225     if ( RCt != 0 ) {
226         * Node = NULL;
227 
228         if ( TheNode != NULL ) {
229             XFSNodeDispose ( & ( TheNode -> node ) );
230             TheNode = NULL;
231         }
232     }
233 
234 /*
235 pLogMsg ( klogDebug, "_EncWsNodeMake ND[$(node)] NM[$(name)] TP[$(type)]", "node=%p,name=%s,type=%d", ( void * ) TheNode, Name, Type );
236 */
237 
238     return RCt;
239 }   /* _EncWsNodeMake () */
240 
241 uint32_t CC
_EncWsNodeFlavor_v1(const struct XFSNode * self)242 _EncWsNodeFlavor_v1 ( const struct XFSNode * self )
243 {
244     return _sFlavorOfWorkspace;
245 }   /* _EncWsNodeFlavor_v1 () */
246 
247 static
248 rc_t CC
_EncWsNodeDispose(const struct _EncWsNode * self)249 _EncWsNodeDispose ( const struct _EncWsNode * self )
250 {
251     struct _EncWsNode * Node = ( struct _EncWsNode * ) self;
252 
253 /*
254 pLogMsg ( klogDebug, "_EncWsNodeDispose ND[$(node)] TP[$(type)]", "node=%p,type=%d", ( void * ) Node, ( Node == NULL ? 0 : Node -> type ) );
255 */
256 
257     if ( Node == 0 ) {
258         return 0;
259     }
260 
261     if ( Node -> workspace != NULL ) {
262         KDirectoryRelease ( Node -> workspace );
263         Node -> workspace = NULL;
264     }
265 
266     if ( Node -> path != NULL ) {
267         free ( ( char * ) Node -> path );
268         Node -> path = NULL;
269     }
270 
271     Node -> type = 0;
272 
273     free ( Node );
274 
275     return 0;
276 }   /* _EncWsNodeDispose () */
277 
278 rc_t CC
_EncWsNodeDispose_v1(const struct XFSNode * self)279 _EncWsNodeDispose_v1 ( const struct XFSNode * self )
280 {
281     return _EncWsNodeDispose ( ( struct _EncWsNode * ) self );
282 }   /* _EncWsNodeDispose_v1 () */
283 
284 /*)))
285  |||
286  +++  There will be two methods to find node: for KDir and for KFile
287  |||
288 (((*/
289 
290 /*)) KFile version
291  ((*/
292 rc_t CC
_EncWsFileNodeFindNode_v1(const struct XFSNode * self,const struct XFSPath * Path,uint32_t PathIndex,const struct XFSNode ** Node)293 _EncWsFileNodeFindNode_v1 (
294             const struct XFSNode * self,
295             const struct XFSPath * Path,
296             uint32_t PathIndex,
297             const struct XFSNode ** Node
298 )
299 {
300     rc_t RCt;
301     uint32_t PathCount;
302     const char * NodeName;
303     bool IsLast;
304 
305     RCt = 0;
306     PathCount = 0;
307     NodeName = NULL;
308     IsLast = false;
309 
310     RCt = XFSNodeFindNodeCheckInitStandard (
311                                             self,
312                                             Path,
313                                             PathIndex,
314                                             Node,
315                                             & NodeName,
316                                             & PathCount,
317                                             & IsLast
318                                             );
319     if ( RCt == 0 ) {
320         if ( IsLast ) {
321             RCt = XFSNodeAddRef ( self );
322 
323             * Node = self;
324         }
325     }
326 
327 
328     return RCt;
329 }   /* _EncWsFileNodeFindNode () */
330 
331 /*)) KDir version
332  ((*/
333 rc_t CC
_EncWsDirNodeFindNode_v1(const struct XFSNode * self,const struct XFSPath * Path,uint32_t PathIndex,const struct XFSNode ** Node)334 _EncWsDirNodeFindNode_v1 (
335             const struct XFSNode * self,
336             const struct XFSPath * Path,
337             uint32_t PathIndex,
338             const struct XFSNode ** Node
339 )
340 {
341     rc_t RCt;
342     uint32_t PathCount;
343     const char * NodeName;
344     char PathBuf [ XFS_SIZE_4096 ];
345     size_t PathBufLen;
346     struct _EncWsNode * EncWsNode;
347     const struct XFSPath * xPath;
348     bool IsLast;
349 
350     RCt = 0;
351     PathCount = 0;
352     NodeName = NULL;
353     * PathBuf = 0;
354     PathBufLen = 0;
355     EncWsNode = NULL;
356     xPath = NULL;
357     IsLast = false;
358 
359     RCt = XFSNodeFindNodeCheckInitStandard (
360                                             self,
361                                             Path,
362                                             PathIndex,
363                                             Node,
364                                             & NodeName,
365                                             & PathCount,
366                                             & IsLast
367                                             );
368     if ( RCt == 0 ) {
369         if ( IsLast ) {
370             RCt = XFSNodeAddRef ( self );
371 
372             * Node = self;
373 
374             return RCt;
375         }
376 
377         EncWsNode = ( struct _EncWsNode * ) self;
378         if ( EncWsNode -> path == NULL ) {
379             return XFS_RC ( rcInvalid );
380         }
381 
382         if ( EncWsNode -> workspace == NULL ) {
383             return XFS_RC ( rcInvalid );
384         }
385 
386         PathBufLen = string_copy_measure (
387                                         PathBuf,
388                                         sizeof ( PathBuf ),
389                                         EncWsNode -> path
390                                         );
391         * ( PathBuf + PathBufLen ) = '/';
392             /*) Here we are trying to create new node
393              (*/
394         RCt = XFSPathFrom ( Path, PathIndex + 1, & xPath );
395         if ( RCt == 0 ) {
396             if ( string_copy (
397                         PathBuf + PathBufLen + 1,
398                         sizeof ( PathBuf ) - PathBufLen,
399                         XFSPathGet ( xPath ),
400                         string_size ( XFSPathGet ( xPath ) )
401                         ) != string_size ( XFSPathGet ( xPath ) ) ) {
402 
403                 RCt = XFS_RC ( rcInvalid );
404             }
405             XFSPathRelease ( xPath );
406         }
407         if ( RCt == 0 ) {
408             RCt = _EncWsNodeMake (
409                                 & EncWsNode,
410                                 EncWsNode -> workspace,
411                                 XFSPathName ( Path ),
412                                 PathBuf
413                                 );
414             if ( RCt == 0 ) {
415                 * Node = & ( EncWsNode -> node );
416             }
417         }
418     }
419 
420 
421     return RCt;
422 }   /* _EncWsDirNodeFindNode () */
423 
424 /*)))
425  |||
426  +++  Unified DirEditor
427  |||
428 (((*/
429 static
430 rc_t CC
_EncWsDir_dispose_v1(const struct XFSEditor * self)431 _EncWsDir_dispose_v1 ( const struct XFSEditor * self )
432 {
433 /*
434     pLogMsg ( klogDebug, "_EncWsDir_dispose_v1 ( $(editor) )", "editor=%p", ( void * ) self );
435 */
436 
437     if ( self != NULL ) {
438         free ( ( struct XFSDirEditor * ) self );
439     }
440 
441     return 0;
442 }   /* _EncWsDir_dispose_v1 () */
443 
444 static
445 rc_t CC
_EncWsDir_list_v1(const struct XFSDirEditor * self,const struct KNamelist ** List)446 _EncWsDir_list_v1 (
447                 const struct XFSDirEditor * self,
448                 const struct KNamelist ** List
449 )
450 {
451     const struct _EncWsNode * Node;
452     struct KNamelist * TempList;
453     rc_t RCt;
454 
455     RCt = 0;
456     Node = NULL;
457     TempList = NULL;
458 
459     if ( self == NULL || List == NULL ) {
460         return XFS_RC ( rcNull );
461     }
462     * List = NULL;
463 
464     Node = ( const struct _EncWsNode * ) XFSEditorNode (
465                                                 & ( self -> Papahen )
466                                                 );
467     if ( Node == NULL ) {
468         return XFS_RC ( rcInvalid );
469     }
470 
471     if ( Node -> path == NULL ) {
472         return XFS_RC ( rcInvalid );
473     }
474 
475     if ( Node -> workspace == NULL ) {
476         return XFS_RC ( rcInvalid );
477     }
478 
479     if ( Node -> type != kxfsDir ) {
480         return XFS_RC ( rcInvalid );
481     }
482 
483     RCt = KDirectoryList (
484                         Node -> workspace,
485                         & TempList,
486                         NULL, /* Filter Func */
487                         NULL, /* Filter Data */
488                         Node -> path
489                         );
490     if ( RCt == 0 ) {
491         * List = TempList;
492     }
493     else {
494         if ( TempList != NULL ) {
495             KNamelistRelease ( TempList );
496         }
497     }
498 
499     return RCt;
500 }   /* _EncWsDir_list_v1 () */
501 
502 static
503 rc_t CC
_EncWsDir_find_v1(const struct XFSDirEditor * self,const char * Name,const struct XFSNode ** Node)504 _EncWsDir_find_v1 (
505                 const struct XFSDirEditor * self,
506                 const char * Name,
507                 const struct XFSNode ** Node
508 )
509 {
510     const struct _EncWsNode * EncWsNode;
511     struct _EncWsNode * TempNode;
512     char FullPath [ XFS_SIZE_4096 ];
513     size_t NumWrit;
514     rc_t RCt;
515 
516     RCt = 0;
517     EncWsNode = NULL;
518     TempNode = NULL;
519     NumWrit = 0;
520     * FullPath = 0;
521 
522     if ( self == NULL || Name == NULL || Node == NULL ) {
523         return XFS_RC ( rcNull );
524     }
525 
526     * Node = NULL;
527 
528     EncWsNode = ( const struct _EncWsNode * ) XFSEditorNode (
529                                                 & ( self -> Papahen )
530                                                 );
531     if ( EncWsNode == NULL ) {
532         return XFS_RC ( rcInvalid );
533     }
534 
535     if ( EncWsNode -> path == NULL ) {
536         return XFS_RC ( rcInvalid );
537     }
538 
539     if ( EncWsNode -> workspace == NULL ) {
540         return XFS_RC ( rcInvalid );
541     }
542 
543     RCt = string_printf (
544                         FullPath,
545                         sizeof ( FullPath ),
546                         & NumWrit,
547                         "%s/%s",
548                         EncWsNode -> path,
549                         Name
550                         );
551     if ( RCt == 0 ) {
552         RCt = _EncWsNodeMake (
553                             & TempNode,
554                             EncWsNode -> workspace,
555                             Name,
556                             FullPath
557                             );
558         if ( RCt == 0 ) {
559             * Node = ( const struct XFSNode * ) TempNode;
560         }
561     }
562 
563     return RCt;
564 }   /* _EncWsDir_find_v1 () */
565 
566 static
567 rc_t CC
_EncWsDir_create_file_v1(const struct XFSDirEditor * self,const char * Name,XFSNMode Mode,const struct XFSHandle ** Handle)568 _EncWsDir_create_file_v1 (
569                 const struct XFSDirEditor * self,
570                 const char * Name,
571                 XFSNMode Mode,
572                 const struct XFSHandle ** Handle
573 )
574 {
575     struct KFile * File;
576     bool Update;
577     KCreateMode CreateMode;
578     char Path [ XFS_SIZE_4096 ];
579     struct _EncWsNode * EncWsNode, * TempNode;
580     struct _EncWsFileEditor * FileEditor;
581     const struct XFSHandle * TempHandle;
582     size_t NumWritten;
583     uint32_t NodeMode;
584     rc_t RCt;
585 
586     File = NULL;
587     Update = false;
588     CreateMode = kcmCreate;
589     * Path = 0;
590     EncWsNode = TempNode = NULL;
591     FileEditor = NULL;
592     TempHandle = NULL;
593     NumWritten = 0;
594     NodeMode = 0;
595     RCt = 0;
596 
597     if ( self == NULL || Name == NULL || Handle == NULL ) {
598         return XFS_RC ( rcNull );
599     }
600 
601     * Handle = NULL;
602 
603     EncWsNode = ( struct _EncWsNode * ) XFSEditorNode (
604                                                 & ( self -> Papahen )
605                                                 );
606     if ( EncWsNode -> path == NULL ) {
607         return XFS_RC ( rcInvalid );
608     }
609 
610     if ( EncWsNode -> workspace == NULL ) {
611         return XFS_RC ( rcInvalid );
612     }
613 
614     RCt = string_printf (
615                         Path,
616                         sizeof ( Path ),
617                         & NumWritten,
618                         "%s/%s",
619                         EncWsNode -> path,
620                         Name
621                         );
622     if ( RCt != 0 ) {
623         return RCt;
624     }
625 
626     Update = Mode == kxfsReadWrite;
627     CreateMode = kcmCreate;
628 
629     NodeMode = ( Mode == kxfsReadWrite || Mode == kxfsWrite )
630                                                 ? XFSPermRWDefNodeNum ()
631                                                 : XFSPermRODefNodeNum ()
632                                                 ;
633 
634         /* Here we are */
635     RCt = KDirectoryCreateFile (
636                             ( struct KDirectory * ) EncWsNode -> workspace,
637                             & File,
638                             Update,
639                             NodeMode,
640                             CreateMode,
641                             Path
642                             );
643     if ( RCt == 0 ) {
644         RCt = _EncWsNodeMake (
645                             & TempNode,
646                             EncWsNode -> workspace,
647                             Name,
648                             Path
649                             );
650         if ( RCt == 0 ) {
651             RCt = XFSNodeFileEditor (
652                                 & ( TempNode -> node ),
653                                 ( const struct XFSFileEditor ** ) & FileEditor
654                                 );
655             if ( RCt == 0 ) {
656                 FileEditor -> File = File;
657                 RCt = XFSHandleMake (
658                                 & ( TempNode -> node ),
659                                 & TempHandle
660                                 );
661                 if ( RCt == 0 ) {
662                     XFSHandleSet ( TempHandle, FileEditor );
663 
664                     * Handle = TempHandle;
665                 }
666             }
667         }
668     }
669 
670     if ( RCt != 0 ) {
671         * Handle = NULL;
672 
673         if ( TempHandle != NULL ) {
674             XFSHandleRelease ( TempHandle );
675         }
676         else {
677             if ( FileEditor != NULL ) {
678                 XFSEditorDispose ( ( const struct XFSEditor * ) FileEditor );
679             }
680         }
681 
682         if ( File != NULL ) {
683             KFileRelease ( File );
684         }
685     }
686 
687     return RCt;
688 }   /* _EncWsDir_create_file_v1 () */
689 
690 static
691 rc_t CC
_EncWsDir_create_dir_v1(const struct XFSDirEditor * self,const char * Name)692 _EncWsDir_create_dir_v1 (
693                 const struct XFSDirEditor * self,
694                 const char * Name
695 )
696 {
697     rc_t RCt;
698     struct _EncWsNode * EncWsNode;
699     char Path [ XFS_SIZE_4096 ];
700     size_t NumWritten;
701 
702     RCt = 0;
703     EncWsNode = NULL;
704     * Path = 0;
705     NumWritten = 0;
706 
707     if ( self == NULL || Name == NULL ) {
708         return XFS_RC ( rcNull );
709     }
710 
711     EncWsNode = ( struct _EncWsNode * ) XFSEditorNode (
712                                                 & ( self -> Papahen )
713                                                 );
714     if ( EncWsNode -> path == NULL ) {
715         return XFS_RC ( rcInvalid );
716     }
717 
718     if ( EncWsNode -> workspace == NULL ) {
719         return XFS_RC ( rcInvalid );
720     }
721 
722     RCt = string_printf (
723                         Path,
724                         sizeof ( Path ),
725                         & NumWritten,
726                         "%s/%s",
727                         EncWsNode -> path,
728                         Name
729                         );
730     if ( RCt != 0 ) {
731         return RCt;
732     }
733 
734     return KDirectoryCreateDir (
735                         ( struct KDirectory * ) EncWsNode -> workspace,
736                         XFSPermRWDefContNum (),
737                         kcmCreate,
738                         Path
739                         );
740 }   /* _EncWsDir_create_dir_v1 () */
741 
742 static
743 rc_t CC
_EncWsDir_delete_v1(const struct XFSDirEditor * self,const char * Name)744 _EncWsDir_delete_v1 (
745                 const struct XFSDirEditor * self,
746                 const char * Name
747 )
748 {
749     rc_t RCt;
750     struct _EncWsNode * EncWsNode;
751     char Path [ XFS_SIZE_4096 ];
752     size_t NumWritten;
753 
754     RCt = 0;
755     EncWsNode = NULL;
756     * Path = 0;
757     NumWritten = 0;
758 
759     if ( self == NULL || Name == NULL ) {
760         return XFS_RC ( rcNull );
761     }
762 
763     EncWsNode = ( struct _EncWsNode * ) XFSEditorNode (
764                                                 & ( self -> Papahen )
765                                                 );
766     if ( EncWsNode -> path == NULL ) {
767         return XFS_RC ( rcInvalid );
768     }
769 
770     if ( EncWsNode -> workspace == NULL ) {
771         return XFS_RC ( rcInvalid );
772     }
773 
774     RCt = string_printf (
775                         Path,
776                         sizeof ( Path ),
777                         & NumWritten,
778                         "%s/%s",
779                         EncWsNode -> path,
780                         Name
781                         );
782     if ( RCt != 0 ) {
783         return RCt;
784     }
785 
786     return KDirectoryRemove (
787                         ( struct KDirectory * ) EncWsNode -> workspace,
788                         true,
789                         Path
790                         );
791 }   /* _EncWsDir_delete_v1 () */
792 
793 rc_t CC
_EncWsDir_move_v1(const struct XFSDirEditor * self,const char * OldName,const struct XFSNode * NewDir,const char * NewName)794 _EncWsDir_move_v1 (
795             const struct XFSDirEditor * self,
796             const char * OldName,
797             const struct XFSNode * NewDir,
798             const char * NewName
799 )
800 {
801     rc_t RCt;
802     struct _EncWsNode * EncWsNode;
803     struct _EncWsNode * NewEncWsNode;
804     char OldPath [ XFS_SIZE_4096 ];
805     char NewPath [ XFS_SIZE_4096 ];
806     size_t NumWritten;
807 
808     RCt = 0;
809     EncWsNode = NULL;
810     NewEncWsNode = NULL;
811     * OldPath = * NewPath = 0;
812     NumWritten = 0;
813 
814     if ( self == NULL || OldName == NULL || NewDir == NULL
815         || NewName == NULL
816     ) {
817         return XFS_RC ( rcNull );
818     }
819 
820         /*) TODO it is temporary, until we will do
821          (*/
822     if ( XFSNodeFlavor ( NewDir ) !=
823             XFSNodeFlavor ( ( self -> Papahen ) . Node ) ) {
824         return XFS_RC ( rcInvalid );
825     }
826 
827     EncWsNode = ( struct _EncWsNode * ) XFSEditorNode (
828                                                 & ( self -> Papahen )
829                                                 );
830     if ( EncWsNode -> path == NULL ) {
831         return XFS_RC ( rcInvalid );
832     }
833 
834     if ( EncWsNode -> workspace == NULL ) {
835         return XFS_RC ( rcInvalid );
836     }
837 
838     NewEncWsNode = ( struct _EncWsNode * ) NewDir;
839 
840     if ( NewEncWsNode -> path == NULL ) {
841         return XFS_RC ( rcInvalid );
842     }
843 
844     if ( NewEncWsNode -> workspace == NULL ) {
845         return XFS_RC ( rcInvalid );
846     }
847 
848     RCt = string_printf (
849                         OldPath,
850                         sizeof ( OldPath ),
851                         & NumWritten,
852                         "%s/%s",
853                         EncWsNode -> path,
854                         OldName
855                         );
856     if ( RCt != 0 ) {
857         return RCt;
858     }
859 
860     RCt = string_printf (
861                         NewPath,
862                         sizeof ( NewPath ),
863                         & NumWritten,
864                         "%s/%s",
865                         NewEncWsNode -> path,
866                         NewName
867                         );
868     if ( RCt != 0 ) {
869         return RCt;
870     }
871 
872     return KDirectoryRename (
873                         ( struct KDirectory * ) EncWsNode -> workspace,
874                         true,
875                         OldPath,
876                         NewPath
877                         );
878 }   /* _EncWsDir_move_v1 () */
879 
880 rc_t CC
_EncWsNodeDir_v1(const struct XFSNode * self,const struct XFSDirEditor ** Dir)881 _EncWsNodeDir_v1 (
882             const struct XFSNode * self,
883             const struct XFSDirEditor ** Dir
884 )
885 {
886     rc_t RCt;
887     struct XFSDirEditor * Editor;
888 
889     RCt = 0;
890     Editor = NULL;
891 
892     if ( self == NULL || Dir == NULL ) {
893         return XFS_RC ( rcNull );
894     }
895 
896     * Dir = NULL;
897 
898     if ( ( ( struct _EncWsNode * ) self ) -> type != kxfsDir ) {
899         return XFS_RC ( rcInvalid );
900     }
901 
902     Editor = calloc ( 1, sizeof ( struct XFSDirEditor ) );
903     if ( Editor == NULL ) {
904         return XFS_RC ( rcExhausted );
905     }
906 
907     RCt = XFSEditorInit (
908                     & ( Editor -> Papahen ),
909                     self,
910                     _EncWsDir_dispose_v1
911                     );
912 
913     if ( RCt == 0 ) {
914         Editor -> list = _EncWsDir_list_v1;
915         Editor -> find = _EncWsDir_find_v1;
916         Editor -> create_file = _EncWsDir_create_file_v1;
917         Editor -> create_dir = _EncWsDir_create_dir_v1;
918         Editor -> delete = _EncWsDir_delete_v1;
919         Editor -> move = _EncWsDir_move_v1;
920 
921         * Dir = Editor;
922     }
923     else {
924         free ( Editor );
925     }
926 
927     return RCt;
928 }   /* _EncWsNodeDir_v1 () */
929 
930 /*)))
931  |||
932  +++  Unified FileEditor
933  |||
934 (((*/
935 
936 static
937 rc_t CC
_EncWsFile_dispose_v1(const struct XFSEditor * self)938 _EncWsFile_dispose_v1 ( const struct XFSEditor * self )
939 {
940     struct _EncWsFileEditor * Editor = ( struct _EncWsFileEditor * ) self;
941 
942 /*
943     pLogMsg ( klogDebug, "_EncWsFile_dispose_v1 ( $(editor) )", "editor=%p", ( void * ) self );
944 */
945 
946     if ( Editor != NULL ) {
947         if ( Editor -> File != NULL ) {
948             KFileRelease ( Editor -> File );
949 
950             Editor -> File = NULL;
951         }
952 
953         free ( Editor );
954     }
955 
956     return 0;
957 }   /* _EncWsFile_dispose_v1 () */
958 
959 static
960 rc_t CC
_EncWsFile_open_v1(const struct XFSFileEditor * self,XFSNMode Mode)961 _EncWsFile_open_v1 (
962                     const struct XFSFileEditor * self,
963                     XFSNMode Mode
964 )
965 {
966     KFile * File;
967     const struct _EncWsNode * Node;
968     rc_t RCt;
969 
970     File = NULL;
971     Node = NULL;
972     RCt = 0;
973 
974     if ( self == NULL ) {
975         return XFS_RC ( rcNull );
976     }
977 
978     Node = ( const struct _EncWsNode * ) XFSEditorNode (
979                                                 & ( self -> Papahen )
980                                                 );
981     if ( Node == NULL ) {
982         return XFS_RC ( rcInvalid );
983     }
984 
985     if ( Node -> type != kxfsFile ) {
986         return XFS_RC ( rcInvalid );
987     }
988 
989     if ( Node -> path == NULL ) {
990         return XFS_RC ( rcInvalid );
991     }
992 
993     if ( Node -> workspace == NULL ) {
994         return XFS_RC ( rcInvalid );
995     }
996 
997     if ( Mode == kxfsRead ) {
998         RCt = KDirectoryOpenFileRead (
999                             ( struct KDirectory * ) Node -> workspace,
1000                             ( const KFile ** ) & File,
1001                             Node -> path
1002                             );
1003     }
1004     else {
1005         RCt = KDirectoryOpenFileWrite (
1006                             ( struct KDirectory * ) Node -> workspace,
1007                             & File,
1008                             ( Mode & kxfsRead ) == kxfsRead,
1009                             Node -> path
1010                             );
1011     }
1012     if ( RCt == 0 ) {
1013         ( ( struct _EncWsFileEditor * ) self ) -> File = File;
1014     }
1015 
1016     return RCt;
1017 }   /* _EncWsFile_open_v1 () */
1018 
1019 static
1020 rc_t CC
_EncWsFile_close_v1(const struct XFSFileEditor * self)1021 _EncWsFile_close_v1 ( const struct XFSFileEditor * self )
1022 {
1023     struct _EncWsFileEditor * Editor;
1024     rc_t RCt;
1025 
1026     Editor = NULL;
1027     RCt = 0;
1028 
1029     if ( self == NULL ) {
1030         return XFS_RC ( rcNull );
1031     }
1032 
1033 
1034     Editor = ( struct _EncWsFileEditor * ) self;
1035 
1036     if ( Editor -> File != NULL ) {
1037         RCt = KFileRelease ( Editor -> File );
1038 
1039         Editor -> File = NULL;
1040     }
1041 
1042     return RCt;
1043 }   /* _EncWsFile_close_v1 () */
1044 
1045 static
1046 rc_t CC
_EncWsFile_read_v1(const struct XFSFileEditor * self,uint64_t Offset,void * Buffer,size_t SizeToRead,size_t * NumReaded)1047 _EncWsFile_read_v1 (
1048                     const struct XFSFileEditor * self,
1049                     uint64_t Offset,
1050                     void * Buffer,
1051                     size_t SizeToRead,
1052                     size_t * NumReaded
1053 )
1054 {
1055     struct _EncWsFileEditor * Editor;
1056     rc_t RCt;
1057 
1058     Editor = NULL;
1059     RCt = 0;
1060 
1061     if ( self == NULL ) {
1062         return XFS_RC ( rcNull );
1063     }
1064 
1065     Editor = ( struct _EncWsFileEditor * ) self;
1066 
1067     if ( Editor -> File == NULL ) {
1068         return XFS_RC ( rcInvalid );
1069     }
1070 
1071     RCt = KFileReadAll (
1072                     Editor -> File,
1073                     Offset,
1074                     Buffer,
1075                     SizeToRead,
1076                     NumReaded
1077                     );
1078 
1079 /* here may be debutt */
1080 
1081     return RCt;
1082 }   /* _EncWsFile_read_v1 () */
1083 
1084 static
1085 rc_t CC
_EncWsFile_write_v1(const struct XFSFileEditor * self,uint64_t Offset,const void * Buffer,size_t SizeToWrite,size_t * NumWritten)1086 _EncWsFile_write_v1 (
1087                     const struct XFSFileEditor * self,
1088                     uint64_t Offset,
1089                     const void * Buffer,
1090                     size_t SizeToWrite,
1091                     size_t * NumWritten
1092 )
1093 {
1094     struct _EncWsFileEditor * Editor;
1095     rc_t RCt;
1096 
1097     Editor = NULL;
1098     RCt = 0;
1099 
1100     if ( self == NULL ) {
1101         return XFS_RC ( rcNull );
1102     }
1103 
1104     Editor = ( struct _EncWsFileEditor * ) self;
1105 
1106     if ( Editor -> File == NULL ) {
1107         return XFS_RC ( rcInvalid );
1108     }
1109 
1110     RCt = KFileWriteAll (
1111                     Editor -> File,
1112                     Offset,
1113                     Buffer,
1114                     SizeToWrite,
1115                     NumWritten
1116                     );
1117 
1118     return RCt;
1119 }   /* _EncWsFile_write_v1 () */
1120 
1121 static
1122 rc_t CC
_EncWsFile_size_v1(const struct XFSFileEditor * self,uint64_t * Size)1123 _EncWsFile_size_v1 (
1124                         const struct XFSFileEditor * self,
1125                         uint64_t * Size
1126 )
1127 {
1128     const struct _EncWsNode * Node;
1129     const struct KFile * File;
1130     uint64_t TempSize;
1131     rc_t RCt;
1132 
1133     Node = NULL;
1134     File = NULL;
1135     TempSize = 0;
1136     RCt = 0;
1137 
1138     XFS_CSA ( Size, 0 )
1139     XFS_CAN ( self )
1140     XFS_CAN ( Size )
1141 
1142     Node = ( const struct _EncWsNode * ) XFSEditorNode (
1143                                                 & ( self -> Papahen )
1144                                                 );
1145 
1146     XFS_CAN ( Node )
1147     XFS_CAN ( Node -> path )
1148     XFS_CAN ( Node -> workspace )
1149 
1150     if ( Node -> type == kxfsDir ) {
1151             /*) Traditionally directory have size ZERO :lol:
1152              (*/
1153         * Size = 0;
1154     }
1155     else {
1156         File = ( const struct KFile * )
1157                         ( ( struct _EncWsFileEditor * ) self ) -> File;
1158         if ( File == NULL ) {
1159             RCt = KDirectoryFileSize (
1160                                 Node -> workspace,
1161                                 & TempSize,
1162                                 Node -> path
1163                                 );
1164 
1165         }
1166         else {
1167             RCt = KFileSize ( File, & TempSize );
1168         }
1169 
1170         if ( RCt == 0 ) {
1171             * Size = TempSize;
1172         }
1173     }
1174 
1175     return RCt;
1176 }   /* _EncWsFile_size_v1 () */
1177 
1178 static
1179 rc_t CC
_EncWsFile_set_size_v1(const struct XFSFileEditor * self,uint64_t Size)1180 _EncWsFile_set_size_v1 (
1181                 const struct XFSFileEditor * self,
1182                 uint64_t Size
1183 )
1184 {
1185     rc_t RCt;
1186     const struct _EncWsNode * Node;
1187     struct KFile * File;
1188 
1189     RCt = 0;
1190     Node = NULL;
1191 
1192     XFS_CAN ( self );
1193 
1194     Node = ( const struct _EncWsNode * ) XFSEditorNode (
1195                                                 & ( self -> Papahen )
1196                                                 );
1197 
1198     XFS_CAN ( Node )
1199     XFS_CAN ( Node -> path )
1200     XFS_CAN ( Node -> workspace )
1201 
1202     if ( Node -> type != kxfsDir ) {
1203         File = ( struct KFile * )
1204                         ( ( struct _EncWsFileEditor * ) self ) -> File;
1205         if ( File == NULL ) {
1206             RCt = KDirectorySetFileSize (
1207                             ( struct KDirectory * ) Node -> workspace,
1208                             Size,
1209                             Node -> path
1210                             );
1211         }
1212         else {
1213             RCt = KFileSetSize ( File, Size );
1214         }
1215     }
1216 
1217     return RCt;
1218 }   /*  _EncWsFile_set_size_v1 () */
1219 
1220 rc_t CC
_EncWsNodeFile_v1(const struct XFSNode * self,const struct XFSFileEditor ** File)1221 _EncWsNodeFile_v1 (
1222             const struct XFSNode * self,
1223             const struct XFSFileEditor ** File
1224 )
1225 {
1226     rc_t RCt;
1227     struct _EncWsFileEditor * FileEditor;
1228     struct XFSFileEditor * Editor;
1229 
1230     RCt = 0;
1231     FileEditor = NULL;
1232     Editor = NULL;
1233 
1234     if ( self == NULL || File == NULL ) {
1235         return XFS_RC ( rcNull );
1236     }
1237 
1238     * File = NULL;
1239 
1240     if ( ( ( struct _EncWsNode * ) self ) -> type != kxfsFile ) {
1241         return XFS_RC ( rcInvalid );
1242     }
1243 
1244     FileEditor = calloc ( 1, sizeof ( struct _EncWsFileEditor ) );
1245     if ( FileEditor == NULL ) {
1246         return XFS_RC ( rcExhausted );
1247     }
1248 
1249     Editor = & ( FileEditor -> Papahen );
1250 
1251     RCt = XFSEditorInit (
1252                     & ( Editor -> Papahen ),
1253                     self,
1254                     _EncWsFile_dispose_v1
1255                     );
1256 
1257     if ( RCt == 0 ) {
1258         Editor -> open = _EncWsFile_open_v1;
1259         Editor -> close = _EncWsFile_close_v1;
1260         Editor -> read = _EncWsFile_read_v1;
1261         Editor -> write = _EncWsFile_write_v1;
1262         Editor -> size = _EncWsFile_size_v1;
1263         Editor -> set_size = _EncWsFile_set_size_v1;
1264 
1265         * File = Editor;
1266     }
1267     else {
1268         free ( Editor );
1269     }
1270 
1271     return RCt;
1272 }   /* _EncWsNodeFile_v1 () */
1273 
1274 /*)))
1275  |||
1276  +++  Unified Attr
1277  |||
1278 (((*/
1279 
1280 static
1281 rc_t CC
_EncWsAttr_dispose_v1(const struct XFSEditor * self)1282 _EncWsAttr_dispose_v1 ( const struct XFSEditor * self )
1283 {
1284 /*
1285     pLogMsg ( klogDebug, "_EncWsAttr_dispose_v1 ( $(editor) )", "editor=%p", ( void * ) self );
1286 */
1287 
1288     if ( self != NULL ) {
1289         free ( ( struct _EncWsAttrEditor * ) self );
1290     }
1291 
1292     return 0;
1293 }   /* _EncWsAttr_dispose_v1 () */
1294 
1295 /*))    Something unusual. Will check-initialize NativeDir and Node
1296  //     NativeDir and Node could be NULL
1297 ((*/
1298 static
1299 rc_t CC
_EncWsAttr_init_check_v1(const struct XFSAttrEditor * self,const struct _EncWsNode ** Node,struct KDirectory ** Workspace)1300 _EncWsAttr_init_check_v1 (
1301                     const struct XFSAttrEditor * self,
1302                     const struct _EncWsNode ** Node,
1303                     struct KDirectory ** Workspace
1304 
1305 )
1306 {
1307     const struct _EncWsNode * RetNode = NULL;
1308 
1309     XFS_CSAN ( Node )
1310     XFS_CSAN ( Workspace )
1311     XFS_CAN ( self )
1312 
1313     RetNode = ( const struct _EncWsNode * ) XFSEditorNode (
1314                                                 & ( self -> Papahen )
1315                                                 );
1316 
1317     if ( RetNode -> path == NULL ) {
1318         return XFS_RC ( rcInvalid );
1319     }
1320 
1321     if ( RetNode -> workspace == NULL ) {
1322         return XFS_RC ( rcInvalid );
1323     }
1324 
1325     if ( Node != NULL ) {
1326         * Node = RetNode;
1327     }
1328 
1329     if ( Workspace != NULL ) {
1330         * Workspace = ( struct KDirectory * ) RetNode -> workspace;
1331     }
1332 
1333     return 0;
1334 }   /* _EncWsAttr_init_check_v1 () */
1335 
1336 static
1337 rc_t CC
_EncWsAttr_permissions_v1(const struct XFSAttrEditor * self,const char ** Permissions)1338 _EncWsAttr_permissions_v1 (
1339                         const struct XFSAttrEditor * self,
1340                         const char ** Permissions
1341 )
1342 {
1343     const struct _EncWsNode * Node;
1344     KDirectory * Workspace;
1345     uint32_t Access;
1346     char * BF;
1347     rc_t RCt;
1348 
1349     Node = NULL;
1350     Workspace = NULL;
1351     BF = NULL;
1352     RCt = 0;
1353 
1354     if ( Permissions == NULL ) {
1355         return XFS_RC ( rcNull );
1356     }
1357     * Permissions = NULL;
1358 
1359     RCt = _EncWsAttr_init_check_v1 ( self, & Node, & Workspace );
1360     if ( RCt == 0 ) {
1361         RCt = KDirectoryAccess ( Workspace, & Access, Node -> path );
1362         if ( RCt == 0 ) {
1363             BF = ( ( struct _EncWsAttrEditor * ) self ) -> perm;
1364             RCt = XFSPermToChar (
1365                                 Access,
1366                                 BF,
1367                                 sizeof ( ( ( struct _EncWsAttrEditor * ) self ) -> perm )
1368                                 );
1369             if ( RCt == 0 ) {
1370                 if ( Node -> type == kxfsDir ) {
1371                     BF [ 0 ] = 'r';
1372                     BF [ 2 ] = 'x';
1373                 }
1374 
1375                 * Permissions = ( const char * ) BF;
1376             }
1377         }
1378     }
1379 
1380     return RCt;
1381 }   /* _EncWsAttr_permissions_v1 () */
1382 
1383 static
1384 rc_t CC
_EncWsAttr_set_permissions_v1(const struct XFSAttrEditor * self,const char * Permissions)1385 _EncWsAttr_set_permissions_v1 (
1386                         const struct XFSAttrEditor * self,
1387                         const char * Permissions
1388 )
1389 {
1390     rc_t RCt;
1391     const struct _EncWsNode * Node;
1392     struct KDirectory * Workspace;
1393     uint32_t Access;
1394 
1395     RCt = 0;
1396     Workspace = NULL;
1397     Node = NULL;
1398 
1399     XFS_CAN ( self )
1400     XFS_CAN ( Permissions )
1401 
1402     if ( Permissions == NULL ) {
1403         return XFS_RC ( rcNull );
1404     }
1405 
1406     RCt = _EncWsAttr_init_check_v1 ( self, & Node, & Workspace );
1407     if ( RCt == 0 ) {
1408         RCt = XFSPermToNum ( Permissions, & Access );
1409         if ( RCt == 0 ) {
1410             RCt = KDirectorySetAccess (
1411                                     Workspace,
1412                                     false,
1413                                     Access,
1414                                     Access,
1415                                     Node -> path
1416                                     );
1417 
1418         }
1419     }
1420 
1421     return RCt;
1422 }   /*  _EncWsAttr_set_permissions_v1 () */
1423 
1424 static
1425 rc_t CC
_EncWsAttr_date_v1(const struct XFSAttrEditor * self,KTime_t * Time)1426 _EncWsAttr_date_v1 (
1427                         const struct XFSAttrEditor * self,
1428                         KTime_t * Time
1429 )
1430 {
1431     const struct _EncWsNode * Node;
1432     struct KDirectory * Workspace;
1433     KTime_t TempTime;
1434     rc_t RCt;
1435 
1436     Node = NULL;
1437     Workspace = NULL;
1438     TempTime = 0;
1439     RCt = 0;
1440 
1441     XFS_CSA ( Time, 0 )
1442     XFS_CAN ( self )
1443     XFS_CAN ( Time )
1444 
1445     RCt = _EncWsAttr_init_check_v1 ( self, & Node, & Workspace );
1446     if ( RCt == 0 ) {
1447         RCt = KDirectoryDate ( Workspace, & TempTime, Node -> path );
1448         if ( RCt == 0 ) {
1449             * Time = TempTime;
1450         }
1451     }
1452 
1453     return RCt;
1454 }   /* _EncWsAttr_date_v1 () */
1455 
1456 static
1457 rc_t CC
_EncWsAttr_set_date_v1(const struct XFSAttrEditor * self,KTime_t Time)1458 _EncWsAttr_set_date_v1 (
1459                 const struct XFSAttrEditor * self,
1460                 KTime_t Time
1461 )
1462 {
1463     rc_t RCt;
1464     const struct _EncWsNode * Node;
1465     struct KDirectory * Workspace;
1466 
1467     RCt = 0;
1468     Workspace = NULL;
1469     Node = NULL;
1470 
1471     XFS_CAN ( self )
1472 
1473     RCt = _EncWsAttr_init_check_v1 ( self, & Node, & Workspace );
1474     if ( RCt == 0 ) {
1475         RCt = KDirectorySetDate ( Workspace, true, Time, Node -> path );
1476     }
1477 
1478     return RCt;
1479 }   /*  _EncWsAttr_set_date_v1 () */
1480 
1481 static
1482 rc_t CC
_EncWsAttr_type_v1(const struct XFSAttrEditor * self,XFSNType * Type)1483 _EncWsAttr_type_v1 (
1484                         const struct XFSAttrEditor * self,
1485                         XFSNType * Type
1486 )
1487 {
1488     const struct _EncWsNode * Node;
1489     rc_t RCt;
1490 
1491     Node = NULL;
1492     RCt = 0;
1493 
1494     XFS_CSA ( Type, kxfsFile )
1495     XFS_CAN ( Type )
1496 
1497     RCt = _EncWsAttr_init_check_v1 ( self, & Node, NULL );
1498     if ( RCt == 0 ) {
1499         * Type = Node -> type;
1500     }
1501 
1502     return RCt;
1503 }   /* _EncWsAttr_type_v1 () */
1504 
1505 static
1506 rc_t CC
_EncWsNodeAttr_v1(const struct XFSNode * self,const struct XFSAttrEditor ** Attr)1507 _EncWsNodeAttr_v1 (
1508             const struct XFSNode * self,
1509             const struct XFSAttrEditor ** Attr
1510 )
1511 {
1512     rc_t RCt;
1513     struct _EncWsAttrEditor * EncWsEditor;
1514     struct XFSAttrEditor * Editor;
1515 
1516     RCt = 0;
1517     EncWsEditor = NULL;
1518     Editor = NULL;
1519 
1520     XFS_CSAN ( Attr )
1521     XFS_CAN ( self )
1522     XFS_CAN ( Attr )
1523 
1524     EncWsEditor = calloc ( 1, sizeof ( struct _EncWsAttrEditor ) );
1525     if ( EncWsEditor == NULL ) {
1526         return XFS_RC ( rcExhausted );
1527     }
1528 
1529     Editor = & ( EncWsEditor -> Papahen );
1530 
1531     RCt = XFSEditorInit (
1532                     & ( Editor -> Papahen ),
1533                     self,
1534                     _EncWsAttr_dispose_v1
1535                     );
1536 
1537     if ( RCt == 0 ) {
1538         Editor -> permissions = _EncWsAttr_permissions_v1;
1539         Editor -> set_permissions = _EncWsAttr_set_permissions_v1;
1540         Editor -> date = _EncWsAttr_date_v1;
1541         Editor -> set_date = _EncWsAttr_set_date_v1;
1542         Editor -> type = _EncWsAttr_type_v1;
1543 
1544         * Attr = Editor;
1545     }
1546     else {
1547         free ( EncWsEditor );
1548     }
1549 
1550     return RCt;
1551 }   /* _EncWsNodeAttr_v1 () */
1552 
1553 /*)))
1554  |||
1555  +++  Unified Discribe
1556  |||
1557 (((*/
1558 
1559 rc_t CC
_EncWsNodeDescribe_v1(const struct XFSNode * self,char * Buffer,size_t BufferSize)1560 _EncWsNodeDescribe_v1 (
1561             const struct XFSNode * self,
1562             char * Buffer,
1563             size_t BufferSize
1564 )
1565 {
1566     rc_t RCt;
1567     size_t NumWrit;
1568     const char * Abbr;
1569 
1570     RCt = 0;
1571     NumWrit = 0;
1572     Abbr = NULL;
1573 
1574     if ( Buffer == NULL || BufferSize == 0 ) {
1575         return XFS_RC ( rcNull );
1576     }
1577 
1578     Abbr = ( ( const struct _EncWsNode * ) self ) -> type == kxfsDir
1579             ? "ENC DIR"
1580             : "ENC FILE"
1581             ;
1582 
1583     if ( self == NULL ) {
1584         string_printf (
1585                     Buffer,
1586                     BufferSize,
1587                     & NumWrit,
1588                     "NODE (%s)[NULL][NULL]",
1589                     Abbr
1590                     );
1591     }
1592     else {
1593         string_printf (
1594                     Buffer,
1595                     BufferSize,
1596                     & NumWrit,
1597                     "NODE (%s)[%s][0x%p]",
1598                     Abbr,
1599                     self -> Name,
1600                     self
1601                     );
1602     }
1603 
1604     return RCt;
1605 }   /* _EncWsNodeDescribe_v1 () */
1606 
1607 /*)))
1608  |||
1609  +++    WorkspaceNode lives here
1610  |||
1611 (((*/
1612 
1613 /*))
1614  ((     Node make/dispose
1615   ))
1616  ((*/
1617 static
1618 rc_t CC
_EncWsNodeConstructor(const struct XFSModel * Model,const struct XFSModelNode * Template,const char * Alias,const struct XFSNode ** Node)1619 _EncWsNodeConstructor (
1620             const struct XFSModel * Model,
1621             const struct XFSModelNode * Template,
1622             const char * Alias,
1623             const struct XFSNode ** Node
1624 )
1625 {
1626     rc_t RCt;
1627     struct _EncWsNode * TheNode;
1628     const struct KDirectory * Workspace;
1629     const char * NodeName;
1630 
1631     RCt = 0;
1632     TheNode = NULL;
1633     Workspace = NULL;
1634     NodeName = NULL;
1635 
1636     XFS_CSAN ( Node )
1637     XFS_CAN ( Model )
1638     XFS_CAN ( Template )
1639     XFS_CAN ( Node )
1640 
1641     * Node = NULL;
1642 
1643     NodeName = Alias == NULL ? XFSModelNodeName ( Template ) : Alias;
1644 
1645         /* First we should find valid Workspace Directory
1646          */
1647     RCt = XFSEncDirectoryOpen (
1648                 & Workspace,
1649                 ! XFSModelNodeReadOnly ( Template ),
1650                 XFSModelNodeProperty ( Template, XFS_MODEL_PASSWD ),
1651                 XFSModelNodeProperty ( Template, XFS_MODEL_ENCTYPE ),
1652                 XFSModelNodeProperty ( Template, XFS_MODEL_SOURCE )
1653                 );
1654 
1655     if ( RCt == 0 ) {
1656         RCt = _EncWsNodeMake (
1657                     & TheNode,
1658                     Workspace,
1659                     NodeName,
1660                     XFSModelNodeProperty ( Template, XFS_MODEL_SOURCE )
1661                     );
1662         if ( RCt == 0 ) {
1663             * Node = ( struct XFSNode * ) TheNode;
1664         }
1665 
1666         KDirectoryRelease ( Workspace );
1667     }
1668 
1669     if ( RCt != 0 ) {
1670         * Node = NULL;
1671 
1672         if ( TheNode != NULL ) {
1673             _EncWsNodeDispose ( TheNode );
1674         }
1675     }
1676 
1677     return RCt;
1678 }   /* _EncWsNodeConstructor () */
1679 
1680 /*)))
1681  |||
1682  +++    Non-Teleport methods to create nodes
1683  |||
1684 (((*/
1685 LIB_EXPORT
1686 rc_t CC
XFSWorkspaceNodeMake(struct XFSNode ** Node,const char * Name,const char * Path,const char * Password,const char * EncType,bool ReadOnly)1687 XFSWorkspaceNodeMake (
1688             struct XFSNode ** Node,
1689             const char * Name,
1690             const char * Path,
1691             const char * Password,
1692             const char * EncType,
1693             bool ReadOnly
1694 )
1695 {
1696     rc_t RCt;
1697     struct _EncWsNode * TheNode;
1698     const struct KDirectory * Workspace;
1699 
1700     RCt = 0;
1701     TheNode = NULL;
1702     Workspace = NULL;
1703 
1704     XFS_CSAN ( Node )
1705     XFS_CAN ( Name )
1706     XFS_CAN ( Path )
1707     XFS_CAN ( Password )
1708     XFS_CAN ( Node )
1709 
1710     RCt = XFSEncDirectoryOpen (
1711                             & Workspace,
1712                             ! ReadOnly,
1713                             Password,
1714                             EncType,
1715                             Path
1716                             );
1717     if ( RCt == 0 ) {
1718         RCt = _EncWsNodeMake ( & TheNode, Workspace, Name, Path );
1719         if ( RCt == 0 ) {
1720             * Node = & ( TheNode -> node );
1721         }
1722 
1723         KDirectoryRelease ( Workspace );
1724     }
1725 
1726     return RCt;
1727 }   /* XFSWorkspaceNodeMake () */
1728 
1729 /*)))
1730  |||
1731  +++    FileNode has a Teleport, and it is HERE
1732  |||
1733 (((*/
1734 static
1735 rc_t CC
_WorkspaceNodeConstructor(const struct XFSModel * Model,const struct XFSModelNode * Template,const char * Alias,const struct XFSNode ** Node)1736 _WorkspaceNodeConstructor (
1737                         const struct XFSModel * Model,
1738                         const struct XFSModelNode * Template,
1739                         const char * Alias,
1740                         const struct XFSNode ** Node
1741 )
1742 {
1743     rc_t RCt;
1744 
1745     RCt = _EncWsNodeConstructor ( Model, Template, Alias, Node );
1746 
1747 /*
1748 pLogMsg ( klogDebug, "_WorkspaceNodeConstructor ( $(model), $(template) (\"name\"), \"alias\" )", "model=%p,template=%p,name=%s,alias=%s", ( void * ) Model, ( void * ) Template, XFSModelNodeName ( Template ), ( Alias == NULL ? "NULL" : Alias ) );
1749 */
1750 
1751     return RCt;
1752 }   /* _WorkspaceNodeConstructor () */
1753 
1754 static
1755 rc_t CC
_WorkspaceNodeValidator(const struct XFSModel * Model,const struct XFSModelNode * Template,const char * Alias,uint32_t Flags)1756 _WorkspaceNodeValidator (
1757             const struct XFSModel * Model,
1758             const struct XFSModelNode * Template,
1759             const char * Alias,
1760             uint32_t Flags
1761 )
1762 {
1763     rc_t RCt;
1764 
1765     RCt = 0;
1766 
1767 /*
1768 pLogMsg ( klogDebug, "_WorkspaceNodeValidator ( $(model), $(template) (\"name\"), \"alias\" )", "model=%p,template=%p,name=%s,alias=%s", ( void * ) Model, ( void * ) Template, XFSModelNodeName ( Template ), ( Alias == NULL ? "NULL" : Alias ) );
1769 */
1770 
1771     return RCt;
1772 }   /* _WorkspaceNodeValidator () */
1773 
1774 static const struct XFSTeleport _sWorkspaceNodeTeleport = {
1775                                             _WorkspaceNodeConstructor,
1776                                             _WorkspaceNodeValidator,
1777                                             false
1778                                             };
1779 
1780 
1781 LIB_EXPORT
1782 rc_t CC
XFSWorkspaceProvider(const struct XFSTeleport ** Teleport)1783 XFSWorkspaceProvider ( const struct XFSTeleport ** Teleport )
1784 {
1785     if ( Teleport == NULL ) {
1786         return XFS_RC ( rcNull );
1787     }
1788 
1789     * Teleport = & _sWorkspaceNodeTeleport;
1790 
1791     return 0;
1792 }   /* XFSWorkspaceProvider () */
1793 
1794