⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 volume.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码。移植性非常高。 微软的代码
💻 C
📖 第 1 页 / 共 5 页
字号:

                pbgbs = (PVOID)LocalReAlloc((HLOCAL)pbgbs,
                                            pdsk->d_diActive.di_bytes_per_sect,
                                            LMEM_MOVEABLE);
                if (pbgbs) {
                    DEBUGALLOC(pdsk->d_diActive.di_bytes_per_sect - cbSecOrig);
                    *ppbgbs = pbgbs;        // update the caller's buffer address, too
                }
                else {
                    dwError = GetLastError();
                    DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: out of memory, volume deemed invalid (%d)\n"), dwError));
                    pvol->v_flags |= VOLF_INVALID;
                    goto exit;
                }
            }
        }
        else {

            // If SetDiskInfo returned an error, then revert to the
            // size originally reported, but continue trying to mount.

            pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: SetDiskInfo call to driver failed (%d)\n"), GetLastError()));
        }
    }

    // Perform some trial reads now (first sector of first FAT, first
    // sector of second FAT if one exists, and anything else we think of).
    // We will clear VOLF_INVALID only on success.  NOTE that we can now reuse
    // the sector containing the BPB;  we've extracted everything we needed
    // from it.

#ifdef FAT32
    if (pvol->v_flags & VOLF_32BIT_FAT) {

        PBIGFATBOOTFSINFO pFSInfo;

        dwError = ReadWriteDisk(pvol,
                                pdsk->d_hdsk,
                                DISK_IOCTL_READ,
                                &pdsk->d_diActive,
                                pvol->v_secVolBias + 1,
                                1,
                                pbgbs);

        if (dwError != ERROR_SUCCESS
            ||
            *(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
            ||
            *(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG)
        {
            DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying extended boot sector, volume deemed invalid (%d)\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }

        // If secFSInfo happens to be 1 (which is typical), then there's no need
        // to perform another read, since it's the same sector we just read (above).

        if (pvol->v_secFSInfo != 1) {
            dwError = ReadWriteDisk(pvol,
                                    pdsk->d_hdsk,
                                    DISK_IOCTL_READ,
                                    &pdsk->d_diActive,
                                    pvol->v_secVolBias + pvol->v_secFSInfo,
                                    1,
                                    pbgbs);
        }

        if (dwError != ERROR_SUCCESS
            ||
            *(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
            ||
            *(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG
            ||
            (pFSInfo = (PBIGFATBOOTFSINFO)((PBYTE)pbgbs + OFFSETFSINFOFRMSECSTRT))->bfFSInf_Sig != FSINFOSIG)
        {
            DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying FS info sector, volume deemed invalid (%d)\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }

        // If we're still here, then assume that we can use the BIGFATBOOTFSINFO fields,
        // if they look valid....

        if (pFSInfo->bfFSInf_free_clus_cnt < pvol->v_clusMax &&
            pFSInfo->bfFSInf_next_free_clus <= pvol->v_clusMax) {

            pvol->v_cclusFree = pFSInfo->bfFSInf_free_clus_cnt;
            pvol->v_clusAlloc = pFSInfo->bfFSInf_next_free_clus;
        }
        else {
            // Note that if the FSInfo fields are simply UNKNOWN_CLUSTER, then my assumption
            // is that they simply haven't been initialized yet (as opposed to being truly bogus).

            DEBUGMSG((ZONE_INIT || ZONE_ERRORS) &&
                     pFSInfo->bfFSInf_free_clus_cnt != UNKNOWN_CLUSTER &&
                     pFSInfo->bfFSInf_next_free_clus != UNKNOWN_CLUSTER, (DBGTEXT("FATFS!TestVolume: FS info data suspicious (%x,%x), ignoring...\n"), pFSInfo->bfFSInf_free_clus_cnt, pFSInfo->bfFSInf_next_free_clus));
        }
    }
#endif  // FAT32

    dwError = ReadWriteDisk(pvol,
                            pdsk->d_hdsk,
                            DISK_IOCTL_READ,
                            &pdsk->d_diActive,
                            pvol->v_secBlkBias + 0,
                            1,
                            pbgbs);

    if (dwError != ERROR_SUCCESS || !ValidateFATSector(pvol, pbgbs))
    {
        DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading first FAT, volume deemed invalid (%d)\n"), dwError));
        pvol->v_flags |= VOLF_INVALID;
        goto exit;
    }

    if (pvol->v_flags & VOLF_BACKUP_FAT) {

        dwError = ReadWriteDisk(pvol,
                                pdsk->d_hdsk,
                                DISK_IOCTL_READ,
                                &pdsk->d_diActive,
                                pvol->v_secBlkBias + pvol->v_csecFAT,
                                1,
                                pbgbs);

        if (dwError != ERROR_SUCCESS || !ValidateFATSector(pvol, pbgbs))
        {
            DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading backup FAT, volume deemed invalid (%d)\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }
    }

    // Verify we can read the last sector in the last cluster of the volume too...
#if 0
    dwError = ReadWriteDisk(pvol,
                            pdsk->d_hdsk,
                            DISK_IOCTL_READ,
                            &pdsk->d_diActive,
                            CLUSTERTOSECTOR(pvol, pvol->v_clusMax) +
                                (1 << pvol->v_log2csecClus) - 1,
                            1,
                            pbgbs);

    if (dwError != ERROR_SUCCESS)
    {
        DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading last sector, volume deemed invalid (%d)\n"), dwError));
        pvol->v_flags |= VOLF_INVALID;
        goto exit;
    }
#endif

    // If we modified the drive parameters but the volume isn't valid anyway, restore the default parameters.

  exit:
    if ((pvol->v_flags & (VOLF_MODDISKINFO | VOLF_INVALID)) == (VOLF_MODDISKINFO | VOLF_INVALID)) {
        pvol->v_flags &= ~VOLF_MODDISKINFO;
        pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
        SetDiskInfo(pdsk->d_hdsk, &pdsk->d_diActive);
    }

    return dwError;
}


/*  RefreshVolume - Refresh a VOLUME's handles
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *
 *  EXIT
 *      Stream handles are restored, provided the volume is valid AND
 *      the streams appear to be in the same state we left them.
 */

void RefreshVolume(PVOLUME pvol)
{
    PDSTREAM pstm, pstmEnd;

    if (!(pvol->v_flags & (VOLF_REMOUNTED | VOLF_RECYCLED)))
        return;

    ASSERT(OWNCRITICALSECTION(&pvol->v_cs));

    // Walk the open stream list, regenerate each stream, then walk the
    // open handle list for each successfully regenerated stream, and clear
    // the unmounted bit for each open handle.

    // First, make sure the VISITED bit is clear in every stream currently
    // open on this volume.

    EnterCriticalSection(&pvol->v_csStms);

    pstm = pvol->v_dlOpenStreams.pstmNext;
    pstmEnd = (PDSTREAM)&pvol->v_dlOpenStreams;

    while (pstm != pstmEnd) {
        pstm->s_flags &= ~STF_VISITED;
        pstm = pstm->s_dlOpenStreams.pstmNext;
    }

    // Now find the next unvisited stream.  Note that every iteration of the
    // loop starts with the volume critical section held.

  restart:
    pstm = pvol->v_dlOpenStreams.pstmNext;
    while (pstm != pstmEnd) {

        if (pstm->s_flags & STF_VISITED) {
            pstm = pstm->s_dlOpenStreams.pstmNext;
            continue;
        }

        pstm->s_flags |= STF_VISITED;

        // Add a ref to insure that the stream can't go away once we
        // let go of the volume's critical section.

        pstm->s_refs++;
        
        LeaveCriticalSection(&pvol->v_csStms);
        EnterCriticalSection(&pstm->s_cs);

        // Find/read the block containing this stream's DIRENTRY, unless
        // it's a VOLUME-based stream, in which case we'll just automatically
        // remount it.

        ASSERT(pstm->s_pvol == pvol);

        // Volume handles are always remounted, regardless

        if (pstm->s_flags & STF_VOLUME)
            pstm->s_flags &= ~STF_UNMOUNTED;

        if ((pstm->s_flags & STF_UNMOUNTED) && !(pvol->v_flags & VOLF_INVALID)) {

            PBUF pbuf;

            ASSERT(pstm->s_blkDir != INVALID_BLOCK);

            if (FindBuffer(pvol, pstm->s_blkDir, NULL, FALSE, &pbuf) == ERROR_SUCCESS) {

                PDIRENTRY pde;

                pde = (PDIRENTRY)(pbuf->b_pdata + pstm->s_offDir);

                // Check the 8.3 name first...

                if (memcmp(pde->de_name, pstm->s_achOEM, sizeof(pde->de_name)) == 0) {

                    
                    DWORD clusEntry = GETDIRENTRYCLUSTER(pstm->s_pvol, pde);
                    if (clusEntry == NO_CLUSTER)
                        clusEntry = UNKNOWN_CLUSTER;

                    if ((pstm->s_flags & STF_DIRTY) ||
                        pde->de_attr == pstm->s_attr &&
                        pde->de_size == pstm->s_size && clusEntry == pstm->s_clusFirst)
                    {
                        pstm->s_flags &= ~STF_UNMOUNTED;
                    }
                }
                UnholdBuffer(pbuf);
            }
        }

        // If the stream is now (re)mounted, make sure all its handles are (re)mounted also.

        if (!(pstm->s_flags & STF_UNMOUNTED)) {

            PFHANDLE pfh, pfhEnd;

            pfh = pstm->s_dlOpenHandles.pfhNext;
            pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;

            while (pfh != pfhEnd) {
                pfh->fh_flags &= ~FHF_UNMOUNTED;
                pfh = pfh->fh_dlOpenHandles.pfhNext;
            }
        }

        CloseStream(pstm);
        EnterCriticalSection(&pvol->v_csStms);
        goto restart;
    }

    LeaveCriticalSection(&pvol->v_csStms);

    // Make sure the buffer pool is clean too, now that we've finished
    // resurrecting and committing all resurrectable streams.

    if (CommitVolumeBuffers(pvol) == ERROR_SUCCESS) {

        DEBUGMSG(ZONE_INIT && (pvol->v_flags & VOLF_DIRTY),(DBGTEXT("FATFS!RefreshVolume: dirty data successfully committed\n")));
        pvol->v_flags &= ~VOLF_DIRTY;

    }
    else
        DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!RefreshVolume: unable to commit dirty data to volume 0x%08x\n"), pvol));
}




DWORD LockVolume(PVOLUME pvol, DWORD dwFlags)
{
    DWORD dwError = ERROR_SUCCESS;
//    pvol->v_flags |= dwFlags;
//   return dwError;
    
    EnterCriticalSection(&pvol->v_cs);

    // Since VOLF_LOCKED is the concatenation of all lock flags, LockVolume
    // is disallowed if any lock of any kind is already in effect.  This
    // simplification should be fine for our purposes.

    if (!(pvol->v_flags & VOLF_LOCKED)) {

        pvol->v_flags |= dwFlags;

        if (CheckStreamHandles(pvol, NULL)) {
            pvol->v_flags &= ~dwFlags;
            dwError = ERROR_ACCESS_DENIED;
        }
    }
    else
        dwError = ERROR_DRIVE_LOCKED;

    LeaveCriticalSection(&pvol->v_cs);

    // If successful, wait until all threads are done before returning.
    // Easiest way to do this is simulate a quick power-off/power-on sequence. 
    // Since the volume's LOCKED bit is already set, we don't need to worry about
    // any new calls doing anything until the volume is unlocked.

    if (!dwError && cFATThreads > 1) {
        FAT_Notify(pvol, FSNOTIFY_POWER_OFF);
        FAT_Notify(pvol, FSNOTIFY_DEVICES_ON);
    }
    return dwError;
}


/*  UnlockVolume - Unlock a previously locked VOLUME
 *
 *  ENTRY
 *      pvol -> VOLUME structure
 *
 *  EXIT
 *      None
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -