@@ -45,36 +45,57 @@ static void php_gziop_report_errors(php_stream *stream, size_t count, const char
4545static  ssize_t  php_gziop_read (php_stream  * stream , char  * buf , size_t  count )
4646{
4747	struct  php_gz_stream_data_t  * self  =  (struct  php_gz_stream_data_t  * ) stream -> abstract ;
48- 	int  read ;
49- 
50- 	/* XXX this needs to be looped for the case count > UINT_MAX */ 
51- 	read  =  gzread (self -> gz_file , buf , count );
48+ 	ssize_t  total_read  =  0 ;
49+ 
50+ 	/* Despite the count argument of gzread() being "unsigned int", 
51+ 	 * the return value is "int". Error returns are values < 0, otherwise the count is returned. 
52+ 	 * To properly distinguish error values from success value, we therefore need to cap at INT_MAX. 
53+ 	 */ 
54+ 	do  {
55+ 		unsigned int   chunk_size  =  MIN (count , INT_MAX );
56+ 		int  read  =  gzread (self -> gz_file , buf , chunk_size );
57+ 		count  -=  chunk_size ;
58+ 
59+ 		if  (gzeof (self -> gz_file )) {
60+ 			stream -> eof  =  1 ;
61+ 		}
5262
53- 	/* Notify user of error, like the standard file wrapper normally does (e.g. errno=13 on mandatory lock failure). */ 
54- 	if  ( UNEXPECTED ( read   <   0 )) { 
55- 		php_gziop_report_errors ( stream ,  count ,  "Read" ) ;
56- 	}
63+ 		 if  ( UNEXPECTED ( read   <   0 )) { 
64+ 			 php_gziop_report_errors ( stream ,  count ,  "Read" ); 
65+ 			 return   read ;
66+ 		 }
5767
58- 	if  ( gzeof ( self -> gz_file )) { 
59- 		stream -> eof   =   1 ;
60- 	}
68+ 		 total_read   +=   read ; 
69+ 		buf   +=   read ;
70+ 	}  while  ( count   >   0   &&  ! stream -> eof ); 
6171
62- 	return  read ;
72+ 	return  total_read ;
6373}
6474
6575static  ssize_t  php_gziop_write (php_stream  * stream , const  char  * buf , size_t  count )
6676{
6777	struct  php_gz_stream_data_t  * self  =  (struct  php_gz_stream_data_t  * ) stream -> abstract ;
78+ 	ssize_t  total_written  =  0 ;
79+ 
80+ 	/* Despite the count argument of gzread() being "unsigned int", 
81+ 	 * the return value is "int". Error returns are values < 0, otherwise the count is returned. 
82+ 	 * To properly distinguish error values from success value, we therefore need to cap at INT_MAX. 
83+ 	 */ 
84+ 	do  {
85+ 		unsigned int   chunk_size  =  MIN (count , INT_MAX );
86+ 		int  written  =  gzwrite (self -> gz_file , buf , chunk_size );
87+ 		count  -=  chunk_size ;
88+ 
89+ 		if  (UNEXPECTED (written  <  0 )) {
90+ 			php_gziop_report_errors (stream , count , "Write" );
91+ 			return  written ;
92+ 		}
6893
69- 	/* XXX this needs to be looped for the case count > UINT_MAX */ 
70- 	int  written  =  gzwrite (self -> gz_file , (char  * ) buf , count );
71- 
72- 	/* Notify user of error, like the standard file wrapper normally does (e.g. errno=13 on mandatory lock failure). */ 
73- 	if  (UNEXPECTED (written  <  0 )) {
74- 		php_gziop_report_errors (stream , count , "Write" );
75- 	}
94+ 		total_written  +=  written ;
95+ 		buf  +=  written ;
96+ 	} while  (count  >  0 );
7697
77- 	 return  written ;
98+      return  total_written ;
7899}
79100
80101static  int  php_gziop_seek (php_stream  * stream , zend_off_t  offset , int  whence , zend_off_t  * newoffs )
0 commit comments