@@ -3,7 +3,7 @@ use zlib_rs::c_api::*;
3
3
use libz_rs_sys:: {
4
4
gzFile_s, gzbuffer, gzclearerr, gzclose, gzclose_r, gzclose_w, gzdirect, gzdopen, gzerror,
5
5
gzflush, gzfread, gzfwrite, gzgetc, gzgetc_, gzgets, gzoffset, gzopen, gzputc, gzputs, gzread,
6
- gztell, gzungetc, gzwrite,
6
+ gzsetparams , gztell, gzungetc, gzwrite,
7
7
} ;
8
8
9
9
use libc:: size_t;
@@ -1472,6 +1472,134 @@ fn gzfwrite_error() {
1472
1472
assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
1473
1473
}
1474
1474
1475
+ #[ test]
1476
+ fn gzsetparams_basic ( ) {
1477
+ // Create a temporary directory that will be automatically removed when
1478
+ // temp_dir goes out of scope.
1479
+ let temp_dir_path = temp_base ( ) ;
1480
+ let temp_dir = tempfile:: TempDir :: new_in ( temp_dir_path) . unwrap ( ) ;
1481
+ let temp_path = temp_dir. path ( ) ;
1482
+ let file_name = path ( temp_path, "output.gz" ) ;
1483
+
1484
+ // Open a file for writing.
1485
+ let file = unsafe {
1486
+ gzopen (
1487
+ CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
1488
+ CString :: new ( "w" ) . unwrap ( ) . as_ptr ( ) ,
1489
+ )
1490
+ } ;
1491
+ assert ! ( !file. is_null( ) ) ;
1492
+
1493
+ // Call gzsetparams before doing any writes. It should return Z_OK and should
1494
+ // not cause any file I/O yet.
1495
+ assert_eq ! ( unsafe { gzsetparams( file, 2 , 0 ) } , Z_OK ) ;
1496
+ assert_eq ! ( file_size( & file_name) . unwrap( ) , 0 ) ;
1497
+
1498
+ // Provide some data to the file descriptor for compression. The deflate output
1499
+ // should be buffered, so the file size should not increase yet.
1500
+ const STRING1 : & [ u8 ] = b"first write " ;
1501
+ assert_eq ! (
1502
+ unsafe { gzwrite( file, STRING1 . as_ptr( ) . cast:: <c_void>( ) , STRING1 . len( ) as _) } ,
1503
+ STRING1 . len( ) as _
1504
+ ) ;
1505
+ assert_eq ! ( file_size( & file_name) . unwrap( ) , 0 ) ;
1506
+
1507
+ // Call gzsetparams to change the deflate parameters. It should return Z_OK and should
1508
+ // flush some of the previously buffered data to the file.
1509
+ assert_eq ! ( unsafe { gzsetparams( file, 9 , 0 ) } , Z_OK ) ;
1510
+ let size = file_size ( & file_name) . unwrap ( ) ;
1511
+ assert ! ( size > 0 ) ;
1512
+
1513
+ // Write more data to the file descriptor.
1514
+ const STRING2 : & [ u8 ] = b"second write " ;
1515
+ assert_eq ! (
1516
+ unsafe { gzwrite( file, STRING2 . as_ptr( ) . cast:: <c_void>( ) , STRING2 . len( ) as _) } ,
1517
+ STRING2 . len( ) as _
1518
+ ) ;
1519
+
1520
+ // Call gzsetparams with the same parameters as last time. This should be a no-op, returning
1521
+ // Z_OK and not forcing a flush of the buffered write.
1522
+ assert_eq ! ( unsafe { gzsetparams( file, 9 , 0 ) } , Z_OK ) ;
1523
+ assert_eq ! ( file_size( & file_name) . unwrap( ) , size) ;
1524
+
1525
+ // Call gzsetparams with different parameters. This should return Z_OK and should flush
1526
+ // the previously buffered output to the file.
1527
+ assert_eq ! ( unsafe { gzsetparams( file, 9 , 1 ) } , Z_OK ) ;
1528
+ let new_size = file_size ( & file_name) . unwrap ( ) ;
1529
+ assert ! ( new_size > size) ;
1530
+ let size = new_size;
1531
+
1532
+ // Do another write, and close the file.
1533
+ const STRING3 : & [ u8 ] = b"third write" ;
1534
+ assert_eq ! (
1535
+ unsafe { gzwrite( file, STRING3 . as_ptr( ) . cast:: <c_void>( ) , STRING3 . len( ) as _) } ,
1536
+ STRING3 . len( ) as _
1537
+ ) ;
1538
+ assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
1539
+ let new_size = file_size ( & file_name) . unwrap ( ) ;
1540
+ assert ! ( new_size > size) ;
1541
+
1542
+ // Read and uncompress the file. We should get back the concatenation of all the
1543
+ // content written to it.
1544
+ let file = unsafe {
1545
+ gzopen (
1546
+ CString :: new ( file_name. as_str ( ) ) . unwrap ( ) . as_ptr ( ) ,
1547
+ CString :: new ( "r" ) . unwrap ( ) . as_ptr ( ) ,
1548
+ )
1549
+ } ;
1550
+ assert ! ( !file. is_null( ) ) ;
1551
+ const EXPECTED : & [ u8 ] = b"first write second write third write" ;
1552
+ let mut buf = [ 0u8 ; EXPECTED . len ( ) + 1 ] ;
1553
+ assert_eq ! (
1554
+ unsafe { gzread( file, buf. as_mut_ptr( ) . cast:: <c_void>( ) , buf. len( ) as _) } ,
1555
+ EXPECTED . len( ) as _
1556
+ ) ;
1557
+ assert_eq ! ( & buf[ ..EXPECTED . len( ) ] , EXPECTED ) ;
1558
+ assert_eq ! ( unsafe { gzclose( file) } , Z_OK ) ;
1559
+ }
1560
+
1561
+ #[ test]
1562
+ fn gzsetparams_error ( ) {
1563
+ // gzsetparams on a null file handle should return Z_STREAM_ERROR.
1564
+ assert_eq ! (
1565
+ unsafe { gzsetparams( ptr:: null_mut( ) , 1 , 0 ) } ,
1566
+ Z_STREAM_ERROR
1567
+ ) ;
1568
+
1569
+ // gzsetparams on a read-only file should return Z_STREAM_ERROR.
1570
+ let file = unsafe { gzdopen ( -2 , CString :: new ( "r" ) . unwrap ( ) . as_ptr ( ) ) } ;
1571
+ assert ! ( !file. is_null( ) ) ;
1572
+ assert_eq ! ( unsafe { gzsetparams( file, 1 , 0 ) } , Z_STREAM_ERROR ) ;
1573
+ assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
1574
+
1575
+ // gzsetparams on a file in direct-write mode should return Z_STREAM_ERROR.
1576
+ let file = unsafe { gzdopen ( -2 , CString :: new ( "wT" ) . unwrap ( ) . as_ptr ( ) ) } ;
1577
+ assert ! ( !file. is_null( ) ) ;
1578
+ assert_eq ! ( unsafe { gzsetparams( file, 1 , 0 ) } , Z_STREAM_ERROR ) ;
1579
+ assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
1580
+
1581
+ // gzsetparams with an invalid strategy should return Z_STREAM_ERROR.
1582
+ let file = unsafe { gzdopen ( -2 , CString :: new ( "w" ) . unwrap ( ) . as_ptr ( ) ) } ;
1583
+ assert ! ( !file. is_null( ) ) ;
1584
+ assert_eq ! ( unsafe { gzsetparams( file, 1 , 0 ) } , Z_OK ) ;
1585
+ assert_eq ! ( unsafe { gzsetparams( file, 1 , -1 ) } , Z_STREAM_ERROR ) ;
1586
+ assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
1587
+
1588
+ // Open a gzip file handle around an invalid file descriptor, do a buffered write,
1589
+ // and then call gzsetparams with valid parameters. This should trigger a file
1590
+ // write that fails, resulting in an error code bubbling back up through
1591
+ // through gzsetparams.
1592
+ let file = unsafe { gzdopen ( -2 , CString :: new ( "w" ) . unwrap ( ) . as_ptr ( ) ) } ;
1593
+ assert ! ( !file. is_null( ) ) ;
1594
+ const CONTENT : & [ u8 ] = b"0123456789" ;
1595
+ assert_eq ! (
1596
+ unsafe { gzwrite( file, CONTENT . as_ptr( ) . cast:: <c_void>( ) , CONTENT . len( ) as _) } ,
1597
+ CONTENT . len( ) as _
1598
+ ) ;
1599
+ assert_eq ! ( unsafe { gzsetparams( file, 1 , 2 ) } , Z_ERRNO ) ;
1600
+ assert_eq ! ( unsafe { gzclose( file) } , Z_ERRNO ) ;
1601
+ }
1602
+
1475
1603
// Get the size in bytes of a file.
1476
1604
//
1477
1605
// # Returns
0 commit comments