Commit 340517c2 authored by Ivan Krasin's avatar Ivan Krasin

A step to decompose low level details from the FileSystem logic

parent a63a983f
package fuse package fuse
// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io"
"os" "os"
) )
...@@ -14,8 +13,8 @@ const ( ...@@ -14,8 +13,8 @@ const (
) )
type FileSystem interface { type FileSystem interface {
Init(in *InitIn) (out *InitOut, code Error) Init(in *InitIn) (out *InitOut, code Error, err os.Error)
GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error, err os.Error)
} }
var was bool var was bool
...@@ -50,11 +49,11 @@ func loop(f *os.File, fs FileSystem, errors chan os.Error) { ...@@ -50,11 +49,11 @@ func loop(f *os.File, fs FileSystem, errors chan os.Error) {
break break
} }
handle(fs, buf[0:n], toW, errors) dispatch(fs, buf[0:n], toW, errors)
} }
} }
func handle(fs FileSystem, in_data []byte, toW chan [][]byte, errors chan os.Error) { func dispatch(fs FileSystem, in_data []byte, toW chan[][]byte, errors chan os.Error) {
fmt.Printf("in_data: %v\n", in_data) fmt.Printf("in_data: %v\n", in_data)
r := bytes.NewBuffer(in_data) r := bytes.NewBuffer(in_data)
h := new(InHeader) h := new(InHeader)
...@@ -66,62 +65,125 @@ func handle(fs FileSystem, in_data []byte, toW chan [][]byte, errors chan os.Err ...@@ -66,62 +65,125 @@ func handle(fs FileSystem, in_data []byte, toW chan [][]byte, errors chan os.Err
errors <- err errors <- err
return return
} }
var out interface{} var out [][]byte
var result Error = OK
fmt.Printf("Opcode: %v, NodeId: %v, h: %v\n", h.Opcode, h.NodeId, h) fmt.Printf("Opcode: %v, NodeId: %v, h: %v\n", h.Opcode, h.NodeId, h)
switch h.Opcode { switch h.Opcode {
case FUSE_INIT: case FUSE_INIT: out, err = initFuse(fs, h, r)
case FUSE_FORGET: return
case FUSE_GETATTR: out, err = getAttr(fs, h, r)
case FUSE_GETXATTR: out, err = getXAttr(h, r)
case FUSE_OPENDIR: out, err = openDir(h, r)
case FUSE_READDIR: out, err = readDir(h, r)
case FUSE_LOOKUP: out, err = lookup(h, r)
case FUSE_RELEASEDIR: out, err = releaseDir(h, r)
default:
errors <- os.NewError(fmt.Sprintf("Unsupported OpCode: %d", h.Opcode))
out, err = serialize(h, EIO, nil)
}
if err != nil {
errors <- err
out, err = serialize(h, EIO, nil)
}
if out == nil || len(out) == 0 {
fmt.Printf("out is empty\n")
return
}
fmt.Printf("Sending to writer: %v\n", out)
toW <- out
}
func serialize(h *InHeader, res Error, out interface{}) (data [][]byte, err os.Error) {
b := new(bytes.Buffer)
out_data := make([]byte, 0)
fmt.Printf("OpCode: %v result: %v\n", h.Opcode, res)
if out != nil && res == OK {
fmt.Printf("out = %v, out == nil: %v\n", out, out == nil)
err = binary.Write(b, binary.LittleEndian, out)
if err == nil {
out_data = b.Bytes()
} else {
err = os.NewError(fmt.Sprintf("Can serialize out: %v", err))
return
}
}
fmt.Printf("out_data: %v, len(out_data): %d, SizeOfOutHeader: %d\n", out_data, len(out_data), SizeOfOutHeader)
var hout OutHeader
hout.Unique = h.Unique
hout.Error = int32(res)
hout.Length = uint32(len(out_data) + SizeOfOutHeader)
b = new(bytes.Buffer)
err = binary.Write(b, binary.LittleEndian, &hout)
if err != nil {
return
}
_, _ = b.Write(out_data)
data = [][]byte { b.Bytes() }
return
}
func initFuse(fs FileSystem, h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
in := new(InitIn) in := new(InitIn)
err = binary.Read(r, binary.LittleEndian, in) err = binary.Read(r, binary.LittleEndian, in)
if err != nil { if err != nil {
break return
} }
fmt.Printf("in: %v\n", in) fmt.Printf("in: %v\n", in)
var init_out *InitOut var out *InitOut
init_out, result = fs.Init(in) out, res, err := fs.Init(in)
if init_out != nil { if err != nil {
out = init_out return
} }
case FUSE_FORGET: data, err = serialize(h, res, out)
return return
}
case FUSE_GETATTR: func getAttr(fs FileSystem, h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
in := new(GetAttrIn) in := new(GetAttrIn)
err = binary.Read(r, binary.LittleEndian, in) err = binary.Read(r, binary.LittleEndian, in)
if err != nil { if err != nil {
break return
} }
fmt.Printf("FUSE_GETATTR: %v\n", in) fmt.Printf("FUSE_GETATTR: %v\n", in)
var attr_out *AttrOut var out *AttrOut
attr_out, result = fs.GetAttr(h, in) out, res, err := fs.GetAttr(h, in)
if attr_out != nil { if err != nil {
out = attr_out return
} }
case FUSE_GETXATTR: data, err = serialize(h, res, out)
result = OK return
out = new(GetXAttrOut) }
case FUSE_OPENDIR: func getXAttr(h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
out := new(GetXAttrOut)
data, err = serialize(h, OK, out)
return
}
func openDir(h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
in := new(OpenIn) in := new(OpenIn)
err = binary.Read(r, binary.LittleEndian, in) err = binary.Read(r, binary.LittleEndian, in)
if err != nil { if err != nil {
break return
} }
fmt.Printf("FUSE_OPENDIR: %v\n", in) fmt.Printf("FUSE_OPENDIR: %v\n", in)
var open_out *OpenOut out := new(OpenOut)
open_out = new(OpenOut) out.Fh = 1
open_out.Fh = 1
out = open_out
was = false was = false
res := OK
data, err = serialize(h, res, out)
return
}
case FUSE_READDIR: func readDir(h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
if was { if was {
break data, err = serialize(h, OK, nil)
return
} }
in := new(ReadIn) in := new(ReadIn)
err = binary.Read(r, binary.LittleEndian, in) err = binary.Read(r, binary.LittleEndian, in)
if err != nil { if err != nil {
break return
} }
fmt.Printf("FUSE_READDIR: %v\n", in) fmt.Printf("FUSE_READDIR: %v\n", in)
...@@ -138,54 +200,26 @@ func handle(fs FileSystem, in_data []byte, toW chan [][]byte, errors chan os.Err ...@@ -138,54 +200,26 @@ func handle(fs FileSystem, in_data []byte, toW chan [][]byte, errors chan os.Err
} }
buf.Write([]byte("hello12")) buf.Write([]byte("hello12"))
buf.WriteByte(0) buf.WriteByte(0)
out = buf.Bytes() out := buf.Bytes()
was = true was = true
case FUSE_LOOKUP: res := OK
data, err = serialize(h, res, out)
return
}
func lookup(h *InHeader, r *bytes.Buffer) (data [][]byte, err os.Error) {
filename := string(r.Bytes()) filename := string(r.Bytes())
fmt.Printf("filename: %s\n", filename) fmt.Printf("filename: %s\n", filename)
entry_out := new(EntryOut) out := new(EntryOut)
entry_out.NodeId = h.NodeId + 1 out.NodeId = h.NodeId + 1
entry_out.Mode = S_IFDIR out.Mode = S_IFDIR
out = entry_out res := OK
case FUSE_RELEASEDIR: data, err = serialize(h, res, out)
return return
}
default: func releaseDir(h *InHeader, r io.Reader) (data [][]byte, err os.Error) {
errors <- os.NewError(fmt.Sprintf("Unsupported OpCode: %d", h.Opcode)) return
result = EIO
}
if err != nil {
errors <- err
out = nil
result = EIO
// Add sending result msg with error
}
b := new(bytes.Buffer)
out_data := make([]byte, 0)
fmt.Printf("OpCode: %v result: %v\n", h.Opcode, result)
if out != nil && result == OK {
fmt.Printf("out = %v, out == nil: %v\n", out, out == nil)
err = binary.Write(b, binary.LittleEndian, out)
if err == nil {
out_data = b.Bytes()
} else {
errors <- os.NewError(fmt.Sprintf("Can serialize out: %v", err))
}
}
fmt.Printf("out_data: %v, len(out_data): %d, SizeOfOutHeader: %d\n", out_data, len(out_data), SizeOfOutHeader)
var hout OutHeader
hout.Unique = h.Unique
hout.Error = int32(result)
hout.Length = uint32(len(out_data) + SizeOfOutHeader)
b = new(bytes.Buffer)
err = binary.Write(b, binary.LittleEndian, &hout)
if err != nil {
errors <- err
return
}
_, _ = b.Write(out_data)
fmt.Printf("Sending to writer: %v\n", b.Bytes())
toW <- [][]byte{b.Bytes()}
} }
func writer(f *os.File, in chan [][]byte, errors chan os.Error) { func writer(f *os.File, in chan [][]byte, errors chan os.Error) {
......
...@@ -13,7 +13,7 @@ const ( ...@@ -13,7 +13,7 @@ const (
type testFuse struct{} type testFuse struct{}
func (fs *testFuse) Init(in *InitIn) (out *InitOut, code Error) { func (fs *testFuse) Init(in *InitIn) (out *InitOut, code Error, err os.Error) {
if in.Major != FUSE_KERNEL_VERSION { if in.Major != FUSE_KERNEL_VERSION {
fmt.Printf("Major versions does not match. Given %d, want %d\n", in.Major, FUSE_KERNEL_VERSION) fmt.Printf("Major versions does not match. Given %d, want %d\n", in.Major, FUSE_KERNEL_VERSION)
code = EIO code = EIO
...@@ -32,7 +32,7 @@ func (fs *testFuse) Init(in *InitIn) (out *InitOut, code Error) { ...@@ -32,7 +32,7 @@ func (fs *testFuse) Init(in *InitIn) (out *InitOut, code Error) {
return return
} }
func (fs *testFuse) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error) { func (fs *testFuse) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error, err os.Error) {
out = new(AttrOut) out = new(AttrOut)
out.Ino = h.NodeId out.Ino = h.NodeId
out.Mode = S_IFDIR out.Mode = S_IFDIR
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment