@@ -618,9 +618,11 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
618618	return  winTime  -  116444736000000000LL ;
619619}
620620
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 )
622622{
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 ;
624626}
625627
626628/** 
@@ -679,9 +681,9 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
679681		buf -> st_size  =  fdata .nFileSizeLow  |
680682			(((off_t )fdata .nFileSizeHigh )<<32 );
681683		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 ));
685687		if  (fdata .dwFileAttributes  &  FILE_ATTRIBUTE_REPARSE_POINT ) {
686688			WIN32_FIND_DATAW  findbuf ;
687689			HANDLE  handle  =  FindFirstFileW (wfilename , & findbuf );
@@ -762,6 +764,29 @@ static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
762764	return  do_lstat (follow , alt_name , buf );
763765}
764766
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+ 
765790int  mingw_lstat (const  char  * file_name , struct  stat  * buf )
766791{
767792	return  do_stat_internal (0 , file_name , buf );
@@ -774,32 +799,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
774799int  mingw_fstat (int  fd , struct  stat  * buf )
775800{
776801	HANDLE  fh  =  (HANDLE )_get_osfhandle (fd );
777- 	BY_HANDLE_FILE_INFORMATION   fdata ;
802+ 	DWORD   avail ,  type   =   GetFileType ( fh )  &  ~ FILE_TYPE_REMOTE ;
778803
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 );
786807
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 )) ;
791812		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+ 		}
799821		return  0 ;
822+ 
823+ 	default :
824+ 		errno  =  EBADF ;
825+ 		return  -1 ;
800826	}
801- 	errno  =  EBADF ;
802- 	return  -1 ;
803827}
804828
805829static  inline  void  time_t_to_filetime (time_t  t , FILETIME  * ft )
0 commit comments