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