shell_rs/core/
fs.rs

1// Copyright (c) 2021 Xu Shaohua <shaohua@biofan.org>. All rights reserved.
2// Use of this source is governed by General Public License that can be found
3// in the LICENSE file.
4
5use std::path::Path;
6
7use crate::error::Error;
8
9/// Check whether two files refere to same file in filesystem.
10pub fn same_file<P: AsRef<Path>>(file1: P, file2: P) -> Result<bool, Error> {
11    let fd1 = unsafe { nc::openat(nc::AT_FDCWD, file1.as_ref(), nc::O_RDONLY, 0)? };
12    let fd2 = unsafe { nc::openat(nc::AT_FDCWD, file2.as_ref(), nc::O_RDONLY, 0)? };
13    let is_same = same_file_fd(fd1, fd2)?;
14    unsafe { nc::close(fd1)? };
15    unsafe { nc::close(fd2)? };
16    Ok(is_same)
17}
18
19/// Check whether two file descriptors refere to same file in filesystem.
20pub fn same_file_fd(fd1: i32, fd2: i32) -> Result<bool, Error> {
21    let mut stat1 = nc::stat_t::default();
22    unsafe { nc::fstat(fd1, &mut stat1)? };
23    let mut stat2 = nc::stat_t::default();
24    unsafe { nc::fstat(fd2, &mut stat2)? };
25    Ok(stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino)
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn test_same_file() {
34        assert_eq!(same_file("/etc/passwd", "/etc/passwd"), Ok(true));
35    }
36}