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

📄 scan.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码.移植性非常高. 里面带有source i.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    scan.c

Abstract:

    This file contains routines for scanning volumes for inconsistencies.

Revision History:

--*/

#include "fatfs.h"


#define LOSTCLUS_PARENT         0x10000000      // start (potentially) of some lost cluster chain
#define LOSTCLUS_CHILD          0x20000000      // referred to by another child or parent
#define LOSTCLUS_MODIFIED       0x80000000
#define LOSTCLUS_FLAGS          (LOSTCLUS_PARENT | LOSTCLUS_CHILD | LOSTCLUS_MODIFIED)

typedef struct _LOSTCLUS {
    DWORD   dwIndex;
    DWORD   dwData;
    struct _LOSTCLUS *plcNext;
} LOSTCLUS, *PLOSTCLUS;


int ScanLostClusters(PVOLUME pvol, PDWORD pdwClusArray, PLOSTCLUS plc, int cLostClusters)
{
    int i, j, k;
    DWORD dwClus;
    int cLostChains = 0;

    for (i=0, j=0, dwClus=DATA_CLUSTER; dwClus <= pvol->v_clusMax && j < cLostClusters; i++,dwClus++) {

        DWORD dwData;
        DWORD dwError = UNPACK(pvol, dwClus, &dwData);

        if (dwError) {
            DEBUGMSG(ZONE_LOGIO || ZONE_ERRORS,(DBGTEXT("FATFS!ScanLostClusters: error reading cluster %d (%d)\n"), dwClus, dwError));
            break;
        }

        if (!TestBitArray(pdwClusArray, i)) {

            if (dwData != FREE_CLUSTER) {

                
                if (dwData == (pvol->v_clusEOF | 0xF))
                    dwData = UNKNOWN_CLUSTER;

                // Make sure the dwIndex fields never get these flag bits set "accidentally"
                ASSERT(!(dwClus & LOSTCLUS_FLAGS));

                plc[j].dwIndex = dwClus;
                plc[j].dwData = dwData;
                plc[j].plcNext = NULL;
                j++;
            }
        }
    }

    ASSERT(j == cLostClusters);

    // OK, now we're ready to identify all the chains.  For every lost cluster,
    // if it has a child, then that child better be lost too, or we must truncate
    // that cluster's chain immediately.  Normally, its child *will* also be lost;
    // we will keep marking all the lost clusters in that chain as LOSTCLUS_CHILD,
    // until we reach the end of the chain or we had to truncate it.

    for (i=0; i<cLostClusters; i++) {

        DWORD dwNext;

        if (plc[i].dwIndex & LOSTCLUS_CHILD)
            continue;   // already visited in the context of some other lost cluster's chain

        ASSERT(!(plc[i].dwIndex & LOSTCLUS_PARENT));
        plc[i].dwIndex |= LOSTCLUS_PARENT;

        k = i;
        dwNext = plc[i].dwData;

        while (dwNext) {

            j = 0;
            if (dwNext > pvol->v_clusMax) {
                // We are either at the natural end of a cluster chain,
                // or we've encountered a too-large cluster number;  if
                // the latter, then we need to properly truncate the chain.
                if (dwNext == UNKNOWN_CLUSTER)
                    break;      // the entry is OK as-is
                goto truncate;
            }

            for (; j<cLostClusters; j++) {

                DWORD dwCur = plc[j].dwIndex;
                if (dwNext == (dwCur & ~LOSTCLUS_FLAGS)) {

                    if (dwCur & LOSTCLUS_CHILD)
                        goto truncate;

                    plc[j].dwIndex |= LOSTCLUS_CHILD;
                    plc[k].plcNext = &plc[j];

                    if (dwCur & LOSTCLUS_PARENT) {
                        plc[j].dwIndex &= ~LOSTCLUS_PARENT;
                        dwNext = 0;
                        break;
                    }
                    dwNext = plc[j].dwData;
                    break;
                }
            }

            // If we couldn't find the next lost cluster, truncate the current
            // lost cluster chain

            if (j == cLostClusters) {
truncate:
                plc[k].dwIndex |= LOSTCLUS_MODIFIED;
                plc[k].dwData = UNKNOWN_CLUSTER;
                break;
            }
            k = j;
        }
    }

    // One more pass through the lost cluster array looking for LOSTCLUS_PARENT flags
    // will tell us how many total lost chains there are.

    for (i=0; i<cLostClusters; i++) {
        if (plc[i].dwIndex & LOSTCLUS_PARENT)
            cLostChains++;
    }

    return cLostChains;
}


DWORD FreeLostClusters(PVOLUME pvol, PLOSTCLUS plc, int cLostClusters)
{
    int i;
    DWORD dwError = ERROR_SUCCESS;

    // Simply zap all the clusters in the LOSTCLUS array...

    for (i=0; i<cLostClusters; i++) {
        dwError = PACK(pvol, plc[i].dwIndex & ~LOSTCLUS_FLAGS, FREE_CLUSTER, NULL);
        if (dwError)
            break;
    }
    return dwError;
}


