diff options
| author | Ron Yorston <rmy@pobox.com> | 2022-05-15 08:52:26 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2022-05-15 08:52:26 +0100 |
| commit | 7fb95a2a569ca6d68dad4cef5b7b299e9fe68e2b (patch) | |
| tree | 53e4d681990f6cc64b97e1f6d81f7e52cdb214bb | |
| parent | b0696b94ab963fe0dd47f5c1ed6327a4337afa09 (diff) | |
| download | busybox-w32-7fb95a2a569ca6d68dad4cef5b7b299e9fe68e2b.tar.gz busybox-w32-7fb95a2a569ca6d68dad4cef5b7b299e9fe68e2b.tar.bz2 busybox-w32-7fb95a2a569ca6d68dad4cef5b7b299e9fe68e2b.zip | |
win32: try to get link count for directories
On Unix the link count of a directory reflects the number of
subdirectories it contains. Enhance readdir(3) to return file
types and use this to count subdirectories when stat(2) is called
for a directory.
As with other features that might slow down stat(2) this is
controlled by the build-time setting FEATURE_EXTRA_FILE_DATA.
(Commit d82db8e9a 'win32: make stat(2) fetch additional metadata').
(GitHub issue #254)
| -rw-r--r-- | win32/dirent.c | 11 | ||||
| -rw-r--r-- | win32/dirent.h | 3 | ||||
| -rw-r--r-- | win32/mingw.c | 23 |
3 files changed, 36 insertions, 1 deletions
diff --git a/win32/dirent.c b/win32/dirent.c index b7de19391..b5b379209 100644 --- a/win32/dirent.c +++ b/win32/dirent.c | |||
| @@ -10,6 +10,17 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAA *fdata) | |||
| 10 | { | 10 | { |
| 11 | /* copy file name from WIN32_FIND_DATA to dirent */ | 11 | /* copy file name from WIN32_FIND_DATA to dirent */ |
| 12 | strcpy(ent->d_name, fdata->cFileName); | 12 | strcpy(ent->d_name, fdata->cFileName); |
| 13 | |||
| 14 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
| 15 | if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && | ||
| 16 | (fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK || | ||
| 17 | fdata->dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) | ||
| 18 | ent->d_type = DT_LNK; | ||
| 19 | else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||
| 20 | ent->d_type = DT_DIR; | ||
| 21 | else | ||
| 22 | ent->d_type = DT_REG; | ||
| 23 | #endif | ||
| 13 | } | 24 | } |
| 14 | 25 | ||
| 15 | DIR *opendir(const char *name) | 26 | DIR *opendir(const char *name) |
diff --git a/win32/dirent.h b/win32/dirent.h index b38d0d133..214f80547 100644 --- a/win32/dirent.h +++ b/win32/dirent.h | |||
| @@ -9,6 +9,9 @@ typedef struct DIR DIR; | |||
| 9 | #define DT_LNK 3 | 9 | #define DT_LNK 3 |
| 10 | 10 | ||
| 11 | struct dirent { | 11 | struct dirent { |
| 12 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
| 13 | unsigned char d_type; | ||
| 14 | #endif | ||
| 12 | char d_name[PATH_MAX]; // file name | 15 | char d_name[PATH_MAX]; // file name |
| 13 | }; | 16 | }; |
| 14 | 17 | ||
diff --git a/win32/mingw.c b/win32/mingw.c index 539aa48d2..c35b1d6af 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
| @@ -588,6 +588,26 @@ static int is_symlink(const char *pathname) | |||
| 588 | return 0; | 588 | return 0; |
| 589 | } | 589 | } |
| 590 | 590 | ||
| 591 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
| 592 | static int count_subdirs(const char *pathname) | ||
| 593 | { | ||
| 594 | int count = 0; | ||
| 595 | DIR *dirp = opendir(pathname); | ||
| 596 | struct dirent *dp; | ||
| 597 | |||
| 598 | if (dirp) { | ||
| 599 | while ((dp = readdir(dirp)) != NULL) { | ||
| 600 | if (dp->d_type == DT_DIR) | ||
| 601 | count++; | ||
| 602 | } | ||
| 603 | closedir(dirp); | ||
| 604 | } else { | ||
| 605 | count = 2; | ||
| 606 | } | ||
| 607 | return count; | ||
| 608 | } | ||
| 609 | #endif | ||
| 610 | |||
| 591 | /* If follow is true then act like stat() and report on the link | 611 | /* If follow is true then act like stat() and report on the link |
| 592 | * target. Otherwise report on the link itself. | 612 | * target. Otherwise report on the link itself. |
| 593 | */ | 613 | */ |
| @@ -656,7 +676,8 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
| 656 | buf->st_dev = hdata.dwVolumeSerialNumber; | 676 | buf->st_dev = hdata.dwVolumeSerialNumber; |
| 657 | buf->st_ino = hdata.nFileIndexLow | | 677 | buf->st_ino = hdata.nFileIndexLow | |
| 658 | (((ino_t)hdata.nFileIndexHigh)<<32); | 678 | (((ino_t)hdata.nFileIndexHigh)<<32); |
| 659 | buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : | 679 | buf->st_nlink = S_ISDIR(buf->st_mode) ? |
| 680 | count_subdirs(file_name) : | ||
| 660 | hdata.nNumberOfLinks; | 681 | hdata.nNumberOfLinks; |
| 661 | } | 682 | } |
| 662 | buf->st_uid = buf->st_gid = file_owner(fh); | 683 | buf->st_uid = buf->st_gid = file_owner(fh); |
