@@ -587,9 +587,11 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
587
587
return winTime - 116444736000000000LL ;
588
588
}
589
589
590
- static inline time_t filetime_to_time_t (const FILETIME * ft )
590
+ static inline void filetime_to_timespec (const FILETIME * ft , struct timespec * ts )
591
591
{
592
- return (time_t )(filetime_to_hnsec (ft ) / 10000000 );
592
+ long long hnsec = filetime_to_hnsec (ft );
593
+ ts -> tv_sec = (time_t )(hnsec / 10000000 );
594
+ ts -> tv_nsec = (hnsec % 10000000 ) * 100 ;
593
595
}
594
596
595
597
/**
@@ -648,9 +650,9 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
648
650
buf -> st_size = fdata .nFileSizeLow |
649
651
(((off_t )fdata .nFileSizeHigh )<<32 );
650
652
buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
651
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
652
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
653
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
653
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & ( buf -> st_atim ));
654
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & ( buf -> st_mtim ));
655
+ filetime_to_timespec (& (fdata .ftCreationTime ), & ( buf -> st_ctim ));
654
656
if (fdata .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
655
657
WIN32_FIND_DATAW findbuf ;
656
658
HANDLE handle = FindFirstFileW (wfilename , & findbuf );
@@ -731,6 +733,29 @@ static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
731
733
return do_lstat (follow , alt_name , buf );
732
734
}
733
735
736
+ static int get_file_info_by_handle (HANDLE hnd , struct stat * buf )
737
+ {
738
+ BY_HANDLE_FILE_INFORMATION fdata ;
739
+
740
+ if (!GetFileInformationByHandle (hnd , & fdata )) {
741
+ errno = err_win_to_posix (GetLastError ());
742
+ return -1 ;
743
+ }
744
+
745
+ buf -> st_ino = 0 ;
746
+ buf -> st_gid = 0 ;
747
+ buf -> st_uid = 0 ;
748
+ buf -> st_nlink = 1 ;
749
+ buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
750
+ buf -> st_size = fdata .nFileSizeLow |
751
+ (((off_t )fdata .nFileSizeHigh )<<32 );
752
+ buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
753
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & (buf -> st_atim ));
754
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & (buf -> st_mtim ));
755
+ filetime_to_timespec (& (fdata .ftCreationTime ), & (buf -> st_ctim ));
756
+ return 0 ;
757
+ }
758
+
734
759
int mingw_lstat (const char * file_name , struct stat * buf )
735
760
{
736
761
return do_stat_internal (0 , file_name , buf );
@@ -743,32 +768,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
743
768
int mingw_fstat (int fd , struct stat * buf )
744
769
{
745
770
HANDLE fh = (HANDLE )_get_osfhandle (fd );
746
- BY_HANDLE_FILE_INFORMATION fdata ;
771
+ DWORD avail , type = GetFileType ( fh ) & ~ FILE_TYPE_REMOTE ;
747
772
748
- if (fh == INVALID_HANDLE_VALUE ) {
749
- errno = EBADF ;
750
- return -1 ;
751
- }
752
- /* direct non-file handles to MS's fstat() */
753
- if (GetFileType (fh ) != FILE_TYPE_DISK )
754
- return _fstati64 (fd , buf );
773
+ switch (type ) {
774
+ case FILE_TYPE_DISK :
775
+ return get_file_info_by_handle (fh , buf );
755
776
756
- if ( GetFileInformationByHandle ( fh , & fdata )) {
757
- buf -> st_ino = 0 ;
758
- buf -> st_gid = 0 ;
759
- buf -> st_uid = 0 ;
777
+ case FILE_TYPE_CHAR :
778
+ case FILE_TYPE_PIPE :
779
+ /* initialize stat fields */
780
+ memset ( buf , 0 , sizeof ( * buf )) ;
760
781
buf -> st_nlink = 1 ;
761
- buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
762
- buf -> st_size = fdata .nFileSizeLow |
763
- (((off_t )fdata .nFileSizeHigh )<<32 );
764
- buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
765
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
766
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
767
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
782
+
783
+ if (type == FILE_TYPE_CHAR ) {
784
+ buf -> st_mode = _S_IFCHR ;
785
+ } else {
786
+ buf -> st_mode = _S_IFIFO ;
787
+ if (PeekNamedPipe (fh , NULL , 0 , NULL , & avail , NULL ))
788
+ buf -> st_size = avail ;
789
+ }
768
790
return 0 ;
791
+
792
+ default :
793
+ errno = EBADF ;
794
+ return -1 ;
769
795
}
770
- errno = EBADF ;
771
- return -1 ;
772
796
}
773
797
774
798
static inline void time_t_to_filetime (time_t t , FILETIME * ft )
0 commit comments