1 use nix::fcntl::{openat, open, OFlag, readlink, readlinkat};
2 use nix::sys::stat::Mode;
3 use nix::unistd::{close, read};
4 use tempdir::TempDir;
5 use tempfile::NamedTempFile;
6 use std::io::prelude::*;
7 use std::os::unix::fs;
8
9 #[test]
test_openat()10 fn test_openat() {
11 const CONTENTS: &[u8] = b"abcd";
12 let mut tmp = NamedTempFile::new().unwrap();
13 tmp.write_all(CONTENTS).unwrap();
14
15 let dirfd = open(tmp.path().parent().unwrap(),
16 OFlag::empty(),
17 Mode::empty()).unwrap();
18 let fd = openat(dirfd,
19 tmp.path().file_name().unwrap(),
20 OFlag::O_RDONLY,
21 Mode::empty()).unwrap();
22
23 let mut buf = [0u8; 1024];
24 assert_eq!(4, read(fd, &mut buf).unwrap());
25 assert_eq!(CONTENTS, &buf[0..4]);
26
27 close(fd).unwrap();
28 close(dirfd).unwrap();
29 }
30
31 #[test]
test_readlink()32 fn test_readlink() {
33 let tempdir = TempDir::new("nix-test_readdir")
34 .unwrap_or_else(|e| panic!("tempdir failed: {}", e));
35 let src = tempdir.path().join("a");
36 let dst = tempdir.path().join("b");
37 println!("a: {:?}, b: {:?}", &src, &dst);
38 fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
39 let dirfd = open(tempdir.path(),
40 OFlag::empty(),
41 Mode::empty()).unwrap();
42
43 let mut buf = vec![0; src.to_str().unwrap().len() + 1];
44 assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
45 src.to_str().unwrap());
46 assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
47 src.to_str().unwrap());
48 }
49
50 #[cfg(any(target_os = "linux", target_os = "android"))]
51 mod linux_android {
52 use std::io::prelude::*;
53 use std::os::unix::prelude::*;
54
55 use libc::loff_t;
56
57 use nix::fcntl::{SpliceFFlags, FallocateFlags, fallocate, splice, tee, vmsplice};
58 use nix::sys::uio::IoVec;
59 use nix::unistd::{close, pipe, read, write};
60
61 use tempfile::{tempfile, NamedTempFile};
62
63 #[test]
test_splice()64 fn test_splice() {
65 const CONTENTS: &[u8] = b"abcdef123456";
66 let mut tmp = tempfile().unwrap();
67 tmp.write_all(CONTENTS).unwrap();
68
69 let (rd, wr) = pipe().unwrap();
70 let mut offset: loff_t = 5;
71 let res = splice(tmp.as_raw_fd(), Some(&mut offset),
72 wr, None, 2, SpliceFFlags::empty()).unwrap();
73
74 assert_eq!(2, res);
75
76 let mut buf = [0u8; 1024];
77 assert_eq!(2, read(rd, &mut buf).unwrap());
78 assert_eq!(b"f1", &buf[0..2]);
79 assert_eq!(7, offset);
80
81 close(rd).unwrap();
82 close(wr).unwrap();
83 }
84
85 #[test]
test_tee()86 fn test_tee() {
87 let (rd1, wr1) = pipe().unwrap();
88 let (rd2, wr2) = pipe().unwrap();
89
90 write(wr1, b"abc").unwrap();
91 let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
92
93 assert_eq!(2, res);
94
95 let mut buf = [0u8; 1024];
96
97 // Check the tee'd bytes are at rd2.
98 assert_eq!(2, read(rd2, &mut buf).unwrap());
99 assert_eq!(b"ab", &buf[0..2]);
100
101 // Check all the bytes are still at rd1.
102 assert_eq!(3, read(rd1, &mut buf).unwrap());
103 assert_eq!(b"abc", &buf[0..3]);
104
105 close(rd1).unwrap();
106 close(wr1).unwrap();
107 close(rd2).unwrap();
108 close(wr2).unwrap();
109 }
110
111 #[test]
test_vmsplice()112 fn test_vmsplice() {
113 let (rd, wr) = pipe().unwrap();
114
115 let buf1 = b"abcdef";
116 let buf2 = b"defghi";
117 let mut iovecs = Vec::with_capacity(2);
118 iovecs.push(IoVec::from_slice(&buf1[0..3]));
119 iovecs.push(IoVec::from_slice(&buf2[0..3]));
120
121 let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
122
123 assert_eq!(6, res);
124
125 // Check the bytes can be read at rd.
126 let mut buf = [0u8; 32];
127 assert_eq!(6, read(rd, &mut buf).unwrap());
128 assert_eq!(b"abcdef", &buf[0..6]);
129
130 close(rd).unwrap();
131 close(wr).unwrap();
132 }
133
134 #[test]
test_fallocate()135 fn test_fallocate() {
136 let tmp = NamedTempFile::new().unwrap();
137
138 let fd = tmp.as_raw_fd();
139 fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
140
141 // Check if we read exactly 100 bytes
142 let mut buf = [0u8; 200];
143 assert_eq!(100, read(fd, &mut buf).unwrap());
144 }
145 }
146