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

📄 stream.c

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

    while (len) {

        // If we can lock a range of blocks outside the buffer pool,
        // in order to read their contents directly from disk to memory
        // instead of through the pool, do so.

        DWORD blk, cblk;

        if (dwError = SeekStream(pstm, pos))
            break;

        DEBUGMSG(ZONE_LOGIO && (pstm->s_flags & STF_DEMANDPAGED),(DBGTEXT("FATFS!ReadStreamData(DP): begin lockblocks for '%.11hs'\n"), pstm->s_achOEM));
        if (LockBlocks(pstm, pos, len, &blk, &cblk, FALSE)) {

            __try {
                DEBUGMSG(ZONE_LOGIO && (pstm->s_flags & STF_DEMANDPAGED),(DBGTEXT("FATFS!ReadStreamData(DP): begin readvolume\n")));
                dwError = ReadVolume(pstm->s_pvol, blk, cblk, pvData);
                DEBUGMSG(ZONE_LOGIO && (pstm->s_flags & STF_DEMANDPAGED),(DBGTEXT("FATFS!ReadStreamData(DP): end readvolume\n")));
                if (!dwError) {
                    cb = cblk << BLOCK_LOG2;
                    (PBYTE)pvData += cb;
                    if (plenRead)
                        *plenRead += cb;
                }
            }
            __except (EXCEPTION_EXECUTE_HANDLER) {
                dwError = ERROR_INVALID_PARAMETER;
            }

            UnlockBlocks(blk, cblk, FALSE);
            if (dwError)
                break;
        }
        else {

            DEBUGMSG(ZONE_LOGIO && (pstm->s_flags & STF_DEMANDPAGED),(DBGTEXT("FATFS!ReadStreamData(DP): begin readstream\n")));
            dwError = ReadStream(pstm, pos, &pbStart, &pbEnd);
            DEBUGMSG(ZONE_LOGIO && (pstm->s_flags & STF_DEMANDPAGED),(DBGTEXT("FATFS!ReadStreamData(DP): begin readstream\n")));
            if (dwError)
                break;

            cb = pbEnd - pbStart;
            if (cb > len)
                cb = len;

            __try {
                memcpy(pvData, pbStart, cb);
                (PBYTE)pvData += cb;
                if (plenRead)
                    *plenRead += cb;
            }
            __except (EXCEPTION_EXECUTE_HANDLER) {
                dwError = ERROR_INVALID_PARAMETER;
            }

            ReleaseStreamBuffer(pstm, FALSE);
            if (dwError)
                break;
        }

#ifdef DEBUG
        if (ZONE_READVERIFY && ZONE_LOGIO) {
            DWORD i, j;
            for (i=0; i<cb; i++) {
                DEBUGMSG(TRUE,(DBGTEXT("%02x "), pbStart[i]));
                j = i+1;
                if (j == cb || j % 16 == 0) {
                    j = j % 16;
                    if (j == 0)
                        j = i - 15;
                    else
                        j = i - j + 1;
                    while (j <= i) {
                        DEBUGMSG(TRUE,(DBGTEXT("%c"), pbStart[j]<' ' || pbStart[j]>=0x7F? '.' : pbStart[j]));
                        j++;
                    }
                    DEBUGMSG(TRUE,(DBGTEXT("\n")));
                }
            }
        }
#endif
        len -= cb;
        pos += cb;
    }
    return dwError;
}


/*  WriteStreamData
 *
 *  Whereas ReadStream returns a pointer (to a buffer) and a length,
 *  and then the caller reads whatever data it wants up to that length
 *  (or modifies data up to that length and calls ModifyStreamBuffer), this
 *  function takes a pointer to data and its length, the position to write
 *  it, and simply writes it.
 *
 *  Thus, unlike ReadStream, where the caller can never get more than a
 *  buffer's worth of data back at a time and probably needs to put a loop
 *  around its ReadStream call, WriteStreamData can write any amount of data
 *  with one call (no external loop).
 *
 *  The same effect could be achieved with a ReadStream/ModifyStreamBuffer
 *  loop, but there are two important differences:  WriteStreamData can avoid
 *  the overhead of reading data that it's simply going to overwrite anyway,
 *  and it takes care of extending the stream if needed.
 *
 *  So, I've changed ReadStreamBuffer to accept an "advisory" lenMod parm,
 *  allowing us to advise it how many bytes we plan to modify.  This
 *  information percolates down to FindBuffer, allowing FindBuffer to avoid
 *  filling a buffer with disk data if the entire buffer contents are going
 *  to be modified anyway. -JTP
 *
 *  ENTRY
 *      pstm - pointer to DSTREAM
 *      pos - position within DSTREAM to write to
 *      pvData - pointer to data to write (or NULL to write zeros)
 *      len - length of data to write
 *      plenWritten - pointer to DWORD for length written (optional)
 *      fCommit - TRUE to commit buffers as they are written
 *
 *  EXIT
 *      0 if successful, error code if not (eg, disk full, or error reading
 *      the disk to fill the non-modified portion of a buffer)
 *
 *  NOTES
 *      If fCommit is FALSE, note that the last buffer modified will still
 *      be held (ie, the stream's current buffer).
 */

