2019-03-16 16:22:14 +03:00
use std ::io ::Write ;
2022-04-10 18:44:34 +03:00
use std ::path ::PathBuf ;
use std ::thread ;
2019-03-16 16:22:14 +03:00
2021-10-08 12:19:37 +03:00
use anyhow ::{ bail , Error } ;
2019-03-16 16:22:14 +03:00
// tar handle files that shrink during backup, by simply padding with zeros.
//
// this binary run multiple thread which writes some large files, then truncates
// them in a loop.
// # tar cf test.tar ./dyntest1/
// tar: dyntest1/testfile0.dat: File shrank by 2768972800 bytes; padding with zeros
// tar: dyntest1/testfile17.dat: File shrank by 2899853312 bytes; padding with zeros
// tar: dyntest1/testfile2.dat: File shrank by 3093422080 bytes; padding with zeros
// tar: dyntest1/testfile7.dat: File shrank by 2833252864 bytes; padding with zeros
// # pxar create test.pxar ./dyntest1/
2020-05-30 17:37:33 +03:00
// Error: detected shrunk file "./dyntest1/testfile0.dat" (22020096 < 12679380992)
2019-03-16 16:22:14 +03:00
fn create_large_file ( path : PathBuf ) {
println! ( " TEST {:?} " , path ) ;
let mut file = std ::fs ::OpenOptions ::new ( )
. write ( true )
. create_new ( true )
2022-04-10 18:44:34 +03:00
. open ( & path )
. unwrap ( ) ;
2019-03-16 16:22:14 +03:00
2022-04-10 18:44:34 +03:00
let buffer = vec! [ 0 u8 ; 64 * 1024 ] ;
2019-03-16 16:22:14 +03:00
loop {
for _ in 0 .. 64 {
file . write_all ( & buffer ) . unwrap ( ) ;
}
file . sync_all ( ) . unwrap ( ) ;
//println!("TRUNCATE {:?}", path);
file . set_len ( 0 ) . unwrap ( ) ;
}
}
fn main ( ) -> Result < ( ) , Error > {
let base = PathBuf ::from ( " dyntest1 " ) ;
let _ = std ::fs ::create_dir ( & base ) ;
let mut handles = vec! [ ] ;
for i in 0 .. 20 {
let base = base . clone ( ) ;
handles . push ( thread ::spawn ( move | | {
create_large_file ( base . join ( format! ( " testfile {} .dat " , i ) ) ) ;
} ) ) ;
}
for h in handles {
2019-10-25 19:04:37 +03:00
if h . join ( ) . is_err ( ) {
2019-03-16 16:22:14 +03:00
bail! ( " join failed " ) ;
}
}
Ok ( ( ) )
}