@@ -87,9 +87,9 @@ struct Settings {
8787/// A timer which triggers on a given interval
8888///
8989/// After being constructed with [`Alarm::with_interval`], [`Alarm::get_trigger`]
90- /// will return [`TRIGGER_TIMER `] once per the given [`Duration`].
90+ /// will return [`ALARM_TRIGGER_TIMER `] once per the given [`Duration`].
9191/// Alarm can be manually triggered with closure returned by [`Alarm::manual_trigger_fn`].
92- /// [`Alarm::get_trigger`] will return [`TRIGGER_SIGNAL `] in this case.
92+ /// [`Alarm::get_trigger`] will return [`ALARM_TRIGGER_SIGNAL `] in this case.
9393///
9494/// Can be cloned, but the trigger status is shared across all instances so only
9595/// the first caller each interval will yield true.
@@ -100,9 +100,9 @@ pub struct Alarm {
100100 trigger : Arc < AtomicU8 > ,
101101}
102102
103- const TRIGGER_NONE : u8 = 0 ;
104- const TRIGGER_TIMER : u8 = 1 ;
105- const TRIGGER_SIGNAL : u8 = 2 ;
103+ pub const ALARM_TRIGGER_NONE : u8 = 0 ;
104+ pub const ALARM_TRIGGER_TIMER : u8 = 1 ;
105+ pub const ALARM_TRIGGER_SIGNAL : u8 = 2 ;
106106
107107impl Alarm {
108108 pub fn with_interval ( interval : Duration ) -> Self {
@@ -112,7 +112,7 @@ impl Alarm {
112112 thread:: spawn ( move || {
113113 while let Some ( trigger) = weak_trigger. upgrade ( ) {
114114 thread:: sleep ( interval) ;
115- trigger. store ( TRIGGER_TIMER , Relaxed ) ;
115+ trigger. store ( ALARM_TRIGGER_TIMER , Relaxed ) ;
116116 }
117117 } ) ;
118118
@@ -123,13 +123,13 @@ impl Alarm {
123123 let weak_trigger = Arc :: downgrade ( & self . trigger ) ;
124124 Box :: new ( move || {
125125 if let Some ( trigger) = weak_trigger. upgrade ( ) {
126- trigger. store ( TRIGGER_SIGNAL , Relaxed ) ;
126+ trigger. store ( ALARM_TRIGGER_SIGNAL , Relaxed ) ;
127127 }
128128 } )
129129 }
130130
131131 pub fn get_trigger ( & self ) -> u8 {
132- self . trigger . swap ( TRIGGER_NONE , Relaxed )
132+ self . trigger . swap ( ALARM_TRIGGER_NONE , Relaxed )
133133 }
134134
135135 pub fn get_interval ( & self ) -> Duration {
@@ -822,6 +822,30 @@ impl<'a> Output<'a> {
822822 }
823823 }
824824
825+ /// writes a block of data. optionally retries when first try didn't complete
826+ ///
827+ /// this is needed by gnu-test: tests/dd/stats.s
828+ /// the write can be interrupted by a system signal.
829+ /// e.g. SIGUSR1 which is send to report status
830+ /// without retry, the data might not be fully written to destination.
831+ fn write_block ( & mut self , chunk : & [ u8 ] ) -> io:: Result < usize > {
832+ let full_len = chunk. len ( ) ;
833+ let mut base_idx = 0 ;
834+ loop {
835+ match self . dst . write ( & chunk[ base_idx..] ) {
836+ Ok ( wlen) => {
837+ base_idx += wlen;
838+ // take iflags.fullblock as oflags shall not have this option
839+ if ( base_idx >= full_len) || !self . settings . iflags . fullblock {
840+ return Ok ( base_idx) ;
841+ }
842+ }
843+ Err ( e) if e. kind ( ) == io:: ErrorKind :: Interrupted => continue ,
844+ Err ( e) => return Err ( e) ,
845+ }
846+ }
847+ }
848+
825849 /// Write the given bytes one block at a time.
826850 ///
827851 /// This may write partial blocks (for example, if the underlying
@@ -835,7 +859,7 @@ impl<'a> Output<'a> {
835859 let mut bytes_total = 0 ;
836860
837861 for chunk in buf. chunks ( self . settings . obs ) {
838- let wlen = self . dst . write ( chunk) ?;
862+ let wlen = self . write_block ( chunk) ?;
839863 if wlen < self . settings . obs {
840864 writes_partial += 1 ;
841865 } else {
@@ -1109,10 +1133,10 @@ fn dd_copy(mut i: Input, o: Output) -> std::io::Result<()> {
11091133 rstat += rstat_update;
11101134 wstat += wstat_update;
11111135 match alarm. get_trigger ( ) {
1112- TRIGGER_NONE => { }
1113- t @ TRIGGER_TIMER | t @ TRIGGER_SIGNAL => {
1136+ ALARM_TRIGGER_NONE => { }
1137+ t @ ALARM_TRIGGER_TIMER | t @ ALARM_TRIGGER_SIGNAL => {
11141138 let tp = match t {
1115- TRIGGER_TIMER => ProgUpdateType :: Periodic ,
1139+ ALARM_TRIGGER_TIMER => ProgUpdateType :: Periodic ,
11161140 _ => ProgUpdateType :: Signal ,
11171141 } ;
11181142 let prog_update = ProgUpdate :: new ( rstat, wstat, start. elapsed ( ) , tp) ;
0 commit comments