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

📄 scan.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码.移植性非常高. 里面带有source i.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
    return dwError;
}


/*  ScanFixInteractive - Query user regarding scan error and ask to fix
 *
 *  ENTRY
 *      psd -> SCANDATA
 *      pdi -> DIRINFO
 *      pfd -> WIN32_FIND_DATAW
 *      dwScanErr == one or more SCANERR_* flags
 *
 *  EXIT
 *      FATUI_NONE, FATUI_YES, FATUI_NO, FATUI_CANCEL or FATUI_DELETE
 */

int ScanFixInteractive(PSCANDATA psd, PDIRINFO pdi, PWIN32_FIND_DATAW pfd, DWORD dwScanErr)
{
    CEOIDINFO oi;
    FATUIDATA fui;
    int i;

    // If the caller to ScanVolume passed a pointer to a dwScanErr
    // variable, collect all the different error types that were encountered;
    // but don't include SCANERR_REPAIRABLE, because that bit is just a signal
    // to us as to whether ScanVolume can actually repair the given error.

    if (psd->sd_pRefData)
        *(PDWORD)psd->sd_pRefData |= (dwScanErr & ~SCANERR_REPAIRABLE);

    if (psd->sd_dwScanVol & SCANVOL_UNATTENDED)
        return (psd->sd_dwScanVol & SCANVOL_REPAIRALL)? FATUI_YES : FATUI_NO;

#if(IDS_FATUI_SCANERR_UNKNOWN   != IDS_FATUI_SCANERR_DIR_BADDATA - 1 || \
    SCANERR_DIR_BADCLUS   != (1 << (IDS_FATUI_SCANERR_DIR_BADCLUS   - IDS_FATUI_SCANERR_DIR_BADDATA)) || \
    SCANERR_DIR_BADSIZE   != (1 << (IDS_FATUI_SCANERR_DIR_BADSIZE   - IDS_FATUI_SCANERR_DIR_BADDATA)) || \
    SCANERR_FAT_BADINDEX  != (1 << (IDS_FATUI_SCANERR_FAT_BADINDEX  - IDS_FATUI_SCANERR_DIR_BADDATA)) || \
    SCANERR_FAT_CROSSLINK != (1 << (IDS_FATUI_SCANERR_FAT_CROSSLINK - IDS_FATUI_SCANERR_DIR_BADDATA)) || \
    SCANERR_FAT_WASTED    != (1 << (IDS_FATUI_SCANERR_FAT_WASTED    - IDS_FATUI_SCANERR_DIR_BADDATA)) )
#error SCANERR_* constants are out of sync with IDS_FATUI_* constants
#endif

    fui.dwSize = sizeof(fui);
    fui.dwFlags = (dwScanErr & SCANERR_REPAIRABLE)? (FATUI_YES | FATUI_NO | FATUI_CANCEL) : (FATUI_CANCEL);
    fui.idsEvent = IDS_FATUI_SCANERR_DIR_BADDATA + Log2(dwScanErr & ~SCANERR_REPAIRABLE);
    fui.idsEventCaption = IDS_FATUI_ERROR;

    fui.auiParams[0].dwType = UIPARAM_STRINGID;
    fui.auiParams[0].dwValue = (dwScanErr & SCANERR_REPAIRABLE)? IDS_FATUI_SCANERR_REPAIR : IDS_FATUI_SCANERR_ADVISE;

    // In the case of SCANERR_FAT_WASTED, pdi and pfd are not DIRINFO and WIN32_FIND_DATAW pointers;
    // pdi is used to pass the number of lost clusters, and pfd is the number of lost chains.

    if (fui.idsEvent == IDS_FATUI_SCANERR_FAT_WASTED) {
        fui.cuiParams = 4;
        fui.auiParams[1].dwType = UIPARAM_VALUE;
        fui.auiParams[1].dwValue = (DWORD)pdi;
        fui.auiParams[2].dwType = UIPARAM_VALUE;
        fui.auiParams[2].dwValue = (DWORD)pfd;
        fui.auiParams[3].dwType = UIPARAM_VALUE;
        fui.auiParams[3].dwValue = (DWORD)(psd->sd_pvol->v_pwsHostRoot+1);
    }
    else {
        fui.cuiParams = 2;
        fui.auiParams[1].dwType = UIPARAM_VALUE;
        fui.auiParams[1].dwValue = (DWORD)pfd->cFileName;
        if (pdi && GetSIDInfo(psd->sd_pvol, &pdi->di_sid, &oi) == ERROR_SUCCESS) {
            int i;
            fui.cuiParams = 3;
            fui.auiParams[2].dwType = UIPARAM_VALUE;
            fui.auiParams[2].dwValue = (DWORD)oi.infFile.szFileName;
            for (i=wcslen(oi.infFile.szFileName); --i > 0;) {
                if (oi.infFile.szFileName[i] == TEXTW('\\')) {
                    oi.infFile.szFileName[i] = 0;       // chop off the final component in the path
                    break;
                }
            }
        }
    }

