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

📄 disk.c

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

        dwError = Sg.sr_status;

     error:
        DEBUGMSGW(ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!ReadWriteDisk(%s, sector %d) failed (%d)\n"), cmd == DISK_IOCTL_READ? TEXTW("READ") : TEXTW("WRITE"), sector, dwError));

        // If the I/O was successful, or we got an unrecoverable error like
        // ERROR_NOT_READY (driver has disabled itself) or ERROR_BAD_UNIT (card
        // has been removed), or we've retried enough already, then get out.

        if (dwError == ERROR_SUCCESS ||
            dwError == ERROR_NOT_READY ||
            dwError == ERROR_BAD_UNIT ||
            cRetry-- == 0)
            break;

        DEBUGMSG(ZONE_DISKIO || ZONE_ERRORS,(DBGTEXT("FATFS!ReadWriteDisk: retrying...\n")));

    } while (TRUE);

    if (dwError) {

        // To be safe, any disk I/O error will set VOLF_UNCERTAIN.  This will
        // prevent us from making unsafe assumptions later (like whether the disk
        // is formatted or not).  VOLF_UNCERTAIN is cleared every time a volume
        // is created or remounted/recycled (in OpenVolume).

        if (pvol)
            pvol->v_flags |= VOLF_UNCERTAIN;
    }

#ifdef DEBUG
    else if (cmd == DISK_IOCTL_READ && ZONE_READVERIFY && pvol) {

        PBYTE pbTmp;

        ALLOCA(pbTmp, pdi->di_bytes_per_sect+2);
        if (pbTmp) {
            while (cSectors--) {
                DEBUGMSG(ZONE_DISKIO,(DBGTEXT("FATFS!ReadWriteDisk: verifying read from sector %d\n"), Sg.sr_start));

                memset(pbTmp, 'J', pdi->di_bytes_per_sect+2);

                Sg.sr_num_sec = 1;
                Sg.sr_sglist[0].sb_len = pdi->di_bytes_per_sect;
                Sg.sr_sglist[0].sb_buf = pbTmp+1;

                if (FSDMGR_DiskIoControl((HDSK)hdsk,
                                    (pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS) ? IOCTL_DISK_READ : DISK_IOCTL_READ,
                                    &Sg, sizeof(Sg),
                                    NULL, 0, &k, NULL) == FALSE) {
                    dwError = GetLastError();
                    DEBUGMSG(ZONE_DISKIO || ZONE_ERRORS,(DBGTEXT("FATFS!ReadWriteDisk(READ, sector %d) failed (%d)\n"), Sg.sr_start, dwError));
                }
                else {
                    if (memcmp(pvBuffer, pbTmp+1, pdi->di_bytes_per_sect) != 0) {
                        dwError = ERROR_GEN_FAILURE;
                        DEBUGMSGW(ZONE_DISKIO || ZONE_ERRORS,(DBGTEXTW("FATFS!ReadWriteDisk(VERIFY, sector %d) failed\n"), Sg.sr_start));
                    }
                    if (pbTmp[0] != 'J' || pbTmp[pdi->di_bytes_per_sect+1] != 'J') {
                        dwError = ERROR_GEN_FAILURE;
                        DEBUGMSGW(ZONE_DISKIO || ZONE_ERRORS,(DBGTEXTW("FATFS!ReadWriteDisk(BOUNDSCHECK, sector %d) failed\n"), Sg.sr_start));
                    }
                }
                Sg.sr_start++;
                (PBYTE)pvBuffer += pdi->di_bytes_per_sect;
            }
        }
    }
