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

📄 find.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码.移植性非常高. 里面带有source i.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
                        // This LFN sequence has TOO MANY entries, which also
                        // means it won't fit in a MAX_PATH buffer.  We could
                        // treat the sequence like orphaned LFN entries, but
                        // that seems a rather risky proposition, since we may be
                        // talking directory corruption here.  Safer to just ignore
                        // them and rely on SCANDSKW to fix things up. -JTP
                        goto resetall;
                    }

                    if (!(di.di_flags & DIRINFO_OEM) && di.di_cdeNeed > 1 && seqLFN != di.di_cdeNeed-1) {

                        // Optimization: this LFN sequence does not have the requisite
                        // number of entries, so it can't possibly be a match.
                        goto resetall;
                    }

                    chksum = plde->lde_chksum;

                    // If this LFN sequence has the wrong OEM chksum, it might simply
                    // be due to charset differences between the system where the OEM name
                    // was originally created and the current system, so unlike previous
                    // releases, we will no longer bail out and 'goto resetall';  we will
                    // instead continue to collect all the LFN chunks and do the full name
                    // comparison.  In other words, we are no longer dependent on the
                    // accuracy of the OEM version of the name (as computed by UniToOEMName). -JTP

                    DEBUGMSGW(di.di_cdeNeed == 1 && chksum != di.di_chksum && ZONE_APIS && ZONE_ERRORS,(DBGTEXTW("FATFS!FindNext: lfn chksum (%x) doesn't match OEM chksum (%x) for '%.11hs'\n"), chksum, di.di_chksum, di.di_achOEM));

                    // Remember this LFN's starting position
                    di.di_posLFN = di.di_pos;

                    cwComp = di.di_cwTail;
                    pwsComp = di.di_pwsTail;
                    pwsBuff = &pfd->cFileName[LDE_NAME_LEN*LN_MAX_ORD_NUM];
                    *--pwsBuff = 0;     // guarantee a NULL-terminator

                    // If this LFN contains the max number of LFNDIRENTRYs,
                    // we have to scoot pwsBuff up one WCHAR and reduce the
                    // amount of the final memcpy (of lde_name3) by one WCHAR,
                    // to insure that the NULL-terminator above is preserved.

                    if (seqLFN == LN_MAX_ORD_NUM) {
                        pwsBuff++;
                        cbName3 -= sizeof(WCHAR);
                    }
                }

                // Skip LFN entries we're not interested in

                else if (seqLFN == -1) {
                    goto resetall;
                }

                // Recover LFN entries that are inconsistent

                else if (seqLFN != plde->lde_ord || chksum != plde->lde_chksum) {

                    // All preceding LFN entries are deemed bogus/recoverable.
                    // If they can be merged with the free count, do it, otherwise
                    // leave them recorded as unrecoverable.

                    DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!FindNext: LFN sequence (0x%x vs. 0x%x) or LFN chksum (0x%x vs. 0x%x) error\n"), seqLFN, plde->lde_ord, chksum, plde->lde_chksum));

                    di.di_posOrphan = di.di_posLFN;
                    di.di_cdeOrphan = (di.di_pos - di.di_posLFN)/sizeof(LFNDIRENTRY);

                    if (di.di_posFree + di.di_cdeFree * sizeof(LFNDIRENTRY) == di.di_posLFN) {
                        di.di_cdeFree += di.di_cdeOrphan;
                        di.di_cdeOrphan = 0;
                    }
                    goto resetall;
                }

                if (di.di_cdeFree < di.di_cdeNeed)
                    di.di_cdeFree = 0;

                // LFN directory entry in sequence. Copy the name entry by
                // entry into a scratch buffer to be matched when all of the
                // entries in the name have been processed.

                pwsBuff -= LDE_NAME_LEN;
                memcpy(pwsBuff, plde->lde_name1, sizeof(plde->lde_name1));
                memcpy(pwsBuff+LDE_LEN1, plde->lde_name2, sizeof(plde->lde_name2));
                memcpy(pwsBuff+LDE_LEN1+LDE_LEN2, plde->lde_name3, cbName3);

                // If we can compare individual pieces, do it now

                if (fComp) {

                    // We perform a quick comparison on the first
                    // character past the end of the LFN (if one exists)
                    // and if that character isn't a NULL, then this
                    // entry isn't a match;  otherwise, compare entire piece.

                    if (cwComp != LDE_NAME_LEN && pwsBuff[cwComp] != 0 ||
                        _wcsnicmp(pwsBuff, pwsComp, cwComp) != 0) {
                        goto resetlfn;
                    }
                    pwsComp -= LDE_NAME_LEN;
                }

                --seqLFN;
                continue;
            }

            // Check for a "normal" directory entry.

            if ((di.di_pde->de_attr & ATTR_DIR_MASK) != ATTR_VOLUME_ID) {

                int len;

                
                if (!(psh->sh_flags & SHF_DOTDOT) &&
                    (*(PDWORD)di.di_pde->de_name == 0x2020202e ||
                     *(PDWORD)di.di_pde->de_name == 0x20202e2e)) {
                    goto resetall;
                }

                // Normal directory entry.  If preceeding LFN
                // directory entries matched, handle this entry
                // as a match.  Otherwise, if the name is 8.3
                // compatible, then try to match the 8.3 OEM name
                // contained in this entry.

                if (seqLFN == 0) {

                    if (chksum == ChkSumName(di.di_pde->de_name)) {

                        len = wcslen(pwsBuff);

                        // We processed all the LFN chunks for the current entry,
                        // (since seqLFN is now 0), so if fComp is TRUE, that means
                        // we compared every chunk as we went, and they must have
                        // all matched, so let's just 'goto match'

                        if (fComp)
                            goto match;

                        // If cdeNeed == -1, we're dealing with wildcards *or* a
                        // a non-name-based search, so we have to explicitly check
                        // for a match.

                        if (di.di_cdeNeed == -1)
                            goto checkmatch;

                        // Well, we must be performing a name-based search, and since
                        // we didn't compare the LFN chunks as we went, we did at least
                        // collect them all in pwsBuff, so let's see if the full LFN
                        // matches....
                        //
                        // Note: we didn't *always* used to do this, which meant that we
                        // always fell into the "normal directory entry" case below, which
                        // which only compared the OEM forms of the filenames;  normally,
                        // that was sufficient, but in cases where the OEM name was created
                        // on a system with different charset mappings, that comparison could
                        // fail.  We should rely on the 8.3 OEM name IFF there are no LFN
                        // entries -- and in this case, there *is*.... -JTP

                        if (len == psh->sh_cwPattern && _wcsnicmp(pwsBuff, psh->sh_awcPattern, len) == 0)
                            goto match;
                    }
                    else {

                        // All preceding LFN entries are deemed bogus/recoverable.
                        // If they can be merged with the free count, do it, otherwise
                        // leave them recorded as unrecoverable.

                        DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!FindNext: LFN chksum (0x%x vs. 0x%x) error\n"), chksum, ChkSumName(di.di_pde->de_name)));

                        di.di_posOrphan = di.di_posLFN;
                        di.di_cdeOrphan = (di.di_pos - di.di_posLFN)/sizeof(LFNDIRENTRY);

                        if (di.di_posFree + di.di_cdeFree * sizeof(LFNDIRENTRY) != di.di_posLFN) {
                            di.di_cdeFree = 0;
                        } else {
                            di.di_cdeFree += di.di_cdeOrphan;
                            di.di_cdeOrphan = 0;
                        }

                        // We used to bail at this point (goto checkshort), but the right
                        // thing to do is just treat the current DIRENTRY as a short-name only.
                        seqLFN = -1;
                    }
                }

                // Normal directory entry, and either there were no preceding LFN
                // entries, or there were but we couldn't make use of them.

                if (di.di_cdeNeed == -1 ||
                    (di.di_flags & DIRINFO_OEM) &&
                    memcmp(di.di_pde->de_name,
                           di.di_achOEM,
                           sizeof(di.di_pde->de_name)) == 0) {
                    
                    // If seqLFN == 0, then the preceding LFN entries probably
                    // provide better name information, so use the OEM name only if
                    // we have to.

                    if (seqLFN != 0) {
                        pwsBuff = pfd->cFileName;
                        len = OEMToUniName(pwsBuff, di.di_pde->de_name);
                    }
                    if (di.di_flags & DIRINFO_OEM)
                        goto match;
                    else
                        goto checkmatch;
                }
                goto checkshort;

              checkmatch:
                // Resync the SHANDLE pos with DIRINFO pos, for MatchNext
                psh->sh_pos = di.di_pos;

                if (MatchNext(psh, pwsBuff, len, di.di_pde)) {

                  match:
                    SETSID(&di.di_sid, di.di_pos, pstmDir->s_clusFirst);
                    pfd->dwOID = OIDFROMSID(pstmDir->s_pvol, &di.di_sid);

                    pfd->dwFileAttributes = di.di_pde->de_attr;
                    if (pfd->dwFileAttributes == 0)
                        pfd->dwFileAttributes = FILE_ATTRIBUTE_NORMAL;

                    pfd->nFileSizeHigh = 0;
                    pfd->nFileSizeLow = di.di_pde->de_size;

                    // If the name was built up from a series of LFN entries,
                    // it may need to be slid down to the start of pfd->cFilename
                    // (since we built it up from the top down).

                    if (pwsBuff != pfd->cFileName) {
                        memcpy(pfd->cFileName, pwsBuff, len*sizeof(WCHAR));
                        pfd->cFileName[len] = 0;
                    }
                    // If the caller passed us a DIRINFO, then leave the
                    // the stream buffer held and let him have the address
                    // of the DIRENTRY (di.di_pde).  We do not need to advance
                    // the search position or fill in the entire WIN32_FIND_DATAW
                    // for such callers.

                    if (pdi) {
                        di.di_clusEntry =
                            GETDIRENTRYCLUSTER(pstmDir->s_pvol, di.di_pde);
                        if (di.di_clusEntry == NO_CLUSTER)
                            di.di_clusEntry = UNKNOWN_CLUSTER;
                        di.di_cwName = len;
                        goto norelease;
                    }

                    // We don't need to waste time converting/copying all the
                    // file times for certain types of searches (eg, SHF_BYCLUS
                    // or SHF_DOTDOT).

                    if ((psh->sh_flags & SHF_BYMASK) != SHF_BYCLUS && !(psh->sh_flags & SHF_DOTDOT))
                        CopyTimes(pfd, di.di_pde);

                    di.di_pde = NULL;
                    psh->sh_pos = di.di_pos + sizeof(DIRENTRY);
                    goto release;
                }

                // We just can't seem to do anything with this
                // directory entry.  Well, if the caller may need to
                // create a new LFN entry, determine if the current
                // entry conflicts with any of the possible short names
                // we can generate.

              checkshort:
                if (pdwShortNameBitArray)
                    CheckNumericTail(&di, pdwShortNameBitArray);
            }

          resetall:
            if (di.di_cdeFree < di.di_cdeNeed)
                di.di_cdeFree = 0;

          resetlfn:
            seqLFN = -1;                // reset LFN match sequence #
            di.di_posLFN = INVALID_POS;

        } while ((di.di_pos += sizeof(DIRENTRY)), ++di.di_pde < pdeEnd);

      } __except (EXCEPTION_EXECUTE_HANDLER) {
        dwError = ERROR_INVALID_PARAMETER;
        di.di_pde = NULL;
      }
    }

  release:
    ReleaseStreamBuffer(pstmDir, FALSE);

  norelease:
    if (pdi) {

        // Before copying the DIRINFO structure, see if the caller was
        // searching on behalf of a CREATE, and try to generate a non-existent
        // short name that he can use to perform the creation.

        if (pdwShortNameBitArray)
            GenerateNumericTail(&di, pdwShortNameBitArray);

        *pdi = di;
    }

    if (dwError)
        psh->sh_pos = INVALID_POS;

    return dwError;
}


