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