#endif

    else if (cmd == DISK_IOCTL_WRITE) {

#ifdef DEBUG
        creqWrite++;            // keep track of total write requests and sectors written
        csecWrite += cSectors;
#endif

        // If the operation was successful, and it was a WRITE, then set the
        // modified flag in the associated VOLUME structure (if there is one).  We
        // use this flag to avoid a full unmount/remount cycle after a scan or format
        // if no changes were actually made.

        if (pvol) {
            pvol->v_flags |= VOLF_MODIFIED;
            
            // Also on writes, if we still have outstanding reads-after-writes to do, do them now;
            // note that we only support this feature on non-simulated volumes.

            if ((pvol->v_bVerifyCount || ZONE_WRITEVERIFY) && !(pdi->di_flags & DISK_INFO_FLAGS_FATFS_SIMULATED)) {

                PBYTE pbTmp;

                ALLOCA(pbTmp, pdi->di_bytes_per_sect);
                if (pbTmp) {
                    cRetry = 1;                             while (cSectors--) {
reverify:
                        DEBUGMSG(pvol->v_bVerifyCount || ZONE_DISKIO,(DBGTEXT("FATFS!ReadWriteDisk: verifying write to sector %d\n"), Sg.sr_start));

                        memset(pbTmp, 'J', pdi->di_bytes_per_sect);

                        Sg.sr_num_sec = 1;
                        Sg.sr_sglist[0].sb_len = pdi->di_bytes_per_sect;
                        Sg.sr_sglist[0].sb_buf = pbTmp;

                        if (FSDMGR_DiskIoControl((HDSK)hdsk,
                                            (pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS) ? IOCTL_DISK_READ : DISK_IOCTL_READ,
                                            &Sg, sizeof(Sg),
                                            NULL, 0, &k, NULL) == FALSE) {
                            dwError = GetLastError();
                            DEBUGMSG(pvol->v_bVerifyCount || ZONE_DISKIO || ZONE_ERRORS,(DBGTEXT("FATFS!ReadWriteDisk(READ, sector %d) failed (%d)\n"), Sg.sr_start, dwError));
                        }
                        else {
                            if (memcmp(pvBuffer, pbTmp, pdi->di_bytes_per_sect) != 0) {
                                dwError = ERROR_GEN_FAILURE;
                                DEBUGMSGW(pvol->v_bVerifyCount || ZONE_DISKIO || ZONE_ERRORS,(DBGTEXTW("FATFS!ReadWriteDisk(VERIFY, sector %d) failed\n"), Sg.sr_start));
                            }
                        }

                        if (dwError) {

                            FATUIDATA fui;
                            DWORD dwVolFlags;

                            // Setting some bit (like VOLF_LOCKED) that will prevent most
                            // any other call from entering FATFS while the following dialog is
                            // active is very important, because this thread is temporarily
                            // leaving our control, so it could re-enter FATFS and screw up the
                            // state of any streams we've currently got locked (since critical
                            // sections only protect our state from *other* threads, not from
                            // ourselves).

                            
                            dwVolFlags = pvol->v_flags;
                            pvol->v_flags |= VOLF_LOCKED;

                            fui.dwSize = sizeof(fui);
                            fui.dwFlags = FATUI_YES | FATUI_NO;
                            fui.idsEvent = IDS_FATUI_WRITEVERIFY_WARNING;
                            fui.idsEventCaption = IDS_FATUI_WARNING;
                            fui.cuiParams = 2;
                            fui.auiParams[0].dwType = UIPARAM_VALUE;
                            fui.auiParams[0].dwValue = Sg.sr_start;
                            fui.auiParams[1].dwType = UIPARAM_VALUE;
                            fui.auiParams[1].dwValue = dwError;

#ifdef FATUI
                            k = FATUIEvent(hFATFS, pvol->v_pwsHostRoot? pvol->v_pwsHostRoot+1 : NULL, &fui);
#else
                            k = FATUI_YES;
#endif                            

                            pvol->v_flags = (pvol->v_flags & ~VOLF_LOCKED) | (dwVolFlags & VOLF_LOCKED);

                            if (k == FATUI_YES) {
                                dwError = ERROR_SUCCESS;
                                if (cRetry-- == 0)
                                    goto exit;  // leave the verify count alone in this case
                                goto reverify;
                            }
                            break;              // just report 1 error per multi-sector write
                        }

                        Sg.sr_start++;
                        (PBYTE)pvBuffer += pdi->di_bytes_per_sect;
                    }
                }

                // As long as there were no verify errors, go ahead and reduce the verify count

                if (!dwError && pvol->v_bVerifyCount > 0 && pvol->v_bVerifyCount < 255)
                    pvol->v_bVerifyCount--;
            }
        }
    }

exit:
    DEBUGMSG(ZONE_DISKIO,(DBGTEXT("FATFS!ReadWriteDisk returned 0x%x\n"), dwError));
    return dwError;
}


/*  NamePartitionInfo - Assign a name to a PARTINFO structure
 *
 *  ENTRY
 *      ppi -> PARTINFO structure
 *      pwsName -> name to be assigned
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or a non-zero error code
 */

