CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
vfs_private.h
1#pragma once
2
3#include "fs_private.h"
4#include "cx/container.h"
5#include "cx/string.h"
6#include "vfs.h"
7
8typedef struct VFSDirEnt {
9 string name;
10 int type;
11 FSStat stat;
12} VFSDirEnt;
13saDeclare(VFSDirEnt);
14
15typedef struct VFSSearch {
16 VFS* vfs;
17
18 sa_VFSDirEnt ents;
19 int32 idx;
20} VFSSearch;
21
22// object-like structures for VFS
23// these use custom type ops instead of the object framework so that
24// they can be tightly packed into arrays/hashtables
25
26typedef struct VFSMount VFSMount;
27
28// One provider that could serve a path, captured while the VFS locks were held.
29typedef struct VFSCand {
30 VFSMount* mount; // holds a reference
31 string mountpath; // absolute VFS path of the mount point
32 string relpath; // path below the mount point, as the provider sees it
33 sa_string relcomp; // relpath, split into components
34} VFSCand;
35saDeclare(VFSCand);
36stDeclare(VFSCand);
37#define SType_VFSCand VFSCand*
38#define STStorageType_VFSCand VFSCand
39#define STypeArg_VFSCand(type, val) stgeneric(opaque, &(val))
40#define STypeArgPtr_VFSCand(type, val) &stgeneric(opaque, (val))
41#define STypeCheckedArg_VFSCand(type, val) stType(type), stArg(type, val)
42#define STypeCheckedPtrArg_VFSCand(type, val) stType(type), stArgPtr(type, val)
43
44// A cache entry discovered while no lock was held, waiting to be inserted once they are back.
45typedef struct VFSPendEnt {
46 VFSMount* mount; // holds a reference
47 string dirpath; // absolute VFS path of the directory this belongs to
48 string name; // entry name within that directory
49 string origpath; // path as the provider sees it
50} VFSPendEnt;
51saDeclare(VFSPendEnt);
52stDeclare(VFSPendEnt);
53#define SType_VFSPendEnt VFSPendEnt*
54#define STStorageType_VFSPendEnt VFSPendEnt
55#define STypeArg_VFSPendEnt(type, val) stgeneric(opaque, &(val))
56#define STypeArgPtr_VFSPendEnt(type, val) &stgeneric(opaque, (val))
57#define STypeCheckedArg_VFSPendEnt(type, val) stType(type), stArg(type, val)
58#define STypeCheckedPtrArg_VFSPendEnt(type, val) stType(type), stArgPtr(type, val)
59
60typedef struct VFSCacheEnt {
61 VFSMount* mount; // which VFS mount this file belongs to
62 string origpath; // original path (relative to provider)
63} VFSCacheEnt;
64VFSCacheEnt* _vfsCacheEntCreate(VFSMount* m, strref opath);
65extern STypeOps VFSCacheEnt_ops;
66
67typedef struct VFSDir VFSDir;
68typedef struct VFSDir {
69 string name;
70 VFSDir* parent; // weak ref
71 VFS* vfs; // weak ref, so the destructor can keep the VFS node count
72 sa_VFSMount mounts; // VFS providers mounted in this directory
73
74 hashtable subdirs; // hashtable of string/VFSDir*
75
76 // CACHE
77 hashtable files; // hashtable of string/VFSCacheEnt*
78 atomic(uint64) touched; // clockTimer() at last use
79 bool cache; // only exists to cache directory entries, can be discarded
80} VFSDir;
81_Ret_valid_ VFSDir* _vfsDirCreate(_Inout_ VFS* vfs, _In_opt_ VFSDir* parent);
82
83// custom types for pointers with cleanup
84
85stDeclare(VFSDir);
86#define SType_VFSDir VFSDir*
87#define STStorageType_VFSDir VFSDir*
88#define STypeArg_VFSDir(type, val) stgeneric(ptr, val)
89#define STypeArgPtr_VFSDir(type, val) (stgeneric*)stCheckPtr(ptr, (void**)(val))
90#define STypeCheckedArg_VFSDir(type, val) stType(type), stArg(type, val)
91#define STypeCheckedPtrArg_VFSDir(type, val) stType(type), stArgPtr(type, val)
92
93stDeclare(VFSCacheEnt);
94#define SType_VFSCacheEnt VFSCacheEnt*
95#define STStorageType_VFSCacheEnt VFSCacheEnt*
96#define STypeArg_VFSCacheEnt(type, val) stgeneric(ptr, val)
97#define STypeArgPtr_VFSCacheEnt(type, val) (stgeneric*)stCheckPtr(ptr, (void**)(val))
98#define STypeCheckedArg_VFSCacheEnt(type, val) stType(type), stArg(type, val)
99#define STypeCheckedPtrArg_VFSCacheEnt(type, val) stType(type), stArgPtr(type, val)
100
101// gets (and creates) path in VFS cache
102// Must be called with vfslock held for read, or -- when exclusive is true -- with vfsdlock held
103// for write instead, which excludes every reader of the directory tree on its own.
104_Ret_valid_ _When_(!exclusive, _Requires_shared_lock_held_(vfs->vfslock)) VFSDir*
105_vfsGetDir(_Inout_ VFS* vfs, _In_opt_ strref path, bool isfile, bool cache, bool exclusive);
106// gets a file from VFS cache if it exists
107// Same locking requirement as _vfsGetDir above.
108_Ret_valid_ _When_(!exclusive, _Requires_shared_lock_held_(vfs->vfslock)) VFSCacheEnt*
109_vfsGetFile(_Inout_ VFS* vfs, _In_opt_ strref path, bool exclusive);
110// finds a suitable provider for a particular file
111enum VFS_FIND_PROVIDER_ENUM {
112 VFS_FindWriteFile = 0x0100,
113 VFS_FindCreate = 0x0200,
114 VFS_FindDelete = 0x0400,
115 VFS_FindCache = 0x1000,
116};
117_Ret_opt_valid_ VFSMount*
118_vfsFindMount(_Inout_ VFS* vfs, _Inout_ string* rpath, _In_opt_ strref path,
119 _Out_opt_ VFSMount** cowmount, _Inout_opt_ string* cowrpath, flags_t flags);
120// Finds a mount registered directly on abspath's own VFSDir node, as opposed to a mount that
121// would serve abspath as a file within its parent (which is what _vfsFindMount answers).
122_Ret_opt_valid_ VFSMount* _vfsFindSelfMount(_Inout_ VFS* vfs, _In_opt_ strref abspath);
123void _vfsInvalidateCache(_Inout_ VFS* vfs, _In_opt_ strref path);
124void _vfsInvalidateRecursive(_Inout_ VFS* vfs, _In_ VFSDir* dir, bool havelock);
125// reads vfs->curdir, which vfsSetCurDir can replace and destroy out from under it
126_Requires_shared_lock_held_(vfs->vfslock) void _vfsAbsPath(_Inout_ VFS* vfs, _Inout_ string* out,
127 _In_opt_ strref path);
128
129// Builds the ordered list of providers that could serve path. Stops at the first opaque layer,
130// since nothing below one is reachable. Takes a reference on every mount it records.
131_Requires_shared_lock_held_(vfs->vfslock) void _vfsSnapshot(_Inout_ VFS* vfs,
132 _Inout_ sa_VFSCand* out,
133 _In_opt_ strref abspath, bool isfile);
134
135// Inserts cache entries that were discovered with no lock held.
136_Requires_exclusive_lock_held_(vfs->vfslock) void _vfsFlushPending(_Inout_ VFS* vfs,
137 _In_ sa_VFSPendEnt* pending);
138
139// Resolves components against a case-sensitive provider by walking its real directory entries,
140// which is how a case-insensitive VFS finds a file whose name it only knows the wrong case of.
141// Writes the provider's real path for it to out and returns its type. Files it passes on the way
142// are appended to pending, to be cached once the caller has the locks back.
143//
144// Calls into the provider, so no VFS lock may be held.
145int _vfsFindCIHelper(_Inout_ string* out, _In_opt_ strref mountpath, _In_ sa_string components,
146 _Inout_ VFSMount* mount, _Inout_ VFSProvider* provif,
147 _Inout_ sa_VFSPendEnt* pending);
148
149// Drops cache-only directories that nothing has touched inside the configured TTL, if the tree
150// has grown past the configured limit. Takes no lock; call it before acquiring any.
151void _vfsMaybeEvict(_Inout_ VFS* vfs);
152
153bool _vfsAddPlatformSpecificMounts(_Inout_ VFS* vfs);
154bool _vfsIsPlatformCaseSensitive();
Generic type-safe containers with runtime type system integration.
#define saDeclare(name)
Definition sarray.h:93
#define stDeclare(name)
Definition stype.h:1908
Copy-on-write strings with automatic memory management and rope optimization.
Definition fs.h:103
VFS Object.
Definition vfsobj.h:51
Virtual Filesystem (VFS)