Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add time to dir entry #215

Merged
merged 7 commits into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions doc/filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
A hard drive is separated in blocks of 512 bytes, grouped into 4 areas:

+------------+
| Boot | (2048 blocks)
| Boot | (4096 blocks)
+------------+
| Superblock | (2 blocks)
+------------+
Expand Down Expand Up @@ -103,16 +103,17 @@ Structure:
A directory entry represents a file or a directory contained inside a
directory. Each entry use a variable number of bytes that must fit inside the
data of one block. Those bytes represent the kind of entry (file or dir), the
address of the first block, the filesize (max 4GB), the length of the filename,
and the filename (max 255 chars) of the entry.
address of the first block, the filesize (max 4GB), the last modified time in
seconds since Unix Epoch, the length of the filename, and the filename (max
255 chars) of the entry.

Structure:

0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 m
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+
|k| addr | size |n| name buffer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 m
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+
|k| addr | size | time |n| name buffer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+

k = kind of entry
n = length of name buffer
Expand Down
110 changes: 110 additions & 0 deletions run/moros-fuse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python

from errno import ENOENT
from fuse import FUSE, FuseOSError, Operations, LoggingMixIn
from stat import S_IFDIR, S_IFREG

class MorosFuse(Operations):
chmod = None
chown = None
create = None
mkdir = None
readlink = None
rename = None
rmdir = None
symlink = None
truncate = None
unlink = None
utimens = None
write = None

def __init__(self, path):
self.image = open(path, "rb")
self.image_offset = 4096
self.block_size = 512
addr = self.image_offset * self.block_size
self.image.seek(addr)
block = self.image.read(self.block_size)

def destroy(self, path):
self.image.close()
return

def getattr(self, path, fh=None):
(kind, addr, size, time, name) = self.__scan(path)
if addr == 0:
raise FuseOSError(ENOENT)
mode = S_IFDIR | 0o755 if kind == 0 else S_IFREG | 0o644
return { "st_atime": 0, "st_mtime": time, "st_uid": 0, "st_gid": 0, "st_mode": mode, "st_size": size }

def read(self, path, size, offset, fh):
(kind, next_block_addr, size, time, name) = self.__scan(path)
res = b""
while next_block_addr != 0:
self.image.seek(next_block_addr)
next_block_addr = int.from_bytes(self.image.read(4), "big") * self.block_size
if offset < self.block_size - 4:
buf = self.image.read(min(self.block_size - 4, size))
res = b"".join([res, buf[offset:]])
offset = 0
else:
offset -= self.block_size - 4
size -= self.block_size - 4
return res

def readdir(self, path, fh):
files = [".", ".."]
(_, next_block_addr, _, _, _) = self.__scan(path)
while next_block_addr != 0:
self.image.seek(next_block_addr)
next_block_addr = int.from_bytes(self.image.read(4), "big")
offset = 4
while offset < self.block_size:
kind = int.from_bytes(self.image.read(1), "big")
addr = int.from_bytes(self.image.read(4), "big") * self.block_size
if addr == 0:
break
size = int.from_bytes(self.image.read(4), "big")
time = int.from_bytes(self.image.read(8), "big")
n = int.from_bytes(self.image.read(1), "big")
name = self.image.read(n).decode("utf-8")
offset += 1 + 4 + 4 + 8 + 1 + n
files.append(name)
return files

def __scan(self, path):
dirs = path[1:].split("/")
d = dirs.pop(0)
next_block_addr = (self.image_offset + 2 + self.block_size) * self.block_size
if d == "":
return (0, next_block_addr, 0, 0, d)
while next_block_addr != 0:
self.image.seek(next_block_addr)
next_block_addr = int.from_bytes(self.image.read(4), "big")
offset = 4
while offset < self.block_size:
kind = int.from_bytes(self.image.read(1), "big")
addr = int.from_bytes(self.image.read(4), "big") * self.block_size
if addr == 0:
break
size = int.from_bytes(self.image.read(4), "big")
time = int.from_bytes(self.image.read(8), "big")
n = int.from_bytes(self.image.read(1), "big")
name = self.image.read(n).decode("utf-8")
offset += 1 + 4 + 4 + 1 + n
if name == d:
if len(dirs) == 0:
return (kind, addr, size, time, name)
else:
next_block_addr = addr
d = dirs.pop(0)
break
return (0, 0, 0, 0, "")