DWORD NamePartitionInfo(PPARTINFO ppi, PWSTR pwsName)
{
    if (ppi->pi_pwsName) {
        DEBUGFREE((wcslen(ppi->pi_pwsName) + 1) * sizeof(WCHAR));
        LocalFree(ppi->pi_pwsName);
        ppi->pi_pwsName = NULL;
    }
    if (pwsName && *pwsName) {
        int cbName = (wcslen(pwsName) + 1) * sizeof(WCHAR);
        if (cbName > MAXVOLUMENAME * sizeof(WCHAR))
            return ERROR_INVALID_PARAMETER;
        ppi->pi_pwsName = (PWSTR)LocalAlloc(LPTR, cbName);
        if (!ppi->pi_pwsName)
            return ERROR_NOT_ENOUGH_MEMORY;
        DEBUGALLOC(cbName);
        memcpy(ppi->pi_pwsName, pwsName, cbName);
    }
    return ERROR_SUCCESS;
}


/*  InsertPartitionInfo - Insert a PARTINFO structure into the specified list, in sector order
 *
 *  ENTRY
 *      pdlPartInfo -> doubly-linked PARTINFO list
 *      ppiNew -> PARTINFO structure
 *
 *  EXIT
 *      None
 */

void InsertPartitionInfo(PPI_DLINK pdlPartInfo, PPARTINFO ppiNew)
{
    PPI_DLINK pdlPrev = pdlPartInfo;
    PPARTINFO ppi = pdlPartInfo->ppiNext;

    while (ppi != (PPARTINFO)pdlPartInfo) {
        if (ppiNew->pi_secAbsolute < ppi->pi_secAbsolute) {
            ASSERT(ppiNew->pi_secAbsolute + ppiNew->pi_PartEntry.Part_TotalSectors <= ppi->pi_secAbsolute);
            break;
        }
        ASSERT(ppi->pi_secAbsolute + ppi->pi_PartEntry.Part_TotalSectors <= ppiNew->pi_secAbsolute);
        pdlPrev = &ppi->pi_dlPartitions;
        ppi = ppi->pi_dlPartitions.ppiNext;
    }
    AddItem((PDLINK)pdlPrev, (PDLINK)&ppiNew->pi_dlPartitions);
}


/*  FindPartitionInfo - Allocate a PARTINFO structure and link it to a DSK structure
 *
 *  ENTRY
 *      pdlPartInfo -> doubly-linked PARTINFO list
 *      secPartition == first sector of partition
 *      ppiParent -> parent PARTINFO structure, NULL if no parent
 *
 *  EXIT
 *      Pointer to a PARTINFO structure, NULL if not found
 */

PPI FindPartitionInfo(PPI_DLINK pdlPartInfo, DWORD secPartition, PPARTINFO ppiParent)
{
    PPARTINFO ppi, ppiChild;

    ppi = pdlPartInfo->ppiNext;
    while (ppi != (PPARTINFO)pdlPartInfo) {
        if ((PDLINK)&ppi->pi_dlChildren != (PDLINK)ppi->pi_dlChildren.ppiNext) {
            if (ppiChild = FindPartitionInfo(&ppi->pi_dlChildren, secPartition, ppiParent))
                return ppiChild;
        }
        if (ppi->pi_secAbsolute == secPartition && ppi->pi_ppiParent == ppiParent)
            return ppi;
        ppi = ppi->pi_dlPartitions.ppiNext;
    }
    return NULL;
}


/*  AllocPartitionInfo - Allocate a PARTINFO structure and link it to a DSK structure
 *
 *  ENTRY
 *      pdsk -> DSK structure
 *      secPartTable == sector of partition table
 *      idxPartTable == index of partition table entry in partition table
 *      ppe -> partition table entry
 *      secPartition == first sector of partition
 *      ppiParent -> parent PARTINFO structure, NULL if no parent
 *      pbSector -> contents of first sector of partition, NULL if not provided
 *
 *  EXIT
 *      Pointer to a PARTINFO structure
 */

