@@ -23,6 +23,19 @@ fn path(prefix: &Path, file: &str) -> String {
23
23
path_buf. as_path ( ) . to_str ( ) . unwrap ( ) . to_owned ( )
24
24
}
25
25
26
+ // Return an open(2) mode, modified as needed to support binary files on the target platform.
27
+ fn binary_mode ( mode : c_int ) -> c_int {
28
+ #[ cfg( target_os = "windows" ) ]
29
+ {
30
+ mode | libc:: O_BINARY
31
+ }
32
+
33
+ #[ cfg( not( target_os = "windows" ) ) ]
34
+ {
35
+ mode
36
+ }
37
+ }
38
+
26
39
// Try to gzopen a file path with a specified mode, and panic if the result is unexpected.
27
40
// NOTE: This is a macro, instead of a function, so that the test runner will report errors
28
41
// with the line number where it is invoked.
@@ -287,6 +300,58 @@ fn gzread_special_cases() {
287
300
) ;
288
301
assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
289
302
}
303
+
304
+ // Create a gzip file with some junk data after the end of the deflate stream.
305
+ // gzread should ignore the junk data.
306
+ // Create a temporary directory that will be automatically removed when
307
+ // temp_dir goes out of scope.
308
+ let temp_dir_path = temp_base ( ) ;
309
+ let temp_dir = tempfile:: TempDir :: new_in ( temp_dir_path) . unwrap ( ) ;
310
+ let temp_path = temp_dir. path ( ) ;
311
+ let file_name = path ( temp_path, "output.gz" ) ;
312
+ let file = unsafe {
313
+ gzopen (
314
+ CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
315
+ CString :: new ( "w" ) . unwrap ( ) . as_ptr ( ) ,
316
+ )
317
+ } ;
318
+ assert ! ( !file. is_null( ) ) ;
319
+ const STRING1 : & [ u8 ] = b"deflated contents" ;
320
+ const STRING2 : & [ u8 ] = b"\n trailing data" ;
321
+ assert_eq ! (
322
+ unsafe { gzwrite( file, STRING1 . as_ptr( ) . cast:: <c_void>( ) , STRING1 . len( ) as _) } ,
323
+ STRING1 . len( ) as _
324
+ ) ;
325
+ assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
326
+ let old_size = file_size ( & file_name) . unwrap ( ) ;
327
+ let fd = unsafe {
328
+ libc:: open (
329
+ CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
330
+ binary_mode ( libc:: O_APPEND | libc:: O_WRONLY ) ,
331
+ )
332
+ } ;
333
+ assert_ne ! ( fd, -1 ) ;
334
+ assert_eq ! (
335
+ unsafe { libc:: write( fd, STRING2 . as_ptr( ) . cast:: <c_void>( ) , STRING2 . len( ) as _) } ,
336
+ STRING2 . len( ) as _
337
+ ) ;
338
+ assert_eq ! ( unsafe { libc:: close( fd) } , 0 ) ;
339
+ let new_size = file_size ( & file_name) . unwrap ( ) ;
340
+ assert_eq ! ( new_size, old_size + STRING2 . len( ) ) ;
341
+ let file = unsafe {
342
+ gzopen (
343
+ CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
344
+ CString :: new ( "r" ) . unwrap ( ) . as_ptr ( ) ,
345
+ )
346
+ } ;
347
+ assert ! ( !file. is_null( ) ) ;
348
+ // Read more than expected to make sure we get everything.
349
+ let mut buf = [ 0u8 ; STRING1 . len ( ) + 1 ] ;
350
+ assert_eq ! (
351
+ unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } ,
352
+ STRING1 . len( ) as _
353
+ ) ;
354
+ assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
290
355
}
291
356
292
357
#[ test]
@@ -720,16 +785,10 @@ fn gzoffset_gztell_read() {
720
785
// header. This should affect the return values of gzoffset but not gztell.
721
786
const OFFSET : usize = 123 ;
722
787
const PADDING : & [ u8 ] = & [ 0u8 ; OFFSET ] ;
723
- let mut mode = libc:: O_CREAT ;
724
- mode |= libc:: O_WRONLY ;
725
- #[ cfg( target_os = "windows" ) ]
726
- {
727
- mode |= libc:: O_BINARY ;
728
- }
729
788
let fd = unsafe {
730
789
libc:: open (
731
790
CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
732
- mode ,
791
+ binary_mode ( libc :: O_CREAT | libc :: O_WRONLY ) ,
733
792
0o644 ,
734
793
)
735
794
} ;
@@ -739,11 +798,7 @@ fn gzoffset_gztell_read() {
739
798
OFFSET as _
740
799
) ;
741
800
let source_name = crate_path ( "src/test-data/issue-109.gz" ) ;
742
- mode = libc:: O_RDONLY ;
743
- #[ cfg( target_os = "windows" ) ]
744
- {
745
- mode |= libc:: O_BINARY ;
746
- }
801
+ let mode = binary_mode ( libc:: O_RDONLY ) ;
747
802
let source_fd =
748
803
unsafe { libc:: open ( CString :: new ( source_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) , mode) } ;
749
804
assert_ne ! ( source_fd, -1 ) ;
@@ -910,12 +965,7 @@ fn gzputc_basic() {
910
965
assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
911
966
912
967
// Validate that the file contains the expected bytes.
913
- let mut mode = 0 ;
914
- #[ cfg( target_os = "windows" ) ]
915
- {
916
- mode |= libc:: O_BINARY ;
917
- }
918
- mode |= libc:: O_RDONLY ;
968
+ let mode = binary_mode ( libc:: O_RDONLY ) ;
919
969
let fd = unsafe { libc:: open ( CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) , mode) } ;
920
970
assert_ne ! ( fd, -1 ) ;
921
971
// Try to read more than the expected amount of data, to ensure we get everything.
@@ -988,12 +1038,7 @@ fn gzputs_basic() {
988
1038
989
1039
// Validate that the file contains the expected bytes.
990
1040
const EXPECTED : & str = "zlib string larger than the buffer size" ;
991
- let mut mode = 0 ;
992
- #[ cfg( target_os = "windows" ) ]
993
- {
994
- mode |= libc:: O_BINARY ;
995
- }
996
- mode |= libc:: O_RDONLY ;
1041
+ let mode = binary_mode ( libc:: O_RDONLY ) ;
997
1042
let fd = unsafe { libc:: open ( CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) , mode) } ;
998
1043
assert_ne ! ( fd, -1 ) ;
999
1044
// Try to read more than the expected amount of data, to ensure we get everything.
@@ -1446,12 +1491,7 @@ fn gzfwrite_basic() {
1446
1491
assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
1447
1492
1448
1493
// Read in the file and verify that the contents match what was passed to gzfwrite.
1449
- let mut mode = 0 ;
1450
- #[ cfg( target_os = "windows" ) ]
1451
- {
1452
- mode |= libc:: O_BINARY ;
1453
- }
1454
- mode |= libc:: O_RDONLY ;
1494
+ let mode = binary_mode ( libc:: O_RDONLY ) ;
1455
1495
let fd = unsafe { libc:: open ( CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) , mode) } ;
1456
1496
assert_ne ! ( fd, -1 ) ;
1457
1497
const EXPECTED : & [ u8 ] = b"test of gzfwrite" ;
@@ -1642,16 +1682,10 @@ fn gzseek_read() {
1642
1682
// all the implementation paths for gzseek.
1643
1683
let gzip_file_name = crate_path ( "src/test-data/issue-109.gz" ) ;
1644
1684
let direct_file_name = path ( temp_path, "uncompressed" ) ;
1645
- let mut mode = libc:: O_CREAT ;
1646
- #[ cfg( target_os = "windows" ) ]
1647
- {
1648
- mode |= libc:: O_BINARY ;
1649
- }
1650
- mode |= libc:: O_WRONLY ;
1651
1685
let fd = unsafe {
1652
1686
libc:: open (
1653
1687
CString :: new ( direct_file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
1654
- mode ,
1688
+ binary_mode ( libc :: O_CREAT | libc :: O_WRONLY ) ,
1655
1689
0o644 ,
1656
1690
)
1657
1691
} ;
@@ -1883,7 +1917,10 @@ fn gzseek_gzsetparams() {
1883
1917
1884
1918
// Write some content to the file handle.
1885
1919
const STRING1 : & [ u8 ] = b"hello" ;
1886
- assert_eq ! ( unsafe { gzwrite( file, STRING1 . as_ptr( ) . cast:: <c_void>( ) , STRING1 . len( ) as _) } , STRING1 . len( ) as _) ;
1920
+ assert_eq ! (
1921
+ unsafe { gzwrite( file, STRING1 . as_ptr( ) . cast:: <c_void>( ) , STRING1 . len( ) as _) } ,
1922
+ STRING1 . len( ) as _
1923
+ ) ;
1887
1924
1888
1925
// Call gzseek to schedule a pending write of some zeros to the compressed stream.
1889
1926
const SEEK_AMOUNT : usize = 4 ;
@@ -1897,7 +1934,10 @@ fn gzseek_gzsetparams() {
1897
1934
// Write some more content to the file handle. This will end up in the second gzip stream
1898
1935
// in the file.
1899
1936
const STRING2 : & [ u8 ] = b"world" ;
1900
- assert_eq ! ( unsafe { gzwrite( file, STRING2 . as_ptr( ) . cast:: <c_void>( ) , STRING2 . len( ) as _) } , STRING2 . len( ) as _) ;
1937
+ assert_eq ! (
1938
+ unsafe { gzwrite( file, STRING2 . as_ptr( ) . cast:: <c_void>( ) , STRING2 . len( ) as _) } ,
1939
+ STRING2 . len( ) as _
1940
+ ) ;
1901
1941
1902
1942
// Close the file handle to flush any buffered output to the file.
1903
1943
assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
@@ -1913,13 +1953,19 @@ fn gzseek_gzsetparams() {
1913
1953
1914
1954
// Read back the content to validate that it was written correctly.
1915
1955
let mut buf = [ 127u8 ; STRING1 . len ( ) ] ;
1916
- assert_eq ! ( unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } , buf. len( ) as _) ;
1956
+ assert_eq ! (
1957
+ unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } ,
1958
+ buf. len( ) as _
1959
+ ) ;
1917
1960
assert_eq ! ( & buf, STRING1 ) ;
1918
1961
for _ in 0 ..SEEK_AMOUNT {
1919
1962
assert_eq ! ( unsafe { gzgetc( file) } , 0 ) ;
1920
1963
}
1921
1964
let mut buf = [ 127u8 ; STRING2 . len ( ) + 1 ] ;
1922
- assert_eq ! ( unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } , ( buf. len( ) - 1 ) as _) ;
1965
+ assert_eq ! (
1966
+ unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } ,
1967
+ ( buf. len( ) - 1 ) as _
1968
+ ) ;
1923
1969
assert_eq ! ( & buf[ ..STRING2 . len( ) ] , STRING2 ) ;
1924
1970
1925
1971
assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
0 commit comments