diff options
author | Ron Yorston <rmy@pobox.com> | 2022-12-22 11:16:57 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-12-22 11:16:57 +0000 |
commit | b11352dcbdd94e23224057056594ddc165883c19 (patch) | |
tree | 49ec413787f5cf886815408a1f40fbd86d679694 | |
parent | aeef07a0752ffdc98e1d5a32c508794b93c9f79d (diff) | |
download | busybox-w32-b11352dcbdd94e23224057056594ddc165883c19.tar.gz busybox-w32-b11352dcbdd94e23224057056594ddc165883c19.tar.bz2 busybox-w32-b11352dcbdd94e23224057056594ddc165883c19.zip |
win32: prevent stat(2) from updating access times
The WIN32 implementation of stat(2) reads the contents of some files
to see if they're executable. This may update the file access time.
Avoid this by a special call to SetFileTime() after opening the file.
For details see:
https://devblogs.microsoft.com/oldnewthing/20111010-00/?p=9433
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfiletime
File access times aren't updated by default in recent versions of
Windows. This commit is only necessary if updating of file access
times is explicitly enabled:
fsutil behavior set DisableLastAccess 0
-rw-r--r-- | win32/mingw.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index 606a48319..8216f2e53 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -432,7 +432,10 @@ mode_t mingw_umask(mode_t new_mode) | |||
432 | */ | 432 | */ |
433 | static int has_exec_format(const char *name) | 433 | static int has_exec_format(const char *name) |
434 | { | 434 | { |
435 | int n, sig; | 435 | HANDLE fh; |
436 | int fd = -1; | ||
437 | ssize_t n; | ||
438 | int sig; | ||
436 | unsigned int offset; | 439 | unsigned int offset; |
437 | unsigned char buf[1024]; | 440 | unsigned char buf[1024]; |
438 | 441 | ||
@@ -440,8 +443,20 @@ static int has_exec_format(const char *name) | |||
440 | if (is_suffixed_with_case(name, ".dll")) | 443 | if (is_suffixed_with_case(name, ".dll")) |
441 | return 0; | 444 | return 0; |
442 | 445 | ||
443 | n = open_read_close(name, buf, sizeof(buf)); | 446 | /* Open file and try to avoid updating access time */ |
444 | if (n < 4) /* at least '#!/x' and not error */ | 447 | fh = CreateFileA(name, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); |
448 | if (fh != INVALID_HANDLE_VALUE) { | ||
449 | FILETIME last_access = { 0xffffffff, 0xffffffff }; | ||
450 | |||
451 | SetFileTime(fh, NULL, &last_access, NULL); | ||
452 | fd = _open_osfhandle((intptr_t)fh, O_RDONLY); | ||
453 | } | ||
454 | |||
455 | if (fd < 0) | ||
456 | return 0; | ||
457 | |||
458 | n = read_close(fd, buf, sizeof(buf)); | ||
459 | if (n < 4) /* Need at least a few bytes and no error */ | ||
445 | return 0; | 460 | return 0; |
446 | 461 | ||
447 | /* shell script */ | 462 | /* shell script */ |
@@ -453,7 +468,7 @@ static int has_exec_format(const char *name) | |||
453 | * Poke about in file to see if it's a PE binary. I've just copied | 468 | * Poke about in file to see if it's a PE binary. I've just copied |
454 | * the magic from the file command. | 469 | * the magic from the file command. |
455 | */ | 470 | */ |
456 | if (buf[0] == 'M' && buf[1] == 'Z') { | 471 | if (buf[0] == 'M' && buf[1] == 'Z' && n > 0x3f) { |
457 | offset = (buf[0x19] << 8) + buf[0x18]; | 472 | offset = (buf[0x19] << 8) + buf[0x18]; |
458 | if (offset > 0x3f) { | 473 | if (offset > 0x3f) { |
459 | offset = (buf[0x3f] << 24) + (buf[0x3e] << 16) + | 474 | offset = (buf[0x3f] << 24) + (buf[0x3e] << 16) + |