1#[cfg(any(target_os = "android", target_os = "linux"))] 2use rustix::fs::Stat; 3 4#[cfg(any(target_os = "android", target_os = "linux"))] 5fn 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] 11fn 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] 34fn 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] 56fn 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