Ignore:
Timestamp:
Nov 6, 2016, 12:18:51 AM (9 years ago)
Author:
bird
Message:

fts-nt.c: Wide char support, part 3.

File:
1 edited

Legend:

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

    r2985 r3004  
    242242/**
    243243 * Implements readdir_r().
     244 *
     245 * @remarks birdDirReadReentrantW is a copy of this.  Keep them in sync!
    244246 */
    245247int birdDirReadReentrant(BirdDir_T *pDir, BirdDirEntry_T *pEntry, BirdDirEntry_T **ppResult)
     
    371373{
    372374    BirdDirEntry_T *pRet = NULL;
    373     birdDirReadReentrant(pDir, &pDir->DirEntry, &pRet);
     375    birdDirReadReentrant(pDir, &pDir->u.DirEntry, &pRet);
     376    return pRet;
     377}
     378
     379
     380static int birdDirCopyNameToEntryW(WCHAR const *pwcName, ULONG cbName, BirdDirEntryW_T *pEntry)
     381{
     382    ULONG cwcName = cbName / sizeof(wchar_t);
     383    if (cwcName < sizeof(pEntry->d_name))
     384    {
     385        memcpy(pEntry->d_name, pwcName, cbName);
     386        pEntry->d_name[cwcName] = '\0';
     387        pEntry->d_namlen = (unsigned __int16)cwcName;
     388        pEntry->d_reclen = (unsigned __int16)((size_t)&pEntry->d_name[cwcName + 1] - (size_t)pEntry);
     389        return 0;
     390    }
     391    return -1;
     392}
     393
     394
     395/**
     396 * Implements readdir_r(), UTF-16 version.
     397 *
     398 * @remarks This is a copy of birdDirReadReentrant where only the name handling
     399 *          and entry type differs.  Remember to keep them in sync!
     400 */
     401int birdDirReadReentrantW(BirdDir_T *pDir, BirdDirEntryW_T *pEntry, BirdDirEntryW_T **ppResult)
     402{
     403    int fSkipEntry;
     404
     405    *ppResult = NULL;
     406
     407    if (!pDir || pDir->uMagic != BIRD_DIR_MAGIC)
     408        return birdSetErrnoToBadFileNo();
     409
     410    do
     411    {
     412        ULONG offNext;
     413        ULONG cbMinCur;
     414
     415        /*
     416         * Read more?
     417         */
     418        if (!pDir->fHaveData)
     419        {
     420            if (birdDirReadMore(pDir) != 0)
     421                return -1;
     422            if (!pDir->fHaveData)
     423                return 0;
     424        }
     425
     426        /*
     427         * Convert the NT data to the unixy output structure.
     428         */
     429        fSkipEntry = 0;
     430        switch (pDir->iInfoClass)
     431        {
     432            case MyFileNamesInformation:
     433            {
     434                MY_FILE_NAMES_INFORMATION *pInfo = (MY_FILE_NAMES_INFORMATION *)&pDir->pabBuf[pDir->offBuf];
     435                if (   pDir->offBuf          >= pDir->cbBuf - MIN_SIZEOF_MY_FILE_NAMES_INFORMATION
     436                    || pInfo->FileNameLength >= pDir->cbBuf
     437                    || pDir->offBuf + pInfo->FileNameLength + MIN_SIZEOF_MY_FILE_NAMES_INFORMATION > pDir->cbBuf)
     438                {
     439                    fSkipEntry = 1;
     440                    pDir->fHaveData = 0;
     441                    continue;
     442                }
     443
     444                memset(&pEntry->d_stat, 0, sizeof(pEntry->d_stat));
     445                pEntry->d_stat.st_mode  = S_IFMT;
     446                pEntry->d_type          = DT_UNKNOWN;
     447                pEntry->d_reclen        = 0;
     448                pEntry->d_namlen        = 0;
     449                if (birdDirCopyNameToEntryW(pInfo->FileName, pInfo->FileNameLength, pEntry) != 0)
     450                    fSkipEntry = 1;
     451
     452                cbMinCur = MIN_SIZEOF_MY_FILE_NAMES_INFORMATION + pInfo->FileNameLength;
     453                offNext  = pInfo->NextEntryOffset;
     454                break;
     455            }
     456
     457            case MyFileIdFullDirectoryInformation:
     458            {
     459                MY_FILE_ID_FULL_DIR_INFORMATION *pInfo = (MY_FILE_ID_FULL_DIR_INFORMATION *)&pDir->pabBuf[pDir->offBuf];
     460                if (   pDir->offBuf          >= pDir->cbBuf - MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION
     461                    || pInfo->FileNameLength >= pDir->cbBuf
     462                    || pDir->offBuf + pInfo->FileNameLength + MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION > pDir->cbBuf)
     463                {
     464                    fSkipEntry = 1;
     465                    pDir->fHaveData = 0;
     466                    continue;
     467                }
     468
     469                pEntry->d_type          = DT_UNKNOWN;
     470                pEntry->d_reclen        = 0;
     471                pEntry->d_namlen        = 0;
     472                if (birdDirCopyNameToEntryW(pInfo->FileName, pInfo->FileNameLength, pEntry) != 0)
     473                    fSkipEntry = 1;
     474                birdStatFillFromFileIdFullDirInfo(&pEntry->d_stat, pInfo, NULL);
     475                pEntry->d_stat.st_dev   = pDir->uDev;
     476                switch (pEntry->d_stat.st_mode & S_IFMT)
     477                {
     478                    case S_IFREG:       pEntry->d_type = DT_REG; break;
     479                    case S_IFDIR:       pEntry->d_type = DT_DIR; break;
     480                    case S_IFLNK:       pEntry->d_type = DT_LNK; break;
     481                    case S_IFIFO:       pEntry->d_type = DT_FIFO; break;
     482                    case S_IFCHR:       pEntry->d_type = DT_CHR; break;
     483                    default:
     484#ifndef NDEBUG
     485                        __debugbreak();
     486#endif
     487                        pEntry->d_type = DT_UNKNOWN;
     488                        break;
     489                }
     490
     491                cbMinCur = MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION + pInfo->FileNameLength;
     492                offNext  = pInfo->NextEntryOffset;
     493                break;
     494            }
     495
     496            default:
     497                return birdSetErrnoToBadFileNo();
     498        }
     499
     500        /*
     501         * Advance.
     502         */
     503        if (   offNext >= cbMinCur
     504            && offNext < pDir->cbBuf)
     505            pDir->offBuf += offNext;
     506        else
     507        {
     508            pDir->fHaveData = 0;
     509            pDir->offBuf    = pDir->cbBuf;
     510        }
     511        pDir->offPos++;
     512    } while (fSkipEntry);
     513
     514
     515    /*
     516     * Successful return.
     517     */
     518    *ppResult = pEntry;
     519    return 0;
     520}
     521
     522/**
     523 * Implements readdir().
     524 */
     525BirdDirEntryW_T *birdDirReadW(BirdDir_T *pDir)
     526{
     527    BirdDirEntryW_T *pRet = NULL;
     528    birdDirReadReentrantW(pDir, &pDir->u.DirEntryW, &pRet);
    374529    return pRet;
    375530}
Note: See TracChangeset for help on using the changeset viewer.