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