@@ -617,9 +617,11 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
617
617
return winTime - 116444736000000000LL ;
618
618
}
619
619
620
- static inline time_t filetime_to_time_t (const FILETIME * ft )
620
+ static inline void filetime_to_timespec (const FILETIME * ft , struct timespec * ts )
621
621
{
622
- return (time_t )(filetime_to_hnsec (ft ) / 10000000 );
622
+ long long hnsec = filetime_to_hnsec (ft );
623
+ ts -> tv_sec = (time_t )(hnsec / 10000000 );
624
+ ts -> tv_nsec = (hnsec % 10000000 ) * 100 ;
623
625
}
624
626
625
627
/**
@@ -678,9 +680,9 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
678
680
buf -> st_size = fdata .nFileSizeLow |
679
681
(((off_t )fdata .nFileSizeHigh )<<32 );
680
682
buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
681
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
682
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
683
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
683
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & ( buf -> st_atim ));
684
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & ( buf -> st_mtim ));
685
+ filetime_to_timespec (& (fdata .ftCreationTime ), & ( buf -> st_ctim ));
684
686
if (fdata .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
685
687
WIN32_FIND_DATAW findbuf ;
686
688
HANDLE handle = FindFirstFileW (wfilename , & findbuf );
@@ -761,6 +763,29 @@ static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
761
763
return do_lstat (follow , alt_name , buf );
762
764
}
763
765
766
+ static int get_file_info_by_handle (HANDLE hnd , struct stat * buf )
767
+ {
768
+ BY_HANDLE_FILE_INFORMATION fdata ;
769
+
770
+ if (!GetFileInformationByHandle (hnd , & fdata )) {
771
+ errno = err_win_to_posix (GetLastError ());
772
+ return -1 ;
773
+ }
774
+
775
+ buf -> st_ino = 0 ;
776
+ buf -> st_gid = 0 ;
777
+ buf -> st_uid = 0 ;
778
+ buf -> st_nlink = 1 ;
779
+ buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
780
+ buf -> st_size = fdata .nFileSizeLow |
781
+ (((off_t )fdata .nFileSizeHigh )<<32 );
782
+ buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
783
+ filetime_to_timespec (& (fdata .ftLastAccessTime ), & (buf -> st_atim ));
784
+ filetime_to_timespec (& (fdata .ftLastWriteTime ), & (buf -> st_mtim ));
785
+ filetime_to_timespec (& (fdata .ftCreationTime ), & (buf -> st_ctim ));
786
+ return 0 ;
787
+ }
788
+
764
789
int mingw_lstat (const char * file_name , struct stat * buf )
765
790
{
766
791
return do_stat_internal (0 , file_name , buf );
@@ -773,32 +798,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
773
798
int mingw_fstat (int fd , struct stat * buf )
774
799
{
775
800
HANDLE fh = (HANDLE )_get_osfhandle (fd );
776
- BY_HANDLE_FILE_INFORMATION fdata ;
801
+ DWORD avail , type = GetFileType ( fh ) & ~ FILE_TYPE_REMOTE ;
777
802
778
- if (fh == INVALID_HANDLE_VALUE ) {
779
- errno = EBADF ;
780
- return -1 ;
781
- }
782
- /* direct non-file handles to MS's fstat() */
783
- if (GetFileType (fh ) != FILE_TYPE_DISK )
784
- return _fstati64 (fd , buf );
803
+ switch (type ) {
804
+ case FILE_TYPE_DISK :
805
+ return get_file_info_by_handle (fh , buf );
785
806
786
- if ( GetFileInformationByHandle ( fh , & fdata )) {
787
- buf -> st_ino = 0 ;
788
- buf -> st_gid = 0 ;
789
- buf -> st_uid = 0 ;
807
+ case FILE_TYPE_CHAR :
808
+ case FILE_TYPE_PIPE :
809
+ /* initialize stat fields */
810
+ memset ( buf , 0 , sizeof ( * buf )) ;
790
811
buf -> st_nlink = 1 ;
791
- buf -> st_mode = file_attr_to_st_mode (fdata .dwFileAttributes );
792
- buf -> st_size = fdata .nFileSizeLow |
793
- (((off_t )fdata .nFileSizeHigh )<<32 );
794
- buf -> st_dev = buf -> st_rdev = 0 ; /* not used by Git */
795
- buf -> st_atime = filetime_to_time_t (& (fdata .ftLastAccessTime ));
796
- buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
797
- buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
812
+
813
+ if (type == FILE_TYPE_CHAR ) {
814
+ buf -> st_mode = _S_IFCHR ;
815
+ } else {
816
+ buf -> st_mode = _S_IFIFO ;
817
+ if (PeekNamedPipe (fh , NULL , 0 , NULL , & avail , NULL ))
818
+ buf -> st_size = avail ;
819
+ }
798
820
return 0 ;
821
+
822
+ default :
823
+ errno = EBADF ;
824
+ return -1 ;
799
825
}
800
- errno = EBADF ;
801
- return -1 ;
802
826
}
803
827
804
828
static inline void time_t_to_filetime (time_t t , FILETIME * ft )
0 commit comments