@@ -648,9 +648,11 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
648
648
return winTime - 116444736000000000LL ;
649
649
}
650
650
651
- static inline time_t filetime_to_time_t (const FILETIME * ft )
651
+ static inline void filetime_to_timespec (const FILETIME * ft , struct timespec * ts )
652
652
{
653
- return (time_t )(filetime_to_hnsec (ft ) / 10000000 );
653
+ long long hnsec = filetime_to_hnsec (ft );
654
+ ts -> tv_sec = (time_t )(hnsec / 10000000 );
655
+ ts -> tv_nsec = (hnsec % 10000000 ) * 100 ;
654
656
}
655
657
656
658
/**
@@ -709,9 +711,9 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
709
711
buf -> st_size = fdata .nFileSizeLow |
710
712
(((off_t )fdata .nFileSizeHigh )<<32 );
711
713
buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
712
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
713
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
714
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
714
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & ( buf -> st_atim ));
715
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & ( buf -> st_mtim ));
716
+ filetime_to_timespec (& (fdata .ftCreationTime ), & ( buf -> st_ctim ));
715
717
if (fdata .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
716
718
WIN32_FIND_DATAW findbuf ;
717
719
HANDLE handle = FindFirstFileW (wfilename , & findbuf );
@@ -792,6 +794,29 @@ static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
792
794
return do_lstat (follow , alt_name , buf );
793
795
}
794
796
797
+ static int get_file_info_by_handle (HANDLE hnd , struct stat * buf )
798
+ {
799
+ BY_HANDLE_FILE_INFORMATION fdata ;
800
+
801
+ if (!GetFileInformationByHandle (hnd , & fdata )) {
802
+ errno = err_win_to_posix (GetLastError ());
803
+ return -1 ;
804
+ }
805
+
806
+ buf -> st_ino = 0 ;
807
+ buf -> st_gid = 0 ;
808
+ buf -> st_uid = 0 ;
809
+ buf -> st_nlink = 1 ;
810
+ buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
811
+ buf -> st_size = fdata .nFileSizeLow |
812
+ (((off_t )fdata .nFileSizeHigh )<<32 );
813
+ buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
814
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & (buf -> st_atim ));
815
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & (buf -> st_mtim ));
816
+ filetime_to_timespec (& (fdata .ftCreationTime ), & (buf -> st_ctim ));
817
+ return 0 ;
818
+ }
819
+
795
820
int mingw_lstat (const char * file_name , struct stat * buf )
796
821
{
797
822
return do_stat_internal (0 , file_name , buf );
@@ -804,32 +829,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
804
829
int mingw_fstat (int fd , struct stat * buf )
805
830
{
806
831
HANDLE fh = (HANDLE )_get_osfhandle (fd );
807
- BY_HANDLE_FILE_INFORMATION fdata ;
832
+ DWORD avail , type = GetFileType ( fh ) & ~ FILE_TYPE_REMOTE ;
808
833
809
- if (fh == INVALID_HANDLE_VALUE ) {
810
- errno = EBADF ;
811
- return -1 ;
812
- }
813
- /* direct non-file handles to MS's fstat() */
814
- if (GetFileType (fh ) != FILE_TYPE_DISK )
815
- return _fstati64 (fd , buf );
834
+ switch (type ) {
835
+ case FILE_TYPE_DISK :
836
+ return get_file_info_by_handle (fh , buf );
816
837
817
- if ( GetFileInformationByHandle ( fh , & fdata )) {
818
- buf -> st_ino = 0 ;
819
- buf -> st_gid = 0 ;
820
- buf -> st_uid = 0 ;
838
+ case FILE_TYPE_CHAR :
839
+ case FILE_TYPE_PIPE :
840
+ /* initialize stat fields */
841
+ memset ( buf , 0 , sizeof ( * buf )) ;
821
842
buf -> st_nlink = 1 ;
822
- buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
823
- buf -> st_size = fdata .nFileSizeLow |
824
- (((off_t )fdata .nFileSizeHigh )<<32 );
825
- buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
826
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
827
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
828
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
843
+
844
+ if (type == FILE_TYPE_CHAR ) {
845
+ buf -> st_mode = _S_IFCHR ;
846
+ } else {
847
+ buf -> st_mode = _S_IFIFO ;
848
+ if (PeekNamedPipe (fh , NULL , 0 , NULL , & avail , NULL ))
849
+ buf -> st_size = avail ;
850
+ }
829
851
return 0 ;
852
+
853
+ default :
854
+ errno = EBADF ;
855
+ return -1 ;
830
856
}
831
- errno = EBADF ;
832
- return -1 ;
833
857
}
834
858
835
859
static inline void time_t_to_filetime (time_t t , FILETIME * ft )
0 commit comments