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