Changeset 3004 for trunk/src/lib/nt
- Timestamp:
- Nov 6, 2016, 12:18:51 AM (9 years ago)
- Location:
- trunk/src/lib/nt
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/nt/fts-nt.c
r3002 r3004 90 90 static FTSENT *fts_alloc_ansi(FTS *sp, char const *name, size_t namelen); 91 91 static FTSENT *fts_alloc_utf16(FTS *sp, wchar_t const *wcsname, size_t cwcname); 92 static void nt_fts_free_alloc_cache(FTS *sp); 92 93 static FTSENT *fts_build(FTS *, int); 93 94 static void fts_lfree(FTSENT *); … … 117 118 #define MAX(a, b) ( (a) >= (b) ? (a) : (b) ) 118 119 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 120 129 121 130 /* … … 126 135 struct _fts_private { 127 136 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 128 152 }; 129 153 … … 338 362 } 339 363 364 340 365 int FTSCALL 341 366 nt_fts_close(FTS *sp) … … 365 390 free(sp->fts_path); 366 391 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); 367 405 368 406 /* Free up the stream pointer. */ … … 371 409 } 372 410 411 412 /** 413 * Frees a FTSENT structure by way of the allocation cache. 414 */ 415 static void 416 fts_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 373 449 /* 374 450 * Special case of "/" at the end of the path so that slashes aren't … … 377 453 #define NAPPEND(p) ( p->fts_pathlen - (p->fts_path[p->fts_pathlen - 1] == '/') ) 378 454 #define NAPPENDW(p) ( p->fts_cwcpath - (p->fts_wcspath[p->fts_cwcpath - 1] == L'/') ) 379 380 static void381 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 }391 455 392 456 FTSENT * FTSCALL … … 420 484 * pointer, follow fails. 421 485 * 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. 425 488 */ 426 489 if (instr == FTS_FOLLOW && … … 428 491 p->fts_info = fts_stat(sp, p, 1, INVALID_HANDLE_VALUE); 429 492 if (p->fts_info == FTS_D /*&& !ISSET(FTS_NOCHDIR)*/) { 430 p->fts_symfd = FTS_NT_DUMMY_SYMFD_VALUE;431 493 p->fts_flags |= FTS_SYMFOLLOW; 432 494 } … … 439 501 if (instr == FTS_SKIP || 440 502 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { 441 if (p->fts_flags & FTS_SYMFOLLOW) {442 p->fts_symfd = INVALID_HANDLE_VALUE;443 }444 503 if (sp->fts_child) { 445 504 fts_lfree(sp->fts_child); … … 489 548 */ 490 549 if (p->fts_level == FTS_ROOTLEVEL) { 491 fts_free_entry( tmp);550 fts_free_entry(sp, tmp); 492 551 fts_load(sp, p); 493 552 return (sp->fts_cur = p); … … 500 559 */ 501 560 if (p->fts_instr == FTS_SKIP) { 502 fts_free_entry( tmp);561 fts_free_entry(sp, tmp); 503 562 goto next; 504 563 } 505 564 if (p->fts_instr == FTS_FOLLOW) { 506 565 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) { 510 568 p->fts_flags |= FTS_SYMFOLLOW; 511 569 } … … 513 571 } 514 572 515 fts_free_entry( tmp);573 fts_free_entry(sp, tmp); 516 574 517 575 name: … … 535 593 * can distinguish between error and EOF. 536 594 */ 537 fts_free_entry( tmp);538 fts_free_entry( p);595 fts_free_entry(sp, tmp); 596 fts_free_entry(sp, p); 539 597 errno = 0; 540 598 return (sp->fts_cur = NULL); … … 551 609 * one directory. 552 610 * 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 */ 558 613 if (p->fts_dirfd != INVALID_HANDLE_VALUE) { 559 614 birdCloseFile(p->fts_dirfd); 560 615 p->fts_dirfd = INVALID_HANDLE_VALUE; 561 616 } 562 fts_free_entry( tmp);617 fts_free_entry(sp, tmp); 563 618 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; 564 619 return (sp->fts_cur = p); … … 685 740 fts_build(FTS *sp, int type) 686 741 { 687 BirdDirEntry_T *dp; 688 FTSENT *p, *head; 689 FTSENT *cur, *tail; 742 BirdDirEntryW_T *dp; 743 FTSENT *p, *head, *cur, **tailp; 690 744 DIR *dirp; 691 745 int saved_errno, doadjust, doadjust_utf16; … … 751 805 */ 752 806 if (sp->fts_options & FTS_NO_ANSI) { 753 len = maxlen = 0; 807 len = 0; 808 maxlen = 0x10000; 754 809 } else { 755 810 len = NAPPEND(cur); … … 766 821 /* Read the directory, attaching each entry to the `link' pointer. */ 767 822 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 { 770 830 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 { 773 836 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 { 777 843 void *oldaddr = sp->fts_path; 778 844 wchar_t *oldwcspath = sp->fts_wcspath; 779 845 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)) { 848 mem1: 782 849 /* 783 850 * No more memory for path or structures. Save … … 785 852 * structures already allocated. 786 853 */ 787 mem1:saved_errno = errno;854 saved_errno = errno; 788 855 if (p) 789 856 free(p); … … 815 882 /* We walk in directory order so "ls -f" doesn't get upset. */ 816 883 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; 823 886 ++nitems; 824 887 } … … 910 973 p->fts_nlink = sbp->st_nlink; 911 974 912 if (ISDOT(p->fts_ name))975 if (ISDOT(p->fts_wcsname)) 913 976 return (FTS_DOT); 914 977 … … 986 1049 fts_alloc(FTS *sp, char const *name, size_t namelen, wchar_t const *wcsname, size_t cwcname) 987 1050 { 1051 struct _fts_private *priv = (struct _fts_private *)sp; 988 1052 FTSENT *p; 989 1053 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 991 1062 /* 992 1063 * The file name is a variable length array. Allocate the FTSENT … … 996 1067 if (!(sp->fts_options & FTS_NO_ANSI)) 997 1068 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 */ 998 1102 p = malloc(len); 999 1103 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; 1027 1135 return (p); 1028 1136 } … … 1068 1176 * @returns Pointer to allocated and mostly initialized FTSENT structure on 1069 1177 * success. NULL on failure, caller needs to record it. 1070 * @param sp Pointer to FTS instance.1178 * @param sp Pointer to the FTS instance. 1071 1179 * @param wcsname The UTF-16 name. 1072 1180 * @param cwcname The UTF-16 name length. … … 1099 1207 } 1100 1208 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 */ 1219 static 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 1101 1237 } 1102 1238 -
trunk/src/lib/nt/fts-nt.h
r2998 r3004 83 83 #define FTS_WHITEOUT 0x080 /* return whiteout information */ 84 84 #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 */ 86 87 87 88 #define FTS_NAMEONLY 0x100 /* (private) child names only */ 88 89 #define FTS_STOP 0x200 /* (private) unrecoverable error */ 89 #define FTS_NO_ANSI 0x40000000 /* NT: No ansi name or access path. */90 90 int fts_options; /* fts_open options, global flags */ 91 91 void *fts_clientptr; /* thunk for sort function */ … … 104 104 wchar_t *fts_wcspath; /* NT: UTF-16 root path */ 105 105 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. */ 107 107 fts_fd_t fts_dirfd; /* NT: Handle to the directory (NT_FTS_)INVALID_HANDLE_VALUE if not valid */ 108 108 size_t fts_pathlen; /* strlen(fts_path) */ … … 111 111 size_t fts_cwcname; /* NT: length of fts_wcsname. */ 112 112 113 fts_nlink_t fts_nlink; /* link count */114 113 fts_ino_t fts_ino; /* inode */ 115 114 fts_dev_t fts_dev; /* device */ 115 fts_nlink_t fts_nlink; /* link count */ 116 116 117 117 #define FTS_ROOTPARENTLEVEL -1 -
trunk/src/lib/nt/ntdir.c
r2985 r3004 242 242 /** 243 243 * Implements readdir_r(). 244 * 245 * @remarks birdDirReadReentrantW is a copy of this. Keep them in sync! 244 246 */ 245 247 int birdDirReadReentrant(BirdDir_T *pDir, BirdDirEntry_T *pEntry, BirdDirEntry_T **ppResult) … … 371 373 { 372 374 BirdDirEntry_T *pRet = NULL; 373 birdDirReadReentrant(pDir, &pDir->DirEntry, &pRet); 375 birdDirReadReentrant(pDir, &pDir->u.DirEntry, &pRet); 376 return pRet; 377 } 378 379 380 static 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 */ 401 int 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 */ 525 BirdDirEntryW_T *birdDirReadW(BirdDir_T *pDir) 526 { 527 BirdDirEntryW_T *pRet = NULL; 528 birdDirReadReentrantW(pDir, &pDir->u.DirEntryW, &pRet); 374 529 return pRet; 375 530 } -
trunk/src/lib/nt/ntdir.h
r2985 r3004 49 49 char d_name[512 - sizeof(BirdStat_T) - 2 - 2 - 1]; 50 50 } BirdDirEntry_T; 51 52 typedef 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; 51 66 52 67 #define d_ino d_stat.st_ino; … … 104 119 105 120 /** Static directory entry. */ 106 BirdDirEntry_T DirEntry; 121 union 122 { 123 BirdDirEntry_T DirEntry; 124 BirdDirEntryW_T DirEntryW; 125 } u; 107 126 } BirdDir_T; 108 127 /** Magic value for BirdDir. */ … … 115 134 BirdDir_T *birdDirOpenFromHandle(void *hDir, const void *pvReserved, unsigned fFlags); 116 135 BirdDirEntry_T *birdDirRead(BirdDir_T *pDir); 136 BirdDirEntryW_T *birdDirReadW(BirdDir_T *pDir); 117 137 long birdDirTell(BirdDir_T *pDir); 118 138 void birdDirSeek(BirdDir_T *pDir, long offDir); -
trunk/src/lib/nt/tstNtFts.c
r2991 r3004 71 71 if (chOpt == '-') 72 72 { 73 chOpt = *pszArg++;74 73 if (!chOpt) 75 74 { … … 99 98 else if (strcmp(pszArg, "verbose") == 0) 100 99 chOpt = 'v'; 100 else if (strcmp(pszArg, "no-ansi") == 0) 101 chOpt = 'w'; 101 102 else 102 103 { 103 fprintf(stderr, "syntax error: Unknown option: --%s\n", pszArg);104 fprintf(stderr, "syntax error: Unknown option: %s (%s)\n", argv[i], pszArg); 104 105 return 2; 105 106 } … … 137 138 case 'x': 138 139 fFtsFlags |= FTS_XDEV; 140 break; 141 case 'w': 142 fFtsFlags |= FTS_NO_ANSI; 139 143 break; 140 144 case 'L': … … 206 210 207 211 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 } 209 218 if ( pFtsEnt->fts_info == FTS_SL 210 219 && pFtsEnt->fts_number == 0
Note:
See TracChangeset
for help on using the changeset viewer.