if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('image')
parser.add_argument('mount')
args = parser.parse_args()
fuse = FUSE(MorosFuse(args.image), args.mount, ro=True, foreground=True, allow_other=True)
9 changes: 9 additions & 0 deletions run/moros-fuse.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

img="disk.img"
path="/tmp/moros"

# pip install fusepy
mkdir -p $path
echo "Mounting $img in $path"
python run/moros-fuse.py $img $path
1 change: 1 addition & 0 deletions src/api/console.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::sys;
use core::fmt;

#[derive(Clone, Copy)]
pub struct Style {
foreground: Option<usize>,
background: Option<usize>,
Expand Down
98 changes: 67 additions & 31 deletions src/sys/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub struct File {
name: String,
addr: u32,
size: u32,
time: u64,
dir: Dir, // TODO: Replace with `parent: Some(Dir)` and also add it to `Dir`
offset: u32,
}
Expand Down Expand Up @@ -192,7 +193,7 @@ impl File {
block.write();
}
self.size = self.offset;
self.dir.update_entry_size(&self.name, self.size);
self.dir.update_entry(&self.name, self.size);
Ok(bytes)
}

Expand Down Expand Up @@ -371,13 +372,14 @@ pub struct DirEntry {
kind: FileType,
addr: u32,
size: u32,
time: u64,
name: String,
}

