From ac691912de4689b03b86933e27c209f9fdf5be08 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Sat, 6 Jul 2024 18:09:22 +0530 Subject: [PATCH 1/8] add comments update tests --- src/safeposix/syscalls/fs_calls.rs | 40 ++++++++++++++-- src/tests/fs_tests.rs | 73 +++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/safeposix/syscalls/fs_calls.rs b/src/safeposix/syscalls/fs_calls.rs index 903ea2d04..5f4d785c2 100644 --- a/src/safeposix/syscalls/fs_calls.rs +++ b/src/safeposix/syscalls/fs_calls.rs @@ -1840,7 +1840,40 @@ impl Cage { } //------------------------------------WRITEV SYSCALL------------------------------------ - + /// ## `writev_syscall` + /// + /// ### Description + /// This function writes data to a file descriptor from multiple buffers. + /// Currently, it supports writing to sockets and pipes. + /// The function first retrieves the file descriptor object associated with the provided file descriptor + /// and then matches the file descriptor type and calls the appropriate write function based on the type. + /// * `Sockets`: The function writes data to the connected socket, handling both TCP and UDP sockets. + /// * Checks if the socket is connected (either fully connected or connected for write-only). + /// * If connected, calls the underlying `writev` function on the raw socket. + /// * Handles errors returned by the underlying `writev` function. + /// * `Pipes`: The function writes data to the pipe, supporting non-blocking writes. + /// * Checks if the pipe is open for writing. + /// * Handles non-blocking writes. + /// * Triggers `SIGPIPE` if the pipe is closed on the other end. + /// + /// ### Function Arguments + /// * `fd`: The file descriptor to write to. + /// * `iovec`: A pointer to an array of `IovecStruct` objects representing the data buffers to write. + /// * `iovcnt`: The number of `IovecStruct` objects in the array. + /// + /// ### Returns + /// * The number of bytes written on success. + /// * A negative value on error, with the specific error code set in `errno`. + /// + /// ### Errors + /// * `EBADF(9)`: The file descriptor is invalid. + /// * `ENOTCONN(107)`: The socket is not connected (for sockets). + /// * `EOPNOTSUPP(95)`: The system call is not supported for the given socket protocol. + /// * `EAGAIN(11)`: There is no data available right now (for pipes). + /// * `EPIPE(32)`: The pipe has been closed on the other end (for pipes). + /// ### Panics + /// * If an unknown error code is returned by the underlying socket writev function. + /// [writev(2)](https://linux.die.net/man/2/writev) pub fn writev_syscall( &self, fd: i32, @@ -1855,7 +1888,7 @@ impl Cage { Socket(socket_filedesc_obj) => { let sock_tmp = socket_filedesc_obj.handle.clone(); let sockhandle = sock_tmp.write(); - + // Check the domain of the socket (IPv4 or IPv6) match sockhandle.domain { AF_INET | AF_INET6 => match sockhandle.protocol { IPPROTO_TCP => { @@ -1958,6 +1991,7 @@ impl Cage { } } Pipe(pipe_filedesc_obj) => { + // Check if the pipe is open for writing. if is_rdonly(pipe_filedesc_obj.flags) { return syscall_error( Errno::EBADF, @@ -1970,7 +2004,7 @@ impl Cage { if pipe_filedesc_obj.flags & O_NONBLOCK != 0 { nonblocking = true; } - + // Write to the pipe using vectored I/O. let retval = pipe_filedesc_obj .pipe diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index 372b3b6d0..8a823a09d 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -2461,4 +2461,75 @@ pub mod fs_tests { assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); lindrustfinalize(); } -} + use crate::tests::FileDescriptor::Socket; + use std::thread; + #[test] + fn ut_lind_fs_writev_socketpair() { + let _thelock = setup::lock_and_init(); + let cage = interface::cagetable_getref(1); + + let mut socketpair = interface::SockPair::default(); + assert_eq!( + Cage::socketpair_syscall(cage.clone(), AF_UNIX, SOCK_STREAM, 0, &mut socketpair), + 0 + ); + + let data = b"Hello, world!"; + let iovec = interface::IovecStruct { + iov_base: data.as_ptr() as *mut libc::c_void, + iov_len: data.len(), + }; + + let bytes_written = cage.writev_syscall(socketpair.sock1, &iovec, 1); + assert_eq!(bytes_written, data.len() as i32); + + let mut buffer = vec![0u8; data.len()]; + let bytes_read = cage.recv_syscall(socketpair.sock2, buffer.as_mut_ptr(), buffer.len(), 0); + assert_eq!(bytes_read, data.len() as i32); + + assert_eq!(buffer, data); + + assert_eq!(cage.close_syscall(socketpair.sock1), 0); + assert_eq!(cage.close_syscall(socketpair.sock2), 0); + + assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); + lindrustfinalize(); + } + + #[test] + fn ut_lind_fs_writev_pipe() { + let _thelock = setup::lock_and_init(); + let cage = interface::cagetable_getref(1); + + // Create a pipe + let mut pipe_fds = PipeArray::default(); + assert_eq!(cage.pipe_syscall(&mut pipe_fds), 0); + let read_fd = pipe_fds.readfd; + let write_fd = pipe_fds.writefd; + + // Prepare the data to be written using an iovec structure + let data = b"Hello, pipe!"; + let iovec = interface::IovecStruct { + iov_base: data.as_ptr() as *mut libc::c_void, + iov_len: data.len(), + }; + + // Write the data to the pipe using writev_syscall + let bytes_written = cage.writev_syscall(write_fd, &iovec, 1); + assert_eq!(bytes_written, data.len() as i32); + + // Read the data from the pipe + let mut buffer = vec![0u8; data.len()]; + let bytes_read = cage.read_syscall(read_fd, buffer.as_mut_ptr(), buffer.len()); + assert_eq!(bytes_read, data.len() as i32); + + // Verify that the data read is the same as the data written + assert_eq!(buffer, data); + + assert_eq!(cage.close_syscall(read_fd), 0); + assert_eq!(cage.close_syscall(write_fd), 0); + + assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); + lindrustfinalize(); + } +} \ No newline at end of file From 4fbf2add91b8d98947fbcd4e6f55f08e4ac5e35f Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Sun, 7 Jul 2024 20:09:56 +0530 Subject: [PATCH 2/8] update --- src/tests/fs_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index 8a823a09d..82749c391 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -2532,4 +2532,4 @@ pub mod fs_tests { assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); lindrustfinalize(); } -} \ No newline at end of file +} From 6931a804df709dbca14fe711a4b8305cd71ff980 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Tue, 16 Jul 2024 13:39:44 +0530 Subject: [PATCH 3/8] udpate comments --- .DS_Store | Bin 0 -> 6148 bytes src/safeposix/syscalls/fs_calls.rs | 11 +++++++---- src/tests/fs_tests.rs | 13 ++++++++----- 3 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3f6995673db15f8221f20009e2136c1abe095567 GIT binary patch literal 6148 zcmeHKJ5Iwu5S?`_WIja-3aV&NfXEF@WD4pW00=<=DVD7$NR)bDU+9wC*s zXigV2L+z_(?VX2@({+En{@L5&Wxo^ZH_ph5)je#Aso%$5`O5cUVhk7q#=w7L06m)} z*%h?a7%&Emfh7a{eeh7mRIw5apAIZx1OUb`2f?0a3C{6~sbVDv55!3-P*Ry?)K7^A?1#LA3jDaQt9l7js|3BG0|2LED$`~*P{uBc) z&W70lkEFe|^>Ey4J@g#P!f}=0G6kE^iV@4L_y8INcF!ANs#poa0 literal 0 HcmV?d00001 diff --git a/src/safeposix/syscalls/fs_calls.rs b/src/safeposix/syscalls/fs_calls.rs index 5f4d785c2..a18a6952c 100644 --- a/src/safeposix/syscalls/fs_calls.rs +++ b/src/safeposix/syscalls/fs_calls.rs @@ -1859,6 +1859,8 @@ impl Cage { /// ### Function Arguments /// * `fd`: The file descriptor to write to. /// * `iovec`: A pointer to an array of `IovecStruct` objects representing the data buffers to write. + /// The IovecStruct structure enables efficient writing of data from multiple buffers to a file + /// descriptor in a single operation using the writev system call, potentially avoiding unnecessary data copying. /// * `iovcnt`: The number of `IovecStruct` objects in the array. /// /// ### Returns @@ -1891,9 +1893,9 @@ impl Cage { // Check the domain of the socket (IPv4 or IPv6) match sockhandle.domain { AF_INET | AF_INET6 => match sockhandle.protocol { + // Handle TCP protocol. IPPROTO_TCP => { - // to be able to send here we either need to be fully connected, or - // connected for write only + // We need to be either fully connected or connected for write-only. if (sockhandle.state != ConnState::CONNECTED) && (sockhandle.state != ConnState::CONNWRONLY) { @@ -1911,6 +1913,7 @@ impl Cage { .as_ref() .unwrap() .writev(iovec, iovcnt); + // Handle errors if retval < 0 { match Errno::from_discriminant(interface::get_errno()) { Ok(i) => { @@ -1939,8 +1942,7 @@ impl Cage { AF_UNIX => { match sockhandle.protocol { IPPROTO_TCP => { - // to be able to send here we either need to be fully connected, - // or connected for write only + // We need to be either fully connected or connected for write-only. if (sockhandle.state != ConnState::CONNECTED) && (sockhandle.state != ConnState::CONNWRONLY) { @@ -1956,6 +1958,7 @@ impl Cage { if socket_filedesc_obj.flags & O_NONBLOCK != 0 { nonblocking = true; } + // Write data to the socket pipe. let retval = match sockinfo.sendpipe.as_ref() { Some(sendpipe) => sendpipe.write_vectored_to_pipe( iovec, diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index 82749c391..38583a3f1 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -2465,6 +2465,8 @@ pub mod fs_tests { use std::thread; #[test] fn ut_lind_fs_writev_socketpair() { + //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, + // and also performs clean env setup let _thelock = setup::lock_and_init(); let cage = interface::cagetable_getref(1); @@ -2473,22 +2475,23 @@ pub mod fs_tests { Cage::socketpair_syscall(cage.clone(), AF_UNIX, SOCK_STREAM, 0, &mut socketpair), 0 ); - + + // Prepare data to write. let data = b"Hello, world!"; let iovec = interface::IovecStruct { iov_base: data.as_ptr() as *mut libc::c_void, iov_len: data.len(), }; - + // Write the data to the first socket using writev_syscall. let bytes_written = cage.writev_syscall(socketpair.sock1, &iovec, 1); assert_eq!(bytes_written, data.len() as i32); - + // Read the data from the second socket. let mut buffer = vec![0u8; data.len()]; let bytes_read = cage.recv_syscall(socketpair.sock2, buffer.as_mut_ptr(), buffer.len(), 0); assert_eq!(bytes_read, data.len() as i32); - + // Verify that the data assert_eq!(buffer, data); - + // Close both sockets. assert_eq!(cage.close_syscall(socketpair.sock1), 0); assert_eq!(cage.close_syscall(socketpair.sock2), 0); From ef5c1d3c16bc9efc1325454b4b2e6a42abf53211 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Tue, 16 Jul 2024 13:45:10 +0530 Subject: [PATCH 4/8] remove untracked --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 3f6995673db15f8221f20009e2136c1abe095567..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5Iwu5S?`_WIja-3aV&NfXEF@WD4pW00=<=DVD7$NR)bDU+9wC*s zXigV2L+z_(?VX2@({+En{@L5&Wxo^ZH_ph5)je#Aso%$5`O5cUVhk7q#=w7L06m)} z*%h?a7%&Emfh7a{eeh7mRIw5apAIZx1OUb`2f?0a3C{6~sbVDv55!3-P*Ry?)K7^A?1#LA3jDaQt9l7js|3BG0|2LED$`~*P{uBc) z&W70lkEFe|^>Ey4J@g#P!f}=0G6kE^iV@4L_y8INcF!ANs#poa0 From ab1ddb25baddfc3646d071f8754af3ed68ea8d58 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Fri, 26 Jul 2024 15:12:56 +0000 Subject: [PATCH 5/8] update comments --- src/safeposix/syscalls/fs_calls.rs | 4 ++++ src/tests/fs_tests.rs | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/safeposix/syscalls/fs_calls.rs b/src/safeposix/syscalls/fs_calls.rs index a18a6952c..af91b1cec 100644 --- a/src/safeposix/syscalls/fs_calls.rs +++ b/src/safeposix/syscalls/fs_calls.rs @@ -1873,6 +1873,7 @@ impl Cage { /// * `EOPNOTSUPP(95)`: The system call is not supported for the given socket protocol. /// * `EAGAIN(11)`: There is no data available right now (for pipes). /// * `EPIPE(32)`: The pipe has been closed on the other end (for pipes). + /// /// ### Panics /// * If an unknown error code is returned by the underlying socket writev function. /// [writev(2)](https://linux.die.net/man/2/writev) @@ -2004,6 +2005,9 @@ impl Cage { } let mut nonblocking = false; + // Check if the O_NONBLOCK flag is set in the pipe's flags. + // If it is, enable non-blocking mode for the write operation. + //Non-blocking I/O allows a process to continue doing other tasks while waiting for I/O operations to complete. if pipe_filedesc_obj.flags & O_NONBLOCK != 0 { nonblocking = true; } diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index 38583a3f1..b8711904c 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -9,6 +9,8 @@ pub mod fs_tests { use libc::c_void; use std::fs::OpenOptions; use std::os::unix::fs::PermissionsExt; + use crate::tests::FileDescriptor::Socket; + use std::thread; #[test] pub fn ut_lind_fs_simple() { @@ -2461,8 +2463,7 @@ pub mod fs_tests { assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); lindrustfinalize(); } - use crate::tests::FileDescriptor::Socket; - use std::thread; + #[test] fn ut_lind_fs_writev_socketpair() { //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, @@ -2489,7 +2490,7 @@ pub mod fs_tests { let mut buffer = vec![0u8; data.len()]; let bytes_read = cage.recv_syscall(socketpair.sock2, buffer.as_mut_ptr(), buffer.len(), 0); assert_eq!(bytes_read, data.len() as i32); - // Verify that the data + // Verify that the data received from the second socket matches the original data. assert_eq!(buffer, data); // Close both sockets. assert_eq!(cage.close_syscall(socketpair.sock1), 0); From ab2b4c6fef8c8dbb3c5d1442667b725a89f933f8 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Sat, 27 Jul 2024 21:08:57 +0000 Subject: [PATCH 6/8] remove imports --- src/tests/fs_tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index b8711904c..dfdf37df5 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -9,8 +9,6 @@ pub mod fs_tests { use libc::c_void; use std::fs::OpenOptions; use std::os::unix::fs::PermissionsExt; - use crate::tests::FileDescriptor::Socket; - use std::thread; #[test] pub fn ut_lind_fs_simple() { From 350449abb4dfe272121c53d6f796b0c14d0c1bc6 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Sat, 27 Jul 2024 21:10:22 +0000 Subject: [PATCH 7/8] add comment --- src/tests/fs_tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index dfdf37df5..c33bc5608 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -2500,6 +2500,8 @@ pub mod fs_tests { #[test] fn ut_lind_fs_writev_pipe() { + //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, + // and also performs clean env setup let _thelock = setup::lock_and_init(); let cage = interface::cagetable_getref(1); From d6d14cdff1aaf679c45c26aa4977987298a772a9 Mon Sep 17 00:00:00 2001 From: rupeshkoushik07 Date: Tue, 20 Aug 2024 16:11:47 +0000 Subject: [PATCH 8/8] update writev_to_pipe --- src/tests/fs_tests.rs | 133 ++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 58 deletions(-) diff --git a/src/tests/fs_tests.rs b/src/tests/fs_tests.rs index b8311b1a0..7c7588cf6 100644 --- a/src/tests/fs_tests.rs +++ b/src/tests/fs_tests.rs @@ -3331,12 +3331,6 @@ pub mod fs_tests { } #[test] - fn ut_lind_fs_writev_socketpair() { - //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, - // and also performs clean env setup - let _thelock = setup::lock_and_init(); - let cage = interface::cagetable_getref(1); - pub fn ut_lind_fs_read_write_only_fd() { //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, // and also performs clean env setup @@ -4339,25 +4333,6 @@ pub mod fs_tests { 0 ); - // Prepare data to write. - let data = b"Hello, world!"; - let iovec = interface::IovecStruct { - iov_base: data.as_ptr() as *mut libc::c_void, - iov_len: data.len(), - }; - // Write the data to the first socket using writev_syscall. - let bytes_written = cage.writev_syscall(socketpair.sock1, &iovec, 1); - assert_eq!(bytes_written, data.len() as i32); - // Read the data from the second socket. - let mut buffer = vec![0u8; data.len()]; - let bytes_read = cage.recv_syscall(socketpair.sock2, buffer.as_mut_ptr(), buffer.len(), 0); - assert_eq!(bytes_read, data.len() as i32); - // Verify that the data received from the second socket matches the original data. - assert_eq!(buffer, data); - // Close both sockets. - assert_eq!(cage.close_syscall(socketpair.sock1), 0); - assert_eq!(cage.close_syscall(socketpair.sock2), 0); - // Close both the socket file descriptors, which should succeed. assert_eq!(cage.close_syscall(socketpair.sock1), 0); assert_eq!(cage.close_syscall(socketpair.sock2), 0); @@ -4372,13 +4347,6 @@ pub mod fs_tests { } #[test] - fn ut_lind_fs_writev_pipe() { - //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, - // and also performs clean env setup - let _thelock = setup::lock_and_init(); - let cage = interface::cagetable_getref(1); - - // Create a pipe pub fn ut_lind_fs_close_pipe() { // acquiring a lock on TESTMUTEX prevents other tests from running concurrently, // and also performs clean env setup @@ -4391,32 +4359,6 @@ pub mod fs_tests { assert_eq!(cage.pipe_syscall(&mut pipe_fds), 0); let read_fd = pipe_fds.readfd; let write_fd = pipe_fds.writefd; - - // Prepare the data to be written using an iovec structure - let data = b"Hello, pipe!"; - let iovec = interface::IovecStruct { - iov_base: data.as_ptr() as *mut libc::c_void, - iov_len: data.len(), - }; - - // Write the data to the pipe using writev_syscall - let bytes_written = cage.writev_syscall(write_fd, &iovec, 1); - assert_eq!(bytes_written, data.len() as i32); - - // Read the data from the pipe - let mut buffer = vec![0u8; data.len()]; - let bytes_read = cage.read_syscall(read_fd, buffer.as_mut_ptr(), buffer.len()); - assert_eq!(bytes_read, data.len() as i32); - - // Verify that the data read is the same as the data written - assert_eq!(buffer, data); - - assert_eq!(cage.close_syscall(read_fd), 0); - assert_eq!(cage.close_syscall(write_fd), 0); - - assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); - lindrustfinalize(); - } // Write data to the pipe let write_data = "Testing"; @@ -4669,4 +4611,79 @@ pub mod fs_tests { lindrustfinalize(); return; } + + #[test] + fn ut_lind_fs_writev_socketpair() { + //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, + // and also performs clean env setup + let _thelock = setup::lock_and_init(); + let cage = interface::cagetable_getref(1); + + let mut socketpair = interface::SockPair::default(); + assert_eq!( + Cage::socketpair_syscall(cage.clone(), AF_UNIX, SOCK_STREAM, 0, &mut socketpair), + 0 + ); + + // Prepare data to write. + let data = b"Hello, world!"; + let iovec = interface::IovecStruct { + iov_base: data.as_ptr() as *mut libc::c_void, + iov_len: data.len(), + }; + // Write the data to the first socket using writev_syscall. + let bytes_written = cage.writev_syscall(socketpair.sock1, &iovec, 1); + assert_eq!(bytes_written, data.len() as i32); + // Read the data from the second socket. + let mut buffer = vec![0u8; data.len()]; + let bytes_read = cage.recv_syscall(socketpair.sock2, buffer.as_mut_ptr(), buffer.len(), 0); + assert_eq!(bytes_read, data.len() as i32); + // Verify that the data received from the second socket matches the original data. + assert_eq!(buffer, data); + // Close both sockets. + assert_eq!(cage.close_syscall(socketpair.sock1), 0); + assert_eq!(cage.close_syscall(socketpair.sock2), 0); + + assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); + lindrustfinalize(); + } + + #[test] + fn ut_lind_fs_writev_pipe() { + //acquiring a lock on TESTMUTEX prevents other tests from running concurrently, + // and also performs clean env setup + let _thelock = setup::lock_and_init(); + let cage = interface::cagetable_getref(1); + + // Create a pipe + let mut pipe_fds = PipeArray::default(); + assert_eq!(cage.pipe_syscall(&mut pipe_fds), 0); + let read_fd = pipe_fds.readfd; + let write_fd = pipe_fds.writefd; + + // Prepare the data to be written using an iovec structure + let data = b"Hello, pipe!"; + let iovec = interface::IovecStruct { + iov_base: data.as_ptr() as *mut libc::c_void, + iov_len: data.len(), + }; + + // Write the data to the pipe using writev_syscall + let bytes_written = cage.writev_syscall(write_fd, &iovec, 1); + assert_eq!(bytes_written, data.len() as i32); + + // Read the data from the pipe + let mut buffer = vec![0u8; data.len()]; + let bytes_read = cage.read_syscall(read_fd, buffer.as_mut_ptr(), buffer.len()); + assert_eq!(bytes_read, data.len() as i32); + + // Verify that the data read is the same as the data written + assert_eq!(buffer, data); + + assert_eq!(cage.close_syscall(read_fd), 0); + assert_eq!(cage.close_syscall(write_fd), 0); + + assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS); + lindrustfinalize(); + } }