@@ -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