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

📄 find.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif        
            LockFAT(pvol);

        dwError = NewCluster(pvol, UNKNOWN_CLUSTER, &pdi->di_clusEntry);
        if (dwError == ERROR_SUCCESS && pdi->di_clusEntry == UNKNOWN_CLUSTER)
            dwError = ERROR_DISK_FULL;
        if (dwError) {
            UnlockFAT(pvol);
            return dwError;
        }

        DEBUGMSG(ZONE_APIS,(DBGTEXT("FATFS!CreateName: new cluster for %s returned %d'\r\n"), pwsName, pdi->di_clusEntry));

        // We must mark this cluster USED right now, because if we have
        // to grow the directory containing this new directory, we don't
        // want it scarfing up the same cluster.  Besides, this will likely
        // save us a redundant write to the FAT in that case.

        dwError = PACK(pvol, pdi->di_clusEntry, EOF_CLUSTER, NULL);

        if (dwError)
            goto exit;
    }

    
    pos = pdi->di_pos;
    if (pdi->di_cdeFree)
        pos = pdi->di_posFree;

    // Remember the original size of the directory stream so we can tell
    // later if ResizeStream grew it.

    cbOldSize = pstmDir->s_size;
    posEnd = pos + cdeNeed * sizeof(DIRENTRY);

    if (posEnd > pdi->di_pos) {

        // Directory may need to grow.  First, make sure we're not
        // trying to push the directory beyond MAX_DIRENTRIES.

        if (posEnd/sizeof(DIRENTRY) > MAX_DIRENTRIES) {
            dwError = ERROR_DISK_FULL;              goto exit;
        }

        // Now make sure directory is large enough.  Make a special
        // call to ResizeStream to grow if necessary but never shrink.  We
        // treat this as a general error rather than a write error, because
        // ResizeStream can fail simply because the disk is full.

        dwError = ResizeStream(pstmDir, posEnd, RESIZESTREAM_NONE);
        if (dwError)
            goto exit;
    }

    clde = 0;
    plde = pldeEnd = NULL;

    cwTail = pdi->di_cwTail;
    pwsTail = pdi->di_pwsTail;

    // Advance cwTail by 1 character to encompass the NULL that OpenName and
    // FindFirst stored.  We don't need to store a NULL if the name fits into
    // the LFN entries perfectly however.

    if (cwTail < LDE_NAME_LEN)
        cwTail++;

    while (cdeNeed > 1) {

        if( plde >= pldeEnd ) {
            if( dwError = ReadStream( pstmDir, pos, &plde, &pldeEnd ))
                goto exit;

#ifdef TFAT
            // clone the buffer; If this existed before...
            if(pvol->v_fTfat)
            {
                dwError = CloneDirCluster( pvol, pstmDir, pstmDir->s_pbufCur->b_blk, NULL );
                if( ERROR_DISK_FULL == dwError ) {                    
                    goto exit;
                }
                else if (CLONE_CLUSTER_COMPLETE == dwError) {                    
                    // The current buffer might be changed in CloneDirCluster
                    // update plde to with the new buffer
                    if( dwError = ReadStream( pstmDir, pos, &plde, &pldeEnd )) {
                        DEBUGMSG (TRUE, (TEXT("FATFSD!TFAT: ERROR!!!! ReadStream failed after CloneDirCluster\n")));
                        ASSERT (0);   // It is bad if happens
                        goto exit;
                    }
                }

                // CloneDirCluster succeeded...let's assert it's right
                ASSERT( pos >= pstmDir->s_runList.r_StartPosition &&
                        pos < pstmDir->s_runList.r_EndPosition);
            }
#endif            
        }

        dwError = ModifyStreamBuffer(pstmDir, plde, sizeof(LFNDIRENTRY));
        if (dwError)
            goto exit;

        memset(plde, 0xFF, sizeof(LFNDIRENTRY));

        plde->lde_ord = (BYTE)(cdeNeed-1);
        if (clde++ == 0) {

            // The first LFN entry must be specially marked.  This is
            // also a good time to compute the checksum of the short name.

            chksum = ChkSumName(pdi->di_achOEM);
            plde->lde_ord |= LN_ORD_LAST_MASK;
        }

        plde->lde_attr = ATTR_LONG;
        plde->lde_flags = 0;
        plde->lde_chksum = chksum;
        plde->lde_clusFirst = 0;

        cw = cwTail >= LDE_LEN1? LDE_LEN1 : cwTail;
        memcpy(plde->lde_name1, pwsTail, cw*sizeof(WCHAR));

        cw = cwTail >= LDE_LEN1+LDE_LEN2? LDE_LEN2 : cwTail-LDE_LEN1;
        if (cw > 0)
            memcpy(plde->lde_name2, pwsTail+LDE_LEN1, cw*sizeof(WCHAR));

        cw = cwTail >= LDE_LEN1+LDE_LEN2+LDE_LEN3? LDE_LEN3 : cwTail-LDE_LEN1-LDE_LEN2;
        if (cw > 0)
            memcpy(plde->lde_name3, pwsTail+LDE_LEN1+LDE_LEN2, cw*sizeof(WCHAR));

        pwsTail -= LDE_NAME_LEN;
        cwTail = LDE_NAME_LEN;

        plde++;
        pos += sizeof(LFNDIRENTRY);
        cdeNeed--;
    }

    // Now write the primary DIRENTRY

    pde = (PDIRENTRY)plde;

    if( pde >= ( PDIRENTRY )pldeEnd ) {
        if( dwError = ReadStream( pstmDir, pos, &pde, &pdeEnd ))
            goto exit;

#ifdef TFAT
        // clone the buffer, if it wasn't just added by resizestream
        if(pvol->v_fTfat)
        {
            dwError = CloneDirCluster( pvol, pstmDir, pstmDir->s_pbufCur->b_blk, NULL );
            if( ERROR_DISK_FULL == dwError ) {
                goto exit;
            }
            else if (CLONE_CLUSTER_COMPLETE == dwError) {
                // The current buffer might be changed in CloneDirCluster
                // update plde with the new buffer
                if( dwError = ReadStream( pstmDir, pos, &pde, &pdeEnd )) {
                    DEBUGMSG (TRUE, (TEXT("FATFSD!TFAT: ERROR!!!! ReadStream failed after CloneDirCluster\n")));
                    ASSERT (0);   // It is bad if happens
                    goto exit;
                }
            }
        }
#endif        
    }

    dwError = ModifyStreamBuffer(pstmDir, pde, sizeof(DIRENTRY));
    if (dwError)
        goto exit;

    CreateDirEntry(pstmDir, pde, pdeClone, (BYTE)flName, pdi->di_clusEntry);
    memcpy(pde->de_name, pdi->di_achOEM, sizeof(pde->de_name));

    // TEST_BREAK
    PWR_BREAK_NOTIFY(23);

    // If ResizeStream had to add any new clusters, then any portion
    // we haven't written yet needs to be zeroed.

    if (cbOldSize != pstmDir->s_size && posEnd < pstmDir->s_size) {

        PBUF pbuf = pstmDir->s_pbufCur;

        // Because WriteStreamData (usually doesn't but) may involve filling a
        // new buffer, and we don't want to lose the hold we've got on the current
        // stream buffer, we have to apply another hold.

        HoldBuffer(pbuf);
        WriteStreamData(pstmDir, posEnd, NULL, pstmDir->s_size-posEnd, NULL, FALSE);
        ReleaseStreamBuffer(pstmDir, FALSE);
        AssignStreamBuffer(pstmDir, pbuf, FALSE);
        UnholdBuffer(pbuf);
    }

    // Commit all buffers associated with the directory stream, held or not,
    // and don't release the current stream buffer either.

    dwError = WriteStreamBuffers(pstmDir);

  exit:
    if (pdi->di_clusEntry != UNKNOWN_CLUSTER) {

        // Since we pre-allocated a cluster for this new stream (namely di_clusEntry),
        // if there was an error, then we want to de-allocate that cluster.

        if (dwError) {
            PACK(pvol, pdi->di_clusEntry, FREE_CLUSTER, NULL);
            pdi->di_clusEntry = UNKNOWN_CLUSTER;
        }
        
#ifdef TFAT
        if (!pvol->v_fTfat)
#endif        
            UnlockFAT(pvol);

    }

    // Make sure any changes made to the FAT are written now, too.  Even if we
    // didn't have to pre-allocate a cluster for the new stream, we might have had to
    // resize the directory containing it (which would have affected the FAT as well),
    // and since we call ResizeStream without RESIZESTREAM_UPDATEFAT in order to minimize
    // writes to the FAT, it's a good idea to have an explicit write somewhere....

    if (!dwError) {
        WriteStreamBuffers(pvol->v_pstmFAT);
    }

