Skip to content
Snippets Groups Projects
Commit 9471a2e4 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

WIP: Add mtime/ctime to Redox

parent dcce0d9e
No related branches found
No related tags found
No related merge requests found
......@@ -3,7 +3,7 @@
extern crate redoxfs;
extern crate syscall;
use std::{env, process, str};
use std::{env, process, str, time};
use redoxfs::FileSystem;
......@@ -14,9 +14,11 @@ pub mod image;
fn main() {
let mut args = env::args();
if let Some(path) = args.nth(1) {
let ctime = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
//Open an existing image
match Image::open(&path) {
Ok(disk) => match FileSystem::create(Box::new(disk)) {
Ok(disk) => match FileSystem::create(Box::new(disk), ctime.as_secs(), ctime.subsec_nanos()) {
Ok(filesystem) => {
println!("redoxfs-mkfs: created filesystem on {}, size {} MB", path, filesystem.header.1.size/1024/1024);
},
......
......@@ -4,6 +4,7 @@ extern crate time;
use redoxfs;
use std::path::Path;
use std::os::unix::ffi::OsStrExt;
use std::time::{SystemTime, UNIX_EPOCH};
use self::fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyCreate, ReplyDirectory, ReplyEmpty, ReplyStatfs, ReplyWrite};
use self::time::Timespec;
......@@ -12,7 +13,7 @@ pub use self::fuse::mount;
const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second
const CREATE_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
const NULL_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
pub struct Fuse {
pub fs: redoxfs::FileSystem,
......@@ -23,10 +24,16 @@ fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
atime: NULL_TIME,
mtime: Timespec {
sec: node.1.mtime as i64,
nsec: node.1.mtime_nsec as i32,
},
ctime: Timespec {
sec: node.1.ctime as i64,
nsec: node.1.ctime_nsec as i32,
},
crtime: NULL_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else if node.1.is_symlink() {
......@@ -68,7 +75,7 @@ impl Filesystem for Fuse {
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 {
......@@ -127,6 +134,23 @@ impl Filesystem for Fuse {
}
}
if let Some(mtime) = mtime {
match self.fs.node(block) {
Ok(mut node) => if mtime.sec as u64 > node.1.mtime || (mtime.sec as u64 == node.1.mtime && mtime.nsec as u32 > node.1.mtime_nsec) {
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;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
match self.fs.node(block) {
Ok(node) => {
reply.attr(&TTL, &node_attr(&node));
......@@ -150,7 +174,8 @@ impl Filesystem for Fuse {
}
fn write(&mut self, _req: &Request, block: u64, _fh: u64, offset: u64, data: &[u8], _flags: u32, reply: ReplyWrite) {
match self.fs.write_node(block, offset, &data) {
let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
match self.fs.write_node(block, offset, &data, mtime.as_secs(), mtime.subsec_nanos()) {
Ok(count) => {
reply.written(count as u32);
},
......@@ -196,7 +221,8 @@ impl Filesystem for Fuse {
}
fn create(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, flags: u32, reply: ReplyCreate) {
match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
Ok(node) => {
// println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.created(&TTL, &node_attr(&node), 0, 0, flags);
......@@ -208,7 +234,8 @@ impl Filesystem for Fuse {
}
fn mkdir(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
Ok(node) => {
// println!("Mkdir {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.entry(&TTL, &node_attr(&node), 0);
......@@ -257,9 +284,11 @@ impl Filesystem for Fuse {
}
fn symlink(&mut self, _req: &Request, parent_block: u64, name: &Path, link: &Path, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_SYMLINK | 0o777, name.to_str().unwrap(), parent_block) {
let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
match self.fs.create_node(redoxfs::Node::MODE_SYMLINK | 0o777, name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
Ok(node) => {
match self.fs.write_node(node.0, 0, link.as_os_str().as_bytes()) {
let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
match self.fs.write_node(node.0, 0, link.as_os_str().as_bytes(), mtime.as_secs(), mtime.subsec_nanos()) {
Ok(_count) => {
reply.entry(&TTL, &node_attr(&node), 0);
},
......
......@@ -37,15 +37,15 @@ impl FileSystem {
}
/// Create a file system on a disk
pub fn create(mut disk: Box<Disk>) -> Result<Self> {
pub fn create(mut disk: Box<Disk>, ctime: u64, ctime_nsec: u32) -> Result<Self> {
let size = disk.size()?;
if size >= 4 * 512 {
let mut free = (2, Node::new(Node::MODE_FILE, "free", 0));
let mut free = (2, Node::new(Node::MODE_FILE, "free", 0, ctime, ctime_nsec));
free.1.extents[0] = Extent::new(4, size - 4 * 512);
disk.write_at(free.0, &free.1)?;
let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0));
let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0, ctime, ctime_nsec));
disk.write_at(root.0, &root.1)?;
let header = (0, Header::new(size, root.0, free.0));
......@@ -194,11 +194,11 @@ impl FileSystem {
}
}
pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<(u64, Node)> {
pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64, ctime: u64, ctime_nsec: u32) -> Result<(u64, Node)> {
if self.find_node(name, parent_block).is_ok() {
Err(Error::new(EEXIST))
} else {
let node = (self.allocate(1)?, Node::new(mode, name, parent_block));
let node = (self.allocate(1)?, Node::new(mode, name, parent_block, ctime, ctime_nsec));
self.write_at(node.0, &node.1)?;
self.insert_blocks(node.0, 512, parent_block)?;
......@@ -276,6 +276,7 @@ impl FileSystem {
}
}
// TODO: modification time
fn node_ensure_len(&mut self, block: u64, mut length: u64) -> Result<()> {
if block == 0 {
return Err(Error::new(ENOENT));
......@@ -319,6 +320,7 @@ impl FileSystem {
}
}
//TODO: modification time
pub fn node_set_len(&mut self, block: u64, mut length: u64) -> Result<()> {
if block == 0 {
return Err(Error::new(ENOENT));
......@@ -450,7 +452,7 @@ impl FileSystem {
Ok(i)
}
pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8]) -> Result<usize> {
pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8], mtime: u64, mtime_nsec: u32) -> Result<usize> {
let block_offset = offset / 512;
let mut byte_offset = (offset % 512) as usize;
......@@ -512,6 +514,15 @@ impl FileSystem {
assert_eq!(block, extent.block + (extent.length + 511)/512);
}
if i > 0 {
let mut node = self.node(block)?;
if mtime > node.1.mtime || (mtime == node.1.mtime && mtime_nsec > node.1.mtime_nsec) {
node.1.mtime = mtime;
node.1.mtime_nsec = mtime_nsec;
self.write_at(node.0, &node.1)?;
}
}
Ok(i)
}
......
......@@ -22,7 +22,7 @@ pub struct Header {
impl Header {
pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0";
pub const VERSION: u64 = 1;
pub const VERSION: u64 = 2;
pub fn default() -> Header {
Header {
......
......@@ -8,7 +8,11 @@ pub struct Node {
pub mode: u16,
pub uid: u32,
pub gid: u32,
pub name: [u8; 246],
pub ctime: u64,
pub ctime_nsec: u32,
pub mtime: u64,
pub mtime_nsec: u32,
pub name: [u8; 222],
pub parent: u64,
pub next: u64,
pub extents: [Extent; 15],
......@@ -30,15 +34,19 @@ impl Node {
mode: 0,
uid: 0,
gid: 0,
name: [0; 246],
ctime: 0,
ctime_nsec: 0,
mtime: 0,
mtime_nsec: 0,
name: [0; 222],
parent: 0,
next: 0,
extents: [Extent::default(); 15],
}
}
pub fn new(mode: u16, name: &str, parent: u64) -> Node {
let mut bytes = [0; 246];
pub fn new(mode: u16, name: &str, parent: u64, ctime: u64, ctime_nsec: u32) -> Node {
let mut bytes = [0; 222];
for (mut b, c) in bytes.iter_mut().zip(name.bytes()) {
*b = c;
}
......@@ -47,6 +55,10 @@ impl Node {
mode: mode,
uid: 0,
gid: 0,
ctime: ctime,
ctime_nsec: ctime_nsec,
mtime: ctime,
mtime_nsec: ctime_nsec,
name: bytes,
parent: parent,
next: 0,
......@@ -105,6 +117,10 @@ impl fmt::Debug for Node {
.field("mode", &self.mode)
.field("uid", &self.uid)
.field("gid", &self.gid)
.field("ctime", &self.ctime)
.field("ctime_nsec", &self.ctime_nsec)
.field("mtime", &self.mtime)
.field("mtime_nsec", &self.mtime_nsec)
.field("name", &self.name())
.field("next", &self.next)
.field("extents", &extents)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment