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
Kirill Smelkov
go-fuse
Commits
ef5d1063
Commit
ef5d1063
authored
Jan 26, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add file/directory/mount tracking for proper EBUSY errors on mounts.
Extends raw API with Release() and ReleaseDir() methods.
parent
0f4e53e7
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
172 additions
and
78 deletions
+172
-78
examplelib/dummyfuse.go
examplelib/dummyfuse.go
+7
-0
examplelib/passthrough_test.go
examplelib/passthrough_test.go
+21
-0
examplelib/stackfs.go
examplelib/stackfs.go
+11
-0
fuse/fuse.go
fuse/fuse.go
+6
-2
fuse/pathfilesystem.go
fuse/pathfilesystem.go
+124
-76
fuse/types.go
fuse/types.go
+3
-0
No files found.
examplelib/dummyfuse.go
View file @
ef5d1063
...
...
@@ -97,6 +97,13 @@ func (self *DummyFuse) OpenDir(header *fuse.InHeader, input *fuse.OpenIn) (flags
return
0
,
nil
,
fuse
.
ENOSYS
}
func
(
self
*
DummyFuse
)
Release
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseFile
)
{
}
func
(
self
*
DummyFuse
)
ReleaseDir
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseDir
)
{
}
////////////////////////////////////////////////////////////////
// DummyFuseFile
...
...
examplelib/passthrough_test.go
View file @
ef5d1063
...
...
@@ -11,6 +11,7 @@ import (
"testing"
"syscall"
"rand"
"time"
)
var
_
=
strings
.
Join
...
...
@@ -634,5 +635,25 @@ func TestRecursiveMount(t *testing.T) {
if
err
!=
nil
{
t
.
Error
(
"lstat submount/file"
,
err
)
}
f
,
err
=
os
.
Open
(
path
.
Join
(
submnt
,
"hello.txt"
),
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
t
.
Error
(
"open submount/file"
,
err
)
}
code
=
ts
.
connector
.
Unmount
(
"/mnt"
)
if
code
!=
fuse
.
EBUSY
{
t
.
Error
(
"expect EBUSY"
)
}
f
.
Close
()
// The close takes some time to propagate through FUSE.
time
.
Sleep
(
1e9
)
code
=
ts
.
connector
.
Unmount
(
"/mnt"
)
if
code
!=
fuse
.
OK
{
t
.
Error
(
"umount failed."
,
code
)
}
ts
.
Cleanup
()
}
examplelib/stackfs.go
View file @
ef5d1063
...
...
@@ -592,6 +592,16 @@ func (self *SubmountFileSystem) OpenDir(header *fuse.InHeader, input *fuse.OpenI
return
subfs
.
Fs
.
OpenDir
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
Release
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseFile
)
{
// TODO - should run release on subfs too.
}
func
(
self
*
SubmountFileSystem
)
ReleaseDir
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseDir
)
{
// TODO - should run releasedir on subfs too.
}
////////////////////////////////////////////////////////////////
type
SubmountFileSystemTopDir
struct
{
...
...
@@ -628,3 +638,4 @@ func (self *SubmountFileSystemTopDir) ReleaseDir() {
func
(
self
*
SubmountFileSystemTopDir
)
FsyncDir
(
input
*
fuse
.
FsyncIn
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOENT
}
fuse/fuse.go
View file @
ef5d1063
...
...
@@ -501,7 +501,9 @@ func doCreate(state *MountState, header *InHeader, input *CreateIn, name string)
}
func
doRelease
(
state
*
MountState
,
header
*
InHeader
,
input
*
ReleaseIn
)
(
out
Empty
,
code
Status
)
{
state
.
FindFile
(
input
.
Fh
)
.
Release
()
f
:=
state
.
FindFile
(
input
.
Fh
)
state
.
fileSystem
.
Release
(
header
,
f
)
f
.
Release
()
state
.
UnregisterFile
(
input
.
Fh
)
return
nil
,
OK
}
...
...
@@ -534,7 +536,9 @@ func doSetattr(state *MountState, header *InHeader, input *SetAttrIn) (out *Attr
// Handling directories
func
doReleaseDir
(
state
*
MountState
,
header
*
InHeader
,
input
*
ReleaseIn
)
(
out
Empty
,
code
Status
)
{
state
.
FindDir
(
input
.
Fh
)
.
ReleaseDir
()
d
:=
state
.
FindDir
(
input
.
Fh
)
state
.
fileSystem
.
ReleaseDir
(
header
,
d
)
d
.
ReleaseDir
()
state
.
UnregisterDir
(
input
.
Fh
)
return
nil
,
OK
}
...
...
fuse/pathfilesystem.go
View file @
ef5d1063
...
...
@@ -9,6 +9,22 @@ import (
"strings"
)
type
mountData
struct
{
// If non-nil the file system mounted here.
fs
PathFilesystem
// If yes, we are looking to unmount the mounted fs.
unmountPending
bool
openFiles
int
openDirs
int
subMounts
int
}
func
newMount
(
fs
PathFilesystem
)
*
mountData
{
return
&
mountData
{
fs
:
fs
}
}
// TODO should rename to dentry?
type
inodeData
struct
{
Parent
*
inodeData
...
...
@@ -20,11 +36,7 @@ type inodeData struct {
// Number of inodeData that have this as parent.
RefCount
int
// If non-nil the file system mounted here.
Mounted
PathFilesystem
// If yes, we are looking to unmount the mounted fs.
unmountPending
bool
mount
*
mountData
}
// Should implement some hash table method instead?
...
...
@@ -41,22 +53,26 @@ func (self *inodeData) Key() string {
return
inodeDataKey
(
p
,
self
.
Name
)
}
func
(
self
*
inodeData
)
GetPath
()
(
path
string
,
fs
PathFilesystem
)
{
func
(
self
*
inodeData
)
GetPath
()
(
path
string
,
mount
*
mountData
)
{
// TODO - softcode this.
var
components
[
100
]
string
j
:=
len
(
components
)
inode
:=
self
for
;
inode
!=
nil
&&
inode
.
Mounted
==
nil
;
inode
=
inode
.
Parent
{
for
;
inode
!=
nil
&&
inode
.
mount
==
nil
;
inode
=
inode
.
Parent
{
j
--
components
[
j
]
=
inode
.
Name
}
if
inode
==
nil
{
panic
(
"did not find parent with mount"
)
}
fullPath
:=
strings
.
Join
(
components
[
j
:
],
"/"
)
if
!
inode
.
unmountPending
{
fs
=
inode
.
Mounted
mount
=
inode
.
mount
if
mount
.
unmountPending
{
mount
=
nil
}
return
fullPath
,
fs
return
fullPath
,
mount
}
type
TimeoutOptions
struct
{
...
...
@@ -167,7 +183,7 @@ func (self *PathFileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int
data
,
ok
:=
self
.
inodePathMapByInode
[
nodeId
]
if
ok
{
data
.
LookupCount
-=
forgetCount
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
Mounted
==
nil
||
data
.
unmountPending
)
{
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
mount
==
nil
||
data
.
mount
.
unmountPending
)
{
self
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
}
}
...
...
@@ -309,34 +325,51 @@ func (self *PathFileSystemConnector) Mount(path string, fs PathFilesystem) Statu
log
.
Println
(
"Mount: "
,
fs
,
"on"
,
path
,
node
)
}
// TODO - this is technically a race-condition.
node
.
Mounted
=
fs
node
.
unmountPending
=
false
// TODO - this is technically a race-condition?
node
.
mount
=
newMount
(
fs
)
if
node
.
Parent
!=
nil
{
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
parentMount
.
subMounts
++
}
return
OK
}
func
(
self
*
PathFileSystemConnector
)
Unmount
(
path
string
)
Status
{
node
:=
self
.
findInode
(
path
)
if
node
==
nil
||
node
.
Mounted
==
nil
{
if
node
==
nil
{
panic
(
path
)
}
mount
:=
node
.
mount
if
mount
==
nil
{
panic
(
path
)
}
// TODO - check if we have open files.
if
mount
.
openFiles
+
mount
.
openDirs
+
mount
.
subMounts
>
0
{
log
.
Println
(
"busy: "
,
mount
)
return
EBUSY
}
if
self
.
Debug
{
log
.
Println
(
"Unmount: "
,
node
)
log
.
Println
(
"Unmount: "
,
mount
)
}
// node manipulations are racy?
if
node
.
RefCount
>
0
{
node
.
Mounted
.
Unmount
()
node
.
unmountPending
=
true
mount
.
fs
.
Unmount
()
mount
.
unmountPending
=
true
}
else
{
node
.
Mounted
=
nil
node
.
mount
=
nil
}
if
node
.
Parent
!=
nil
{
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
parentMount
.
subMounts
--
}
return
OK
}
func
(
self
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
fs
PathFilesystem
)
{
func
(
self
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
mount
*
mountData
)
{
return
self
.
getInodeData
(
nodeid
)
.
GetPath
()
}
...
...
@@ -355,13 +388,13 @@ func (self *PathFileSystemConnector) Lookup(header *InHeader, name string) (out
// TODO - fuse.c has special case code for name == "." and
// "..", those lookups happen if FUSE_EXPORT_SUPPORT is set in
// Init.
fullPath
,
fs
:=
parent
.
GetPath
()
if
fs
==
nil
{
fullPath
,
mount
:=
parent
.
GetPath
()
if
mount
==
nil
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
}
fullPath
=
path
.
Join
(
fullPath
,
name
)
attr
,
err
:=
fs
.
GetAttr
(
fullPath
)
attr
,
err
:=
mount
.
fs
.
GetAttr
(
fullPath
)
if
err
==
ENOENT
&&
self
.
options
.
NegativeTimeout
>
0.0
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
...
...
@@ -390,11 +423,11 @@ func (self *PathFileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
func
(
self
*
PathFileSystemConnector
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
// TODO - should we update inodeData.Type?
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
attr
,
err
:=
fs
.
GetAttr
(
fullPath
)
attr
,
err
:=
mount
.
fs
.
GetAttr
(
fullPath
)
if
err
!=
OK
{
return
nil
,
err
}
...
...
@@ -408,29 +441,34 @@ func (self *PathFileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn)
}
func
(
self
*
PathFileSystemConnector
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
ENOENT
}
// TODO - how to handle return flags, the FUSE open flags?
f
,
err
:=
fs
.
OpenDir
(
fullPath
)
f
,
err
:=
mount
.
fs
.
OpenDir
(
fullPath
)
if
err
!=
OK
{
return
0
,
nil
,
err
}
// TODO - racy?
mount
.
openDirs
++
return
0
,
f
,
OK
}
func
(
self
*
PathFileSystemConnector
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
ENOENT
}
// TODO - how to handle return flags, the FUSE open flags?
f
,
err
:=
fs
.
Open
(
fullPath
,
input
.
Flags
)
f
,
err
:=
mount
.
fs
.
Open
(
fullPath
,
input
.
Flags
)
if
err
!=
OK
{
return
0
,
nil
,
err
}
// TODO - racy?
mount
.
openFiles
++
return
0
,
f
,
OK
}
...
...
@@ -438,23 +476,23 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
var
err
Status
=
OK
// TODO - support Fh. (FSetAttr/FGetAttr/FTruncate.)
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
if
input
.
Valid
&
FATTR_MODE
!=
0
{
err
=
fs
.
Chmod
(
fullPath
,
input
.
Mode
)
err
=
mount
.
fs
.
Chmod
(
fullPath
,
input
.
Mode
)
}
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_UID
!=
0
||
input
.
Valid
&
FATTR_GID
!=
0
)
{
// TODO - can we get just FATTR_GID but not FATTR_UID ?
err
=
fs
.
Chown
(
fullPath
,
uint32
(
input
.
Uid
),
uint32
(
input
.
Gid
))
err
=
mount
.
fs
.
Chown
(
fullPath
,
uint32
(
input
.
Uid
),
uint32
(
input
.
Gid
))
}
if
input
.
Valid
&
FATTR_SIZE
!=
0
{
fs
.
Truncate
(
fullPath
,
input
.
Size
)
mount
.
fs
.
Truncate
(
fullPath
,
input
.
Size
)
}
if
err
!=
OK
&&
(
input
.
Valid
&
FATTR_ATIME
!=
0
||
input
.
Valid
&
FATTR_MTIME
!=
0
)
{
err
=
fs
.
Utimens
(
fullPath
,
err
=
mount
.
fs
.
Utimens
(
fullPath
,
uint64
(
input
.
Atime
*
1e9
)
+
uint64
(
input
.
Atimensec
),
uint64
(
input
.
Mtime
*
1e9
)
+
uint64
(
input
.
Mtimensec
))
}
...
...
@@ -471,21 +509,21 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
}
func
(
self
*
PathFileSystemConnector
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
val
,
err
:=
fs
.
Readlink
(
fullPath
)
val
,
err
:=
mount
.
fs
.
Readlink
(
fullPath
)
return
bytes
.
NewBufferString
(
val
)
.
Bytes
(),
err
}
func
(
self
*
PathFileSystemConnector
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
fullPath
=
path
.
Join
(
fullPath
,
name
)
err
:=
fs
.
Mknod
(
fullPath
,
input
.
Mode
,
uint32
(
input
.
Rdev
))
err
:=
mount
.
fs
.
Mknod
(
fullPath
,
input
.
Mode
,
uint32
(
input
.
Rdev
))
if
err
!=
OK
{
return
nil
,
err
}
...
...
@@ -493,11 +531,11 @@ func (self *PathFileSystemConnector) Mknod(header *InHeader, input *MknodIn, nam
}
func
(
self
*
PathFileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
err
:=
fs
.
Mkdir
(
path
.
Join
(
fullPath
,
name
),
input
.
Mode
)
err
:=
mount
.
fs
.
Mkdir
(
path
.
Join
(
fullPath
,
name
),
input
.
Mode
)
if
err
!=
OK
{
return
nil
,
err
}
...
...
@@ -506,11 +544,11 @@ func (self *PathFileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, nam
}
func
(
self
*
PathFileSystemConnector
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
code
=
fs
.
Unlink
(
path
.
Join
(
fullPath
,
name
))
code
=
mount
.
fs
.
Unlink
(
path
.
Join
(
fullPath
,
name
))
// Like fuse.c, we update our internal tables.
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
...
...
@@ -519,21 +557,21 @@ func (self *PathFileSystemConnector) Unlink(header *InHeader, name string) (code
}
func
(
self
*
PathFileSystemConnector
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
code
=
fs
.
Rmdir
(
path
.
Join
(
fullPath
,
name
))
code
=
mount
.
fs
.
Rmdir
(
path
.
Join
(
fullPath
,
name
))
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
return
code
}
func
(
self
*
PathFileSystemConnector
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
err
:=
fs
.
Symlink
(
pointedTo
,
path
.
Join
(
fullPath
,
linkName
))
err
:=
mount
.
fs
.
Symlink
(
pointedTo
,
path
.
Join
(
fullPath
,
linkName
))
if
err
!=
OK
{
return
nil
,
err
}
...
...
@@ -543,18 +581,18 @@ func (self *PathFileSystemConnector) Symlink(header *InHeader, pointedTo string,
}
func
(
self
*
PathFileSystemConnector
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldPath
,
old
Fs
:=
self
.
GetPath
(
header
.
NodeId
)
newPath
,
fs
:=
self
.
GetPath
(
input
.
Newdir
)
if
fs
==
nil
||
oldFs
==
nil
{
oldPath
,
old
Mount
:=
self
.
GetPath
(
header
.
NodeId
)
newPath
,
mount
:=
self
.
GetPath
(
input
.
Newdir
)
if
mount
==
nil
||
oldMount
==
nil
{
return
ENOENT
}
if
fs
!=
oldFs
{
if
mount
!=
oldMount
{
return
EXDEV
}
oldPath
=
path
.
Join
(
oldPath
,
oldName
)
newPath
=
path
.
Join
(
newPath
,
newName
)
code
=
fs
.
Rename
(
oldPath
,
newPath
)
code
=
mount
.
fs
.
Rename
(
oldPath
,
newPath
)
if
code
!=
OK
{
return
}
...
...
@@ -571,18 +609,17 @@ func (self *PathFileSystemConnector) Rename(header *InHeader, input *RenameIn, o
}
func
(
self
*
PathFileSystemConnector
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
filename
string
)
(
out
*
EntryOut
,
code
Status
)
{
orig
,
fs
:=
self
.
GetPath
(
input
.
Oldnodeid
)
newName
,
new
Fs
:=
self
.
GetPath
(
header
.
NodeId
)
orig
,
mount
:=
self
.
GetPath
(
input
.
Oldnodeid
)
newName
,
new
Mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
||
newFs
==
nil
{
if
mount
==
nil
||
newMount
==
nil
{
return
nil
,
ENOENT
}
if
newFs
!=
fs
{
if
mount
!=
newMount
{
return
nil
,
EXDEV
}
newName
=
path
.
Join
(
newName
,
filename
)
err
:=
fs
.
Link
(
orig
,
newName
)
err
:=
mount
.
fs
.
Link
(
orig
,
newName
)
if
err
!=
OK
{
return
nil
,
err
...
...
@@ -592,29 +629,40 @@ func (self *PathFileSystemConnector) Link(header *InHeader, input *LinkIn, filen
}
func
(
self
*
PathFileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
p
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
p
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
return
fs
.
Access
(
p
,
input
.
Mask
)
return
mount
.
fs
.
Access
(
p
,
input
.
Mask
)
}
func
(
self
*
PathFileSystemConnector
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
directory
,
fs
:=
self
.
GetPath
(
header
.
NodeId
)
if
fs
==
nil
{
directory
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
nil
,
ENOENT
}
fullPath
:=
path
.
Join
(
directory
,
name
)
f
,
err
:=
fs
.
Create
(
fullPath
,
uint32
(
input
.
Flags
),
input
.
Mode
)
f
,
err
:=
mount
.
fs
.
Create
(
fullPath
,
uint32
(
input
.
Flags
),
input
.
Mode
)
if
err
!=
OK
{
return
0
,
nil
,
nil
,
err
}
mount
.
openFiles
++
out
,
code
=
self
.
Lookup
(
header
,
name
)
return
0
,
f
,
out
,
code
}
func
(
self
*
PathFileSystemConnector
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
_
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
mount
.
openFiles
--
}
func
(
self
*
PathFileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
_
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
mount
.
openDirs
--
}
////////////////////////////////////////////////////////////////
// unimplemented.
...
...
fuse/types.go
View file @
ef5d1063
...
...
@@ -531,6 +531,9 @@ type RawFileSystem interface {
// The return flags are FOPEN_xx.
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
}
type
RawFuseFile
interface
{
...
...
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