pub(super) fn read_bytes_fallible<T: Task>(
    task: &mut T,
    addr: RemotePtr<Void>,
    buf: &mut [u8],
) -> Result<usize, ()> {
    if buf.len() == 0 {
        return Ok(0);
    }

    match task.vm().local_mapping(addr, buf.len()) {
        Some(found) => {
            buf.copy_from_slice(&found[0..buf.len()]);
            return Ok(buf.len());
        }
        None => (),
    }

    if !task.vm().mem_fd().is_open() {
        return Ok(task.read_bytes_ptrace(addr, buf));
    }

    let mut all_read = 0;
    while all_read < buf.len() {
        Errno::clear();
        let nread: isize = unsafe {
            pread64(
                task.vm().mem_fd().as_raw(),
                buf.get_mut(all_read..)
                    .unwrap()
                    .as_mut_ptr()
                    .cast::<c_void>(),
                // How much more left to read
                buf.len() - all_read,
                // Where you're reading from in the tracee
                // This is of type off_t which is a i32 in x86 and i64 on x64
                (addr.as_usize() + all_read) as isize as _,
            )
        };
        // We open the mem_fd just after being notified of
        // exec(), when the Task is created.  Trying to read from that
        // fd seems to return 0 with errno 0.  Reopening the mem fd
        // allows the pwrite to succeed.  It seems that the first mem
        // fd we open, very early in exec, refers to the address space
        // before the exec and the second mem fd refers to the address
        // space after exec.
        if 0 == nread && 0 == all_read && 0 == errno() {
            // If we couldn't open the mem fd, then report 0 bytes read
            if !task.open_mem_fd() {
                // @TODO is this a wise decision?
                // Hmmm.. given that errno is 0 it seems logical.
                return Ok(0);
            }
            // Try again
            continue;
        }
        if nread <= 0 {
            if all_read > 0 {
                // We did successfully read _some_ data, so return success and ignore
                // any error.
                Errno::clear();
                return Ok(all_read);
            }
            return Err(());
        }
        // We read some data. We should try again in case we get short reads.
        all_read += nread as usize;
    }

    Ok(all_read)
}
/// Forwarded method definition
///
/// Read/write the number of bytes.
/// Number of bytes read can be less than desired
/// - Returns Err(()) if No bytes could be read at all AND there was an error
/// - Returns Ok(usize) if 0 or more bytes could be read. All bytes requested may not have been
/// read.
Forwarded method definition
Read/write the number of bytes.
Number of bytes read can be less than desired
Returns Err(()) if No bytes could be read at all AND there was an error
Returns Ok(usize) if 0 or more bytes could be read. All bytes requested may not have been
read.
Forwarded method definition Read / write the number of bytes . Number of bytes read can be less than desired Returns Err (( )) if No bytes could be read at all AND there was an error Returns Ok ( usize ) if 0 or more bytes could be read . All bytes requested may not have been read .
pub(super) fn read_bytes_fallible<T: Task>(
    task: &mut T,
    addr: RemotePtr<Void>,
    buf: &mut [u8],
) -> Result<usize, ()> {
    if buf.len() == 0 {
        return Ok(0);
    }
    match task.vm().local_mapping(addr, buf.len()) {
        Some(found) => {
            buf.copy_from_slice(&found[0..buf.len()]);
            return Ok(buf.len());
        }
        None => (),
    }
    if !task.vm().mem_fd().is_open() {
        return Ok(task.read_bytes_ptrace(addr, buf));
    }
    let mut all_read = 0;
    while all_read < buf.len() {
        Errno::clear();
        let nread: isize = unsafe {
            pread64(
                task.vm().mem_fd().as_raw(),
                buf.get_mut(all_read..)
                    .unwrap()
                    .as_mut_ptr()
                    .cast::<c_void>(),
                // How much more left to read
                buf.len() - all_read,
                // Where you're reading from in the tracee
                // This is of type off_t which is a i32 in x86 and i64 on x64
                (addr.as_usize() + all_read) as isize as _,
            )
        };
        // We open the mem_fd just after being notified of
        // exec(), when the Task is created.  Trying to read from that
        // fd seems to return 0 with errno 0.  Reopening the mem fd
        // allows the pwrite to succeed.  It seems that the first mem
        // fd we open, very early in exec, refers to the address space
        // before the exec and the second mem fd refers to the address
        // space after exec.
        if 0 == nread && 0 == all_read && 0 == errno() {
            // If we couldn't open the mem fd, then report 0 bytes read
            if !task.open_mem_fd() {
                // @TODO is this a wise decision?
                // Hmmm.. given that errno is 0 it seems logical.
                return Ok(0);
            }
            // Try again
            continue;
        }
        if nread <= 0 {
            if all_read > 0 {
                // We did successfully read _some_ data, so return success and ignore
                // any error.
                Errno::clear();
                return Ok(all_read);
            }
            return Err(());
        }
        // We read some data. We should try again in case we get short reads.
        all_read += nread as usize;
    }
    Ok(all_read)
}
pub ( super ) fn read_bytes_fallible < T : Task > ( task : & mut T , addr : RemotePtr < Void > , buf : & mut [ u8 ] , ) -> Result < usize , ( ) > { if buf . len ( ) == 0 { return Ok ( 0 ) ; } match task . vm ( ) . local_mapping ( addr , buf . len ( ) ) { Some ( found ) => { buf . copy_from_slice ( & found [ 0 .. buf . len ( ) ] ) ; return Ok ( buf . len ( ) ) ; } None => ( ) , } if ! task . vm ( ) . mem_fd ( ) . is_open ( ) { return Ok ( task . read_bytes_ptrace ( addr , buf ) ) ; } let mut all_read = 0 ; while all_read < buf . len ( ) { Errno :: clear ( ) ; let nread : isize = unsafe { pread64 ( task . vm ( ) . mem_fd ( ) . as_raw ( ) , buf . get_mut ( all_read .. ) . unwrap ( ) . as_mut_ptr ( ) . cast :: < c_void > ( ) , // How much more left to read buf . len ( ) - all_read , // Where you're reading from in the tracee // This is of type off_t which is a i32 in x86 and i64 on x64 ( addr . as_usize ( ) + all_read ) as isize as _ , ) } ; // We open the mem_fd just after being notified of // exec(), when the Task is created.  Trying to read from that // fd seems to return 0 with errno 0.  Reopening the mem fd // allows the pwrite to succeed.  It seems that the first mem // fd we open, very early in exec, refers to the address space // before the exec and the second mem fd refers to the address // space after exec. if 0 == nread && 0 == all_read && 0 == errno ( ) { // If we couldn't open the mem fd, then report 0 bytes read if ! task . open_mem_fd ( ) { // @TODO is this a wise decision? // Hmmm.. given that errno is 0 it seems logical. return Ok ( 0 ) ; } // Try again continue ; } if nread <= 0 { if all_read > 0 { // We did successfully read _some_ data, so return success and ignore // any error. Errno :: clear ( ) ; return Ok ( all_read ) ; } return Err ( ( ) ) ; } // We read some data. We should try again in case we get short reads. all_read += nread as usize ; } Ok ( all_read ) }
Forwarded method definition
Read/write the number of bytes.
Forwarded method definition Read / write the number of bytes .
task
&mut T
addr
RemotePtr<Void>
buf
&mut [u8]