@@ -518,8 +518,54 @@ int p_creat(const char *path, mode_t mode)
518518
519519int p_fallocate (int fd , off_t offset , off_t len )
520520{
521- error = ENOSYS ;
522- return -1 ;
521+ HANDLE fh = (HANDLE )_get_osfhandle (fd );
522+ LARGE_INTEGER zero , position , oldsize , newsize ;
523+ size_t size ;
524+
525+ if (fh == INVALID_HANDLE_VALUE ) {
526+ errno = EBADF ;
527+ return -1 ;
528+ }
529+
530+ if (offset < 0 || len <= 0 ) {
531+ errno = EINVAL ;
532+ return -1 ;
533+ }
534+
535+ if (git__add_sizet_overflow (& size , offset , len )) {
536+ errno = EINVAL ;
537+ return -1 ;
538+ }
539+
540+ zero .u .LowPart = 0 ;
541+ zero .u .HighPart = 0 ;
542+
543+ newsize .u .LowPart = (size & 0xffffffff );
544+
545+ #if (SIZE_MAX > UINT32_MAX )
546+ newsize .u .HighPart = size >> 32 ;
547+ #else
548+ newsize .u .HighPart = 0 ;
549+ #endif
550+
551+ if (!GetFileSizeEx (fh , & oldsize )) {
552+ set_errno ();
553+ return -1 ;
554+ }
555+
556+ /* POSIX emulation: attempting to shrink the file is ignored */
557+ if (oldsize .QuadPart >= newsize .QuadPart )
558+ return 0 ;
559+
560+ if (!SetFilePointerEx (fh , zero , & position , FILE_CURRENT ) ||
561+ !SetFilePointerEx (fh , newsize , NULL , FILE_BEGIN ) ||
562+ !SetEndOfFile (fh ) ||
563+ !SetFilePointerEx (fh , position , 0 , FILE_BEGIN )) {
564+ set_errno ();
565+ return -1 ;
566+ }
567+
568+ return 0 ;
523569}
524570
525571int p_utimes (const char * path , const struct p_timeval times [2 ])
0 commit comments