#ifdef TFAT
    if (pvol->v_fTfat)
        UnlockFAT (pvol);
#endif    


    if (!dwError) {

        // Update the DIRINFO structure, so that the caller has all
        // the same info that a successful FindNext would have returned.

        pdi->di_pde = pde;
        pdi->di_pos = pos;
        SETSID(&pdi->di_sid, pos, pstmDir->s_clusFirst);

        // I can tell you're wondering why we're reloading di_clusEntry
        // from the DIRENTRY, since we passed di_clusEntry to CreateDirEntry
        // in the first place, so wouldn't they already be the same?  The
        // answer is NO if CreateDirEntry was also given a pde to clone;
        // in that case, we DO need to reload di_clusEntry from the DIRENTRY.

        pdi->di_clusEntry = GETDIRENTRYCLUSTER(pvol,pde);
        if (pdi->di_clusEntry == NO_CLUSTER)
            pdi->di_clusEntry = UNKNOWN_CLUSTER;
    }
    return dwError;
}


/*  DestroyName - destroy a DIRENTRY in the specified directory stream
 *
 *  ENTRY
 *      pstmDir - pointer to directory stream
 *      pdi - pointer to DIRINFO (information returned by search)
 *
 *  EXIT
 *      Error code (0 if success, non-zero if error)
 *
 *  NOTES
 *      The DIRINFO structure identifies what DIRENTRY to blow away.  The
 *      stream's current buffer must be held and must contain the entry to
 *      be deleted.
 *
 *      A deliberate peculiarity of this function is that it does not extract
 *      clusFirst from the DIRENTRY to determine what clusters to decommit.
 *      It relies on the (normally identical) clusEntry field in the DIRINFO
 *      structure instead.  The reason is to give caller's the option of leaving
 *      the cluster chain intact, in case they're simply destroying a name as
 *      part of, say, a RENAME operation.
 */

