1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #define TRACK_REFERENCES 0
28
29 #include <kfs/extern.h>
30 #include <kfs/impl.h>
31 #include <klib/refcount.h>
32 #include <klib/rc.h>
33 #include <klib/text.h>
34 #include <klib/printf.h>
35 #include <sysalloc.h>
36
37 #include <stdlib.h>
38
39 /*--------------------------------------------------------------------------
40 * KDirectory
41 * a directory
42 */
43
44 static const char classname[] = "KDirectory";
45
46 /* AddRef
47 * creates a new reference
48 * ignores NULL references
49 */
KDirectoryAddRef_v1(const KDirectory_v1 * self)50 LIB_EXPORT rc_t CC KDirectoryAddRef_v1 ( const KDirectory_v1 *self )
51 {
52 if ( self != NULL )
53 {
54 switch ( KRefcountAdd ( & self -> refcount, classname ) )
55 {
56 case krefLimit:
57 return RC ( rcFS, rcDirectory, rcAttaching, rcRange, rcExcessive );
58 }
59 }
60 return 0;
61 }
62
63 /* Release
64 * discard reference to directory
65 * ignores NULL references
66 */
KDirectoryRelease_v1(const KDirectory_v1 * cself)67 LIB_EXPORT rc_t CC KDirectoryRelease_v1 ( const KDirectory_v1 *cself )
68 {
69 KDirectory_v1 *self = ( KDirectory* ) cself;
70 if ( cself != NULL )
71 {
72 switch ( KRefcountDrop ( & self -> refcount, classname ) )
73 {
74 case krefWhack:
75 {
76 rc_t rc;
77
78 switch ( self -> vt -> v1 . maj )
79 {
80 case 1:
81 rc = ( * self -> vt -> v1 . destroy ) ( self );
82 break;
83
84 default:
85 rc = RC ( rcFS, rcDirectory, rcReleasing, rcInterface, rcBadVersion );
86 }
87
88 if ( rc != 0 )
89 KRefcountInit ( & self -> refcount, 1, classname, "failed-release", "orphan" );
90 return rc;
91 }
92 case krefNegative:
93 return RC ( rcDB, rcTable, rcReleasing, rcRange, rcExcessive );
94 }
95 }
96 return 0;
97 }
98
99 /* List
100 * create a directory listing
101 *
102 * "list" [ OUT ] - return parameter for list object
103 *
104 * "path" [ IN, NULL OKAY ] - optional parameter for target
105 * directory. if NULL, interpreted to mean "." will be
106 * interpreted as format string if arguments follow
107 */
KDirectoryList_v1(const KDirectory_v1 * self,struct KNamelist ** list,bool (CC * f)(const KDirectory_v1 * dir,const char * name,void * data),void * data,const char * path,...)108 LIB_EXPORT rc_t CC KDirectoryList_v1 ( const KDirectory_v1 *self, struct KNamelist **list,
109 bool ( CC * f ) ( const KDirectory_v1 *dir, const char *name, void *data ),
110 void *data, const char *path, ... )
111 {
112 rc_t rc;
113 va_list args;
114
115 va_start ( args, path );
116 rc = KDirectoryVList ( self, list, f, data, path, args );
117 va_end ( args );
118
119 return rc;
120 }
121
KDirectoryVList(const KDirectory_v1 * self,struct KNamelist ** list,bool (CC * f)(const KDirectory_v1 * dir,const char * name,void * data),void * data,const char * path,va_list args)122 LIB_EXPORT rc_t CC KDirectoryVList ( const KDirectory_v1 *self, struct KNamelist **list,
123 bool ( CC * f ) ( const KDirectory_v1 *dir, const char *name, void *data ),
124 void *data, const char *path, va_list args )
125 {
126 if ( list == NULL )
127 return RC ( rcFS, rcDirectory, rcListing, rcParam, rcNull );
128
129 * list = NULL;
130
131 if ( self == NULL )
132 return RC ( rcFS, rcDirectory, rcListing, rcSelf, rcNull );
133
134 if ( path == NULL || path [ 0 ] == 0 )
135 path = ".";
136
137 switch ( self -> vt -> v1 . maj )
138 {
139 case 1:
140 return ( * self -> vt -> v1 . list_dir ) ( self, list, f, data, path, args );
141 }
142
143 return RC ( rcFS, rcDirectory, rcListing, rcInterface, rcBadVersion );
144 }
145
146 /* Visit
147 * visit each path under designated directory,
148 * recursively if so indicated
149 *
150 * "recurse" [ IN ] - if non-zero, recursively visit sub-directories
151 *
152 * "f" [ IN ] and "data" [ IN, OPAQUE ] - function to execute
153 * on each path. receives a base directory and relative path
154 * for each entry. if "f" returns non-zero, the iteration will
155 * terminate and that value will be returned. NB - "dir" will not
156 * be the same as "self".
157 *
158 * "path" [ IN ] - NUL terminated string in directory-native character set
159 */
KDirectoryVisit_v1(const KDirectory_v1 * self,bool recurse,rc_t (CC * f)(const KDirectory_v1 * dir,uint32_t type,const char * name,void * data),void * data,const char * path,...)160 LIB_EXPORT rc_t CC KDirectoryVisit_v1 ( const KDirectory_v1 *self, bool recurse,
161 rc_t ( CC * f ) ( const KDirectory_v1 *dir, uint32_t type, const char *name, void *data ),
162 void *data, const char *path, ... )
163 {
164 rc_t rc;
165 va_list args;
166
167 va_start ( args, path );
168 rc = KDirectoryVVisit ( self, recurse, f, data, path, args );
169 va_end ( args );
170
171 return rc;
172 }
173
KDirectoryVVisit(const KDirectory_v1 * self,bool recurse,rc_t (CC * f)(const KDirectory_v1 * dir,uint32_t type,const char * name,void * data),void * data,const char * path,va_list args)174 LIB_EXPORT rc_t CC KDirectoryVVisit ( const KDirectory_v1 *self, bool recurse,
175 rc_t ( CC * f ) ( const KDirectory_v1 *dir, uint32_t type, const char *name, void *data ),
176 void *data, const char *path, va_list args )
177 {
178 if ( self == NULL )
179 return RC ( rcFS, rcDirectory, rcVisiting, rcSelf, rcNull );
180 if ( f == NULL )
181 return RC ( rcFS, rcDirectory, rcVisiting, rcFunction, rcNull );
182
183 if ( path == NULL || path [ 0 ] == 0 )
184 path = ".";
185
186 switch ( self -> vt -> v1 . maj )
187 {
188 case 1:
189 return ( * self -> vt -> v1 . visit ) ( self, recurse, f, data, path, args );
190 }
191
192 return RC ( rcFS, rcDirectory, rcVisiting, rcInterface, rcBadVersion );
193 }
194
195 /* VisitUpdate
196 *
197 */
KDirectoryVisitUpdate_v1(KDirectory_v1 * self,bool recurse,rc_t (CC * f)(KDirectory_v1 * dir,uint32_t type,const char * name,void * data),void * data,const char * path,...)198 LIB_EXPORT rc_t CC KDirectoryVisitUpdate_v1 ( KDirectory_v1 *self, bool recurse,
199 rc_t ( CC * f ) ( KDirectory_v1 *dir, uint32_t type, const char *name, void *data ),
200 void *data, const char *path, ... )
201 {
202 rc_t rc;
203 va_list args;
204
205 va_start ( args, path );
206 rc = KDirectoryVVisitUpdate ( self, recurse, f, data, path, args );
207 va_end ( args );
208
209 return rc;
210 }
211
KDirectoryVVisitUpdate(KDirectory_v1 * self,bool recurse,rc_t (CC * f)(KDirectory_v1 * dir,uint32_t type,const char * name,void * data),void * data,const char * path,va_list args)212 LIB_EXPORT rc_t CC KDirectoryVVisitUpdate ( KDirectory_v1 *self, bool recurse,
213 rc_t ( CC * f ) ( KDirectory_v1 *dir, uint32_t type, const char *name, void *data ),
214 void *data, const char *path, va_list args )
215 {
216 if ( self == NULL )
217 return RC ( rcFS, rcDirectory, rcVisiting, rcSelf, rcNull );
218 if ( f == NULL )
219 return RC ( rcFS, rcDirectory, rcVisiting, rcFunction, rcNull );
220
221 if ( path == NULL || path [ 0 ] == 0 )
222 path = ".";
223
224 if ( self -> read_only )
225 return RC ( rcFS, rcDirectory, rcVisiting, rcDirectory, rcReadonly );
226
227 switch ( self -> vt -> v1 . maj )
228 {
229 case 1:
230 return ( * self -> vt -> v1 . visit_update )
231 ( self, recurse, f, data, path, args );
232 }
233
234 return RC ( rcFS, rcDirectory, rcVisiting, rcInterface, rcBadVersion );
235 }
236
237 /* PathType
238 * returns a KPathType
239 *
240 * "path" [ IN ] - NUL terminated string in directory-native character set
241 */
KDirectoryPathType_v1(const KDirectory_v1 * self,const char * path,...)242 LIB_EXPORT uint32_t CC KDirectoryPathType_v1 ( const KDirectory_v1 *self, const char *path, ... )
243 {
244 uint32_t type;
245 va_list args;
246
247 va_start ( args, path );
248 type = KDirectoryVPathType ( self, path, args );
249 va_end ( args );
250
251 return type;
252 }
253
KDirectoryVPathType(const KDirectory_v1 * self,const char * path,va_list args)254 LIB_EXPORT uint32_t CC KDirectoryVPathType ( const KDirectory_v1 *self, const char *path, va_list args )
255 {
256 if ( self == NULL || path == NULL || path [ 0 ] == 0 )
257 return kptBadPath;
258
259 switch ( self -> vt -> v1 . maj )
260 {
261 case 1:
262 return ( * self -> vt -> v1 . path_type ) ( self, path, args );
263 }
264
265 return kptBadPath;
266 }
267
268 /* ResolvePath
269 * resolves path to an absolute or directory-relative path
270 *
271 * "absolute" [ IN ] - if non-zero, always give a path starting
272 * with '/'. NB - if the directory is chroot'd, the absolute path
273 * will still be relative to directory root.
274 *
275 * "resolved" [ OUT ] and "rsize" [ IN ] - buffer for
276 * NUL terminated result path in directory-native character set
277 * the resolved path will be directory relative
278 *
279 * "path" [ IN ] - NUL terminated string in directory-native
280 * character set denoting target path. NB - need not exist.
281 */
KDirectoryResolvePath_v1(const KDirectory_v1 * self,bool absolute,char * resolved,size_t rsize,const char * path,...)282 LIB_EXPORT rc_t CC KDirectoryResolvePath_v1 ( const KDirectory_v1 *self, bool absolute,
283 char *resolved, size_t rsize, const char *path, ... )
284 {
285 rc_t rc;
286 va_list args;
287
288 va_start ( args, path );
289 rc = KDirectoryVResolvePath ( self, absolute,
290 resolved, rsize, path, args );
291 va_end ( args );
292
293 return rc;
294 }
295
KDirectoryVResolvePath(const KDirectory_v1 * self,bool absolute,char * resolved,size_t rsize,const char * path,va_list args)296 LIB_EXPORT rc_t CC KDirectoryVResolvePath ( const KDirectory_v1 *self, bool absolute,
297 char *resolved, size_t rsize, const char *path, va_list args )
298 {
299 if ( self == NULL )
300 return RC ( rcFS, rcDirectory, rcResolving, rcSelf, rcNull );
301
302 /* allow NULL buffers of 0 size */
303 if ( resolved == NULL && rsize != 0 )
304 return RC ( rcFS, rcDirectory, rcResolving, rcBuffer, rcNull );
305
306 if ( path == NULL )
307 return RC ( rcFS, rcDirectory, rcResolving, rcPath, rcNull );
308 if ( path [ 0 ] == 0 )
309 return RC ( rcFS, rcDirectory, rcResolving, rcPath, rcInvalid );
310
311 switch ( self -> vt -> v1 . maj )
312 {
313 case 1:
314 return ( * self -> vt -> v1 . resolve_path )
315 ( self, absolute, resolved, rsize, path, args );
316 }
317
318 return RC ( rcFS, rcDirectory, rcResolving, rcInterface, rcBadVersion );
319 }
320
321 /* ResolveAlias
322 * resolves an alias path to its immediate target
323 * NB - the resolved path may be yet another alias
324 *
325 * "absolute" [ IN ] - if non-zero, always give a path starting
326 * with '/'. NB - if the directory is chroot'd, the absolute path
327 * will still be relative to directory root.
328 *
329 * "resolved" [ OUT ] and "rsize" [ IN ] - buffer for
330 * NUL terminated result path in directory-native character set
331 * the resolved path will be directory relative
332 *
333 * "alias" [ IN ] - NUL terminated string in directory-native
334 * character set denoting an object presumed to be an alias.
335 */
KDirectoryResolveAlias_v1(const KDirectory_v1 * self,bool absolute,char * resolved,size_t rsize,const char * alias,...)336 LIB_EXPORT rc_t CC KDirectoryResolveAlias_v1 ( const KDirectory_v1 *self, bool absolute,
337 char *resolved, size_t rsize, const char *alias, ... )
338 {
339 rc_t rc;
340 va_list args;
341
342 va_start ( args, alias );
343 rc = KDirectoryVResolveAlias ( self, absolute,
344 resolved, rsize, alias, args );
345 va_end ( args );
346
347 return rc;
348 }
349
KDirectoryVResolveAlias(const KDirectory_v1 * self,bool absolute,char * resolved,size_t rsize,const char * alias,va_list args)350 LIB_EXPORT rc_t CC KDirectoryVResolveAlias ( const KDirectory_v1 *self, bool absolute,
351 char *resolved, size_t rsize, const char *alias, va_list args )
352 {
353 if ( self == NULL )
354 return RC ( rcFS, rcDirectory, rcResolving, rcSelf, rcNull );
355
356 /* allow NULL buffers of 0 size */
357 if ( resolved == NULL && rsize != 0 )
358 return RC ( rcFS, rcDirectory, rcResolving, rcBuffer, rcNull );
359
360 if ( alias == NULL )
361 return RC ( rcFS, rcDirectory, rcResolving, rcPath, rcNull );
362 if ( alias [ 0 ] == 0 )
363 return RC ( rcFS, rcDirectory, rcResolving, rcPath, rcInvalid );
364
365 switch ( self -> vt -> v1 . maj )
366 {
367 case 1:
368 return ( * self -> vt -> v1 . resolve_alias )
369 ( self, absolute, resolved, rsize, alias, args );
370 }
371
372 return RC ( rcFS, rcDirectory, rcResolving, rcInterface, rcBadVersion );
373 }
374
375 /* Rename
376 * rename an object accessible from directory, replacing
377 * any existing target object of the same type
378 *
379 * "from" [ IN ] - NUL terminated string in directory-native
380 * character set denoting existing object
381 *
382 * "to" [ IN ] - NUL terminated string in directory-native
383 * character set denoting existing object
384 */
KDirectoryRename_v1(KDirectory_v1 * self,bool force,const char * from,const char * to)385 LIB_EXPORT rc_t CC KDirectoryRename_v1 ( KDirectory_v1 *self, bool force, const char *from, const char *to )
386 {
387 if ( self == NULL )
388 return RC ( rcFS, rcDirectory, rcRenaming, rcSelf, rcNull );
389
390 if ( from == NULL || to == NULL )
391 return RC ( rcFS, rcDirectory, rcRenaming, rcPath, rcNull );
392 if ( from [ 0 ] == 0 || to [ 0 ] == 0 )
393 return RC ( rcFS, rcDirectory, rcRenaming, rcPath, rcInvalid );
394
395 if ( self -> read_only )
396 return RC ( rcFS, rcDirectory, rcRenaming, rcDirectory, rcReadonly );
397
398 switch ( self -> vt -> v1 . maj )
399 {
400 case 1:
401 return ( * self -> vt -> v1 . rename ) ( self, force, from, to );
402 }
403
404 return RC ( rcFS, rcDirectory, rcRenaming, rcInterface, rcBadVersion );
405 }
406
407 /* Remove
408 * remove an accessible object from its directory
409 *
410 * "force" [ IN ] - if non-zero and target is a directory,
411 * remove recursively
412 *
413 * "path" [ IN ] - NUL terminated string in directory-native
414 * character set denoting target object
415 */
KDirectoryRemove_v1(KDirectory_v1 * self,bool force,const char * path,...)416 LIB_EXPORT rc_t CC KDirectoryRemove_v1 ( KDirectory_v1 *self, bool force, const char *path, ... )
417 {
418 rc_t rc;
419 va_list args;
420
421 va_start ( args, path );
422 rc = KDirectoryVRemove ( self, force, path, args );
423 va_end ( args );
424
425 return rc;
426 }
427
KDirectoryVRemove(KDirectory_v1 * self,bool force,const char * path,va_list args)428 LIB_EXPORT rc_t CC KDirectoryVRemove ( KDirectory_v1 *self, bool force, const char *path, va_list args )
429 {
430 if ( self == NULL )
431 return RC ( rcFS, rcDirectory, rcRemoving, rcSelf, rcNull );
432
433 if ( path == NULL )
434 return RC ( rcFS, rcDirectory, rcRemoving, rcPath, rcNull );
435 if ( path [ 0 ] == 0 )
436 return RC ( rcFS, rcDirectory, rcRemoving, rcPath, rcInvalid );
437
438 if ( self -> read_only )
439 return RC ( rcFS, rcDirectory, rcRemoving, rcDirectory, rcReadonly );
440
441 switch ( self -> vt -> v1 . maj )
442 {
443 case 1:
444 return ( * self -> vt -> v1 . remove ) ( self, force, path, args );
445 }
446
447 return RC ( rcFS, rcDirectory, rcRemoving, rcInterface, rcBadVersion );
448 }
449
450 /* ClearDir
451 * remove all directory contents
452 *
453 * "force" [ IN ] - if non-zero and directory entry is a
454 * sub-directory, remove recursively
455 *
456 * "path" [ IN ] - NUL terminated string in directory-native
457 * character set denoting target directory
458 */
KDirectoryClearDir_v1(KDirectory_v1 * self,bool force,const char * path,...)459 LIB_EXPORT rc_t CC KDirectoryClearDir_v1 ( KDirectory_v1 *self, bool force, const char *path, ... )
460 {
461 rc_t rc;
462 va_list args;
463
464 va_start ( args, path );
465 rc = KDirectoryVClearDir ( self, force, path, args );
466 va_end ( args );
467
468 return rc;
469 }
470
KDirectoryVClearDir(KDirectory_v1 * self,bool force,const char * path,va_list args)471 LIB_EXPORT rc_t CC KDirectoryVClearDir ( KDirectory_v1 *self, bool force, const char *path, va_list args )
472 {
473 if ( self == NULL )
474 return RC ( rcFS, rcDirectory, rcRemoving, rcSelf, rcNull );
475
476 if ( path == NULL )
477 return RC ( rcFS, rcDirectory, rcRemoving, rcPath, rcNull );
478 if ( path [ 0 ] == 0 )
479 return RC ( rcFS, rcDirectory, rcRemoving, rcPath, rcInvalid );
480
481 if ( self -> read_only )
482 return RC ( rcFS, rcDirectory, rcRemoving, rcDirectory, rcReadonly );
483
484 switch ( self -> vt -> v1 . maj )
485 {
486 case 1:
487 return ( * self -> vt -> v1 . clear_dir ) ( self, force, path, args );
488 }
489
490 return RC ( rcFS, rcDirectory, rcRemoving, rcInterface, rcBadVersion );
491 }
492
493 /* Access
494 * get access to object
495 *
496 * "access" [ OUT ] - return parameter for Unix access mode
497 *
498 * "path" [ IN ] - NUL terminated string in directory-native
499 * character set denoting target object
500 */
KDirectoryAccess_v1(const KDirectory_v1 * self,uint32_t * access,const char * path,...)501 LIB_EXPORT rc_t CC KDirectoryAccess_v1 ( const KDirectory_v1 *self,
502 uint32_t *access, const char *path, ... )
503 {
504 rc_t rc;
505 va_list args;
506
507 va_start ( args, path );
508 rc = KDirectoryVAccess ( self, access, path, args );
509 va_end ( args );
510
511 return rc;
512 }
513
KDirectoryVAccess(const KDirectory_v1 * self,uint32_t * access,const char * path,va_list args)514 LIB_EXPORT rc_t CC KDirectoryVAccess ( const KDirectory_v1 *self,
515 uint32_t *access, const char *path, va_list args )
516 {
517 if ( access == NULL )
518 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
519
520 * access = 0;
521
522 if ( self == NULL )
523 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
524
525 if ( path == NULL )
526 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
527 if ( path [ 0 ] == 0 )
528 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
529
530 switch ( self -> vt -> v1 . maj )
531 {
532 case 1:
533 return ( * self -> vt -> v1 . access ) ( self, access, path, args );
534 }
535
536 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
537 }
538
539 /* SetAccess
540 * set access to object a la Unix "chmod"
541 *
542 * "recurse" [ IN ] - if non zero and "path" is a directory,
543 * apply changes recursively.
544 *
545 * "access" [ IN ] and "mask" [ IN ] - definition of change
546 * where "access" contains new bit values and "mask defines
547 * which bits should be changed.
548 *
549 * "path" [ IN ] - NUL terminated string in directory-native
550 * character set denoting target object
551 */
KDirectorySetAccess_v1(KDirectory_v1 * self,bool recurse,uint32_t access,uint32_t mask,const char * path,...)552 LIB_EXPORT rc_t CC KDirectorySetAccess_v1 ( KDirectory_v1 *self, bool recurse,
553 uint32_t access, uint32_t mask, const char *path, ... )
554 {
555 rc_t rc;
556 va_list args;
557
558 va_start ( args, path );
559 rc = KDirectoryVSetAccess ( self, recurse,
560 access, mask, path, args );
561 va_end ( args );
562
563 return rc;
564 }
565
KDirectoryVSetAccess(KDirectory_v1 * self,bool recurse,uint32_t access,uint32_t mask,const char * path,va_list args)566 LIB_EXPORT rc_t CC KDirectoryVSetAccess ( KDirectory_v1 *self, bool recurse,
567 uint32_t access, uint32_t mask, const char *path, va_list args )
568 {
569 if ( self == NULL )
570 return RC ( rcFS, rcDirectory, rcUpdating, rcSelf, rcNull );
571
572 if ( path == NULL )
573 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcNull );
574 if ( path [ 0 ] == 0 )
575 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcInvalid );
576
577 if ( self -> read_only )
578 return RC ( rcFS, rcDirectory, rcUpdating, rcDirectory, rcReadonly );
579
580 switch ( self -> vt -> v1 . maj )
581 {
582 case 1:
583 /* TBD - perhaps limit bits to lower 9 */
584 return ( * self -> vt -> v1 . set_access )
585 ( self, recurse, access, mask, path, args );
586 }
587
588 return RC ( rcFS, rcDirectory, rcUpdating, rcInterface, rcBadVersion );
589 }
590
591 /* Date
592 * get date/time to object
593 *
594 * "date" [ OUT ] - return parameter
595 *
596 * "path" [ IN ] - NUL terminated string in directory-native
597 * character set denoting target object
598 */
KDirectoryDate_v1(const KDirectory_v1 * self,KTime_t * date,const char * path,...)599 LIB_EXPORT rc_t CC KDirectoryDate_v1 ( const KDirectory_v1 *self,
600 KTime_t *date, const char *path, ... )
601 {
602 rc_t rc;
603 va_list args;
604
605 va_start ( args, path );
606 rc = KDirectoryVDate ( self, date, path, args );
607 va_end ( args );
608
609 return rc;
610 }
KDirectoryVDate(const KDirectory_v1 * self,KTime_t * date,const char * path,va_list args)611 LIB_EXPORT rc_t CC KDirectoryVDate ( const KDirectory_v1 *self,
612 KTime_t *date, const char *path, va_list args )
613 {
614 if ( date == NULL )
615 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
616
617 * date = 0;
618
619 if ( self == NULL )
620 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
621
622 if ( path == NULL )
623 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
624 if ( path [ 0 ] == 0 )
625 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
626
627 switch ( self -> vt -> v1 . maj )
628 {
629 case 1:
630 if ( self -> vt -> v1 . min >= 1 )
631 return ( * self -> vt -> v1 . date ) ( self, date, path, args );
632 break;
633 }
634
635 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
636 }
637
638
639 /* SetDate
640 * set date to object
641 *
642 * "recurse" [ IN ] - if non zero and "path" is a directory,
643 * apply changes recursively.
644 *
645 * "date" [ IN ] - new time and date for the object
646 *
647 * "path" [ IN ] - NUL terminated string in directory-native
648 * character set denoting target object
649 */
KDirectorySetDate_v1(KDirectory_v1 * self,bool recurse,KTime_t date,const char * path,...)650 LIB_EXPORT rc_t CC KDirectorySetDate_v1 ( KDirectory_v1 *self, bool recurse,
651 KTime_t date, const char *path, ... )
652 {
653 rc_t rc;
654 va_list args;
655
656 va_start ( args, path );
657 rc = KDirectoryVSetDate ( self, recurse,
658 date, path, args );
659 va_end ( args );
660
661 return rc;
662 }
663
KDirectoryVSetDate(KDirectory_v1 * self,bool recurse,KTime_t date,const char * path,va_list args)664 LIB_EXPORT rc_t CC KDirectoryVSetDate ( KDirectory_v1 *self, bool recurse,
665 KTime_t date, const char *path, va_list args )
666 {
667 if ( self == NULL )
668 return RC ( rcFS, rcDirectory, rcUpdating, rcSelf, rcNull );
669
670 if ( path == NULL )
671 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcNull );
672 if ( path [ 0 ] == 0 )
673 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcInvalid );
674
675 if ( self -> read_only )
676 return RC ( rcFS, rcDirectory, rcUpdating, rcDirectory, rcReadonly );
677
678 switch ( self -> vt -> v1 . maj )
679 {
680 case 1:
681 /* TBD - perhaps limit bits to lower 9 */
682 if ( self -> vt -> v1 . min >= 1 )
683 return ( * self -> vt -> v1 . setdate ) ( self, recurse, date, path, args );
684 break;
685 }
686
687 return RC ( rcFS, rcDirectory, rcUpdating, rcInterface, rcBadVersion );
688 }
689
690
691 /* CreateAlias
692 * creates a path alias according to create mode
693 *
694 * "access" [ IN ] - standard Unix directory access mode
695 * used when "mode" has kcmParents set and alias path does
696 * not exist.
697 *
698 * "mode" [ IN ] - a creation mode ( see explanation above ).
699 *
700 * "targ" [ IN ] - NUL terminated string in directory-native
701 * character set denoting target object
702 *
703 * "alias" [ IN ] - NUL terminated string in directory-native
704 * character set denoting target alias
705 */
KDirectoryCreateAlias_v1(KDirectory_v1 * self,uint32_t access,KCreateMode mode,const char * targ,const char * alias)706 LIB_EXPORT rc_t CC KDirectoryCreateAlias_v1 ( KDirectory_v1 *self,
707 uint32_t access, KCreateMode mode,
708 const char *targ, const char *alias )
709 {
710 if ( self == NULL )
711 return RC ( rcFS, rcDirectory, rcUpdating, rcSelf, rcNull );
712
713 if ( targ == NULL || alias == NULL )
714 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcNull );
715 if ( targ [ 0 ] == 0 || alias [ 0 ] == 0 )
716 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcInvalid );
717
718 if ( self -> read_only )
719 return RC ( rcFS, rcDirectory, rcUpdating, rcDirectory, rcReadonly );
720
721 switch ( self -> vt -> v1 . maj )
722 {
723 case 1:
724 return ( * self -> vt -> v1 . create_alias )
725 ( self, access, mode, targ, alias );
726 }
727
728 return RC ( rcFS, rcDirectory, rcUpdating, rcInterface, rcBadVersion );
729 }
730
731
732 /* CreateLink ( v1.5 )
733 * creates a new link (also known as a hard link).
734 *
735 * "access" [ IN ] - standard Unix directory access mode
736 * used when "mode" has kcmParents set and new link path does
737 * not exist.
738 *
739 * "mode" [ IN ] - a creation mode ( see explanation in kfs/defs.h ).
740 *
741 * "oldpath" [ IN ] - NUL terminated string in directory-native
742 * character set denoting existing object. THE PATH IS GIVEN RELATIVE
743 * TO DIRECTORY ( "self" ), NOT LINK ( "newpath" )!
744 *
745 * "newpath" [ IN ] - NUL terminated string in directory-native
746 * character set denoting a new link.
747 */
KDirectoryCreateLink_v1(KDirectory_v1 * self,uint32_t access,KCreateMode mode,const char * oldpath,const char * newpath)748 LIB_EXPORT rc_t CC KDirectoryCreateLink_v1 ( KDirectory_v1 *self,
749 uint32_t access, KCreateMode mode,
750 const char *oldpath, const char *newpath )
751 {
752 if ( self == NULL )
753 return RC ( rcFS, rcDirectory, rcUpdating, rcSelf, rcNull );
754
755 if ( oldpath == NULL || newpath == NULL )
756 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcNull );
757 if ( oldpath [ 0 ] == 0 || newpath [ 0 ] == 0 )
758 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcInvalid );
759
760 if ( self -> read_only )
761 return RC ( rcFS, rcDirectory, rcUpdating, rcDirectory, rcReadonly );
762
763 switch ( self -> vt -> v1 . maj )
764 {
765 case 1:
766 if ( self -> vt -> v1 . min >= 5 )
767 {
768 return ( * self -> vt -> v1 . create_link )
769 ( self, access, mode, oldpath, newpath );
770 }
771 break;
772 }
773
774 return RC ( rcFS, rcDirectory, rcUpdating, rcInterface, rcBadVersion );
775 }
776
777 /* OpenFileRead
778 * opens an existing file with read-only access
779 *
780 * "f" [ OUT ] - return parameter for newly opened file
781 *
782 * "path" [ IN ] - NUL terminated string in directory-native
783 * character set denoting target file
784 */
KDirectoryOpenFileRead_v1(const KDirectory_v1 * self,struct KFile const ** f,const char * path,...)785 LIB_EXPORT rc_t CC KDirectoryOpenFileRead_v1 ( const KDirectory_v1 *self,
786 struct KFile const **f, const char *path, ... )
787 {
788 rc_t rc;
789 va_list args;
790
791 va_start ( args, path );
792 rc = KDirectoryVOpenFileRead ( self, f, path, args );
793 va_end ( args );
794
795 return rc;
796 }
797
KDirectoryVOpenFileRead(const KDirectory_v1 * self,struct KFile const ** f,const char * path,va_list args)798 LIB_EXPORT rc_t CC KDirectoryVOpenFileRead ( const KDirectory_v1 *self,
799 struct KFile const **f, const char *path, va_list args )
800 {
801 if ( f == NULL )
802 return RC ( rcFS, rcDirectory, rcOpening, rcFile, rcNull );
803
804 * f = NULL;
805
806 if ( self == NULL )
807 return RC ( rcFS, rcDirectory, rcOpening, rcSelf, rcNull );
808
809 if ( path == NULL )
810 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcNull );
811 if ( path [ 0 ] == 0 )
812 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcInvalid );
813
814 switch ( self -> vt -> v1 . maj )
815 {
816 case 1:
817 return ( * self -> vt -> v1 . open_file_read ) ( self, f, path, args );
818 }
819
820 return RC ( rcFS, rcDirectory, rcOpening, rcInterface, rcBadVersion );
821 }
822
823 /* OpenFileWrite
824 * opens an existing file with write access
825 *
826 * "f" [ OUT ] - return parameter for newly opened file
827 *
828 * "update" [ IN ] - if non-zero, open in read/write mode
829 * otherwise, open in write-only mode
830 *
831 * "path" [ IN ] - NUL terminated string in directory-native
832 * character set denoting target file
833 */
KDirectoryOpenFileWrite_v1(KDirectory_v1 * self,struct KFile ** f,bool update,const char * path,...)834 LIB_EXPORT rc_t CC KDirectoryOpenFileWrite_v1 ( KDirectory_v1 *self,
835 struct KFile **f, bool update, const char *path, ... )
836 {
837 rc_t rc;
838 va_list args;
839
840 va_start ( args, path );
841 rc = KDirectoryVOpenFileWrite ( self, f, update, path, args );
842 va_end ( args );
843
844 return rc;
845 }
846
KDirectoryVOpenFileWrite(KDirectory_v1 * self,struct KFile ** f,bool update,const char * path,va_list args)847 LIB_EXPORT rc_t CC KDirectoryVOpenFileWrite ( KDirectory_v1 *self,
848 struct KFile **f, bool update, const char *path, va_list args )
849 {
850 if ( f == NULL )
851 return RC ( rcFS, rcDirectory, rcOpening, rcFile, rcNull );
852
853 * f = NULL;
854
855 if ( self == NULL )
856 return RC ( rcFS, rcDirectory, rcOpening, rcSelf, rcNull );
857
858 if ( path == NULL )
859 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcNull );
860 if ( path [ 0 ] == 0 )
861 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcInvalid );
862
863
864 if ( self -> read_only )
865 return RC ( rcFS, rcDirectory, rcOpening, rcDirectory, rcReadonly );
866
867 switch ( self -> vt -> v1 . maj )
868 {
869 case 1:
870 return ( * self -> vt -> v1 . open_file_write )
871 ( self, f, update, path, args );
872 }
873
874 return RC ( rcFS, rcDirectory, rcOpening, rcInterface, rcBadVersion );
875 }
876
877 /* OpenFileSharedWrite ( v1.4 )
878 * opens an existing file with shared write access
879 *
880 * "f" [ OUT ] - return parameter for newly opened file
881 *
882 * "update" [ IN ] - if true, open in read/write mode
883 * otherwise, open in write-only mode
884 *
885 * "path" [ IN ] - NUL terminated string in directory-native
886 * character set denoting target file
887 */
KDirectoryOpenFileSharedWrite_v1(KDirectory_v1 * self,struct KFile ** f,bool update,const char * path,...)888 LIB_EXPORT rc_t CC KDirectoryOpenFileSharedWrite_v1 ( KDirectory_v1 *self,
889 struct KFile **f, bool update, const char *path, ... )
890 {
891 rc_t rc;
892 va_list args;
893
894 va_start ( args, path );
895 rc = KDirectoryVOpenFileSharedWrite ( self, f, update, path, args );
896 va_end ( args );
897
898 return rc;
899 }
900
KDirectoryVOpenFileSharedWrite(KDirectory_v1 * self,struct KFile ** f,bool update,const char * path,va_list args)901 LIB_EXPORT rc_t CC KDirectoryVOpenFileSharedWrite ( KDirectory_v1 *self,
902 struct KFile **f, bool update, const char *path, va_list args )
903 {
904 if ( f == NULL )
905 return RC ( rcFS, rcDirectory, rcOpening, rcFile, rcNull );
906
907 * f = NULL;
908
909 if ( self == NULL )
910 return RC ( rcFS, rcDirectory, rcOpening, rcSelf, rcNull );
911
912 if ( path == NULL )
913 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcNull );
914 if ( path [ 0 ] == 0 )
915 return RC ( rcFS, rcDirectory, rcOpening, rcPath, rcInvalid );
916
917
918 if ( self -> read_only )
919 return RC ( rcFS, rcDirectory, rcOpening, rcDirectory, rcReadonly );
920
921 switch ( self -> vt -> v1 . maj )
922 {
923 case 1:
924 if ( self -> vt -> v1 . min >= 4 )
925 {
926 return ( * self -> vt -> v1 . open_file_shared_write )
927 ( self, f, update, path, args );
928 }
929 break;
930 }
931
932 return RC ( rcFS, rcDirectory, rcOpening, rcInterface, rcBadVersion );
933 }
934
935 /* CreateFile
936 * opens a file with write access
937 *
938 * "f" [ OUT ] - return parameter for newly opened file
939 *
940 * "update" [ IN ] - if non-zero, open in read/write mode
941 * otherwise, open in write-only mode
942 *
943 * "access" [ IN ] - standard Unix access mode, e.g. 0664
944 *
945 * "mode" [ IN ] - a creation mode ( see explanation above ).
946 *
947 * "path" [ IN ] - NUL terminated string in directory-native
948 * character set denoting target file
949 */
KDirectoryCreateFile_v1(KDirectory_v1 * self,struct KFile ** f,bool update,uint32_t access,KCreateMode mode,const char * path,...)950 LIB_EXPORT rc_t CC KDirectoryCreateFile_v1 ( KDirectory_v1 *self, struct KFile **f,
951 bool update, uint32_t access, KCreateMode mode, const char *path, ... )
952 {
953 rc_t rc;
954 va_list args;
955
956 va_start ( args, path );
957 rc = KDirectoryVCreateFile ( self, f, update,
958 access, mode, path, args );
959 va_end ( args );
960
961 return rc;
962 }
963
KDirectoryVCreateFile(KDirectory_v1 * self,struct KFile ** f,bool update,uint32_t access,KCreateMode mode,const char * path,va_list args)964 LIB_EXPORT rc_t CC KDirectoryVCreateFile ( KDirectory_v1 *self, struct KFile **f,
965 bool update, uint32_t access, KCreateMode mode, const char *path, va_list args )
966 {
967 if ( f == NULL )
968 return RC ( rcFS, rcDirectory, rcCreating, rcFile, rcNull );
969
970 * f = NULL;
971
972 if ( self == NULL )
973 return RC ( rcFS, rcDirectory, rcCreating, rcSelf, rcNull );
974
975 if ( path == NULL )
976 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcNull );
977 if ( path [ 0 ] == 0 )
978 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcInvalid );
979
980
981 if ( self -> read_only )
982 return RC ( rcFS, rcDirectory, rcCreating, rcDirectory, rcReadonly );
983
984 switch ( self -> vt -> v1 . maj )
985 {
986 case 1:
987 return ( * self -> vt -> v1 . create_file )
988 ( self, f, update, access, mode, path, args );
989 }
990
991 return RC ( rcFS, rcDirectory, rcCreating, rcInterface, rcBadVersion );
992 }
993
994 /* FileLocator
995 * returns locator in bytes of target file
996 *
997 * "locator" [ OUT ] - return parameter for file locator
998 *
999 * "path" [ IN ] - NUL terminated string in directory-native
1000 * character set denoting target file
1001 */
KDirectoryFileLocator_v1(const KDirectory_v1 * self,uint64_t * locator,const char * path,...)1002 LIB_EXPORT rc_t CC KDirectoryFileLocator_v1 ( const KDirectory_v1 *self,
1003 uint64_t *locator, const char *path, ... )
1004 {
1005 rc_t rc;
1006 va_list args;
1007
1008 va_start ( args, path );
1009 rc = KDirectoryVFileLocator ( self, locator, path, args );
1010 va_end ( args );
1011
1012 return rc;
1013 }
1014
KDirectoryVFileLocator(const KDirectory_v1 * self,uint64_t * locator,const char * path,va_list args)1015 LIB_EXPORT rc_t CC KDirectoryVFileLocator ( const KDirectory_v1 *self,
1016 uint64_t *locator, const char *path, va_list args )
1017 {
1018 if ( locator == NULL )
1019 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
1020
1021 * locator = 0;
1022
1023 if ( self == NULL )
1024 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
1025 if ( path == NULL )
1026 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
1027 if ( path [ 0 ] == 0 )
1028 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
1029
1030 switch ( self -> vt -> v1 . maj )
1031 {
1032 case 1:
1033 if ( self -> vt -> v1 . min >= 2 )
1034 return ( * self -> vt -> v1 . file_locator ) ( self, locator, path, args );
1035 break;
1036 }
1037
1038 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
1039 }
1040
1041 /* FileSize
1042 * returns size in bytes of target file
1043 *
1044 * "size" [ OUT ] - return parameter for file size
1045 *
1046 * "path" [ IN ] - NUL terminated string in directory-native
1047 * character set denoting target file
1048 */
KDirectoryFileSize_v1(const KDirectory_v1 * self,uint64_t * size,const char * path,...)1049 LIB_EXPORT rc_t CC KDirectoryFileSize_v1 ( const KDirectory_v1 *self,
1050 uint64_t *size, const char *path, ... )
1051 {
1052 rc_t rc;
1053 va_list args;
1054
1055 va_start ( args, path );
1056 rc = KDirectoryVFileSize ( self, size, path, args );
1057 va_end ( args );
1058
1059 return rc;
1060 }
1061
KDirectoryVFileSize(const KDirectory_v1 * self,uint64_t * size,const char * path,va_list args)1062 LIB_EXPORT rc_t CC KDirectoryVFileSize ( const KDirectory_v1 *self,
1063 uint64_t *size, const char *path, va_list args )
1064 {
1065 if ( size == NULL )
1066 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
1067
1068 * size = 0;
1069
1070 if ( self == NULL )
1071 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
1072 if ( path == NULL )
1073 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
1074 if ( path [ 0 ] == 0 )
1075 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
1076
1077 switch ( self -> vt -> v1 . maj )
1078 {
1079 case 1:
1080 return ( * self -> vt -> v1 . file_size ) ( self, size, path, args );
1081 }
1082
1083 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
1084 }
1085
1086 /* FilePhysicalSize
1087 * returns size in bytes of target file
1088 *
1089 * "size" [ OUT ] - return parameter for file size
1090 *
1091 * "path" [ IN ] - NUL terminated string in directory-native
1092 * character set denoting target file
1093 */
KDirectoryFilePhysicalSize_v1(const KDirectory_v1 * self,uint64_t * size,const char * path,...)1094 LIB_EXPORT rc_t CC KDirectoryFilePhysicalSize_v1 ( const KDirectory_v1 *self,
1095 uint64_t *size, const char *path, ... )
1096 {
1097 rc_t rc;
1098 va_list args;
1099
1100 va_start ( args, path );
1101 rc = KDirectoryVFilePhysicalSize ( self, size, path, args );
1102 va_end ( args );
1103
1104 return rc;
1105 }
1106
KDirectoryVFilePhysicalSize(const KDirectory_v1 * self,uint64_t * size,const char * path,va_list args)1107 LIB_EXPORT rc_t CC KDirectoryVFilePhysicalSize ( const KDirectory_v1 *self,
1108 uint64_t *size, const char *path, va_list args )
1109 {
1110 if ( size == NULL )
1111 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
1112
1113 * size = 0;
1114
1115 if ( self == NULL )
1116 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
1117 if ( path == NULL )
1118 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
1119 if ( path [ 0 ] == 0 )
1120 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
1121
1122 switch ( self -> vt -> v1 . maj )
1123 {
1124 case 1:
1125 if ( self -> vt -> v1 . min >= 3 )
1126 return ( * self -> vt -> v1 . file_phys_size ) ( self, size, path, args );
1127 break;
1128 }
1129
1130 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
1131 }
1132
1133 /* SetFileSize
1134 * sets size in bytes of target file
1135 *
1136 * "size" [ IN ] - new file size
1137 *
1138 * "path" [ IN ] - NUL terminated string in directory-native
1139 * character set denoting target file
1140 */
KDirectorySetFileSize_v1(KDirectory_v1 * self,uint64_t size,const char * path,...)1141 LIB_EXPORT rc_t CC KDirectorySetFileSize_v1 ( KDirectory_v1 *self,
1142 uint64_t size, const char *path, ... )
1143 {
1144 rc_t rc;
1145 va_list args;
1146
1147 va_start ( args, path );
1148 rc = KDirectoryVSetFileSize ( self, size, path, args );
1149 va_end ( args );
1150
1151 return rc;
1152 }
1153
KDirectoryVSetFileSize(KDirectory_v1 * self,uint64_t size,const char * path,va_list args)1154 LIB_EXPORT rc_t CC KDirectoryVSetFileSize ( KDirectory_v1 *self,
1155 uint64_t size, const char *path, va_list args )
1156 {
1157 if ( self == NULL )
1158 return RC ( rcFS, rcDirectory, rcUpdating, rcSelf, rcNull );
1159
1160 if ( path == NULL )
1161 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcNull );
1162 if ( path [ 0 ] == 0 )
1163 return RC ( rcFS, rcDirectory, rcUpdating, rcPath, rcInvalid );
1164
1165 if ( self -> read_only )
1166 return RC ( rcFS, rcDirectory, rcUpdating, rcDirectory, rcReadonly );
1167
1168 switch ( self -> vt -> v1 . maj )
1169 {
1170 case 1:
1171 return ( * self -> vt -> v1 . set_size ) ( self, size, path, args );
1172 }
1173
1174 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
1175 }
1176
1177 /* FileContiguous
1178 * returns true if the file is "contiguous". Chunked or sparse files are not
1179 * contiguous while most data files are. Virtual generated files would likely
1180 * not be contiguous.
1181 *
1182 * "contiguous" [ OUT ] - return parameter for file contiguous
1183 *
1184 * "path" [ IN ] - NUL terminated string in directory-native
1185 * character set denoting target file
1186 */
KDirectoryFileContiguous_v1(const KDirectory_v1 * self,bool * contiguous,const char * path,...)1187 LIB_EXPORT rc_t CC KDirectoryFileContiguous_v1 ( const KDirectory_v1 *self,
1188 bool *contiguous, const char *path, ... )
1189 {
1190 rc_t rc;
1191 va_list args;
1192
1193 va_start ( args, path );
1194 rc = KDirectoryVFileContiguous ( self, contiguous, path, args );
1195 va_end ( args );
1196
1197 return rc;
1198 }
1199
KDirectoryVFileContiguous(const KDirectory_v1 * self,bool * contiguous,const char * path,va_list args)1200 LIB_EXPORT rc_t CC KDirectoryVFileContiguous ( const KDirectory_v1 *self,
1201 bool *contiguous, const char *path, va_list args )
1202 {
1203 if ( contiguous == NULL )
1204 return RC ( rcFS, rcDirectory, rcAccessing, rcParam, rcNull );
1205
1206 * contiguous = 0;
1207
1208 if ( self == NULL )
1209 return RC ( rcFS, rcDirectory, rcAccessing, rcSelf, rcNull );
1210 if ( path == NULL )
1211 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcNull );
1212 if ( path [ 0 ] == 0 )
1213 return RC ( rcFS, rcDirectory, rcAccessing, rcPath, rcInvalid );
1214
1215 switch ( self -> vt -> v1 . maj )
1216 {
1217 case 1:
1218 if ( self -> vt -> v1 . min >= 3 )
1219 return ( * self -> vt -> v1 . file_contiguous ) ( self, contiguous, path, args );
1220 break;
1221 }
1222
1223 return RC ( rcFS, rcDirectory, rcAccessing, rcInterface, rcBadVersion );
1224 }
1225
1226 /* OpenDirRead
1227 * KDirectoryOpenDirUpdate
1228 * opens a sub-directory
1229 *
1230 * "chroot" [ IN ] - if non-zero, the new directory becomes
1231 * chroot'd and will interpret paths beginning with '/'
1232 * relative to itself.
1233 *
1234 * "path" [ IN ] - NUL terminated string in directory-native
1235 * character set denoting target directory
1236 */
KDirectoryOpenDirRead_v1(const KDirectory_v1 * self,const KDirectory_v1 ** sub,bool chroot,const char * path,...)1237 LIB_EXPORT rc_t CC KDirectoryOpenDirRead_v1 ( const KDirectory_v1 *self,
1238 const KDirectory_v1 **sub, bool chroot, const char *path, ... )
1239 {
1240 rc_t rc;
1241 va_list args;
1242
1243 va_start ( args, path );
1244 rc = KDirectoryVOpenDirRead ( self, sub, chroot, path, args );
1245 va_end ( args );
1246
1247 return rc;
1248 }
1249
KDirectoryVOpenDirRead(const KDirectory_v1 * self,const KDirectory_v1 ** sub,bool chroot,const char * path,va_list args)1250 LIB_EXPORT rc_t CC KDirectoryVOpenDirRead ( const KDirectory_v1 *self,
1251 const KDirectory_v1 **sub, bool chroot, const char *path, va_list args )
1252 {
1253 if ( sub == NULL )
1254 return RC ( rcFS, rcDirectory, rcOpening, rcDirectory, rcNull );
1255
1256 * sub = NULL;
1257
1258 if ( self == NULL )
1259 return RC ( rcFS, rcDirectory, rcOpening, rcSelf, rcNull );
1260
1261 if ( path == NULL || path [ 0 ] == 0 )
1262 path = ".";
1263
1264 switch ( self -> vt -> v1 . maj )
1265 {
1266 case 1:
1267 return ( * self -> vt -> v1 . open_dir_read )
1268 ( self, sub, chroot, path, args );
1269 }
1270
1271 return RC ( rcFS, rcDirectory, rcOpening, rcInterface, rcBadVersion );
1272 }
1273
KDirectoryOpenDirUpdate_v1(KDirectory_v1 * self,KDirectory_v1 ** sub,bool chroot,const char * path,...)1274 LIB_EXPORT rc_t CC KDirectoryOpenDirUpdate_v1 ( KDirectory_v1 *self,
1275 KDirectory_v1 **sub, bool chroot, const char *path, ... )
1276 {
1277 rc_t rc;
1278 va_list args;
1279
1280 va_start ( args, path );
1281 rc = KDirectoryVOpenDirUpdate ( self, sub, chroot, path, args );
1282 va_end ( args );
1283
1284 return rc;
1285 }
1286
KDirectoryVOpenDirUpdate(KDirectory_v1 * self,KDirectory_v1 ** sub,bool chroot,const char * path,va_list args)1287 LIB_EXPORT rc_t CC KDirectoryVOpenDirUpdate ( KDirectory_v1 *self,
1288 KDirectory_v1 **sub, bool chroot, const char *path, va_list args )
1289 {
1290 if ( sub == NULL )
1291 return RC ( rcFS, rcDirectory, rcOpening, rcDirectory, rcNull );
1292
1293 * sub = NULL;
1294
1295 if ( self == NULL )
1296 return RC ( rcFS, rcDirectory, rcOpening, rcSelf, rcNull );
1297
1298 if ( self -> read_only )
1299 /* TODO: Maybe for writing wncbi-vdb we need to return RC */
1300 return SILENT_RC ( rcFS, rcDirectory, rcOpening, rcDirectory, rcReadonly );
1301
1302 if ( path == NULL || path [ 0 ] == 0 )
1303 path = ".";
1304
1305 switch ( self -> vt -> v1 . maj )
1306 {
1307 case 1:
1308 return ( * self -> vt -> v1 . open_dir_update )
1309 ( self, sub, chroot, path, args );
1310 }
1311
1312 return RC ( rcFS, rcDirectory, rcOpening, rcInterface, rcBadVersion );
1313 }
1314
1315 /* CreateDir
1316 * create a sub-directory
1317 *
1318 * "access" [ IN ] - standard Unix directory mode, e.g.0775
1319 *
1320 * "mode" [ IN ] - a creation mode ( see explanation above ).
1321 *
1322 * "path" [ IN ] - NUL terminated string in directory-native
1323 * character set denoting target directory
1324 */
KDirectoryCreateDir_v1(KDirectory_v1 * self,uint32_t access,KCreateMode mode,const char * path,...)1325 LIB_EXPORT rc_t CC KDirectoryCreateDir_v1 ( KDirectory_v1 *self,
1326 uint32_t access, KCreateMode mode, const char *path, ... )
1327 {
1328 rc_t rc;
1329 va_list args;
1330
1331 va_start ( args, path );
1332 rc = KDirectoryVCreateDir ( self, access, mode, path, args );
1333 va_end ( args );
1334
1335 return rc;
1336 }
1337
KDirectoryVCreateDir(KDirectory_v1 * self,uint32_t access,KCreateMode mode,const char * path,va_list args)1338 LIB_EXPORT rc_t CC KDirectoryVCreateDir ( KDirectory_v1 *self,
1339 uint32_t access, KCreateMode mode, const char *path, va_list args )
1340 {
1341 if ( self == NULL )
1342 return RC ( rcFS, rcDirectory, rcCreating, rcSelf, rcNull );
1343
1344 if ( path == NULL )
1345 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcNull );
1346 if ( path [ 0 ] == 0 )
1347 return RC ( rcFS, rcDirectory, rcCreating, rcPath, rcInvalid );
1348
1349 if ( self -> read_only )
1350 return RC ( rcFS, rcDirectory, rcCreating, rcDirectory, rcReadonly );
1351
1352 switch ( self -> vt -> v1 . maj )
1353 {
1354 case 1:
1355 return ( * self -> vt -> v1 . create_dir ) ( self, access, mode, path, args );
1356 }
1357
1358 return RC ( rcFS, rcDirectory, rcCreating, rcInterface, rcBadVersion );
1359 }
1360
1361 /* Init
1362 * initialize a newly allocated directory object
1363 */
KDirectoryInit_v1(KDirectory_v1 * self,const KDirectory_vt * vt,const char * class_name,const char * path,bool update)1364 LIB_EXPORT rc_t CC KDirectoryInit_v1 ( KDirectory_v1 *self, const KDirectory_vt *vt,
1365 const char * class_name, const char * path, bool update )
1366 {
1367 if ( self == NULL )
1368 return RC ( rcFS, rcDirectory, rcConstructing, rcSelf, rcNull );
1369 if ( vt == NULL )
1370 return RC ( rcFS, rcDirectory, rcConstructing, rcInterface, rcNull );
1371 switch ( vt -> v1 . maj )
1372 {
1373 case 0:
1374 return RC ( rcFS, rcDirectory, rcConstructing, rcInterface, rcInvalid );
1375 case 1:
1376 switch ( vt -> v1 . min )
1377 {
1378 /* ADD NEW MINOR VERSION CASES HERE */
1379 case 5:
1380 #if _DEBUGGING
1381 if ( vt -> v1 . create_link == NULL )
1382 return RC ( rcFS, rcFile, rcConstructing,
1383 rcInterface, rcNull );
1384 #endif
1385 /* no break */
1386 case 4:
1387 #if _DEBUGGING
1388 if ( vt -> v1 . open_file_shared_write == NULL )
1389 return RC ( rcFS, rcFile, rcConstructing, rcInterface, rcNull );
1390 #endif
1391 /* no break */
1392 case 3:
1393 #if _DEBUGGING
1394 if ( vt -> v1 . file_phys_size == NULL ||
1395 vt -> v1 . file_contiguous == NULL )
1396 return RC ( rcFS, rcFile, rcConstructing, rcInterface, rcNull );
1397 #endif
1398 /* no break */
1399 case 2:
1400 #if _DEBUGGING
1401 if ( vt -> v1 . file_locator == NULL )
1402 return RC ( rcFS, rcFile, rcConstructing, rcInterface, rcNull );
1403 #endif
1404 /* no break */
1405 case 1:
1406 #if _DEBUGGING
1407 if ( vt -> v1 . get_sysdir == NULL ||
1408 vt -> v1 . setdate == NULL ||
1409 vt -> v1 . date == NULL )
1410 return RC ( rcFS, rcFile, rcConstructing, rcInterface, rcNull );
1411 #endif
1412 /* no break */
1413 case 0:
1414 #if _DEBUGGING
1415 /* vt -> v1 . destroy_file CAN be NULL */
1416 if ( vt -> v1 . create_dir == NULL ||
1417 vt -> v1 . open_dir_update == NULL ||
1418 vt -> v1 . open_dir_read == NULL ||
1419 vt -> v1 . set_size == NULL ||
1420 vt -> v1 . file_size == NULL ||
1421 vt -> v1 . create_file == NULL ||
1422 vt -> v1 . open_file_write == NULL ||
1423 vt -> v1 . open_file_read == NULL ||
1424 vt -> v1 . create_alias == NULL ||
1425 vt -> v1 . set_access == NULL ||
1426 vt -> v1 . access == NULL ||
1427 vt -> v1 . clear_dir == NULL ||
1428 vt -> v1 . remove == NULL ||
1429 vt -> v1 . rename == NULL ||
1430 vt -> v1 . resolve_alias == NULL ||
1431 vt -> v1 . resolve_path == NULL ||
1432 vt -> v1 . path_type == NULL ||
1433 vt -> v1 . visit_update == NULL ||
1434 vt -> v1 . visit == NULL ||
1435 vt -> v1 . list_dir == NULL ||
1436 vt -> v1 . destroy == NULL )
1437 return RC ( rcFS, rcFile, rcConstructing, rcInterface, rcNull );
1438 #endif
1439 break;
1440 default:
1441 return RC ( rcFS, rcDirectory, rcConstructing, rcInterface, rcBadVersion );
1442 }
1443 break;
1444 default:
1445 return RC ( rcFS, rcDirectory, rcConstructing, rcInterface, rcBadVersion );
1446 }
1447
1448 self -> vt = vt;
1449 self -> read_only = ( uint8_t ) ( update == 0 );
1450
1451
1452 KRefcountInit ( &self->refcount, 1, class_name, "init", path );
1453
1454 return 0;
1455 }
1456
1457 /* DestroyFile
1458 * does whatever is necessary with an unreferenced file
1459 */
KDirectoryDestroyFile_v1(const KDirectory_v1 * self,KFile * f)1460 LIB_EXPORT rc_t CC KDirectoryDestroyFile_v1 ( const KDirectory_v1 *self, KFile *f )
1461 {
1462 const KDirectory_vt *vt = self -> vt;
1463 switch ( vt -> v1 . maj )
1464 {
1465 case 1:
1466 if ( vt -> v1 . destroy_file != NULL )
1467 return ( * vt -> v1 . destroy_file ) ( ( KDirectory_v1* ) self, f );
1468 return KFileDestroy_v1 ( f );
1469 }
1470
1471 return RC ( rcFS, rcDirectory, rcDestroying, rcInterface, rcBadVersion );
1472 }
1473
1474 /* GetSysDir
1475 * returns an underlying system file object
1476 */
KDirectoryGetSysDir_v1(const KDirectory_v1 * self)1477 LIB_EXPORT struct KSysDir_v1* CC KDirectoryGetSysDir_v1 ( const KDirectory_v1 *self )
1478 {
1479 if ( self != NULL )
1480 {
1481 switch ( self -> vt -> v1 . maj )
1482 {
1483 case 1:
1484 if ( self -> vt -> v1 . min > 0 )
1485 return ( * self -> vt -> v1 . get_sysdir ) ( self );
1486 break;
1487 }
1488 }
1489 return NULL;
1490 }
1491
1492
copy_loop(const KFile * src,KFile * dst,size_t bsize)1493 static rc_t copy_loop( const KFile *src, KFile *dst, size_t bsize )
1494 {
1495 rc_t rc = 0;
1496 uint64_t pos = 0;
1497 size_t num_read = 1;
1498
1499 char * buffer = malloc( bsize );
1500 if ( buffer == NULL )
1501 return RC( rcFS, rcDirectory, rcCopying, rcMemory, rcExhausted );
1502
1503 while ( rc == 0 && num_read > 0 )
1504 {
1505 rc = KFileRead ( src, pos, buffer, bsize, &num_read );
1506 if ( rc == 0 && num_read > 0 )
1507 {
1508 size_t num_writ;
1509 rc = KFileWrite ( dst, pos, buffer, num_read, &num_writ );
1510 pos += num_read;
1511 }
1512 }
1513 free( buffer );
1514 return rc;
1515 }
1516
1517
KDirectoryCopyPath(const KDirectory_v1 * src_dir,KDirectory_v1 * dst_dir,const char * src_path,const char * dst_path)1518 LIB_EXPORT rc_t CC KDirectoryCopyPath ( const KDirectory_v1 *src_dir,
1519 KDirectory_v1 *dst_dir, const char *src_path, const char * dst_path )
1520 {
1521 rc_t rc;
1522 struct KFile const *f_src;
1523
1524 if ( src_dir == NULL || dst_dir == NULL )
1525 return RC ( rcFS, rcDirectory, rcCopying, rcSelf, rcNull );
1526 if ( src_path == NULL || dst_path == NULL )
1527 return RC ( rcFS, rcDirectory, rcCopying, rcParam, rcNull );
1528
1529 rc = KDirectoryOpenFileRead ( src_dir, &f_src, "%s", src_path );
1530 if ( rc == 0 )
1531 {
1532 uint32_t pt = KDirectoryPathType ( dst_dir, "%s", dst_path );
1533 switch( pt )
1534 {
1535 case kptFile : ; /* intentional fall through! */
1536 case kptDir : rc = KDirectoryRemove ( dst_dir, true, "%s", dst_path ); break;
1537 }
1538 if ( rc == 0 )
1539 {
1540 struct KFile *f_dst;
1541 uint32_t access = 0664;
1542 rc = KDirectoryCreateFile ( dst_dir, &f_dst, false, access, kcmCreate, "%s", dst_path );
1543 if ( rc == 0 )
1544 {
1545 rc = copy_loop( f_src, f_dst, 1024 * 1024 );
1546 KFileRelease(f_dst);
1547 }
1548 }
1549 KFileRelease(f_src);
1550 }
1551 return rc;
1552 }
1553
1554
build_obj_path(char ** s,const char * path,const char * objname)1555 static rc_t build_obj_path( char **s, const char *path, const char * objname )
1556 {
1557 rc_t rc;
1558 size_t lp = string_size( path );
1559 size_t l = lp + string_size( objname ) + 2;
1560 *s = malloc( l );
1561 if ( *s == NULL )
1562 rc = RC( rcFS, rcDirectory, rcCopying, rcMemory, rcExhausted );
1563 else
1564 {
1565 size_t written;
1566 const char * concat = ( ( path[ lp - 1 ] == '/' ) ? "%s%s" : "%s/%s" );
1567 rc = string_printf( *s, l, &written, concat, path, objname );
1568 }
1569 return rc;
1570 }
1571
1572
KDirectoryCopyPaths(const KDirectory_v1 * src_dir,KDirectory_v1 * dst_dir,bool recursive,const char * src,const char * dst)1573 LIB_EXPORT rc_t CC KDirectoryCopyPaths( const KDirectory_v1 * src_dir,
1574 KDirectory_v1 * dst_dir, bool recursive, const char *src, const char *dst )
1575 {
1576 rc_t rc;
1577 struct KNamelist *list;
1578
1579 if ( src_dir == NULL || dst_dir == NULL )
1580 return RC ( rcFS, rcDirectory, rcCopying, rcSelf, rcNull );
1581 if ( src == NULL || dst == NULL )
1582 return RC ( rcFS, rcDirectory, rcCopying, rcParam, rcNull );
1583
1584 rc = KDirectoryList ( src_dir, &list, NULL, NULL, "%s", src );
1585 if ( rc == 0 )
1586 {
1587 uint32_t pt = KDirectoryPathType ( dst_dir, "%s", dst );
1588 /* if the output-directory does not exist: create it! */
1589 switch( pt )
1590 {
1591 case kptFile : rc = KDirectoryRemove ( dst_dir, true, "%s", dst );
1592 /* intentially no break ! */
1593
1594 case kptNotFound : if ( rc == 0 )
1595 rc = KDirectoryCreateDir ( dst_dir, 0775, kcmCreate | kcmParents, "%s", dst );
1596 break;
1597 }
1598 if ( rc == 0 )
1599 {
1600 uint32_t i, n;
1601 rc = KNamelistCount ( list, &n );
1602 for ( i = 0; i < n && rc == 0; ++i )
1603 {
1604 const char *name;
1605 rc = KNamelistGet ( list, i, &name );
1606 if ( rc == 0 )
1607 {
1608 char *src_obj;
1609 rc = build_obj_path( &src_obj, src, name );
1610 if ( rc == 0 )
1611 {
1612 char *dst_obj;
1613 rc = build_obj_path( &dst_obj, dst, name );
1614 if ( rc == 0 )
1615 {
1616 pt = KDirectoryPathType ( src_dir, "%s", src_obj );
1617 switch( pt )
1618 {
1619 case kptFile : rc = KDirectoryCopyPath ( src_dir, dst_dir, src_obj, dst_obj );
1620 break;
1621
1622 case kptDir : if ( recursive )
1623 rc = KDirectoryCopyPaths( src_dir, dst_dir, true, src_obj, dst_obj );
1624 break;
1625 }
1626 free( dst_obj );
1627 }
1628 free( src_obj );
1629 }
1630 }
1631 }
1632 }
1633 KNamelistRelease ( list );
1634 }
1635 return rc;
1636 }
1637
1638
KDirectoryCopy(const KDirectory_v1 * src_dir,KDirectory_v1 * dst_dir,bool recursive,const char * src,const char * dst)1639 LIB_EXPORT rc_t CC KDirectoryCopy( const KDirectory_v1 * src_dir,
1640 KDirectory_v1 * dst_dir, bool recursive, const char *src, const char *dst )
1641 {
1642 rc_t rc = 0;
1643 uint32_t pt;
1644
1645 if ( src_dir == NULL || dst_dir == NULL )
1646 return RC ( rcFS, rcDirectory, rcCopying, rcSelf, rcNull );
1647 if ( src == NULL || dst == NULL )
1648 return RC ( rcFS, rcDirectory, rcCopying, rcParam, rcNull );
1649
1650 pt = KDirectoryPathType ( src_dir, "%s", src );
1651 switch( pt )
1652 {
1653 case kptFile : rc = KDirectoryCopyPath ( src_dir, dst_dir, src, dst );
1654 break;
1655 case kptDir : rc = KDirectoryCopyPaths ( src_dir, dst_dir, recursive, src, dst );
1656 break;
1657 }
1658 return rc;
1659 }
1660