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 <kfs/extern.h>
27 #include <kfs/quickmount.h>
28 #include <kfs/directory.h>
29 
30 #include <klib/rc.h>
31 #include <klib/printf.h>
32 
33 #include <sysalloc.h>
34 
35 #include <string.h>
36 #include <stdlib.h>
37 #include <assert.h>
38 
39 /* ----------------------------------------------------------------------
40  *
41  */
42 
43 /* -----
44  * define the specific types to be used in the templatish/inheritancish
45  * definition of vtables and their elements
46  */
47 #define KDIR_IMPL struct KQuickMountDir
48 #define KNAMELIST_IMPL   struct KQuickMountListing
49 #include <kfs/impl.h>
50 
51 /* ======================================================================
52  */
53 /*--------------------------------------------------------------------------
54  * KQuickMountDir
55  *  a directory inside an archive (tar or SRA for example)
56  *
57  * This type is being engineered to mimic KQuickMountDir.
58  */
59 struct KQuickMountDir
60 {
61     KDirectory   dad;
62     int          root;
63     const KFile* file;
64     char *       mount;
65     char         path[1];
66     /* actual allocation is based on actual string length */
67 };
68 
69 
70 
71 /* KQuickMountDirCanonPath
72  */
73 static
KQuickMountDirCanonPath(const KQuickMountDir * self,enum RCContext ctx,char * path,size_t psize)74 rc_t KQuickMountDirCanonPath ( const KQuickMountDir *self, enum RCContext ctx, char *path, size_t psize )
75 {
76     char *low, *dst, *last, *end = path + psize;
77     low = dst = last = path + self -> root;
78 
79     while ( 1 )
80     {
81         char *src = strchr ( last + 1, '/' );
82         if ( src == NULL )
83             src = end;
84 
85         /* detect special sequences */
86         switch ( src - last )
87         {
88         case 2:
89             if ( last [ 1 ] == '.' )
90             {
91                 /* skip over */
92                 last = src;
93                 if ( src != end )
94                     continue;
95             }
96             break;
97 
98         case 3:
99             if ( last [ 1 ] == '.' && last [ 2 ] == '.' )
100             {
101                 /* remove previous leaf in path */
102                 dst [ 0 ] = 0;
103                 dst = strrchr ( path, '/' );
104                 if ( dst == NULL || dst < low )
105                     return RC ( rcFS, rcDirectory, ctx, rcPath, rcInvalid );
106 
107                 last = src;
108                 if ( src != end )
109                     continue;
110             }
111             break;
112         }
113 
114         /* if rewriting, copy leaf */
115         assert ( src >= last );
116 
117         if ( dst != last )
118             memmove ( dst, last, src - last );
119 
120         /* move destination ahead */
121         dst += src - last;
122 
123         /* if we're done, go */
124         if ( src == end )
125                 break;
126 
127         /* find next separator */
128         last = src;
129     }
130 
131     /* NUL terminate if modified */
132     if ( dst != end )
133         * dst = 0;
134 
135     return 0;
136 }
137 
138 /* KQuickMountDirRelativePath
139  *  makes "path" relative to "root"
140  *  both "root" and "path" MUST be absolute
141  *  both "root" and "path" MUST be canonical, i.e. have no "./" or "../" sequences
142  */
143 static
KQuickMountDirRelativePath(const KQuickMountDir * self,enum RCContext ctx,const char * root,char * path,size_t path_max)144 rc_t KQuickMountDirRelativePath (const KQuickMountDir *self, enum RCContext ctx,
145                                  const char *root, char *path, size_t path_max)
146 {
147     int backup;
148     size_t bsize, psize;
149 
150     const char *r = root + self -> root;
151     const char *p = path + self -> root;
152 
153     assert ( r != NULL && r [ 0 ] == '/' );
154     assert ( p != NULL && p [ 0 ] == '/' );
155 
156     for ( ; * r == * p; ++ r, ++ p )
157     {
158         /* disallow identical paths */
159         if ( * r == 0 )
160             return RC ( rcFS, rcDirectory, ctx, rcPath, rcInvalid );
161     }
162 
163     /* paths are identical up to "r","p"
164        if "r" is within a leaf name, then no backup is needed
165        by counting every '/' from "r" to end, obtain backup count */
166     for ( backup = 0; * r != 0; ++ r )
167     {
168         if ( * r == '/' )
169             ++ backup;
170     }
171 
172     /* the number of bytes to be inserted */
173     bsize = backup * 3;
174 
175     /* align "p" to last directory separator */
176     while ( p [ -1 ] != '/' ) -- p;
177 
178     /* the size of the remaining relative path */
179     psize = strlen ( p );
180 
181     /* open up space if needed */
182     if ( (size_t) (p - path) < bsize )
183     {
184         /* prevent overflow */
185         if ( bsize + psize >= path_max )
186             return RC ( rcFS, rcDirectory, ctx, rcPath, rcExcessive );
187         memmove ( path + bsize, p, psize + 1 /* 1 for '\0'*/ );
188     }
189 
190     /* insert backup sequences */
191     for ( bsize = 0; backup > 0; bsize += 3, -- backup )
192         memmove ( & path [ bsize ], "../", 3 );
193 
194     /* close gap */
195     if ( (size_t) (p - path) > bsize )
196         memmove ( & path [ bsize ], p, strlen ( p ) + 1 );
197 
198     return 0;
199 }
200 
201 
202 
203 static __inline__
KQuickMountDirVMakePath(const KQuickMountDir * self,enum RCContext ctx,bool canon,char * buffer,size_t path_max,const char * path,va_list args)204 rc_t KQuickMountDirVMakePath (const KQuickMountDir * self, enum RCContext ctx,
205                               bool canon, char * buffer, size_t path_max,
206                               const char * path, va_list args)
207 {
208     size_t psize;
209     size_t bsize;
210     rc_t rc;
211 
212     if ( path == NULL )
213         return RC ( rcFS, rcDirectory, ctx, rcPath, rcNull );
214     if ( path [ 0 ] == 0 )
215         return RC ( rcFS, rcDirectory, ctx, rcPath, rcInvalid );
216 
217     /*VDB-4386: cannot treat va_list as a pointer!*/
218     if ( /*args != NULL &&*/ path [ 0 ] == '%' )
219     {
220         rc = string_vprintf (buffer, path_max, &psize, path, args);
221 
222         if (psize > path_max)
223             return RC ( rcFS, rcDirectory, ctx, rcPath, rcExcessive );
224         if (rc)
225             return rc;
226         if ( buffer [ 0 ] != '/' )
227         {
228             bsize = (self->mount - self->path) - 1;
229             if ( bsize + psize >= path_max )
230                 return RC ( rcFS, rcDirectory, ctx, rcPath, rcExcessive );
231             memmove ( buffer + bsize, buffer, psize + 1 );
232             assert ( self -> path [ bsize - 1 ] == '/' );
233             memmove ( buffer, self -> path, bsize );
234         }
235         else if ( ( bsize = self -> root ) != 0 )
236         {
237             if ( bsize + psize >= path_max )
238                 return RC ( rcFS, rcDirectory, ctx, rcPath, rcExcessive );
239             memmove ( buffer + bsize, buffer, psize + 1 );
240             assert ( self -> path [ bsize - 1 ] != '/' );
241             memmove ( buffer, self -> path, bsize );
242         }
243     }
244     else
245     {
246         if ( path [ 0 ] != '/' )
247         {
248 /*             assert ( self -> path [ self -> size - 1 ] == '/' ); */
249             memmove ( buffer, self -> path, bsize = (self->mount - self->path) - 1 );
250         }
251         else if ( ( bsize = self -> root ) != 0 )
252         {
253             assert ( self -> path [ bsize - 1 ] != '/' );
254             memmove ( buffer, self -> path, bsize );
255         }
256 
257 
258         rc = string_vprintf ( buffer + bsize, path_max - bsize, &psize, path, args );
259         if (bsize + psize >= path_max)
260             return RC ( rcFS, rcDirectory, ctx, rcPath, rcExcessive );
261         if (rc)
262             return rc;
263     }
264 
265     if ( buffer [ bsize + psize ] == '/' )
266         buffer [ bsize + -- psize ] = 0;
267 
268     if ( psize > 0 && ( canon || self -> root != 0 ) )
269         return KQuickMountDirCanonPath ( self, ctx, buffer, bsize + psize );
270 
271     return 0;
272 }
273 
274 
275 static __inline__
KQuickMountDirMakePath(const KQuickMountDir * self,enum RCContext ctx,bool canon,char * buffer,size_t path_max,const char * path,...)276 rc_t KQuickMountDirMakePath (const KQuickMountDir * self, enum RCContext ctx,
277                              bool canon, char * buffer, size_t path_max,
278                              const char * path, ...)
279 {
280     va_list args;
281     rc_t rc;
282 
283     va_start (args, path);
284     rc = KQuickMountDirVMakePath (self, ctx, canon, buffer,
285                                   path_max, path, args);
286     va_end (args);
287     return rc;
288 }
289 
290 
291 /* ----------------------------------------------------------------------
292  * KQuickMountDirDestroy
293  */
KQuickMountDirDestroy(KQuickMountDir * self)294 static rc_t CC KQuickMountDirDestroy (KQuickMountDir *self)
295 {
296     rc_t rc;
297 
298     rc = KFileRelease (self->file);
299 
300     free (self);
301 
302     return rc;
303 }
304 
305 
306 /* ----------------------------------------------------------------------
307  * KQuickMountDirList
308  *  create a directory listing
309  *
310  *  "list" [ OUT ] - return parameter for list object
311  *
312  *  "path" [ IN, NULL OKAY ] - optional parameter for target
313  *  directory. if NULL, interpreted to mean "."
314  *
315  * [RET] rc_t					0 for success; anything else for a failure
316  *						see itf/klib/rc.h for general details
317  * [IN]	 const KQuickMountDir *	self		Object oriented C; KQuickMountDir object for this method
318  * [OUT] KNamelist **		listp,
319  * [IN]  bool (* 		f	)(const KDirectory*,const char *, void *)
320  * [IN]  void *			data
321  * [IN]  const char *		path
322  * [IN]  va_list		args
323  */
324 static
KQuickMountDirList(const KQuickMountDir * self,KNamelist ** listp,bool (CC * f)(const KDirectory * dir,const char * name,void * data),void * data,const char * path,va_list args)325 rc_t CC KQuickMountDirList (const KQuickMountDir *self,
326                        KNamelist **listp,
327                        bool (CC* f) (const KDirectory *dir, const char *name, void *data),
328                        void *data,
329                        const char *path,
330                        va_list args)
331 {
332     return RC (rcFS, rcDirectory, rcAccessing, rcFunction, rcUnsupported);
333 }
334 
335 
336 /* ----------------------------------------------------------------------
337  * KQuickMountDirVisit
338  *  visit each path under designated directory,
339  *  recursively if so indicated
340  *
341  *  "recurse" [ IN ] - if non-zero, recursively visit sub-directories
342  *
343  *  "f" [ IN ] and "data" [ IN, OPAQUE ] - function to execute
344  *  on each path. receives a base directory and relative path
345  *  for each entry, where each path is also given the leaf name
346  *  for convenience. if "f" returns non-zero, the iteration will
347  *  terminate and that value will be returned. NB - "dir" will not
348  *  be the same as "self".
349  *
350  *  "path" [ IN ] - NUL terminated string in directory-native character set
351  */
352 static
KQuickMountDirVisit(const KQuickMountDir * self,bool recurse,rc_t (CC * f)(const KDirectory *,uint32_t,const char *,void *),void * data,const char * path,va_list args)353 rc_t CC KQuickMountDirVisit (const KQuickMountDir *self,
354                       bool recurse,
355                       rc_t (CC* f) (const KDirectory *, uint32_t, const char *, void *),
356                       void *data,
357                       const char *path,
358                       va_list args)
359 {
360     return RC (rcFS, rcDirectory, rcAccessing, rcFunction, rcUnsupported);
361 }
362 
363 
364 /* ----------------------------------------------------------------------
365  * KQuickMountDirVisitUpdate
366  */
KQuickMountDirVisitUpdate(KQuickMountDir * self,bool recurse,rc_t (CC * f)(KDirectory *,uint32_t,const char *,void *),void * data,const char * path,va_list args)367 static rc_t CC KQuickMountDirVisitUpdate (KQuickMountDir *self,
368                                    bool recurse,
369                                    rc_t (CC*f) (KDirectory *,uint32_t,const char *,void *),
370                                    void *data,
371                                    const char *path,
372                                    va_list args)
373 {
374     return RC (rcFS, rcDirectory, rcUpdating, rcFunction, rcUnsupported);
375 }
376 
377 
378 /* ----------------------------------------------------------------------
379  * KQuickMountDirPathType
380  *  returns a KPathType
381  *
382  *  "path" [ IN ] - NUL terminated string in directory-native character set
383  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
384  *
385  * [RET] uint32_t
386  * [IN]  const KQuickMountDir *	self		Object oriented C; KQuickMountDir object for this method
387  * [IN]  const char *		path
388  * [IN]  va_list		args
389  */
KQuickMountDirPathType(const KQuickMountDir * self,const char * path,va_list args)390 static uint32_t CC KQuickMountDirPathType (const KQuickMountDir *self, const char *path, va_list args)
391 {
392     char buff [8192];
393     rc_t rc;
394 
395     rc = KQuickMountDirVMakePath (self, rcAccessing, true, buff, sizeof buff, path, args);
396     if (rc)
397         return kptBadPath;
398 
399     if (strcmp (buff, self->path) == 0)
400         return kptFile;
401 
402     return kptNotFound;
403 }
404 
405 
406 /* ----------------------------------------------------------------------
407  * KQuickMountDirResolvePath
408  *
409  *  resolves path to an absolute or directory-relative path
410  *
411  * [IN]  const KQuickMountDir *self		Objected oriented self
412  * [IN]	 bool 		absolute	if non-zero, always give a path starting
413  *  					with '/'. NB - if the directory is
414  *					chroot'd, the absolute path
415  *					will still be relative to directory root.
416  * [OUT] char *		resolved	buffer for NUL terminated result path in
417  *					directory-native character set
418  * [IN]	 size_t		rsize		limiting size of resolved buffer
419  * [IN]  const char *	path		NUL terminated string in directory-native
420  *					character set denoting target path.
421  *					NB - need not exist.
422  *
423  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
424  */
KQuickMountDirResolvePath(const KQuickMountDir * self,bool absolute,char * resolved,size_t rsize,const char * path,va_list args)425 static rc_t CC KQuickMountDirResolvePath (const KQuickMountDir *self,
426                                           bool absolute,
427                                           char *resolved,
428                                           size_t rsize,
429                                           const char *path,
430                                           va_list args)
431 {
432     char full [ 8192 ];
433     rc_t rc = KQuickMountDirVMakePath ( self, rcResolving, true, full, sizeof full, path, args );
434     if ( rc == 0 )
435     {
436         size_t path_size = strlen ( full );
437 
438         if ( absolute )
439         {
440             /* test buffer capacity */
441             if ( path_size - self -> root >= rsize )
442                 return RC ( rcFS, rcDirectory, rcResolving, rcBuffer, rcInsufficient );
443 
444             /* ready to go */
445             strcpy ( resolved, & full [ self -> root ] );
446 /*             assert ( resolved [ 0 ] == '/' ); */
447         }
448         else
449         {
450             rc = KQuickMountDirRelativePath ( self, rcResolving, self -> path, full, sizeof full /*path_size*/ );
451             if ( rc == 0 )
452             {
453                 path_size = strlen ( full );
454                 if ( path_size >= rsize )
455                     return RC ( rcFS, rcDirectory, rcResolving, rcBuffer, rcInsufficient );
456                 strcpy ( resolved, full );
457             }
458         }
459     }
460     return rc;
461 }
462 
463 
464 /* ----------------------------------------------------------------------
465  * KQuickMountDirResolveAlias
466  *  resolves an alias path to its immediate target
467  *  NB - the resolved path may be yet another alias
468  *
469  *  "alias" [ IN ] - NUL terminated string in directory-native
470  *  character set denoting an object presumed to be an alias.
471  *
472  *  "resolved" [ OUT ] and "rsize" [ IN ] - buffer for
473  *  NUL terminated result path in directory-native character set
474  *
475  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
476  */
KQuickMountDirResolveAlias(const KQuickMountDir * self,bool absolute,char * resolved,size_t rsize,const char * alias,va_list args)477 static rc_t CC KQuickMountDirResolveAlias (const KQuickMountDir * self,
478 				 bool absolute,
479 				 char * resolved,
480 				 size_t rsize,
481 				 const char *alias,
482 				 va_list args)
483 {
484     return RC (rcFS, rcDirectory, rcAccessing, rcFunction, rcUnsupported);
485 }
486 
487 /* ----------------------------------------------------------------------
488  * KQuickMountDirRename
489  *  rename an object accessible from directory, replacing
490  *  any existing target object of the same type
491  *
492  *  "from" [ IN ] - NUL terminated string in directory-native
493  *  character set denoting existing object
494  *
495  *  "to" [ IN ] - NUL terminated string in directory-native
496  *  character set denoting existing object
497  */
498 static
KQuickMountDirRename(KQuickMountDir * self,bool force,const char * from,const char * to)499 rc_t CC KQuickMountDirRename (KQuickMountDir *self, bool force, const char *from, const char *to)
500 {
501     assert (self != NULL);
502     assert (from != NULL);
503     assert (to != NULL);
504 
505     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
506 }
507 
508 /* ----------------------------------------------------------------------
509  * KQuickMountDirRemove
510  *  remove an accessible object from its directory
511  *
512  *  "path" [ IN ] - NUL terminated string in directory-native
513  *  character set denoting target object
514  *
515  *  "force" [ IN ] - if non-zero and target is a directory,
516  *  remove recursively
517  */
518 static
KQuickMountDirRemove(KQuickMountDir * self,bool force,const char * path,va_list args)519 rc_t CC KQuickMountDirRemove (KQuickMountDir *self, bool force, const char *path, va_list args)
520 {
521     assert (self != NULL);
522     assert (path != NULL);
523 
524     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
525 }
526 
527 /* ----------------------------------------------------------------------
528  * KQuickMountDirClearDir
529  *  remove all directory contents
530  *
531  *  "path" [ IN ] - NUL terminated string in directory-native
532  *  character set denoting target directory
533  *
534  *  "force" [ IN ] - if non-zero and directory entry is a
535  *  sub-directory, remove recursively
536  */
537 static
KQuickMountDirClearDir(KQuickMountDir * self,bool force,const char * path,va_list args)538 rc_t CC KQuickMountDirClearDir (KQuickMountDir *self, bool force, const char *path, va_list args)
539 {
540     assert (self != NULL);
541     assert (path != NULL);
542 
543     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
544 }
545 
546 
547 /* ----------------------------------------------------------------------
548  * KQuickMountDirAccess
549  *  get access to object
550  *
551  *  "access" [ OUT ] - return parameter for Unix access mode
552  *
553  *  "path" [ IN ] - NUL terminated string in directory-native
554  *  character set denoting target object
555  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
556  */
KQuickMountDirVAccess(const KQuickMountDir * self,uint32_t * access,const char * path,va_list args)557 static rc_t CC KQuickMountDirVAccess (const KQuickMountDir *self,
558 			    uint32_t *access,
559 			    const char *path,
560 			    va_list args)
561 {
562     return RC (rcFS, rcDirectory, rcAccessing, rcFunction, rcUnsupported);
563 }
564 
565 
566 /* ----------------------------------------------------------------------
567  * KQuickMountDirSetAccess
568  *  set access to object a la Unix "chmod"
569  *
570  *  "path" [ IN ] - NUL terminated string in directory-native
571  *  character set denoting target object
572  *
573  *  "access" [ IN ] and "mask" [ IN ] - definition of change
574  *  where "access" contains new bit values and "mask defines
575  *  which bits should be changed.
576  *
577  *  "recurse" [ IN ] - if non zero and "path" is a directory,
578  *  apply changes recursively.
579  */
KQuickMountDirSetAccess(KQuickMountDir * self,bool recurse,uint32_t access,uint32_t mask,const char * path,va_list args)580 static rc_t CC KQuickMountDirSetAccess (KQuickMountDir *self,
581 			      bool recurse,
582 			      uint32_t access,
583 			      uint32_t mask,
584 			      const char *path,
585 			      va_list args)
586 {
587     assert (self != NULL);
588     assert (path != NULL);
589 
590     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
591 }
592 
593 
594 /* ----------------------------------------------------------------------
595  * KQuickMountDirCreateAlias
596  *  creates a path alias according to create mode
597  *
598  *  "targ" [ IN ] - NUL terminated string in directory-native
599  *  character set denoting target object
600  *
601  *  "alias" [ IN ] - NUL terminated string in directory-native
602  *  character set denoting target alias
603  *
604  *  "access" [ IN ] - standard Unix directory access mode
605  *  used when "mode" has kcmParents set and alias path does
606  *  not exist.
607  *
608  *  "mode" [ IN ] - a creation mode (see explanation above).
609  */
610 static
KQuickMountDirCreateAlias(KQuickMountDir * self,uint32_t access,KCreateMode mode,const char * targ,const char * alias)611 rc_t CC KQuickMountDirCreateAlias (KQuickMountDir *self,
612 			 uint32_t access,
613 			 KCreateMode mode,
614 			 const char *targ,
615 			 const char *alias)
616 {
617     assert (self != NULL);
618     assert (targ != NULL);
619     assert (alias != NULL);
620 
621     return RC (rcFS, rcDirectory, rcCreating, rcSelf, rcUnsupported);
622 }
623 
624 
625 /* ----------------------------------------------------------------------
626  * KQuickMountDirOpenFileRead
627  *  opens an existing file with read-only access
628  *
629  *  "f" [ OUT ] - return parameter for newly opened file
630  *
631  *  "path" [ IN ] - NUL terminated string in directory-native
632  *  character set denoting target file
633  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
634  */
635 static
KQuickMountDirOpenFileRead(const KQuickMountDir * self,const KFile ** f,const char * path,va_list args)636 rc_t CC KQuickMountDirOpenFileRead	(const KQuickMountDir *self,
637 					 const KFile **f,
638 					 const char *path,
639 					 va_list args)
640 {
641     return RC (rcFS, rcDirectory, rcOpening, rcSelf, rcUnsupported);
642 }
643 
644 
645 /* ----------------------------------------------------------------------
646  * KQuickMountDirOpenFileWrite
647  *  opens an existing file with write access
648  *
649  *  "f" [ OUT ] - return parameter for newly opened file
650  *
651  *  "path" [ IN ] - NUL terminated string in directory-native
652  *  character set denoting target file
653  *
654  *  "update" [ IN ] - if non-zero, open in read/write mode
655  *  otherwise, open in write-only mode
656  */
657 static
KQuickMountDirOpenFileWrite(KQuickMountDir * self,KFile ** f,bool update,const char * path,va_list args)658 rc_t CC KQuickMountDirOpenFileWrite	(KQuickMountDir *self,
659 					 KFile **f,
660 					 bool update,
661 					 const char *path,
662 					 va_list args)
663 {
664     assert (self != NULL);
665     assert (f != NULL);
666     assert (path != NULL);
667 
668     return RC (rcFS, rcDirectory, rcCreating, rcSelf, rcUnsupported);
669 }
670 
671 
672 /* ----------------------------------------------------------------------
673  * KQuickMountDirCreateFile
674  *  opens a file with write access
675  *
676  *  "f" [ OUT ] - return parameter for newly opened file
677  *
678  *  "path" [ IN ] - NUL terminated string in directory-native
679  *  character set denoting target file
680  *
681  *  "access" [ IN ] - standard Unix access mode, e.g. 0664
682  *
683  *  "update" [ IN ] - if non-zero, open in read/write mode
684  *  otherwise, open in write-only mode
685  *
686  *  "mode" [ IN ] - a creation mode (see explanation above).
687  */
688 static
KQuickMountDirCreateFile(KQuickMountDir * self,KFile ** f,bool update,uint32_t access,KCreateMode cmode,const char * path,va_list args)689 rc_t CC KQuickMountDirCreateFile	(KQuickMountDir *self,
690 					 KFile **f,
691 					 bool update,
692 					 uint32_t access,
693 					 KCreateMode cmode,
694 					 const char *path,
695 					 va_list args)
696 {
697     assert (self != NULL);
698     assert (f != NULL);
699     assert (path != NULL);
700 
701     return RC (rcFS, rcDirectory, rcCreating, rcSelf, rcUnsupported);
702 }
703 
704 
705 /* ----------------------------------------------------------------------
706  * KQuickMountDirFileSize
707  *  returns size in bytes of target file
708  *
709  *  "path" [ IN ] - NUL terminated string in directory-native
710  *  character set denoting target file
711  *
712  *  "size" [ OUT ] - return parameter for file size
713  * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path
714  */
715 static
KQuickMountDirFileSize(const KQuickMountDir * self,uint64_t * size,const char * path,va_list args)716 rc_t CC KQuickMountDirFileSize		(const KQuickMountDir *self,
717 					 uint64_t *size,
718 					 const char *path,
719 					 va_list args)
720 {
721     return RC (rcFS, rcDirectory, rcCreating, rcSelf, rcUnsupported);
722 }
723 
724 
725 /* ----------------------------------------------------------------------
726  * KQuickMountDirSetFileSize
727  *  sets size in bytes of target file
728  *
729  *  "path" [ IN ] - NUL terminated string in directory-native
730  *  character set denoting target file
731  *
732  *  "size" [ IN ] - new file size
733  */
734 static
KQuickMountDirSetFileSize(KQuickMountDir * self,uint64_t size,const char * path,va_list args)735 rc_t CC KQuickMountDirSetFileSize	(KQuickMountDir *self,
736 					 uint64_t size,
737 					 const char *path,
738 					 va_list args)
739 {
740     assert (self != NULL);
741     assert (path != NULL);
742 
743     return RC (rcFS, rcDirectory, rcWriting, rcSelf, rcUnsupported);
744 }
745 
746 
747 /* ----------------------------------------------------------------------
748  * KQuickMountDirOpenDirRead
749  *
750  *  opens a sub-directory
751  *
752  * [IN]  const KQuickMountDir *	self	Object Oriented C KQuickMountDir self
753  * [OUT] const KDirectory **	subp	Where to put the new KDirectory/KQuickMountDir
754  * [IN]  bool			chroot	Create a chroot cage for this new subdirectory
755  * [IN]  const char *		path	Path to the directory to open
756  * [IN]  va_list		args	So far the only use of args is possible additions to path
757  */
758 static
KQuickMountDirOpenDirRead(const KQuickMountDir * self,const KDirectory ** subp,bool chroot,const char * path,va_list args)759 rc_t CC KQuickMountDirOpenDirRead	(const KQuickMountDir *self,
760 					 const KDirectory **subp,
761 					 bool chroot,
762 					 const char *path,
763 					 va_list args)
764 {
765     return RC (rcFS, rcDirectory, rcOpening, rcSelf, rcUnsupported);
766 }
767 
768 
769 /* ----------------------------------------------------------------------
770  * KQuickMountDirOpenDirUpdate
771  *  opens a sub-directory
772  *
773  *  "path" [ IN ] - NUL terminated string in directory-native
774  *  character set denoting target directory
775  *
776  *  "chroot" [ IN ] - if non-zero, the new directory becomes
777  *  chroot'd and will interpret paths beginning with '/'
778  *  relative to itself.
779  */
780 static
KQuickMountDirOpenDirUpdate(KQuickMountDir * self,KDirectory ** subp,bool chroot,const char * path,va_list args)781 rc_t CC KQuickMountDirOpenDirUpdate	(KQuickMountDir *self,
782 					 KDirectory ** subp,
783 					 bool chroot,
784 					 const char *path,
785 					 va_list args)
786 {
787     assert (self != NULL);
788     assert (subp != NULL);
789     assert (path != NULL);
790 
791     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
792 }
793 
794 /* ----------------------------------------------------------------------
795  * KQuickMountDirCreateDir
796  *  create a sub-directory
797  *
798  *  "path" [ IN ] - NUL terminated string in directory-native
799  *  character set denoting target directory
800  *
801  *  "access" [ IN ] - standard Unix directory permissions
802  *
803  *  "mode" [ IN ] - a creation mode (see explanation above).
804  */
805 static
KQuickMountDirCreateDir(KQuickMountDir * self,uint32_t access,KCreateMode mode,const char * path,va_list args)806 rc_t CC KQuickMountDirCreateDir	(KQuickMountDir *self,
807 					 uint32_t access,
808 					 KCreateMode mode,
809 					 const char *path,
810 					 va_list args)
811 {
812     assert (self != NULL);
813     assert (path != NULL);
814 
815     return RC (rcFS, rcDirectory, rcCreating, rcSelf, rcUnsupported);
816 }
817 
818 
819 /* ----------------------------------------------------------------------
820  * KQuickMountDirDestroyFile
821  */
822 #if 0
823 static
824 rc_t CC KQuickMountDirDestroyFile	(KQuickMountDir *self,
825 					 KFile * f)
826 {
827     assert (self != NULL);
828     assert (f != NULL);
829 
830     return RC (rcFS, rcDirectory, rcDestroying, rcSelf, rcUnsupported);
831 }
832 
833 
834 static	rc_t CC KQuickMountDirDate (const KQuickMountDir *self,
835 					 KTime_t *date,
836 					 const char *path,
837 					 va_list args)
838 {
839     return RC (rcFS, rcDirectory, rcAccessing, rcSelf, rcUnsupported);
840 
841 }
842 
843 
844 static	rc_t CC KQuickMountDirSetDate		(KQuickMountDir *self,
845 					 bool recurse,
846 					 KTime_t date,
847 					 const char *path,
848 					 va_list args)
849 {
850     assert (self != NULL);
851     assert (path != NULL);
852 
853     return RC (rcFS, rcDirectory, rcUpdating, rcSelf, rcUnsupported);
854 }
855 #endif
856 
857 /* ----------------------------------------------------------------------
858  *
859  */
860 static KDirectory_vt_v1 vtKQuickMountDir =
861 {
862     /* version 1.0 */
863     1, 0,
864 
865     /* start minor version 0 methods*/
866     KQuickMountDirDestroy,
867     KQuickMountDirList,
868     KQuickMountDirVisit,
869     KQuickMountDirVisitUpdate,
870     KQuickMountDirPathType,
871     KQuickMountDirResolvePath,
872     KQuickMountDirResolveAlias,
873     KQuickMountDirRename,
874     KQuickMountDirRemove,
875     KQuickMountDirClearDir,
876     KQuickMountDirVAccess,
877     KQuickMountDirSetAccess,
878     KQuickMountDirCreateAlias,
879     KQuickMountDirOpenFileRead,
880     KQuickMountDirOpenFileWrite,
881     KQuickMountDirCreateFile,
882     KQuickMountDirFileSize,
883     KQuickMountDirSetFileSize,
884     KQuickMountDirOpenDirRead,
885     KQuickMountDirOpenDirUpdate,
886     KQuickMountDirCreateDir,
887     NULL,
888     /* end minor version 0 methods*/
889     /* start minor version 1 methods*/
890     NULL,
891     NULL,
892     NULL,
893     /* end minor version 2 methods*/
894     NULL,
895     /* end minor version 2 methods*/
896     /* end minor version 3 methods*/
897     NULL,
898     NULL
899     /* end minor version 3 methods*/
900 };
901 
902 
KQuickMountDirAlloc(size_t path_size,size_t mount_size)903 static KQuickMountDir * KQuickMountDirAlloc (size_t path_size, size_t mount_size)
904 {
905     return calloc (sizeof (KQuickMountDir) + path_size + mount_size + 1, 1);
906 }
907 
908 
KQuickMountDirMake(const KDirectory * self,const KDirectory ** pnewdir,const KFile * file,const char * path,size_t path_size,const char * mount,size_t mount_size)909 KFS_EXTERN rc_t KQuickMountDirMake (const KDirectory * self,
910                                     const KDirectory ** pnewdir,
911                                     const KFile * file,
912                                     const char * path, size_t path_size,
913                                     const char * mount, size_t mount_size)
914 {
915     KQuickMountDir * newdir;
916     char * pc;
917     rc_t rc;
918     bool endslash;
919     char tbuff [8193];
920 
921     endslash = path[path_size-1] == '/';
922 
923     if (sizeof tbuff - 1 < mount_size)
924         return RC (rcFS, rcDirectory, rcCreating, rcBuffer, rcInsufficient);
925 
926     memmove (tbuff, mount, mount_size);
927     tbuff[mount_size] = '\0';
928 
929     while ((pc = strpbrk (tbuff, "\"\\/")) != NULL)
930         *pc = '_';
931 
932     rc = KFileAddRef (file);
933     if (rc == 0)
934     {
935         newdir = KQuickMountDirAlloc (path_size, mount_size);
936         if (newdir == NULL)
937             rc = RC (rcFS, rcDirectory, rcAllocating, rcMemory, rcExhausted);
938         else
939         {
940             newdir->file = file;
941             newdir->mount = newdir->path + path_size;
942             rc = KQuickMountDirMakePath (newdir, rcCreating, true, newdir->path,
943                                          path_size + 1 + mount_size + 1,
944                                          endslash?"%s%s":"%s/%s", path, tbuff);
945             if (rc == 0)
946             {
947                 rc = KDirectoryInit (&newdir->dad, (const KDirectory_vt*) &vtKQuickMountDir,
948                                      "KQuickMountDir", path?path:"(null)", false);
949                 if (rc == 0)
950                 {
951                     newdir->mount = newdir->path + path_size + 1;
952                     newdir->root = 0;
953                     *pnewdir = &newdir->dad;
954                     return 0;
955                 }
956 /*             rc = RC (rcFS, rcDirectory, rcInitializing, rcObject, rcInvalid); */
957             }
958             KQuickMountDirDestroy (newdir);
959         }
960         KFileRelease (file);
961     }
962     return rc;
963 }
964 
965 
966 
967 /* end of file quickmount.c */
968 
969