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
7c3c1e41
Commit
7c3c1e41
authored
Feb 21, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Uniformize receiver names to 'me'.
parent
1fe92061
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
733 additions
and
733 deletions
+733
-733
examplelib/passthrough.go
examplelib/passthrough.go
+51
-51
examplelib/passthrough_test.go
examplelib/passthrough_test.go
+175
-175
examplelib/stackfs.go
examplelib/stackfs.go
+133
-133
examplelib/stackfs_test.go
examplelib/stackfs_test.go
+58
-58
examplelib/zipfs.go
examplelib/zipfs.go
+6
-6
fuse/bufferpool.go
fuse/bufferpool.go
+21
-21
fuse/datafile.go
fuse/datafile.go
+4
-4
fuse/default.go
fuse/default.go
+52
-52
fuse/direntry.go
fuse/direntry.go
+14
-14
fuse/fuse.go
fuse/fuse.go
+83
-83
fuse/pathfilesystem.go
fuse/pathfilesystem.go
+136
-136
No files found.
examplelib/passthrough.go
View file @
7c3c1e41
...
...
@@ -27,12 +27,12 @@ func NewPassThroughFuse(root string) (out *PassThroughFuse) {
return
out
}
func
(
self
*
PassThroughFuse
)
GetPath
(
relPath
string
)
string
{
return
path
.
Join
(
self
.
root
,
relPath
)
func
(
me
*
PassThroughFuse
)
GetPath
(
relPath
string
)
string
{
return
path
.
Join
(
me
.
root
,
relPath
)
}
func
(
self
*
PassThroughFuse
)
GetAttr
(
name
string
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
fullPath
:=
self
.
GetPath
(
name
)
func
(
me
*
PassThroughFuse
)
GetAttr
(
name
string
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
fullPath
:=
me
.
GetPath
(
name
)
fi
,
err
:=
os
.
Lstat
(
fullPath
)
if
err
!=
nil
{
return
nil
,
fuse
.
ENOENT
...
...
@@ -43,10 +43,10 @@ func (self *PassThroughFuse) GetAttr(name string) (*fuse.Attr, fuse.Status) {
return
out
,
fuse
.
OK
}
func
(
self
*
PassThroughFuse
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
status
fuse
.
Status
)
{
func
(
me
*
PassThroughFuse
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
status
fuse
.
Status
)
{
// What other ways beyond O_RDONLY are there to open
// directories?
f
,
err
:=
os
.
Open
(
self
.
GetPath
(
name
),
os
.
O_RDONLY
,
0
)
f
,
err
:=
os
.
Open
(
me
.
GetPath
(
name
),
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
return
nil
,
fuse
.
OsErrorToFuseError
(
err
)
}
...
...
@@ -76,75 +76,75 @@ func (self *PassThroughFuse) OpenDir(name string) (stream chan fuse.DirEntry, st
return
output
,
fuse
.
OK
}
func
(
self
*
PassThroughFuse
)
Open
(
name
string
,
flags
uint32
)
(
fuseFile
fuse
.
RawFuseFile
,
status
fuse
.
Status
)
{
f
,
err
:=
os
.
Open
(
self
.
GetPath
(
name
),
int
(
flags
),
0
)
func
(
me
*
PassThroughFuse
)
Open
(
name
string
,
flags
uint32
)
(
fuseFile
fuse
.
RawFuseFile
,
status
fuse
.
Status
)
{
f
,
err
:=
os
.
Open
(
me
.
GetPath
(
name
),
int
(
flags
),
0
)
if
err
!=
nil
{
return
nil
,
fuse
.
OsErrorToFuseError
(
err
)
}
return
&
PassThroughFile
{
file
:
f
},
fuse
.
OK
}
func
(
self
*
PassThroughFuse
)
Chmod
(
path
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
err
:=
os
.
Chmod
(
self
.
GetPath
(
path
),
mode
)
func
(
me
*
PassThroughFuse
)
Chmod
(
path
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
err
:=
os
.
Chmod
(
me
.
GetPath
(
path
),
mode
)
return
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFuse
)
Chown
(
path
string
,
uid
uint32
,
gid
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Chown
(
self
.
GetPath
(
path
),
int
(
uid
),
int
(
gid
)))
func
(
me
*
PassThroughFuse
)
Chown
(
path
string
,
uid
uint32
,
gid
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Chown
(
me
.
GetPath
(
path
),
int
(
uid
),
int
(
gid
)))
}
func
(
self
*
PassThroughFuse
)
Truncate
(
path
string
,
offset
uint64
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Truncate
(
self
.
GetPath
(
path
),
int64
(
offset
)))
func
(
me
*
PassThroughFuse
)
Truncate
(
path
string
,
offset
uint64
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Truncate
(
me
.
GetPath
(
path
),
int64
(
offset
)))
}
func
(
self
*
PassThroughFuse
)
Utimens
(
path
string
,
AtimeNs
uint64
,
MtimeNs
uint64
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Chtimes
(
self
.
GetPath
(
path
),
int64
(
AtimeNs
),
int64
(
MtimeNs
)))
func
(
me
*
PassThroughFuse
)
Utimens
(
path
string
,
AtimeNs
uint64
,
MtimeNs
uint64
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Chtimes
(
me
.
GetPath
(
path
),
int64
(
AtimeNs
),
int64
(
MtimeNs
)))
}
func
(
self
*
PassThroughFuse
)
Readlink
(
name
string
)
(
out
string
,
code
fuse
.
Status
)
{
f
,
err
:=
os
.
Readlink
(
self
.
GetPath
(
name
))
func
(
me
*
PassThroughFuse
)
Readlink
(
name
string
)
(
out
string
,
code
fuse
.
Status
)
{
f
,
err
:=
os
.
Readlink
(
me
.
GetPath
(
name
))
return
f
,
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFuse
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Mknod
(
self
.
GetPath
(
name
),
mode
,
int
(
dev
)))
func
(
me
*
PassThroughFuse
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Mknod
(
me
.
GetPath
(
name
),
mode
,
int
(
dev
)))
}
func
(
self
*
PassThroughFuse
)
Mkdir
(
path
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Mkdir
(
self
.
GetPath
(
path
),
mode
))
func
(
me
*
PassThroughFuse
)
Mkdir
(
path
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Mkdir
(
me
.
GetPath
(
path
),
mode
))
}
func
(
self
*
PassThroughFuse
)
Unlink
(
name
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Remove
(
self
.
GetPath
(
name
)))
func
(
me
*
PassThroughFuse
)
Unlink
(
name
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Remove
(
me
.
GetPath
(
name
)))
}
func
(
self
*
PassThroughFuse
)
Rmdir
(
name
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Remove
(
self
.
GetPath
(
name
)))
func
(
me
*
PassThroughFuse
)
Rmdir
(
name
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Remove
(
me
.
GetPath
(
name
)))
}
func
(
self
*
PassThroughFuse
)
Symlink
(
pointedTo
string
,
linkName
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Symlink
(
pointedTo
,
self
.
GetPath
(
linkName
)))
func
(
me
*
PassThroughFuse
)
Symlink
(
pointedTo
string
,
linkName
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Symlink
(
pointedTo
,
me
.
GetPath
(
linkName
)))
}
func
(
self
*
PassThroughFuse
)
Rename
(
oldPath
string
,
newPath
string
)
(
code
fuse
.
Status
)
{
err
:=
os
.
Rename
(
self
.
GetPath
(
oldPath
),
self
.
GetPath
(
newPath
))
func
(
me
*
PassThroughFuse
)
Rename
(
oldPath
string
,
newPath
string
)
(
code
fuse
.
Status
)
{
err
:=
os
.
Rename
(
me
.
GetPath
(
oldPath
),
me
.
GetPath
(
newPath
))
return
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFuse
)
Link
(
orig
string
,
newName
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Link
(
self
.
GetPath
(
orig
),
self
.
GetPath
(
newName
)))
func
(
me
*
PassThroughFuse
)
Link
(
orig
string
,
newName
string
)
(
code
fuse
.
Status
)
{
return
fuse
.
OsErrorToFuseError
(
os
.
Link
(
me
.
GetPath
(
orig
),
me
.
GetPath
(
newName
)))
}
func
(
self
*
PassThroughFuse
)
Access
(
name
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Access
(
self
.
GetPath
(
name
),
mode
))
func
(
me
*
PassThroughFuse
)
Access
(
name
string
,
mode
uint32
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Access
(
me
.
GetPath
(
name
),
mode
))
}
func
(
self
*
PassThroughFuse
)
Create
(
path
string
,
flags
uint32
,
mode
uint32
)
(
fuseFile
fuse
.
RawFuseFile
,
code
fuse
.
Status
)
{
f
,
err
:=
os
.
Open
(
self
.
GetPath
(
path
),
int
(
flags
)
|
os
.
O_CREAT
,
mode
)
func
(
me
*
PassThroughFuse
)
Create
(
path
string
,
flags
uint32
,
mode
uint32
)
(
fuseFile
fuse
.
RawFuseFile
,
code
fuse
.
Status
)
{
f
,
err
:=
os
.
Open
(
me
.
GetPath
(
path
),
int
(
flags
)
|
os
.
O_CREAT
,
mode
)
return
&
PassThroughFile
{
file
:
f
},
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFuse
)
SetOptions
(
options
*
fuse
.
PathFileSystemConnectorOptions
)
{
func
(
me
*
PassThroughFuse
)
SetOptions
(
options
*
fuse
.
PathFileSystemConnectorOptions
)
{
options
.
NegativeTimeout
=
100.0
options
.
AttrTimeout
=
100.0
options
.
EntryTimeout
=
100.0
...
...
@@ -158,10 +158,10 @@ type PassThroughFile struct {
fuse
.
DefaultRawFuseFile
}
func
(
self
*
PassThroughFile
)
Read
(
input
*
fuse
.
ReadIn
,
buffers
*
fuse
.
BufferPool
)
([]
byte
,
fuse
.
Status
)
{
func
(
me
*
PassThroughFile
)
Read
(
input
*
fuse
.
ReadIn
,
buffers
*
fuse
.
BufferPool
)
([]
byte
,
fuse
.
Status
)
{
slice
:=
buffers
.
AllocBuffer
(
input
.
Size
)
n
,
err
:=
self
.
file
.
ReadAt
(
slice
,
int64
(
input
.
Offset
))
n
,
err
:=
me
.
file
.
ReadAt
(
slice
,
int64
(
input
.
Offset
))
if
err
==
os
.
EOF
{
// TODO - how to signal EOF?
return
slice
[
:
n
],
fuse
.
OK
...
...
@@ -169,17 +169,17 @@ func (self *PassThroughFile) Read(input *fuse.ReadIn, buffers *fuse.BufferPool)
return
slice
[
:
n
],
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFile
)
Write
(
input
*
fuse
.
WriteIn
,
data
[]
byte
)
(
uint32
,
fuse
.
Status
)
{
n
,
err
:=
self
.
file
.
WriteAt
(
data
,
int64
(
input
.
Offset
))
func
(
me
*
PassThroughFile
)
Write
(
input
*
fuse
.
WriteIn
,
data
[]
byte
)
(
uint32
,
fuse
.
Status
)
{
n
,
err
:=
me
.
file
.
WriteAt
(
data
,
int64
(
input
.
Offset
))
return
uint32
(
n
),
fuse
.
OsErrorToFuseError
(
err
)
}
func
(
self
*
PassThroughFile
)
Release
()
{
self
.
file
.
Close
()
func
(
me
*
PassThroughFile
)
Release
()
{
me
.
file
.
Close
()
}
func
(
self
*
PassThroughFile
)
Fsync
(
*
fuse
.
FsyncIn
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Fsync
(
self
.
file
.
Fd
()))
func
(
me
*
PassThroughFile
)
Fsync
(
*
fuse
.
FsyncIn
)
(
code
fuse
.
Status
)
{
return
fuse
.
Status
(
syscall
.
Fsync
(
me
.
file
.
Fd
()))
}
////////////////////////////////////////////////////////////////
...
...
@@ -193,25 +193,25 @@ type PassThroughDir struct {
}
func
NewPassThroughDir
(
file
*
os
.
File
)
*
PassThroughDir
{
self
:=
new
(
PassThroughDir
)
self
.
directoryChannel
=
make
(
chan
*
os
.
FileInfo
,
500
)
me
:=
new
(
PassThroughDir
)
me
.
directoryChannel
=
make
(
chan
*
os
.
FileInfo
,
500
)
go
func
()
{
for
{
want
:=
500
infos
,
err
:=
file
.
Readdir
(
want
)
for
i
,
_
:=
range
infos
{
self
.
directoryChannel
<-
&
infos
[
i
]
me
.
directoryChannel
<-
&
infos
[
i
]
}
if
len
(
infos
)
<
want
{
break
}
if
err
!=
nil
{
self
.
directoryError
=
err
me
.
directoryError
=
err
break
}
}
close
(
self
.
directoryChannel
)
close
(
me
.
directoryChannel
)
file
.
Close
()
}()
return
self
return
me
}
examplelib/passthrough_test.go
View file @
7c3c1e41
...
...
@@ -38,79 +38,79 @@ type testCase struct {
}
// Create and mount filesystem.
func
(
self
*
testCase
)
Setup
(
t
*
testing
.
T
)
{
self
.
tester
=
t
func
(
me
*
testCase
)
Setup
(
t
*
testing
.
T
)
{
me
.
tester
=
t
const
name
string
=
"hello.txt"
const
subdir
string
=
"subdir"
self
.
origDir
=
fuse
.
MakeTempDir
()
self
.
mountPoint
=
fuse
.
MakeTempDir
()
me
.
origDir
=
fuse
.
MakeTempDir
()
me
.
mountPoint
=
fuse
.
MakeTempDir
()
self
.
mountFile
=
path
.
Join
(
self
.
mountPoint
,
name
)
self
.
mountSubdir
=
path
.
Join
(
self
.
mountPoint
,
subdir
)
self
.
mountSubfile
=
path
.
Join
(
self
.
mountSubdir
,
"subfile"
)
self
.
origFile
=
path
.
Join
(
self
.
origDir
,
name
)
self
.
origSubdir
=
path
.
Join
(
self
.
origDir
,
subdir
)
self
.
origSubfile
=
path
.
Join
(
self
.
origSubdir
,
"subfile"
)
me
.
mountFile
=
path
.
Join
(
me
.
mountPoint
,
name
)
me
.
mountSubdir
=
path
.
Join
(
me
.
mountPoint
,
subdir
)
me
.
mountSubfile
=
path
.
Join
(
me
.
mountSubdir
,
"subfile"
)
me
.
origFile
=
path
.
Join
(
me
.
origDir
,
name
)
me
.
origSubdir
=
path
.
Join
(
me
.
origDir
,
subdir
)
me
.
origSubfile
=
path
.
Join
(
me
.
origSubdir
,
"subfile"
)
pfs
:=
NewPassThroughFuse
(
self
.
origDir
)
self
.
connector
=
fuse
.
NewPathFileSystemConnector
(
pfs
)
self
.
connector
.
Debug
=
true
self
.
state
=
fuse
.
NewMountState
(
self
.
connector
)
self
.
state
.
Mount
(
self
.
mountPoint
)
pfs
:=
NewPassThroughFuse
(
me
.
origDir
)
me
.
connector
=
fuse
.
NewPathFileSystemConnector
(
pfs
)
me
.
connector
.
Debug
=
true
me
.
state
=
fuse
.
NewMountState
(
me
.
connector
)
me
.
state
.
Mount
(
me
.
mountPoint
)
//
self
.state.Debug = false
self
.
state
.
Debug
=
true
//
me
.state.Debug = false
me
.
state
.
Debug
=
true
fmt
.
Println
(
"Orig "
,
self
.
origDir
,
" mount "
,
self
.
mountPoint
)
fmt
.
Println
(
"Orig "
,
me
.
origDir
,
" mount "
,
me
.
mountPoint
)
// Unthreaded, but in background.
go
self
.
state
.
Loop
(
false
)
go
me
.
state
.
Loop
(
false
)
}
// Unmount and del.
func
(
self
*
testCase
)
Cleanup
()
{
func
(
me
*
testCase
)
Cleanup
()
{
fmt
.
Println
(
"Unmounting."
)
err
:=
self
.
state
.
Unmount
()
err
:=
me
.
state
.
Unmount
()
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Can't unmount a dir, err: %v"
,
err
)
me
.
tester
.
Errorf
(
"Can't unmount a dir, err: %v"
,
err
)
}
os
.
Remove
(
self
.
mountPoint
)
os
.
RemoveAll
(
self
.
origDir
)
os
.
Remove
(
me
.
mountPoint
)
os
.
RemoveAll
(
me
.
origDir
)
}
////////////////
// Utilities.
func
(
self
*
testCase
)
makeOrigSubdir
()
{
err
:=
os
.
Mkdir
(
self
.
origSubdir
,
0777
)
func
(
me
*
testCase
)
makeOrigSubdir
()
{
err
:=
os
.
Mkdir
(
me
.
origSubdir
,
0777
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"orig mkdir subdir %v"
,
err
)
me
.
tester
.
Errorf
(
"orig mkdir subdir %v"
,
err
)
}
}
func
(
self
*
testCase
)
removeMountSubdir
()
{
err
:=
os
.
RemoveAll
(
self
.
mountSubdir
)
func
(
me
*
testCase
)
removeMountSubdir
()
{
err
:=
os
.
RemoveAll
(
me
.
mountSubdir
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"orig rmdir subdir %v"
,
err
)
me
.
tester
.
Errorf
(
"orig rmdir subdir %v"
,
err
)
}
}
func
(
self
*
testCase
)
removeMountFile
()
{
os
.
Remove
(
self
.
mountFile
)
func
(
me
*
testCase
)
removeMountFile
()
{
os
.
Remove
(
me
.
mountFile
)
// ignore errors.
}
func
(
self
*
testCase
)
writeOrigFile
()
{
f
,
err
:=
os
.
Open
(
self
.
origFile
,
os
.
O_WRONLY
|
os
.
O_CREAT
,
0700
)
func
(
me
*
testCase
)
writeOrigFile
()
{
f
,
err
:=
os
.
Open
(
me
.
origFile
,
os
.
O_WRONLY
|
os
.
O_CREAT
,
0700
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Error orig open: %v"
,
err
)
me
.
tester
.
Errorf
(
"Error orig open: %v"
,
err
)
}
_
,
err
=
f
.
Write
([]
byte
(
contents
))
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Write %v"
,
err
)
me
.
tester
.
Errorf
(
"Write %v"
,
err
)
}
f
.
Close
()
}
...
...
@@ -118,36 +118,36 @@ func (self *testCase) writeOrigFile() {
////////////////
// Tests.
func
(
self
*
testCase
)
testOpenUnreadable
()
{
_
,
err
:=
os
.
Open
(
path
.
Join
(
self
.
mountPoint
,
"doesnotexist"
),
os
.
O_RDONLY
,
0
)
func
(
me
*
testCase
)
testOpenUnreadable
()
{
_
,
err
:=
os
.
Open
(
path
.
Join
(
me
.
mountPoint
,
"doesnotexist"
),
os
.
O_RDONLY
,
0
)
if
err
==
nil
{
self
.
tester
.
Errorf
(
"open non-existent should raise error"
)
me
.
tester
.
Errorf
(
"open non-existent should raise error"
)
}
}
func
(
self
*
testCase
)
testReadThroughFuse
()
{
self
.
writeOrigFile
()
func
(
me
*
testCase
)
testReadThroughFuse
()
{
me
.
writeOrigFile
()
fmt
.
Println
(
"Testing chmod."
)
err
:=
os
.
Chmod
(
self
.
mountFile
,
mode
)
err
:=
os
.
Chmod
(
me
.
mountFile
,
mode
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Chmod %v"
,
err
)
me
.
tester
.
Errorf
(
"Chmod %v"
,
err
)
}
fmt
.
Println
(
"Testing Lstat."
)
fi
,
err
:=
os
.
Lstat
(
self
.
mountFile
)
fi
,
err
:=
os
.
Lstat
(
me
.
mountFile
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Lstat %v"
,
err
)
me
.
tester
.
Errorf
(
"Lstat %v"
,
err
)
}
if
(
fi
.
Mode
&
0777
)
!=
mode
{
self
.
tester
.
Errorf
(
"Wrong mode %o != %o"
,
fi
.
Mode
,
mode
)
me
.
tester
.
Errorf
(
"Wrong mode %o != %o"
,
fi
.
Mode
,
mode
)
}
// Open (for read), read.
fmt
.
Println
(
"Testing open."
)
f
,
err
:=
os
.
Open
(
self
.
mountFile
,
os
.
O_RDONLY
,
0
)
f
,
err
:=
os
.
Open
(
me
.
mountFile
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Fuse open %v"
,
err
)
me
.
tester
.
Errorf
(
"Fuse open %v"
,
err
)
}
fmt
.
Println
(
"Testing read."
)
...
...
@@ -156,105 +156,105 @@ func (self *testCase) testReadThroughFuse() {
n
,
err
:=
f
.
Read
(
slice
)
if
len
(
slice
[
:
n
])
!=
len
(
contents
)
{
self
.
tester
.
Errorf
(
"Content error %v"
,
slice
)
me
.
tester
.
Errorf
(
"Content error %v"
,
slice
)
}
fmt
.
Println
(
"Testing close."
)
f
.
Close
()
self
.
removeMountFile
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testRemove
()
{
self
.
writeOrigFile
()
func
(
me
*
testCase
)
testRemove
()
{
me
.
writeOrigFile
()
fmt
.
Println
(
"Testing remove."
)
err
:=
os
.
Remove
(
self
.
mountFile
)
err
:=
os
.
Remove
(
me
.
mountFile
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Remove %v"
,
err
)
me
.
tester
.
Errorf
(
"Remove %v"
,
err
)
}
_
,
err
=
os
.
Lstat
(
self
.
origFile
)
_
,
err
=
os
.
Lstat
(
me
.
origFile
)
if
err
==
nil
{
self
.
tester
.
Errorf
(
"Lstat() after delete should have generated error."
)
me
.
tester
.
Errorf
(
"Lstat() after delete should have generated error."
)
}
}
func
(
self
*
testCase
)
testWriteThroughFuse
()
{
func
(
me
*
testCase
)
testWriteThroughFuse
()
{
// Create (for write), write.
self
.
tester
.
Log
(
"Testing create."
)
f
,
err
:=
os
.
Open
(
self
.
mountFile
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0644
)
me
.
tester
.
Log
(
"Testing create."
)
f
,
err
:=
os
.
Open
(
me
.
mountFile
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0644
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Fuse create/open %v"
,
err
)
me
.
tester
.
Errorf
(
"Fuse create/open %v"
,
err
)
}
self
.
tester
.
Log
(
"Testing write."
)
me
.
tester
.
Log
(
"Testing write."
)
n
,
err
:=
f
.
WriteString
(
contents
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"fuse write %v"
,
err
)
me
.
tester
.
Errorf
(
"fuse write %v"
,
err
)
}
if
n
!=
len
(
contents
)
{
self
.
tester
.
Errorf
(
"Write mismatch: %v of %v"
,
n
,
len
(
contents
))
me
.
tester
.
Errorf
(
"Write mismatch: %v of %v"
,
n
,
len
(
contents
))
}
fi
,
err
:=
os
.
Lstat
(
self
.
origFile
)
fi
,
err
:=
os
.
Lstat
(
me
.
origFile
)
if
fi
.
Mode
&
0777
!=
0644
{
self
.
tester
.
Errorf
(
"create mode error %o"
,
fi
.
Mode
&
0777
)
me
.
tester
.
Errorf
(
"create mode error %o"
,
fi
.
Mode
&
0777
)
}
f
,
err
=
os
.
Open
(
self
.
origFile
,
os
.
O_RDONLY
,
0
)
f
,
err
=
os
.
Open
(
me
.
origFile
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"orig open %v"
,
err
)
me
.
tester
.
Errorf
(
"orig open %v"
,
err
)
}
var
buf
[
1024
]
byte
slice
:=
buf
[
:
]
n
,
err
=
f
.
Read
(
slice
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"orig read %v"
,
err
)
me
.
tester
.
Errorf
(
"orig read %v"
,
err
)
}
self
.
tester
.
Log
(
"Orig contents"
,
slice
[
:
n
])
me
.
tester
.
Log
(
"Orig contents"
,
slice
[
:
n
])
if
string
(
slice
[
:
n
])
!=
contents
{
self
.
tester
.
Errorf
(
"write contents error %v"
,
slice
[
:
n
])
me
.
tester
.
Errorf
(
"write contents error %v"
,
slice
[
:
n
])
}
f
.
Close
()
self
.
removeMountFile
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testMkdirRmdir
()
{
func
(
me
*
testCase
)
testMkdirRmdir
()
{
// Mkdir/Rmdir.
err
:=
os
.
Mkdir
(
self
.
mountSubdir
,
0777
)
err
:=
os
.
Mkdir
(
me
.
mountSubdir
,
0777
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"mount mkdir"
,
err
)
me
.
tester
.
Errorf
(
"mount mkdir"
,
err
)
}
fi
,
err
:=
os
.
Lstat
(
self
.
origSubdir
)
fi
,
err
:=
os
.
Lstat
(
me
.
origSubdir
)
if
!
fi
.
IsDirectory
()
{
self
.
tester
.
Errorf
(
"Not a directory: %o"
,
fi
.
Mode
)
me
.
tester
.
Errorf
(
"Not a directory: %o"
,
fi
.
Mode
)
}
err
=
os
.
Remove
(
self
.
mountSubdir
)
err
=
os
.
Remove
(
me
.
mountSubdir
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"rmdir %v"
,
err
)
me
.
tester
.
Errorf
(
"rmdir %v"
,
err
)
}
}
func
(
self
*
testCase
)
testLink
()
{
self
.
tester
.
Log
(
"Testing hard links."
)
self
.
writeOrigFile
()
err
:=
os
.
Mkdir
(
self
.
origSubdir
,
0777
)
func
(
me
*
testCase
)
testLink
()
{
me
.
tester
.
Log
(
"Testing hard links."
)
me
.
writeOrigFile
()
err
:=
os
.
Mkdir
(
me
.
origSubdir
,
0777
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"mount mkdir"
,
err
)
me
.
tester
.
Errorf
(
"mount mkdir"
,
err
)
}
// Link.
err
=
os
.
Link
(
self
.
mountFile
,
self
.
mountSubfile
)
err
=
os
.
Link
(
me
.
mountFile
,
me
.
mountSubfile
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"mount link %v"
,
err
)
me
.
tester
.
Errorf
(
"mount link %v"
,
err
)
}
fi
,
err
:=
os
.
Lstat
(
self
.
mountFile
)
fi
,
err
:=
os
.
Lstat
(
me
.
mountFile
)
if
fi
.
Nlink
!=
2
{
self
.
tester
.
Errorf
(
"Expect 2 links: %v"
,
fi
)
me
.
tester
.
Errorf
(
"Expect 2 links: %v"
,
fi
)
}
f
,
err
:=
os
.
Open
(
self
.
mountSubfile
,
os
.
O_RDONLY
,
0
)
f
,
err
:=
os
.
Open
(
me
.
mountSubfile
,
os
.
O_RDONLY
,
0
)
var
buf
[
1024
]
byte
slice
:=
buf
[
:
]
...
...
@@ -263,123 +263,123 @@ func (self *testCase) testLink() {
strContents
:=
string
(
slice
[
:
n
])
if
strContents
!=
contents
{
self
.
tester
.
Errorf
(
"Content error: %v"
,
slice
[
:
n
])
me
.
tester
.
Errorf
(
"Content error: %v"
,
slice
[
:
n
])
}
self
.
removeMountSubdir
()
self
.
removeMountFile
()
me
.
removeMountSubdir
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testSymlink
()
{
self
.
tester
.
Log
(
"testing symlink/readlink."
)
self
.
writeOrigFile
()
func
(
me
*
testCase
)
testSymlink
()
{
me
.
tester
.
Log
(
"testing symlink/readlink."
)
me
.
writeOrigFile
()
linkFile
:=
"symlink-file"
orig
:=
"hello.txt"
err
:=
os
.
Symlink
(
orig
,
path
.
Join
(
self
.
mountPoint
,
linkFile
))
defer
os
.
Remove
(
path
.
Join
(
self
.
mountPoint
,
linkFile
))
defer
self
.
removeMountFile
()
err
:=
os
.
Symlink
(
orig
,
path
.
Join
(
me
.
mountPoint
,
linkFile
))
defer
os
.
Remove
(
path
.
Join
(
me
.
mountPoint
,
linkFile
))
defer
me
.
removeMountFile
()
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"symlink %v"
,
err
)
me
.
tester
.
Errorf
(
"symlink %v"
,
err
)
}
origLink
:=
path
.
Join
(
self
.
origDir
,
linkFile
)
origLink
:=
path
.
Join
(
me
.
origDir
,
linkFile
)
fi
,
err
:=
os
.
Lstat
(
origLink
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"link lstat %v"
,
err
)
me
.
tester
.
Errorf
(
"link lstat %v"
,
err
)
return
}
if
!
fi
.
IsSymlink
()
{
self
.
tester
.
Errorf
(
"not a symlink: %o"
,
fi
.
Mode
)
me
.
tester
.
Errorf
(
"not a symlink: %o"
,
fi
.
Mode
)
return
}
read
,
err
:=
os
.
Readlink
(
path
.
Join
(
self
.
mountPoint
,
linkFile
))
read
,
err
:=
os
.
Readlink
(
path
.
Join
(
me
.
mountPoint
,
linkFile
))
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"orig readlink %v"
,
err
)
me
.
tester
.
Errorf
(
"orig readlink %v"
,
err
)
return
}
if
read
!=
orig
{
self
.
tester
.
Errorf
(
"unexpected symlink value '%v'"
,
read
)
me
.
tester
.
Errorf
(
"unexpected symlink value '%v'"
,
read
)
}
}
func
(
self
*
testCase
)
testRename
()
{
self
.
tester
.
Log
(
"Testing rename."
)
self
.
writeOrigFile
()
self
.
makeOrigSubdir
()
func
(
me
*
testCase
)
testRename
()
{
me
.
tester
.
Log
(
"Testing rename."
)
me
.
writeOrigFile
()
me
.
makeOrigSubdir
()
err
:=
os
.
Rename
(
self
.
mountFile
,
self
.
mountSubfile
)
err
:=
os
.
Rename
(
me
.
mountFile
,
me
.
mountSubfile
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"rename %v"
,
err
)
me
.
tester
.
Errorf
(
"rename %v"
,
err
)
}
if
FileExists
(
self
.
origFile
)
{
self
.
tester
.
Errorf
(
"original %v still exists."
,
self
.
origFile
)
if
FileExists
(
me
.
origFile
)
{
me
.
tester
.
Errorf
(
"original %v still exists."
,
me
.
origFile
)
}
if
!
FileExists
(
self
.
origSubfile
)
{
self
.
tester
.
Errorf
(
"destination %v does not exist."
,
self
.
origSubfile
)
if
!
FileExists
(
me
.
origSubfile
)
{
me
.
tester
.
Errorf
(
"destination %v does not exist."
,
me
.
origSubfile
)
}
self
.
removeMountSubdir
()
me
.
removeMountSubdir
()
}
func
(
self
*
testCase
)
testAccess
()
{
self
.
writeOrigFile
()
err
:=
os
.
Chmod
(
self
.
origFile
,
0
)
func
(
me
*
testCase
)
testAccess
()
{
me
.
writeOrigFile
()
err
:=
os
.
Chmod
(
me
.
origFile
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"chmod %v"
,
err
)
me
.
tester
.
Errorf
(
"chmod %v"
,
err
)
}
// Ugh - copied from unistd.h
const
W_OK
uint32
=
2
errCode
:=
syscall
.
Access
(
self
.
mountFile
,
W_OK
)
errCode
:=
syscall
.
Access
(
me
.
mountFile
,
W_OK
)
if
errCode
!=
syscall
.
EACCES
{
self
.
tester
.
Errorf
(
"Expected EACCES for non-writable, %v %v"
,
errCode
,
syscall
.
EACCES
)
me
.
tester
.
Errorf
(
"Expected EACCES for non-writable, %v %v"
,
errCode
,
syscall
.
EACCES
)
}
err
=
os
.
Chmod
(
self
.
origFile
,
0222
)
err
=
os
.
Chmod
(
me
.
origFile
,
0222
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"chmod %v"
,
err
)
me
.
tester
.
Errorf
(
"chmod %v"
,
err
)
}
errCode
=
syscall
.
Access
(
self
.
mountFile
,
W_OK
)
errCode
=
syscall
.
Access
(
me
.
mountFile
,
W_OK
)
if
errCode
!=
0
{
self
.
tester
.
Errorf
(
"Expected no error code for writable. %v"
,
errCode
)
me
.
tester
.
Errorf
(
"Expected no error code for writable. %v"
,
errCode
)
}
self
.
removeMountFile
()
self
.
removeMountFile
()
me
.
removeMountFile
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testMknod
()
{
self
.
tester
.
Log
(
"Testing mknod."
)
errNo
:=
syscall
.
Mknod
(
self
.
mountFile
,
syscall
.
S_IFIFO
|
0777
,
0
)
func
(
me
*
testCase
)
testMknod
()
{
me
.
tester
.
Log
(
"Testing mknod."
)
errNo
:=
syscall
.
Mknod
(
me
.
mountFile
,
syscall
.
S_IFIFO
|
0777
,
0
)
if
errNo
!=
0
{
self
.
tester
.
Errorf
(
"Mknod %v"
,
errNo
)
me
.
tester
.
Errorf
(
"Mknod %v"
,
errNo
)
}
fi
,
_
:=
os
.
Lstat
(
self
.
origFile
)
fi
,
_
:=
os
.
Lstat
(
me
.
origFile
)
if
fi
==
nil
||
!
fi
.
IsFifo
()
{
self
.
tester
.
Errorf
(
"Expected FIFO filetype."
)
me
.
tester
.
Errorf
(
"Expected FIFO filetype."
)
}
self
.
removeMountFile
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testReaddir
()
{
self
.
tester
.
Log
(
"Testing readdir."
)
self
.
writeOrigFile
()
self
.
makeOrigSubdir
()
func
(
me
*
testCase
)
testReaddir
()
{
me
.
tester
.
Log
(
"Testing readdir."
)
me
.
writeOrigFile
()
me
.
makeOrigSubdir
()
dir
,
err
:=
os
.
Open
(
self
.
mountPoint
,
os
.
O_RDONLY
,
0
)
dir
,
err
:=
os
.
Open
(
me
.
mountPoint
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
me
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
return
}
infos
,
err
:=
dir
.
Readdir
(
10
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"readdir err %v"
,
err
)
me
.
tester
.
Errorf
(
"readdir err %v"
,
err
)
}
wanted
:=
map
[
string
]
bool
{
...
...
@@ -387,46 +387,46 @@ func (self *testCase) testReaddir() {
"subdir"
:
true
,
}
if
len
(
wanted
)
!=
len
(
infos
)
{
self
.
tester
.
Errorf
(
"Length mismatch %v"
,
infos
)
me
.
tester
.
Errorf
(
"Length mismatch %v"
,
infos
)
}
else
{
for
_
,
v
:=
range
infos
{
_
,
ok
:=
wanted
[
v
.
Name
]
if
!
ok
{
self
.
tester
.
Errorf
(
"Unexpected name %v"
,
v
.
Name
)
me
.
tester
.
Errorf
(
"Unexpected name %v"
,
v
.
Name
)
}
}
}
dir
.
Close
()
self
.
removeMountSubdir
()
self
.
removeMountFile
()
me
.
removeMountSubdir
()
me
.
removeMountFile
()
}
func
(
self
*
testCase
)
testFSync
()
{
self
.
tester
.
Log
(
"Testing fsync."
)
self
.
writeOrigFile
()
func
(
me
*
testCase
)
testFSync
()
{
me
.
tester
.
Log
(
"Testing fsync."
)
me
.
writeOrigFile
()
f
,
err
:=
os
.
Open
(
self
.
mountFile
,
os
.
O_WRONLY
,
0
)
f
,
err
:=
os
.
Open
(
me
.
mountFile
,
os
.
O_WRONLY
,
0
)
_
,
err
=
f
.
WriteString
(
"hello there"
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"writestring %v"
,
err
)
me
.
tester
.
Errorf
(
"writestring %v"
,
err
)
}
// How to really test fsync ?
errNo
:=
syscall
.
Fsync
(
f
.
Fd
())
if
errNo
!=
0
{
self
.
tester
.
Errorf
(
"fsync returned %v"
,
errNo
)
me
.
tester
.
Errorf
(
"fsync returned %v"
,
errNo
)
}
f
.
Close
()
}
func
(
self
*
testCase
)
testLargeRead
()
{
self
.
tester
.
Log
(
"Testing large read."
)
name
:=
path
.
Join
(
self
.
origDir
,
"large"
)
func
(
me
*
testCase
)
testLargeRead
()
{
me
.
tester
.
Log
(
"Testing large read."
)
name
:=
path
.
Join
(
me
.
origDir
,
"large"
)
f
,
err
:=
os
.
Open
(
name
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0777
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"open write err %v"
,
err
)
me
.
tester
.
Errorf
(
"open write err %v"
,
err
)
}
b
:=
bytes
.
NewBuffer
(
nil
)
...
...
@@ -439,40 +439,40 @@ func (self *testCase) testLargeRead() {
slice
:=
b
.
Bytes
()
n
,
err
:=
f
.
Write
(
slice
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"write err %v %v"
,
err
,
n
)
me
.
tester
.
Errorf
(
"write err %v %v"
,
err
,
n
)
}
err
=
f
.
Close
()
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"close err %v"
,
err
)
me
.
tester
.
Errorf
(
"close err %v"
,
err
)
}
// Read in one go.
g
,
err
:=
os
.
Open
(
path
.
Join
(
self
.
mountPoint
,
"large"
),
os
.
O_RDONLY
,
0
)
g
,
err
:=
os
.
Open
(
path
.
Join
(
me
.
mountPoint
,
"large"
),
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"open err %v"
,
err
)
me
.
tester
.
Errorf
(
"open err %v"
,
err
)
}
readSlice
:=
make
([]
byte
,
len
(
slice
))
m
,
err
:=
g
.
Read
(
readSlice
)
if
m
!=
n
{
self
.
tester
.
Errorf
(
"read mismatch %v %v"
,
m
,
n
)
me
.
tester
.
Errorf
(
"read mismatch %v %v"
,
m
,
n
)
}
for
i
,
v
:=
range
readSlice
{
if
slice
[
i
]
!=
v
{
self
.
tester
.
Errorf
(
"char mismatch %v %v %v"
,
i
,
slice
[
i
],
v
)
me
.
tester
.
Errorf
(
"char mismatch %v %v %v"
,
i
,
slice
[
i
],
v
)
break
}
}
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"read mismatch %v"
,
err
)
me
.
tester
.
Errorf
(
"read mismatch %v"
,
err
)
}
g
.
Close
()
// Read in chunks
g
,
err
=
os
.
Open
(
path
.
Join
(
self
.
mountPoint
,
"large"
),
os
.
O_RDONLY
,
0
)
g
,
err
=
os
.
Open
(
path
.
Join
(
me
.
mountPoint
,
"large"
),
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"open err %v"
,
err
)
me
.
tester
.
Errorf
(
"open err %v"
,
err
)
}
readSlice
=
make
([]
byte
,
4096
)
total
:=
0
...
...
@@ -482,13 +482,13 @@ func (self *testCase) testLargeRead() {
break
}
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"read err %v %v"
,
err
,
m
)
me
.
tester
.
Errorf
(
"read err %v %v"
,
err
,
m
)
break
}
total
+=
m
}
if
total
!=
len
(
slice
)
{
self
.
tester
.
Errorf
(
"slice error %d"
,
total
)
me
.
tester
.
Errorf
(
"slice error %d"
,
total
)
}
g
.
Close
()
...
...
@@ -508,13 +508,13 @@ func randomLengthString(length int) string {
}
func
(
self
*
testCase
)
testLargeDirRead
()
{
self
.
tester
.
Log
(
"Testing large readdir."
)
func
(
me
*
testCase
)
testLargeDirRead
()
{
me
.
tester
.
Log
(
"Testing large readdir."
)
created
:=
100
names
:=
make
([]
string
,
created
)
subdir
:=
path
.
Join
(
self
.
origDir
,
"readdirSubdir"
)
subdir
:=
path
.
Join
(
me
.
origDir
,
"readdirSubdir"
)
os
.
Mkdir
(
subdir
,
0700
)
longname
:=
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
...
...
@@ -529,7 +529,7 @@ func (self *testCase) testLargeDirRead() {
f
,
err
:=
os
.
Open
(
name
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0777
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"open write err %v"
,
err
)
me
.
tester
.
Errorf
(
"open write err %v"
,
err
)
break
}
f
.
WriteString
(
"bla"
)
...
...
@@ -538,9 +538,9 @@ func (self *testCase) testLargeDirRead() {
names
[
i
]
=
name
}
dir
,
err
:=
os
.
Open
(
path
.
Join
(
self
.
mountPoint
,
"readdirSubdir"
),
os
.
O_RDONLY
,
0
)
dir
,
err
:=
os
.
Open
(
path
.
Join
(
me
.
mountPoint
,
"readdirSubdir"
),
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"dirread %v"
,
err
)
me
.
tester
.
Errorf
(
"dirread %v"
,
err
)
}
// Chunked read.
total
:=
0
...
...
@@ -548,7 +548,7 @@ func (self *testCase) testLargeDirRead() {
for
{
namesRead
,
err
:=
dir
.
Readdirnames
(
200
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"readdir err %v %v"
,
err
,
namesRead
)
me
.
tester
.
Errorf
(
"readdir err %v %v"
,
err
,
namesRead
)
}
if
len
(
namesRead
)
==
0
{
...
...
@@ -561,12 +561,12 @@ func (self *testCase) testLargeDirRead() {
}
if
total
!=
created
{
self
.
tester
.
Errorf
(
"readdir mismatch got %v wanted %v"
,
total
,
created
)
me
.
tester
.
Errorf
(
"readdir mismatch got %v wanted %v"
,
total
,
created
)
}
for
k
,
_
:=
range
nameSet
{
_
,
ok
:=
readSet
[
k
]
if
!
ok
{
self
.
tester
.
Errorf
(
"Name %v not found in output"
,
k
)
me
.
tester
.
Errorf
(
"Name %v not found in output"
,
k
)
}
}
...
...
examplelib/stackfs.go
View file @
7c3c1e41
...
...
@@ -25,23 +25,23 @@ type subFsInfo struct {
Attr
fuse
.
Attr
}
func
(
self
*
subFsInfo
)
getGlobalNode
(
node
uint64
)
(
uint64
,
bool
)
{
self
.
ParentNodeIdsLock
.
RLock
()
defer
self
.
ParentNodeIdsLock
.
RUnlock
()
global
,
ok
:=
self
.
ParentNodeIds
[
node
]
func
(
me
*
subFsInfo
)
getGlobalNode
(
node
uint64
)
(
uint64
,
bool
)
{
me
.
ParentNodeIdsLock
.
RLock
()
defer
me
.
ParentNodeIdsLock
.
RUnlock
()
global
,
ok
:=
me
.
ParentNodeIds
[
node
]
return
global
,
ok
}
func
(
self
*
subFsInfo
)
dropGlobalNode
(
node
uint64
)
{
self
.
ParentNodeIdsLock
.
Lock
()
defer
self
.
ParentNodeIdsLock
.
Unlock
()
self
.
ParentNodeIds
[
node
]
=
0
,
false
func
(
me
*
subFsInfo
)
dropGlobalNode
(
node
uint64
)
{
me
.
ParentNodeIdsLock
.
Lock
()
defer
me
.
ParentNodeIdsLock
.
Unlock
()
me
.
ParentNodeIds
[
node
]
=
0
,
false
}
func
(
self
*
subFsInfo
)
addGlobalNode
(
local
uint64
,
global
uint64
)
{
self
.
ParentNodeIdsLock
.
Lock
()
defer
self
.
ParentNodeIdsLock
.
Unlock
()
self
.
ParentNodeIds
[
local
]
=
global
func
(
me
*
subFsInfo
)
addGlobalNode
(
local
uint64
,
global
uint64
)
{
me
.
ParentNodeIdsLock
.
Lock
()
defer
me
.
ParentNodeIdsLock
.
Unlock
()
me
.
ParentNodeIds
[
local
]
=
global
}
...
...
@@ -56,8 +56,8 @@ type subInodeData struct {
LookupCount
int
}
func
(
self
*
subInodeData
)
Deletable
()
bool
{
return
self
.
LookupCount
<=
0
&&
(
self
.
NodeId
!=
fuse
.
FUSE_ROOT_ID
||
self
.
SubFs
==
nil
)
func
(
me
*
subInodeData
)
Deletable
()
bool
{
return
me
.
LookupCount
<=
0
&&
(
me
.
NodeId
!=
fuse
.
FUSE_ROOT_ID
||
me
.
SubFs
==
nil
)
}
////////////////////////////////////////////////////////////////
...
...
@@ -72,7 +72,7 @@ func (self *subInodeData) Deletable() bool {
// Each of these directories should be RawFileSystem instances. This
// class takes care of the mapping between global inode ids and inode ids
// of each sub-FUSE filesystem.
//
//
// No files or directories may be created in the toplevel dir. Instead,
// the daemon should issue AddFileSystem() and RemoveFileSystem()
// methods internally. This could be done in response to writes in a
...
...
@@ -94,44 +94,44 @@ type SubmountFileSystemOptions struct {
}
////////////////
// Routines that do locking.
// Routines that do locking.
func
(
self
*
SubmountFileSystem
)
registerLookup
(
subInode
uint64
,
subfs
*
subFsInfo
)
(
globalNodeId
uint64
)
{
func
(
me
*
SubmountFileSystem
)
registerLookup
(
subInode
uint64
,
subfs
*
subFsInfo
)
(
globalNodeId
uint64
)
{
globalNodeId
,
ok
:=
subfs
.
getGlobalNode
(
subInode
)
var
globalNode
*
subInodeData
=
nil
self
.
nodeMapLock
.
Lock
()
defer
self
.
nodeMapLock
.
Unlock
()
me
.
nodeMapLock
.
Lock
()
defer
me
.
nodeMapLock
.
Unlock
()
if
ok
{
globalNode
=
self
.
nodeMap
[
globalNodeId
]
globalNode
=
me
.
nodeMap
[
globalNodeId
]
}
else
{
globalNodeId
=
self
.
nextFreeInode
self
.
nextFreeInode
++
globalNodeId
=
me
.
nextFreeInode
me
.
nextFreeInode
++
globalNode
=
&
subInodeData
{
SubFs
:
subfs
,
NodeId
:
subInode
,
}
self
.
nodeMap
[
globalNodeId
]
=
globalNode
me
.
nodeMap
[
globalNodeId
]
=
globalNode
subfs
.
addGlobalNode
(
subInode
,
globalNodeId
)
}
globalNode
.
LookupCount
++
return
globalNodeId
}
func
(
self
*
SubmountFileSystem
)
getSubFs
(
local
uint64
)
(
nodeid
uint64
,
subfs
*
subFsInfo
)
{
self
.
nodeMapLock
.
RLock
()
defer
self
.
nodeMapLock
.
RUnlock
()
data
:=
self
.
nodeMap
[
local
]
func
(
me
*
SubmountFileSystem
)
getSubFs
(
local
uint64
)
(
nodeid
uint64
,
subfs
*
subFsInfo
)
{
me
.
nodeMapLock
.
RLock
()
defer
me
.
nodeMapLock
.
RUnlock
()
data
:=
me
.
nodeMap
[
local
]
return
data
.
NodeId
,
data
.
SubFs
}
func
(
self
*
SubmountFileSystem
)
addFileSystem
(
name
string
,
fs
fuse
.
RawFileSystem
,
attr
fuse
.
Attr
)
bool
{
self
.
toplevelEntriesLock
.
Lock
()
defer
self
.
toplevelEntriesLock
.
Unlock
()
_
,
ok
:=
self
.
toplevelEntries
[
name
]
func
(
me
*
SubmountFileSystem
)
addFileSystem
(
name
string
,
fs
fuse
.
RawFileSystem
,
attr
fuse
.
Attr
)
bool
{
me
.
toplevelEntriesLock
.
Lock
()
defer
me
.
toplevelEntriesLock
.
Unlock
()
_
,
ok
:=
me
.
toplevelEntries
[
name
]
if
ok
{
return
false
}
...
...
@@ -142,44 +142,44 @@ func (self *SubmountFileSystem) addFileSystem(name string, fs fuse.RawFileSystem
Attr
:
attr
,
}
self
.
toplevelEntries
[
name
]
=
subfs
me
.
toplevelEntries
[
name
]
=
subfs
self
.
nodeMapLock
.
Lock
()
defer
self
.
nodeMapLock
.
Unlock
()
me
.
nodeMapLock
.
Lock
()
defer
me
.
nodeMapLock
.
Unlock
()
self
.
nodeMap
[
self
.
nextFreeInode
]
=
&
subInodeData
{
me
.
nodeMap
[
me
.
nextFreeInode
]
=
&
subInodeData
{
SubFs
:
subfs
,
NodeId
:
fuse
.
FUSE_ROOT_ID
,
LookupCount
:
0
,
}
subfs
.
ParentNodeIds
=
map
[
uint64
]
uint64
{
fuse
.
FUSE_ROOT_ID
:
self
.
nextFreeInode
}
subfs
.
GlobalNodeId
=
self
.
nextFreeInode
subfs
.
ParentNodeIds
=
map
[
uint64
]
uint64
{
fuse
.
FUSE_ROOT_ID
:
me
.
nextFreeInode
}
subfs
.
GlobalNodeId
=
me
.
nextFreeInode
subfs
.
Attr
.
Mode
|=
fuse
.
S_IFDIR
subfs
.
Attr
.
Ino
=
self
.
nextFreeInode
subfs
.
Attr
.
Ino
=
me
.
nextFreeInode
self
.
nextFreeInode
++
me
.
nextFreeInode
++
return
true
}
func
(
self
*
SubmountFileSystem
)
removeFileSystem
(
name
string
)
*
subFsInfo
{
self
.
toplevelEntriesLock
.
Lock
()
defer
self
.
toplevelEntriesLock
.
Unlock
()
func
(
me
*
SubmountFileSystem
)
removeFileSystem
(
name
string
)
*
subFsInfo
{
me
.
toplevelEntriesLock
.
Lock
()
defer
me
.
toplevelEntriesLock
.
Unlock
()
subfs
,
ok
:=
self
.
toplevelEntries
[
name
]
subfs
,
ok
:=
me
.
toplevelEntries
[
name
]
if
!
ok
{
return
nil
}
self
.
toplevelEntries
[
name
]
=
nil
,
false
me
.
toplevelEntries
[
name
]
=
nil
,
false
// We leave the keys of node map as is, since the kernel may
// still issue requests with nodeids in it.
self
.
nodeMapLock
.
Lock
()
defer
self
.
nodeMapLock
.
Unlock
()
me
.
nodeMapLock
.
Lock
()
defer
me
.
nodeMapLock
.
Unlock
()
for
_
,
v
:=
range
self
.
nodeMap
{
for
_
,
v
:=
range
me
.
nodeMap
{
if
v
.
SubFs
==
subfs
{
v
.
SubFs
=
nil
}
...
...
@@ -188,15 +188,15 @@ func (self *SubmountFileSystem) removeFileSystem(name string) *subFsInfo {
return
subfs
}
func
(
self
*
SubmountFileSystem
)
listFileSystems
()
([]
string
,
[]
uint32
)
{
self
.
toplevelEntriesLock
.
RLock
()
defer
self
.
toplevelEntriesLock
.
RUnlock
()
func
(
me
*
SubmountFileSystem
)
listFileSystems
()
([]
string
,
[]
uint32
)
{
me
.
toplevelEntriesLock
.
RLock
()
defer
me
.
toplevelEntriesLock
.
RUnlock
()
names
:=
make
([]
string
,
len
(
self
.
toplevelEntries
))
modes
:=
make
([]
uint32
,
len
(
self
.
toplevelEntries
))
names
:=
make
([]
string
,
len
(
me
.
toplevelEntries
))
modes
:=
make
([]
uint32
,
len
(
me
.
toplevelEntries
))
j
:=
0
for
name
,
entry
:=
range
self
.
toplevelEntries
{
for
name
,
entry
:=
range
me
.
toplevelEntries
{
names
[
j
]
=
name
modes
[
j
]
=
entry
.
Attr
.
Mode
j
++
...
...
@@ -204,21 +204,21 @@ func (self *SubmountFileSystem) listFileSystems() ([]string, []uint32) {
return
names
,
modes
}
func
(
self
*
SubmountFileSystem
)
lookupRoot
(
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
self
.
toplevelEntriesLock
.
RLock
()
subfs
,
ok
:=
self
.
toplevelEntries
[
name
]
self
.
toplevelEntriesLock
.
RUnlock
()
func
(
me
*
SubmountFileSystem
)
lookupRoot
(
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
me
.
toplevelEntriesLock
.
RLock
()
subfs
,
ok
:=
me
.
toplevelEntries
[
name
]
me
.
toplevelEntriesLock
.
RUnlock
()
if
!
ok
{
out
=
new
(
fuse
.
EntryOut
)
out
.
NodeId
=
0
fuse
.
SplitNs
(
self
.
Options
.
NegativeTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
fuse
.
SplitNs
(
me
.
Options
.
NegativeTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
return
nil
,
fuse
.
ENOENT
}
self
.
nodeMapLock
.
RLock
()
dentry
,
ok
:=
self
.
nodeMap
[
subfs
.
GlobalNodeId
]
self
.
nodeMapLock
.
RUnlock
()
me
.
nodeMapLock
.
RLock
()
dentry
,
ok
:=
me
.
nodeMap
[
subfs
.
GlobalNodeId
]
me
.
nodeMapLock
.
RUnlock
()
if
!
ok
{
panic
(
fmt
.
Sprintf
(
"unknown toplevel node %d"
,
subfs
.
GlobalNodeId
))
...
...
@@ -230,22 +230,22 @@ func (self *SubmountFileSystem) lookupRoot(name string) (out *fuse.EntryOut, cod
out
.
NodeId
=
subfs
.
GlobalNodeId
out
.
Attr
=
subfs
.
Attr
fuse
.
SplitNs
(
self
.
Options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
fuse
.
SplitNs
(
self
.
Options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
fuse
.
SplitNs
(
me
.
Options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
fuse
.
SplitNs
(
me
.
Options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
return
out
,
fuse
.
OK
}
func
(
self
*
SubmountFileSystem
)
forget
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
ForgetIn
)
*
subInodeData
{
self
.
nodeMapLock
.
Lock
()
defer
self
.
nodeMapLock
.
Unlock
()
func
(
me
*
SubmountFileSystem
)
forget
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
ForgetIn
)
*
subInodeData
{
me
.
nodeMapLock
.
Lock
()
defer
me
.
nodeMapLock
.
Unlock
()
subNodeData
:=
self
.
nodeMap
[
h
.
NodeId
]
subNodeData
:=
me
.
nodeMap
[
h
.
NodeId
]
globalNodeId
:=
h
.
NodeId
subNodeData
.
LookupCount
-=
int
(
input
.
Nlookup
)
if
subNodeData
.
Deletable
()
{
self
.
nodeMap
[
globalNodeId
]
=
nil
,
false
me
.
nodeMap
[
globalNodeId
]
=
nil
,
false
if
subNodeData
.
SubFs
!=
nil
{
subNodeData
.
SubFs
.
dropGlobalNode
(
subNodeData
.
NodeId
)
}
...
...
@@ -254,29 +254,29 @@ func (self *SubmountFileSystem) forget(h *fuse.InHeader, input *fuse.ForgetIn) *
}
////////////////////////////////////////////////////////////////
// Functions below should not need locking primitives.
// Functions below should not need locking primitives.
// Caller should init after this returns successfully.
func
(
self
*
SubmountFileSystem
)
AddFileSystem
(
name
string
,
fs
fuse
.
RawFileSystem
,
attr
fuse
.
Attr
)
bool
{
ok
:=
self
.
addFileSystem
(
name
,
fs
,
attr
)
func
(
me
*
SubmountFileSystem
)
AddFileSystem
(
name
string
,
fs
fuse
.
RawFileSystem
,
attr
fuse
.
Attr
)
bool
{
ok
:=
me
.
addFileSystem
(
name
,
fs
,
attr
)
return
ok
}
// Caller should call destroy.
func
(
self
*
SubmountFileSystem
)
RemoveFileSystem
(
name
string
)
fuse
.
RawFileSystem
{
subfs
:=
self
.
removeFileSystem
(
name
)
func
(
me
*
SubmountFileSystem
)
RemoveFileSystem
(
name
string
)
fuse
.
RawFileSystem
{
subfs
:=
me
.
removeFileSystem
(
name
)
if
subfs
!=
nil
{
return
subfs
.
Fs
}
return
nil
}
func
(
self
*
SubmountFileSystem
)
Lookup
(
h
*
fuse
.
InHeader
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Lookup
(
h
*
fuse
.
InHeader
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
if
h
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
return
self
.
lookupRoot
(
name
)
return
me
.
lookupRoot
(
name
)
}
subInode
,
subfs
:=
self
.
getSubFs
(
h
.
NodeId
)
subInode
,
subfs
:=
me
.
getSubFs
(
h
.
NodeId
)
if
subInode
==
0
{
panic
(
"parent unknown"
)
}
...
...
@@ -289,13 +289,13 @@ func (self *SubmountFileSystem) Lookup(h *fuse.InHeader, name string) (out *fuse
return
out
,
code
}
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Forget
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
ForgetIn
)
{
func
(
me
*
SubmountFileSystem
)
Forget
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
ForgetIn
)
{
if
h
.
NodeId
!=
fuse
.
FUSE_ROOT_ID
{
subNodeData
:=
self
.
forget
(
h
,
input
)
subNodeData
:=
me
.
forget
(
h
,
input
)
if
subNodeData
!=
nil
&&
subNodeData
.
SubFs
!=
nil
{
h
.
NodeId
=
subNodeData
.
NodeId
subNodeData
.
SubFs
.
Fs
.
Forget
(
h
,
input
)
...
...
@@ -313,25 +313,25 @@ func NewSubmountFileSystem() *SubmountFileSystem {
}
// What to do about sub fs init's ?
func
(
self
*
SubmountFileSystem
)
Init
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
InitIn
)
(
*
fuse
.
InitOut
,
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Init
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
InitIn
)
(
*
fuse
.
InitOut
,
fuse
.
Status
)
{
return
new
(
fuse
.
InitOut
),
fuse
.
OK
}
func
(
self
*
SubmountFileSystem
)
Destroy
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
InitIn
)
{
for
_
,
v
:=
range
self
.
toplevelEntries
{
func
(
me
*
SubmountFileSystem
)
Destroy
(
h
*
fuse
.
InHeader
,
input
*
fuse
.
InitIn
)
{
for
_
,
v
:=
range
me
.
toplevelEntries
{
v
.
Fs
.
Destroy
(
h
,
input
)
}
}
func
(
self
*
SubmountFileSystem
)
GetAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
GetAttrIn
)
(
out
*
fuse
.
AttrOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
GetAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
GetAttrIn
)
(
out
*
fuse
.
AttrOut
,
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
out
:=
new
(
fuse
.
AttrOut
)
// TODO - what to answer for this?
out
.
Attr
.
Mode
=
fuse
.
S_IFDIR
|
0755
return
out
,
fuse
.
OK
}
subId
,
subfs
:=
self
.
getSubFs
(
header
.
NodeId
)
subId
,
subfs
:=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -352,9 +352,9 @@ func (self *SubmountFileSystem) GetAttr(header *fuse.InHeader, input *fuse.GetAt
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Open
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
OpenIn
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseFile
,
status
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Open
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
OpenIn
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseFile
,
status
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
0
,
nil
,
fuse
.
ENOENT
}
...
...
@@ -362,9 +362,9 @@ func (self *SubmountFileSystem) Open(header *fuse.InHeader, input *fuse.OpenIn)
return
subfs
.
Fs
.
Open
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
SetAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
SetAttrIn
)
(
out
*
fuse
.
AttrOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
SetAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
SetAttrIn
)
(
out
*
fuse
.
AttrOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -376,18 +376,18 @@ func (self *SubmountFileSystem) SetAttr(header *fuse.InHeader, input *fuse.SetAt
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Readlink
(
header
*
fuse
.
InHeader
)
(
out
[]
byte
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Readlink
(
header
*
fuse
.
InHeader
)
(
out
[]
byte
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
return
subfs
.
Fs
.
Readlink
(
header
)
}
func
(
self
*
SubmountFileSystem
)
Mknod
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
MknodIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Mknod
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
MknodIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -395,20 +395,20 @@ func (self *SubmountFileSystem) Mknod(header *fuse.InHeader, input *fuse.MknodIn
out
,
code
=
subfs
.
Fs
.
Mknod
(
header
,
input
,
name
)
if
out
!=
nil
{
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
Attr
.
Ino
=
out
.
NodeId
}
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Mkdir
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
MkdirIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Mkdir
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
MkdirIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
nil
,
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -416,20 +416,20 @@ func (self *SubmountFileSystem) Mkdir(header *fuse.InHeader, input *fuse.MkdirIn
out
,
code
=
subfs
.
Fs
.
Mkdir
(
header
,
input
,
name
)
if
out
!=
nil
{
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
Attr
.
Ino
=
out
.
NodeId
}
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Unlink
(
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Unlink
(
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
fuse
.
ENOENT
}
...
...
@@ -437,48 +437,48 @@ func (self *SubmountFileSystem) Unlink(header *fuse.InHeader, name string) (code
return
subfs
.
Fs
.
Unlink
(
header
,
name
)
}
func
(
self
*
SubmountFileSystem
)
Rmdir
(
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Rmdir
(
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
fuse
.
ENOENT
}
return
subfs
.
Fs
.
Rmdir
(
header
,
name
)
}
func
(
self
*
SubmountFileSystem
)
Symlink
(
header
*
fuse
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Symlink
(
header
*
fuse
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
nil
,
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
out
,
code
=
subfs
.
Fs
.
Symlink
(
header
,
pointedTo
,
linkName
)
if
out
!=
nil
{
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
Attr
.
Ino
=
out
.
NodeId
}
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Rename
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Rename
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
||
input
.
Newdir
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
fuse
.
ENOENT
}
...
...
@@ -486,24 +486,24 @@ func (self *SubmountFileSystem) Rename(header *fuse.InHeader, input *fuse.Rename
return
subfs
.
Fs
.
Rename
(
header
,
input
,
oldName
,
newName
)
}
func
(
self
*
SubmountFileSystem
)
Link
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
LinkIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Link
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
LinkIn
,
name
string
)
(
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
out
,
code
=
subfs
.
Fs
.
Link
(
header
,
input
,
name
)
if
out
!=
nil
{
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
Attr
.
Ino
=
out
.
NodeId
}
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
SetXAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
SetXAttrIn
)
fuse
.
Status
{
func
(
me
*
SubmountFileSystem
)
SetXAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
SetXAttrIn
)
fuse
.
Status
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
fuse
.
ENOENT
}
...
...
@@ -511,9 +511,9 @@ func (self *SubmountFileSystem) SetXAttr(header *fuse.InHeader, input *fuse.SetX
return
subfs
.
Fs
.
SetXAttr
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
GetXAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
GetXAttrIn
)
(
out
*
fuse
.
GetXAttrOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
GetXAttr
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
GetXAttrIn
)
(
out
*
fuse
.
GetXAttrOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -521,53 +521,53 @@ func (self *SubmountFileSystem) GetXAttr(header *fuse.InHeader, input *fuse.GetX
return
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Access
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
AccessIn
)
(
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Access
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
AccessIn
)
(
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
return
subfs
.
Fs
.
Access
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
Create
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseFile
,
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Create
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseFile
,
out
*
fuse
.
EntryOut
,
code
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
// ENOSYS ?
return
0
,
nil
,
nil
,
fuse
.
EPERM
}
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
0
,
nil
,
nil
,
fuse
.
ENOENT
}
flags
,
fuseFile
,
out
,
code
=
subfs
.
Fs
.
Create
(
header
,
input
,
name
)
if
out
!=
nil
{
out
.
NodeId
=
self
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
NodeId
=
me
.
registerLookup
(
out
.
NodeId
,
subfs
)
out
.
Attr
.
Ino
=
out
.
NodeId
}
return
flags
,
fuseFile
,
out
,
code
}
func
(
self
*
SubmountFileSystem
)
Bmap
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
BmapIn
)
(
out
*
fuse
.
BmapOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Bmap
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
BmapIn
)
(
out
*
fuse
.
BmapOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
return
subfs
.
Fs
.
Bmap
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
Ioctl
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
IoctlIn
)
(
out
*
fuse
.
IoctlOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Ioctl
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
IoctlIn
)
(
out
*
fuse
.
IoctlOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
return
subfs
.
Fs
.
Ioctl
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
Poll
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
PollIn
)
(
out
*
fuse
.
PollOut
,
code
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
Poll
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
PollIn
)
(
out
*
fuse
.
PollOut
,
code
fuse
.
Status
)
{
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -575,26 +575,26 @@ func (self *SubmountFileSystem) Poll(header *fuse.InHeader, input *fuse.PollIn)
return
subfs
.
Fs
.
Poll
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
OpenDir
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
OpenIn
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseDir
,
status
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystem
)
OpenDir
(
header
*
fuse
.
InHeader
,
input
*
fuse
.
OpenIn
)
(
flags
uint32
,
fuseFile
fuse
.
RawFuseDir
,
status
fuse
.
Status
)
{
if
header
.
NodeId
==
fuse
.
FUSE_ROOT_ID
{
return
0
,
NewSubmountFileSystemTopDir
(
self
),
fuse
.
OK
return
0
,
NewSubmountFileSystemTopDir
(
me
),
fuse
.
OK
}
// TODO - we have to parse and unparse the readdir results, to substitute inodes.
var
subfs
*
subFsInfo
header
.
NodeId
,
subfs
=
self
.
getSubFs
(
header
.
NodeId
)
header
.
NodeId
,
subfs
=
me
.
getSubFs
(
header
.
NodeId
)
if
subfs
==
nil
{
return
0
,
nil
,
fuse
.
ENOENT
}
return
subfs
.
Fs
.
OpenDir
(
header
,
input
)
}
func
(
self
*
SubmountFileSystem
)
Release
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseFile
)
{
func
(
me
*
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
)
{
func
(
me
*
SubmountFileSystem
)
ReleaseDir
(
header
*
fuse
.
InHeader
,
f
fuse
.
RawFuseDir
)
{
// TODO - should run releasedir on subfs too.
}
...
...
@@ -616,13 +616,13 @@ func NewSubmountFileSystemTopDir(fs *SubmountFileSystem) *SubmountFileSystemTopD
return
out
}
func
(
self
*
SubmountFileSystemTopDir
)
ReadDir
(
input
*
fuse
.
ReadIn
)
(
*
fuse
.
DirEntryList
,
fuse
.
Status
)
{
func
(
me
*
SubmountFileSystemTopDir
)
ReadDir
(
input
*
fuse
.
ReadIn
)
(
*
fuse
.
DirEntryList
,
fuse
.
Status
)
{
de
:=
fuse
.
NewDirEntryList
(
int
(
input
.
Size
))
for
self
.
nextRead
<
len
(
self
.
names
)
{
i
:=
self
.
nextRead
if
de
.
AddString
(
self
.
names
[
i
],
fuse
.
FUSE_UNKNOWN_INO
,
self
.
modes
[
i
])
{
self
.
nextRead
++
for
me
.
nextRead
<
len
(
me
.
names
)
{
i
:=
me
.
nextRead
if
de
.
AddString
(
me
.
names
[
i
],
fuse
.
FUSE_UNKNOWN_INO
,
me
.
modes
[
i
])
{
me
.
nextRead
++
}
else
{
break
}
...
...
examplelib/stackfs_test.go
View file @
7c3c1e41
...
...
@@ -29,63 +29,63 @@ type stackFsTestCase struct {
state
*
fuse
.
MountState
}
func
(
self
*
stackFsTestCase
)
Setup
(
t
*
testing
.
T
)
{
self
.
tester
=
t
func
(
me
*
stackFsTestCase
)
Setup
(
t
*
testing
.
T
)
{
me
.
tester
=
t
self
.
testDir
=
fuse
.
MakeTempDir
()
self
.
origDir1
=
path
.
Join
(
self
.
testDir
,
"orig1"
)
self
.
origDir2
=
path
.
Join
(
self
.
testDir
,
"orig2"
)
self
.
mountDir
=
path
.
Join
(
self
.
testDir
,
"mount"
)
me
.
testDir
=
fuse
.
MakeTempDir
()
me
.
origDir1
=
path
.
Join
(
me
.
testDir
,
"orig1"
)
me
.
origDir2
=
path
.
Join
(
me
.
testDir
,
"orig2"
)
me
.
mountDir
=
path
.
Join
(
me
.
testDir
,
"mount"
)
os
.
Mkdir
(
self
.
origDir1
,
0700
)
os
.
Mkdir
(
self
.
origDir2
,
0700
)
os
.
Mkdir
(
self
.
mountDir
,
0700
)
os
.
Mkdir
(
me
.
origDir1
,
0700
)
os
.
Mkdir
(
me
.
origDir2
,
0700
)
os
.
Mkdir
(
me
.
mountDir
,
0700
)
fs1
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
self
.
origDir1
))
fs2
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
self
.
origDir2
))
fs1
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
me
.
origDir1
))
fs2
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
me
.
origDir2
))
self
.
fs
=
NewSubmountFileSystem
()
me
.
fs
=
NewSubmountFileSystem
()
attr
:=
fuse
.
Attr
{
Mode
:
uint32
(
magicMode
),
}
self
.
fs
.
AddFileSystem
(
"sub1"
,
fs1
,
attr
)
self
.
fs
.
AddFileSystem
(
"sub2"
,
fs2
,
attr
)
me
.
fs
.
AddFileSystem
(
"sub1"
,
fs1
,
attr
)
me
.
fs
.
AddFileSystem
(
"sub2"
,
fs2
,
attr
)
self
.
state
=
fuse
.
NewMountState
(
self
.
fs
)
self
.
state
.
Mount
(
self
.
mountDir
)
me
.
state
=
fuse
.
NewMountState
(
me
.
fs
)
me
.
state
.
Mount
(
me
.
mountDir
)
self
.
state
.
Debug
=
true
me
.
state
.
Debug
=
true
fmt
.
Println
(
"tempdir: "
,
self
.
testDir
)
fmt
.
Println
(
"tempdir: "
,
me
.
testDir
)
// Unthreaded, but in background.
go
self
.
state
.
Loop
(
false
)
go
me
.
state
.
Loop
(
false
)
}
// Unmount and del.
func
(
self
*
stackFsTestCase
)
Cleanup
()
{
func
(
me
*
stackFsTestCase
)
Cleanup
()
{
fmt
.
Println
(
"Unmounting."
)
err
:=
self
.
state
.
Unmount
()
err
:=
me
.
state
.
Unmount
()
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Can't unmount a dir, err: %v"
,
err
)
me
.
tester
.
Errorf
(
"Can't unmount a dir, err: %v"
,
err
)
}
os
.
RemoveAll
(
self
.
testDir
)
os
.
RemoveAll
(
me
.
testDir
)
}
////////////////
func
(
self
*
stackFsTestCase
)
testReaddir
()
{
func
(
me
*
stackFsTestCase
)
testReaddir
()
{
fmt
.
Println
(
"testReaddir... "
)
dir
,
err
:=
os
.
Open
(
self
.
mountDir
,
os
.
O_RDONLY
,
0
)
dir
,
err
:=
os
.
Open
(
me
.
mountDir
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
me
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
return
}
infos
,
err
:=
dir
.
Readdir
(
10
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"readdir err %v"
,
err
)
me
.
tester
.
Errorf
(
"readdir err %v"
,
err
)
}
wanted
:=
map
[
string
]
bool
{
...
...
@@ -93,16 +93,16 @@ func (self *stackFsTestCase) testReaddir() {
"sub2"
:
true
,
}
if
len
(
wanted
)
!=
len
(
infos
)
{
self
.
tester
.
Errorf
(
"Length mismatch %v"
,
infos
)
me
.
tester
.
Errorf
(
"Length mismatch %v"
,
infos
)
}
else
{
for
_
,
v
:=
range
infos
{
_
,
ok
:=
wanted
[
v
.
Name
]
if
!
ok
{
self
.
tester
.
Errorf
(
"Unexpected name %v"
,
v
.
Name
)
me
.
tester
.
Errorf
(
"Unexpected name %v"
,
v
.
Name
)
}
if
v
.
Mode
&
0777
!=
magicMode
{
self
.
tester
.
Errorf
(
"Unexpected mode %o, %v"
,
v
.
Mode
,
v
)
me
.
tester
.
Errorf
(
"Unexpected mode %o, %v"
,
v
.
Mode
,
v
)
}
}
}
...
...
@@ -111,11 +111,11 @@ func (self *stackFsTestCase) testReaddir() {
}
func
(
self
*
stackFsTestCase
)
testSubFs
()
{
func
(
me
*
stackFsTestCase
)
testSubFs
()
{
fmt
.
Println
(
"testSubFs... "
)
for
i
:=
1
;
i
<=
2
;
i
++
{
// orig := path.Join(
self
.testDir, fmt.Sprintf("orig%d", i))
mount
:=
path
.
Join
(
self
.
mountDir
,
fmt
.
Sprintf
(
"sub%d"
,
i
))
// orig := path.Join(
me
.testDir, fmt.Sprintf("orig%d", i))
mount
:=
path
.
Join
(
me
.
mountDir
,
fmt
.
Sprintf
(
"sub%d"
,
i
))
name
:=
"testFile"
...
...
@@ -123,13 +123,13 @@ func (self *stackFsTestCase) testSubFs() {
f
,
err
:=
os
.
Open
(
mountFile
,
os
.
O_WRONLY
,
0
)
if
err
==
nil
{
self
.
tester
.
Errorf
(
"Expected error for open write %v"
,
name
)
me
.
tester
.
Errorf
(
"Expected error for open write %v"
,
name
)
continue
}
content1
:=
"booh!"
f
,
err
=
os
.
Open
(
mountFile
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
magicMode
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Create %v"
,
err
)
me
.
tester
.
Errorf
(
"Create %v"
,
err
)
}
f
.
Write
([]
byte
(
content1
))
...
...
@@ -137,80 +137,80 @@ func (self *stackFsTestCase) testSubFs() {
err
=
os
.
Chmod
(
mountFile
,
magicMode
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"chmod %v"
,
err
)
me
.
tester
.
Errorf
(
"chmod %v"
,
err
)
}
fi
,
err
:=
os
.
Lstat
(
mountFile
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Lstat %v"
,
err
)
me
.
tester
.
Errorf
(
"Lstat %v"
,
err
)
}
else
{
if
fi
.
Mode
&
0777
!=
magicMode
{
self
.
tester
.
Errorf
(
"Mode %o"
,
fi
.
Mode
)
me
.
tester
.
Errorf
(
"Mode %o"
,
fi
.
Mode
)
}
}
g
,
err
:=
os
.
Open
(
mountFile
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"Open %v"
,
err
)
me
.
tester
.
Errorf
(
"Open %v"
,
err
)
}
else
{
buf
:=
make
([]
byte
,
1024
)
n
,
err
:=
g
.
Read
(
buf
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"read err %v"
,
err
)
me
.
tester
.
Errorf
(
"read err %v"
,
err
)
}
if
string
(
buf
[
:
n
])
!=
content1
{
self
.
tester
.
Errorf
(
"content %v"
,
buf
[
:
n
])
me
.
tester
.
Errorf
(
"content %v"
,
buf
[
:
n
])
}
g
.
Close
()
}
}
}
func
(
self
*
stackFsTestCase
)
testAddRemove
()
{
self
.
tester
.
Log
(
"testAddRemove"
)
func
(
me
*
stackFsTestCase
)
testAddRemove
()
{
me
.
tester
.
Log
(
"testAddRemove"
)
attr
:=
fuse
.
Attr
{
Mode
:
0755
,
}
conn
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
self
.
origDir1
))
ok
:=
self
.
fs
.
AddFileSystem
(
"sub1"
,
conn
,
attr
)
conn
:=
fuse
.
NewPathFileSystemConnector
(
NewPassThroughFuse
(
me
.
origDir1
))
ok
:=
me
.
fs
.
AddFileSystem
(
"sub1"
,
conn
,
attr
)
if
ok
{
self
.
tester
.
Errorf
(
"AddFileSystem should fail"
)
me
.
tester
.
Errorf
(
"AddFileSystem should fail"
)
return
}
ok
=
self
.
fs
.
AddFileSystem
(
"third"
,
conn
,
attr
)
ok
=
me
.
fs
.
AddFileSystem
(
"third"
,
conn
,
attr
)
if
!
ok
{
self
.
tester
.
Errorf
(
"AddFileSystem fail"
)
me
.
tester
.
Errorf
(
"AddFileSystem fail"
)
}
conn
.
Init
(
new
(
fuse
.
InHeader
),
new
(
fuse
.
InitIn
))
fi
,
err
:=
os
.
Lstat
(
path
.
Join
(
self
.
mountDir
,
"third"
))
fi
,
err
:=
os
.
Lstat
(
path
.
Join
(
me
.
mountDir
,
"third"
))
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"third lstat err %v"
,
err
)
me
.
tester
.
Errorf
(
"third lstat err %v"
,
err
)
}
else
{
if
!
fi
.
IsDirectory
()
{
self
.
tester
.
Errorf
(
"not a directory %v"
,
fi
)
me
.
tester
.
Errorf
(
"not a directory %v"
,
fi
)
}
}
fs
:=
self
.
fs
.
RemoveFileSystem
(
"third"
)
fs
:=
me
.
fs
.
RemoveFileSystem
(
"third"
)
if
fs
==
nil
{
self
.
tester
.
Errorf
(
"remove fail"
)
me
.
tester
.
Errorf
(
"remove fail"
)
}
dir
,
err
:=
os
.
Open
(
self
.
mountDir
,
os
.
O_RDONLY
,
0
)
dir
,
err
:=
os
.
Open
(
me
.
mountDir
,
os
.
O_RDONLY
,
0
)
if
err
!=
nil
{
self
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
me
.
tester
.
Errorf
(
"opendir err %v"
,
err
)
return
}
infos
,
err
:=
dir
.
Readdir
(
10
)
if
len
(
infos
)
!=
2
{
self
.
tester
.
Errorf
(
"lstat expect 2 infos %v"
,
infos
)
me
.
tester
.
Errorf
(
"lstat expect 2 infos %v"
,
infos
)
}
dir
.
Close
()
_
,
err
=
os
.
Open
(
path
.
Join
(
self
.
mountDir
,
"third"
),
os
.
O_RDONLY
,
0
)
_
,
err
=
os
.
Open
(
path
.
Join
(
me
.
mountDir
,
"third"
),
os
.
O_RDONLY
,
0
)
if
err
==
nil
{
self
.
tester
.
Errorf
(
"expect enoent %v"
,
err
)
me
.
tester
.
Errorf
(
"expect enoent %v"
,
err
)
}
}
...
...
examplelib/zipfs.go
View file @
7c3c1e41
...
...
@@ -119,8 +119,8 @@ func NewZipFileFuse(name string) *ZipFileFuse {
const
zip_DIRMODE
uint32
=
fuse
.
S_IFDIR
|
0700
const
zip_FILEMODE
uint32
=
fuse
.
S_IFREG
|
0600
func
(
self
*
ZipFileFuse
)
GetAttr
(
name
string
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
dir
,
file
:=
self
.
tree
.
Lookup
(
name
)
func
(
me
*
ZipFileFuse
)
GetAttr
(
name
string
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
dir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
dir
==
nil
{
return
nil
,
fuse
.
ENOENT
}
...
...
@@ -136,16 +136,16 @@ func (self *ZipFileFuse) GetAttr(name string) (*fuse.Attr, fuse.Status) {
return
a
,
fuse
.
OK
}
func
(
self
*
ZipFileFuse
)
Open
(
name
string
,
flags
uint32
)
(
file
fuse
.
RawFuseFile
,
code
fuse
.
Status
)
{
_
,
zfile
:=
self
.
tree
.
Lookup
(
name
)
func
(
me
*
ZipFileFuse
)
Open
(
name
string
,
flags
uint32
)
(
file
fuse
.
RawFuseFile
,
code
fuse
.
Status
)
{
_
,
zfile
:=
me
.
tree
.
Lookup
(
name
)
if
zfile
==
nil
{
return
nil
,
fuse
.
ENOENT
}
return
NewZipFile
(
zfile
),
fuse
.
OK
}
func
(
self
*
ZipFileFuse
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
code
fuse
.
Status
)
{
zdir
,
file
:=
self
.
tree
.
Lookup
(
name
)
func
(
me
*
ZipFileFuse
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
code
fuse
.
Status
)
{
zdir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
file
!=
nil
{
return
nil
,
fuse
.
ENOSYS
}
...
...
fuse/bufferpool.go
View file @
7c3c1e41
...
...
@@ -41,37 +41,37 @@ func NewBufferPool() *BufferPool {
return
bp
}
func
(
self
*
BufferPool
)
String
()
string
{
func
(
me
*
BufferPool
)
String
()
string
{
s
:=
""
for
exp
,
bufs
:=
range
self
.
buffersByExponent
{
for
exp
,
bufs
:=
range
me
.
buffersByExponent
{
s
=
s
+
fmt
.
Sprintf
(
"%d = %d
\n
"
,
exp
,
len
(
bufs
))
}
return
s
}
func
(
self
*
BufferPool
)
getBuffer
(
exponent
uint
)
[]
byte
{
if
len
(
self
.
buffersByExponent
)
<=
int
(
exponent
)
{
func
(
me
*
BufferPool
)
getBuffer
(
exponent
uint
)
[]
byte
{
if
len
(
me
.
buffersByExponent
)
<=
int
(
exponent
)
{
return
nil
}
bufferList
:=
self
.
buffersByExponent
[
exponent
]
bufferList
:=
me
.
buffersByExponent
[
exponent
]
if
len
(
bufferList
)
==
0
{
return
nil
}
result
:=
bufferList
[
len
(
bufferList
)
-
1
]
self
.
buffersByExponent
[
exponent
]
=
self
.
buffersByExponent
[
exponent
][
:
len
(
bufferList
)
-
1
]
me
.
buffersByExponent
[
exponent
]
=
me
.
buffersByExponent
[
exponent
][
:
len
(
bufferList
)
-
1
]
return
result
}
func
(
self
*
BufferPool
)
addBuffer
(
slice
[]
byte
,
exp
uint
)
{
for
len
(
self
.
buffersByExponent
)
<=
int
(
exp
)
{
self
.
buffersByExponent
=
append
(
self
.
buffersByExponent
,
make
([][]
byte
,
0
))
func
(
me
*
BufferPool
)
addBuffer
(
slice
[]
byte
,
exp
uint
)
{
for
len
(
me
.
buffersByExponent
)
<=
int
(
exp
)
{
me
.
buffersByExponent
=
append
(
me
.
buffersByExponent
,
make
([][]
byte
,
0
))
}
self
.
buffersByExponent
[
exp
]
=
append
(
self
.
buffersByExponent
[
exp
],
slice
)
me
.
buffersByExponent
[
exp
]
=
append
(
me
.
buffersByExponent
[
exp
],
slice
)
}
func
(
self
*
BufferPool
)
AllocBuffer
(
size
uint32
)
[]
byte
{
func
(
me
*
BufferPool
)
AllocBuffer
(
size
uint32
)
[]
byte
{
sz
:=
int
(
size
)
if
sz
<
PAGESIZE
{
sz
=
PAGESIZE
...
...
@@ -82,10 +82,10 @@ func (self *BufferPool) AllocBuffer(size uint32) []byte {
exp
-=
IntToExponent
(
PAGESIZE
)
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
b
:=
self
.
getBuffer
(
exp
)
b
:=
me
.
getBuffer
(
exp
)
if
b
!=
nil
{
b
=
b
[
:
size
]
...
...
@@ -93,24 +93,24 @@ func (self *BufferPool) AllocBuffer(size uint32) []byte {
}
b
=
make
([]
byte
,
size
,
rounded
)
self
.
outstandingBuffers
[
uintptr
(
unsafe
.
Pointer
(
&
b
[
0
]))]
=
exp
me
.
outstandingBuffers
[
uintptr
(
unsafe
.
Pointer
(
&
b
[
0
]))]
=
exp
return
b
}
// Takes back a buffer if it was allocated through AllocBuffer. It is
// not an error to call FreeBuffer() on a slice obtained elsewhere.
func
(
self
*
BufferPool
)
FreeBuffer
(
slice
[]
byte
)
{
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
func
(
me
*
BufferPool
)
FreeBuffer
(
slice
[]
byte
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
if
cap
(
slice
)
<
PAGESIZE
{
return
}
key
:=
uintptr
(
unsafe
.
Pointer
(
&
slice
[
0
]))
exp
,
ok
:=
self
.
outstandingBuffers
[
key
]
exp
,
ok
:=
me
.
outstandingBuffers
[
key
]
if
ok
{
self
.
addBuffer
(
slice
,
exp
)
self
.
outstandingBuffers
[
key
]
=
0
,
false
me
.
addBuffer
(
slice
,
exp
)
me
.
outstandingBuffers
[
key
]
=
0
,
false
}
}
fuse/datafile.go
View file @
7c3c1e41
...
...
@@ -14,11 +14,11 @@ func NewReadOnlyFile(data []byte) *ReadOnlyFile {
return
f
}
func
(
self
*
ReadOnlyFile
)
Read
(
input
*
ReadIn
,
bp
*
BufferPool
)
([]
byte
,
Status
)
{
func
(
me
*
ReadOnlyFile
)
Read
(
input
*
ReadIn
,
bp
*
BufferPool
)
([]
byte
,
Status
)
{
end
:=
int
(
input
.
Offset
)
+
int
(
input
.
Size
)
if
end
>
len
(
self
.
data
)
{
end
=
len
(
self
.
data
)
if
end
>
len
(
me
.
data
)
{
end
=
len
(
me
.
data
)
}
return
self
.
data
[
input
.
Offset
:
end
],
OK
return
me
.
data
[
input
.
Offset
:
end
],
OK
}
fuse/default.go
View file @
7c3c1e41
...
...
@@ -6,124 +6,124 @@ import (
var
_
=
log
.
Println
func
(
self
*
DefaultRawFuseFileSystem
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
return
new
(
InitOut
),
OK
}
func
(
self
*
DefaultRawFuseFileSystem
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
}
func
(
self
*
DefaultRawFuseFileSystem
)
Lookup
(
h
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Lookup
(
h
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Forget
(
h
*
InHeader
,
input
*
ForgetIn
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Forget
(
h
*
InHeader
,
input
*
ForgetIn
)
{
}
func
(
self
*
DefaultRawFuseFileSystem
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
return
0
,
nil
,
OK
}
func
(
self
*
DefaultRawFuseFileSystem
)
SetAttr
(
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
SetAttr
(
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
return
new
(
EntryOut
),
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
SetXAttr
(
header
*
InHeader
,
input
*
SetXAttrIn
)
Status
{
func
(
me
*
DefaultRawFuseFileSystem
)
SetXAttr
(
header
*
InHeader
,
input
*
SetXAttrIn
)
Status
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
GetXAttr
(
header
*
InHeader
,
input
*
GetXAttrIn
)
(
out
*
GetXAttrOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
GetXAttr
(
header
*
InHeader
,
input
*
GetXAttrIn
)
(
out
*
GetXAttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
return
0
,
nil
,
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
return
0
,
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFileSystem
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
}
func
(
self
*
DefaultRawFuseFileSystem
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
func
(
me
*
DefaultRawFuseFileSystem
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
}
////////////////////////////////////////////////////////////////
// DefaultRawFuseFile
func
(
self
*
DefaultRawFuseFile
)
Read
(
*
ReadIn
,
*
BufferPool
)
([]
byte
,
Status
)
{
func
(
me
*
DefaultRawFuseFile
)
Read
(
*
ReadIn
,
*
BufferPool
)
([]
byte
,
Status
)
{
return
[]
byte
(
""
),
ENOSYS
}
func
(
self
*
DefaultRawFuseFile
)
Write
(
*
WriteIn
,
[]
byte
)
(
uint32
,
Status
)
{
func
(
me
*
DefaultRawFuseFile
)
Write
(
*
WriteIn
,
[]
byte
)
(
uint32
,
Status
)
{
return
0
,
ENOSYS
}
func
(
self
*
DefaultRawFuseFile
)
Flush
()
Status
{
func
(
me
*
DefaultRawFuseFile
)
Flush
()
Status
{
return
ENOSYS
}
func
(
self
*
DefaultRawFuseFile
)
Release
()
{
func
(
me
*
DefaultRawFuseFile
)
Release
()
{
}
func
(
self
*
DefaultRawFuseFile
)
Fsync
(
*
FsyncIn
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseFile
)
Fsync
(
*
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
...
...
@@ -131,91 +131,91 @@ func (self *DefaultRawFuseFile) Fsync(*FsyncIn) (code Status) {
////////////////////////////////////////////////////////////////
//
func
(
self
*
DefaultRawFuseDir
)
ReadDir
(
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
func
(
me
*
DefaultRawFuseDir
)
ReadDir
(
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultRawFuseDir
)
ReleaseDir
()
{
func
(
me
*
DefaultRawFuseDir
)
ReleaseDir
()
{
}
func
(
self
*
DefaultRawFuseDir
)
FsyncDir
(
input
*
FsyncIn
)
(
code
Status
)
{
func
(
me
*
DefaultRawFuseDir
)
FsyncDir
(
input
*
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
////////////////////////////////////////////////////////////////
// DefaultPathFilesystem
func
(
self
*
DefaultPathFilesystem
)
GetAttr
(
name
string
)
(
*
Attr
,
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
GetAttr
(
name
string
)
(
*
Attr
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Readlink
(
name
string
)
(
string
,
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Readlink
(
name
string
)
(
string
,
Status
)
{
return
""
,
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
)
Status
{
func
(
me
*
DefaultPathFilesystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
)
Status
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Mkdir
(
name
string
,
mode
uint32
)
Status
{
func
(
me
*
DefaultPathFilesystem
)
Mkdir
(
name
string
,
mode
uint32
)
Status
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Unlink
(
name
string
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Unlink
(
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Rmdir
(
name
string
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Rmdir
(
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Symlink
(
value
string
,
linkName
string
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Symlink
(
value
string
,
linkName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Rename
(
oldName
string
,
newName
string
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Rename
(
oldName
string
,
newName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Link
(
oldName
string
,
newName
string
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Link
(
oldName
string
,
newName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Chmod
(
name
string
,
mode
uint32
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Chmod
(
name
string
,
mode
uint32
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Truncate
(
name
string
,
offset
uint64
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Truncate
(
name
string
,
offset
uint64
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Open
(
name
string
,
flags
uint32
)
(
file
RawFuseFile
,
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Open
(
name
string
,
flags
uint32
)
(
file
RawFuseFile
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
OpenDir
(
name
string
)
(
stream
chan
DirEntry
,
status
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
OpenDir
(
name
string
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Mount
(
conn
*
PathFileSystemConnector
)
Status
{
func
(
me
*
DefaultPathFilesystem
)
Mount
(
conn
*
PathFileSystemConnector
)
Status
{
return
OK
}
func
(
self
*
DefaultPathFilesystem
)
Unmount
()
{
func
(
me
*
DefaultPathFilesystem
)
Unmount
()
{
}
func
(
self
*
DefaultPathFilesystem
)
Access
(
name
string
,
mode
uint32
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Access
(
name
string
,
mode
uint32
)
(
code
Status
)
{
return
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
)
(
file
RawFuseFile
,
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
)
(
file
RawFuseFile
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
DefaultPathFilesystem
)
Utimens
(
name
string
,
AtimeNs
uint64
,
CtimeNs
uint64
)
(
code
Status
)
{
func
(
me
*
DefaultPathFilesystem
)
Utimens
(
name
string
,
AtimeNs
uint64
,
CtimeNs
uint64
)
(
code
Status
)
{
return
ENOSYS
}
fuse/direntry.go
View file @
7c3c1e41
...
...
@@ -25,41 +25,41 @@ func NewDirEntryList(max int) *DirEntryList {
return
&
DirEntryList
{
maxSize
:
max
}
}
func
(
d
e
*
DirEntryList
)
AddString
(
name
string
,
inode
uint64
,
mode
uint32
)
bool
{
return
d
e
.
Add
([]
byte
(
name
),
inode
,
mode
)
func
(
m
e
*
DirEntryList
)
AddString
(
name
string
,
inode
uint64
,
mode
uint32
)
bool
{
return
m
e
.
Add
([]
byte
(
name
),
inode
,
mode
)
}
func
(
d
e
*
DirEntryList
)
Add
(
name
[]
byte
,
inode
uint64
,
mode
uint32
)
bool
{
lastLen
:=
d
e
.
buf
.
Len
()
d
e
.
offset
++
func
(
m
e
*
DirEntryList
)
Add
(
name
[]
byte
,
inode
uint64
,
mode
uint32
)
bool
{
lastLen
:=
m
e
.
buf
.
Len
()
m
e
.
offset
++
dirent
:=
new
(
Dirent
)
dirent
.
Off
=
d
e
.
offset
dirent
.
Off
=
m
e
.
offset
dirent
.
Ino
=
inode
dirent
.
NameLen
=
uint32
(
len
(
name
))
dirent
.
Typ
=
ModeToType
(
mode
)
err
:=
binary
.
Write
(
&
d
e
.
buf
,
binary
.
LittleEndian
,
dirent
)
err
:=
binary
.
Write
(
&
m
e
.
buf
,
binary
.
LittleEndian
,
dirent
)
if
err
!=
nil
{
panic
(
"Serialization of Dirent failed"
)
}
d
e
.
buf
.
Write
(
name
)
m
e
.
buf
.
Write
(
name
)
padding
:=
8
-
len
(
name
)
&
7
if
padding
<
8
{
d
e
.
buf
.
Write
(
make
([]
byte
,
padding
))
m
e
.
buf
.
Write
(
make
([]
byte
,
padding
))
}
if
de
.
buf
.
Len
()
>
d
e
.
maxSize
{
d
e
.
buf
.
Truncate
(
lastLen
)
d
e
.
offset
--
if
me
.
buf
.
Len
()
>
m
e
.
maxSize
{
m
e
.
buf
.
Truncate
(
lastLen
)
m
e
.
offset
--
return
false
}
return
true
}
func
(
d
e
*
DirEntryList
)
Bytes
()
[]
byte
{
return
d
e
.
buf
.
Bytes
()
func
(
m
e
*
DirEntryList
)
Bytes
()
[]
byte
{
return
m
e
.
buf
.
Bytes
()
}
////////////////////////////////////////////////////////////////
...
...
fuse/fuse.go
View file @
7c3c1e41
...
...
@@ -60,47 +60,47 @@ type MountState struct {
operationCounts
*
expvar
.
Map
}
func
(
self
*
MountState
)
RegisterFile
(
file
RawFuseFile
)
uint64
{
self
.
openedFilesMutex
.
Lock
()
defer
self
.
openedFilesMutex
.
Unlock
()
func
(
me
*
MountState
)
RegisterFile
(
file
RawFuseFile
)
uint64
{
me
.
openedFilesMutex
.
Lock
()
defer
me
.
openedFilesMutex
.
Unlock
()
// We will be screwed if nextFree ever wraps.
self
.
nextFreeFile
++
index
:=
self
.
nextFreeFile
self
.
openedFiles
[
index
]
=
file
me
.
nextFreeFile
++
index
:=
me
.
nextFreeFile
me
.
openedFiles
[
index
]
=
file
return
index
}
func
(
self
*
MountState
)
FindFile
(
index
uint64
)
RawFuseFile
{
self
.
openedFilesMutex
.
RLock
()
defer
self
.
openedFilesMutex
.
RUnlock
()
return
self
.
openedFiles
[
index
]
func
(
me
*
MountState
)
FindFile
(
index
uint64
)
RawFuseFile
{
me
.
openedFilesMutex
.
RLock
()
defer
me
.
openedFilesMutex
.
RUnlock
()
return
me
.
openedFiles
[
index
]
}
func
(
self
*
MountState
)
UnregisterFile
(
handle
uint64
)
{
self
.
openedFilesMutex
.
Lock
()
defer
self
.
openedFilesMutex
.
Unlock
()
self
.
openedFiles
[
handle
]
=
nil
,
false
func
(
me
*
MountState
)
UnregisterFile
(
handle
uint64
)
{
me
.
openedFilesMutex
.
Lock
()
defer
me
.
openedFilesMutex
.
Unlock
()
me
.
openedFiles
[
handle
]
=
nil
,
false
}
func
(
self
*
MountState
)
RegisterDir
(
dir
RawFuseDir
)
uint64
{
self
.
openedDirsMutex
.
Lock
()
defer
self
.
openedDirsMutex
.
Unlock
()
self
.
nextFreeDir
++
index
:=
self
.
nextFreeDir
self
.
openedDirs
[
index
]
=
dir
func
(
me
*
MountState
)
RegisterDir
(
dir
RawFuseDir
)
uint64
{
me
.
openedDirsMutex
.
Lock
()
defer
me
.
openedDirsMutex
.
Unlock
()
me
.
nextFreeDir
++
index
:=
me
.
nextFreeDir
me
.
openedDirs
[
index
]
=
dir
return
index
}
func
(
self
*
MountState
)
FindDir
(
index
uint64
)
RawFuseDir
{
self
.
openedDirsMutex
.
RLock
()
defer
self
.
openedDirsMutex
.
RUnlock
()
return
self
.
openedDirs
[
index
]
func
(
me
*
MountState
)
FindDir
(
index
uint64
)
RawFuseDir
{
me
.
openedDirsMutex
.
RLock
()
defer
me
.
openedDirsMutex
.
RUnlock
()
return
me
.
openedDirs
[
index
]
}
func
(
self
*
MountState
)
UnregisterDir
(
handle
uint64
)
{
self
.
openedDirsMutex
.
Lock
()
defer
self
.
openedDirsMutex
.
Unlock
()
self
.
openedDirs
[
handle
]
=
nil
,
false
func
(
me
*
MountState
)
UnregisterDir
(
handle
uint64
)
{
me
.
openedDirsMutex
.
Lock
()
defer
me
.
openedDirsMutex
.
Unlock
()
me
.
openedDirs
[
handle
]
=
nil
,
false
}
// Mount filesystem on mountPoint.
...
...
@@ -110,48 +110,48 @@ func (self *MountState) UnregisterDir(handle uint64) {
// using channels.
//
// TODO - error handling should perhaps be user-serviceable.
func
(
self
*
MountState
)
Mount
(
mountPoint
string
)
os
.
Error
{
func
(
me
*
MountState
)
Mount
(
mountPoint
string
)
os
.
Error
{
file
,
mp
,
err
:=
mount
(
mountPoint
)
if
err
!=
nil
{
return
err
}
self
.
mountPoint
=
mp
self
.
mountFile
=
file
me
.
mountPoint
=
mp
me
.
mountFile
=
file
self
.
operationCounts
=
expvar
.
NewMap
(
fmt
.
Sprintf
(
"mount(%v)"
,
mountPoint
))
me
.
operationCounts
=
expvar
.
NewMap
(
fmt
.
Sprintf
(
"mount(%v)"
,
mountPoint
))
return
nil
}
// Normally, callers should run loop() and wait for FUSE to exit, but
// tests will want to run this in a goroutine.
func
(
self
*
MountState
)
Loop
(
threaded
bool
)
{
self
.
threaded
=
threaded
if
self
.
threaded
{
self
.
outputChannel
=
make
(
chan
[][]
byte
,
100
)
self
.
errorChannel
=
make
(
chan
os
.
Error
,
100
)
go
self
.
asyncWriterThread
()
go
self
.
DefaultErrorHandler
()
func
(
me
*
MountState
)
Loop
(
threaded
bool
)
{
me
.
threaded
=
threaded
if
me
.
threaded
{
me
.
outputChannel
=
make
(
chan
[][]
byte
,
100
)
me
.
errorChannel
=
make
(
chan
os
.
Error
,
100
)
go
me
.
asyncWriterThread
()
go
me
.
DefaultErrorHandler
()
}
self
.
loop
()
me
.
loop
()
if
self
.
threaded
{
close
(
self
.
outputChannel
)
close
(
self
.
errorChannel
)
if
me
.
threaded
{
close
(
me
.
outputChannel
)
close
(
me
.
errorChannel
)
}
}
func
(
self
*
MountState
)
Unmount
()
os
.
Error
{
func
(
me
*
MountState
)
Unmount
()
os
.
Error
{
// Todo: flush/release all files/dirs?
result
:=
unmount
(
self
.
mountPoint
)
result
:=
unmount
(
me
.
mountPoint
)
if
result
==
nil
{
self
.
mountPoint
=
""
me
.
mountPoint
=
""
}
return
result
}
func
(
self
*
MountState
)
DefaultErrorHandler
()
{
for
err
:=
range
self
.
errorChannel
{
func
(
me
*
MountState
)
DefaultErrorHandler
()
{
for
err
:=
range
me
.
errorChannel
{
if
err
==
os
.
EOF
||
err
==
nil
{
break
}
...
...
@@ -159,45 +159,45 @@ func (self *MountState) DefaultErrorHandler() {
}
}
func
(
self
*
MountState
)
Error
(
err
os
.
Error
)
{
func
(
me
*
MountState
)
Error
(
err
os
.
Error
)
{
// It is safe to do errors unthreaded, since the logger is thread-safe.
if
!
self
.
threaded
||
self
.
Debug
{
if
!
me
.
threaded
||
me
.
Debug
{
log
.
Println
(
"error: "
,
err
)
}
else
{
self
.
errorChannel
<-
err
me
.
errorChannel
<-
err
}
}
func
(
self
*
MountState
)
Write
(
packet
[][]
byte
)
{
func
(
me
*
MountState
)
Write
(
packet
[][]
byte
)
{
if
packet
==
nil
{
return
}
if
self
.
threaded
{
self
.
outputChannel
<-
packet
if
me
.
threaded
{
me
.
outputChannel
<-
packet
}
else
{
self
.
syncWrite
(
packet
)
me
.
syncWrite
(
packet
)
}
}
func
NewMountState
(
fs
RawFileSystem
)
*
MountState
{
self
:=
new
(
MountState
)
self
.
openedDirs
=
make
(
map
[
uint64
]
RawFuseDir
)
self
.
openedFiles
=
make
(
map
[
uint64
]
RawFuseFile
)
self
.
mountPoint
=
""
self
.
fileSystem
=
fs
self
.
buffers
=
NewBufferPool
()
return
self
me
:=
new
(
MountState
)
me
.
openedDirs
=
make
(
map
[
uint64
]
RawFuseDir
)
me
.
openedFiles
=
make
(
map
[
uint64
]
RawFuseFile
)
me
.
mountPoint
=
""
me
.
fileSystem
=
fs
me
.
buffers
=
NewBufferPool
()
return
me
}
// TODO - have more statistics.
func
(
self
*
MountState
)
Stats
()
string
{
func
(
me
*
MountState
)
Stats
()
string
{
var
lines
[]
string
// TODO - bufferpool should use expvar.
lines
=
append
(
lines
,
fmt
.
Sprintf
(
"buffers: %v"
,
self
.
buffers
.
String
()))
fmt
.
Sprintf
(
"buffers: %v"
,
me
.
buffers
.
String
()))
for
v
:=
range
expvar
.
Iter
()
{
if
strings
.
HasPrefix
(
v
.
Key
,
"mount"
)
{
...
...
@@ -210,19 +210,19 @@ func (self *MountState) Stats() string {
////////////////
// Private routines.
func
(
self
*
MountState
)
asyncWriterThread
()
{
for
packet
:=
range
self
.
outputChannel
{
self
.
syncWrite
(
packet
)
func
(
me
*
MountState
)
asyncWriterThread
()
{
for
packet
:=
range
me
.
outputChannel
{
me
.
syncWrite
(
packet
)
}
}
func
(
self
*
MountState
)
syncWrite
(
packet
[][]
byte
)
{
_
,
err
:=
Writev
(
self
.
mountFile
.
Fd
(),
packet
)
func
(
me
*
MountState
)
syncWrite
(
packet
[][]
byte
)
{
_
,
err
:=
Writev
(
me
.
mountFile
.
Fd
(),
packet
)
if
err
!=
nil
{
self
.
Error
(
os
.
NewError
(
fmt
.
Sprintf
(
"writer: Writev %v failed, err: %v"
,
packet
,
err
)))
me
.
Error
(
os
.
NewError
(
fmt
.
Sprintf
(
"writer: Writev %v failed, err: %v"
,
packet
,
err
)))
}
for
_
,
v
:=
range
packet
{
self
.
buffers
.
FreeBuffer
(
v
)
me
.
buffers
.
FreeBuffer
(
v
)
}
}
...
...
@@ -230,11 +230,11 @@ func (self *MountState) syncWrite(packet [][]byte) {
////////////////////////////////////////////////////////////////
// Logic for the control loop.
func
(
self
*
MountState
)
loop
()
{
func
(
me
*
MountState
)
loop
()
{
// See fuse_kern_chan_receive()
for
{
buf
:=
self
.
buffers
.
AllocBuffer
(
bufSize
)
n
,
err
:=
self
.
mountFile
.
Read
(
buf
)
buf
:=
me
.
buffers
.
AllocBuffer
(
bufSize
)
n
,
err
:=
me
.
mountFile
.
Read
(
buf
)
if
err
!=
nil
{
errNo
:=
OsErrorToFuseError
(
err
)
...
...
@@ -254,21 +254,21 @@ func (self *MountState) loop() {
}
readErr
:=
os
.
NewError
(
fmt
.
Sprintf
(
"Failed to read from fuse conn: %v"
,
err
))
self
.
Error
(
readErr
)
me
.
Error
(
readErr
)
break
}
if
self
.
threaded
{
go
self
.
handle
(
buf
[
0
:
n
])
if
me
.
threaded
{
go
me
.
handle
(
buf
[
0
:
n
])
}
else
{
self
.
handle
(
buf
[
0
:
n
])
me
.
handle
(
buf
[
0
:
n
])
}
}
self
.
mountFile
.
Close
()
me
.
mountFile
.
Close
()
}
func
(
self
*
MountState
)
handle
(
in_data
[]
byte
)
{
func
(
me
*
MountState
)
handle
(
in_data
[]
byte
)
{
r
:=
bytes
.
NewBuffer
(
in_data
)
header
:=
new
(
InHeader
)
err
:=
binary
.
Read
(
r
,
binary
.
LittleEndian
,
header
)
...
...
@@ -276,11 +276,11 @@ func (self *MountState) handle(in_data []byte) {
err
=
os
.
NewError
(
fmt
.
Sprintf
(
"MountPoint, handle: can't read a header, in_data: %v"
,
in_data
))
}
if
err
!=
nil
{
self
.
Error
(
err
)
me
.
Error
(
err
)
return
}
self
.
Write
(
dispatch
(
self
,
header
,
r
))
self
.
buffers
.
FreeBuffer
(
in_data
)
me
.
Write
(
dispatch
(
me
,
header
,
r
))
me
.
buffers
.
FreeBuffer
(
in_data
)
}
...
...
fuse/pathfilesystem.go
View file @
7c3c1e41
...
...
@@ -45,20 +45,20 @@ func inodeDataKey(parentInode uint64, name string) string {
return
string
(
parentInode
)
+
":"
+
name
}
func
(
self
*
inodeData
)
Key
()
string
{
func
(
me
*
inodeData
)
Key
()
string
{
var
p
uint64
=
0
if
self
.
Parent
!=
nil
{
p
=
self
.
Parent
.
NodeId
if
me
.
Parent
!=
nil
{
p
=
me
.
Parent
.
NodeId
}
return
inodeDataKey
(
p
,
self
.
Name
)
return
inodeDataKey
(
p
,
me
.
Name
)
}
func
(
self
*
inodeData
)
GetPath
()
(
path
string
,
mount
*
mountData
)
{
func
(
me
*
inodeData
)
GetPath
()
(
path
string
,
mount
*
mountData
)
{
// TODO - softcode this.
var
components
[
100
]
string
j
:=
len
(
components
)
inode
:=
self
inode
:=
me
for
;
inode
!=
nil
&&
inode
.
mount
==
nil
;
inode
=
inode
.
Parent
{
j
--
components
[
j
]
=
inode
.
Name
...
...
@@ -116,8 +116,8 @@ type PathFileSystemConnector struct {
}
// Must be called with lock held.
func
(
self
*
PathFileSystemConnector
)
setParent
(
data
*
inodeData
,
parentId
uint64
)
{
newParent
:=
self
.
inodePathMapByInode
[
parentId
]
func
(
me
*
PathFileSystemConnector
)
setParent
(
data
*
inodeData
,
parentId
uint64
)
{
newParent
:=
me
.
inodePathMapByInode
[
parentId
]
if
data
.
Parent
==
newParent
{
return
}
...
...
@@ -128,7 +128,7 @@ func (self *PathFileSystemConnector) setParent(data *inodeData, parentId uint64)
oldParent
:=
data
.
Parent
if
oldParent
!=
nil
{
self
.
unrefNode
(
oldParent
)
me
.
unrefNode
(
oldParent
)
}
data
.
Parent
=
newParent
if
newParent
!=
nil
{
...
...
@@ -137,74 +137,74 @@ func (self *PathFileSystemConnector) setParent(data *inodeData, parentId uint64)
}
// Must be called with lock held.
func
(
self
*
PathFileSystemConnector
)
unrefNode
(
data
*
inodeData
)
{
func
(
me
*
PathFileSystemConnector
)
unrefNode
(
data
*
inodeData
)
{
data
.
RefCount
--
if
data
.
RefCount
<=
0
&&
data
.
LookupCount
<=
0
{
self
.
inodePathMapByInode
[
data
.
NodeId
]
=
nil
,
false
me
.
inodePathMapByInode
[
data
.
NodeId
]
=
nil
,
false
}
}
func
(
self
*
PathFileSystemConnector
)
lookup
(
key
string
)
*
inodeData
{
self
.
lock
.
RLock
()
defer
self
.
lock
.
RUnlock
()
return
self
.
inodePathMap
[
key
]
func
(
me
*
PathFileSystemConnector
)
lookup
(
key
string
)
*
inodeData
{
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
return
me
.
inodePathMap
[
key
]
}
func
(
self
*
PathFileSystemConnector
)
lookupUpdate
(
nodeId
uint64
,
name
string
)
*
inodeData
{
func
(
me
*
PathFileSystemConnector
)
lookupUpdate
(
nodeId
uint64
,
name
string
)
*
inodeData
{
key
:=
inodeDataKey
(
nodeId
,
name
)
data
:=
self
.
lookup
(
key
)
data
:=
me
.
lookup
(
key
)
if
data
!=
nil
{
return
data
}
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
data
,
ok
:=
self
.
inodePathMap
[
key
]
data
,
ok
:=
me
.
inodePathMap
[
key
]
if
!
ok
{
data
=
new
(
inodeData
)
self
.
setParent
(
data
,
nodeId
)
data
.
NodeId
=
self
.
nextFreeInode
me
.
setParent
(
data
,
nodeId
)
data
.
NodeId
=
me
.
nextFreeInode
data
.
Name
=
name
self
.
nextFreeInode
++
me
.
nextFreeInode
++
self
.
inodePathMapByInode
[
data
.
NodeId
]
=
data
self
.
inodePathMap
[
key
]
=
data
me
.
inodePathMapByInode
[
data
.
NodeId
]
=
data
me
.
inodePathMap
[
key
]
=
data
}
return
data
}
func
(
self
*
PathFileSystemConnector
)
getInodeData
(
nodeid
uint64
)
*
inodeData
{
self
.
lock
.
RLock
()
defer
self
.
lock
.
RUnlock
()
func
(
me
*
PathFileSystemConnector
)
getInodeData
(
nodeid
uint64
)
*
inodeData
{
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
val
:=
self
.
inodePathMapByInode
[
nodeid
]
val
:=
me
.
inodePathMapByInode
[
nodeid
]
if
val
==
nil
{
panic
(
fmt
.
Sprintf
(
"inode %v unknown"
,
nodeid
))
}
return
val
}
func
(
self
*
PathFileSystemConnector
)
forgetUpdate
(
nodeId
uint64
,
forgetCount
int
)
{
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
func
(
me
*
PathFileSystemConnector
)
forgetUpdate
(
nodeId
uint64
,
forgetCount
int
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
data
,
ok
:=
self
.
inodePathMapByInode
[
nodeId
]
data
,
ok
:=
me
.
inodePathMapByInode
[
nodeId
]
if
ok
{
data
.
LookupCount
-=
forgetCount
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
mount
==
nil
||
data
.
mount
.
unmountPending
)
{
self
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
me
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
}
}
}
func
(
self
*
PathFileSystemConnector
)
renameUpdate
(
oldParent
uint64
,
oldName
string
,
newParent
uint64
,
newName
string
)
{
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
func
(
me
*
PathFileSystemConnector
)
renameUpdate
(
oldParent
uint64
,
oldName
string
,
newParent
uint64
,
newName
string
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
oldKey
:=
inodeDataKey
(
oldParent
,
oldName
)
data
:=
self
.
inodePathMap
[
oldKey
]
data
:=
me
.
inodePathMap
[
oldKey
]
if
data
==
nil
{
// This can happen if a rename raced with an unlink or
// another rename.
...
...
@@ -215,13 +215,13 @@ func (self *PathFileSystemConnector) renameUpdate(oldParent uint64, oldName stri
return
}
self
.
inodePathMap
[
oldKey
]
=
nil
,
false
me
.
inodePathMap
[
oldKey
]
=
nil
,
false
self
.
setParent
(
data
,
newParent
)
me
.
setParent
(
data
,
newParent
)
data
.
Name
=
newName
newKey
:=
data
.
Key
()
target
:=
self
.
inodePathMap
[
newKey
]
target
:=
me
.
inodePathMap
[
newKey
]
if
target
!=
nil
{
// This could happen if some other thread creates a
// file in the destination position.
...
...
@@ -231,47 +231,47 @@ func (self *PathFileSystemConnector) renameUpdate(oldParent uint64, oldName stri
// fuse.c just removes the node from its internal
// tables, which might lead to paths being both directories
// (parents) and normal files?
self
.
inodePathMap
[
newKey
]
=
nil
,
false
me
.
inodePathMap
[
newKey
]
=
nil
,
false
self
.
setParent
(
target
,
FUSE_ROOT_ID
)
target
.
Name
=
fmt
.
Sprintf
(
"overwrittenByRename%d"
,
self
.
nextFreeInode
)
self
.
nextFreeInode
++
me
.
setParent
(
target
,
FUSE_ROOT_ID
)
target
.
Name
=
fmt
.
Sprintf
(
"overwrittenByRename%d"
,
me
.
nextFreeInode
)
me
.
nextFreeInode
++
self
.
inodePathMap
[
target
.
Key
()]
=
target
me
.
inodePathMap
[
target
.
Key
()]
=
target
}
self
.
inodePathMap
[
data
.
Key
()]
=
data
me
.
inodePathMap
[
data
.
Key
()]
=
data
}
func
(
self
*
PathFileSystemConnector
)
unlinkUpdate
(
nodeid
uint64
,
name
string
)
{
self
.
lock
.
Lock
()
defer
self
.
lock
.
Unlock
()
func
(
me
*
PathFileSystemConnector
)
unlinkUpdate
(
nodeid
uint64
,
name
string
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
oldKey
:=
inodeDataKey
(
nodeid
,
name
)
data
:=
self
.
inodePathMap
[
oldKey
]
data
:=
me
.
inodePathMap
[
oldKey
]
if
data
!=
nil
{
self
.
inodePathMap
[
oldKey
]
=
nil
,
false
self
.
unrefNode
(
data
)
me
.
inodePathMap
[
oldKey
]
=
nil
,
false
me
.
unrefNode
(
data
)
}
}
// Walk the file system starting from the root.
func
(
self
*
PathFileSystemConnector
)
findInode
(
fullPath
string
)
*
inodeData
{
func
(
me
*
PathFileSystemConnector
)
findInode
(
fullPath
string
)
*
inodeData
{
fullPath
=
strings
.
TrimLeft
(
path
.
Clean
(
fullPath
),
"/"
)
comps
:=
strings
.
Split
(
fullPath
,
"/"
,
-
1
)
self
.
lock
.
RLock
()
defer
self
.
lock
.
RUnlock
()
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
node
:=
self
.
inodePathMapByInode
[
FUSE_ROOT_ID
]
node
:=
me
.
inodePathMapByInode
[
FUSE_ROOT_ID
]
for
i
,
component
:=
range
comps
{
if
len
(
component
)
==
0
{
continue
}
key
:=
inodeDataKey
(
node
.
NodeId
,
component
)
node
=
self
.
inodePathMap
[
key
]
node
=
me
.
inodePathMap
[
key
]
if
node
==
nil
{
panic
(
fmt
.
Sprintf
(
"findInode: %v %v"
,
i
,
fullPath
))
}
...
...
@@ -306,23 +306,23 @@ func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector
return
out
}
func
(
self
*
PathFileSystemConnector
)
SetOptions
(
opts
PathFileSystemConnectorOptions
)
{
self
.
options
=
opts
func
(
me
*
PathFileSystemConnector
)
SetOptions
(
opts
PathFileSystemConnectorOptions
)
{
me
.
options
=
opts
}
func
(
self
*
PathFileSystemConnector
)
Mount
(
mountPoint
string
,
fs
PathFilesystem
)
Status
{
func
(
me
*
PathFileSystemConnector
)
Mount
(
mountPoint
string
,
fs
PathFilesystem
)
Status
{
var
node
*
inodeData
if
mountPoint
!=
"/"
{
dirParent
,
base
:=
path
.
Split
(
mountPoint
)
dirParentNode
:=
self
.
findInode
(
dirParent
)
dirParentNode
:=
me
.
findInode
(
dirParent
)
// Make sure we know the mount point.
attr
,
_
:=
self
.
internalLookup
(
dirParentNode
.
NodeId
,
base
,
0
)
attr
,
_
:=
me
.
internalLookup
(
dirParentNode
.
NodeId
,
base
,
0
)
}
node
=
self
.
findInode
(
mountPoint
)
node
=
me
.
findInode
(
mountPoint
)
// TODO - check that fs was not mounted elsewhere.
if
node
.
RefCount
>
0
{
...
...
@@ -332,15 +332,15 @@ func (self *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem)
return
EINVAL
}
code
:=
fs
.
Mount
(
self
)
code
:=
fs
.
Mount
(
me
)
if
code
!=
OK
{
if
self
.
Debug
{
if
me
.
Debug
{
log
.
Println
(
"Mount error: "
,
mountPoint
,
code
)
}
return
code
}
if
self
.
Debug
{
if
me
.
Debug
{
log
.
Println
(
"Mount: "
,
fs
,
"on"
,
mountPoint
,
node
)
}
...
...
@@ -354,8 +354,8 @@ func (self *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem)
return
OK
}
func
(
self
*
PathFileSystemConnector
)
Unmount
(
path
string
)
Status
{
node
:=
self
.
findInode
(
path
)
func
(
me
*
PathFileSystemConnector
)
Unmount
(
path
string
)
Status
{
node
:=
me
.
findInode
(
path
)
if
node
==
nil
{
panic
(
path
)
}
...
...
@@ -370,7 +370,7 @@ func (self *PathFileSystemConnector) Unmount(path string) Status {
return
EBUSY
}
if
self
.
Debug
{
if
me
.
Debug
{
log
.
Println
(
"Unmount: "
,
mount
)
}
// node manipulations are racy?
...
...
@@ -388,46 +388,46 @@ func (self *PathFileSystemConnector) Unmount(path string) Status {
return
OK
}
func
(
self
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
mount
*
mountData
)
{
return
self
.
getInodeData
(
nodeid
)
.
GetPath
()
func
(
me
*
PathFileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
mount
*
mountData
)
{
return
me
.
getInodeData
(
nodeid
)
.
GetPath
()
}
func
(
self
*
PathFileSystemConnector
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
func
(
me
*
PathFileSystemConnector
)
Init
(
h
*
InHeader
,
input
*
InitIn
)
(
*
InitOut
,
Status
)
{
// TODO ?
return
new
(
InitOut
),
OK
}
func
(
self
*
PathFileSystemConnector
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
func
(
me
*
PathFileSystemConnector
)
Destroy
(
h
*
InHeader
,
input
*
InitIn
)
{
// TODO - umount all.
}
func
(
self
*
PathFileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
return
self
.
internalLookup
(
header
.
NodeId
,
name
,
1
)
func
(
me
*
PathFileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
return
me
.
internalLookup
(
header
.
NodeId
,
name
,
1
)
}
func
(
self
*
PathFileSystemConnector
)
internalLookup
(
nodeid
uint64
,
name
string
,
lookupCount
int
)
(
out
*
EntryOut
,
status
Status
)
{
parent
:=
self
.
getInodeData
(
nodeid
)
func
(
me
*
PathFileSystemConnector
)
internalLookup
(
nodeid
uint64
,
name
string
,
lookupCount
int
)
(
out
*
EntryOut
,
status
Status
)
{
parent
:=
me
.
getInodeData
(
nodeid
)
// TODO - fuse.c has special case code for name == "." and
// "..", those lookups happen if FUSE_EXPORT_SUPPORT is set in
// Init.
fullPath
,
mount
:=
parent
.
GetPath
()
if
mount
==
nil
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
return
NegativeEntry
(
me
.
options
.
NegativeTimeout
),
OK
}
fullPath
=
path
.
Join
(
fullPath
,
name
)
attr
,
err
:=
mount
.
fs
.
GetAttr
(
fullPath
)
if
err
==
ENOENT
&&
self
.
options
.
NegativeTimeout
>
0.0
{
return
NegativeEntry
(
self
.
options
.
NegativeTimeout
),
OK
if
err
==
ENOENT
&&
me
.
options
.
NegativeTimeout
>
0.0
{
return
NegativeEntry
(
me
.
options
.
NegativeTimeout
),
OK
}
if
err
!=
OK
{
return
nil
,
err
}
data
:=
self
.
lookupUpdate
(
nodeid
,
name
)
data
:=
me
.
lookupUpdate
(
nodeid
,
name
)
data
.
LookupCount
+=
lookupCount
data
.
Type
=
ModeToType
(
attr
.
Mode
)
...
...
@@ -435,20 +435,20 @@ func (self *PathFileSystemConnector) internalLookup(nodeid uint64, name string,
out
.
NodeId
=
data
.
NodeId
out
.
Generation
=
1
// where to get the generation?
SplitNs
(
self
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
self
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
SplitNs
(
me
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
out
.
Attr
=
*
attr
out
.
Attr
.
Ino
=
data
.
NodeId
return
out
,
OK
}
func
(
self
*
PathFileSystemConnector
)
Forget
(
h
*
InHeader
,
input
*
ForgetIn
)
{
self
.
forgetUpdate
(
h
.
NodeId
,
int
(
input
.
Nlookup
))
func
(
me
*
PathFileSystemConnector
)
Forget
(
h
*
InHeader
,
input
*
ForgetIn
)
{
me
.
forgetUpdate
(
h
.
NodeId
,
int
(
input
.
Nlookup
))
}
func
(
self
*
PathFileSystemConnector
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
GetAttr
(
header
*
InHeader
,
input
*
GetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
// TODO - should we update inodeData.Type?
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -460,13 +460,13 @@ func (self *PathFileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn)
out
=
new
(
AttrOut
)
out
.
Attr
=
*
attr
out
.
Attr
.
Ino
=
header
.
NodeId
SplitNs
(
self
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
return
out
,
OK
}
func
(
self
*
PathFileSystemConnector
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseDir
,
status
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
ENOENT
}
...
...
@@ -480,14 +480,14 @@ func (self *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (f
mount
.
openDirs
++
de
:=
new
(
FuseDir
)
de
.
connector
=
self
de
.
connector
=
me
de
.
parentIno
=
header
.
NodeId
de
.
stream
=
stream
return
0
,
de
,
OK
}
func
(
self
*
PathFileSystemConnector
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
status
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
ENOENT
}
...
...
@@ -502,11 +502,11 @@ func (self *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flag
return
0
,
f
,
OK
}
func
(
self
*
PathFileSystemConnector
)
SetAttr
(
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
SetAttr
(
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
*
AttrOut
,
code
Status
)
{
var
err
Status
=
OK
// TODO - support Fh. (FSetAttr/FGetAttr/FTruncate.)
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -535,11 +535,11 @@ func (self *PathFileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn)
}
// TODO - where to get GetAttrIn.Flags / Fh ?
return
self
.
GetAttr
(
header
,
new
(
GetAttrIn
))
return
me
.
GetAttr
(
header
,
new
(
GetAttrIn
))
}
func
(
self
*
PathFileSystemConnector
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Readlink
(
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -547,8 +547,8 @@ func (self *PathFileSystemConnector) Readlink(header *InHeader) (out []byte, cod
return
bytes
.
NewBufferString
(
val
)
.
Bytes
(),
err
}
func
(
self
*
PathFileSystemConnector
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Mknod
(
header
*
InHeader
,
input
*
MknodIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -557,11 +557,11 @@ func (self *PathFileSystemConnector) Mknod(header *InHeader, input *MknodIn, nam
if
err
!=
OK
{
return
nil
,
err
}
return
self
.
Lookup
(
header
,
name
)
return
me
.
Lookup
(
header
,
name
)
}
func
(
self
*
PathFileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -569,35 +569,35 @@ func (self *PathFileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, nam
if
err
!=
OK
{
return
nil
,
err
}
out
,
code
=
self
.
Lookup
(
header
,
name
)
out
,
code
=
me
.
Lookup
(
header
,
name
)
return
out
,
code
}
func
(
self
*
PathFileSystemConnector
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Unlink
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
code
=
mount
.
fs
.
Unlink
(
path
.
Join
(
fullPath
,
name
))
// Like fuse.c, we update our internal tables.
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
me
.
unlinkUpdate
(
header
.
NodeId
,
name
)
return
code
}
func
(
self
*
PathFileSystemConnector
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Rmdir
(
header
*
InHeader
,
name
string
)
(
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
code
=
mount
.
fs
.
Rmdir
(
path
.
Join
(
fullPath
,
name
))
self
.
unlinkUpdate
(
header
.
NodeId
,
name
)
me
.
unlinkUpdate
(
header
.
NodeId
,
name
)
return
code
}
func
(
self
*
PathFileSystemConnector
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Symlink
(
header
*
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
EntryOut
,
code
Status
)
{
fullPath
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
nil
,
ENOENT
}
...
...
@@ -606,13 +606,13 @@ func (self *PathFileSystemConnector) Symlink(header *InHeader, pointedTo string,
return
nil
,
err
}
out
,
code
=
self
.
Lookup
(
header
,
linkName
)
out
,
code
=
me
.
Lookup
(
header
,
linkName
)
return
out
,
code
}
func
(
self
*
PathFileSystemConnector
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldPath
,
oldMount
:=
self
.
GetPath
(
header
.
NodeId
)
newPath
,
mount
:=
self
.
GetPath
(
input
.
Newdir
)
func
(
me
*
PathFileSystemConnector
)
Rename
(
header
*
InHeader
,
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldPath
,
oldMount
:=
me
.
GetPath
(
header
.
NodeId
)
newPath
,
mount
:=
me
.
GetPath
(
input
.
Newdir
)
if
mount
==
nil
||
oldMount
==
nil
{
return
ENOENT
}
...
...
@@ -634,13 +634,13 @@ func (self *PathFileSystemConnector) Rename(header *InHeader, input *RenameIn, o
//
// It should not hurt for us to do it here as well, although
// it remains unclear how we should update Count.
self
.
renameUpdate
(
header
.
NodeId
,
oldName
,
input
.
Newdir
,
newName
)
me
.
renameUpdate
(
header
.
NodeId
,
oldName
,
input
.
Newdir
,
newName
)
return
code
}
func
(
self
*
PathFileSystemConnector
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
filename
string
)
(
out
*
EntryOut
,
code
Status
)
{
orig
,
mount
:=
self
.
GetPath
(
input
.
Oldnodeid
)
newName
,
newMount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Link
(
header
*
InHeader
,
input
*
LinkIn
,
filename
string
)
(
out
*
EntryOut
,
code
Status
)
{
orig
,
mount
:=
me
.
GetPath
(
input
.
Oldnodeid
)
newName
,
newMount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
||
newMount
==
nil
{
return
nil
,
ENOENT
...
...
@@ -655,19 +655,19 @@ func (self *PathFileSystemConnector) Link(header *InHeader, input *LinkIn, filen
return
nil
,
err
}
return
self
.
Lookup
(
header
,
filename
)
return
me
.
Lookup
(
header
,
filename
)
}
func
(
self
*
PathFileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
p
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
p
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
ENOENT
}
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
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
fuseFile
RawFuseFile
,
out
*
EntryOut
,
code
Status
)
{
directory
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
if
mount
==
nil
{
return
0
,
nil
,
nil
,
ENOENT
}
...
...
@@ -679,39 +679,39 @@ func (self *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, n
}
mount
.
openFiles
++
out
,
code
=
self
.
Lookup
(
header
,
name
)
out
,
code
=
me
.
Lookup
(
header
,
name
)
return
0
,
f
,
out
,
code
}
func
(
self
*
PathFileSystemConnector
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
_
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
mount
.
openFiles
--
}
func
(
self
*
PathFileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
_
,
mount
:=
self
.
GetPath
(
header
.
NodeId
)
func
(
me
*
PathFileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
mount
.
openDirs
--
}
////////////////////////////////////////////////////////////////
// unimplemented.
func
(
self
*
PathFileSystemConnector
)
SetXAttr
(
header
*
InHeader
,
input
*
SetXAttrIn
)
Status
{
func
(
me
*
PathFileSystemConnector
)
SetXAttr
(
header
*
InHeader
,
input
*
SetXAttrIn
)
Status
{
return
ENOSYS
}
func
(
self
*
PathFileSystemConnector
)
GetXAttr
(
header
*
InHeader
,
input
*
GetXAttrIn
)
(
out
*
GetXAttrOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
GetXAttr
(
header
*
InHeader
,
input
*
GetXAttrIn
)
(
out
*
GetXAttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
PathFileSystemConnector
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
PathFileSystemConnector
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
self
*
PathFileSystemConnector
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
func
(
me
*
PathFileSystemConnector
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
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