1 /* $Id: kFsCache.h 2967 2016-09-26 18:14:13Z bird $ */ 2 /** @file 3 * kFsCache.c - NT directory content cache. 4 */ 5 6 /* 7 * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx@anduin.net> 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 * IN THE SOFTWARE. 26 * 27 * Alternatively, the content of this file may be used under the terms of the 28 * GPL version 2 or later, or LGPL version 2.1 or later. 29 */ 30 31 #ifndef ___lib_nt_kFsCache_h___ 32 #define ___lib_nt_kFsCache_h___ 33 34 35 #include <k/kHlp.h> 36 #include "ntstat.h" 37 #ifndef NDEBUG 38 # include <stdarg.h> 39 #endif 40 41 42 /** @def KFSCACHE_CFG_UTF16 43 * Whether to compile in the UTF-16 names support. */ 44 #define KFSCACHE_CFG_UTF16 1 45 /** @def KFSCACHE_CFG_SHORT_NAMES 46 * Whether to compile in the short name support. */ 47 #define KFSCACHE_CFG_SHORT_NAMES 1 48 /** @def KFSCACHE_CFG_PATH_HASH_TAB_SIZE 49 * Size of the path hash table. */ 50 #define KFSCACHE_CFG_PATH_HASH_TAB_SIZE 99991 51 /** The max length paths we consider. */ 52 #define KFSCACHE_CFG_MAX_PATH 1024 53 /** The max ANSI name length. */ 54 #define KFSCACHE_CFG_MAX_ANSI_NAME (256*3 + 16) 55 /** The max UTF-16 name length. */ 56 #define KFSCACHE_CFG_MAX_UTF16_NAME (256*2 + 16) 57 58 59 60 /** Special KFSOBJ::uCacheGen number indicating that it does not apply. */ 61 #define KFSOBJ_CACHE_GEN_IGNORE KU32_MAX 62 63 64 /** @name KFSOBJ_TYPE_XXX - KFSOBJ::bObjType 65 * @{ */ 66 /** Directory, type KFSDIR. */ 67 #define KFSOBJ_TYPE_DIR KU8_C(0x01) 68 /** Regular file - type KFSOBJ. */ 69 #define KFSOBJ_TYPE_FILE KU8_C(0x02) 70 /** Other file - type KFSOBJ. */ 71 #define KFSOBJ_TYPE_OTHER KU8_C(0x03) 72 /** Caching of a negative result - type KFSOBJ. 73 * @remarks We will allocate enough space for the largest cache node, so this 74 * can metamorph into any other object should it actually turn up. */ 75 #define KFSOBJ_TYPE_MISSING KU8_C(0x04) 76 ///** Invalidated entry flag. */ 77 //#define KFSOBJ_TYPE_F_INVALID KU8_C(0x20) 78 /** @} */ 79 80 /** @name KFSOBJ_F_XXX - KFSOBJ::fFlags 81 * @{ */ 82 /** Use custom generation. 83 * @remarks This is given the value 1, as we use it as an index into 84 * KFSCACHE::auGenerations, 0 being the default. */ 85 #define KFSOBJ_F_USE_CUSTOM_GEN KU32_C(0x00000001) 86 87 /** Whether the file system update the modified timestamp of directories 88 * when something is removed from it or added to it. 89 * @remarks They say NTFS is the only windows filesystem doing this. */ 90 #define KFSOBJ_F_WORKING_DIR_MTIME KU32_C(0x00000002) 91 /** NTFS file system volume. */ 92 #define KFSOBJ_F_NTFS KU32_C(0x80000000) 93 /** Flags that are automatically inherited. */ 94 #define KFSOBJ_F_INHERITED_MASK KU32_C(0xffffffff) 95 /** @} */ 96 97 98 #define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') ) 99 #define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/') 100 101 102 103 104 /** Pointer to a cache. */ 105 typedef struct KFSCACHE *PKFSCACHE; 106 /** Pointer to a core object. */ 107 typedef struct KFSOBJ *PKFSOBJ; 108 /** Pointer to a directory object. */ 109 typedef struct KFSDIR *PKFSDIR; 110 /** Pointer to a directory hash table entry. */ 111 typedef struct KFSOBJHASH *PKFSOBJHASH; 112 113 114 115 /** Pointer to a user data item. */ 116 typedef struct KFSUSERDATA *PKFSUSERDATA; 117 /** 118 * User data item associated with a cache node. 119 */ 120 typedef struct KFSUSERDATA 121 { 122 /** Pointer to the next piece of user data. */ 123 PKFSUSERDATA pNext; 124 /** The key identifying this user. */ 125 KUPTR uKey; 126 /** The destructor. */ 127 void (*pfnDestructor)(PKFSCACHE pCache, PKFSOBJ pObj, PKFSUSERDATA pData); 128 } KFSUSERDATA; 129 130 131 /** 132 * Storage for name strings for the unlikely event that they should grow in 133 * length after the KFSOBJ was created. 134 */ 135 typedef struct KFSOBJNAMEALLOC 136 { 137 /** Size of the allocation. */ 138 KU32 cb; 139 /** The space for names. */ 140 char abSpace[1]; 141 } KFSOBJNAMEALLOC; 142 /** Name growth allocation. */ 143 typedef KFSOBJNAMEALLOC *PKFSOBJNAMEALLOC; 144 145 146 /** 147 * Base cache node. 148 */ 149 typedef struct KFSOBJ 150 { 151 /** Magic value (KFSOBJ_MAGIC). */ 152 KU32 u32Magic; 153 /** Number of references. */ 154 KU32 volatile cRefs; 155 /** The cache generation, see KFSOBJ_CACHE_GEN_IGNORE. */ 156 KU32 uCacheGen; 157 /** The object type, KFSOBJ_TYPE_XXX. */ 158 KU8 bObjType; 159 /** Set if the Stats member is valid, clear if not. */ 160 KBOOL fHaveStats; 161 /** Unused flags. */ 162 KBOOL abUnused[2]; 163 /** Flags, KFSOBJ_F_XXX. */ 164 KU32 fFlags; 165 166 /** Hash value of the name inserted into the parent hash table. 167 * This is 0 if not inserted. Names are only hashed and inserted as they are 168 * first found thru linear searching of its siblings, and which name it is 169 * dependens on the lookup function (W or A) and whether the normal name or 170 * short name seems to have matched. 171 * 172 * @note It was ruled out as too much work to hash and track all four names, 173 * so instead this minimalist approach was choosen in stead. */ 174 KU32 uNameHash; 175 /** Pointer to the next child with the same name hash value. */ 176 PKFSOBJ pNextNameHash; 177 /** Pointer to the parent (directory). 178 * This is only NULL for a root. */ 179 PKFSDIR pParent; 180 181 /** The directory name. (Allocated after the structure.) */ 182 const char *pszName; 183 /** The length of pszName. */ 184 KU16 cchName; 185 /** The length of the parent path (up to where pszName starts). 186 * @note This is valuable when constructing an absolute path to this node by 187 * means of the parent pointer (no need for recursion). */ 188 KU16 cchParent; 189 #ifdef KFSCACHE_CFG_UTF16 190 /** The length of pwszName (in wchar_t's). */ 191 KU16 cwcName; 192 /** The length of the parent UTF-16 path (in wchar_t's). 193 * @note This is valuable when constructing an absolute path to this node by 194 * means of the parent pointer (no need for recursion). */ 195 KU16 cwcParent; 196 /** The UTF-16 object name. (Allocated after the structure.) */ 197 const wchar_t *pwszName; 198 #endif 199 200 #ifdef KFSCACHE_CFG_SHORT_NAMES 201 /** The short object name. (Allocated after the structure, could be same 202 * as pszName.) */ 203 const char *pszShortName; 204 /** The length of pszShortName. */ 205 KU16 cchShortName; 206 /** The length of the short parent path (up to where pszShortName starts). */ 207 KU16 cchShortParent; 208 # ifdef KFSCACHE_CFG_UTF16 209 /** The length of pwszShortName (in wchar_t's). */ 210 KU16 cwcShortName; 211 /** The length of the short parent UTF-16 path (in wchar_t's). */ 212 KU16 cwcShortParent; 213 /** The UTF-16 short object name. (Allocated after the structure, possibly 214 * same as pwszName.) */ 215 const wchar_t *pwszShortName; 216 # endif 217 #endif 218 219 /** Allocation for handling name length increases. */ 220 PKFSOBJNAMEALLOC pNameAlloc; 221 222 /** Pointer to the first user data item */ 223 PKFSUSERDATA pUserDataHead; 224 225 /** Stats - only valid when fHaveStats is set. */ 226 BirdStat_T Stats; 227 } KFSOBJ; 228 229 /** The magic for a KFSOBJ structure (Thelonious Sphere Monk). */ 230 #define KFSOBJ_MAGIC KU32_C(0x19171010) 231 232 233 /** 234 * Directory node in the cache. 235 */ 236 typedef struct KFSDIR 237 { 238 /** The core object information. */ 239 KFSOBJ Obj; 240 241 /** Child objects. */ 242 PKFSOBJ *papChildren; 243 /** The number of child objects. */ 244 KU32 cChildren; 245 /** The allocated size of papChildren. */ 246 KU32 cChildrenAllocated; 247 248 /** Pointer to the child hash table. */ 249 PKFSOBJ *papHashTab; 250 /** The mask shift of the hash table. 251 * Hash table size is a power of two, this is the size minus one. 252 * 253 * @remarks The hash table is optional and populated by lookup hits. The 254 * assumption being that a lookup is repeated and will choose a good 255 * name to hash on. We've got up to 4 different hashes, so this 256 * was the easy way out. */ 257 KU32 fHashTabMask; 258 259 /** Handle to the directory (we generally keep it open). */ 260 #ifndef DECLARE_HANDLE 261 KUPTR hDir; 262 #else 263 HANDLE hDir; 264 #endif 265 /** The device number we queried/inherited when opening it. */ 266 KU64 uDevNo; 267 268 /** The last write time sampled the last time the directory was refreshed. 269 * @remarks May differ from st_mtim because it will be updated when the 270 * parent directory is refreshed. */ 271 KI64 iLastWrite; 272 273 /** Set if populated. */ 274 KBOOL fPopulated; 275 /** Set if it needs re-populated. */ 276 KBOOL fNeedRePopulating; 277 } KFSDIR; 278 279 280 /** 281 * Lookup errors. 282 */ 283 typedef enum KFSLOOKUPERROR 284 { 285 /** Lookup was a success. */ 286 KFSLOOKUPERROR_SUCCESS = 0, 287 /** A path component was not found. */ 288 KFSLOOKUPERROR_PATH_COMP_NOT_FOUND, 289 /** A path component is not a directory. */ 290 KFSLOOKUPERROR_PATH_COMP_NOT_DIR, 291 /** The final path entry is not a directory (trailing slash). */ 292 KFSLOOKUPERROR_NOT_DIR, 293 /** Not found. */ 294 KFSLOOKUPERROR_NOT_FOUND, 295 /** The path is too long. */ 296 KFSLOOKUPERROR_PATH_TOO_LONG, 297 /** Unsupported path type. */ 298 KFSLOOKUPERROR_UNSUPPORTED, 299 /** We're out of memory. */ 300 KFSLOOKUPERROR_OUT_OF_MEMORY, 301 302 /** Error opening directory. */ 303 KFSLOOKUPERROR_DIR_OPEN_ERROR, 304 /** Error reading directory. */ 305 KFSLOOKUPERROR_DIR_READ_ERROR, 306 /** UTF-16 to ANSI conversion error. */ 307 KFSLOOKUPERROR_ANSI_CONVERSION_ERROR, 308 /** ANSI to UTF-16 conversion error. */ 309 KFSLOOKUPERROR_UTF16_CONVERSION_ERROR, 310 /** Internal error. */ 311 KFSLOOKUPERROR_INTERNAL_ERROR 312 } KFSLOOKUPERROR; 313 314 315 /** Pointer to an ANSI path hash table entry. */ 316 typedef struct KFSHASHA *PKFSHASHA; 317 /** 318 * ANSI file system path hash table entry. 319 * The path hash table allows us to skip parsing and walking a path. 320 */ 321 typedef struct KFSHASHA 322 { 323 /** Next entry with the same hash table slot. */ 324 PKFSHASHA pNext; 325 /** Path hash value. */ 326 KU32 uHashPath; 327 /** The path length. */ 328 KU16 cchPath; 329 /** Set if aboslute path. */ 330 KBOOL fAbsolute; 331 /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */ 332 KU8 idxMissingGen; 333 /** The cache generation ID. */ 334 KU32 uCacheGen; 335 /** The lookup error (when pFsObj is NULL). */ 336 KFSLOOKUPERROR enmError; 337 /** The path. (Allocated after the structure.) */ 338 const char *pszPath; 339 /** Pointer to the matching FS object. 340 * This is NULL for negative path entries? */ 341 PKFSOBJ pFsObj; 342 } KFSHASHA; 343 344 345 #ifdef KFSCACHE_CFG_UTF16 346 /** Pointer to an UTF-16 path hash table entry. */ 347 typedef struct KFSHASHW *PKFSHASHW; 348 /** 349 * UTF-16 file system path hash table entry. The path hash table allows us 350 * to skip parsing and walking a path. 351 */ 352 typedef struct KFSHASHW 353 { 354 /** Next entry with the same hash table slot. */ 355 PKFSHASHW pNext; 356 /** Path hash value. */ 357 KU32 uHashPath; 358 /** The path length (in wchar_t units). */ 359 KU16 cwcPath; 360 /** Set if aboslute path. */ 361 KBOOL fAbsolute; 362 /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */ 363 KU8 idxMissingGen; 364 /** The cache generation ID. */ 365 KU32 uCacheGen; 366 /** The lookup error (when pFsObj is NULL). */ 367 KFSLOOKUPERROR enmError; 368 /** The path. (Allocated after the structure.) */ 369 const wchar_t *pwszPath; 370 /** Pointer to the matching FS object. 371 * This is NULL for negative path entries? */ 372 PKFSOBJ pFsObj; 373 } KFSHASHW; 374 #endif 375 376 377 /** @name KFSCACHE_F_XXX 378 * @{ */ 379 /** Whether to cache missing directory entries (KFSOBJ_TYPE_MISSING). */ 380 #define KFSCACHE_F_MISSING_OBJECTS KU32_C(0x00000001) 381 /** Whether to cache missing paths. */ 382 #define KFSCACHE_F_MISSING_PATHS KU32_C(0x00000002) 383 /** @} */ 384 385 386 /** 387 * Directory cache instance. 388 */ 389 typedef struct KFSCACHE 390 { 391 /** Magic value (KFSCACHE_MAGIC). */ 392 KU32 u32Magic; 393 /** Cache flags. */ 394 KU32 fFlags; 395 396 /** The default and custom cache generations for stuff that exists, indexed by 397 * KFSOBJ_F_USE_CUSTOM_GEN. 398 * 399 * The custom generation can be used to invalidate parts of the file system that 400 * are known to be volatile without triggering refreshing of the more static 401 * parts. Like the 'out' directory in a kBuild setup or a 'TEMP' directory are 402 * expected to change and you need to invalidate the caching of these frequently 403 * to stay on top of things. Whereas the sources, headers, compilers, sdk, 404 * ddks, windows directory and such generally doesn't change all that often. 405 */ 406 KU32 auGenerations[2]; 407 /** The current cache generation for missing objects, negative results, ++. 408 * This comes with a custom variant too. Indexed by KFSOBJ_F_USE_CUSTOM_GEN. */ 409 KU32 auGenerationsMissing[2]; 410 411 /** Number of cache objects. */ 412 KSIZE cObjects; 413 /** Memory occupied by the cache object structures. */ 414 KSIZE cbObjects; 415 /** Number of lookups. */ 416 KSIZE cLookups; 417 /** Number of hits in the path hash tables. */ 418 KSIZE cPathHashHits; 419 /** Number of hits walking the file system hierarchy. */ 420 KSIZE cWalkHits; 421 /** Number of child searches. */ 422 KSIZE cChildSearches; 423 /** Number of cChildLookups resolved thru hash table hits. */ 424 KSIZE cChildHashHits; 425 /** The number of child hash tables. */ 426 KSIZE cChildHashTabs; 427 /** The sum of all child hash table sizes. */ 428 KSIZE cChildHashEntriesTotal; 429 /** Number of children inserted into the hash tables. */ 430 KSIZE cChildHashed; 431 /** Number of collisions in the child hash tables. */ 432 KSIZE cChildHashCollisions; 433 /** Number times a object name changed. */ 434 KSIZE cNameChanges; 435 /** Number times a object name grew and needed KFSOBJNAMEALLOC. 436 * (Subset of cNameChanges) */ 437 KSIZE cNameGrowths; 438 439 /** The root directory. */ 440 KFSDIR RootDir; 441 442 /** File system hash table for ANSI filename strings. */ 443 PKFSHASHA apAnsiPaths[KFSCACHE_CFG_PATH_HASH_TAB_SIZE]; 444 /** Number of paths in the apAnsiPaths hash table. */ 445 KSIZE cAnsiPaths; 446 /** Number of collisions in the apAnsiPaths hash table. */ 447 KSIZE cAnsiPathCollisions; 448 /** Amount of memory used by the path entries. */ 449 KSIZE cbAnsiPaths; 450 451 #ifdef KFSCACHE_CFG_UTF16 452 /** Number of paths in the apUtf16Paths hash table. */ 453 KSIZE cUtf16Paths; 454 /** Number of collisions in the apUtf16Paths hash table. */ 455 KSIZE cUtf16PathCollisions; 456 /** Amount of memory used by the UTF-16 path entries. */ 457 KSIZE cbUtf16Paths; 458 /** File system hash table for UTF-16 filename strings. */ 459 PKFSHASHW apUtf16Paths[KFSCACHE_CFG_PATH_HASH_TAB_SIZE]; 460 #endif 461 } KFSCACHE; 462 463 /** Magic value for KFSCACHE::u32Magic (Jon Batiste). */ 464 #define KFSCACHE_MAGIC KU32_C(0x19861111) 465 466 467 /** @def KW_LOG 468 * Generic logging. 469 * @param a Argument list for kFsCacheDbgPrintf */ 470 #ifdef NDEBUG 471 # define KFSCACHE_LOG(a) do { } while (0) 472 #else 473 # define KFSCACHE_LOG(a) kFsCacheDbgPrintf a 474 void kFsCacheDbgPrintfV(const char *pszFormat, va_list va); 475 void kFsCacheDbgPrintf(const char *pszFormat, ...); 476 #endif 477 478 479 KBOOL kFsCacheDirEnsurePopuplated(PKFSCACHE pCache, PKFSDIR pDir, KFSLOOKUPERROR *penmError); 480 KBOOL kFsCacheDirAddChild(PKFSCACHE pCache, PKFSDIR pParent, PKFSOBJ pChild, KFSLOOKUPERROR *penmError); 481 PKFSOBJ kFsCacheCreateObject(PKFSCACHE pCache, PKFSDIR pParent, 482 char const *pszName, KU16 cchName, wchar_t const *pwszName, KU16 cwcName, 483 #ifdef KFSCACHE_CFG_SHORT_NAMES 484 char const *pszShortName, KU16 cchShortName, wchar_t const *pwszShortName, KU16 cwcShortName, 485 #endif 486 KU8 bObjType, KFSLOOKUPERROR *penmError); 487 PKFSOBJ kFsCacheCreateObjectW(PKFSCACHE pCache, PKFSDIR pParent, wchar_t const *pwszName, KU32 cwcName, 488 #ifdef KFSCACHE_CFG_SHORT_NAMES 489 wchar_t const *pwszShortName, KU32 cwcShortName, 490 #endif 491 KU8 bObjType, KFSLOOKUPERROR *penmError); 492 PKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError); 493 PKFSOBJ kFsCacheLookupW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError); 494 PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath, KU32 fFlags, 495 KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor); 496 PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath, KU32 fFlags, 497 KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor); 498 PKFSOBJ kFsCacheLookupWithLengthA(PKFSCACHE pCache, const char *pchPath, KSIZE cchPath, KFSLOOKUPERROR *penmError); 499 PKFSOBJ kFsCacheLookupWithLengthW(PKFSCACHE pCache, const wchar_t *pwcPath, KSIZE cwcPath, KFSLOOKUPERROR *penmError); 500 PKFSOBJ kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError); 501 PKFSOBJ kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError); 502 503 /** @name KFSCACHE_LOOKUP_F_XXX - lookup flags 504 * @{ */ 505 /** No inserting new cache entries. 506 * This effectively prevent directories from being repopulated too. */ 507 #define KFSCACHE_LOOKUP_F_NO_INSERT KU32_C(1) 508 /** No refreshing cache entries. */ 509 #define KFSCACHE_LOOKUP_F_NO_REFRESH KU32_C(2) 510 /** @} */ 511 512 KU32 kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj); 513 KU32 kFsCacheObjReleaseTagged(PKFSCACHE pCache, PKFSOBJ pObj, const char *pszWhere); 514 #ifndef NDEBUG /* enable to debug object release. */ 515 # define kFsCacheObjRelease(a_pCache, a_pObj) kFsCacheObjReleaseTagged(a_pCache, a_pObj, __FUNCTION__) 516 #endif 517 KU32 kFsCacheObjRetain(PKFSOBJ pObj); 518 PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey, KSIZE cbUserData); 519 PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey); 520 KBOOL kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash); 521 KBOOL kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash); 522 KBOOL kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash); 523 KBOOL kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash); 524 525 KBOOL kFsCacheFileSimpleOpenReadClose(PKFSCACHE pCache, PKFSOBJ pFileObj, KU64 offStart, void *pvBuf, KSIZE cbToRead); 526 527 PKFSCACHE kFsCacheCreate(KU32 fFlags); 528 void kFsCacheDestroy(PKFSCACHE); 529 void kFsCacheInvalidateMissing(PKFSCACHE pCache); 530 void kFsCacheInvalidateAll(PKFSCACHE pCache); 531 void kFsCacheInvalidateCustomMissing(PKFSCACHE pCache); 532 void kFsCacheInvalidateCustomBoth(PKFSCACHE pCache); 533 KBOOL kFsCacheSetupCustomRevisionForTree(PKFSCACHE pCache, PKFSOBJ pRoot); 534 KBOOL kFsCacheInvalidateDeletedDirectoryA(PKFSCACHE pCache, const char *pszDir); 535 536 #endif 537