1b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
2b8a62b91Sopenharmony_ciuse rustix::fs::Stat;
3b8a62b91Sopenharmony_ci
4b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
5b8a62b91Sopenharmony_cifn same(a: &Stat, b: &Stat) -> bool {
6b8a62b91Sopenharmony_ci    a.st_ino == b.st_ino && a.st_dev == b.st_dev
7b8a62b91Sopenharmony_ci}
8b8a62b91Sopenharmony_ci
9b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
10b8a62b91Sopenharmony_ci#[test]
11b8a62b91Sopenharmony_cifn test_renameat() {
12b8a62b91Sopenharmony_ci    use rustix::fs::{cwd, openat, renameat, statat, AtFlags, Mode, OFlags};
13b8a62b91Sopenharmony_ci
14b8a62b91Sopenharmony_ci    let tmp = tempfile::tempdir().unwrap();
15b8a62b91Sopenharmony_ci    let dir = openat(
16b8a62b91Sopenharmony_ci        cwd(),
17b8a62b91Sopenharmony_ci        tmp.path(),
18b8a62b91Sopenharmony_ci        OFlags::RDONLY | OFlags::PATH,
19b8a62b91Sopenharmony_ci        Mode::empty(),
20b8a62b91Sopenharmony_ci    )
21b8a62b91Sopenharmony_ci    .unwrap();
22b8a62b91Sopenharmony_ci
23b8a62b91Sopenharmony_ci    let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
24b8a62b91Sopenharmony_ci    let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
25b8a62b91Sopenharmony_ci    renameat(&dir, "foo", &dir, "bar").unwrap();
26b8a62b91Sopenharmony_ci    let renamed = statat(&dir, "bar", AtFlags::empty()).unwrap();
27b8a62b91Sopenharmony_ci    assert!(same(&before, &renamed));
28b8a62b91Sopenharmony_ci}
29b8a62b91Sopenharmony_ci
30b8a62b91Sopenharmony_ci/// Like `test_renameat` but the file already exists, so `renameat`
31b8a62b91Sopenharmony_ci/// overwrites it.
32b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
33b8a62b91Sopenharmony_ci#[test]
34b8a62b91Sopenharmony_cifn test_renameat_overwrite() {
35b8a62b91Sopenharmony_ci    use rustix::fs::{cwd, openat, renameat, statat, AtFlags, Mode, OFlags};
36b8a62b91Sopenharmony_ci
37b8a62b91Sopenharmony_ci    let tmp = tempfile::tempdir().unwrap();
38b8a62b91Sopenharmony_ci    let dir = openat(
39b8a62b91Sopenharmony_ci        cwd(),
40b8a62b91Sopenharmony_ci        tmp.path(),
41b8a62b91Sopenharmony_ci        OFlags::RDONLY | OFlags::PATH,
42b8a62b91Sopenharmony_ci        Mode::empty(),
43b8a62b91Sopenharmony_ci    )
44b8a62b91Sopenharmony_ci    .unwrap();
45b8a62b91Sopenharmony_ci
46b8a62b91Sopenharmony_ci    let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
47b8a62b91Sopenharmony_ci    let _ = openat(&dir, "bar", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
48b8a62b91Sopenharmony_ci    let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
49b8a62b91Sopenharmony_ci    renameat(&dir, "foo", &dir, "bar").unwrap();
50b8a62b91Sopenharmony_ci    let renamed = statat(&dir, "bar", AtFlags::empty()).unwrap();
51b8a62b91Sopenharmony_ci    assert!(same(&before, &renamed));
52b8a62b91Sopenharmony_ci}
53b8a62b91Sopenharmony_ci
54b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
55b8a62b91Sopenharmony_ci#[test]
56b8a62b91Sopenharmony_cifn test_renameat_with() {
57b8a62b91Sopenharmony_ci    use rustix::fs::{cwd, openat, renameat_with, statat, AtFlags, Mode, OFlags, RenameFlags};
58b8a62b91Sopenharmony_ci
59b8a62b91Sopenharmony_ci    let tmp = tempfile::tempdir().unwrap();
60b8a62b91Sopenharmony_ci    let dir = openat(
61b8a62b91Sopenharmony_ci        cwd(),
62b8a62b91Sopenharmony_ci        tmp.path(),
63b8a62b91Sopenharmony_ci        OFlags::RDONLY | OFlags::PATH,
64b8a62b91Sopenharmony_ci        Mode::empty(),
65b8a62b91Sopenharmony_ci    )
66b8a62b91Sopenharmony_ci    .unwrap();
67b8a62b91Sopenharmony_ci
68b8a62b91Sopenharmony_ci    let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
69b8a62b91Sopenharmony_ci    let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
70b8a62b91Sopenharmony_ci
71b8a62b91Sopenharmony_ci    match renameat_with(&dir, "foo", &dir, "red", RenameFlags::empty()) {
72b8a62b91Sopenharmony_ci        Ok(()) => (),
73b8a62b91Sopenharmony_ci        Err(err) if err == rustix::io::Errno::NOSYS => return,
74b8a62b91Sopenharmony_ci        Err(err) => unreachable!("unexpected error from renameat_with: {:?}", err),
75b8a62b91Sopenharmony_ci    }
76b8a62b91Sopenharmony_ci
77b8a62b91Sopenharmony_ci    let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
78b8a62b91Sopenharmony_ci    assert!(same(&before, &renamed));
79b8a62b91Sopenharmony_ci
80b8a62b91Sopenharmony_ci    let _ = openat(
81b8a62b91Sopenharmony_ci        &dir,
82b8a62b91Sopenharmony_ci        "green",
83b8a62b91Sopenharmony_ci        OFlags::CREATE | OFlags::WRONLY,
84b8a62b91Sopenharmony_ci        Mode::empty(),
85b8a62b91Sopenharmony_ci    )
86b8a62b91Sopenharmony_ci    .unwrap();
87b8a62b91Sopenharmony_ci
88b8a62b91Sopenharmony_ci    #[cfg(all(target_os = "linux", target_env = "gnu"))]
89b8a62b91Sopenharmony_ci    {
90b8a62b91Sopenharmony_ci        let green = statat(&dir, "green", AtFlags::empty()).unwrap();
91b8a62b91Sopenharmony_ci
92b8a62b91Sopenharmony_ci        renameat_with(&dir, "red", &dir, "green", RenameFlags::NOREPLACE).unwrap_err();
93b8a62b91Sopenharmony_ci        let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
94b8a62b91Sopenharmony_ci        assert!(same(&before, &renamed));
95b8a62b91Sopenharmony_ci        let orig = statat(&dir, "green", AtFlags::empty()).unwrap();
96b8a62b91Sopenharmony_ci        assert!(same(&green, &orig));
97b8a62b91Sopenharmony_ci
98b8a62b91Sopenharmony_ci        renameat_with(&dir, "red", &dir, "green", RenameFlags::EXCHANGE).unwrap();
99b8a62b91Sopenharmony_ci        let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
100b8a62b91Sopenharmony_ci        assert!(same(&green, &renamed));
101b8a62b91Sopenharmony_ci        let orig = statat(&dir, "green", AtFlags::empty()).unwrap();
102b8a62b91Sopenharmony_ci        assert!(same(&before, &orig));
103b8a62b91Sopenharmony_ci    }
104b8a62b91Sopenharmony_ci}
105