impl DirEntry {
pub fn new(dir: Dir, kind: FileType, addr: u32, size: u32, name: &str) -> Self {
pub fn new(dir: Dir, kind: FileType, addr: u32, size: u32, time: u64, name: &str) -> Self {
let name = String::from(name);
Self { dir, kind, addr, size, name }
Self { dir, kind, addr, size, time, name }
}

pub fn is_dir(&self) -> bool {
Expand All @@ -392,6 +394,10 @@ impl DirEntry {
self.size
}

pub fn time(&self) -> u64 {
self.time
}

pub fn name(&self) -> String {
self.name.clone()
}
Expand All @@ -407,13 +413,14 @@ impl DirEntry {
name: self.name.clone(),
addr: self.addr,
size: self.size,
time: self.time,
dir: self.dir,
offset: 0,
}
}

pub fn len(&self) -> usize {
1 + 4 + 4 + 1 + self.name.len()
1 + 4 + 4 + 8 + 1 + self.name.len()
}
}

Expand Down Expand Up @@ -509,28 +516,37 @@ impl Dir {

let entry_kind = kind;
let entry_size = 0;
let entry_time = sys::clock::realtime() as u64;
let entry_addr = new_block.addr();
let entry_name = name.as_bytes();

let n = entry_name.len();
let i = read_dir.data_offset;
let data = read_dir.block.data_mut();
data[i + 0] = entry_kind as u8;
data[i + 1] = entry_addr.get_bits(24..32) as u8;
data[i + 2] = entry_addr.get_bits(16..24) as u8;
data[i + 3] = entry_addr.get_bits(8..16) as u8;
data[i + 4] = entry_addr.get_bits(0..8) as u8;
data[i + 5] = entry_size.get_bits(24..32) as u8;
data[i + 6] = entry_size.get_bits(16..24) as u8;
data[i + 7] = entry_size.get_bits(8..16) as u8;
data[i + 8] = entry_size.get_bits(0..8) as u8;
data[i + 9] = n as u8;
data[i + 0] = entry_kind as u8;
data[i + 1] = entry_addr.get_bits(24..32) as u8;
data[i + 2] = entry_addr.get_bits(16..24) as u8;
data[i + 3] = entry_addr.get_bits(8..16) as u8;
data[i + 4] = entry_addr.get_bits(0..8) as u8;
data[i + 5] = entry_size.get_bits(24..32) as u8;
data[i + 6] = entry_size.get_bits(16..24) as u8;
data[i + 7] = entry_size.get_bits(8..16) as u8;
data[i + 8] = entry_size.get_bits(0..8) as u8;
data[i + 9] = entry_time.get_bits(56..64) as u8;
data[i + 10] = entry_time.get_bits(48..56) as u8;
data[i + 11] = entry_time.get_bits(40..48) as u8;
data[i + 12] = entry_time.get_bits(32..40) as u8;
data[i + 13] = entry_time.get_bits(24..32) as u8;
data[i + 14] = entry_time.get_bits(16..24) as u8;
data[i + 15] = entry_time.get_bits(8..16) as u8;
data[i + 16] = entry_time.get_bits(0..8) as u8;
data[i + 17] = n as u8;
for j in 0..n {
data[i + 10 + j] = entry_name[j];
data[i + 18 + j] = entry_name[j];
}
read_dir.block.write();

Some(DirEntry::new(*self, kind, entry_addr, entry_size, name))
Some(DirEntry::new(*self, kind, entry_addr, entry_size, entry_time, name))
}

// Deleting an entry is done by setting the entry address to 0
Expand Down Expand Up @@ -564,16 +580,25 @@ impl Dir {
Err(())
}

fn update_entry_size(&mut self, name: &str, size: u32) {
fn update_entry(&mut self, name: &str, size: u32) {
let mut read_dir = self.read();
for entry in &mut read_dir {
if entry.name == name {
let time = sys::clock::realtime() as u64;
let data = read_dir.block.data_mut();
let i = read_dir.data_offset - entry.len();
data[i + 5] = size.get_bits(24..32) as u8;
data[i + 6] = size.get_bits(16..24) as u8;
data[i + 7] = size.get_bits(8..16) as u8;
data[i + 8] = size.get_bits(0..8) as u8;
data[i + 5] = size.get_bits(24..32) as u8;
data[i + 6] = size.get_bits(16..24) as u8;
data[i + 7] = size.get_bits(8..16) as u8;
data[i + 8] = size.get_bits(0..8) as u8;
data[i + 9] = time.get_bits(56..64) as u8;
data[i + 10] = time.get_bits(48..56) as u8;
data[i + 11] = time.get_bits(40..48) as u8;
data[i + 12] = time.get_bits(32..40) as u8;
data[i + 13] = time.get_bits(24..32) as u8;
data[i + 14] = time.get_bits(16..24) as u8;
data[i + 15] = time.get_bits(8..16) as u8;
data[i + 16] = time.get_bits(0..8) as u8;
read_dir.block.write();
break;
}
Expand Down Expand Up @@ -624,15 +649,26 @@ impl Iterator for ReadDir {
1 => FileType::File,
_ => break,
};
let entry_addr = (data[i + 1] as u32) << 24
| (data[i + 2] as u32) << 16
| (data[i + 3] as u32) << 8
| (data[i + 4] as u32);
let entry_size = (data[i + 5] as u32) << 24
| (data[i + 6] as u32) << 16
| (data[i + 7] as u32) << 8
| (data[i + 8] as u32);
i += 9;

let entry_addr = (data[i + 1] as u32) << 24
| (data[i + 2] as u32) << 16
| (data[i + 3] as u32) << 8
| (data[i + 4] as u32);

let entry_size = (data[i + 5] as u32) << 24
| (data[i + 6] as u32) << 16
| (data[i + 7] as u32) << 8
| (data[i + 8] as u32);

let entry_time = (data[i + 9] as u64) << 56
| (data[i + 10] as u64) << 48
| (data[i + 11] as u64) << 40
| (data[i + 12] as u64) << 32
| (data[i + 13] as u64) << 24
| (data[i + 14] as u64) << 16
| (data[i + 15] as u64) << 8
| (data[i + 16] as u64);
i += 17;

let mut n = data[i];
if n == 0 || n as usize >= data.len() - i {
Expand All @@ -658,7 +694,7 @@ impl Iterator for ReadDir {
continue;
}

return Some(DirEntry::new(self.dir, entry_kind, entry_addr, entry_size, &entry_name));
return Some(DirEntry::new(self.dir, entry_kind, entry_addr, entry_size, entry_time, &entry_name));
}

match self.block.next() {
Expand Down
Loading