Changeset 2863 for trunk/src


Ignore:
Timestamp:
Sep 2, 2016, 6:32:50 PM (9 years ago)
Author:
bird
Message:

updates

Location:
trunk/src/lib/nt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/kFsCache.c

    r2862 r2863  
    6262# define KFSCACHE_LOG2(a) do { } while (0)
    6363#endif
     64
     65
     66/*********************************************************************************************************************************
     67*   Structures and Typedefs                                                                                                      *
     68*********************************************************************************************************************************/
     69/**
     70 * Used by the code re-populating a directory.
     71 */
     72typedef struct KFSDIRREPOP
     73{
     74    /** The old papChildren array. */
     75    PKFSOBJ    *papOldChildren;
     76    /** Number of children in the array. */
     77    KU32        cOldChildren;
     78    /** The index into papOldChildren we expect to find the next entry.  */
     79    KU32        iNextOldChild;
     80    /** Add this to iNextOldChild . */
     81    KI32        cNextOldChildInc;
     82    /** Pointer to the cache (name changes). */
     83    PKFSCACHE   pCache;
     84} KFSDIRREPOP;
     85/** Pointer to directory re-population data. */
     86typedef KFSDIRREPOP *PKFSDIRREPOP;
    6487
    6588
     
    231254
    232255/**
     256 * For use when kFsCacheIAreEqualW hit's something non-trivial.
     257 *
     258 * @returns K_TRUE if equal, K_FALSE if different.
     259 * @param   pwcName1            The first string.
     260 * @param   pwcName2            The second string.
     261 * @param   cwcName             The length of the two strings (in wchar_t's).
     262 */
     263KBOOL kFsCacheIAreEqualSlowW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU16 cwcName)
     264{
     265    MY_UNICODE_STRING UniStr1 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName1 };
     266    MY_UNICODE_STRING UniStr2 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName2 };
     267    return g_pfnRtlEqualUnicodeString(&UniStr1, &UniStr2, TRUE /*fCaseInsensitive*/);
     268}
     269
     270
     271/**
     272 * Compares two UTF-16 strings in a case-insensitive fashion.
     273 *
     274 * You would think we should be using _wscnicmp here instead, however it is
     275 * locale dependent and defaults to ASCII upper/lower handling setlocale hasn't
     276 * been called.
     277 *
     278 * @returns K_TRUE if equal, K_FALSE if different.
     279 * @param   pwcName1            The first string.
     280 * @param   pwcName2            The second string.
     281 * @param   cwcName             The length of the two strings (in wchar_t's).
     282 */
     283K_INLINE KBOOL kFsCacheIAreEqualW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU32 cwcName)
     284{
     285    while (cwcName > 0)
     286    {
     287        wchar_t wc1 = *pwcName1;
     288        wchar_t wc2 = *pwcName2;
     289        if (wc1 == wc2)
     290        { /* not unlikely */ }
     291        else if (  (KU16)wc1 < (KU16)0xc0 /* U+00C0 is the first upper/lower letter after 'z'. */
     292                && (KU16)wc2 < (KU16)0xc0)
     293        {
     294            /* ASCII upper case. */
     295            if ((KU16)wc1 - (KU16)0x61 < (KU16)26)
     296                wc1 &= ~(wchar_t)0x20;
     297            if ((KU16)wc2 - (KU16)0x61 < (KU16)26)
     298                wc2 &= ~(wchar_t)0x20;
     299            if (wc1 != wc2)
     300                return K_FALSE;
     301        }
     302        else
     303            return kFsCacheIAreEqualSlowW(pwcName1, pwcName2, (KU16)cwcName);
     304
     305        pwcName2++;
     306        pwcName1++;
     307        cwcName--;
     308    }
     309
     310    return K_TRUE;
     311}
     312
     313
     314/**
    233315 * Looks for '..' in the path.
    234316 *
     
    405487static KBOOL kFsCacheDirAddChild(PKFSCACHE pCache, PKFSDIR pParent, PKFSOBJ pChild, KFSLOOKUPERROR *penmError)
    406488{
    407     if ((pParent->cChildren % 16) == 0)
    408     {
    409         void *pvNew = kHlpRealloc(pParent->papChildren, (pParent->cChildren + 16) * sizeof(pParent->papChildren[0]));
     489    if (pParent->cChildren >= pParent->cChildrenAllocated)
     490    {
     491        void *pvNew = kHlpRealloc(pParent->papChildren, (pParent->cChildrenAllocated + 16) * sizeof(pParent->papChildren[0]));
    410492        if (!pvNew)
    411493            return K_FALSE;
    412494        pParent->papChildren = (PKFSOBJ *)pvNew;
     495        pParent->cChildrenAllocated += 16;
    413496        pCache->cbObjects += 16 * sizeof(pParent->papChildren[0]);
    414497    }
     
    533616        {
    534617            PKFSDIR pDirObj = (PKFSDIR)pObj;
    535             pDirObj->cChildren      = 0;
    536             pDirObj->papChildren    = NULL;
    537             pDirObj->cHashTab       = 0;
    538             pDirObj->paHashTab      = NULL;
    539             pDirObj->hDir           = INVALID_HANDLE_VALUE;
    540             pDirObj->uDevNo         = pParent->uDevNo;
    541             pDirObj->iLastWrite     = 0;
    542             pDirObj->fPopulated     = K_FALSE;
     618            pDirObj->cChildren          = 0;
     619            pDirObj->cChildrenAllocated = 0;
     620            pDirObj->papChildren        = NULL;
     621            pDirObj->cHashTab           = 0;
     622            pDirObj->paHashTab          = NULL;
     623            pDirObj->hDir               = INVALID_HANDLE_VALUE;
     624            pDirObj->uDevNo             = pParent->uDevNo;
     625            pDirObj->iLastWrite         = 0;
     626            pDirObj->fPopulated         = K_FALSE;
    543627        }
    544628    }
     
    685769}
    686770
     771/**
     772 * Worker for kFsCacheDirFindOldChild that refreshes the file ID value on an
     773 * object found by name.
     774 *
     775 * @returns Pointer to the existing object if found, NULL if not.
     776 * @param   pDirRePop       Repopulation data.
     777 * @param   pCur            The object to check the names of.
     778 * @param   idFile          The file ID.
     779 */
     780static PKFSOBJ kFsCacheDirRefreshOldChildFileId(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, KI64 idFile)
     781{
     782    KFSCACHE_LOG(("Refreshing %s/%s/ - %s changed file ID from %#llx -> %#llx...\n",
     783                  pCur->pParent->Obj.pParent->Obj.pszName, pCur->pParent->Obj.pszName, pCur->pszName,
     784                  pCur->Stats.st_ino, idFile));
     785    pCur->Stats.st_ino = idFile;
     786    /** @todo inform user data items...  */
     787    return pCur;
     788}
     789
     790
     791/**
     792 * Worker for kFsCacheDirFindOldChild that checks the names after an old object
     793 * has been found the file ID.
     794 *
     795 * @returns Pointer to the existing object if found, NULL if not.
     796 * @param   pDirRePop       Repopulation data.
     797 * @param   pCur            The object to check the names of.
     798 * @param   pwcName         The file name.
     799 * @param   cwcName         The length of the filename (in wchar_t's).
     800 * @param   pwcShortName    The short name, if present.
     801 * @param   cwcShortName    The length of the short name (in wchar_t's).
     802 */
     803static PKFSOBJ kFsCacheDirRefreshOldChildName(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, wchar_t const *pwcName, KU32 cwcName
     804#ifdef KFSCACHE_CFG_SHORT_NAMES
     805                                              , wchar_t const *pwcShortName, KU32 cwcShortName
     806#endif
     807                                              )
     808{
     809    __debugbreak();
     810    /** @todo implement this.  It's not entirely straight forward, especially if
     811     *        the name increases!  Also, it's something that may happend during
     812     *        individual object refresh and we might want to share code... */
     813
     814    return pCur;
     815}
     816
     817
     818/**
     819 * Worker for kFsCacheDirFindOldChild that checks the names after an old object
     820 * has been found the file ID.
     821 *
     822 * @returns Pointer to the existing object if found, NULL if not.
     823 * @param   pDirRePop       Repopulation data.
     824 * @param   pCur            The object to check the names of.
     825 * @param   pwcName         The file name.
     826 * @param   cwcName         The length of the filename (in wchar_t's).
     827 * @param   pwcShortName    The short name, if present.
     828 * @param   cwcShortName    The length of the short name (in wchar_t's).
     829 */
     830K_INLINE PKFSOBJ kFsCacheDirCheckOldChildName(PKFSDIRREPOP pDirRePop, PKFSOBJ pCur, wchar_t const *pwcName, KU32 cwcName
     831#ifdef KFSCACHE_CFG_SHORT_NAMES
     832                                              , wchar_t const *pwcShortName, KU32 cwcShortName
     833#endif
     834                                              )
     835{
     836    if (   pCur->cwcName == cwcName
     837        && kHlpMemComp(pCur->pwszName, pwcName, cwcName * sizeof(wchar_t)) == 0)
     838    {
     839#ifdef KFSCACHE_CFG_SHORT_NAMES
     840        if (cwcShortName == 0
     841            ?    pCur->pwszShortName == pCur->pwszName
     842              || (   pCur->cwcShortName == cwcName
     843                  && kHlpMemComp(pCur->pwszShortName, pCur->pwszName, cwcName * sizeof(wchar_t)) == 0)
     844            :    pCur->cwcShortName == cwcShortName
     845              && kHlpMemComp(pCur->pwszShortName, pwcShortName, cwcShortName * sizeof(wchar_t)) == 0 )
     846#endif
     847        {
     848            return pCur;
     849        }
     850    }
     851#ifdef KFSCACHE_CFG_SHORT_NAMES
     852    return kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     853#else
     854    return kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName);
     855#endif
     856}
     857
     858
     859/**
     860 * Worker for kFsCachePopuplateOrRefreshDir that locates an old child object
     861 * while re-populating a directory.
     862 *
     863 * @returns Pointer to the existing object if found, NULL if not.
     864 * @param   pDirRePop       Repopulation data.
     865 * @param   idFile          The file ID, 0 if none.
     866 * @param   pwcName         The file name.
     867 * @param   cwcName         The length of the filename (in wchar_t's).
     868 * @param   pwcShortName    The short name, if present.
     869 * @param   cwcShortName    The length of the short name (in wchar_t's).
     870 */
     871static PKFSOBJ kFsCacheDirFindOldChildSlow(PKFSDIRREPOP pDirRePop, KI64 idFile, wchar_t const *pwcName, KU32 cwcName
     872#ifdef KFSCACHE_CFG_SHORT_NAMES
     873                                           , wchar_t const *pwcShortName, KU32 cwcShortName
     874#endif
     875                                           )
     876{
     877    KU32        cOldChildren  = pDirRePop->cOldChildren;
     878    KU32 const  iNextOldChild = K_MIN(pDirRePop->iNextOldChild, cOldChildren - 1);
     879    KU32        iCur;
     880    KI32        cInc;
     881    KI32        cDirLefts;
     882
     883    kHlpAssertReturn(cOldChildren > 0, NULL);
     884
     885    /*
     886     * Search by file ID first, if we've got one.
     887     * ASSUMES that KU32 wraps around when -1 is added to 0.
     888     */
     889    if (   idFile != 0
     890        && idFile != KI64_MAX
     891        && idFile != KI64_MIN)
     892    {
     893        cInc = pDirRePop->cNextOldChildInc;
     894        kHlpAssert(cInc == -1 || cInc == 1);
     895        for (cDirLefts = 2; cDirLefts > 0; cDirLefts--)
     896        {
     897            for (iCur = iNextOldChild; iCur < cOldChildren; iCur += cInc)
     898            {
     899                PKFSOBJ pCur = pDirRePop->papOldChildren[iCur];
     900                if (pCur->Stats.st_ino == idFile)
     901                {
     902                    /* Remove it and check the name. */
     903                    pDirRePop->cOldChildren = --cOldChildren;
     904                    if (iCur < cOldChildren)
     905                        pDirRePop->papOldChildren[iCur] = pDirRePop->papOldChildren[cOldChildren];
     906                    else
     907                        cInc = -1;
     908                    pDirRePop->cNextOldChildInc = cInc;
     909                    pDirRePop->iNextOldChild    = iCur + cInc;
     910
     911#ifdef KFSCACHE_CFG_SHORT_NAMES
     912                    return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     913#else
     914                    return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     915#endif
     916                }
     917            }
     918            cInc = -cInc;
     919        }
     920    }
     921
     922    /*
     923     * Search by name.
     924     * ASSUMES that KU32 wraps around when -1 is added to 0.
     925     */
     926    cInc = pDirRePop->cNextOldChildInc;
     927    kHlpAssert(cInc == -1 || cInc == 1);
     928    for (cDirLefts = 2; cDirLefts > 0; cDirLefts--)
     929    {
     930        for (iCur = iNextOldChild; iCur < cOldChildren; iCur += cInc)
     931        {
     932            PKFSOBJ pCur = pDirRePop->papOldChildren[iCur];
     933            if (   (   pCur->cwcName == cwcName
     934                    && kFsCacheIAreEqualW(pCur->pwszName, pwcName, cwcName))
     935#ifdef KFSCACHE_CFG_SHORT_NAMES
     936                || (   pCur->cwcShortName == cwcName
     937                    && pCur->pwszShortName != pCur->pwszName
     938                    && kFsCacheIAreEqualW(pCur->pwszShortName, pwcName, cwcName))
     939#endif
     940               )
     941            {
     942                /* Do this first so the compiler can share the rest with the above file ID return. */
     943                if (pCur->Stats.st_ino == idFile)
     944                { /* likely */ }
     945                else
     946                    pCur = kFsCacheDirRefreshOldChildFileId(pDirRePop, pCur, idFile);
     947
     948                /* Remove it and check the name. */
     949                pDirRePop->cOldChildren = --cOldChildren;
     950                if (iCur < cOldChildren)
     951                    pDirRePop->papOldChildren[iCur] = pDirRePop->papOldChildren[cOldChildren];
     952                else
     953                    cInc = -1;
     954                pDirRePop->cNextOldChildInc = cInc;
     955                pDirRePop->iNextOldChild    = iCur + cInc;
     956
     957#ifdef KFSCACHE_CFG_SHORT_NAMES
     958                return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     959#else
     960                return kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     961#endif
     962            }
     963        }
     964        cInc = -cInc;
     965    }
     966
     967    return NULL;
     968}
     969
     970
     971
     972/**
     973 * Worker for kFsCachePopuplateOrRefreshDir that locates an old child object
     974 * while re-populating a directory.
     975 *
     976 * @returns Pointer to the existing object if found, NULL if not.
     977 * @param   pDirRePop       Repopulation data.
     978 * @param   idFile          The file ID, 0 if none.
     979 * @param   pwcName         The file name.
     980 * @param   cwcName         The length of the filename (in wchar_t's).
     981 * @param   pwcShortName    The short name, if present.
     982 * @param   cwcShortName    The length of the short name (in wchar_t's).
     983 */
     984K_INLINE PKFSOBJ kFsCacheDirFindOldChild(PKFSDIRREPOP pDirRePop, KI64 idFile, wchar_t const *pwcName, KU32 cwcName
     985#ifdef KFSCACHE_CFG_SHORT_NAMES
     986                                         , wchar_t const *pwcShortName, KU32 cwcShortName
     987#endif
     988                                         )
     989{
     990    /*
     991     * We only check the iNextOldChild element here, hoping that the compiler
     992     * will actually inline this code, letting the slow version of the function
     993     * do the rest.
     994     */
     995    KU32 cOldChildren = pDirRePop->cOldChildren;
     996    if (cOldChildren > 0)
     997    {
     998        KU32 const  iNextOldChild = K_MIN(pDirRePop->iNextOldChild, cOldChildren);
     999        PKFSOBJ     pCur          = pDirRePop->papOldChildren[iNextOldChild];
     1000
     1001        if (   pCur->Stats.st_ino == idFile
     1002            && idFile != 0
     1003            && idFile != KI64_MAX
     1004            && idFile != KI64_MIN)
     1005            pCur = kFsCacheDirCheckOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     1006        else if (   pCur->cwcName == cwcName
     1007                 && kHlpMemComp(pCur->pwszName,  pwcName, cwcName * sizeof(wchar_t)) == 0)
     1008        {
     1009            if (pCur->Stats.st_ino == idFile)
     1010            { /* likely */ }
     1011            else
     1012                pCur = kFsCacheDirRefreshOldChildFileId(pDirRePop, pCur, idFile);
     1013
     1014#ifdef KFSCACHE_CFG_SHORT_NAMES
     1015            if (cwcShortName == 0
     1016                ?    pCur->pwszShortName == pCur->pwszName
     1017                  || (   pCur->cwcShortName == cwcName
     1018                      && kHlpMemComp(pCur->pwszShortName, pCur->pwszName, cwcName * sizeof(wchar_t)) == 0)
     1019                :    pCur->cwcShortName == cwcShortName
     1020                  && kHlpMemComp(pCur->pwszShortName, pwcShortName, cwcShortName * sizeof(wchar_t)) == 0 )
     1021             { /* likely */ }
     1022             else
     1023                 pCur = kFsCacheDirRefreshOldChildName(pDirRePop, pCur, pwcName, cwcName, pwcShortName, cwcShortName);
     1024#endif
     1025        }
     1026        else
     1027            pCur = NULL;
     1028        if (pCur)
     1029        {
     1030            /*
     1031             * Got a match.  Remove the child from the array, replacing it with
     1032             * the last element.  (This means we're reversing the second half of
     1033             * the elements, which is why we need cNextOldChildInc.)
     1034             */
     1035            pDirRePop->cOldChildren = --cOldChildren;
     1036            if (iNextOldChild < cOldChildren)
     1037                pDirRePop->papOldChildren[iNextOldChild] = pDirRePop->papOldChildren[cOldChildren];
     1038            pDirRePop->iNextOldChild = iNextOldChild + pDirRePop->cNextOldChildInc;
     1039            return pCur;
     1040        }
     1041
     1042#ifdef KFSCACHE_CFG_SHORT_NAMES
     1043        return kFsCacheDirFindOldChildSlow(pDirRePop, idFile, pwcName, cwcName, pwcShortName, cwcShortName);
     1044#else
     1045        return kFsCacheDirFindOldChildSlow(pDirRePop, idFile, pwcName, cwcName);
     1046#endif
     1047    }
     1048
     1049    return NULL;
     1050}
     1051
     1052
    6871053
    6881054/**
     
    6991065static KBOOL kFsCachePopuplateOrRefreshDir(PKFSCACHE pCache, PKFSDIR pDir, KFSLOOKUPERROR *penmError)
    7001066{
    701     KBOOL                       fRefreshing  = K_FALSE;
    702     /** @todo will have to make this more flexible wrt information classes since
     1067    KBOOL                       fRefreshing = K_FALSE;
     1068    KFSDIRREPOP                 DirRePop    = { NULL, 0, 0, 0, NULL };
     1069    MY_UNICODE_STRING           UniStrStar  = { 1 * sizeof(wchar_t), 2 * sizeof(wchar_t), L"*" };
     1070
     1071    /** @todo May have to make this more flexible wrt information classes since
    7031072     *        older windows versions (XP, w2K) might not correctly support the
    7041073     *        ones with file ID on all file systems. */
     
    7201089        KU8                                 abBuf[56*1024];
    7211090    } uBuf;
     1091
    7221092
    7231093    /*
     
    7631133        }
    7641134    }
     1135    /*
     1136     * When re-populating, we replace papChildren in the directory and pick
     1137     * from the old one as we go along.
     1138     */
    7651139    else if (pDir->fPopulated)
    7661140    {
    767         /** @todo refreshing directories. */
    768         __debugbreak();
     1141        KU32  cAllocated = K_ALIGN_Z(pDir->cChildren, 16);
     1142        void *pvNew      = kHlpAlloc(sizeof(pDir->papChildren[0]) * cAllocated);
     1143        if (pvNew)
     1144        {
     1145            DirRePop.papOldChildren     = pDir->papChildren;
     1146            DirRePop.cOldChildren       = pDir->cChildren;
     1147            DirRePop.iNextOldChild      = 0;
     1148            DirRePop.cNextOldChildInc   = 1;
     1149            DirRePop.pCache             = pCache;
     1150
     1151            pDir->cChildren             = 0;
     1152            pDir->cChildrenAllocated    = cAllocated;
     1153            pDir->papChildren           = (PKFSOBJ *)pvNew;
     1154        }
     1155        else
     1156        {
     1157            *penmError = KFSLOOKUPERROR_OUT_OF_MEMORY;
     1158            return K_FALSE;
     1159        }
     1160
    7691161        fRefreshing = K_TRUE;
    7701162    }
     
    7761168    /*
    7771169     * Enumerate the directory content.
     1170     *
     1171     * Note! The "*" filter is necessary because kFsCacheRefreshObj may have
     1172     *       previously quried a single file name and just passing NULL would
     1173     *       restart that single file name query.
    7781174     */
    7791175    Ios.Information = -1;
     
    7881184                                     enmInfoClass,
    7891185                                     FALSE,     /* fReturnSingleEntry */
    790                                      NULL,      /* Filter / restart pos. */
     1186                                     &UniStrStar, /* Filter / restart pos. */
    7911187                                     TRUE);     /* fRestartScan */
    7921188    while (MY_NT_SUCCESS(rcNt))
     
    8121208            KU32        offNext;
    8131209            KU32        cbMinCur;
    814             wchar_t    *pwszFilename;
     1210            wchar_t    *pwchFilename;
    8151211
    8161212            /* ASSUME only the FileName member differs between the two structures. */
     
    8181214            if (enmInfoClass == enmInfoClassWithId)
    8191215            {
    820                 pwszFilename = &uPtr.pWithId->FileName[0];
     1216                pwchFilename = &uPtr.pWithId->FileName[0];
    8211217                cbMinCur  = (KU32)((uintptr_t)&uPtr.pWithId->FileName[0] - (uintptr_t)uPtr.pWithId);
    8221218                cbMinCur += uPtr.pNoId->FileNameLength;
     
    8241220            else
    8251221            {
    826                 pwszFilename = &uPtr.pNoId->FileName[0];
     1222                pwchFilename = &uPtr.pNoId->FileName[0];
    8271223                cbMinCur  = (KU32)((uintptr_t)&uPtr.pNoId->FileName[0] - (uintptr_t)uPtr.pNoId);
    8281224                cbMinCur += uPtr.pNoId->FileNameLength;
     
    8301226
    8311227            /* We need to skip the '.' and '..' entries. */
    832             if (   *pwszFilename != '.'
     1228            if (   *pwchFilename != '.'
    8331229                ||  uPtr.pNoId->FileNameLength > 4
    8341230                ||  !(   uPtr.pNoId->FileNameLength == 2
    8351231                      ||  (   uPtr.pNoId->FileNameLength == 4
    836                            && pwszFilename[1] == '.') )
     1232                           && pwchFilename[1] == '.') )
    8371233               )
    8381234            {
     1235                KBOOL       fRc;
     1236                KU8 const   bObjType = uPtr.pNoId->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ? KFSOBJ_TYPE_DIR
     1237                                     : uPtr.pNoId->FileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)
     1238                                     ? KFSOBJ_TYPE_OTHER : KFSOBJ_TYPE_FILE;
     1239
    8391240                /*
    840                  * Create the entry (not linked yet).
     1241                 * If refreshing, we must first see if this directory entry already
     1242                 * exists.
    8411243                 */
    842                 pCur = kFsCacheCreateObjectW(pCache, pDir, pwszFilename, uPtr.pNoId->FileNameLength / sizeof(wchar_t),
     1244                if (!fRefreshing)
     1245                    pCur = NULL;
     1246                else
     1247                {
     1248                    pCur = kFsCacheDirFindOldChild(&DirRePop,
     1249                                                   enmInfoClass == enmInfoClassWithId ? uPtr.pWithId->FileId.QuadPart : 0,
     1250                                                   pwchFilename, uPtr.pWithId->FileNameLength / sizeof(wchar_t)
    8431251#ifdef KFSCACHE_CFG_SHORT_NAMES
    844                                              uPtr.pNoId->ShortName, uPtr.pNoId->ShortNameLength / sizeof(wchar_t),
    845 #endif
    846                                              uPtr.pNoId->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ? KFSOBJ_TYPE_DIR
    847                                              : uPtr.pNoId->FileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)
    848                                              ? KFSOBJ_TYPE_OTHER : KFSOBJ_TYPE_FILE,
    849                                              penmError);
     1252                                                   , uPtr.pWithId->ShortName, uPtr.pWithId->ShortNameLength / sizeof(wchar_t)
     1253#endif
     1254                                                   );
     1255                    if (pCur)
     1256                    {
     1257                        if (pCur->bObjType == bObjType)
     1258                        {
     1259                            if (pCur->bObjType == KFSOBJ_TYPE_DIR)
     1260                            {
     1261                                PKFSDIR pCurDir = (PKFSDIR)pCur;
     1262                                if (   !pCurDir->fPopulated
     1263                                    ||  (   pCurDir->iLastWrite == uPtr.pWithId->LastWriteTime.QuadPart
     1264                                         && (pCur->fFlags & KFSOBJ_F_WORKING_DIR_MTIME) ) )
     1265                                { /* kind of likely */ }
     1266                                else
     1267                                {
     1268                                    KFSCACHE_LOG(("Refreshing %s/%s/ - %s/ needs re-populating...\n",
     1269                                                  pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName));
     1270                                    pCurDir->fNeedRePopulating = K_TRUE;
     1271                                }
     1272                            }
     1273                        }
     1274                        else if (pCur->bObjType == KFSOBJ_TYPE_MISSING)
     1275                        {
     1276                            KFSCACHE_LOG(("Refreshing %s/%s/ - %s appeared as %u, was missing.\n",
     1277                                          pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName, bObjType));
     1278                            pCur->bObjType = bObjType;
     1279                        }
     1280                        else
     1281                        {
     1282                            KFSCACHE_LOG(("Refreshing %s/%s/ - %s changed type from %u to %u! Dropping old object.\n",
     1283                                          pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pCur->pszName,
     1284                                          pCur->bObjType, bObjType));
     1285                            kFsCacheObjRelease(pCache, pCur);
     1286                            pCur = NULL;
     1287                        }
     1288                    }
     1289                    else
     1290                        KFSCACHE_LOG(("Refreshing %s/%s/ - %*.*ls added.\n", pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName,
     1291                                      uPtr.pNoId->FileNameLength / sizeof(wchar_t), uPtr.pNoId->FileNameLength / sizeof(wchar_t),
     1292                                      pwchFilename));
     1293                }
     1294
    8501295                if (!pCur)
    851                     return K_FALSE;
    852                 kHlpAssert(pCur->cRefs == 1);
     1296                {
     1297                    /*
     1298                     * Create the entry (not linked yet).
     1299                     */
     1300                    pCur = kFsCacheCreateObjectW(pCache, pDir, pwchFilename, uPtr.pNoId->FileNameLength / sizeof(wchar_t),
     1301#ifdef KFSCACHE_CFG_SHORT_NAMES
     1302                                                 uPtr.pNoId->ShortName, uPtr.pNoId->ShortNameLength / sizeof(wchar_t),
     1303#endif
     1304                                                 bObjType, penmError);
     1305                    if (!pCur)
     1306                        return K_FALSE;
     1307                    kHlpAssert(pCur->cRefs == 1);
     1308                }
    8531309
    8541310#ifdef KFSCACHE_CFG_SHORT_NAMES
     
    8671323
    8681324                /*
    869                  * If we're updating we have to check the data.
     1325                 * Add the entry to the directory.
    8701326                 */
    871                 if (fRefreshing)
     1327                fRc = kFsCacheDirAddChild(pCache, pDir, pCur, penmError);
     1328                kFsCacheObjRelease(pCache, pCur);
     1329                if (fRc)
     1330                { /* likely */ }
     1331                else
    8721332                {
    873                     __debugbreak();
    874                 }
    875 
    876                 /*
    877                  * If we've still got pCur, add it to the directory.
    878                  */
    879                 if (pCur)
    880                 {
    881                     KBOOL fRc = kFsCacheDirAddChild(pCache, pDir, pCur, penmError);
    882                     kFsCacheObjRelease(pCache, pCur);
    883                     if (fRc)
    884                     { /* likely */ }
    885                     else
    886                         return K_FALSE;
     1333                    rcNt = STATUS_NO_MEMORY;
     1334                    break;
    8871335                }
    8881336            }
     
    9291377                                         enmInfoClass,
    9301378                                         FALSE,     /* fReturnSingleEntry */
    931                                          NULL,      /* Filter / restart pos. */
     1379                                         &UniStrStar, /* Filter / restart pos. */
    9321380                                         FALSE);    /* fRestartScan */
    9331381    }
     
    9351383    if (rcNt == MY_STATUS_NO_MORE_FILES)
    9361384    {
     1385        /*
     1386         * If refreshing, add missing children objects and ditch the rest.
     1387         * We ignore errors while adding missing children (lazy bird).
     1388         */
     1389        if (!fRefreshing)
     1390        { /* more likely */ }
     1391        else
     1392        {
     1393            while (DirRePop.cOldChildren > 0)
     1394            {
     1395                KFSLOOKUPERROR enmErrorIgn;
     1396                PKFSOBJ pOldChild = DirRePop.papOldChildren[--DirRePop.cOldChildren];
     1397                if (pOldChild->bObjType == KFSOBJ_TYPE_MISSING)
     1398                    kFsCacheDirAddChild(pCache, pDir, pOldChild, &enmErrorIgn);
     1399                else
     1400                {
     1401                    KFSCACHE_LOG(("Refreshing %s/%s/ - %s was removed.\n",
     1402                                  pDir->Obj.pParent->Obj.pszName, pDir->Obj.pszName, pOldChild->pszName));
     1403                    kHlpAssert(pOldChild->bObjType != KFSOBJ_TYPE_DIR);
     1404                }
     1405                kFsCacheObjRelease(pCache, pOldChild);
     1406            }
     1407            kHlpFree(DirRePop.papOldChildren);
     1408        }
     1409
    9371410        /*
    9381411         * Mark the directory as fully populated and up to date.
    9391412         */
    940         pDir->fPopulated = K_TRUE;
     1413        pDir->fPopulated        = K_TRUE;
     1414        pDir->fNeedRePopulating = K_FALSE;
    9411415        if (pDir->Obj.uCacheGen != KFSOBJ_CACHE_GEN_IGNORE)
    9421416            pDir->Obj.uCacheGen = pCache->uGeneration;
    9431417        return K_TRUE;
     1418    }
     1419
     1420    /*
     1421     * If we failed during refresh, add back remaining old children.
     1422     */
     1423    if (!fRefreshing)
     1424    {
     1425        while (DirRePop.cOldChildren > 0)
     1426        {
     1427            KFSLOOKUPERROR enmErrorIgn;
     1428            PKFSOBJ pOldChild = DirRePop.papOldChildren[--DirRePop.cOldChildren];
     1429            kFsCacheDirAddChild(pCache, pDir, pOldChild, &enmErrorIgn);
     1430            kFsCacheObjRelease(pCache, pOldChild);
     1431        }
     1432        kHlpFree(DirRePop.papOldChildren);
    9441433    }
    9451434
     
    10691558
    10701559
     1560/**
     1561 * Generic object refresh.
     1562 *
     1563 * This does not refresh the content of directories.
     1564 *
     1565 * @returns K_TRUE on success.  K_FALSE and *penmError on failure.
     1566 * @param   pCache              The cache.
     1567 * @param   pObj                The object.
     1568 * @param   penmError           Where to return error info.
     1569 */
    10711570static KBOOL kFsCacheRefreshObj(PKFSCACHE pCache, PKFSOBJ pObj, KFSLOOKUPERROR *penmError)
    10721571{
     
    11311630            }
    11321631#else
    1133             /* This alternative lets us keep the inode number up to date. */
     1632            /* This alternative lets us keep the inode number up to date and
     1633               detect name case changes. */
    11341634            MY_UNICODE_STRING    UniStr;
    11351635# ifdef KFSCACHE_CFG_SHORT_NAMES
     
    12001700            }
    12011701#endif
     1702            if (MY_NT_SUCCESS(rcNt))
     1703            {
     1704                pObj->uCacheGen = pCache->uGeneration;
     1705                fRc = K_TRUE;
     1706            }
     1707            else
     1708            {
     1709                /* ouch! */
     1710                kHlpAssertMsgFailed(("%#x\n", rcNt));
     1711                __debugbreak();
     1712                fRc = K_FALSE;
     1713            }
    12021714        }
    12031715        else
     
    12271739                                             / BIRD_STAT_BLOCK_SIZE;
    12281740
    1229                 if (   pDir->iLastWrite -= uBuf.FullInfo.LastWriteTime.QuadPart
     1741                if (   pDir->iLastWrite == uBuf.FullInfo.LastWriteTime.QuadPart
    12301742                    && (pObj->fFlags & KFSOBJ_F_WORKING_DIR_MTIME) )
    12311743                    KFSCACHE_LOG(("Refreshing %s/%s/ - no re-populating necessary.\n",
     
    12461758                }
    12471759            }
    1248 
    1249         }
    1250         if (MY_NT_SUCCESS(rcNt))
    1251         {
    1252             pObj->uCacheGen = pCache->uGeneration;
    1253             fRc = K_TRUE;
    1254         }
    1255         else
    1256         {
    1257             /* ouch! */
    1258             kHlpAssertMsgFailed(("%#x\n", rcNt));
    1259             __debugbreak();
    1260             fRc = K_FALSE;
     1760            if (MY_NT_SUCCESS(rcNt))
     1761            {
     1762                pObj->uCacheGen = pCache->uGeneration;
     1763                fRc = K_TRUE;
     1764            }
     1765            else
     1766            {
     1767                /* ouch! */
     1768                kHlpAssertMsgFailed(("%#x\n", rcNt));
     1769                __debugbreak();
     1770                fRc = K_FALSE;
     1771            }
    12611772        }
    12621773    }
     
    15062017
    15072018/**
    1508  * For use when kFsCacheIAreEqualW hit's something non-trivial.
    1509  *
    1510  * @returns K_TRUE if equal, K_FALSE if different.
    1511  * @param   pwcName1            The first string.
    1512  * @param   pwcName2            The second string.
    1513  * @param   cwcName             The length of the two strings (in wchar_t's).
    1514  */
    1515 KBOOL kFsCacheIAreEqualSlowW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU16 cwcName)
    1516 {
    1517     MY_UNICODE_STRING UniStr1 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName1 };
    1518     MY_UNICODE_STRING UniStr2 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName2 };
    1519     return g_pfnRtlEqualUnicodeString(&UniStr1, &UniStr2, TRUE /*fCaseInsensitive*/);
    1520 }
    1521 
    1522 
    1523 /**
    1524  * Compares two UTF-16 strings in a case-insensitive fashion.
    1525  *
    1526  * You would think we should be using _wscnicmp here instead, however it is
    1527  * locale dependent and defaults to ASCII upper/lower handling setlocale hasn't
    1528  * been called.
    1529  *
    1530  * @returns K_TRUE if equal, K_FALSE if different.
    1531  * @param   pwcName1            The first string.
    1532  * @param   pwcName2            The second string.
    1533  * @param   cwcName             The length of the two strings (in wchar_t's).
    1534  */
    1535 K_INLINE KBOOL kFsCacheIAreEqualW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU32 cwcName)
    1536 {
    1537     while (cwcName > 0)
    1538     {
    1539         wchar_t wc1 = *pwcName1;
    1540         wchar_t wc2 = *pwcName2;
    1541         if (wc1 == wc2)
    1542         { /* not unlikely */ }
    1543         else if (  (KU16)wc1 < (KU16)0xc0 /* U+00C0 is the first upper/lower letter after 'z'. */
    1544                 && (KU16)wc2 < (KU16)0xc0)
    1545         {
    1546             /* ASCII upper case. */
    1547             if ((KU16)wc1 - (KU16)0x61 < (KU16)26)
    1548                 wc1 &= ~(wchar_t)0x20;
    1549             if ((KU16)wc2 - (KU16)0x61 < (KU16)26)
    1550                 wc2 &= ~(wchar_t)0x20;
    1551             if (wc1 != wc2)
    1552                 return K_FALSE;
    1553         }
    1554         else
    1555             return kFsCacheIAreEqualSlowW(pwcName1, pwcName2, (KU16)cwcName);
    1556 
    1557         pwcName2++;
    1558         pwcName1++;
    1559         cwcName--;
    1560     }
    1561 
    1562     return K_TRUE;
    1563 }
    1564 
    1565 
    1566 /**
    15672019 * Look up a child node, UTF-16 version.
    15682020 *
     
    27013153    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
    27023154
     3155    KFSCACHE_LOG(("Destroying %s/%s, type=%d\n", pObj->pParent ? pObj->pParent->Obj.pszName : "", pObj->pszName, pObj->bObjType));
     3156__debugbreak();
     3157
    27033158    /*
    27043159     * Invalidate the structure.
     
    32433698#endif
    32443699        pCache->RootDir.cChildren           = 0;
     3700        pCache->RootDir.cChildrenAllocated  = 0;
    32453701        pCache->RootDir.papChildren         = NULL;
    32463702        pCache->RootDir.hDir                = INVALID_HANDLE_VALUE;
  • trunk/src/lib/nt/kFsCache.h

    r2862 r2863  
    221221    /** The number of child objects. */
    222222    KU32                cChildren;
    223 
     223    /** The allocated size of papChildren. */
     224    KU32                cChildrenAllocated;
     225
     226    /** Pointer to the hash table.
     227     * @todo this isn't quite there yet, structure wise. sigh.  */
     228    PKFSOBJHASH         paHashTab;
    224229    /** The size of the hash table.
    225230     * @remarks The hash table is optional and only used when there are a lot of
    226231     *          entries in the directory. */
    227232    KU32                cHashTab;
    228     /** Pointer to the hash table.
    229      * @todo this isn't quite there yet, structure wise. sigh.  */
    230     PKFSOBJHASH         paHashTab;
    231233
    232234    /** Handle to the directory (we generally keep it open). */
Note: See TracChangeset for help on using the changeset viewer.