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