1#[cfg(feature = "fs")] 2use std::io::{IoSlice, IoSliceMut}; 3 4#[cfg(feature = "fs")] 5#[cfg(not(target_os = "solaris"))] // no preadv/pwritev 6#[cfg(not(target_os = "haiku"))] // no preadv/pwritev 7#[test] 8fn test_readwrite_pv() { 9 use rustix::fs::{cwd, openat, Mode, OFlags}; 10 use rustix::io::{preadv, pwritev}; 11 12 let tmp = tempfile::tempdir().unwrap(); 13 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 14 let foo = openat( 15 &dir, 16 "foo", 17 OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, 18 Mode::RUSR | Mode::WUSR, 19 ) 20 .unwrap(); 21 22 // For most targets, just call `pwritev`. 23 #[cfg(not(any(target_os = "ios", target_os = "macos")))] 24 { 25 pwritev(&foo, &[IoSlice::new(b"hello")], 200).unwrap(); 26 } 27 // macOS only has pwritev in newer versions; allow it to fail with `ENOSYS`. 28 #[cfg(any(target_os = "ios", target_os = "macos"))] 29 { 30 match pwritev(&foo, &[IoSlice::new(b"hello")], 200) { 31 Ok(_) => (), 32 Err(rustix::io::Errno::NOSYS) => return, 33 Err(err) => Err(err).unwrap(), 34 } 35 } 36 pwritev(&foo, &[IoSlice::new(b"world")], 300).unwrap(); 37 let mut buf = [0_u8; 5]; 38 preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 200).unwrap(); 39 assert_eq!(&buf, b"hello"); 40 preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 300).unwrap(); 41 assert_eq!(&buf, b"world"); 42} 43 44#[cfg(feature = "fs")] 45#[test] 46fn test_readwrite_p() { 47 use rustix::fs::{cwd, openat, Mode, OFlags}; 48 use rustix::io::{pread, pwrite}; 49 50 let tmp = tempfile::tempdir().unwrap(); 51 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 52 let foo = openat( 53 &dir, 54 "foo", 55 OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, 56 Mode::RUSR | Mode::WUSR, 57 ) 58 .unwrap(); 59 60 pwrite(&foo, b"hello", 200).unwrap(); 61 pwrite(&foo, b"world", 300).unwrap(); 62 let mut buf = [0_u8; 5]; 63 pread(&foo, &mut buf, 200).unwrap(); 64 assert_eq!(&buf, b"hello"); 65 pread(&foo, &mut buf, 300).unwrap(); 66 assert_eq!(&buf, b"world"); 67} 68 69#[cfg(feature = "fs")] 70#[test] 71fn test_readwrite_v() { 72 use rustix::fs::{cwd, openat, seek, Mode, OFlags}; 73 use rustix::io::{readv, writev, SeekFrom}; 74 75 let tmp = tempfile::tempdir().unwrap(); 76 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 77 let foo = openat( 78 &dir, 79 "foo", 80 OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, 81 Mode::RUSR | Mode::WUSR, 82 ) 83 .unwrap(); 84 85 writev(&foo, &[IoSlice::new(b"hello")]).unwrap(); 86 writev(&foo, &[IoSlice::new(b"world")]).unwrap(); 87 seek(&foo, SeekFrom::Start(0)).unwrap(); 88 let mut buf = [0_u8; 5]; 89 readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap(); 90 assert_eq!(&buf, b"hello"); 91 readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap(); 92 assert_eq!(&buf, b"world"); 93} 94 95#[cfg(feature = "fs")] 96#[test] 97fn test_readwrite() { 98 use rustix::fs::{cwd, openat, seek, Mode, OFlags}; 99 use rustix::io::{read, write}; 100 use std::io::SeekFrom; 101 102 let tmp = tempfile::tempdir().unwrap(); 103 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 104 let foo = openat( 105 &dir, 106 "foo", 107 OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, 108 Mode::RUSR | Mode::WUSR, 109 ) 110 .unwrap(); 111 112 write(&foo, b"hello").unwrap(); 113 write(&foo, b"world").unwrap(); 114 seek(&foo, SeekFrom::Start(0)).unwrap(); 115 let mut buf = [0_u8; 5]; 116 read(&foo, &mut buf).unwrap(); 117 assert_eq!(&buf, b"hello"); 118 read(&foo, &mut buf).unwrap(); 119 assert_eq!(&buf, b"world"); 120} 121 122#[cfg(all(target_os = "linux", target_env = "gnu"))] 123#[test] 124fn test_rwf_values() { 125 // We use the kernel's values for these flags; check that libc doesn't 126 // have different values. 127 assert_eq!( 128 rustix::io::ReadWriteFlags::APPEND.bits() as i32, 129 libc::RWF_APPEND 130 ); 131 assert_eq!( 132 rustix::io::ReadWriteFlags::DSYNC.bits() as i32, 133 libc::RWF_DSYNC 134 ); 135 assert_eq!( 136 rustix::io::ReadWriteFlags::HIPRI.bits() as i32, 137 libc::RWF_HIPRI 138 ); 139 assert_eq!( 140 rustix::io::ReadWriteFlags::NOWAIT.bits() as i32, 141 libc::RWF_NOWAIT 142 ); 143 assert_eq!( 144 rustix::io::ReadWriteFlags::SYNC.bits() as i32, 145 libc::RWF_SYNC 146 ); 147} 148 149#[cfg(any(target_os = "android", target_os = "linux"))] 150#[cfg(feature = "fs")] 151#[test] 152fn test_pwritev2() { 153 use rustix::fs::{cwd, openat, seek, Mode, OFlags}; 154 use rustix::io::{preadv2, pwritev2, writev, ReadWriteFlags, SeekFrom}; 155 156 let tmp = tempfile::tempdir().unwrap(); 157 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 158 let foo = openat( 159 &dir, 160 "foo", 161 OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, 162 Mode::RUSR | Mode::WUSR, 163 ) 164 .unwrap(); 165 166 writev(&foo, &[IoSlice::new(b"hello")]).unwrap(); 167 seek(&foo, SeekFrom::Start(0)).unwrap(); 168 169 // pwritev2 to append with a 0 offset: don't update the current position. 170 match pwritev2(&foo, &[IoSlice::new(b"world")], 0, ReadWriteFlags::APPEND) { 171 Ok(_) => {} 172 // Skip the rest of the test if we don't have `pwritev2` and `RWF_APPEND`. 173 Err(rustix::io::Errno::NOSYS) | Err(rustix::io::Errno::NOTSUP) => return, 174 Err(err) => Err(err).unwrap(), 175 } 176 assert_eq!(seek(&foo, SeekFrom::Current(0)).unwrap(), 0); 177 178 // pwritev2 to append with a !0 offset: do update the current position. 179 pwritev2(&foo, &[IoSlice::new(b"world")], !0, ReadWriteFlags::APPEND).unwrap(); 180 assert_eq!(seek(&foo, SeekFrom::Current(0)).unwrap(), 15); 181 182 seek(&foo, SeekFrom::Start(0)).unwrap(); 183 let mut buf = [0_u8; 5]; 184 preadv2( 185 &foo, 186 &mut [IoSliceMut::new(&mut buf)], 187 0, 188 ReadWriteFlags::empty(), 189 ) 190 .unwrap(); 191 assert_eq!(&buf, b"hello"); 192 preadv2( 193 &foo, 194 &mut [IoSliceMut::new(&mut buf)], 195 5, 196 ReadWriteFlags::empty(), 197 ) 198 .unwrap(); 199 assert_eq!(&buf, b"world"); 200} 201