?? stream.c
字號:
break;
}
// posEnd advances, and clus becomes the new clusEnd
posEnd += pvol->v_cbClus;
if (clusEnd != UNKNOWN_CLUSTER)
clusPrev = clusEnd;
clusEnd = clus;
} while (posEnd < cbNew);
// If the stream has any new clusters at all...
if (clusEnd != UNKNOWN_CLUSTER) {
// If a PACK fails, we're having trouble writing to the FAT
if (clus != UNKNOWN_CLUSTER) {
if (PACK(pvol, clusEnd, EOF_CLUSTER, NULL) != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!ResizeStream: trouble terminating new FAT chain\r\n")));
clus = UNKNOWN_CLUSTER;
}
AppendRunList(&pstm->s_runList, posEnd, EOF_CLUSTER);
}
if (pstm->s_size != posEnd) {
pstm->s_size = posEnd;
pstm->s_flags |= STF_DIRTY;
}
// If we couldn't allocate all the clusters we needed,
// then (try to) resize the stream to its original size.
if (clus == UNKNOWN_CLUSTER) {
DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!ResizeStream: shrinking FAT chain back down...\r\n")));
ResizeStream(pstm, oldSize, dwResizeFlags | RESIZESTREAM_SHRINK);
dwError = ERROR_DISK_FULL;
}
else {
// It's important that we record the cluster-granular
// size for directories, because when CreateName grows a
// directory, it uses this size to calculate how much data
// has to be zeroed. For all other streams, it's important
// to record only the exact number of bytes requested.
if (!(pstm->s_attr & ATTR_DIRECTORY)) {
pstm->s_size = cbNew;
}
}
}
#ifdef TFAT
// Need to update the parent dir in all cases for a file and only if the
// first cluster changed for a directory.
if (pvol->v_fTfat && (!(pstm->s_attr & ATTR_DIRECTORY) || bFirstClusChanged))
UpdateDirEntryCluster(pstm);
#endif
// Commit and release FAT buffers now
if (dwResizeFlags & RESIZESTREAM_UPDATEFAT) {
BOOL fTempWriteThru = FALSE;
// If stream is write-through, but FAT stream is not, temporarily make it so that the
// modified FAT buffers will be write-through.
if ((pstm->s_flags & STF_WRITETHRU) && !(pvol->v_pstmFAT->s_flags & STF_WRITETHRU)) {
fTempWriteThru = TRUE;
pvol->v_pstmFAT->s_flags |= STF_WRITETHRU;
}
WriteAndReleaseStreamBuffers(pvol->v_pstmFAT);
if (fTempWriteThru)
pvol->v_pstmFAT->s_flags &= ~STF_WRITETHRU;
}
UnlockFAT(pvol);
DEBUGMSG(ZONE_STREAMS || ZONE_ERRORS && dwError,(DBGTEXT("FATFS!ResizeStream(GROW) returned %d for '%.11hs'\r\n"), dwError, pstm->s_achOEM));
return dwError;
}
// If shrinking was not enabled, then we're done
if (!(dwResizeFlags & RESIZESTREAM_SHRINK))
return ERROR_SUCCESS;
// We enter the FAT's critical section even though we're just freeing
// clusters, because in the process, we could alter the FAT stream's
// current buffer, and that could mess up someone else accessing the FAT.
LockFAT(pvol);
// If clusEnd is NO_CLUSTER, then all the file's clusters can be freed;
// set pstm->s_clusFirst to UNKNOWN_CLUSTER, which will get propagated
// as ZERO to the DIRENTRY when the stream is committed (CommitStream will
// eventually do that, because we also set STF_DIRTY, below).
if (clusEnd == NO_CLUSTER) {
// clusEnd becomes the first cluster to free.
if (pstm->s_clusFirst != UNKNOWN_CLUSTER)
pstm->s_flags |= STF_DIRTY_CLUS;
clusEnd = pstm->s_clusFirst;
pstm->s_clusFirst = UNKNOWN_CLUSTER;
bFirstClusChanged = TRUE;
}
else {
dwError = PACK(pvol, clusEnd, EOF_CLUSTER, &clusEnd);
}
// Update the stream's new size
pstm->s_size = cbNew;
pstm->s_flags |= STF_DIRTY;
// Now free all the remaining clusters in the chain.
#ifdef TFAT
// TFAT - don't delete the cluster, freeze it instead
if (pstm->s_pvol->v_fTfat) {
DWORD clusFirst = NO_CLUSTER, clusNext = clusEnd;
// Get the last cluster in the chain
while (!dwError && clusNext >= DATA_CLUSTER && !ISEOF(pvol, clusNext))
{
if (NO_CLUSTER == clusFirst)
clusFirst = clusEnd;
clusEnd = clusNext;
// get next cluster
dwError = UNPACK( pvol, clusNext, &clusNext );
}
if (NO_CLUSTER != clusFirst)
FreezeClusters (pvol, clusFirst, clusEnd);
// Need to update the parent dir in all cases for a file and only if the
// first cluster changed for a directory.
if (!(pstm->s_attr & ATTR_DIRECTORY) || bFirstClusChanged)
UpdateDirEntryCluster(pstm);
}
else
#endif
{
while (!dwError && clusEnd >= DATA_CLUSTER && !ISEOF(pvol, clusEnd)) {
FreeClustersOnDisk(pvol, clusEnd, 1);
dwError = PACK(pvol, clusEnd, FREE_CLUSTER, &clusEnd);
}
}
// Commit and release FAT buffers now.
if (dwResizeFlags & RESIZESTREAM_UPDATEFAT)
WriteAndReleaseStreamBuffers(pvol->v_pstmFAT);
// We need to update the stream's run info
dwError = TruncateRunList (&pstm->s_runList, cbNew);
if (dwError == ERROR_SUCCESS) {
DWORD dwEndPosition = (cbNew + pvol->v_cbClus - 1) & ~(pvol->v_cbClus - 1);
dwError = AppendRunList(&pstm->s_runList, dwEndPosition, EOF_CLUSTER);
}
UnlockFAT(pvol);
DEBUGMSG(ZONE_STREAMS || ZONE_ERRORS && dwError,(DBGTEXT("FATFS!ResizeStream(SHRINK) returned %d for '%.11hs'\r\n"), dwError, pstm->s_achOEM));
return dwError;
}
/* CheckStreamHandles - Check for stream with open handles
*
* ENTRY
* pvol - pointer to VOLUME
* psid - pointer to SID, or NULL to check all streams for open handles
*
* EXIT
* TRUE if stream exists and has open handles, FALSE if not
*
* NOTES
* This check excludes VOLUME-based handles, because it excludes VOLUME-
* based streams (ie, the FAT and root directory).
*/
BOOL CheckStreamHandles(PVOLUME pvol, PDSID psid)
{
PDSTREAM pstm;
BOOL fOpen = FALSE;
EnterCriticalSection(&pvol->v_csStms);
for (pstm = pvol->v_dlOpenStreams.pstmNext; pstm != (PDSTREAM)&pvol->v_dlOpenStreams; pstm = pstm->s_dlOpenStreams.pstmNext) {
if (pstm->s_flags & STF_VOLUME)
continue;
if (psid == NULL || pstm->s_sid.sid_clusDir == psid->sid_clusDir && pstm->s_sid.sid_ordDir == psid->sid_ordDir) {
fOpen = (pstm->s_dlOpenHandles.pfhNext != (PFHANDLE)&pstm->s_dlOpenHandles);
if (psid || fOpen)
break;
}
}
LeaveCriticalSection(&pvol->v_csStms);
return fOpen;
}
/* UpdateSourceStream - Updates source stream after a MoveFile
*
* ENTRY
* pvol - pointer to VOLUME
* psidSrc - pointer to SID of the source stream
* pdiDst - pointer to DIRINFO of destination file
* pstmDstParent - pointer to stream of parent directory of destination file
*
* EXIT
* None
*
* NOTES
* This is necessary in case there are open file handles that point to the
* source stream.
*/
VOID UpdateSourceStream (PVOLUME pvol, PDSID psidSrc, PDIRINFO pdiDst, PDSTREAM pstmDstParent)
{
// Search through any open handles that carry the source stream
// and update the stream to point to the destination
PDSTREAM pstmSrc;
EnterCriticalSection(&pvol->v_csStms);
// Search for a stream that matches stream ID of source
for (pstmSrc = pvol->v_dlOpenStreams.pstmNext; pstmSrc != (PDSTREAM)&pvol->v_dlOpenStreams;
pstmSrc = pstmSrc->s_dlOpenStreams.pstmNext) {
if (pstmSrc->s_sid.sid_clusDir == psidSrc->sid_clusDir && pstmSrc->s_sid.sid_ordDir == psidSrc->sid_ordDir)
break;
}
pstmSrc->s_refs++;
LeaveCriticalSection(&pvol->v_csStms);
// If we found a match, update stream's info so it refers to the destination file now
if (pstmSrc != (PDSTREAM)&pvol->v_dlOpenStreams) {
EnterCriticalSection (&pstmSrc->s_cs);
memcpy(pstmSrc->s_achOEM, pdiDst->di_pde->de_name, sizeof(pdiDst->di_pde->de_name));
pstmSrc->s_sid = pdiDst->di_sid;
pstmSrc->s_sidParent = pstmDstParent->s_sid;
pstmSrc->s_cwPath = pdiDst->di_cwName + pstmDstParent->s_cwPath + 1;
if ((pstmDstParent->s_pbufCur) && !(pstmSrc->s_attr & ATTR_DIRECTORY)) {
pstmSrc->s_blkDir = pstmDstParent->s_pbufCur->b_blk;
pstmSrc->s_offDir = (PBYTE)pdiDst->di_pde - pstmDstParent->s_pbufCur->b_pdata;
}
#ifdef TFAT
// Update the parent stream, if needed
if (pstmSrc->s_pvol->v_fTfat && pstmSrc->s_pstmParent && pstmSrc->s_pstmParent != pstmDstParent) {
// Remove reference to the previous parent
ASSERT(pstmSrc->s_pstmParent->s_refs);
if(1 == pstmSrc->s_pstmParent->s_refs){
EnterCriticalSection(&pstmSrc->s_pstmParent->s_cs);
CloseStream(pstmSrc->s_pstmParent);
} else{
--pstmSrc->s_pstmParent->s_refs;
}
// Add reference to the new parent
pstmSrc->s_pstmParent = pstmDstParent;
pstmDstParent->s_refs++;
}
#endif
LeaveCriticalSection (&pstmSrc->s_cs);
}
pstmSrc->s_refs--;
}
/* StreamOpenedForExclAccess - Check if file is already open for exclusive access
*
* ENTRY
* pvol - pointer to VOLUME
*
* EXIT
* TRUE if file is already open for exclusive access, FALSE if not
*
* NOTES
* This check excludes VOLUME-based handles, because it excludes VOLUME-
* based streams (ie, the FAT and root directory).
*/
BOOL StreamOpenedForExclAccess(PVOLUME pvol, PDSID psid)
{
PDSTREAM pstm;
PFHANDLE pfh, pfhEnd;
BOOL fOpenedForExclAccess = FALSE;
ASSERT(psid);
EnterCriticalSection(&pvol->v_csStms);
for (pstm = pvol->v_dlOpenStreams.pstmNext;
!fOpenedForExclAccess && pstm != (PDSTREAM)&pvol->v_dlOpenStreams;
pstm = pstm->s_dlOpenStreams.pstmNext) {
if (pstm->s_sid.sid_clusDir == psid->sid_clusDir && pstm->s_sid.sid_ordDir == psid->sid_ordDir) {
// Walk the handle list. Return TRUE if any are opened for exclusive access.
for(pfh = pstm->s_dlOpenHandles.pfhNext, pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;
pfh != pfhEnd; pfh = pfh->fh_dlOpenHandles.pfhNext) {
if ( (!(pfh->fh_mode & FH_MODE_SHARE_READ) || (pfh->fh_mode & FH_MODE_WRITE)) &&
!(pfh->fh_mode & FH_MODE_SHARE_WRITE)) {
fOpenedForExclAccess = TRUE;
break;
}
}
}
}
LeaveCriticalSection(&pvol->v_csStms);
return fOpenedForExclAccess;
}
/* CheckStreamSharing - Check requested mode against stream
*
* ENTRY
* pstm - pointer to DSTREAM
* mode - requested mode
*
* EXIT
* TRUE if all handles for stream permit the specified mode, FALSE if not
*/
BOOL CheckStreamSharing(PDSTREAM pstm, int mode, BOOL fTruncate)
{
BYTE bRequiredShare = 0;
BYTE bExcludedAccess = 0;
PFHANDLE pfh, pfhEnd;
ASSERT(pstm);
ASSERT(OWNCRITICALSECTION(&pstm->s_cs));
// If user wants to open a file for read and/or write, all
// open handles must have been opened for read sharing and/or
// write sharing respectively. Also, if user wants to truncate,
// other handles must have write sharing.
if (mode & FH_MODE_READ)
bRequiredShare |= FH_MODE_SHARE_READ;
if (fTruncate || (mode & FH_MODE_WRITE))
bRequiredShare |= FH_MODE_SHARE_WRITE;
// If user disallows a file for read sharing and/or write
// sharing, open handles cannot have been opened for read and/or
// write respectively
if (!(mode & FH_MODE_SHARE_READ))
bExcludedAccess |= FH_MODE_READ;
if (!(mode & FH_MODE_SHARE_WRITE))
bExcludedAccess |= FH_MODE_WRITE;
pfh = pstm->s_dlOpenHandles.pfhNext;
pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;
while (pfh != pfhEnd) {
if ((pfh->fh_mode & bRequiredShare) != bRequiredShare)
return FALSE;
if (pfh->fh_mode & bExcludedAccess)
return FALSE;
pfh = pfh->fh_dlOpenHandles.pfhNext;
}
return TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -