aboutsummaryrefslogtreecommitdiff
path: root/win32
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 /win32
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.
Diffstat (limited to 'win32')
-rw-r--r--win32/mingw.c39
1 files changed, 35 insertions, 4 deletions
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 }