void CreateDirEntry(PDSTREAM pstmDir, PDIRENTRY pde, PDIRENTRY pdeClone, BYTE bAttr, DWORD clusFirst)
{
    FILETIME ft;
    SYSTEMTIME st;

    if (pdeClone) {
        *pde = *pdeClone;
        return;
    }

    memset(pde->de_name, ' ', sizeof(pde->de_name));
    memset(&pde->de_attr, 0, sizeof(DIRENTRY)-sizeof(pde->de_name));

    pde->de_attr = bAttr;

    if (clusFirst != UNKNOWN_CLUSTER && clusFirst >= DATA_CLUSTER)
        SETDIRENTRYCLUSTER(pstmDir->s_pvol, pde, clusFirst);

    GetSystemTimeAsFileTime(&ft);

    // Directories don't really benefit from creation and access
    // timestamps, but we'll set them anyway.  MS-DOS only sets access
    // and modified dates, but Win95's VFAT sets all three, so so will we.

    FileTimeToDOSTime(&ft,
                      &pde->de_createdDate,
                      &pde->de_createdTime,
                      &pde->de_createdTimeMsec);

    FileTimeToDOSTime(&ft, &pde->de_date, &pde->de_time, NULL);

    // This is simpler than truncating the local system time to midnight,
    // converting it to a local file time, then converting it to a non-local
    // file time, then calling FileTimeToDOSTime, which turns around and
    // undoes most of that.

    GetLocalTime(&st);

    DEBUGMSG(ZONE_STREAMS,(DBGTEXT("FATFS!CreateDirEntry: local file system ACCESS time: y=%d,m=%d,d=%d,h=%d,m=%d,s=%d\n"), st.wYear, st.wMonth, st.wDay, 0, 0, 0));

    pde->de_lastAccessDate = ((st.wYear-1980) << 9) | (st.wMonth << 5) | (st.wDay);
}

⌨️ 快捷键说明

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