PPI AllocPartitionInfo(PDSK pdsk, DWORD secPartTable, int idxPartTable, PPARTENTRY ppe, DWORD secPartition, PPARTINFO ppiParent, PBYTE pbSector)
{
    PPARTINFO ppi;
    PWSTR pwsName = NULL;
    
    // See if info on this partition already exists...

    if (ppi = FindPartitionInfo(&pdsk->d_dlPartitions, secPartition, ppiParent)) {
        ASSERT(ppi->pi_secPartTable == secPartTable && 
               ppi->pi_idxPartTable == (WORD)idxPartTable && 
               ppi->pi_PartEntry.Part_TotalSectors == ppe->Part_TotalSectors);
        return ppi;
    }

    // If this partition has a name associated with it, that name will be located
    // at OFFSETVOLUMENAME in pbSector, will begin with a non-NULL character, will be padded
    // with NULLs, and will be preceded by BOOTSECVOLUMESIG at offset OFFSETVOLUMESIG.

    if (pbSector &&
        *(PDWORD)(pbSector+OFFSETVOLUMESIG) == BOOTSECVOLUMESIG &&
        *(PDWORD)(pbSector+OFFSETVOLUMENAME) != 0 && *(PDWORD)(pbSector+OFFSETTRLSIG-4) == 0) {
        pwsName = (PWCHAR)(pbSector+OFFSETVOLUMENAME);
    }

    ppi = (PPARTINFO)LocalAlloc(LPTR, sizeof(PARTINFO));
    if (!ppi)
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!AllocPartitionInfo: out of memory!\n")));
    else {
        DEBUGALLOC(sizeof(PARTINFO));
        InitList((PDLINK)&ppi->pi_dlChildren);
        ppi->pi_dwSig = BOOTSECVOLUMESIG;
        ppi->pi_pdsk = pdsk;
        ppi->pi_secPartTable = secPartTable;
        ppi->pi_idxPartTable = (WORD)idxPartTable;
        ppi->pi_PartEntry = *ppe;
        ppi->pi_secAbsolute = secPartition;
        NamePartitionInfo(ppi, pwsName);
        if (!ppiParent) {
            InsertPartitionInfo(&pdsk->d_dlPartitions, ppi);
        }
        else {
            InsertPartitionInfo(&ppiParent->pi_dlChildren, ppi);
            ppi->pi_ppiParent = ppiParent;
        }
    }

    DEBUGMSG(ZONE_DISKIO,(DBGTEXT("FATFS!AllocPartitionInfo(0x%08x): parent=0x%08x, sectbl=%x, secpart=%x, sectotal=%x\n"), ppi, ppiParent, secPartTable, secPartition, ppe->Part_TotalSectors));
    return ppi;
}




/*  WalkPartitionInfo
 *
 *  ENTRY
 *      pdlPartInfo -> doubly-linked PARTINFO list
 *      secStart == beginning of partitioned range
 *      csecTotal == size of partitioned range, in sectors
 *      pps -> PARTSRCH structure
 *
 *  EXIT
 *      TRUE if desired search criteria satisfied, FALSE if not;  in the latter
 *      case, pps->ps_csecFound must be examined to determine whether or not even
 *      the minimum criteria could be satisfied.
 */

BOOL WalkPartitionInfo(PPI_DLINK pdlPartInfo, DWORD secStart, DWORD csecTotal, PPARTSRCH pps)
{
    DWORD secEnd, csecGap;
    PPARTINFO ppi = pdlPartInfo->ppiNext;

    // Handle the empty PARTINFO list case here...

    if (ppi == (PPARTINFO)pdlPartInfo) {
        if (csecTotal >= pps->ps_csecDesired ||
            csecTotal >= pps->ps_csecMinimum && csecTotal > pps->ps_csecFound) {
            pps->ps_pdlFound = pdlPartInfo;
            pps->ps_ppiFound = NULL;
            pps->ps_csecFound = csecTotal;
        }
        pps->ps_csecTotalFound += csecTotal;
        return (csecTotal >= pps->ps_csecDesired);
    }

    // Handle the non-empty PARTINFO list case here...

    secEnd = secStart + csecTotal;

    while (ppi != (PPARTINFO)pdlPartInfo) {
        if ((PDLINK)&ppi->pi_dlChildren != (PDLINK)ppi->pi_dlChildren.ppiNext) {
            if (WalkPartitionInfo(&ppi->pi_dlChildren, ppi->pi_secAbsolute, ppi->pi_PartEntry.Part_TotalSectors, pps))
                return TRUE;

⌨️ 快捷键说明

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