📄 fatfs.h
字号:
struct _DSTREAM {
STM_DLINK s_dlOpenStreams; // linkage for v_dlOpenStreams
FH_DLINK s_dlOpenHandles; // list of FHANDLE's or SHANDLE's
PVOLUME s_pvol; // VOLUME the DSTREAM is open on
long s_refs; // usage count for the stream
WORD s_flags; // stream status flags (see STF_*)
WORD s_cwPath; // # characters in path to this stream (excluding NULL)
StreamRunList s_runList; // run info from current/last operation
PBUF s_pbufCur; // pointer to stream's current buffer, if any
DWORD s_offbufCur; // stream offset associated with current buffer
DWORD s_size; // length of the stream
FILELOCKSTATE s_filelockstate; // data required to manage sub-file locks on file
CRITICAL_SECTION s_cs; // critical section for this stream
#ifdef TFAT
PDSTREAM s_pstmParent; // parent stream: TFAT only
#endif
//
// Beginning of portion that actually relates to non-STF_VOLUME streams only!
// (actually, s_cwPath belongs down here as well, but since it's a WORD, it fits
// better up above)
//
DSID s_sid; // unique stream ID
DSID s_sidParent; // unique stream ID for parent
DWORD s_offDir; // offset in block of stream's DIRENTRY
DWORD s_blkDir; // block of dir containing stream's DIRENTRY
DWORD s_clusFirst; // first cluster in stream
FILETIME s_ftCreate; // creation time from DIRENTRY
FILETIME s_ftAccess; // last access time from DIRENTRY
FILETIME s_ftWrite; // last write time from DIRENTRY
BYTE s_attr; // file attribute byte
BYTE s_achOEM[OEMNAMESIZE+1];
};
/* Open file handle structure:
*
* There is one these for each open file handle on the volume. It holds the
* current file position, the file access mode, etc.
*/
// values for fh_flags:
#define FHF_FAILUI 0x01 // Used to determine if we need to put up a UI window on failure
#define FHF_LOCKED 0x10 // volume-level lock granted
#define FHF_VOLUME 0x20 // volume-level access only (ie, CreateFile("VOL:"))
#define FHF_UNMOUNTED 0x40 // this handle currently unavailable (volume has been unmounted)
#define FHF_FHANDLE 0x80 // this bit NOT set for SHANDLEs
struct _FHANDLE {
FH_DLINK fh_dlOpenHandles;
PDSTREAM fh_pstm; // DSTREAM for the file
BYTE fh_flags; // handle status flags (see FHF_*)
BYTE fh_mode; // file access & sharing modes
WORD fh_pad;
DWORD fh_pos; // current file position
HANDLE fh_h; // kernel handle to this FHANDLE
HANDLE fh_hProc; // process that opened the file
};
/* Open search handle structure:
*
* There is one of these for each open FindFirst/FindNext. It holds the
* current position of the find and the pattern being sought. For internal
* (SHF_BYORD or SHF_BYCLUS) searches, sh_h is overloaded as the desired
* DIRENTRY ordinal or cluster.
*
* Also, when an SHANDLE is allocated, sh_awcPattern is not really allocated
* to MAX_PATH WCHARs. It is only allocated to the length stored in sh_cwPattern.
*/
#define INVALID_POS 0xFFFFFFFF
#define INVALID_ATTR 0xFFFFFFFF
// The first three "search by" flags are mutually exclusive searches, hence
// they don't need completely separate bits.
// values for sh_flags:
#define SHF_BYNAME 0x01 // search by name
#define SHF_BYORD 0x02 // search by DIRENTRY ordinal
#define SHF_BYCLUS 0x03 // search by DIRENTRY containing specific cluster
#define SHF_BYMASK 0x03 // mask for the mutually exclusive search types
#define SHF_BYATTR 0x04 #define SHF_WILD 0x08 // allow wildcards
#define SHF_DOTDOT 0x10 // allow search for "." and ".." entries
#define SHF_CREATE 0x20 // turn on auto-generated short name creation
#define SHF_UNMOUNTED FHF_UNMOUNTED
#define SHF_NOT_SHANDLE FHF_FHANDLE
struct _SHANDLE {
SH_DLINK sh_dlOpenHandles;
PDSTREAM sh_pstm; // DSTREAM for the directory
BYTE sh_flags; // search status flags (see SHF_*)
BYTE sh_attr; WORD sh_cwPattern; // # characters in sh_awcPattern (includes room for NULL)
DWORD sh_pos; // last position within directory
HANDLE sh_h; // kernel handle to this SHANDLE
HANDLE sh_hProc; // process that opened the file
#ifdef DEBUG
DWORD sh_cbAlloc; // used to track size of this allocation only
#endif
WCHAR sh_awcPattern[MAX_PATH];// search pattern
};
#ifndef UNDER_CE
#define offsetof(x,y) 0
#endif
ERRFALSE(offsetof(FHANDLE,fh_dlOpenHandles) == offsetof(SHANDLE,sh_dlOpenHandles));
ERRFALSE(offsetof(FHANDLE,fh_pstm) == offsetof(SHANDLE,sh_pstm));
ERRFALSE(offsetof(FHANDLE,fh_flags) == offsetof(SHANDLE,sh_flags));
ERRFALSE(offsetof(FHANDLE,fh_h) == offsetof(SHANDLE,sh_h));
ERRFALSE(offsetof(FHANDLE,fh_hProc) == offsetof(SHANDLE,sh_hProc));
/* Define the maximum number of short name (8.3) collisions supported;
* note that if you increase this beyond one more order of magnitude (> 9999),
* then you will have to change itopch() to support larger numbers.
*/
#define MAX_SHORT_NAMES 999
/* Directory search information structure:
*
* This structure can be passed to FindNext to return additional information
* about the directory it just searched. Most of this information is essential
* only if we need to call CreateName. Note that for every DIRINFO structure,
* the caller should have a corresponding SHANDLE structure, because some of the
* information that FindNext records in the DIRINFO is dependent on the SHANDLE
* it was given.
*/
#define DIRINFO_OEM 0x01 // name conforms to 8.3
struct _DIRINFO {
PDIRENTRY di_pde; // pointer to matching DIRENTRY (NULL if none)
DSID di_sid;
DWORD di_clusEntry; // cluster extracted from DIRENTRY
DWORD di_pos; // position of matching (or last) DIRENTRY
DWORD di_posLFN; // position of 1st matching LFN DIRENTRY, if any
int di_cdeNeed; // number of DIRENTRY's needed for LFN (-1 if unknown)
DWORD di_posFree; // position of first free/deleted DIRENTRY to satisfy
int di_cdeFree; // count of free/deleted DIRENTRY(s), 0 if none
DWORD di_posOrphan; // position of orphaned LFN(s) to recover
int di_cdeOrphan; // count of orphaned DIRENTRY(s), 0 if none
int di_cwName; // size of entire name associated with DIRENTRY
PCWSTR di_pwsTail; // pointer to end-most LFN piece, in associated SHANDLE structure
WORD di_cwTail; // size of end-most LFN piece
BYTE di_bNumericTail;// DIRENTRY position (0-6) where numeric tail should start
BYTE di_chksum; // checksum of di_achOEM (valid only if DIRINFO_OEM set)
BYTE di_flags; // see DIRINFO_* above
BYTE di_achOEM[OEMNAMESIZE];
};
typedef struct _DIRINFO DIRINFO, *PDIRINFO;
#define GETDIRENTRYCLUSTER(pvol,pde) ( \
(pvol)->v_clusEOF <= 0xFFFF? \
(pde)->de_clusFirst : \
(pde)->de_clusFirst+(DWORD)((pde)->de_clusFirstHigh<<16)\
)
#define SETDIRENTRYCLUSTER(pvol,pde,clus) { \
(pde)->de_clusFirst = (WORD)(clus); \
if ((pvol)->v_clusEOF > 0xFFFF) \
(pde)->de_clusFirstHigh = (WORD)((clus) >> 16); \
}
#define AccessToMode(dwAccess) ((dwAccess)>>24)
#define FH_MODE_READ AccessToMode(GENERIC_READ) // 0x80
#define FH_MODE_WRITE AccessToMode(GENERIC_WRITE) // 0x40
#define ShareToMode(dwShare) (dwShare)
#define FH_MODE_SHARE_READ ShareToMode(FILE_SHARE_READ) // 0x01
#define FH_MODE_SHARE_WRITE ShareToMode(FILE_SHARE_WRITE) // 0x02
ERRFALSE(FH_MODE_READ!=0);
ERRFALSE(FH_MODE_WRITE!=0);
ERRFALSE((AccessToMode((GENERIC_READ|GENERIC_WRITE)) & (FILE_SHARE_READ|FILE_SHARE_WRITE)) == 0);
// OpenName/CreateName options. These are defined such that ATTR_* flags
// can be combined with them without conflict (but since FH_MODE_* flags already
// conflict with ATTR_*, we have no choice but to shift them into place).
#define NAME_ATTR_MASK 0x000000FF // mask for ATTR_* bits
#define NAME_FILE 0x00000100 // name must be a file
#define NAME_DIR 0x00000200 // name must be a directory
#define NAME_VOLUME 0x00000400 // name may be "VOL:"
#define NAME_NEW 0x00001000 // file must be new
#define NAME_CREATE 0x00002000 // file can be created
#define NAME_TRUNCATE 0x00004000 // file must be truncated
#define NAME_CREATED 0x00008000 // file was actually created
#define NAME_MODE_MASK 0x00FF0000 // mask for FH_MODE_* bits
#define NAME_MODE_SHIFT 16 // shift for FH_MODE_* bits
#define NAME_MODE_READ (FH_MODE_READ << NAME_MODE_SHIFT)
#define NAME_MODE_WRITE (FH_MODE_WRITE << NAME_MODE_SHIFT)
#define NAME_MODE_SHARE_READ (FH_MODE_SHARE_READ << NAME_MODE_SHIFT)
#define NAME_MODE_SHARE_WRITE (FH_MODE_SHARE_WRITE << NAME_MODE_SHIFT)
/* Stucture for SetSizePointer in MISC.C
*/
typedef struct _SIZEPTR {
DWORD c; // count of elements
PVOID p; // pointer to elements
} SIZEPTR;
typedef SIZEPTR *PSIZEPTR;
/* API.C functions
*/
BOOL FAT_NoSupport(void);
BOOL FAT_CloseAllFiles(PVOLUME pvol, HANDLE hProc);
void FAT_Notify(PVOLUME pvol, DWORD dwFlags);
BOOL FATEnter(PVOLUME pvol, BYTE idLog);
void FATEnterQuick(void);
void FATExit(PVOLUME pvol, BYTE idLog);
void FATExitQuick(void);
PDSK FSD_Init(PCWSTR pwsDisk);
BOOL FSD_Deinit(PDSK pdsk);
BOOL WINAPI FATMain(HINSTANCE DllInstance, INT Reason, LPVOID Reserved);
/* BUFFER.C functions
*
* Note that HoldBuffer and UnholdBuffer are actually macros.
*
* Uses of HoldBuffer and UnholdBuffer outside the normal buffer manipulation
* functions (like those in path.c) are simply applying an *additional* hold to a
* buffer that is already known to be held; without that additional hold, a read to
* a different part of the same stream might otherwise release that buffer's contents,
* allowing it to be reused and thereby invalidating any pointers the caller had
* obtained to the earlier contents of the buffer.
*
* This should help explain the logic in the DEBUG-only assertions embedded in the
* macros below. Also, the hold threshold of 32 is arbitrary; it is simply an attempt
* to validate that hold counts will never exceed the capacity of a BYTE.
*/
#define HoldBuffer(pbuf) ( \
ASSERT((pbuf)->b_hold < 32), \
InterlockedIncrement (&((pbuf)->b_hold)) \
)
#define UnholdBuffer(pbuf) ( \
ASSERT((pbuf)->b_hold != 0), \
InterlockedDecrement (&((pbuf)->b_hold)) \
)
#define HeldBuffer(pbuf) ( \
(pbuf)->b_hold != 0 \
)
#define ASSERTHELDBUFFER(pbuf) ( \
(pbuf)->b_hold != 0 \
)
BOOL BufInit(PVOLUME pvol);
void BufDeinit(PVOLUME pvol);
BOOL BufEnter(PVOLUME pvol, BOOL fForce);
void BufExit(PVOLUME pvol);
BOOL AllocBufferPool(PVOLUME pvol);
BOOL FreeBufferPool(PVOLUME pvol);
DWORD ModifyBuffer(PBUF pbuf, PVOID pMod, int cbMod);
void DirtyBuffer(PBUF pbuf);
void DirtyBufferError(PBUF pbuf, PVOID pMod, int cbMod);
DWORD CommitBuffer(PBUF pbuf, BOOL fCS);
void CleanBuffer(PBUF pbuf);
DWORD FindBuffer(PVOLUME pvol, DWORD blk, PDSTREAM pstm, BOOL fNoRead, PBUF *ppbuf);
void AssignStreamBuffer(PDSTREAM pstm, PBUF pbuf, BOOL fCS);
DWORD ReleaseStreamBuffer(PDSTREAM pstm, BOOL fCS);
DWORD ReadStreamBuffer(PDSTREAM pstm, DWORD pos, int lenMod, PVOID *ppvStart, PVOID *ppvEnd);
DWORD ModifyStreamBuffer(PDSTREAM pstm, PVOID pMod, int cbMod);
#define CommitAndReleaseStreamBuffers(pstm) CommitBufferSet(pstm, 1)
#define CommitStreamBuffers(pstm) CommitBufferSet(pstm, 0)
#define CommitVolumeBuffers(pvol) CommitBufferSet((PDSTREAM)(pvol), -1)
//#define CommitAllBuffers() CommitBufferSet(NULL, -1)
//#define CommitOldBuffers() CommitBufferSet(NULL, -2)
#define WriteAndReleaseStreamBuffers(pstm) CommitAndReleaseStreamBuffers(pstm)
#define WriteStreamBuffers(pstm) CommitStreamBuffers(pstm)
DWORD CommitBufferSet(PDSTREAM pstm, int iCommit);
DWORD InvalidateSteamBuffer(PDSTREAM pstm);
void InvalidateBufferSet(PVOLUME pvol, BOOL fAll);
BOOL LockBlocks(PDSTREAM pstm, DWORD pos, DWORD len, DWORD *pblk, DWORD *pcblk, BOOL fWrite);
void UnlockBlocks(PDSTREAM pstm, DWORD blk, DWORD cblk, BOOL fWrite);
/* CACHE.C functions
*/
void PathCacheCreate(PVOLUME pvol, PCWSTR pwsPath, int len, PDSTREAM pstm);
PDSTREAM PathCacheSearch(PVOLUME pvol, PCWSTR *ppwsPath);
BOOL PathCacheInvalidate(PVOLUME pvol, PCWSTR pwsPath);
BOOL PathCacheStreamInvalidate(PVOLUME pvol, PDSTREAM pstm);
int PathCacheLength(PCWSTR *ppwsPath, int celRemove);
PCACHE PathCacheFindStream(PVOLUME pvol, PDSTREAM pstm);
PDSTREAM PathCacheDestroy(PVOLUME pvol, PCACHE pcch, BOOL fClose);
void PathCacheDestroyAll(PVOLUME pvol);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -