Changeset 3004 for trunk/src/lib/nt


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

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

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

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/fts-nt.c

    r3002 r3004  
    9090static FTSENT   *fts_alloc_ansi(FTS *sp, char const *name, size_t namelen);
    9191static FTSENT   *fts_alloc_utf16(FTS *sp, wchar_t const *wcsname, size_t cwcname);
     92static void      nt_fts_free_alloc_cache(FTS *sp);
    9293static FTSENT   *fts_build(FTS *, int);
    9394static void      fts_lfree(FTSENT *);
     
    117118#define MAX(a, b)  ( (a) >= (b) ? (a) : (b) )
    118119
    119 #define FTS_NT_DUMMY_SYMFD_VALUE        ((HANDLE)~(intptr_t)(2)) /* current process */
     120#define FTS_WITH_ALLOC_CACHE
     121/** Number of size buckets for the FTSENT allocation cache. */
     122#define FTS_NUM_FREE_BUCKETS    64
     123/** Shift for converting size to free bucket index. */
     124#define FTS_FREE_BUCKET_SHIFT   4
     125/** The FTSENT allocation alignment. */
     126#define FTS_ALIGN_FTSENT        (1U << FTS_FREE_BUCKET_SHIFT)
     127/** Enables allocation statistics. */
     128//#define FTS_WITH_STATISTICS
    120129
    121130/*
     
    126135struct _fts_private {
    127136        FTS             ftsp_fts;
     137#ifdef FTS_WITH_ALLOC_CACHE
     138        /** Number of free entries in the above buckets. */
     139        size_t          numfree;
     140# ifdef FTS_WITH_STATISTICS
     141        size_t          allocs;
     142        size_t          hits;
     143        size_t          misses;
     144# endif
     145        /** Free FTSENT buckets (by size).
     146         * This is to avoid hitting the heap, which is a little sluggish on windows. */
     147        struct
     148        {
     149                FTSENT          *head;
     150        } freebuckets[FTS_NUM_FREE_BUCKETS];
     151#endif
    128152};
    129153
     
    338362}
    339363
     364
    340365int FTSCALL
    341366nt_fts_close(FTS *sp)
     
    365390        free(sp->fts_path);
    366391        free(sp->fts_wcspath);
     392#ifdef FTS_WITH_ALLOC_CACHE
     393# ifdef FTS_WITH_STATISTICS
     394        {
     395                struct _fts_private *priv = (struct _fts_private *)sp;
     396                fprintf(stderr, "numfree=%u allocs=%u  hits=%u (%uppt)  misses=%u (%uppt)  other=%u\n",
     397                        priv->numfree, priv->allocs,
     398                        priv->hits,   (unsigned)((double)priv->hits   * 1000.0 / priv->allocs),
     399                        priv->misses, (unsigned)((double)priv->misses * 1000.0 / priv->allocs),
     400                        priv->allocs - priv->misses - priv->hits);
     401        }
     402# endif
     403#endif
     404        nt_fts_free_alloc_cache(sp);
    367405
    368406        /* Free up the stream pointer. */
     
    371409}
    372410
     411
     412/**
     413 * Frees a FTSENT structure by way of the allocation cache.
     414 */
     415static void
     416fts_free_entry(FTS *sp, FTSENT *tmp)
     417{
     418        if (tmp != NULL) {
     419                struct _fts_private *priv = (struct _fts_private *)sp;
     420#ifdef FTS_WITH_ALLOC_CACHE
     421                size_t idx;
     422#endif
     423
     424                if (tmp->fts_dirfd == INVALID_HANDLE_VALUE) {
     425                        /* There are probably more files than directories out there. */
     426                } else {
     427                        birdCloseFile(tmp->fts_dirfd);
     428                        tmp->fts_dirfd = INVALID_HANDLE_VALUE;
     429                }
     430
     431#ifdef FTS_WITH_ALLOC_CACHE
     432                idx = (tmp->fts_alloc_size - sizeof(FTSENT)) >> FTS_FREE_BUCKET_SHIFT;
     433                if (idx < FTS_NUM_FREE_BUCKETS) {
     434                        tmp->fts_link = priv->freebuckets[idx].head;
     435                        priv->freebuckets[idx].head = tmp;
     436                } else {
     437                        tmp->fts_link = priv->freebuckets[FTS_NUM_FREE_BUCKETS - 1].head;
     438                        priv->freebuckets[FTS_NUM_FREE_BUCKETS - 1].head = tmp;
     439                }
     440
     441                priv->numfree++;
     442#else
     443                free(tmp);
     444#endif
     445        }
     446}
     447
     448
    373449/*
    374450 * Special case of "/" at the end of the path so that slashes aren't
     
    377453#define NAPPEND(p)  ( p->fts_pathlen - (p->fts_path[p->fts_pathlen - 1]    ==  '/') )
    378454#define NAPPENDW(p) ( p->fts_cwcpath - (p->fts_wcspath[p->fts_cwcpath - 1] == L'/') )
    379 
    380 static void
    381 fts_free_entry(FTSENT *tmp)
    382 {
    383     if (tmp != NULL) {
    384                 if (tmp->fts_dirfd != INVALID_HANDLE_VALUE) {
    385                         birdCloseFile(tmp->fts_dirfd);
    386                         tmp->fts_dirfd = INVALID_HANDLE_VALUE;
    387                 }
    388                 free(tmp);
    389     }
    390 }
    391455
    392456FTSENT * FTSCALL
     
    420484         * pointer, follow fails.
    421485         *
    422          * NT: Since we don't change directory, we just set fts_symfd to a
    423          *     placeholder value handle value here in case a API client
    424          *     checks it. Ditto FTS_SYMFOLLOW.
     486         * NT: Since we don't change directory, we just set FTS_SYMFOLLOW
     487         *     here in case a API client checks it.
    425488         */
    426489        if (instr == FTS_FOLLOW &&
     
    428491                p->fts_info = fts_stat(sp, p, 1, INVALID_HANDLE_VALUE);
    429492                if (p->fts_info == FTS_D /*&& !ISSET(FTS_NOCHDIR)*/) {
    430                         p->fts_symfd = FTS_NT_DUMMY_SYMFD_VALUE;
    431493                        p->fts_flags |= FTS_SYMFOLLOW;
    432494                }
     
    439501                if (instr == FTS_SKIP ||
    440502                    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
    441                         if (p->fts_flags & FTS_SYMFOLLOW) {
    442                                 p->fts_symfd = INVALID_HANDLE_VALUE;
    443                         }
    444503                        if (sp->fts_child) {
    445504                                fts_lfree(sp->fts_child);
     
    489548                 */
    490549                if (p->fts_level == FTS_ROOTLEVEL) {
    491                         fts_free_entry(tmp);
     550                        fts_free_entry(sp, tmp);
    492551                        fts_load(sp, p);
    493552                        return (sp->fts_cur = p);
     
    500559                 */
    501560                if (p->fts_instr == FTS_SKIP) {
    502                         fts_free_entry(tmp);
     561                        fts_free_entry(sp, tmp);
    503562                        goto next;
    504563                }
    505564                if (p->fts_instr == FTS_FOLLOW) {
    506565                        p->fts_info = fts_stat(sp, p, 1, INVALID_HANDLE_VALUE);
    507                         /* NT: See above regarding fts_symfd. */
    508                         if (p->fts_info == FTS_D /*&& !ISSET(FTS_NOCHDIR)*/) {
    509                                 p->fts_symfd = FTS_NT_DUMMY_SYMFD_VALUE;
     566                        /* NT: See above regarding fts_flags. */
     567                        if (p->fts_info == FTS_D) {
    510568                                p->fts_flags |= FTS_SYMFOLLOW;
    511569                        }
     
    513571                }
    514572
    515                 fts_free_entry(tmp);
     573                fts_free_entry(sp, tmp);
    516574
    517575name:
     
    535593                 * can distinguish between error and EOF.
    536594                 */
    537                 fts_free_entry(tmp);
    538                 fts_free_entry(p);
     595                fts_free_entry(sp, tmp);
     596                fts_free_entry(sp, p);
    539597                errno = 0;
    540598                return (sp->fts_cur = NULL);
     
    551609         * one directory.
    552610         *
    553          * NT: We're doing no fchdir, but we need to close the directory handle
    554          *     and clear fts_symfd now.
    555          */
    556         if (p->fts_flags & FTS_SYMFOLLOW)
    557                 p->fts_symfd = INVALID_HANDLE_VALUE;
     611         * NT: We're doing no fchdir, but we need to close the directory handle.
     612         */
    558613        if (p->fts_dirfd != INVALID_HANDLE_VALUE) {
    559614                birdCloseFile(p->fts_dirfd);
    560615                p->fts_dirfd = INVALID_HANDLE_VALUE;
    561616        }
    562         fts_free_entry(tmp);
     617        fts_free_entry(sp, tmp);
    563618        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
    564619        return (sp->fts_cur = p);
     
    685740fts_build(FTS *sp, int type)
    686741{
    687         BirdDirEntry_T *dp;
    688         FTSENT *p, *head;
    689         FTSENT *cur, *tail;
     742        BirdDirEntryW_T *dp;
     743        FTSENT *p, *head, *cur, **tailp;
    690744        DIR *dirp;
    691745        int saved_errno, doadjust, doadjust_utf16;
     
    751805         */
    752806        if (sp->fts_options & FTS_NO_ANSI) {
    753                 len = maxlen = 0;
     807                len = 0;
     808                maxlen = 0x10000;
    754809        } else {
    755810                len = NAPPEND(cur);
     
    766821        /* Read the directory, attaching each entry to the `link' pointer. */
    767822        doadjust = doadjust_utf16 = 0;
    768         for (head = tail = NULL, nitems = 0; dirp && (dp = birdDirRead(dirp));) {
    769                 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
     823        nitems = 0;
     824        head = NULL;
     825        tailp = &head;
     826        while ((dp = birdDirReadW(dirp)) != NULL) {
     827                if (ISSET(FTS_SEEDOT) || !ISDOT(dp->d_name))  {
     828                        /* assume dirs have two or more entries */
     829                } else {
    770830                        continue;
    771 
    772                 if ((p = fts_alloc_ansi(sp, dp->d_name, dp->d_namlen)) == NULL)
     831                }
     832
     833                if ((p = fts_alloc_utf16(sp, dp->d_name, dp->d_namlen)) != NULL) {
     834                        /* likely */
     835                } else {
    773836                        goto mem1;
    774 
    775                 if (p->fts_namelen >= maxlen
    776                  || p->fts_cwcname >= cwcmax) {  /* include space for NUL */
     837                }
     838
     839                /* include space for NUL */
     840                if (p->fts_namelen < maxlen && p->fts_cwcname < cwcmax) {
     841                    /* likely */
     842                } else {
    777843                        void *oldaddr = sp->fts_path;
    778844                        wchar_t *oldwcspath = sp->fts_wcspath;
    779845                        if (fts_palloc(sp,
    780                                                    p->fts_namelen >= maxlen ? len + p->fts_namelen + 1 : 0,
    781                                                    p->fts_cwcname >= cwcmax ? cwcdir + p->fts_cwcname + 1 : 0)) {
     846                                       p->fts_namelen >= maxlen ? len + p->fts_namelen + 1 : 0,
     847                                       p->fts_cwcname >= cwcmax ? cwcdir + p->fts_cwcname + 1 : 0)) {
     848mem1:
    782849                                /*
    783850                                 * No more memory for path or structures.  Save
     
    785852                                 * structures already allocated.
    786853                                 */
    787 mem1:                           saved_errno = errno;
     854                                saved_errno = errno;
    788855                                if (p)
    789856                                        free(p);
     
    815882                /* We walk in directory order so "ls -f" doesn't get upset. */
    816883                p->fts_link = NULL;
    817                 if (head == NULL)
    818                         head = tail = p;
    819                 else {
    820                         tail->fts_link = p;
    821                         tail = p;
    822                 }
     884                *tailp = p;
     885                tailp = &p->fts_link;
    823886                ++nitems;
    824887        }
     
    910973                p->fts_nlink = sbp->st_nlink;
    911974
    912                 if (ISDOT(p->fts_name))
     975                if (ISDOT(p->fts_wcsname))
    913976                        return (FTS_DOT);
    914977
     
    9861049fts_alloc(FTS *sp, char const *name, size_t namelen, wchar_t const *wcsname, size_t cwcname)
    9871050{
     1051        struct _fts_private *priv = (struct _fts_private *)sp;
    9881052        FTSENT *p;
    9891053        size_t len;
    990 
     1054#ifdef FTS_WITH_ALLOC_CACHE
     1055        size_t aligned;
     1056        size_t idx;
     1057#endif
     1058
     1059#if defined(FTS_WITH_STATISTICS) && defined(FTS_WITH_ALLOC_CACHE)
     1060        priv->allocs++;
     1061#endif
    9911062        /*
    9921063         * The file name is a variable length array.  Allocate the FTSENT
     
    9961067        if (!(sp->fts_options & FTS_NO_ANSI))
    9971068                len += namelen + 1;
     1069
     1070        /*
     1071         * To speed things up we cache entries.  This code is a little insane,
     1072         * but that's preferable to slow code.
     1073         */
     1074#ifdef FTS_WITH_ALLOC_CACHE
     1075        aligned = (len + FTS_ALIGN_FTSENT + 1) & ~(size_t)(FTS_ALIGN_FTSENT - 1);
     1076        idx     = ((aligned - sizeof(FTSENT)) >> FTS_FREE_BUCKET_SHIFT);
     1077        if (   idx < FTS_NUM_FREE_BUCKETS
     1078            && (p = priv->freebuckets[idx].head)
     1079            && p->fts_alloc_size >= len) {
     1080                priv->freebuckets[idx].head = p->fts_link;
     1081                priv->numfree--;
     1082# ifdef FTS_WITH_STATISTICS
     1083                priv->hits++;
     1084# endif
     1085
     1086        } else {
     1087# ifdef FTS_WITH_STATISTICS
     1088                priv->misses++;
     1089# endif
     1090                p = malloc(aligned);
     1091                if (p) {
     1092                        p->fts_alloc_size = (unsigned)aligned;
     1093                } else {
     1094                        nt_fts_free_alloc_cache(sp);
     1095                        p = malloc(len);
     1096                        if (!p)
     1097                                return NULL;
     1098                        p->fts_alloc_size = (unsigned)len;
     1099                }
     1100        }
     1101#else  /* !FTS_WITH_ALLOC_CACHE */
    9981102        p = malloc(len);
    9991103        if (p) {
    1000                 /* Copy the names and guarantee NUL termination. */
    1001                 p->fts_wcsname = (wchar_t *)(p + 1);
    1002                 memcpy(p->fts_wcsname, wcsname, cwcname * sizeof(wchar_t));
    1003                 p->fts_wcsname[cwcname] = '\0';
    1004                 p->fts_cwcname = cwcname;
    1005                 if (!(sp->fts_options & FTS_NO_ANSI)) {
    1006                         p->fts_name = (char *)(p->fts_wcsname + cwcname + 1);
    1007                         memcpy(p->fts_name, name, namelen);
    1008                         p->fts_name[namelen] = '\0';
    1009                         p->fts_namelen = namelen;
    1010                 } else {
    1011                         p->fts_name = NULL;
    1012                         p->fts_namelen = 0;
    1013                 }
    1014 
    1015                 p->fts_path = sp->fts_path;
    1016                 p->fts_wcspath = sp->fts_wcspath;
    1017                 p->fts_statp = &p->fts_stat;
    1018                 p->fts_errno = 0;
    1019                 p->fts_flags = 0;
    1020                 p->fts_instr = FTS_NOINSTR;
    1021                 p->fts_number = 0;
    1022                 p->fts_pointer = NULL;
    1023                 p->fts_fts = sp;
    1024                 p->fts_symfd = INVALID_HANDLE_VALUE;
    1025                 p->fts_dirfd = INVALID_HANDLE_VALUE;
    1026         }
     1104                p->fts_alloc_size = (unsigned)len;
     1105        } else {
     1106                return NULL;
     1107        }
     1108#endif /* !FTS_WITH_ALLOC_CACHE */
     1109
     1110        /* Copy the names and guarantee NUL termination. */
     1111        p->fts_wcsname = (wchar_t *)(p + 1);
     1112        memcpy(p->fts_wcsname, wcsname, cwcname * sizeof(wchar_t));
     1113        p->fts_wcsname[cwcname] = '\0';
     1114        p->fts_cwcname = cwcname;
     1115        if (!(sp->fts_options & FTS_NO_ANSI)) {
     1116                p->fts_name = (char *)(p->fts_wcsname + cwcname + 1);
     1117                memcpy(p->fts_name, name, namelen);
     1118                p->fts_name[namelen] = '\0';
     1119                p->fts_namelen = namelen;
     1120        } else {
     1121                p->fts_name = NULL;
     1122                p->fts_namelen = 0;
     1123        }
     1124
     1125        p->fts_path = sp->fts_path;
     1126        p->fts_wcspath = sp->fts_wcspath;
     1127        p->fts_statp = &p->fts_stat;
     1128        p->fts_errno = 0;
     1129        p->fts_flags = 0;
     1130        p->fts_instr = FTS_NOINSTR;
     1131        p->fts_number = 0;
     1132        p->fts_pointer = NULL;
     1133        p->fts_fts = sp;
     1134        p->fts_dirfd = INVALID_HANDLE_VALUE;
    10271135        return (p);
    10281136}
     
    10681176 * @returns Pointer to allocated and mostly initialized FTSENT structure on
    10691177 *          success.  NULL on failure, caller needs to record it.
    1070  * @param   sp                  Pointer to FTS instance.
     1178 * @param   sp                  Pointer to the FTS instance.
    10711179 * @param   wcsname             The UTF-16 name.
    10721180 * @param   cwcname             The UTF-16 name length.
     
    10991207        }
    11001208        return pRet;
     1209}
     1210
     1211
     1212/**
     1213 * Frees up the FTSENT allocation cache.
     1214 *
     1215 * Used by nt_fts_close, but also called by fts_alloc on alloc failure.
     1216 *
     1217 * @param   sp                  Pointer to the FTS instance.
     1218 */
     1219static void nt_fts_free_alloc_cache(FTS *sp)
     1220{
     1221#ifdef FTS_WITH_ALLOC_CACHE
     1222        struct _fts_private *priv = (struct _fts_private *)sp;
     1223        unsigned i = K_ELEMENTS(priv->freebuckets);
     1224        while (i-- > 0) {
     1225                FTSENT *cur = priv->freebuckets[i].head;
     1226                priv->freebuckets[i].head = NULL;
     1227                while (cur) {
     1228                        FTSENT *freeit = cur;
     1229                        cur = cur->fts_link;
     1230                        free(freeit);
     1231                }
     1232        }
     1233        priv->numfree = 0;
     1234#else
     1235        (void)sp;
     1236#endif
    11011237}
    11021238
  • trunk/src/lib/nt/fts-nt.h

    r2998 r3004  
    8383#define FTS_WHITEOUT    0x080           /* return whiteout information */
    8484#endif
    85 #define FTS_OPTIONMASK  0x0ff           /* valid user option mask */
     85#define FTS_NO_ANSI     0x40000000      /* NT: No ansi name or access path. */
     86#define FTS_OPTIONMASK  0x400000ff      /* valid user option mask */
    8687
    8788#define FTS_NAMEONLY    0x100           /* (private) child names only */
    8889#define FTS_STOP        0x200           /* (private) unrecoverable error */
    89 #define FTS_NO_ANSI     0x40000000      /* NT: No ansi name or access path. */
    9090        int fts_options;                /* fts_open options, global flags */
    9191        void *fts_clientptr;            /* thunk for sort function */
     
    104104        wchar_t *fts_wcspath;           /* NT: UTF-16 root path */
    105105        int fts_errno;                  /* errno for this node */
    106         fts_fd_t fts_symfd;             /* NT: Normally -1; -2 we followed this symlinked dir */
     106        size_t fts_alloc_size;          /* internal - size of the allocation for this entry. */
    107107        fts_fd_t fts_dirfd;             /* NT: Handle to the directory (NT_FTS_)INVALID_HANDLE_VALUE if not valid */
    108108        size_t fts_pathlen;             /* strlen(fts_path) */
     
    111111        size_t fts_cwcname;             /* NT: length of fts_wcsname. */
    112112
    113         fts_nlink_t fts_nlink;          /* link count */
    114113        fts_ino_t fts_ino;              /* inode */
    115114        fts_dev_t fts_dev;              /* device */
     115        fts_nlink_t fts_nlink;          /* link count */
    116116
    117117#define FTS_ROOTPARENTLEVEL     -1
  • 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}
  • trunk/src/lib/nt/ntdir.h

    r2985 r3004  
    4949    char                d_name[512 - sizeof(BirdStat_T) - 2 - 2 - 1];
    5050} BirdDirEntry_T;
     51
     52typedef struct direntw
     53{
     54    /** Optional stat information.
     55     * Only provided if using birdDirOpenExtraInfo(). */
     56    BirdStat_T          d_stat;
     57    /** The record length. */
     58    unsigned __int16    d_reclen;
     59    /** The name length (in wchar_t). */
     60    unsigned __int16    d_namlen;
     61    /** The name type. */
     62    unsigned char       d_type;
     63    /** The name. */
     64    wchar_t             d_name[512 - sizeof(BirdStat_T) - 2 - 2 - 1];
     65} BirdDirEntryW_T;
    5166
    5267#define d_ino           d_stat.st_ino;
     
    104119
    105120    /** Static directory entry. */
    106     BirdDirEntry_T      DirEntry;
     121    union
     122    {
     123        BirdDirEntry_T  DirEntry;
     124        BirdDirEntryW_T DirEntryW;
     125    } u;
    107126} BirdDir_T;
    108127/** Magic value for BirdDir. */
     
    115134BirdDir_T      *birdDirOpenFromHandle(void *hDir, const void *pvReserved, unsigned fFlags);
    116135BirdDirEntry_T *birdDirRead(BirdDir_T *pDir);
     136BirdDirEntryW_T *birdDirReadW(BirdDir_T *pDir);
    117137long            birdDirTell(BirdDir_T *pDir);
    118138void            birdDirSeek(BirdDir_T *pDir, long offDir);
  • trunk/src/lib/nt/tstNtFts.c

    r2991 r3004  
    7171            if (chOpt == '-')
    7272            {
    73                 chOpt = *pszArg++;
    7473                if (!chOpt)
    7574                {
     
    9998                else if (strcmp(pszArg, "verbose") == 0)
    10099                    chOpt = 'v';
     100                else if (strcmp(pszArg, "no-ansi") == 0)
     101                    chOpt = 'w';
    101102                else
    102103                {
    103                     fprintf(stderr, "syntax error: Unknown option: --%s\n", pszArg);
     104                    fprintf(stderr, "syntax error: Unknown option: %s (%s)\n", argv[i], pszArg);
    104105                    return 2;
    105106                }
     
    137138                    case 'x':
    138139                        fFtsFlags |= FTS_XDEV;
     140                        break;
     141                    case 'w':
     142                        fFtsFlags |= FTS_NO_ANSI;
    139143                        break;
    140144                    case 'L':
     
    206210
    207211                if (cVerbosity > 0)
    208                     printf("%8s %s\n", pszState, pFtsEnt->fts_accpath);
     212                {
     213                    if (fFtsFlags & FTS_NO_ANSI)
     214                        printf("%8s %ls\n", pszState, pFtsEnt->fts_wcsaccpath);
     215                    else
     216                        printf("%8s %s\n", pszState, pFtsEnt->fts_accpath);
     217                }
    209218                if (   pFtsEnt->fts_info == FTS_SL
    210219                    && pFtsEnt->fts_number == 0
Note: See TracChangeset for help on using the changeset viewer.