Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
919f45da
Commit
919f45da
authored
Apr 22, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use arrays for opcode dispatches; work in progress.
parent
88b3aa85
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
267 additions
and
237 deletions
+267
-237
fuse/fuse.go
fuse/fuse.go
+57
-144
fuse/opcode.go
fuse/opcode.go
+205
-90
fuse/types.go
fuse/types.go
+5
-3
No files found.
fuse/fuse.go
View file @
919f45da
// Code that handles the control loop, and en/decoding messages
// to/from the kernel. Dispatches calls into RawFileSystem.
package
fuse
import
(
...
...
@@ -28,8 +31,9 @@ type request struct {
inputBuf
[]
byte
// These split up inputBuf.
inHeader
*
InHeader
arg
[]
byte
inHeader
*
InHeader
// generic header
inData
unsafe
.
Pointer
// per op data
arg
[]
byte
// flat data.
// Unstructured data, a pointer to the relevant XxxxOut struct.
data
unsafe
.
Pointer
...
...
@@ -46,6 +50,14 @@ type request struct {
preWriteNs
int64
}
func
(
me
*
request
)
filename
()
string
{
return
strings
.
TrimRight
(
string
(
me
.
arg
),
"
\x00
"
)
}
func
(
me
*
request
)
filenames
(
count
int
)
[]
string
{
return
strings
.
Split
(
string
(
me
.
arg
),
"
\x00
"
,
count
)
}
type
MountState
struct
{
// Empty if unmounted.
mountPoint
string
...
...
@@ -261,35 +273,40 @@ func (me *MountState) handle(req *request) {
func
(
me
*
MountState
)
dispatch
(
req
*
request
)
{
h
:=
req
.
inHeader
arg
umentSize
,
ok
:=
inputSizeMap
[
int
(
h
.
Opcode
)]
arg
Size
,
ok
:=
inputSize
(
h
.
Opcode
)
if
!
ok
{
log
.
Println
(
"Unknown opcode %d (input)"
,
h
.
Opcode
)
req
.
status
=
ENOSYS
return
}
if
len
(
req
.
arg
)
<
argumentSize
{
if
len
(
req
.
arg
)
<
argSize
{
log
.
Println
(
"Short read for %v: %v"
,
h
.
Opcode
,
req
.
arg
)
req
.
status
=
EIO
return
}
var
inData
unsafe
.
Pointer
if
argumentSize
>
0
{
inData
=
unsafe
.
Pointer
(
&
req
.
arg
[
0
])
if
argSize
>
0
{
req
.
inData
=
unsafe
.
Pointer
(
&
req
.
arg
[
0
])
req
.
arg
=
req
.
arg
[
argSize
:
]
}
data
:=
req
.
arg
[
argumentSize
:
]
var
status
Status
=
OK
fs
:=
me
.
fileSystem
f
:=
lookupOperation
(
h
.
Opcode
)
if
f
!=
nil
{
f
(
me
,
req
)
return
}
req
.
status
=
OK
filename
:=
""
// Perhaps a map is faster?
if
h
.
Opcode
==
FUSE_UNLINK
||
h
.
Opcode
==
FUSE_RMDIR
||
h
.
Opcode
==
FUSE_LOOKUP
||
h
.
Opcode
==
FUSE_MKDIR
||
h
.
Opcode
==
FUSE_MKNOD
||
h
.
Opcode
==
FUSE_CREATE
||
h
.
Opcode
==
FUSE_LINK
||
h
.
Opcode
==
FUSE_GETXATTR
||
h
.
Opcode
==
FUSE_MKNOD
||
h
.
Opcode
==
FUSE_LINK
||
h
.
Opcode
==
FUSE_REMOVEXATTR
{
filename
=
strings
.
TrimRight
(
string
(
data
),
"
\x00
"
)
filename
=
strings
.
TrimRight
(
string
(
req
.
arg
),
"
\x00
"
)
}
if
me
.
Debug
{
nm
:=
""
...
...
@@ -297,43 +314,43 @@ func (me *MountState) dispatch(req *request) {
nm
=
"n: '"
+
filename
+
"'"
}
if
h
.
Opcode
==
FUSE_RENAME
{
nm
=
"n: '"
+
string
(
data
)
+
"'"
nm
=
"n: '"
+
string
(
req
.
arg
)
+
"'"
}
log
.
Printf
(
"Dispatch: %v, NodeId: %v %s
\n
"
,
operationName
(
h
.
Opcode
),
h
.
NodeId
,
nm
)
}
// Follow ordering of fuse_lowlevel.h.
var
status
Status
fs
:=
me
.
fileSystem
switch
h
.
Opcode
{
case
FUSE_INIT
:
req
.
data
,
status
=
me
.
init
(
h
,
(
*
InitIn
)(
inData
))
req
.
data
,
status
=
me
.
init
(
h
,
(
*
InitIn
)(
req
.
inData
))
case
FUSE_DESTROY
:
fs
.
Destroy
(
h
,
(
*
InitIn
)(
inData
))
fs
.
Destroy
(
h
,
(
*
InitIn
)(
req
.
inData
))
case
FUSE_LOOKUP
:
lookupOut
,
s
:=
fs
.
Lookup
(
h
,
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
lookupOut
)
case
FUSE_FORGET
:
fs
.
Forget
(
h
,
(
*
ForgetIn
)(
inData
))
fs
.
Forget
(
h
,
(
*
ForgetIn
)(
req
.
inData
))
// If we try to write OK, nil, we will get
// error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
// failed, err: writev: no such file or directory
return
case
FUSE_GETATTR
:
// TODO - if inData.Fh is set, do file.GetAttr
attrOut
,
s
:=
fs
.
GetAttr
(
h
,
(
*
GetAttrIn
)(
inData
))
// TODO - if
req.
inData.Fh is set, do file.GetAttr
attrOut
,
s
:=
fs
.
GetAttr
(
h
,
(
*
GetAttrIn
)(
req
.
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
attrOut
)
case
FUSE_SETATTR
:
req
.
data
,
status
=
doSetattr
(
me
,
h
,
(
*
SetAttrIn
)(
inData
))
case
FUSE_READLINK
:
req
.
flatData
,
status
=
fs
.
Readlink
(
h
)
case
FUSE_MKNOD
:
entryOut
,
s
:=
fs
.
Mknod
(
h
,
(
*
MknodIn
)(
inData
),
filename
)
entryOut
,
s
:=
fs
.
Mknod
(
h
,
(
*
MknodIn
)(
req
.
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_MKDIR
:
entryOut
,
s
:=
fs
.
Mkdir
(
h
,
(
*
MkdirIn
)(
inData
),
filename
)
entryOut
,
s
:=
fs
.
Mkdir
(
h
,
(
*
MkdirIn
)(
req
.
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_UNLINK
:
...
...
@@ -341,7 +358,7 @@ func (me *MountState) dispatch(req *request) {
case
FUSE_RMDIR
:
status
=
fs
.
Rmdir
(
h
,
filename
)
case
FUSE_SYMLINK
:
filenames
:=
strings
.
Split
(
string
(
data
),
"
\x00
"
,
3
)
filenames
:=
req
.
filenames
(
3
)
if
len
(
filenames
)
>=
2
{
entryOut
,
s
:=
fs
.
Symlink
(
h
,
filenames
[
1
],
filenames
[
0
])
status
=
s
...
...
@@ -350,63 +367,48 @@ func (me *MountState) dispatch(req *request) {
status
=
EIO
}
case
FUSE_RENAME
:
filenames
:=
strings
.
Split
(
string
(
data
),
"
\x00
"
,
3
)
filenames
:=
strings
.
Split
(
string
(
req
.
arg
),
"
\x00
"
,
3
)
if
len
(
filenames
)
>=
2
{
status
=
fs
.
Rename
(
h
,
(
*
RenameIn
)(
inData
),
filenames
[
0
],
filenames
[
1
])
status
=
fs
.
Rename
(
h
,
(
*
RenameIn
)(
req
.
inData
),
filenames
[
0
],
filenames
[
1
])
}
else
{
status
=
EIO
}
case
FUSE_LINK
:
entryOut
,
s
:=
fs
.
Link
(
h
,
(
*
LinkIn
)(
inData
),
filename
)
entryOut
,
s
:=
fs
.
Link
(
h
,
(
*
LinkIn
)(
req
.
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_OPEN
:
req
.
data
,
status
=
doOpen
(
me
,
h
,
(
*
OpenIn
)(
inData
))
case
FUSE_READ
:
req
.
flatData
,
status
=
me
.
fileSystem
.
Read
((
*
ReadIn
)(
inData
),
me
.
buffers
)
case
FUSE_WRITE
:
req
.
data
,
status
=
doWrite
(
me
,
h
,
(
*
WriteIn
)(
inData
),
data
)
req
.
flatData
,
status
=
me
.
fileSystem
.
Read
((
*
ReadIn
)(
req
.
inData
),
me
.
buffers
)
case
FUSE_FLUSH
:
status
=
me
.
fileSystem
.
Flush
((
*
FlushIn
)(
inData
))
status
=
me
.
fileSystem
.
Flush
((
*
FlushIn
)(
req
.
inData
))
case
FUSE_RELEASE
:
me
.
fileSystem
.
Release
(
h
,
(
*
ReleaseIn
)(
inData
))
me
.
fileSystem
.
Release
(
h
,
(
*
ReleaseIn
)(
req
.
inData
))
case
FUSE_FSYNC
:
status
=
me
.
fileSystem
.
Fsync
((
*
FsyncIn
)(
inData
))
case
FUSE_OPENDIR
:
req
.
data
,
status
=
doOpenDir
(
me
,
h
,
(
*
OpenIn
)(
inData
))
case
FUSE_READDIR
:
req
.
flatData
,
status
=
doReadDir
(
me
,
h
,
(
*
ReadIn
)(
inData
))
status
=
me
.
fileSystem
.
Fsync
((
*
FsyncIn
)(
req
.
inData
))
case
FUSE_RELEASEDIR
:
me
.
fileSystem
.
ReleaseDir
(
h
,
(
*
ReleaseIn
)(
inData
))
me
.
fileSystem
.
ReleaseDir
(
h
,
(
*
ReleaseIn
)(
req
.
inData
))
case
FUSE_FSYNCDIR
:
status
=
me
.
fileSystem
.
FsyncDir
(
h
,
(
*
FsyncIn
)(
inData
))
status
=
me
.
fileSystem
.
FsyncDir
(
h
,
(
*
FsyncIn
)(
req
.
inData
))
case
FUSE_SETXATTR
:
splits
:=
bytes
.
Split
(
data
,
[]
byte
{
0
},
2
)
status
=
fs
.
SetXAttr
(
h
,
(
*
SetXAttrIn
)(
inData
),
string
(
splits
[
0
]),
splits
[
1
])
case
FUSE_GETXATTR
:
req
.
data
,
req
.
flatData
,
status
=
doGetXAttr
(
me
,
h
,
(
*
GetXAttrIn
)(
inData
),
filename
,
h
.
Opcode
)
case
FUSE_LISTXATTR
:
req
.
data
,
req
.
flatData
,
status
=
doGetXAttr
(
me
,
h
,
(
*
GetXAttrIn
)(
inData
),
filename
,
h
.
Opcode
)
splits
:=
bytes
.
Split
(
req
.
arg
,
[]
byte
{
0
},
2
)
status
=
fs
.
SetXAttr
(
h
,
(
*
SetXAttrIn
)(
req
.
inData
),
string
(
splits
[
0
]),
splits
[
1
])
case
FUSE_REMOVEXATTR
:
status
=
fs
.
RemoveXAttr
(
h
,
filename
)
case
FUSE_ACCESS
:
status
=
fs
.
Access
(
h
,
(
*
AccessIn
)(
inData
))
case
FUSE_CREATE
:
req
.
data
,
status
=
doCreate
(
me
,
h
,
(
*
CreateIn
)(
inData
),
filename
)
status
=
fs
.
Access
(
h
,
(
*
AccessIn
)(
req
.
inData
))
// TODO - implement file locking.
// case FUSE_SETLK
// case FUSE_SETLKW
case
FUSE_BMAP
:
bmapOut
,
s
:=
fs
.
Bmap
(
h
,
(
*
BmapIn
)(
inData
))
bmapOut
,
s
:=
fs
.
Bmap
(
h
,
(
*
BmapIn
)(
req
.
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
bmapOut
)
case
FUSE_IOCTL
:
ioctlOut
,
s
:=
fs
.
Ioctl
(
h
,
(
*
IoctlIn
)(
inData
))
ioctlOut
,
s
:=
fs
.
Ioctl
(
h
,
(
*
IoctlIn
)(
req
.
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
ioctlOut
)
case
FUSE_POLL
:
pollOut
,
s
:=
fs
.
Poll
(
h
,
(
*
PollIn
)(
inData
))
pollOut
,
s
:=
fs
.
Poll
(
h
,
(
*
PollIn
)(
req
.
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
pollOut
)
...
...
@@ -428,7 +430,7 @@ func asSlice(ptr unsafe.Pointer, byteCount int) []byte {
}
func
serialize
(
req
*
request
,
debug
bool
)
{
dataLength
,
ok
:=
outputSize
Map
[
int
(
req
.
inHeader
.
Opcode
)]
dataLength
,
ok
:=
outputSize
(
req
.
inHeader
.
Opcode
)
if
!
ok
{
log
.
Println
(
"Unknown opcode %d (output)"
,
req
.
inHeader
.
Opcode
)
req
.
status
=
ENOSYS
...
...
@@ -487,92 +489,3 @@ func (me *MountState) init(h *InHeader, input *InitIn) (unsafe.Pointer, Status)
return
unsafe
.
Pointer
(
out
),
OK
}
////////////////////////////////////////////////////////////////
// Handling files.
func
doOpen
(
state
*
MountState
,
header
*
InHeader
,
input
*
OpenIn
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
Open
(
header
,
input
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
OpenOut
)
out
.
Fh
=
handle
out
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doCreate
(
state
*
MountState
,
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
entry
,
status
:=
state
.
fileSystem
.
Create
(
header
,
input
,
name
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
CreateOut
)
out
.
Entry
=
*
entry
out
.
Open
.
Fh
=
handle
out
.
Open
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doWrite
(
state
*
MountState
,
header
*
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
out
unsafe
.
Pointer
,
code
Status
)
{
n
,
status
:=
state
.
fileSystem
.
Write
(
input
,
data
)
o
:=
&
WriteOut
{
Size
:
n
,
}
return
unsafe
.
Pointer
(
o
),
status
}
func
doSetattr
(
state
*
MountState
,
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
unsafe
.
Pointer
,
code
Status
)
{
// TODO - if Fh != 0, we should do a FSetAttr instead.
o
,
s
:=
state
.
fileSystem
.
SetAttr
(
header
,
input
)
return
unsafe
.
Pointer
(
o
),
s
}
func
doGetXAttr
(
state
*
MountState
,
header
*
InHeader
,
input
*
GetXAttrIn
,
attr
string
,
opcode
uint32
)
(
out
unsafe
.
Pointer
,
data
[]
byte
,
code
Status
)
{
if
opcode
==
FUSE_GETXATTR
{
data
,
code
=
state
.
fileSystem
.
GetXAttr
(
header
,
attr
)
}
else
{
data
,
code
=
state
.
fileSystem
.
ListXAttr
(
header
)
}
if
code
!=
OK
{
return
nil
,
nil
,
code
}
size
:=
uint32
(
len
(
data
))
if
input
.
Size
==
0
{
out
:=
new
(
GetXAttrOut
)
out
.
Size
=
size
return
unsafe
.
Pointer
(
out
),
nil
,
OK
}
if
size
>
input
.
Size
{
return
nil
,
nil
,
ERANGE
}
return
nil
,
data
,
OK
}
////////////////////////////////////////////////////////////////
// Handling directories
func
doOpenDir
(
state
*
MountState
,
header
*
InHeader
,
input
*
OpenIn
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
OpenDir
(
header
,
input
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
OpenOut
)
out
.
Fh
=
handle
out
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doReadDir
(
state
*
MountState
,
header
*
InHeader
,
input
*
ReadIn
)
(
out
[]
byte
,
code
Status
)
{
entries
,
code
:=
state
.
fileSystem
.
ReadDir
(
header
,
input
)
if
entries
==
nil
{
return
nil
,
code
}
return
entries
.
Bytes
(),
code
}
fuse/opcode.go
View file @
919f45da
...
...
@@ -13,7 +13,7 @@ func (code Status) String() string {
return
fmt
.
Sprintf
(
"%d=%v"
,
int
(
code
),
os
.
Errno
(
code
))
}
func
replyString
(
opcode
uint32
,
ptr
unsafe
.
Pointer
)
string
{
func
replyString
(
opcode
Opcode
,
ptr
unsafe
.
Pointer
)
string
{
var
val
interface
{}
switch
opcode
{
case
FUSE_LOOKUP
:
...
...
@@ -27,95 +27,153 @@ func replyString(opcode uint32, ptr unsafe.Pointer) string {
return
""
}
func
operationName
(
opcode
uint32
)
string
{
switch
opcode
{
case
FUSE_LOOKUP
:
return
"FUSE_LOOKUP"
case
FUSE_FORGET
:
return
"FUSE_FORGET"
case
FUSE_GETATTR
:
return
"FUSE_GETATTR"
case
FUSE_SETATTR
:
return
"FUSE_SETATTR"
case
FUSE_READLINK
:
return
"FUSE_READLINK"
case
FUSE_SYMLINK
:
return
"FUSE_SYMLINK"
case
FUSE_MKNOD
:
return
"FUSE_MKNOD"
case
FUSE_MKDIR
:
return
"FUSE_MKDIR"
case
FUSE_UNLINK
:
return
"FUSE_UNLINK"
case
FUSE_RMDIR
:
return
"FUSE_RMDIR"
case
FUSE_RENAME
:
return
"FUSE_RENAME"
case
FUSE_LINK
:
return
"FUSE_LINK"
case
FUSE_OPEN
:
return
"FUSE_OPEN"
case
FUSE_READ
:
return
"FUSE_READ"
case
FUSE_WRITE
:
return
"FUSE_WRITE"
case
FUSE_STATFS
:
return
"FUSE_STATFS"
case
FUSE_RELEASE
:
return
"FUSE_RELEASE"
case
FUSE_FSYNC
:
return
"FUSE_FSYNC"
case
FUSE_SETXATTR
:
return
"FUSE_SETXATTR"
case
FUSE_GETXATTR
:
return
"FUSE_GETXATTR"
case
FUSE_LISTXATTR
:
return
"FUSE_LISTXATTR"
case
FUSE_REMOVEXATTR
:
return
"FUSE_REMOVEXATTR"
case
FUSE_FLUSH
:
return
"FUSE_FLUSH"
case
FUSE_INIT
:
return
"FUSE_INIT"
case
FUSE_OPENDIR
:
return
"FUSE_OPENDIR"
case
FUSE_READDIR
:
return
"FUSE_READDIR"
case
FUSE_RELEASEDIR
:
return
"FUSE_RELEASEDIR"
case
FUSE_FSYNCDIR
:
return
"FUSE_FSYNCDIR"
case
FUSE_GETLK
:
return
"FUSE_GETLK"
case
FUSE_SETLK
:
return
"FUSE_SETLK"
case
FUSE_SETLKW
:
return
"FUSE_SETLKW"
case
FUSE_ACCESS
:
return
"FUSE_ACCESS"
case
FUSE_CREATE
:
return
"FUSE_CREATE"
case
FUSE_INTERRUPT
:
return
"FUSE_INTERRUPT"
case
FUSE_BMAP
:
return
"FUSE_BMAP"
case
FUSE_DESTROY
:
return
"FUSE_DESTROY"
case
FUSE_IOCTL
:
return
"FUSE_IOCTL"
case
FUSE_POLL
:
return
"FUSE_POLL"
}
return
"UNKNOWN"
}
var
inputSizeMap
map
[
int
]
int
var
outputSizeMap
map
[
int
]
int
////////////////////////////////////////////////////////////////
func
doOpen
(
state
*
MountState
,
req
*
request
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
Open
(
req
.
inHeader
,
(
*
OpenIn
)(
req
.
inData
))
req
.
status
=
status
if
status
!=
OK
{
return
}
out
:=
&
OpenOut
{
Fh
:
handle
,
OpenFlags
:
flags
,
}
req
.
data
=
unsafe
.
Pointer
(
out
)
}
func
doCreate
(
state
*
MountState
,
req
*
request
)
{
flags
,
handle
,
entry
,
status
:=
state
.
fileSystem
.
Create
(
req
.
inHeader
,
(
*
CreateIn
)(
req
.
inData
),
req
.
filename
())
req
.
status
=
status
if
status
==
OK
{
req
.
data
=
unsafe
.
Pointer
(
&
CreateOut
{
EntryOut
:
*
entry
,
OpenOut
:
OpenOut
{
Fh
:
handle
,
OpenFlags
:
flags
,
},
})
}
}
func
doReadDir
(
state
*
MountState
,
req
*
request
)
{
entries
,
code
:=
state
.
fileSystem
.
ReadDir
(
req
.
inHeader
,
(
*
ReadIn
)(
req
.
inData
))
if
entries
!=
nil
{
req
.
flatData
=
entries
.
Bytes
()
}
req
.
status
=
code
}
func
doOpenDir
(
state
*
MountState
,
req
*
request
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
OpenDir
(
req
.
inHeader
,
(
*
OpenIn
)(
req
.
inData
))
req
.
status
=
status
if
status
==
OK
{
req
.
data
=
unsafe
.
Pointer
(
&
OpenOut
{
Fh
:
handle
,
OpenFlags
:
flags
,
})
}
}
func
doSetattr
(
state
*
MountState
,
req
*
request
)
{
// TODO - if Fh != 0, we should do a FSetAttr instead.
o
,
s
:=
state
.
fileSystem
.
SetAttr
(
req
.
inHeader
,
(
*
SetAttrIn
)(
req
.
inData
))
req
.
data
=
unsafe
.
Pointer
(
o
)
req
.
status
=
s
}
func
doWrite
(
state
*
MountState
,
req
*
request
)
{
n
,
status
:=
state
.
fileSystem
.
Write
((
*
WriteIn
)(
req
.
inData
),
req
.
arg
)
o
:=
&
WriteOut
{
Size
:
n
,
}
req
.
data
=
unsafe
.
Pointer
(
o
)
req
.
status
=
status
}
func
doGetXAttr
(
state
*
MountState
,
req
*
request
)
{
input
:=
(
*
GetXAttrIn
)(
req
.
inData
)
var
data
[]
byte
if
req
.
inHeader
.
Opcode
==
FUSE_GETXATTR
{
data
,
req
.
status
=
state
.
fileSystem
.
GetXAttr
(
req
.
inHeader
,
req
.
filename
())
}
else
{
data
,
req
.
status
=
state
.
fileSystem
.
ListXAttr
(
req
.
inHeader
)
}
if
req
.
status
!=
OK
{
return
}
size
:=
uint32
(
len
(
data
))
if
input
.
Size
==
0
{
out
:=
&
GetXAttrOut
{
Size
:
size
,
}
req
.
data
=
unsafe
.
Pointer
(
out
)
}
if
size
>
input
.
Size
{
req
.
status
=
ERANGE
}
req
.
flatData
=
data
}
////////////////////////////////////////////////////////////////
var
operationNames
[]
string
var
inputSizeMap
[]
int
var
outputSizeMap
[]
int
type
operation
func
(
*
MountState
,
*
request
)
var
operationFuncs
[]
operation
func
operationName
(
opcode
Opcode
)
string
{
if
opcode
>
OPCODE_COUNT
{
return
"unknown"
}
return
operationNames
[
opcode
]
}
func
inputSize
(
o
Opcode
)
(
int
,
bool
)
{
return
lookupSize
(
o
,
inputSizeMap
)
}
func
outputSize
(
o
Opcode
)
(
int
,
bool
)
{
return
lookupSize
(
o
,
outputSizeMap
)
}
func
lookupSize
(
o
Opcode
,
sMap
[]
int
)
(
int
,
bool
)
{
if
o
>=
OPCODE_COUNT
{
return
-
1
,
false
}
return
sMap
[
int
(
o
)],
true
}
func
lookupOperation
(
o
Opcode
)
operation
{
return
operationFuncs
[
o
]
}
func
makeSizeMap
(
dict
map
[
int
]
int
)
[]
int
{
out
:=
make
([]
int
,
OPCODE_COUNT
)
for
i
,
_
:=
range
out
{
out
[
i
]
=
-
1
}
for
code
,
val
:=
range
dict
{
out
[
code
]
=
val
}
return
out
}
func
init
()
{
inputSizeMap
=
map
[
int
]
int
{
inputSizeMap
=
ma
keSizeMap
(
ma
p
[
int
]
int
{
FUSE_LOOKUP
:
0
,
FUSE_FORGET
:
unsafe
.
Sizeof
(
ForgetIn
{}),
FUSE_GETATTR
:
unsafe
.
Sizeof
(
GetAttrIn
{}),
...
...
@@ -154,9 +212,9 @@ func init() {
FUSE_DESTROY
:
0
,
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlIn
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollIn
{}),
}
}
)
outputSizeMap
=
map
[
int
]
int
{
outputSizeMap
=
ma
keSizeMap
(
ma
p
[
int
]
int
{
FUSE_LOOKUP
:
unsafe
.
Sizeof
(
EntryOut
{}),
FUSE_FORGET
:
0
,
FUSE_GETATTR
:
unsafe
.
Sizeof
(
AttrOut
{}),
...
...
@@ -196,5 +254,62 @@ func init() {
FUSE_DESTROY
:
0
,
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlOut
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollOut
{}),
})
operationNames
=
make
([]
string
,
OPCODE_COUNT
)
for
k
,
v
:=
range
map
[
int
]
string
{
FUSE_LOOKUP
:
"FUSE_LOOKUP"
,
FUSE_FORGET
:
"FUSE_FORGET"
,
FUSE_GETATTR
:
"FUSE_GETATTR"
,
FUSE_SETATTR
:
"FUSE_SETATTR"
,
FUSE_READLINK
:
"FUSE_READLINK"
,
FUSE_SYMLINK
:
"FUSE_SYMLINK"
,
FUSE_MKNOD
:
"FUSE_MKNOD"
,
FUSE_MKDIR
:
"FUSE_MKDIR"
,
FUSE_UNLINK
:
"FUSE_UNLINK"
,
FUSE_RMDIR
:
"FUSE_RMDIR"
,
FUSE_RENAME
:
"FUSE_RENAME"
,
FUSE_LINK
:
"FUSE_LINK"
,
FUSE_OPEN
:
"FUSE_OPEN"
,
FUSE_READ
:
"FUSE_READ"
,
FUSE_WRITE
:
"FUSE_WRITE"
,
FUSE_STATFS
:
"FUSE_STATFS"
,
FUSE_RELEASE
:
"FUSE_RELEASE"
,
FUSE_FSYNC
:
"FUSE_FSYNC"
,
FUSE_SETXATTR
:
"FUSE_SETXATTR"
,
FUSE_GETXATTR
:
"FUSE_GETXATTR"
,
FUSE_LISTXATTR
:
"FUSE_LISTXATTR"
,
FUSE_REMOVEXATTR
:
"FUSE_REMOVEXATTR"
,
FUSE_FLUSH
:
"FUSE_FLUSH"
,
FUSE_INIT
:
"FUSE_INIT"
,
FUSE_OPENDIR
:
"FUSE_OPENDIR"
,
FUSE_READDIR
:
"FUSE_READDIR"
,
FUSE_RELEASEDIR
:
"FUSE_RELEASEDIR"
,
FUSE_FSYNCDIR
:
"FUSE_FSYNCDIR"
,
FUSE_GETLK
:
"FUSE_GETLK"
,
FUSE_SETLK
:
"FUSE_SETLK"
,
FUSE_SETLKW
:
"FUSE_SETLKW"
,
FUSE_ACCESS
:
"FUSE_ACCESS"
,
FUSE_CREATE
:
"FUSE_CREATE"
,
FUSE_INTERRUPT
:
"FUSE_INTERRUPT"
,
FUSE_BMAP
:
"FUSE_BMAP"
,
FUSE_DESTROY
:
"FUSE_DESTROY"
,
FUSE_IOCTL
:
"FUSE_IOCTL"
,
FUSE_POLL
:
"FUSE_POLL"
}
{
operationNames
[
k
]
=
v
}
operationFuncs
=
make
([]
operation
,
OPCODE_COUNT
)
for
k
,
v
:=
range
map
[
Opcode
]
operation
{
FUSE_OPEN
:
doOpen
,
FUSE_READDIR
:
doReadDir
,
FUSE_WRITE
:
doWrite
,
FUSE_OPENDIR
:
doOpenDir
,
FUSE_CREATE
:
doCreate
,
FUSE_SETATTR
:
doSetattr
,
FUSE_GETXATTR
:
doGetXAttr
,
FUSE_LISTXATTR
:
doGetXAttr
,
}
{
operationFuncs
[
k
]
=
v
}
}
fuse/types.go
View file @
919f45da
...
...
@@ -143,6 +143,8 @@ const (
FUSE_IOCTL
=
39
FUSE_POLL
=
40
OPCODE_COUNT
=
41
CUSE_INIT
=
4096
)
...
...
@@ -287,8 +289,8 @@ type OpenOut struct {
}
type
CreateOut
struct
{
Entry
Entry
Out
Open
Open
Out
EntryOut
OpenOut
}
type
ReleaseIn
struct
{
...
...
@@ -456,7 +458,7 @@ type NotifyPollWakeupOut struct {
type
InHeader
struct
{
Length
uint32
Opcode
uint32
Opcode
Unique
uint64
NodeId
uint64
Identity
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment