Skip to main content

rspack_fs/
file_metadata.rs

1use std::fs::{Metadata, Permissions};
2
3use cfg_if::cfg_if;
4
5use crate::{Error, IoResultToFsResultExt, Result};
6
7#[derive(Debug, Clone)]
8pub struct FileMetadata {
9  pub is_file: bool,
10  pub is_directory: bool,
11  pub is_symlink: bool,
12  pub atime_ms: u64,
13  pub mtime_ms: u64,
14  pub ctime_ms: u64,
15  pub size: u64,
16}
17
18impl FileMetadata {
19  #[allow(unused_variables)]
20  fn get_ctime_ms(metadata: &Metadata) -> u64 {
21    #[cfg(unix)]
22    {
23      let ctime = std::os::unix::fs::MetadataExt::ctime(metadata);
24      let ctime_nsec = std::os::unix::fs::MetadataExt::ctime_nsec(metadata);
25      let ctime_ms = ctime * 1000 + ctime_nsec / 1_000_000;
26      return ctime_ms as u64;
27    }
28    // windows not support ctime
29    #[allow(unreachable_code)]
30    0u64
31  }
32}
33
34impl TryFrom<Metadata> for FileMetadata {
35  type Error = Error;
36
37  fn try_from(metadata: Metadata) -> Result<Self> {
38    let mtime_ms = metadata
39      .modified()
40      .to_fs_result()?
41      .duration_since(std::time::UNIX_EPOCH)
42      .expect("mtime is before unix epoch")
43      .as_millis() as u64;
44    let atime_ms = metadata
45      .accessed()
46      .to_fs_result()?
47      .duration_since(std::time::UNIX_EPOCH)
48      .expect("atime is before unix epoch")
49      .as_millis() as u64;
50    let ctime_ms = Self::get_ctime_ms(&metadata);
51
52    Ok(Self {
53      is_directory: metadata.is_dir(),
54      is_file: metadata.is_file(),
55      is_symlink: metadata.is_symlink(),
56      size: metadata.len(),
57      mtime_ms,
58      ctime_ms,
59      atime_ms,
60    })
61  }
62}
63
64/// This is a target-agnostic file permission abstraction.
65/// Currently we only support getting and setting file permissions on unix target.
66/// If we are supporting more targets, organizing the code like [std::sys::fs] will be a better choice.
67#[derive(Debug, Clone)]
68pub struct FilePermissions(#[cfg(target_family = "unix")] u32);
69
70impl FilePermissions {
71  cfg_if! {
72      if #[cfg(target_family = "unix")] {
73        pub fn from_mode(mode: u32) -> Self {
74          Self(mode)
75        }
76
77        pub fn into_mode(self) -> Option<u32> {
78          Some(self.0)
79        }
80
81        pub fn from_std(perm: Permissions) -> Self {
82          use std::os::unix::fs::PermissionsExt;
83          Self(perm.mode())
84        }
85
86        pub fn into_std(self) -> Option<Permissions> {
87          use std::os::unix::fs::PermissionsExt;
88          Some(Permissions::from_mode(self.0))
89        }
90      } else {
91        pub fn from_mode(_mode: u32) -> Self {
92          Self()
93        }
94
95        pub fn into_mode(self) -> Option<u32> {
96          None
97        }
98
99        pub fn from_std(_perm: Permissions) -> Self {
100          Self()
101        }
102
103        pub fn into_std(self) -> Option<Permissions> {
104          None
105        }
106      }
107  }
108}