mingw: replace MSVCRT's fstat() with a Win32-based implementation

fstat() is the only stat-related CRT function for which we don't have a full replacement yet (and thus the only reason to stick with MSVCRT's 'struct stat' definition). Fully implement fstat(), in preparation of implementing a POSIX 2013 compatible 'struct stat' with nanosecond-precision file times. This allows us also to implement some clever code to handle pipes and character devices in our own way. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karsten Blees committed Oct 23, 2018 at 03:23 UTC d75e6973539f1f99561ae6f42a81f024497e3dfa
1 file changed +21 -10
compat/mingw.c
+21 -10
@@ -771,20 +771,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
771 int mingw_fstat(int fd, struct stat *buf)
772 {
773 HANDLE fh = (HANDLE)_get_osfhandle(fd);
774 + DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
775
775 - if (fh == INVALID_HANDLE_VALUE) {
776 - errno = EBADF;
777 - return -1;
778 - }
779 - /* direct non-file handles to MS's fstat() */
780 - if (GetFileType(fh) != FILE_TYPE_DISK)
781 - return _fstati64(fd, buf);
776 + switch (type) {
777 + case FILE_TYPE_DISK:
778 + return get_file_info_by_handle(fh, buf);
779
783 - if (!get_file_info_by_handle(fh, buf))
780 + case FILE_TYPE_CHAR:
781 + case FILE_TYPE_PIPE:
782 + /* initialize stat fields */
783 + memset(buf, 0, sizeof(*buf));
784 + buf->st_nlink = 1;
785 +
786 + if (type == FILE_TYPE_CHAR) {
787 + buf->st_mode = _S_IFCHR;
788 + } else {
789 + buf->st_mode = _S_IFIFO;
790 + if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
791 + buf->st_size = avail;
792 + }
793 return 0;
794
786 - errno = EBADF;
787 - return -1;
795 + default:
796 + errno = EBADF;
797 + return -1;
798 + }
799 }
800
801 static inline void time_t_to_filetime(time_t t, FILETIME *ft)