1 #[cfg(feature = "fs")]
2 use 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]
test_readwrite_pv()8 fn 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]
test_readwrite_p()46 fn 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]
test_readwrite_v()71 fn 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]
test_readwrite()97 fn 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]
test_rwf_values()124 fn 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]
test_pwritev2()152 fn 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