DWORD DestroyName(PDSTREAM pstmDir, PDIRINFO pdi)
{
    DWORD dwError;
    PDIRENTRY pde, pdeEnd;
    PVOLUME pvol = pstmDir->s_pvol;
    
#ifdef DEBUG
    char achName[sizeof(pdi->di_pde->de_name)];
#endif

#ifdef TFAT
    DWORD blkNew;
#endif

    // We kill the directory entries first and THEN any clusters
    // so that in the event of a crash, you're more likely to end up
    // with orphaned clusters than cross-linkable clusters.  However,
    // *guaranteeing* that would require changing the very first
    // ModifyStreamBuffer's commit parm to TRUE, which is undesirable.

    // Since the stream's buffer has been held for us, and that buffer
    // contains the primary DIRENTRY for this file, kill that entry first.

    ASSERT(pdi->di_pde);

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!Enter DestroyName (%.11hs)\r\n"), pdi->di_pde->de_name));

    // TFAT, LockFAT around WriteAndReleaseStreamBuffers(pstmDir) and FreezeClusters
    // the direntry matches what's in the FAT
    LockFAT(pvol);


#ifdef TFAT
    if (pvol->v_fTfat) {
        // we need to clone the current buffer
        // before we make any modifications!
        if (CLONE_CLUSTER_COMPLETE == CloneDirCluster( pvol, pstmDir, pstmDir->s_pbufCur->b_blk, &blkNew ))
        {
            // The current buffer might be changed in CloneDirCluster
            // update plde to with the new buffer
            if( dwError = ReadStream( pstmDir, pdi->di_pos, &pdi->di_pde, NULL))
                goto exit;
        }
    }
#endif

    dwError = ModifyStreamBuffer(pstmDir, pdi->di_pde, sizeof(DIRENTRY));
    if (dwError)
        goto exit;

#ifdef DEBUG
    memcpy(achName, pdi->di_pde->de_name, sizeof(pdi->di_pde->de_name));
#endif
    pdi->di_pde->de_name[0] = DIRFREE;

    // Now see if there were also LFN entries that need to be killed;
    // since all the LFN entries have to be associated with the entry above,
    // we can just kill every entry we find until we reach a non-LFN entry.

    if (pdi->di_posLFN != INVALID_POS) {

        
        
        while(( dwError = ReadStream( pstmDir, pdi->di_posLFN, &pde, &pdeEnd )) == ERROR_SUCCESS ) {
#ifdef TFAT     
            if (pvol->v_fTfat) {
                // We need to check if we need to clone the block for TFAT vols.
                if(pstmDir->s_pbufCur->b_blk != blkNew ) {
                    // If we read in a different block than we replaced
                    // earlier, we need to replace this one as well.
    			if (CLONE_CLUSTER_COMPLETE == CloneDirCluster( pvol, pstmDir, pstmDir->s_pbufCur->b_blk, &blkNew ))
    			{
                        // The current buffer might be changed in CloneDirCluster
                        // update plde to with the new buffer
                        if( dwError = ReadStream( pstmDir, pdi->di_posLFN, &pde, &pdeEnd )) {
                            RETAILMSG (TRUE, (TEXT("FATFSD!TFAT: ERROR!!!! ReadStream failed after CloneDirCluster\n")));
                            ASSERT (0);  // It is bad if happens
                            goto exit;

⌨️ 快捷键说明

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