CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
vfsobj.cxh
1/// @brief VFS object definitions
2/// @addtogroup fs_vfs
3/// @{
4#include <cx/thread/atomic.h>
5#include <cx/thread/rwlock.h>
6
7struct VFSDir;
8
9/// Directory cache accounting. See vfsSetCacheLimits().
10typedef struct VFSDirCache {
11 atomic(int64) lastprune; ///< clockTimer() when the last prune ran
12 atomic(uint32) dircount; ///< VFSDir nodes currently in the tree
13 uint32 maxdirs; ///< node count above which a prune is allowed to run
14 int64 ttl; ///< how long an unused directory survives, in microseconds
15} VFSDirCache;
16
17/// VFS Object
18class VFS {
19 VFSDir *root; ///< Root for namespaceless paths
20
21 // Namespaces are never case sensitive even if the paths are
22 [noinit] hashtable namespaces; ///< Hashtable of string/VFSDir
23 string curdir; ///< Current working directory of the VFS
24
25 // Two locks, and vfsdlock is always the outer one: a thread may take vfsdlock and then
26 // vfslock, never the reverse.
27 //
28 // vfslock guards additions to the directory cache and the curdir string. vfsdlock guards
29 // operations that destroy VFSDir entries or remove mounts. The invariant that makes that
30 // split work is stronger than it looks and is not enforced anywhere: every reader that
31 // walks the directory tree takes vfsdlock for read first, so holding vfsdlock for write is
32 // by itself exclusive against all of them. That is why the mount and unmount paths mutate
33 // the subdirs and files hashtables with vfslock never taken at all. A new code path that
34 // takes only vfslock and then touches the tree breaks this.
35 RWLock vfslock;
36 RWLock vfsdlock;
37
38 /// Bumped whenever a mount is added or removed. A lookup that dropped the locks to call a
39 /// provider compares this before caching what it learned, so it never records a result for
40 /// a directory tree that changed underneath it.
41 uint32 mountgen;
42 uint32 flags;
43 VFSDirCache dcache; ///< directory cache size accounting
44
45 /// Creates a new empty VFS instance with no mounted providers
46 ///
47 /// The returned VFS contains no data sources. Use vfsMountFS() or
48 /// vfsMountProvider() to attach filesystem providers before accessing files.
49 ///
50 /// @param flags Combination of VFS configuration flags (VFS_ReadOnly, VFS_CaseSensitive, etc.)
51 /// @return New VFS instance (never NULL, call objRelease() when done)
52 ///
53 /// Example:
54 /// @code
55 /// VFS *vfs = vfsCreate(0);
56 /// vfsMountFS(vfs, _SL("/"), _SL("c:/data"));
57 /// // ... use VFS ...
58 /// objRelease(&vfs);
59 /// @endcode
60 factory create(uint32 flags);
61
62 // hmm this is a comment
63 /// Creates a VFS pre-configured with OS filesystem access
64 ///
65 /// Returns a VFS that mirrors the underlying OS filesystem. The exact
66 /// namespace configuration is platform-dependent:
67 /// - Windows: Each drive letter (c:, d:, etc.) is a separate namespace
68 /// - Unix: Single root namespace at /
69 ///
70 /// The VFS case sensitivity is configured to match the OS default:
71 /// - Windows: Case-insensitive
72 /// - Unix: Case-sensitive
73 ///
74 /// This is a convenience function equivalent to creating an empty VFS
75 /// and mounting the OS filesystem at the appropriate paths.
76 ///
77 /// @return VFS instance mirroring OS filesystem, or NULL on failure
78 ///
79 /// Example:
80 /// @code
81 /// VFS *vfs = vfsCreateFromFS();
82 /// if (vfs) {
83 /// // VFS paths now map directly to OS filesystem
84 /// VFSFile *f = vfsOpen(vfs, _SL("c:/data/file.txt"), FS_Read);
85 /// }
86 /// @endcode
87 [canfail] factory createFromFS();
88}
89
90class VFSMount {
91 object[ObjInst] provider;
92 uint32 flags;
93
94 factory create(ObjInst *provider, uint32 flags);
95}
96
97/// @}