[libos] Fix error handling of sendfile
This commit is contained in:
parent
eba7e08453
commit
40ad9d1648
@ -22,28 +22,66 @@ pub fn do_sendfile(
|
||||
None => in_file.seek(SeekFrom::Current(0))?,
|
||||
} as usize;
|
||||
|
||||
// read from specified offset and write new offset back
|
||||
let mut bytes_read = 0;
|
||||
while bytes_read < count {
|
||||
let len = min(buffer.len(), count - bytes_read);
|
||||
let read_len = in_file.read_at(read_offset, &mut buffer[..len])?;
|
||||
if read_len == 0 {
|
||||
break;
|
||||
}
|
||||
bytes_read += read_len;
|
||||
read_offset += read_len;
|
||||
// write_file is used to write buffer into out_file, the closure avoids complex loop structure
|
||||
let mut write_file = |buffer: &[u8]| -> Result<usize> {
|
||||
let buffer_len = buffer.len();
|
||||
let mut bytes_written = 0;
|
||||
while bytes_written < read_len {
|
||||
let write_len = out_file.write(&buffer[bytes_written..read_len])?;
|
||||
if write_len == 0 {
|
||||
return_errno!(EBADF, "sendfile write return 0");
|
||||
let mut write_error = None;
|
||||
|
||||
while bytes_written < buffer_len {
|
||||
match out_file.write(&buffer[bytes_written..]) {
|
||||
Ok(write_len) => {
|
||||
debug_assert!(write_len > 0);
|
||||
bytes_written += write_len;
|
||||
}
|
||||
Err(e) => {
|
||||
// handle sendmsg return err
|
||||
write_error = Some(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bytes_written > 0 {
|
||||
Ok(bytes_written)
|
||||
} else {
|
||||
// if bytes_written = 0, write_error must be Some(e).
|
||||
Err(write_error.unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
// read from specified offset and write new offset back
|
||||
let mut bytes_sent = 0;
|
||||
let mut send_error = None;
|
||||
while bytes_sent < count {
|
||||
let len = min(buffer.len(), count - bytes_sent);
|
||||
|
||||
match in_file.read_at(read_offset, &mut buffer[..len]) {
|
||||
Ok(read_len) if read_len > 0 => match write_file(&buffer[..read_len]) {
|
||||
Ok(write_len) => {
|
||||
bytes_sent += write_len;
|
||||
read_offset += write_len;
|
||||
}
|
||||
Err(e) => {
|
||||
send_error = Some(e);
|
||||
break;
|
||||
}
|
||||
},
|
||||
Ok(..) => break,
|
||||
Err(e) => {
|
||||
send_error = Some(e);
|
||||
break;
|
||||
}
|
||||
bytes_written += write_len;
|
||||
}
|
||||
}
|
||||
|
||||
if offset.is_none() {
|
||||
in_file.seek(SeekFrom::Current(bytes_read as i64))?;
|
||||
in_file.seek(SeekFrom::Current(bytes_sent as i64))?;
|
||||
}
|
||||
|
||||
if bytes_sent > 0 {
|
||||
Ok((bytes_sent, read_offset))
|
||||
} else {
|
||||
send_error.map_or_else(|| Ok((0, read_offset)), |e| Err(e))
|
||||
}
|
||||
Ok((bytes_read, read_offset))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user