Skip to content

Commit

Permalink
Move DirBuffer into ReplyDirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
zargony committed Apr 3, 2014
1 parent a33df7e commit f02b645
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 122 deletions.
12 changes: 6 additions & 6 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::default::Default;
use std::libc::{ENOENT, S_IFDIR, S_IFREG};
use std::io::{TypeFile, TypeDirectory};
use std::os;
use fuse::{Filesystem, Request, ReplyData, ReplyDirectory, ReplyRaw, fuse_attr, fuse_entry_out, fuse_attr_out, DirBuffer};
use fuse::{Filesystem, Request, ReplyData, ReplyDirectory, ReplyRaw, fuse_attr, fuse_entry_out, fuse_attr_out};

struct HelloFS;

Expand Down Expand Up @@ -47,14 +47,14 @@ impl Filesystem for HelloFS {
}
}

fn readdir (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, mut buffer: DirBuffer, reply: ReplyDirectory) {
fn readdir (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, mut reply: ReplyDirectory) {
if ino == 1 {
if offset == 0 {
buffer.fill(1, 0, TypeDirectory, &PosixPath::new("."));
buffer.fill(1, 1, TypeDirectory, &PosixPath::new(".."));
buffer.fill(2, 2, TypeFile, &PosixPath::new("hello.txt"));
reply.add(1, 0, TypeDirectory, &PosixPath::new("."));
reply.add(1, 1, TypeDirectory, &PosixPath::new(".."));
reply.add(2, 2, TypeFile, &PosixPath::new("hello.txt"));
}
reply.ok(&buffer);
reply.ok();
} else {
reply.error(ENOENT);
}
Expand Down
4 changes: 1 addition & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ pub use fuse::consts;
pub use reply::{Reply, ReplyEmpty, ReplyData, ReplyDirectory};
pub use reply::ReplyRaw; // FIXME: ReplyRaw is going to be replaced with specialized reply types
pub use request::Request;
pub use sendable::DirBuffer;
pub use session::{Session, BackgroundSession};

mod argument;
mod channel;
mod fuse;
mod reply;
mod request;
mod sendable;
mod session;

/// Filesystem trait.
Expand Down Expand Up @@ -212,7 +210,7 @@ pub trait Filesystem {
/// requested size. Send an empty buffer on end of stream. fh will contain the
/// value set by the opendir method, or will be undefined if the opendir method
/// didn't set any value.
fn readdir (&mut self, _req: &Request, _ino: u64, _fh: u64, _offset: u64, _buffer: DirBuffer, reply: ReplyDirectory) {
fn readdir (&mut self, _req: &Request, _ino: u64, _fh: u64, _offset: u64, reply: ReplyDirectory) {
reply.error(ENOSYS);
}

Expand Down
74 changes: 64 additions & 10 deletions src/reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
//! exactly once).
//!

use std::{mem, slice};
use std::{cast, mem, ptr, slice};
use std::io::{FileType, TypeFile, TypeDirectory, TypeNamedPipe, TypeBlockSpecial, TypeSymlink, TypeUnknown};
use std::libc::{c_int, EIO};
use fuse::fuse_out_header;
use sendable::{Sendable, DirBuffer};
use std::libc::{S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFLNK};
use fuse::{fuse_out_header, fuse_dirent};

/// Generic reply trait
pub trait Reply {
Expand Down Expand Up @@ -139,20 +140,56 @@ impl ReplyData {
///
pub struct ReplyDirectory {
reply: ReplyRaw<()>,
size: uint,
data: Vec<u8>,
}

impl Reply for ReplyDirectory {
fn new (unique: u64, sender: proc:Send(&[&[u8]])) -> ReplyDirectory {
ReplyDirectory { reply: Reply::new(unique, sender) }
ReplyDirectory { reply: Reply::new(unique, sender), size: 0, data: Vec::with_capacity(4096) }
}
}

impl ReplyDirectory {
/// Reply to a request with the given data
pub fn ok (mut self, buffer: &DirBuffer) {
buffer.as_bytegroups(|bytes| {
self.reply.send(0, bytes);
});
/// Changes the max size of the directory buffer
pub fn sized (mut self, size: uint) -> ReplyDirectory {
self.size = size;
self.data.reserve(size);
self
}

/// Add an entry to the directory reply buffer. Returns true if the buffer is full.
/// A transparent offset value can be provided for each entry. The kernel uses these
/// value to request the next entries in further readdir calls
pub fn add (&mut self, ino: u64, offset: u64, kind: FileType, name: &PosixPath) -> bool {
let name = name.as_vec();
let entlen = mem::size_of::<fuse_dirent>() + name.len();
let entsize = (entlen + mem::size_of::<u64>() - 1) & !(mem::size_of::<u64>() - 1); // 64bit align
let padlen = entsize - entlen;
if self.data.len() + entsize > self.data.capacity() { return true; }
unsafe {
let p = self.data.as_mut_ptr().offset(self.data.len() as int);
let pdirent: *mut fuse_dirent = cast::transmute(p);
(*pdirent).ino = ino;
(*pdirent).off = offset;
(*pdirent).namelen = name.len() as u32;
(*pdirent).typ = match kind {
TypeFile => S_IFREG, TypeDirectory => S_IFDIR, TypeNamedPipe => S_IFCHR,
TypeBlockSpecial => S_IFBLK, TypeSymlink => S_IFLNK, TypeUnknown => 0,
} as u32 >> 12;
let p = p.offset(mem::size_of_val(&*pdirent) as int);
ptr::copy_memory(p, name.as_ptr(), name.len());
let p = p.offset(name.len() as int);
ptr::zero_memory(p, padlen);
let newlen = self.data.len() + entsize;
self.data.set_len(newlen);
}
false
}

/// Reply to a request with the filled directory buffer
pub fn ok (mut self) {
self.reply.send(0, [self.data.as_slice()]);
}

/// Reply to a request with the given error code
Expand All @@ -164,8 +201,9 @@ impl ReplyDirectory {

#[cfg(test)]
mod test {
use std::io::{TypeFile, TypeDirectory};
use super::as_bytes;
use super::{Reply, ReplyRaw, ReplyEmpty, ReplyData};
use super::{Reply, ReplyRaw, ReplyEmpty, ReplyData, ReplyDirectory};

#[test]
fn serialize_empty () {
Expand Down Expand Up @@ -236,4 +274,20 @@ mod test {
});
reply.ok([0xde, 0xad, 0xbe, 0xef]);
}

#[test]
fn reply_directory () {
let mut reply: ReplyDirectory = Reply::new(0xdeadbeef, proc(bytes) {
assert!(bytes == [
&[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00],
&[0xbb, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00 ,0x00, 0x00,
0xdd, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x72, 0x73],
]);
});
reply.add(0xaabb, 1, TypeDirectory, &PosixPath::new("hello"));
reply.add(0xccdd, 2, TypeFile, &PosixPath::new("world.rs"));
reply.ok();
}
}
7 changes: 3 additions & 4 deletions src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ use channel::ChannelSender;
use Filesystem;
use fuse::*;
use fuse::consts::*;
use reply::{Reply, ReplyRaw, ReplyEmpty};
use sendable::DirBuffer;
use reply::{Reply, ReplyRaw, ReplyEmpty, ReplyDirectory};
use session::{MAX_WRITE_SIZE, Session};

/// We generally support async reads, lookups of . and .. and writes larger than 4k
Expand Down Expand Up @@ -72,7 +71,7 @@ impl<'a> Request<'a> {
let opcode: fuse_opcode = match FromPrimitive::from_u32(self.header.opcode) {
Some(op) => op,
None => {
warn!("Ignoring unknown FUSE operation {:u}", self.header.opcode)
warn!("Ignoring unknown FUSE operation {:u}", self.header.opcode);
self.reply::<ReplyEmpty>().error(ENOSYS);
return;
},
Expand Down Expand Up @@ -245,7 +244,7 @@ impl<'a> Request<'a> {
FUSE_READDIR => {
let arg: &fuse_read_in = data.fetch();
debug!("READDIR({:u}) ino {:#018x}, fh {:u}, offset {:u}, size {:u}", self.header.unique, self.header.nodeid, arg.fh, arg.offset, arg.size);
se.filesystem.readdir(self, self.header.nodeid, arg.fh, arg.offset, DirBuffer::new(arg.size as uint), self.reply());
se.filesystem.readdir(self, self.header.nodeid, arg.fh, arg.offset, self.reply::<ReplyDirectory>().sized(arg.size as uint));
},
FUSE_RELEASEDIR => {
let arg: &fuse_release_in = data.fetch();
Expand Down
99 changes: 0 additions & 99 deletions src/sendable.rs

This file was deleted.

0 comments on commit f02b645

Please sign in to comment.