DWORD ReclaimLostClusters(PVOLUME pvol, PLOSTCLUS plc, int cLostClusters, int cLostChains)
{
    int i, j, k;
    PLOSTCLUS plcCur;
    DWORD dwError = ERROR_SUCCESS;

    // WARNING: If you change this template string, make sure that 
    // wsFileName is still large enough to hold the result from wsprintf! -JTP
    static CONST WCHAR awcTemplate[] = TEXTW("FILE%04d.CHK");


    // For each chain, we want to create a FILEnnnn.CHK file, and hook all the clusters
    // in that chain onto that file.

    for (i=1,k=1; i<=cLostChains && !dwError; i++) {

        PDSTREAM pstm;

        do {
            WCHAR wsFileName[OEMNAMESIZE+2];
            int flName = NAME_FILE | NAME_NEW | NAME_CREATE;

            // Each time we build a name, we also auto-increment the "nnnn" part

            wsprintf(wsFileName, awcTemplate, k++);
            pstm = OpenName((PDSTREAM)pvol, wsFileName, 0, &flName);

            
        } while (!pstm && GetLastError() == ERROR_FILE_EXISTS && k <= 999);

        if (pstm) {

            DWORD dwNewSize = 0;
            ASSERT(pstm->s_clusFirst == UNKNOWN_CLUSTER);

            // Find the beginning of some lost cluster chain, and start threading the
            // clusters on that chain onto this file.

            for (j=0; j<cLostClusters; j++) {
                if (plc[j].dwIndex & LOSTCLUS_PARENT)
                    break;
            }

            ASSERT(j<cLostClusters);    // we should always find a parent

            plcCur = &plc[j];           
                                        // we don't want to find this parent again
            plcCur->dwIndex &= ~LOSTCLUS_PARENT;

            while (plcCur) {

                DWORD dwClus = plcCur->dwIndex & ~LOSTCLUS_FLAGS;

                if (pstm->s_clusFirst == UNKNOWN_CLUSTER) {

                    
                    pstm->s_clusFirst = dwClus;
                    pstm->s_flags |= STF_DIRTY | STF_DIRTY_CLUS;
                }

                if (plcCur->dwIndex & LOSTCLUS_MODIFIED) {
                    dwError = PACK(pvol, dwClus, plcCur->dwData, NULL);
                    if (dwError)
                        break;                          }

                dwNewSize += pvol->v_cbClus;

                plcCur = plcCur->plcNext;
                ASSERT(plcCur == NULL || plcCur->dwIndex & LOSTCLUS_CHILD);
            }

            // Commit and close the new entry

            if (dwNewSize > 0) {
                pstm->s_size = dwNewSize;
                pstm->s_flags |= STF_DIRTY;
            }

            CloseStream(pstm);
        }
        else
            dwError = GetLastError();
    }
    return dwError;
}


DWORD ModifyCluster(PDSTREAM pstmDir, PDIRENTRY pde, DWORD dwClus)
{
    DWORD dwError = ERROR_SUCCESS;

    if (dwClus < DATA_CLUSTER || dwClus == UNKNOWN_CLUSTER)
        dwClus = NO_CLUSTER;
    if (pde->de_clusFirst != LOWORD(dwClus))
        dwError = ModifyStreamBuffer(pstmDir, &pde->de_clusFirst, sizeof(pde->de_clusFirst));
    if (!dwError) {
        pde->de_clusFirst = LOWORD(dwClus);
        if (pde->de_clusFirstHigh != HIWORD(dwClus))
            dwError = ModifyStreamBuffer(pstmDir, &pde->de_clusFirstHigh, sizeof(pde->de_clusFirstHigh));
        if (!dwError)
            pde->de_clusFirstHigh = HIWORD(dwClus);
    }
    return dwError;
}


/*  ScanDirectory - Scan a directory (on a volume) for inconsistencies
 *
 *  ENTRY
 *      psd - pointer to SCANDATA
 *      pstmDir - pointer to DSTREAM
 *      pdiPrev - pointer to previous DIRINFO, if any
 *      pfdPrev - pointer to previous WIN32_FIND_DATAW, if any
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, error code if not
 */

DWORD ScanDirectory(PSCANDATA psd, PDSTREAM pstmDir, PDIRINFO pdiPrev, PWIN32_FIND_DATAW pfdPrev)
{
    int iFix;
    PWSTR pwsEnd;
    PSHANDLE psh;
    DWORD dwError;
    DIRINFO di;
    PVOLUME pvol = psd->sd_pvol;
    PWIN32_FIND_DATAW pfd = NULL;

    DEBUGMSGW(ZONE_LOGIO,(DBGTEXTW("FATFS!ScanDirectory(\"%s\")\n"), psd->sd_wsPath));

    pwsEnd = psd->sd_wsPath + wcslen(psd->sd_wsPath);

    if (!pstmDir) {

        if (pstmDir = OpenRoot(pvol)) {

#ifdef FAT32
            // Handle clusters in the root directory of a FAT32 volume

            DWORD dwClus = pvol->v_pstmRoot->s_clusFirst, dwData;

            while (dwClus >= DATA_CLUSTER && !ISEOF(pvol, dwClus)) {

                ASSERT(pvol->v_flags & VOLF_32BIT_FAT);
                ASSERT(!TestBitArray(psd->sd_pdwClusArray, dwClus-DATA_CLUSTER));

                dwError = UNPACK(pvol, dwClus, &dwData);
                if (dwError) {
                    DEBUGMSGW(ZONE_LOGIO || ZONE_ERRORS,(DBGTEXTW("FATFS!ScanDirectory: \"<ROOT>\" error reading cluster %d (%d)\n"), dwClus, dwError));
                    goto exit;
                }
                else if (dwData == FREE_CLUSTER) {
                    DEBUGMSGW(ZONE_LOGIO || ZONE_ERRORS,(DBGTEXTW("FATFS!ScanDirectory: \"<ROOT>\" cluster %d points to bogus cluster %d\n"), dwClus, dwData));
                    dwError = ERROR_INVALID_DATA;
                    goto exit;
                }
                SetBitArray(psd->sd_pdwClusArray, dwClus-DATA_CLUSTER);
                dwClus = dwData;
            }
#endif

⌨️ 快捷键说明

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