#ifdef FATUI
    i = FATUIEvent(hFATFS, psd->sd_pvol->v_pwsHostRoot+1, &fui);
#else
    i = FATUI_YES;
#endif
    return i;
}


BOOL ScanFixDefault(PSCANDATA psd, PDIRINFO pdi, PWIN32_FIND_DATAW pfd, DWORD dwScanErr)
{
    int i;
    PVOID p;

    if (p = psd->sd_pRefData)
        ((PSCANRESULTS)psd->sd_pRefData)->sr_dwScanErr |= (dwScanErr & ~SCANERR_REPAIRABLE);

    if (!(psd->sd_dwScanVol & SCANVOL_UNATTENDED)) {
        psd->sd_pRefData = NULL;
        i = ScanFixInteractive(psd, pdi, pfd, dwScanErr);
        psd->sd_pRefData = p;
        return i;
    }

    return (psd->sd_dwScanVol & SCANVOL_REPAIRALL)? FATUI_YES : FATUI_NO;
}


void ScanNotify(PVOLUME pvol, UINT idsMessage)
{
    FATUIDATA fui;

    fui.dwSize = sizeof(fui);
    fui.dwFlags = FATUI_NONE;
    fui.idsEvent = idsMessage;
    fui.idsEventCaption = IDS_FATUI_WARNING;
    fui.cuiParams = 0;
    // Since this is just a notification, we don't care what the FATUIEvent response was...
#ifdef FATUI
    FATUIEvent(hFATFS, pvol->v_pwsHostRoot+1, &fui);
#endif    
}


/*  ScanVolume - Scan a volume for inconsistencies
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      dwScanVol - one or more SCANVOL_* flags
 *      pfnScanFix - pointer to PFNSCANFIX function
 *      pRefData - pointer to caller-defined data;  if pfnScanFix
 *      is NULL, then the default handler (ScanFixDefault) expects
 *      pRefData to be either NULL or a pointer to a SCANRESULTS structure.
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, error code if not, or 0xFFFFFFFF
 *      if scan was interrupted/cancelled.
 *
 *  NOTES
 *      There are a very large number of problems that a FAT volume
 *      can suffer from, but many of them are minor (stuff like non-OEM
 *      characters in 8.3 names, dates in the future, paths that can't
 *      be reached by MSDOS-based applications, etc).
 *
 *      What I deem most important:  (1) that all files point to valid
 *      and unique sets of clusters, (2) that all file sizes agree with
 *      the number of clusters allocated to them, (3) that all other
 *      clusters are marked free, and (4) that all copies of the FAT are
 *      in agreement.
 *
 *      To verify (1) and (3), I allocate a bitarray representing all
 *      the clusters on the volume, and then start walking the directory
 *      structure, and every cluster chain in that structure, and flag
 *      every cluster in use.  If a cluster is already marked in use,
 *      then we have a cross-link.  Now a limitation of the bitmap is
 *      that I won't be able to (easily) identify the first file using
 *      the same clusters, but I can at least list the second file and offer
 *      to allocate it separate clusters with duplicate contents.
 */

