aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-02-16 12:36:52 +0000
committerRon Yorston <rmy@pobox.com>2019-02-16 12:36:52 +0000
commitd82db8e9a618ddd9a11cc57aff37f687abb0effb (patch)
treebd072e7344a3c3f0eff553d41c0f154c4470736e
parent91e49fbc7b55e8be78ac3ff943e9b7d4494dfe59 (diff)
downloadbusybox-w32-d82db8e9a618ddd9a11cc57aff37f687abb0effb.tar.gz
busybox-w32-d82db8e9a618ddd9a11cc57aff37f687abb0effb.tar.bz2
busybox-w32-d82db8e9a618ddd9a11cc57aff37f687abb0effb.zip
win32: make stat(2) fetch additional metadata
Modify the WIN32 implementation of stat(2) to fetch inode number, device id and number of hardlinks. This requires opening a handle to the target file so it will be slower. A number of features can be enabled or start to work: - tar can detect if an archive is being stored in itself; - find can support the -inum and -links options; - ls can display inode numbers; - diff can detect attempts to compare a file with itself; - du has better support for hardlinked files; - cp can detect attempts to copy a file over itself.
-rw-r--r--Config.in10
-rw-r--r--archival/tar.c6
-rw-r--r--configs/mingw32_defconfig6
-rw-r--r--configs/mingw64_defconfig6
-rw-r--r--coreutils/ls.c4
-rw-r--r--editors/diff.c3
-rw-r--r--findutils/find.c8
-rw-r--r--include/libbb.h2
-rw-r--r--include/mingw.h3
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/copy_file.c2
-rw-r--r--win32/mingw.c39
12 files changed, 74 insertions, 16 deletions
diff --git a/Config.in b/Config.in
index 0318a6aff..9f8d4bf7c 100644
--- a/Config.in
+++ b/Config.in
@@ -463,6 +463,16 @@ config FEATURE_EURO
463 requires the OEM code page to be 858. If the OEM code page of 463 requires the OEM code page to be 858. If the OEM code page of
464 the console is 850 when BusyBox starts it's changed to 858. 464 the console is 850 when BusyBox starts it's changed to 858.
465 465
466config FEATURE_EXTRA_FILE_DATA
467 bool "Read additional file metadata (1.3 kb)"
468 default y
469 depends on PLATFORM_MINGW32
470 help
471 Read additional file metadata: device id, inode number and number
472 of hard links. This may slow down some file operations but it
473 permits extra features such as warning of attempts to copy a file
474 onto itself or to store a tar archive in itself.
475
466comment 'Build Options' 476comment 'Build Options'
467 477
468config STATIC 478config STATIC
diff --git a/archival/tar.c b/archival/tar.c
index b9ae93004..54989b953 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -161,7 +161,7 @@ typedef struct TarBallInfo {
161# endif 161# endif
162 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */ 162 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
163 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ 163 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
164#if !ENABLE_PLATFORM_MINGW32 164#if !ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA
165//TODO: save only st_dev + st_ino 165//TODO: save only st_dev + st_ino
166 struct stat tarFileStatBuf; /* Stat info for the tarball, letting 166 struct stat tarFileStatBuf; /* Stat info for the tarball, letting
167 * us know the inode and device that the 167 * us know the inode and device that the
@@ -529,7 +529,7 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
529 } 529 }
530 } 530 }
531 531
532#if !ENABLE_PLATFORM_MINGW32 532#if !ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA
533 /* It is a bad idea to store the archive we are in the process of creating, 533 /* It is a bad idea to store the archive we are in the process of creating,
534 * so check the device and inode to be sure that this particular file isn't 534 * so check the device and inode to be sure that this particular file isn't
535 * the new tarball */ 535 * the new tarball */
@@ -707,7 +707,7 @@ static NOINLINE int writeTarFile(
707 707
708 /*tbInfo->hlInfoHead = NULL; - already is */ 708 /*tbInfo->hlInfoHead = NULL; - already is */
709 709
710#if !ENABLE_PLATFORM_MINGW32 710#if !ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA
711 /* Store the stat info for the tarball's file, so 711 /* Store the stat info for the tarball's file, so
712 * can avoid including the tarball into itself.... */ 712 * can avoid including the tarball into itself.... */
713 xfstat(tbInfo->tarFd, &tbInfo->tarFileStatBuf, "can't stat tar file"); 713 xfstat(tbInfo->tarFd, &tbInfo->tarFileStatBuf, "can't stat tar file");
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
index aec3b97e7..cb74f8c20 100644
--- a/configs/mingw32_defconfig
+++ b/configs/mingw32_defconfig
@@ -48,6 +48,8 @@ CONFIG_FEATURE_ICON=y
48# CONFIG_FEATURE_ICON_ATERM is not set 48# CONFIG_FEATURE_ICON_ATERM is not set
49# CONFIG_FEATURE_ICON_STERM is not set 49# CONFIG_FEATURE_ICON_STERM is not set
50CONFIG_FEATURE_ICON_ALL=y 50CONFIG_FEATURE_ICON_ALL=y
51CONFIG_FEATURE_EURO=y
52CONFIG_FEATURE_EXTRA_FILE_DATA=y
51 53
52# 54#
53# Build Options 55# Build Options
@@ -457,7 +459,7 @@ CONFIG_FEATURE_FIND_EXECUTABLE=y
457# CONFIG_FEATURE_FIND_XDEV is not set 459# CONFIG_FEATURE_FIND_XDEV is not set
458CONFIG_FEATURE_FIND_MAXDEPTH=y 460CONFIG_FEATURE_FIND_MAXDEPTH=y
459CONFIG_FEATURE_FIND_NEWER=y 461CONFIG_FEATURE_FIND_NEWER=y
460# CONFIG_FEATURE_FIND_INUM is not set 462CONFIG_FEATURE_FIND_INUM=y
461CONFIG_FEATURE_FIND_EXEC=y 463CONFIG_FEATURE_FIND_EXEC=y
462CONFIG_FEATURE_FIND_EXEC_PLUS=y 464CONFIG_FEATURE_FIND_EXEC_PLUS=y
463# CONFIG_FEATURE_FIND_USER is not set 465# CONFIG_FEATURE_FIND_USER is not set
@@ -472,7 +474,7 @@ CONFIG_FEATURE_FIND_DELETE=y
472CONFIG_FEATURE_FIND_PATH=y 474CONFIG_FEATURE_FIND_PATH=y
473CONFIG_FEATURE_FIND_REGEX=y 475CONFIG_FEATURE_FIND_REGEX=y
474# CONFIG_FEATURE_FIND_CONTEXT is not set 476# CONFIG_FEATURE_FIND_CONTEXT is not set
475# CONFIG_FEATURE_FIND_LINKS is not set 477CONFIG_FEATURE_FIND_LINKS=y
476CONFIG_GREP=y 478CONFIG_GREP=y
477CONFIG_EGREP=y 479CONFIG_EGREP=y
478CONFIG_FGREP=y 480CONFIG_FGREP=y
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig
index 4fa2a1735..a0569b23a 100644
--- a/configs/mingw64_defconfig
+++ b/configs/mingw64_defconfig
@@ -48,6 +48,8 @@ CONFIG_FEATURE_ICON=y
48# CONFIG_FEATURE_ICON_ATERM is not set 48# CONFIG_FEATURE_ICON_ATERM is not set
49# CONFIG_FEATURE_ICON_STERM is not set 49# CONFIG_FEATURE_ICON_STERM is not set
50CONFIG_FEATURE_ICON_ALL=y 50CONFIG_FEATURE_ICON_ALL=y
51CONFIG_FEATURE_EURO=y
52CONFIG_FEATURE_EXTRA_FILE_DATA=y
51 53
52# 54#
53# Build Options 55# Build Options
@@ -457,7 +459,7 @@ CONFIG_FEATURE_FIND_EXECUTABLE=y
457# CONFIG_FEATURE_FIND_XDEV is not set 459# CONFIG_FEATURE_FIND_XDEV is not set
458CONFIG_FEATURE_FIND_MAXDEPTH=y 460CONFIG_FEATURE_FIND_MAXDEPTH=y
459CONFIG_FEATURE_FIND_NEWER=y 461CONFIG_FEATURE_FIND_NEWER=y
460# CONFIG_FEATURE_FIND_INUM is not set 462CONFIG_FEATURE_FIND_INUM=y
461CONFIG_FEATURE_FIND_EXEC=y 463CONFIG_FEATURE_FIND_EXEC=y
462CONFIG_FEATURE_FIND_EXEC_PLUS=y 464CONFIG_FEATURE_FIND_EXEC_PLUS=y
463# CONFIG_FEATURE_FIND_USER is not set 465# CONFIG_FEATURE_FIND_USER is not set
@@ -472,7 +474,7 @@ CONFIG_FEATURE_FIND_DELETE=y
472CONFIG_FEATURE_FIND_PATH=y 474CONFIG_FEATURE_FIND_PATH=y
473CONFIG_FEATURE_FIND_REGEX=y 475CONFIG_FEATURE_FIND_REGEX=y
474# CONFIG_FEATURE_FIND_CONTEXT is not set 476# CONFIG_FEATURE_FIND_CONTEXT is not set
475# CONFIG_FEATURE_FIND_LINKS is not set 477CONFIG_FEATURE_FIND_LINKS=y
476CONFIG_GREP=y 478CONFIG_GREP=y
477CONFIG_EGREP=y 479CONFIG_EGREP=y
478CONFIG_FGREP=y 480CONFIG_FGREP=y
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 48927c964..a1782ed45 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -499,7 +499,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
499#endif 499#endif
500 500
501 if (opt & OPT_i) /* show inode# */ 501 if (opt & OPT_i) /* show inode# */
502#if !ENABLE_FEATURE_EXTRA_FILE_DATA
502 column += printf("%7"LL_FMT"u ", (long long) dn->dn_ino); 503 column += printf("%7"LL_FMT"u ", (long long) dn->dn_ino);
504#else
505 column += printf("%19"LL_FMT"u ", (long long) dn->dn_ino);
506#endif
503//TODO: -h should affect -s too: 507//TODO: -h should affect -s too:
504 if (opt & OPT_s) /* show allocated blocks */ 508 if (opt & OPT_s) /* show allocated blocks */
505 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); 509 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1));
diff --git a/editors/diff.c b/editors/diff.c
index 929beb054..815c8a915 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -1039,7 +1039,8 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
1039 * single NFS file system, if a local device number (st_dev) exceeds 1039 * single NFS file system, if a local device number (st_dev) exceeds
1040 * 255, or if a local inode number (st_ino) exceeds 16777215. 1040 * 255, or if a local inode number (st_ino) exceeds 16777215.
1041 */ 1041 */
1042 if (ENABLE_DESKTOP && !ENABLE_PLATFORM_MINGW32 1042 if (ENABLE_DESKTOP
1043 && (!ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA)
1043 && stb[0].st_ino == stb[1].st_ino 1044 && stb[0].st_ino == stb[1].st_ino
1044 && stb[0].st_dev == stb[1].st_dev 1045 && stb[0].st_dev == stb[1].st_dev
1045 && stb[0].st_size == stb[1].st_size 1046 && stb[0].st_size == stb[1].st_size
diff --git a/findutils/find.c b/findutils/find.c
index 06ad1b39c..0381f0685 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -121,7 +121,7 @@
121//config:config FEATURE_FIND_INUM 121//config:config FEATURE_FIND_INUM
122//config: bool "Enable -inum: inode number matching" 122//config: bool "Enable -inum: inode number matching"
123//config: default y 123//config: default y
124//config: depends on FIND 124//config: depends on FIND && (PLATFORM_POSIX || FEATURE_EXTRA_FILE_DATA)
125//config: 125//config:
126//config:config FEATURE_FIND_EXEC 126//config:config FEATURE_FIND_EXEC
127//config: bool "Enable -exec: execute commands" 127//config: bool "Enable -exec: execute commands"
@@ -227,7 +227,7 @@
227//config:config FEATURE_FIND_LINKS 227//config:config FEATURE_FIND_LINKS
228//config: bool "Enable -links: link count matching" 228//config: bool "Enable -links: link count matching"
229//config: default y 229//config: default y
230//config: depends on FIND 230//config: depends on FIND && (PLATFORM_POSIX || FEATURE_EXTRA_FILE_DATA)
231//config: help 231//config: help
232//config: Support the 'find -links' option for matching number of links. 232//config: Support the 'find -links' option for matching number of links.
233 233
@@ -1361,7 +1361,11 @@ static action*** parse_params(char **argv)
1361 action_inum *ap; 1361 action_inum *ap;
1362 dbg("%d", __LINE__); 1362 dbg("%d", __LINE__);
1363 ap = ALLOC_ACTION(inum); 1363 ap = ALLOC_ACTION(inum);
1364# if !ENABLE_FEATURE_EXTRA_FILE_DATA
1364 ap->inode_num = xatoul(arg1); 1365 ap->inode_num = xatoul(arg1);
1366# else
1367 ap->inode_num = xatoull(arg1);
1368# endif
1365 } 1369 }
1366#endif 1370#endif
1367#if ENABLE_FEATURE_FIND_USER 1371#if ENABLE_FEATURE_FIND_USER
diff --git a/include/libbb.h b/include/libbb.h
index 0c7e03ee8..61574b5ee 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1712,7 +1712,7 @@ int bb_xioctl(int fd, unsigned request, void *argp) FAST_FUNC;
1712#define xioctl(fd,request,argp) bb_xioctl(fd,request,argp) 1712#define xioctl(fd,request,argp) bb_xioctl(fd,request,argp)
1713#endif 1713#endif
1714 1714
1715#if !ENABLE_PLATFORM_MINGW32 1715#if !ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA
1716char *is_in_ino_dev_hashtable(const struct stat *statbuf) FAST_FUNC; 1716char *is_in_ino_dev_hashtable(const struct stat *statbuf) FAST_FUNC;
1717void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) FAST_FUNC; 1717void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) FAST_FUNC;
1718void reset_ino_dev_hashtable(void) FAST_FUNC; 1718void reset_ino_dev_hashtable(void) FAST_FUNC;
diff --git a/include/mingw.h b/include/mingw.h
index 185eb66ed..0f403b993 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -283,6 +283,9 @@ int mingw_chmod(const char *path, int mode);
283typedef int nlink_t; 283typedef int nlink_t;
284typedef int blksize_t; 284typedef int blksize_t;
285typedef off_t blkcnt_t; 285typedef off_t blkcnt_t;
286#if ENABLE_FEATURE_EXTRA_FILE_DATA
287#define ino_t uint64_t
288#endif
286 289
287struct mingw_stat { 290struct mingw_stat {
288 dev_t st_dev; 291 dev_t st_dev;
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index b298040ac..799f6d01a 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -98,6 +98,7 @@ lib-$(CONFIG_PLATFORM_POSIX) += getpty.o
98lib-$(CONFIG_PLATFORM_POSIX) += get_volsize.o 98lib-$(CONFIG_PLATFORM_POSIX) += get_volsize.o
99lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o 99lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o
100lib-$(CONFIG_PLATFORM_POSIX) += inode_hash.o 100lib-$(CONFIG_PLATFORM_POSIX) += inode_hash.o
101lib-$(CONFIG_FEATURE_EXTRA_FILE_DATA) += inode_hash.o
101lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o 102lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o
102lib-$(CONFIG_PLATFORM_POSIX) += login.o 103lib-$(CONFIG_PLATFORM_POSIX) += login.o
103lib-$(CONFIG_PLATFORM_POSIX) += makedev.o 104lib-$(CONFIG_PLATFORM_POSIX) += makedev.o
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 299cd7bea..db7a00060 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -105,7 +105,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
105 return -1; 105 return -1;
106 } 106 }
107 } else { 107 } else {
108#if !ENABLE_PLATFORM_MINGW32 108#if !ENABLE_PLATFORM_MINGW32 || ENABLE_FEATURE_EXTRA_FILE_DATA
109 /* MinGW does not have inode, and does not use device */ 109 /* MinGW does not have inode, and does not use device */
110 if (source_stat.st_dev == dest_stat.st_dev 110 if (source_stat.st_dev == dest_stat.st_dev
111 && source_stat.st_ino == dest_stat.st_ino 111 && source_stat.st_ino == dest_stat.st_ino
diff --git a/win32/mingw.c b/win32/mingw.c
index 8217ec772..03636a04b 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -403,7 +403,7 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
403 buf->st_ino = 0; 403 buf->st_ino = 0;
404 buf->st_uid = DEFAULT_UID; 404 buf->st_uid = DEFAULT_UID;
405 buf->st_gid = DEFAULT_GID; 405 buf->st_gid = DEFAULT_GID;
406 buf->st_nlink = 1; 406 buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : 1;
407 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); 407 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
408 if (S_ISREG(buf->st_mode) && 408 if (S_ISREG(buf->st_mode) &&
409 (has_exe_suffix(file_name) || has_exec_format(file_name))) 409 (has_exe_suffix(file_name) || has_exec_format(file_name)))
@@ -434,6 +434,30 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
434 } 434 }
435 } 435 }
436 436
437#if ENABLE_FEATURE_EXTRA_FILE_DATA
438 {
439 BY_HANDLE_FILE_INFORMATION hdata;
440 HANDLE fh = CreateFile(file_name, 0,
441 0, NULL, OPEN_EXISTING,
442 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
443 NULL);
444 if (fh != INVALID_HANDLE_VALUE) {
445 if (GetFileInformationByHandle(fh, &hdata)) {
446 buf->st_dev = hdata.dwVolumeSerialNumber;
447 buf->st_ino = hdata.nFileIndexLow |
448 (((uint64_t)hdata.nFileIndexHigh)<<32);
449 buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 :
450 hdata.nNumberOfLinks;
451 }
452 CloseHandle(fh);
453 }
454 else {
455 errno = err_win_to_posix(GetLastError());
456 return -1;
457 }
458 }
459#endif
460
437 /* 461 /*
438 * Assume a block is 4096 bytes and calculate number of 512 byte 462 * Assume a block is 4096 bytes and calculate number of 512 byte
439 * sectors. 463 * sectors.
@@ -522,12 +546,19 @@ int mingw_fstat(int fd, struct mingw_stat *buf)
522 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); 546 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
523 buf->st_blocks = ((buf->st_size+4095)>>12)<<3; 547 buf->st_blocks = ((buf->st_size+4095)>>12)<<3;
524 success: 548 success:
525 buf->st_dev = buf->st_rdev = 0; 549#if ENABLE_FEATURE_EXTRA_FILE_DATA
550 buf->st_dev = fdata.dwVolumeSerialNumber;
551 buf->st_ino = fdata.nFileIndexLow |
552 (((uint64_t)fdata.nFileIndexHigh)<<32);
553 buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : fdata.nNumberOfLinks;
554#else
555 buf->st_dev = 0;
526 buf->st_ino = 0; 556 buf->st_ino = 0;
557 buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : 1;
558#endif
559 buf->st_rdev = 0;
527 buf->st_uid = DEFAULT_UID; 560 buf->st_uid = DEFAULT_UID;
528 buf->st_gid = DEFAULT_GID; 561 buf->st_gid = DEFAULT_GID;
529 /* could use fdata.nNumberOfLinks but it's inconsistent with stat */
530 buf->st_nlink = 1;
531 buf->st_blksize = 4096; 562 buf->st_blksize = 4096;
532 return 0; 563 return 0;
533 } 564 }