Function nc::dup3

source ·
pub unsafe fn dup3(oldfd: i32, newfd: i32, flags: i32) -> Result<(), Errno>
Expand description

Save as dup2(), but can set the close-on-exec flag on newfd.

§Example

let path = "/tmp/nc-dup3-file";
let fd = unsafe { nc::openat(nc::AT_FDCWD, path, nc::O_CREAT | nc::O_WRONLY | nc::O_TRUNC, 0o644) };
assert!(fd.is_ok());
let fd = fd.unwrap();
let newfd = 8;
let ret = unsafe { nc::dup3(fd, newfd, nc::O_CLOEXEC) };
assert!(ret.is_ok());
let ret = unsafe { nc::close(fd) };
assert!(ret.is_ok());
let ret = unsafe { nc::close(newfd) };
assert!(ret.is_ok());
let ret = unsafe { nc::unlinkat(nc::AT_FDCWD, path, 0) };
assert!(ret.is_ok());
Examples found in repository?
examples/pidfd.rs (line 40)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
fn run_main() {
    const STDOUT_FD: i32 = 1;

    let pid = unsafe { nc::fork() };
    assert!(pid.is_ok());
    if pid == Ok(0) {
        let curr_pid = unsafe { nc::getpid() };
        println!("In child process, pid: {}", curr_pid);
        let path = "/tmp/nc-pidfdopen";
        let fd = unsafe {
            nc::openat(
                nc::AT_FDCWD,
                path,
                nc::O_CREAT | nc::O_WRONLY | nc::O_TRUNC,
                0o644,
            )
        };
        assert!(fd.is_ok());
        let fd = fd.unwrap();
        let ret = unsafe { nc::dup3(fd, STDOUT_FD, 0) };
        assert!(ret.is_ok());
        println!("[child] stdout redirected to file!");

        let t = nc::timespec_t {
            tv_sec: 2,
            tv_nsec: 0,
        };
        unsafe {
            let ret = nc::nanosleep(&t, None);
            assert!(ret.is_ok());
            let ret = nc::close(fd);
            assert!(ret.is_ok());
            let ret = nc::unlinkat(nc::AT_FDCWD, path, 0);
            assert!(ret.is_ok());
            nc::exit(0);
        }
    }

    let pid = pid.unwrap();
    println!("[parent] child pid: {}", pid);

    let t = nc::timespec_t {
        tv_sec: 2,
        tv_nsec: 0,
    };
    let ret = unsafe { nc::nanosleep(&t, None) };
    assert!(ret.is_ok());

    let pidfd = unsafe { nc::pidfd_open(pid, 0) };
    assert!(pidfd.is_ok());
    let pidfd = pidfd.unwrap();

    let ret = unsafe { nc::pidfd_getfd(pidfd, STDOUT_FD, 0) };
    println!("ret: {:?}", ret);
    if let Err(errno) = ret {
        eprintln!("pidfd_getfd() failed, err: {}", nc::strerror(errno));
    }
    let child_stdout_fd = ret.unwrap();
    let msg = "Hello, msg from parent process\n";
    let ret = unsafe { nc::write(child_stdout_fd, msg.as_ptr() as usize, msg.len()) };
    assert!(ret.is_ok());
    let nwrite = ret.unwrap();
    assert_eq!(nwrite as usize, msg.len());

    let mut info = nc::siginfo_t::default();
    let ret = unsafe { nc::pidfd_send_signal(pidfd, nc::SIGKILL, &mut info, 0) };
    println!("ret: {:?}", ret);
    if let Err(errno) = ret {
        eprintln!("pidfd_send_signal() failed, err: {}", nc::strerror(errno));
    }

    unsafe {
        let ret = nc::close(pidfd);
        assert!(ret.is_ok());
        let ret = nc::close(child_stdout_fd);
        assert!(ret.is_ok());
    }
}