DWORD ScanVolume(PVOLUME pvol, DWORD dwScanVol, PFNSCANFIX pfnScanFix, PVOID pRefData)
{
    BOOL iFix;
    SCANDATA sd;
    DWORD i, dwClus;
    DWORD cClusters;
    DWORD dwError = ERROR_SUCCESS;

    // An invalid volume is generally an unformatted volume;  in any case, if the
    // volume is known to be invalid, there's no point in scanning it.  Similarly, if
    // we're already scanning it, no need to do so again.

    if (pvol->v_flags & (VOLF_INVALID | VOLF_SCANNING))
        goto abort;             
    DEBUGMSGW(ZONE_LOGIO,(DBGTEXTW("FATFS!ScanVolume(%s) starting...\n"), pvol->v_pwsHostRoot));

    dwError = LockVolume(pvol, VOLF_READLOCKED);
    if (dwError) {
        DEBUGMSG(ZONE_LOGIO || ZONE_ERRORS,(DBGTEXT("FATFS!ScanVolume: unable to lock volume (%d)\n"), dwError));
        goto exit;
    }

    // Set the SCANNING flag to prevent re-entrancy, and clear the MODIFIED flag
    // so that if no modifications are made during the scan, UnlockVolume can avoid
    // an expensive unmount/remount of the volume.

    pvol->v_flags |= VOLF_SCANNING;
    pvol->v_flags &= ~VOLF_MODIFIED;

    ScanNotify(pvol, IDS_FATUI_SCANSTART_WARNING);

    // Initialize the SCANDATA structure and allocate a bitarray for all the clusters on the volume

    sd.sd_pvol = pvol;
    sd.sd_dwScanVol = dwScanVol;
    sd.sd_pfnScanFix = (pfnScanFix? pfnScanFix : ScanFixDefault);
    sd.sd_pRefData = pRefData;

    ASSERT(pvol->v_clusMax > DATA_CLUSTER);
    cClusters = pvol->v_clusMax - DATA_CLUSTER + 1;

    CreateBitArray(sd.sd_pdwClusArray, cClusters);
    if (!sd.sd_pdwClusArray) {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        goto unlockvol;
    }

    LockFAT(pvol);

    sd.sd_cFiles = 0;
    sd.sd_cLevels = 0;
    sd.sd_flags = SCANDATA_NONE;
    sd.sd_wsPath[0] = '\0';
    dwError = ScanDirectory(&sd, NULL, NULL, NULL);

    DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!ScanVolume scanned %d files (%d)\n"), sd.sd_cFiles, dwError));

    if (sd.sd_flags & SCANDATA_TOODEEP) {

        // This should simply generate the IDS_SCANERR_UNKNOWN message.  We
        // don't care what the response is, because it's a generic, unrepairable error.

        sd.sd_pfnScanFix(&sd, NULL, NULL, 0);
    }
    else if (dwError != SCAN_CANCELLED) {
        
        // Now make sure that all the clusters in the FAT for which the
        // corresponding bit in the bitarray is clear are actually "free",
        // and since we're verifying the set of free clusters, we might as well
        // take this opportunity to update the cached free cluster count in the
        // VOLUME structure too...

        
        
        int cLostClusters = 0;

        dwError = ERROR_SUCCESS;
        pvol->v_cclusFree = 0;

        for (i=0, dwClus=DATA_CLUSTER; dwClus <= pvol->v_clusMax; i++,dwClus++) {
            DWORD dwData;
            dwError = UNPACK(pvol, dwClus, &dwData);
            if (dwError) {
                DEBUGMSG(ZONE_LOGIO || ZONE_ERRORS,(DBGTEXT("FATFS!ScanVolume: error reading cluster %d (%d)\n"), dwClus, dwError));
                pvol->v_cclusFree = UNKNOWN_CLUSTER;    // if we bail, zap cached free cluster count too
                break;
            }
            if (!TestBitArray(sd.sd_pdwClusArray, i)) {
                if (dwData == FREE_CLUSTER)
                    pvol->v_cclusFree++;                // update cached free cluster count
                else if (dwData == (pvol->v_clusEOF|0x8)-1) {
                    SetBitArray(sd.sd_pdwClusArray, i);
                    DEBUGMSG(ZONE_LOGIO,(DBGTEXT("FATFS!ScanVolume: cluster %d marked bad (0x%x)\n"), dwClus, dwData));
                }
                else {
                    cLostClusters++;
                    // Used to be ZONE_LOGIO || ZONE_ERRORS, but too noisy when card has lots of lost clusters...
                    DEBUGMSG(ZONE_LOGIO,(DBGTEXT("FATFS!ScanVolume: cluster %d should be free but instead contains %d (0x%x)\n"), dwClus, dwData, dwData));
                }
            }
            else {
                // dwData == FREE_CLUSTER suggests a bit-array inconsistency, hence the break -JTP
                DEBUGMSGBREAK(ZONE_LOGIO && dwData == FREE_CLUSTER,(DBGTEXT("FATFS!ScanVolume: cluster %d should be used but instead is free\n"), dwClus));
            }
        }

        
        if (cLostClusters*sizeof(LOSTCLUS) > 32*1024) {

            // This should simply generate the IDS_SCANERR_UNKNOWN message.  We
            // don't care what the response is, because it's a generic, unrepairable error.

            sd.sd_pfnScanFix(&sd, NULL, NULL, 0);
            dwError = ERROR_OUTOFMEMORY;
            cLostClusters = 0;
        }

        if (cLostClusters) {

            PLOSTCLUS plc;

            ALLOCA(plc, cLostClusters*sizeof(LOSTCLUS));
            if (!plc) {
                DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!ScanVolume: unable to allocate %d bytes to recover lost clusters\n"), cLostClusters*sizeof(LOSTCLUS)));
                dwError = ERROR_OUTOFMEMORY;
            }
            else {
                // Identify all the chains now

                int cLostChains;
                cLostChains = ScanLostClusters(pvol, sd.sd_pdwClusArray, plc, cLostClusters);

                // Offer to repair (ie, recover) all the chains

                iFix = sd.sd_pfnScanFix(&sd, (PVOID)cLostClusters, (PVOID)cLostChains, SCANERR_FAT_WASTED|SCANERR_REPAIRABLE);
                if (iFix == FATUI_CANCEL) {
                    dwError = SCAN_CANCELLED;
                }
                else if (iFix == FATUI_YES) {
                    dwError = ReclaimLostClusters(pvol, plc, cLostClusters, cLostChains);
                }
                else if (iFix == FATUI_DELETE) {
                    dwError = FreeLostClusters(pvol, plc, cLostClusters);
                }
            }
        }

        
            }

    // Commit the FAT now, just in case we dirtied any of its buffers...

    CommitAndReleaseStreamBuffers(pvol->v_pstmFAT);
    UnlockFAT(pvol);

    DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!ScanVolume scanned %d clusters (%d free)\n"), i, pvol->v_cclusFree));

unlockvol:
    ScanNotify(pvol, IDS_FATUI_SCANDONE_WARNING);

    UnlockVolume(pvol);

exit:
    pvol->v_flags &= ~VOLF_SCANNING;

    DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!ScanVolume(%s) complete, returned %d\n"), pvol->v_pwsHostRoot, dwError));

abort:
    return dwError;
}

⌨️ 快捷键说明

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