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 /win32 | |
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)
Diffstat (limited to 'win32')
-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); |