-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a trivial root directory implementation (#24)
This change adds the foundations of the in-memory representation of the contents of a sandboxfs instance. In particular, a Node trait that will handle all node-related operations and the basics of a Dir implementation. The implementation of the root directory does nothing interesting at this point: it just exposes the . and .. entries and returns ENOENT for any lookups, which is sufficient to introduce the basic file system concepts. Note that this does not yet allow us to enable more tests in travis-build.sh, so the new code introduced by this change was purely tested locally by mounting the file system and ensuring an "ls -a" shows the dot entries and that accessing any file returns ENOENT.
- Loading branch information
Showing
4 changed files
with
254 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,4 +18,6 @@ env_logger = "0.5" | |
failure = "0.1" | ||
fuse = "0.3" | ||
getopts = "0.2" | ||
libc = "0.2" | ||
log = "0.4" | ||
time = "0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2018 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy | ||
// of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
extern crate fuse; | ||
extern crate libc; | ||
extern crate time; | ||
|
||
use std::ffi::OsStr; | ||
use std::sync::{Arc, Mutex}; | ||
use self::time::Timespec; | ||
use super::KernelError; | ||
use super::Node; | ||
use super::NodeResult; | ||
|
||
/// Representation of a directory node. | ||
pub struct Dir { | ||
inode: u64, | ||
state: Mutex<MutableDir>, | ||
} | ||
|
||
/// Holds the mutable data of a directory node. | ||
struct MutableDir { | ||
parent: u64, | ||
attr: fuse::FileAttr, | ||
} | ||
|
||
impl Dir { | ||
/// Creates a new scaffold directory to represent the root directory. | ||
/// | ||
/// `time` is the timestamp to be used for all node times. | ||
/// | ||
/// `uid` and `gid` indicate the ownership details of the node. These should always match the | ||
/// values of the currently-running process -- but not necessarily if we want to let users | ||
/// customize these via flags at some point. | ||
pub fn new_root(time: Timespec, uid: u32, gid: u32) -> Arc<Node> { | ||
let inode = fuse::FUSE_ROOT_ID; | ||
|
||
let attr = fuse::FileAttr { | ||
ino: inode, | ||
kind: fuse::FileType::Directory, | ||
nlink: 2, // "." entry plus whichever initial named node points at this. | ||
size: 2, // TODO(jmmv): Reevaluate what directory sizes should be. | ||
blocks: 1, // TODO(jmmv): Reevaluate what directory blocks should be. | ||
atime: time, | ||
mtime: time, | ||
ctime: time, | ||
crtime: time, | ||
perm: 0o555 as u16, // Scaffold directories cannot be mutated by the user. | ||
uid: uid, | ||
gid: gid, | ||
rdev: 0, | ||
flags: 0, | ||
}; | ||
|
||
let state = MutableDir { parent: inode, attr }; | ||
|
||
Arc::new(Dir { | ||
inode, | ||
state: Mutex::from(state), | ||
}) | ||
} | ||
} | ||
|
||
impl Node for Dir { | ||
fn inode(&self) -> u64 { | ||
self.inode | ||
} | ||
|
||
fn getattr(&self) -> NodeResult<fuse::FileAttr> { | ||
let state = self.state.lock().unwrap(); | ||
Ok(state.attr.clone()) | ||
} | ||
|
||
fn lookup(&self, _name: &OsStr) -> NodeResult<(Arc<Node>, fuse::FileAttr)> { | ||
return Err(KernelError::from_errno(libc::ENOENT)); | ||
} | ||
|
||
fn readdir(&self, reply: &mut fuse::ReplyDirectory) -> NodeResult<()> { | ||
let state = self.state.lock().unwrap(); | ||
|
||
reply.add(self.inode, 0, fuse::FileType::Directory, "."); | ||
reply.add(state.parent, 1, fuse::FileType::Directory, ".."); | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2018 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy | ||
// of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
use fuse; | ||
use std::ffi::OsStr; | ||
use std::sync::Arc; | ||
|
||
mod dir; | ||
pub use self::dir::Dir; | ||
|
||
/// Type that represents an error understood by the kernel. | ||
#[derive(Debug, Fail)] | ||
#[fail(display = "errno={}", errno)] | ||
pub struct KernelError { | ||
errno: i32, | ||
} | ||
|
||
impl KernelError { | ||
/// Constructs a new error given a raw errno code. | ||
fn from_errno(errno: i32) -> KernelError { | ||
KernelError { errno } | ||
} | ||
|
||
/// Obtains the errno code contained in this error, which can be fed back into the kernel. | ||
pub fn errno(&self) -> i32 { | ||
return self.errno; | ||
} | ||
} | ||
|
||
/// Generic result type for of all node operations. | ||
pub type NodeResult<T> = Result<T, KernelError>; | ||
|
||
/// Abstract representation of a file system node. | ||
/// | ||
/// Due to the way nodes and node operations are represented in the kernel, this trait exposes a | ||
/// collection of methods that do not all make sense for all possible node types: some methods will | ||
/// only make sense for directories and others will only make sense for regular files, for example. | ||
/// These conflicting methods come with a default implementation that panics. | ||
pub trait Node { | ||
/// Returns the inode number of this node. | ||
/// | ||
/// The inode number is immutable and, as such, this information can be queried without having | ||
/// to lock the node. | ||
fn inode(&self) -> u64; | ||
|
||
/// Retrieves the node's metadata. | ||
fn getattr(&self) -> NodeResult<fuse::FileAttr>; | ||
|
||
/// Looks up a node with the given name within the current node and returns the found node and | ||
/// its attributes at the time of the query. | ||
/// | ||
/// The attributes are returned to avoid having to relock the node on the caller side in order | ||
/// to supply those attributes to the kernel. | ||
fn lookup(&self, _name: &OsStr) -> NodeResult<(Arc<Node>, fuse::FileAttr)> { | ||
panic!("Not implemented"); | ||
} | ||
|
||
/// Reads all directory entries into the given reply object. | ||
/// | ||
/// It is the responsibility of the caller to invoke `reply.ok()` on the reply object. This is | ||
/// for consistency with the handling of any errors returned by this function. | ||
fn readdir(&self, _reply: &mut fuse::ReplyDirectory) -> NodeResult<()> { | ||
panic!("Not implemented"); | ||
} | ||
} |