aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-15 08:52:26 +0100
committerRon Yorston <rmy@pobox.com>2022-05-15 08:52:26 +0100
commit7fb95a2a569ca6d68dad4cef5b7b299e9fe68e2b (patch)
tree53e4d681990f6cc64b97e1f6d81f7e52cdb214bb /win32
parentb0696b94ab963fe0dd47f5c1ed6327a4337afa09 (diff)
downloadbusybox-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.c11
-rw-r--r--win32/dirent.h3
-rw-r--r--win32/mingw.c23
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
15DIR *opendir(const char *name) 26DIR *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
11struct dirent { 11struct 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
592static 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);