DWORD WriteStreamData(PDSTREAM pstm, DWORD pos, PCVOID pvData, DWORD len, PDWORD plenWritten, BOOL fCommit)
{
    DWORD dwError;
    PBYTE pbStart, pbEnd;

    ASSERT(OWNCRITICALSECTION(&pstm->s_cs));

    if (pstm->s_pvol->v_flags & VOLF_READONLY)
        return ERROR_WRITE_PROTECT;

    dwError = ERROR_SUCCESS;

    // A write of 0 bytes always succeeds, and is not supposed to do
    // anything other than cause the "last write" timestamp to eventually
    // get updated.

    if (len == 0) {
        pstm->s_flags |= STF_DIRTY_DATA;
        pstm->s_flags &= ~STF_WRITE_TIME;
        goto exit;
    }

    do {
        RewindStream(pstm, pos);

        do {
            // Locate the data run which contains the bytes requested.

            while (pos < pstm->s_run.r_end) {

                DWORD cb, blk, cblk;

                if (pvData && LockBlocks(pstm, pos, len, &blk, &cblk, TRUE)) {

                    __try {
                        dwError = WriteVolume(pstm->s_pvol, blk, cblk, (PVOID)pvData);
                        if (!dwError) {
                            cb = cblk << BLOCK_LOG2;
                            (PBYTE)pvData += cb;
                            if (plenWritten)
                                *plenWritten += cb;
                        }
                        else
                            DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!WriteStreamData: WriteVolume(block %d, %d blocks) failed (%d)\n"), blk, cblk, dwError));
                    }
                    __except (EXCEPTION_EXECUTE_HANDLER) {
                        dwError = ERROR_INVALID_PARAMETER;
                    }

                    UnlockBlocks(blk, cblk, TRUE);
                    if (dwError)
                        goto exit;
                }
                else {

                    dwError = ReadStreamBuffer(pstm,
                                               pos,
                                               pos+len < pstm->s_size? len : pstm->s_run.r_end - pos,
                                               &pbStart,
                                               &pbEnd);

                    if (dwError) {
                        DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!WriteStreamData: ReadStreamBuffer(block %d) failed (%d)\n"), pstm->s_run.r_blk + ((pos - pstm->s_run.r_start) >> BLOCK_LOG2), dwError));
                        goto exit;
                    }

                    cb = pbEnd - pbStart;
                    if (cb > len)
                        cb = len;

                    dwError = ModifyStreamBuffer(pstm, pbStart, cb);
                    if (dwError)
                        goto exit;

                    if (pvData) {
                        __try {
                            memcpy(pbStart, pvData, cb);
                            (PBYTE)pvData += cb;
                            if (plenWritten)
                                *plenWritten += cb;
                        }
                        __except (EXCEPTION_EXECUTE_HANDLER) {
                            dwError = ERROR_INVALID_PARAMETER;
                            goto exit;
                        }
                    }
                    else
                        memset(pbStart, 0, cb);
                }

                len -= cb;
                pos += cb;

                // Once we get this far at least once through the loop,
                // we need to make sure the stream data is flagged as dirty.

                pstm->s_flags |= STF_DIRTY;
                pstm->s_flags &= ~STF_WRITE_TIME;

                // Furthermore, if we just wrote beyond the "official"
                // size of the stream, then update the "official" size

                if (pos > pstm->s_size)
                    pstm->s_size = pos;

                // This is where all successful WriteStreamData calls
                // end up (except when len is ZERO to begin with, of course).

                if (len == 0)
                    goto exit;
            }

            
        } while (UnpackRun(pstm) == ERROR_SUCCESS);

        // We've run out of cluster runs, and we still have len bytes
        // to write at pos.  Resize the stream to encompass that boundary
        // and try to continue.

    } while ((dwError = ResizeStream(pstm, pos + len, RESIZESTREAM_SHRINK|RESIZESTREAM_UPDATEFAT)) == ERROR_SUCCESS);

    DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!WriteStreamData failed (%d)\n"), dwError));

  exit:
    if (fCommit) {

        DWORD dw;

        
        if (pstm->s_flags & STF_DIRTY_CLUS) {
            dw = CommitStream(pstm, FALSE);
            if (!dwError)
                dwError = dw;
        }

        dw = ReleaseStreamBuffer(pstm, FALSE);
        if (!dwError)
            dwError = dw;
    }

    return dwError;
}


/*  ResizeStream - truncate or extend a stream
 *
 *  ENTRY
 *      pstm - pointer to DSTREAM
 *      cbNew - new size of stream
 *      dwResizeFlags - zero or more RESIZESTREAM flags;  RESIZESTREAM_SHRINK
 *      forces shrinking (instead of simply insuring that the stream is at least
 *      as large as cbNew), and RESIZESTREAM_UPDATEFAT requests that changes to 
 *      the FAT be written.
 *
 *  EXIT
 *      ERROR_SUCCESS (0) if successful, non-zero if not
 *
 *      Truncating streams should only fail due to "hard" error conditions
 *      (eg, write-protected media), whereas extending a stream can also fail
 *      due to "soft" error conditions (eg, disk is full, or non-cluster-mapped
 *      stream -- like the root directory -- is full).
 */

DWORD ResizeStream(PDSTREAM pstm, DWORD cbNew, DWORD dwResizeFlags)
{
    PVOLUME pvol;
    DWORD dwError = ERROR_SUCCESS;
    DWORD posEnd, clus, clusEnd, clusPrev;
    DWORD clusRun, clusRunEnd, cclusRun, cbRun;

    ASSERT(OWNCRITICALSECTION(&pstm->s_cs));

    DEBUGMSG(ZONE_STREAMS,(DBGTEXT("FATFS!ResizeStream: changing size from 0x%x to 0x%x for '%.11hs'\n"), pstm->s_size, cbNew, pstm->s_achOEM));

    // Early exit if stream size already matches desired size.

    if (pstm->s_size == cbNew)
        return ERROR_SUCCESS;

    

⌨️ 快捷键说明

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