Skip to content

Commit a35dafc

Browse files
cre4turesylvestre
authored andcommitted
consider "fullblock" cmd line arg also for block writes
1 parent a626899 commit a35dafc

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

src/uu/dd/src/dd.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

107107
impl 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 {
@@ -831,6 +831,30 @@ impl<'a> Output<'a> {
831831
}
832832
}
833833

834+
/// writes a block of data. optionally retries when first try didn't complete
835+
///
836+
/// this is needed by gnu-test: tests/dd/stats.s
837+
/// the write can be interrupted by a system signal.
838+
/// e.g. SIGUSR1 which is send to report status
839+
/// without retry, the data might not be fully written to destination.
840+
fn write_block(&mut self, chunk: &[u8]) -> io::Result<usize> {
841+
let full_len = chunk.len();
842+
let mut base_idx = 0;
843+
loop {
844+
match self.dst.write(&chunk[base_idx..]) {
845+
Ok(wlen) => {
846+
base_idx += wlen;
847+
// take iflags.fullblock as oflags shall not have this option
848+
if (base_idx >= full_len) || !self.settings.iflags.fullblock {
849+
return Ok(base_idx);
850+
}
851+
}
852+
Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
853+
Err(e) => return Err(e),
854+
}
855+
}
856+
}
857+
834858
/// Write the given bytes one block at a time.
835859
///
836860
/// This may write partial blocks (for example, if the underlying
@@ -844,7 +868,7 @@ impl<'a> Output<'a> {
844868
let mut bytes_total = 0;
845869

846870
for chunk in buf.chunks(self.settings.obs) {
847-
let wlen = self.dst.write(chunk)?;
871+
let wlen = self.write_block(chunk)?;
848872
if wlen < self.settings.obs {
849873
writes_partial += 1;
850874
} else {
@@ -1118,10 +1142,10 @@ fn dd_copy(mut i: Input, o: Output) -> std::io::Result<()> {
11181142
rstat += rstat_update;
11191143
wstat += wstat_update;
11201144
match alarm.get_trigger() {
1121-
TRIGGER_NONE => {}
1122-
t @ TRIGGER_TIMER | t @ TRIGGER_SIGNAL => {
1145+
ALARM_TRIGGER_NONE => {}
1146+
t @ ALARM_TRIGGER_TIMER | t @ ALARM_TRIGGER_SIGNAL => {
11231147
let tp = match t {
1124-
TRIGGER_TIMER => ProgUpdateType::Periodic,
1148+
ALARM_TRIGGER_TIMER => ProgUpdateType::Periodic,
11251149
_ => ProgUpdateType::Signal,
11261150
};
11271151
let prog_update = ProgUpdate::new(rstat, wstat, start.elapsed(), tp);

0 commit comments

Comments
 (0)