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