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
1f1c157d
Commit
1f1c157d
authored
Jan 25, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow different PathFilesystems to be mounted within directories of
PathFileSystemConnector file system.
parent
9d51ae3f
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
297 additions
and
85 deletions
+297
-85
.gitignore
.gitignore
+1
-0
example/main.go
example/main.go
+3
-3
examplelib/Makefile
examplelib/Makefile
+2
-1
examplelib/dummyfuse.go
examplelib/dummyfuse.go
+3
-6
examplelib/misc.go
examplelib/misc.go
+20
-0
examplelib/passthrough.go
examplelib/passthrough.go
+3
-3
examplelib/passthrough_test.go
examplelib/passthrough_test.go
+47
-21
examplelib/stackfs_test.go
examplelib/stackfs_test.go
+1
-1
fuse/direntry.go
fuse/direntry.go
+1
-1
fuse/misc.go
fuse/misc.go
+4
-0
fuse/pathfilesystem.go
fuse/pathfilesystem.go
+207
-45
fuse/types.go
fuse/types.go
+5
-4
No files found.
.gitignore
View file @
1f1c157d
*~
*~
*.6
*.6
8.out
.nfs*
.nfs*
_*
_*
example/main.go
View file @
1f1c157d
...
@@ -21,9 +21,9 @@ func main() {
...
@@ -21,9 +21,9 @@ func main() {
}
}
orig
:=
flag
.
Arg
(
0
)
orig
:=
flag
.
Arg
(
0
)
pt
:=
examplelib
.
NewPassThroughFuse
(
orig
)
fs
:=
examplelib
.
NewPassThroughFuse
(
orig
)
fs
:=
fuse
.
NewPathFileSystemConnector
(
pt
)
conn
:=
fuse
.
NewPathFileSystemConnector
(
fs
)
state
:=
fuse
.
NewMountState
(
fs
)
state
:=
fuse
.
NewMountState
(
conn
)
state
.
Debug
=
*
debug
state
.
Debug
=
*
debug
mountPoint
:=
flag
.
Arg
(
1
)
mountPoint
:=
flag
.
Arg
(
1
)
...
...
examplelib/Makefile
View file @
1f1c157d
...
@@ -7,7 +7,8 @@ DEPS=../fuse
...
@@ -7,7 +7,8 @@ DEPS=../fuse
GOFILES
=
dummyfuse.go
\
GOFILES
=
dummyfuse.go
\
passthrough.go
\
passthrough.go
\
stackfs.go
stackfs.go
\
misc.go
include
$(GOROOT)/src/Make.pkg
include
$(GOROOT)/src/Make.pkg
examplelib/dummyfuse.go
View file @
1f1c157d
...
@@ -194,11 +194,11 @@ func (self *DummyPathFuse) OpenDir(name string) (dir fuse.RawFuseDir, code fuse.
...
@@ -194,11 +194,11 @@ func (self *DummyPathFuse) OpenDir(name string) (dir fuse.RawFuseDir, code fuse.
return
nil
,
fuse
.
ENOSYS
return
nil
,
fuse
.
ENOSYS
}
}
func
(
self
*
DummyPathFuse
)
Init
()
(
*
fuse
.
InitOut
,
fuse
.
Status
)
{
func
(
self
*
DummyPathFuse
)
Mount
(
conn
*
fuse
.
PathFileSystemConnector
)
(
fuse
.
Status
)
{
return
nil
,
fuse
.
ENOSYS
return
fuse
.
OK
}
}
func
(
self
*
DummyPathFuse
)
Destroy
()
{
func
(
self
*
DummyPathFuse
)
Unmount
()
{
}
}
func
(
self
*
DummyPathFuse
)
Access
(
name
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
func
(
self
*
DummyPathFuse
)
Access
(
name
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
...
@@ -213,6 +213,3 @@ func (self *DummyPathFuse) Utimens(name string, AtimeNs uint64, CtimeNs uint64)
...
@@ -213,6 +213,3 @@ func (self *DummyPathFuse) Utimens(name string, AtimeNs uint64, CtimeNs uint64)
return
fuse
.
ENOSYS
return
fuse
.
ENOSYS
}
}
func
(
self
*
DummyPathFuse
)
SetOptions
(
*
fuse
.
PathFileSystemConnectorOptions
)
{
}
examplelib/misc.go
0 → 100644
View file @
1f1c157d
package
examplelib
import
"os"
////////////////
func
IsDir
(
name
string
)
bool
{
fi
,
_
:=
os
.
Lstat
(
name
)
return
fi
!=
nil
&&
fi
.
IsDirectory
()
}
func
IsFile
(
name
string
)
bool
{
fi
,
_
:=
os
.
Lstat
(
name
)
return
fi
!=
nil
&&
fi
.
IsRegular
()
}
func
FileExists
(
name
string
)
bool
{
_
,
err
:=
os
.
Lstat
(
name
)
return
err
==
nil
}
examplelib/passthrough.go
View file @
1f1c157d
...
@@ -25,11 +25,11 @@ func NewPassThroughFuse(root string) (out *PassThroughFuse) {
...
@@ -25,11 +25,11 @@ func NewPassThroughFuse(root string) (out *PassThroughFuse) {
return
out
return
out
}
}
func
(
self
*
PassThroughFuse
)
Init
()
(
*
fuse
.
InitOut
,
fuse
.
Status
)
{
func
(
self
*
PassThroughFuse
)
Mount
(
conn
*
fuse
.
PathFileSystemConnector
)
(
fuse
.
Status
)
{
return
new
(
fuse
.
InitOut
),
fuse
.
OK
return
fuse
.
OK
}
}
func
(
self
*
PassThroughFuse
)
Destroy
()
{
func
(
self
*
PassThroughFuse
)
Unmount
()
{
}
}
...
...
examplelib/passthrough_test.go
View file @
1f1c157d
...
@@ -16,23 +16,6 @@ import (
...
@@ -16,23 +16,6 @@ import (
var
_
=
strings
.
Join
var
_
=
strings
.
Join
var
_
=
log
.
Println
var
_
=
log
.
Println
////////////////
func
IsDir
(
name
string
)
bool
{
fi
,
_
:=
os
.
Lstat
(
name
)
return
fi
!=
nil
&&
fi
.
IsDirectory
()
}
func
IsFile
(
name
string
)
bool
{
fi
,
_
:=
os
.
Lstat
(
name
)
return
fi
!=
nil
&&
fi
.
IsRegular
()
}
func
FileExists
(
name
string
)
bool
{
_
,
err
:=
os
.
Lstat
(
name
)
return
err
==
nil
}
////////////////
////////////////
// state for our testcase, mostly constants
// state for our testcase, mostly constants
...
@@ -50,6 +33,7 @@ type testCase struct {
...
@@ -50,6 +33,7 @@ type testCase struct {
origSubfile
string
origSubfile
string
tester
*
testing
.
T
tester
*
testing
.
T
state
*
fuse
.
MountState
state
*
fuse
.
MountState
connector
*
fuse
.
PathFileSystemConnector
}
}
// Create and mount filesystem.
// Create and mount filesystem.
...
@@ -69,9 +53,10 @@ func (self *testCase) Setup(t *testing.T) {
...
@@ -69,9 +53,10 @@ func (self *testCase) Setup(t *testing.T) {
self
.
origSubdir
=
path
.
Join
(
self
.
origDir
,
subdir
)
self
.
origSubdir
=
path
.
Join
(
self
.
origDir
,
subdir
)
self
.
origSubfile
=
path
.
Join
(
self
.
origSubdir
,
"subfile"
)
self
.
origSubfile
=
path
.
Join
(
self
.
origSubdir
,
"subfile"
)
fs
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
self
.
origDir
))
pfs
:=
NewPassThroughFuse
(
self
.
origDir
)
self
.
connector
=
fuse
.
NewPathFileSystemConnector
(
pfs
)
self
.
state
=
fuse
.
NewMountState
(
fs
)
self
.
connector
.
Debug
=
true
self
.
state
=
fuse
.
NewMountState
(
self
.
connector
)
self
.
state
.
Mount
(
self
.
mountPoint
)
self
.
state
.
Mount
(
self
.
mountPoint
)
//self.state.Debug = false
//self.state.Debug = false
...
@@ -610,3 +595,44 @@ func TestMount(t *testing.T) {
...
@@ -610,3 +595,44 @@ func TestMount(t *testing.T) {
ts
.
testLargeDirRead
()
ts
.
testLargeDirRead
()
ts
.
Cleanup
()
ts
.
Cleanup
()
}
}
func
TestRecursiveMount
(
t
*
testing
.
T
)
{
ts
:=
new
(
testCase
)
ts
.
Setup
(
t
)
f
,
err
:=
os
.
Open
(
path
.
Join
(
ts
.
mountPoint
,
"hello.txt"
),
os
.
O_WRONLY
|
os
.
O_CREATE
,
0777
)
if
err
!=
nil
{
t
.
Errorf
(
"open write err %v"
,
err
)
}
f
.
WriteString
(
"bla"
)
f
.
Close
()
pfs2
:=
NewPassThroughFuse
(
ts
.
origDir
)
code
:=
ts
.
connector
.
Mount
(
"/hello.txt"
,
pfs2
)
if
code
!=
fuse
.
EINVAL
{
t
.
Error
(
"expect EINVAL"
,
code
)
}
submnt
:=
path
.
Join
(
ts
.
mountPoint
,
"mnt"
)
err
=
os
.
Mkdir
(
submnt
,
0777
)
if
err
!=
nil
{
t
.
Errorf
(
"mkdir"
)
}
code
=
ts
.
connector
.
Mount
(
"/mnt"
,
pfs2
)
if
code
!=
fuse
.
OK
{
t
.
Errorf
(
"mkdir"
)
}
_
,
err
=
os
.
Lstat
(
submnt
)
if
err
!=
nil
{
t
.
Error
(
"lstat submount"
,
err
)
}
_
,
err
=
os
.
Lstat
(
path
.
Join
(
submnt
,
"hello.txt"
))
if
err
!=
nil
{
t
.
Error
(
"lstat submount/file"
,
err
)
}
ts
.
Cleanup
()
}
examplelib/stackfs_test.go
View file @
1f1c157d
fuse/direntry.go
View file @
1f1c157d
...
@@ -31,7 +31,7 @@ func (de *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool {
...
@@ -31,7 +31,7 @@ func (de *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool {
dirent
.
Off
=
de
.
offset
dirent
.
Off
=
de
.
offset
dirent
.
Ino
=
inode
dirent
.
Ino
=
inode
dirent
.
NameLen
=
uint32
(
len
(
name
))
dirent
.
NameLen
=
uint32
(
len
(
name
))
dirent
.
Typ
=
(
mode
&
0170000
)
>>
12
dirent
.
Typ
=
ModeToType
(
mode
)
err
:=
binary
.
Write
(
&
de
.
buf
,
binary
.
LittleEndian
,
dirent
)
err
:=
binary
.
Write
(
&
de
.
buf
,
binary
.
LittleEndian
,
dirent
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
fuse/misc.go
View file @
1f1c157d
...
@@ -291,3 +291,7 @@ func NegativeEntry(time float64) *EntryOut {
...
@@ -291,3 +291,7 @@ func NegativeEntry(time float64) *EntryOut {
SplitNs
(
time
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
time
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
return
out
return
out
}
}
func
ModeToType
(
mode
uint32
)
uint32
{
return
(
mode
&
0170000
)
>>
12
}
fuse/pathfilesystem.go
View file @
1f1c157d
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"bytes"
"bytes"
"sync"
"sync"
"fmt"
"fmt"
"log"
"path"
"path"
"strings"
"strings"
)
)
...
@@ -15,8 +16,15 @@ type inodeData struct {
...
@@ -15,8 +16,15 @@ type inodeData struct {
Name
string
Name
string
LookupCount
int
LookupCount
int
Type
uint32
// Number of inodeData that have this as parent.
// Number of inodeData that have this as parent.
RefCount
int
RefCount
int
// If non-nil the file system mounted here.
Mounted
PathFilesystem
// If yes, we are looking to unmount the mounted fs.
unmountPending
bool
}
}
// Should implement some hash table method instead?
// Should implement some hash table method instead?
...
@@ -33,18 +41,22 @@ func (self *inodeData) Key() string {
...
@@ -33,18 +41,22 @@ func (self *inodeData) Key() string {
return
inodeDataKey
(
p
,
self
.
Name
)
return
inodeDataKey
(
p
,
self
.
Name
)
}
}
func
(
self
*
inodeData
)
GetPath
()
string
{
func
(
self
*
inodeData
)
GetPath
()
(
path
string
,
fs
PathFilesystem
)
{
// TODO - softcode this.
// TODO - softcode this.
var
components
[
100
]
string
var
components
[
100
]
string
j
:=
len
(
components
)
j
:=
len
(
components
)
for
p
:=
self
;
p
!=
nil
&&
p
.
NodeId
!=
FUSE_ROOT_ID
;
p
=
p
.
Parent
{
inode
:=
self
for
;
inode
!=
nil
&&
inode
.
Mounted
==
nil
;
inode
=
inode
.
Parent
{
j
--
j
--
components
[
j
]
=
p
.
Name
components
[
j
]
=
inode
.
Name
}
}
fullPath
:=
strings
.
Join
(
components
[
j
:
],
"/"
)
fullPath
:=
strings
.
Join
(
components
[
j
:
],
"/"
)
return
fullPath
if
!
inode
.
unmountPending
{
fs
=
inode
.
Mounted
}
return
fullPath
,
fs
}
}
type
TimeoutOptions
struct
{
type
TimeoutOptions
struct
{
...
@@ -66,8 +78,6 @@ type PathFileSystemConnectorOptions struct {
...
@@ -66,8 +78,6 @@ type PathFileSystemConnectorOptions struct {
}
}
type
PathFileSystemConnector
struct
{
type
PathFileSystemConnector
struct
{
fileSystem
PathFilesystem
// Protects the hashmap, its contents and the nextFreeInode counter.
// Protects the hashmap, its contents and the nextFreeInode counter.
lock
sync
.
RWMutex
lock
sync
.
RWMutex
...
@@ -86,6 +96,7 @@ type PathFileSystemConnector struct {
...
@@ -86,6 +96,7 @@ type PathFileSystemConnector struct {
nextFreeInode
uint64
nextFreeInode
uint64
options
PathFileSystemConnectorOptions
options
PathFileSystemConnectorOptions
Debug
bool
}
}
// Must be called with lock held.
// Must be called with lock held.
...
@@ -156,7 +167,7 @@ func (self *PathFileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int
...
@@ -156,7 +167,7 @@ func (self *PathFileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int
data
,
ok
:=
self
.
inodePathMapByInode
[
nodeId
]
data
,
ok
:=
self
.
inodePathMapByInode
[
nodeId
]
if
ok
{
if
ok
{
data
.
LookupCount
-=
forgetCount
data
.
LookupCount
-=
forgetCount
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
{
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
Mounted
==
nil
||
data
.
unmountPending
)
{
self
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
self
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
}
}
}
}
...
@@ -219,6 +230,29 @@ func (self *PathFileSystemConnector) unlinkUpdate(nodeid uint64, name string) {
...
@@ -219,6 +230,29 @@ func (self *PathFileSystemConnector) unlinkUpdate(nodeid uint64, name string) {
}
}
}
}
// Walk the file system starting from the root.
func
(
self
*
PathFileSystemConnector
)
findInode
(
fullPath
string
)
*
inodeData
{
fullPath
=
strings
.
TrimLeft
(
path
.
Clean
(
fullPath
),
"/"
)
comps
:=
strings
.
Split
(
fullPath
,
"/"
,
-
1
)
self
.
lock
.
RLock
()
defer
self
.
lock
.
RUnlock
()
node
:=
self
.
inodePathMapByInode
[
FUSE_ROOT_ID
]
for
i
,
component
:=
range
(
comps
)
{
if
len
(
component
)
==
0
{
continue
}
key
:=
inodeDataKey
(
node
.
NodeId
,
component
)
node
=
self
.
inodePathMap
[
key
]
if
node
==
nil
{
panic
(
fmt
.
Sprintf
(
"findInode: %v %v"
,
i
,
fullPath
))
}
}
return
node
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Below routines should not access inodePathMap(ByInode) directly,
// Below routines should not access inodePathMap(ByInode) directly,
// and there need no locking.
// and there need no locking.
...
@@ -227,10 +261,10 @@ func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector
...
@@ -227,10 +261,10 @@ func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector
out
=
new
(
PathFileSystemConnector
)
out
=
new
(
PathFileSystemConnector
)
out
.
inodePathMap
=
make
(
map
[
string
]
*
inodeData
)
out
.
inodePathMap
=
make
(
map
[
string
]
*
inodeData
)
out
.
inodePathMapByInode
=
make
(
map
[
uint64
]
*
inodeData
)
out
.
inodePathMapByInode
=
make
(
map
[
uint64
]
*
inodeData
)
out
.
fileSystem
=
fs
rootData
:=
new
(
inodeData
)
rootData
:=
new
(
inodeData
)
rootData
.
NodeId
=
FUSE_ROOT_ID
rootData
.
NodeId
=
FUSE_ROOT_ID
rootData
.
Type
=
ModeToType
(
S_IFDIR
)
out
.
inodePathMap
[
rootData
.
Key
()]
=
rootData
out
.
inodePathMap
[
rootData
.
Key
()]
=
rootData
out
.
inodePathMapByInode
[
FUSE_ROOT_ID
]
=
rootData
out
.
inodePathMapByInode
[
FUSE_ROOT_ID
]
=
rootData
...
@@ -240,21 +274,79 @@ func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector
...
@@ -240,21 +274,79 @@ func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector
out
.
options
.
AttrTimeout
=
1.0
out
.
options
.
AttrTimeout
=
1.0
out
.
options
.
EntryTimeout
=
1.0
out
.
options
.
EntryTimeout
=
1.0
fs
.
SetOptions
(
&
out
.
options
)
if
code
:=
out
.
Mount
(
"/"
,
fs
);
code
!=
OK
{
panic
(
"root mount failed."
)
}
return
out
return
out
}
}
func
(
self
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
string
{
func
(
self
*
PathFileSystemConnector
)
SetOptions
(
opts
PathFileSystemConnectorOptions
)
{
self
.
options
=
opts
}
func
(
self
*
PathFileSystemConnector
)
Mount
(
path
string
,
fs
PathFilesystem
)
Status
{
node
:=
self
.
findInode
(
path
)
// TODO - check that fs was not mounted elsewhere.
if
node
.
RefCount
>
0
{
return
EBUSY
}
if
node
.
Type
&
ModeToType
(
S_IFDIR
)
==
0
{
return
EINVAL
}
code
:=
fs
.
Mount
(
self
)
if
code
!=
OK
{
if
self
.
Debug
{
log
.
Println
(
"Mount error: "
,
path
,
code
)
}
return
code
}
if
self
.
Debug
{
log
.
Println
(
"Mount: "
,
fs
,
"on"
,
path
,
node
)
}
// TODO - this is technically a race-condition.
node
.
Mounted
=
fs
node
.
unmountPending
=
false
return
OK
}
func
(
self
*
PathFileSystemConnector
)
Unmount
(
path
string
)
Status
{
node
:=
self
.
findInode
(
path
)
if
node
==
nil
||
node
.
Mounted
==
nil
{
panic
(
path
)
}
// TODO - check if we have open files.
if
self
.
Debug
{
log
.
Println
(
"Unmount: "
,
node
)
}
// node manipulations are racy?
if
node
.
RefCount
>
0
{
node
.
Mounted
.
Unmount
()
node
.
unmountPending
=
true
}
else
{
node
.
Mounted
=
nil
}
return
OK
}
func
(
self
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
fs
PathFilesystem
)
{
return
self
.
getInodeData
(
nodeid
)
.
GetPath
()
return
self
.
getInodeData
(
nodeid
)
.
GetPath
()
}
}
func
(
self
*
PathFileSystemConnector
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
return
self
.
fileSystem
.
Init
()
// TODO ?
return
new
(
InitOut
),
OK
}
}
func
(
self
*
PathFileSystemConnector
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
func
(
self
*
PathFileSystemConnector
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
self
.
fileSystem
.
Destroy
()
// TODO - umount all.
}
}
func
(
self
*
PathFileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
...
@@ -263,8 +355,14 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
...
@@ -263,8 +355,14 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
// TODO - fuse.c has special case code for name == "." and
// TODO - fuse.c has special case code for name == "." and
// "..", those lookups happen if FUSE_EXPORT_SUPPORT is set in
// "..", those lookups happen if FUSE_EXPORT_SUPPORT is set in
// Init.
// Init.
fullPath
:=
path
.
Join
(
parent
.
GetPath
(),
name
)
fullPath
,
fs
:=
parent
.
GetPath
()
attr
,
err
:=
self
.
fileSystem
.
GetAttr
(
fullPath
)
if
fs
==
nil
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
}
fullPath
=
path
.
Join
(
fullPath
,
name
)
attr
,
err
:=
fs
.
GetAttr
(
fullPath
)
if
err
==
ENOENT
&&
self
.
options
.
NegativeTimeout
>
0.0
{
if
err
==
ENOENT
&&
self
.
options
.
NegativeTimeout
>
0.0
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
}
}
...
@@ -274,6 +372,7 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
...
@@ -274,6 +372,7 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
}
}
data
:=
self
.
lookupUpdate
(
header
.
NodeId
,
name
)
data
:=
self
.
lookupUpdate
(
header
.
NodeId
,
name
)
data
.
Type
=
ModeToType
(
attr
.
Mode
)
out
=
new
(
EntryOut
)
out
=
new
(
EntryOut
)
out
.
NodeId
=
data
.
NodeId
out
.
NodeId
=
data
.
NodeId
...
@@ -282,7 +381,6 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
...
@@ -282,7 +381,6 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
SplitNs
(
self
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
self
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
self
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
SplitNs
(
self
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
out
.
Attr
=
*
attr
out
.
Attr
=
*
attr
return
out
,
OK
return
out
,
OK
}
}
...
@@ -291,7 +389,12 @@ func (self *PathFileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
...
@@ -291,7 +389,12 @@ func (self *PathFileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
}
}
func
(
self
*
PathFileSystemConnector
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
attr
,
err
:=
self
.
fileSystem
.
GetAttr
(
self
.
GetPath
(
header
.
NodeId
))
// TODO - should we update inodeData.Type?
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
nil
,
ENOENT
}
attr
,
err
:=
fs
.
GetAttr
(
fullPath
)
if
err
!=
OK
{
if
err
!=
OK
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -305,8 +408,12 @@ func (self *PathFileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn)
...
@@ -305,8 +408,12 @@ func (self *PathFileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn)
}
}
func
(
self
*
PathFileSystemConnector
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
func
(
self
*
PathFileSystemConnector
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
0
,
nil
,
ENOENT
}
// TODO - how to handle return flags, the FUSE open flags?
// TODO - how to handle return flags, the FUSE open flags?
f
,
err
:=
self
.
fileSystem
.
OpenDir
(
self
.
GetPath
(
header
.
NodeId
)
)
f
,
err
:=
fs
.
OpenDir
(
fullPath
)
if
err
!=
OK
{
if
err
!=
OK
{
return
0
,
nil
,
err
return
0
,
nil
,
err
}
}
...
@@ -315,8 +422,12 @@ func (self *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (f
...
@@ -315,8 +422,12 @@ func (self *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (f
}
}
func
(
self
*
PathFileSystemConnector
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
0
,
nil
,
ENOENT
}
// TODO - how to handle return flags, the FUSE open flags?
// TODO - how to handle return flags, the FUSE open flags?
f
,
err
:=
self
.
fileSystem
.
Open
(
self
.
GetPath
(
header
.
NodeId
)
,
input
.
Flags
)
f
,
err
:=
fs
.
Open
(
fullPath
,
input
.
Flags
)
if
err
!=
OK
{
if
err
!=
OK
{
return
0
,
nil
,
err
return
0
,
nil
,
err
}
}
...
@@ -327,19 +438,23 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
...
@@ -327,19 +438,23 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
var
err
Status
=
OK
var
err
Status
=
OK
// TODO - support Fh. (FSetAttr/FGetAttr/FTruncate.)
// TODO - support Fh. (FSetAttr/FGetAttr/FTruncate.)
fullPath
:=
self
.
GetPath
(
header
.
NodeId
)
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
nil
,
ENOENT
}
if
input
.
Valid
&
FATTR_MODE
!=
0
{
if
input
.
Valid
&
FATTR_MODE
!=
0
{
err
=
self
.
fileSystem
.
Chmod
(
fullPath
,
input
.
Mode
)
err
=
fs
.
Chmod
(
fullPath
,
input
.
Mode
)
}
}
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_UID
!=
0
||
input
.
Valid
&
FATTR_GID
!=
0
)
{
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_UID
!=
0
||
input
.
Valid
&
FATTR_GID
!=
0
)
{
// TODO - can we get just FATTR_GID but not FATTR_UID ?
// TODO - can we get just FATTR_GID but not FATTR_UID ?
err
=
self
.
fileSystem
.
Chown
(
fullPath
,
uint32
(
input
.
Uid
),
uint32
(
input
.
Gid
))
err
=
fs
.
Chown
(
fullPath
,
uint32
(
input
.
Uid
),
uint32
(
input
.
Gid
))
}
}
if
input
.
Valid
&
FATTR_SIZE
!=
0
{
if
input
.
Valid
&
FATTR_SIZE
!=
0
{
self
.
fileSystem
.
Truncate
(
fullPath
,
input
.
Size
)
fs
.
Truncate
(
fullPath
,
input
.
Size
)
}
}
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_ATIME
!=
0
||
input
.
Valid
&
FATTR_MTIME
!=
0
)
{
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_ATIME
!=
0
||
input
.
Valid
&
FATTR_MTIME
!=
0
)
{
err
=
self
.
fileSystem
.
Utimens
(
fullPath
,
err
=
fs
.
Utimens
(
fullPath
,
uint64
(
input
.
Atime
*
1e9
)
+
uint64
(
input
.
Atimensec
),
uint64
(
input
.
Atime
*
1e9
)
+
uint64
(
input
.
Atimensec
),
uint64
(
input
.
Mtime
*
1e9
)
+
uint64
(
input
.
Mtimensec
))
uint64
(
input
.
Mtime
*
1e9
)
+
uint64
(
input
.
Mtimensec
))
}
}
...
@@ -356,14 +471,21 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
...
@@ -356,14 +471,21 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
}
}
func
(
self
*
PathFileSystemConnector
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
fullPath
:=
self
.
GetPath
(
header
.
NodeId
)
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
val
,
err
:=
self
.
fileSystem
.
Readlink
(
fullPath
)
if
fs
==
nil
{
return
nil
,
ENOENT
}
val
,
err
:=
fs
.
Readlink
(
fullPath
)
return
bytes
.
NewBufferString
(
val
)
.
Bytes
(),
err
return
bytes
.
NewBufferString
(
val
)
.
Bytes
(),
err
}
}
func
(
self
*
PathFileSystemConnector
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
:=
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
name
)
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
err
:=
self
.
fileSystem
.
Mknod
(
fullPath
,
input
.
Mode
,
uint32
(
input
.
Rdev
))
if
fs
==
nil
{
return
nil
,
ENOENT
}
fullPath
=
path
.
Join
(
fullPath
,
name
)
err
:=
fs
.
Mknod
(
fullPath
,
input
.
Mode
,
uint32
(
input
.
Rdev
))
if
err
!=
OK
{
if
err
!=
OK
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -371,7 +493,11 @@ func (self *PathFileSystemConnector) Mknod(header *InHeader, input *MknodIn, nam
...
@@ -371,7 +493,11 @@ func (self *PathFileSystemConnector) Mknod(header *InHeader, input *MknodIn, nam
}
}
func
(
self
*
PathFileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
err
:=
self
.
fileSystem
.
Mkdir
(
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
name
),
input
.
Mode
)
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
nil
,
ENOENT
}
err
:=
fs
.
Mkdir
(
path
.
Join
(
fullPath
,
name
),
input
.
Mode
)
if
err
!=
OK
{
if
err
!=
OK
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -380,7 +506,11 @@ func (self *PathFileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, nam
...
@@ -380,7 +506,11 @@ func (self *PathFileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, nam
}
}
func
(
self
*
PathFileSystemConnector
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
code
=
self
.
fileSystem
.
Unlink
(
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
name
))
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
ENOENT
}
code
=
fs
.
Unlink
(
path
.
Join
(
fullPath
,
name
))
// Like fuse.c, we update our internal tables.
// Like fuse.c, we update our internal tables.
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
...
@@ -389,13 +519,21 @@ func (self *PathFileSystemConnector) Unlink(header *InHeader, name string) (code
...
@@ -389,13 +519,21 @@ func (self *PathFileSystemConnector) Unlink(header *InHeader, name string) (code
}
}
func
(
self
*
PathFileSystemConnector
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
code
=
self
.
fileSystem
.
Rmdir
(
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
name
))
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
ENOENT
}
code
=
fs
.
Rmdir
(
path
.
Join
(
fullPath
,
name
))
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
return
code
return
code
}
}
func
(
self
*
PathFileSystemConnector
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
err
:=
self
.
fileSystem
.
Symlink
(
pointedTo
,
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
linkName
))
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
nil
,
ENOENT
}
err
:=
fs
.
Symlink
(
pointedTo
,
path
.
Join
(
fullPath
,
linkName
))
if
err
!=
OK
{
if
err
!=
OK
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -405,10 +543,18 @@ func (self *PathFileSystemConnector) Symlink(header *InHeader, pointedTo string,
...
@@ -405,10 +543,18 @@ func (self *PathFileSystemConnector) Symlink(header *InHeader, pointedTo string,
}
}
func
(
self
*
PathFileSystemConnector
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldPath
:=
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
oldName
)
oldPath
,
oldFs
:=
self
.
GetPath
(
header
.
NodeId
)
newPath
:=
path
.
Join
(
self
.
GetPath
(
input
.
Newdir
),
newName
)
newPath
,
fs
:=
self
.
GetPath
(
input
.
Newdir
)
if
fs
==
nil
||
oldFs
==
nil
{
return
ENOENT
}
if
fs
!=
oldFs
{
return
EXDEV
}
code
=
self
.
fileSystem
.
Rename
(
oldPath
,
newPath
)
oldPath
=
path
.
Join
(
oldPath
,
oldName
)
newPath
=
path
.
Join
(
newPath
,
newName
)
code
=
fs
.
Rename
(
oldPath
,
newPath
)
if
code
!=
OK
{
if
code
!=
OK
{
return
return
}
}
...
@@ -425,9 +571,18 @@ func (self *PathFileSystemConnector) Rename(header *InHeader, input *RenameIn, o
...
@@ -425,9 +571,18 @@ func (self *PathFileSystemConnector) Rename(header *InHeader, input *RenameIn, o
}
}
func
(
self
*
PathFileSystemConnector
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
filename
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
filename
string
)
(
out
*
EntryOut
,
code
Status
)
{
orig
:=
self
.
GetPath
(
input
.
Oldnodeid
)
orig
,
fs
:=
self
.
GetPath
(
input
.
Oldnodeid
)
newName
:=
path
.
Join
(
self
.
GetPath
(
header
.
NodeId
),
filename
)
newName
,
newFs
:=
self
.
GetPath
(
header
.
NodeId
)
err
:=
self
.
fileSystem
.
Link
(
orig
,
newName
)
if
fs
==
nil
||
newFs
==
nil
{
return
nil
,
ENOENT
}
if
newFs
!=
fs
{
return
nil
,
EXDEV
}
newName
=
path
.
Join
(
newName
,
filename
)
err
:=
fs
.
Link
(
orig
,
newName
)
if
err
!=
OK
{
if
err
!=
OK
{
return
nil
,
err
return
nil
,
err
...
@@ -437,14 +592,21 @@ func (self *PathFileSystemConnector) Link(header *InHeader, input *LinkIn, filen
...
@@ -437,14 +592,21 @@ func (self *PathFileSystemConnector) Link(header *InHeader, input *LinkIn, filen
}
}
func
(
self
*
PathFileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
return
self
.
fileSystem
.
Access
(
self
.
GetPath
(
header
.
NodeId
),
input
.
Mask
)
p
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
ENOENT
}
return
fs
.
Access
(
p
,
input
.
Mask
)
}
}
func
(
self
*
PathFileSystemConnector
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
func
(
self
*
PathFileSystemConnector
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
directory
:=
self
.
GetPath
(
header
.
NodeId
)
directory
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
return
0
,
nil
,
nil
,
ENOENT
}
fullPath
:=
path
.
Join
(
directory
,
name
)
fullPath
:=
path
.
Join
(
directory
,
name
)
f
,
err
:=
self
.
fileSystem
.
Create
(
fullPath
,
uint32
(
input
.
Flags
),
input
.
Mode
)
f
,
err
:=
fs
.
Create
(
fullPath
,
uint32
(
input
.
Flags
),
input
.
Mode
)
if
err
!=
OK
{
if
err
!=
OK
{
return
0
,
nil
,
nil
,
err
return
0
,
nil
,
nil
,
err
}
}
...
...
fuse/types.go
View file @
1f1c157d
...
@@ -92,6 +92,9 @@ const (
...
@@ -92,6 +92,9 @@ const (
ENOTDIR
=
Status
(
syscall
.
ENOTDIR
)
ENOTDIR
=
Status
(
syscall
.
ENOTDIR
)
EACCES
=
Status
(
syscall
.
EACCES
)
EACCES
=
Status
(
syscall
.
EACCES
)
EPERM
=
Status
(
syscall
.
EPERM
)
EPERM
=
Status
(
syscall
.
EPERM
)
EBUSY
=
Status
(
syscall
.
EBUSY
)
EINVAL
=
Status
(
syscall
.
EINVAL
)
EXDEV
=
Status
(
syscall
.
EXDEV
)
)
)
type
Opcode
int
type
Opcode
int
...
@@ -568,14 +571,12 @@ type PathFilesystem interface {
...
@@ -568,14 +571,12 @@ type PathFilesystem interface {
OpenDir
(
name
string
)
(
dir
RawFuseDir
,
code
Status
)
OpenDir
(
name
string
)
(
dir
RawFuseDir
,
code
Status
)
// TODO - what is a good interface?
// TODO - what is a good interface?
Init
()
(
*
InitOut
,
Status
)
Mount
(
connector
*
PathFileSystemConnector
)
Status
Destroy
()
Unmount
()
Access
(
name
string
,
mode
uint32
)
(
code
Status
)
Access
(
name
string
,
mode
uint32
)
(
code
Status
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
)
(
file
RawFuseFile
,
code
Status
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
)
(
file
RawFuseFile
,
code
Status
)
Utimens
(
name
string
,
AtimeNs
uint64
,
CtimeNs
uint64
)
(
code
Status
)
Utimens
(
name
string
,
AtimeNs
uint64
,
CtimeNs
uint64
)
(
code
Status
)
// unimplemented: poll, ioctl, bmap.
// unimplemented: poll, ioctl, bmap.
SetOptions
(
*
PathFileSystemConnectorOptions
)
}
}
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