aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-01-23 10:40:57 +0000
committerRon Yorston <rmy@pobox.com>2023-01-23 10:40:57 +0000
commit1a88782fd33db4ad3531b63c9fb744c64282fee2 (patch)
tree65e826528ab2f57ebfb12c74e9b13898157de783
parentafbf21c45d2e6a710aa27cb2784a540bb3ceedea (diff)
downloadbusybox-w32-1a88782fd33db4ad3531b63c9fb744c64282fee2.tar.gz
busybox-w32-1a88782fd33db4ad3531b63c9fb744c64282fee2.tar.bz2
busybox-w32-1a88782fd33db4ad3531b63c9fb744c64282fee2.zip
win32: only count subdirectories if necessary
Commit 7fb95a2a5 (win32: try to get link count for directories) allowed stat(2) to report accurate values of st_nlink for directories. There are only a couple of places in busybox-w32 where these values are required. Disable counting of subdirectories by default and only enable it when necessary. Microsoft kindly provide directories to test edge cases like this: C:/Windows/WinSxS (contains many subdirectories) C:/Windows/WinSxS/Manifests (contains many files) Adds 84-112 bytes.
-rw-r--r--coreutils/ls.c6
-rw-r--r--coreutils/stat.c4
-rw-r--r--include/mingw.h1
-rw-r--r--win32/mingw.c18
4 files changed, 26 insertions, 3 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index d8cfe27d3..3c659294c 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1241,6 +1241,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1241 option_mask32 |= OPT_dirs_first; 1241 option_mask32 |= OPT_dirs_first;
1242 } 1242 }
1243 1243
1244#if ENABLE_FEATURE_EXTRA_FILE_DATA
1245 /* Enable accurate link counts for directories */
1246 if (opt & OPT_l)
1247 count_subdirs(NULL);
1248#endif
1249
1244 argv += optind; 1250 argv += optind;
1245 if (!argv[0]) 1251 if (!argv[0])
1246 *--argv = (char*)"."; 1252 *--argv = (char*)".";
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 940ade89a..dc20c2356 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -785,6 +785,10 @@ int stat_main(int argc UNUSED_PARAM, char **argv)
785 selinux_or_die(); 785 selinux_or_die();
786 } 786 }
787#endif 787#endif
788#if ENABLE_FEATURE_EXTRA_FILE_DATA
789 /* Enable accurate link counts for directories */
790 count_subdirs(NULL);
791#endif
788 ok = 1; 792 ok = 1;
789 argv += optind; 793 argv += optind;
790 for (i = 0; argv[i]; ++i) 794 for (i = 0; argv[i]; ++i)
diff --git a/include/mingw.h b/include/mingw.h
index 4c3354864..6259bc2c6 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -349,6 +349,7 @@ struct mingw_stat {
349#define st_mtime st_mtim.tv_sec 349#define st_mtime st_mtim.tv_sec
350#define st_ctime st_ctim.tv_sec 350#define st_ctime st_ctim.tv_sec
351 351
352int count_subdirs(const char *pathname);
352int mingw_lstat(const char *file_name, struct mingw_stat *buf); 353int mingw_lstat(const char *file_name, struct mingw_stat *buf);
353int mingw_stat(const char *file_name, struct mingw_stat *buf); 354int mingw_stat(const char *file_name, struct mingw_stat *buf);
354int mingw_fstat(int fd, struct mingw_stat *buf); 355int mingw_fstat(int fd, struct mingw_stat *buf);
diff --git a/win32/mingw.c b/win32/mingw.c
index 79bcaa47d..75e6c3f24 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -619,13 +619,25 @@ static int mingw_is_directory(const char *path)
619} 619}
620 620
621#if ENABLE_FEATURE_EXTRA_FILE_DATA 621#if ENABLE_FEATURE_EXTRA_FILE_DATA
622static int count_subdirs(const char *pathname) 622/*
623 * By default we don't count subdirectories. Counting can be enabled
624 * in specific cases by calling 'count_subdirs(NULL)' before making
625 * any calls to stat(2) or lstat(2) that require accurate values of
626 * st_nlink for directories.
627 */
628int count_subdirs(const char *pathname)
623{ 629{
624 int count = 0; 630 int count = 0;
625 DIR *dirp = opendir(pathname); 631 DIR *dirp;
626 struct dirent *dp; 632 struct dirent *dp;
633 static int do_count = FALSE;
634
635 if (pathname == NULL) {
636 do_count = TRUE;
637 return 0;
638 }
627 639
628 if (dirp) { 640 if (do_count && (dirp = opendir(pathname))) {
629 while ((dp = readdir(dirp)) != NULL) { 641 while ((dp = readdir(dirp)) != NULL) {
630 if (dp->d_type == DT_DIR) 642 if (dp->d_type == DT_DIR)
631 count++; 643 count++;