[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 { | ||||
|     // 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; | ||||
|         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; | ||||
|                 } | ||||
|         bytes_read += read_len; | ||||
|         read_offset += read_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"); | ||||
|             } | ||||
|             bytes_written += write_len; | ||||
|         } | ||||
| 
 | ||||
|         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; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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