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