diff --git a/Cargo.lock b/Cargo.lock index e381c19cfef0bbc2bc73ce12a28ad83dcd946549..a0d2a97805b165abb5aff3b0075c6f172a542dea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,7 +97,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redoxfs" -version = "0.3.7" +version = "0.4.0" dependencies = [ "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 48e423bfe416f2563c95e3fce3a806b2eefec6bd..3fb711a3d01cc27e9358c79d0ddf616a85a73da9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "redoxfs" description = "The Redox Filesystem" repository = "https://gitlab.redox-os.org/redox-os/redoxfs" -version = "0.3.7" +version = "0.4.0" license-file = "LICENSE" readme = "README.md" authors = ["Jeremy Soller <jackpot51@gmail.com>"] diff --git a/src/filesystem.rs b/src/filesystem.rs index ce112bb307c496dc5c3a2ba30525d6d664dcb5a5..e1e0bd7e86c09cb67d752e6ded81ad43ecebeda5 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -1,4 +1,5 @@ use std::cmp::min; +use std::time::{SystemTime, UNIX_EPOCH}; use syscall::error::{Result, Error, EEXIST, EISDIR, EINVAL, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY}; @@ -428,6 +429,7 @@ impl<D: Disk> FileSystem<D> { } pub fn read_node(&mut self, block: u64, offset: u64, buf: &mut [u8]) -> Result<usize> { + let atime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); let block_offset = offset / BLOCK_SIZE; let mut byte_offset = (offset % BLOCK_SIZE) as usize; @@ -483,6 +485,20 @@ impl<D: Disk> FileSystem<D> { assert_eq!(block, extent.block + (extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE); } + if i > 0 { + let atime_nsec = atime.subsec_nanos(); + let atime = atime.as_secs(); + let mut node = self.node(block)?; + if atime > node.1.atime || (atime == node.1.atime && atime_nsec > node.1.atime_nsec) { + let is_old = atime - node.1.atime > 3600; // Last read was more than a day ago + node.1.atime = atime; + node.1.atime_nsec = atime_nsec; + if is_old { + self.write_at(node.0, &node.1)?; + } + } + } + Ok(i) } diff --git a/src/lib.rs b/src/lib.rs index bc9fba2594f65e726993532f3b108fa000a8064e..0d7bf32106dc32a2da5d1134b56259a22178a3c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -#![crate_name="redoxfs"] -#![crate_type="lib"] +#![crate_name = "redoxfs"] +#![crate_type = "lib"] extern crate syscall; extern crate uuid; @@ -8,7 +8,7 @@ use std::sync::atomic::AtomicUsize; pub const BLOCK_SIZE: u64 = 4096; pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0"; -pub const VERSION: u64 = 3; +pub const VERSION: u64 = 4; pub static IS_UMT: AtomicUsize = AtomicUsize::new(0); pub use self::archive::{archive, archive_at}; diff --git a/src/mount/fuse.rs b/src/mount/fuse.rs index 9ea08a772063b187773535224e6a9a5d680f6c6e..b5335e4ed38da133852baaf22d8001468a2f4003 100644 --- a/src/mount/fuse.rs +++ b/src/mount/fuse.rs @@ -117,7 +117,7 @@ impl<D: Disk> Filesystem for Fuse<D> { fn setattr(&mut self, _req: &Request, block: u64, mode: Option<u32>, uid: Option<u32>, gid: Option<u32>, size: Option<u64>, - _atime: Option<Timespec>, mtime: Option<Timespec>, _fh: Option<u64>, + atime: Option<Timespec>, mtime: Option<Timespec>, _fh: Option<u64>, _crtime: Option<Timespec>, _chgtime: Option<Timespec>, _bkuptime: Option<Timespec>, _flags: Option<u32>, reply: ReplyAttr) { if let Some(mode) = mode { @@ -176,11 +176,20 @@ impl<D: Disk> Filesystem for Fuse<D> { } } - if let Some(mtime) = mtime { + let need_update = atime.is_some() || mtime.is_some(); + if need_update { match self.fs.node(block) { Ok(mut node) => { - node.1.mtime = mtime.sec as u64; - node.1.mtime_nsec = mtime.nsec as u32; + if let Some(atime) = atime { + node.1.atime = atime.sec as u64; + node.1.atime_nsec = atime.nsec as u32; + } + + if let Some(mtime) = mtime { + node.1.mtime = mtime.sec as u64; + node.1.mtime_nsec = mtime.nsec as u32; + } + if let Err(err) = self.fs.write_at(node.0, &node.1) { reply.error(err.errno as i32); return; diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs index 04a3af4fd458108cc5d2ab7f64bd2c880679b211..49fa2aadd35a2e64b3f40bd830b9407f5330f070 100644 --- a/src/mount/redox/resource.rs +++ b/src/mount/redox/resource.rs @@ -165,6 +165,8 @@ impl<D: Disk> Resource<D> for DirResource { st_size: fs.node_len(self.block)?, st_mtime: node.1.mtime, st_mtime_nsec: node.1.mtime_nsec, + st_atime: node.1.atime, + st_atime_nsec: node.1.atime_nsec, st_ctime: node.1.ctime, st_ctime_nsec: node.1.ctime_nsec, ..Default::default() @@ -426,6 +428,8 @@ impl<D: Disk> Resource<D> for FileResource { st_size: fs.node_len(self.block)?, st_mtime: node.1.mtime, st_mtime_nsec: node.1.mtime_nsec, + st_atime: node.1.atime, + st_atime_nsec: node.1.atime_nsec, st_ctime: node.1.ctime, st_ctime_nsec: node.1.ctime_nsec, ..Default::default() @@ -455,17 +459,16 @@ impl<D: Disk> Resource<D> for FileResource { let mut node = fs.node(self.block)?; if node.1.uid == self.uid || self.uid == 0 { - if let Some(mtime) = times.get(1) { + if let &[atime, mtime] = times { node.1.mtime = mtime.tv_sec as u64; node.1.mtime_nsec = mtime.tv_nsec as u32; + node.1.atime = atime.tv_sec as u64; + node.1.atime_nsec = atime.tv_nsec as u32; fs.write_at(node.0, &node.1)?; - - Ok(0) - } else { - Ok(0) } + Ok(0) } else { Err(Error::new(EPERM)) } diff --git a/src/node.rs b/src/node.rs index f8b257ca9f68204cc8e671d22e0b78f5ed586039..f85a341cd7bf844095d18a8665bc4bedd707005e 100644 --- a/src/node.rs +++ b/src/node.rs @@ -14,10 +14,12 @@ pub struct Node { pub ctime_nsec: u32, pub mtime: u64, pub mtime_nsec: u32, - pub name: [u8; 222], + pub atime: u64, + pub atime_nsec: u32, + pub name: [u8; 226], pub parent: u64, pub next: u64, - pub extents: [Extent; (BLOCK_SIZE as usize - 272)/16], + pub extents: [Extent; (BLOCK_SIZE as usize - 288)/16], } impl Node { @@ -40,15 +42,17 @@ impl Node { ctime_nsec: 0, mtime: 0, mtime_nsec: 0, - name: [0; 222], + atime: 0, + atime_nsec: 0, + name: [0; 226], parent: 0, next: 0, - extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16], + extents: [Extent::default(); (BLOCK_SIZE as usize - 288)/16], } } pub fn new(mode: u16, name: &str, parent: u64, ctime: u64, ctime_nsec: u32) -> syscall::Result<Node> { - let mut bytes = [0; 222]; + let mut bytes = [0; 226]; if name.len() > bytes.len() { return Err(syscall::Error::new(syscall::ENAMETOOLONG)); } @@ -64,10 +68,12 @@ impl Node { ctime_nsec: ctime_nsec, mtime: ctime, mtime_nsec: ctime_nsec, + atime: ctime, + atime_nsec: ctime_nsec, name: bytes, parent: parent, next: 0, - extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16], + extents: [Extent::default(); (BLOCK_SIZE as usize - 288)/16], }) } @@ -85,7 +91,7 @@ impl Node { } pub fn set_name(&mut self, name: &str) -> syscall::Result<()> { - let mut bytes = [0; 222]; + let mut bytes = [0; 226]; if name.len() > bytes.len() { return Err(syscall::Error::new(syscall::ENAMETOOLONG)); }