Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go-fuse
Commits
0155dffe
Commit
0155dffe
authored
Aug 04, 2016
by
Adam H. Leventhal
Committed by
Han-Wen Nienhuys
Aug 10, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed all tests on Darwin
Fixed handling of ENOSYS in unionfs.
parent
bddfd80b
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
202 additions
and
98 deletions
+202
-98
README
README
+1
-2
fuse/pathfs/loopback_darwin.go
fuse/pathfs/loopback_darwin.go
+3
-2
fuse/test/loopback_darwin_test.go
fuse/test/loopback_darwin_test.go
+11
-5
unionfs/autounion.go
unionfs/autounion.go
+11
-20
unionfs/autounion_test.go
unionfs/autounion_test.go
+26
-16
unionfs/unionfs.go
unionfs/unionfs.go
+1
-1
unionfs/unionfs_test.go
unionfs/unionfs_test.go
+7
-39
unionfs/unionfs_test_linux.go
unionfs/unionfs_test_linux.go
+44
-0
unionfs/unionfs_xattr_test.go
unionfs/unionfs_xattr_test.go
+21
-5
unionfs/unionfs_xattr_test_darwin.go
unionfs/unionfs_xattr_test_darwin.go
+37
-0
unionfs/unionfs_xattr_test_linux.go
unionfs/unionfs_xattr_test_linux.go
+14
-0
zipfs/multizip.go
zipfs/multizip.go
+2
-1
zipfs/multizip_test.go
zipfs/multizip_test.go
+23
-7
zipfs/zipfs_test.go
zipfs/zipfs_test.go
+1
-0
No files found.
README
View file @
0155dffe
...
@@ -104,8 +104,7 @@ go-fuse works somewhat on OSX. Known limitations:
...
@@ -104,8 +104,7 @@ go-fuse works somewhat on OSX. Known limitations:
* OSX has trouble with concurrent reads from the FUSE device, leading
* OSX has trouble with concurrent reads from the FUSE device, leading
to performance concerns.
to performance concerns.
* A bunch of tests under fuse/test/ fail, and the functionality they
* Tests are expected to pass; report any failure as a bug!
test for OSX is likely broken.
CREDITS
CREDITS
...
...
fuse/pathfs/loopback_darwin.go
View file @
0155dffe
...
@@ -17,11 +17,12 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
...
@@ -17,11 +17,12 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
if
err
==
nil
{
if
err
==
nil
{
return
&
fuse
.
StatfsOut
{
return
&
fuse
.
StatfsOut
{
Blocks
:
s
.
Blocks
,
Blocks
:
s
.
Blocks
,
Bsize
:
uint32
(
s
.
Bsize
),
Bfree
:
s
.
Bfree
,
Bfree
:
s
.
Bfree
,
Bavail
:
s
.
Bavail
,
Bavail
:
s
.
Bavail
,
Files
:
s
.
Files
,
Files
:
s
.
Files
,
Ffree
:
s
.
Ffree
,
Ffree
:
s
.
Ffree
,
Bsize
:
uint32
(
s
.
Iosize
),
// Iosize translates to Bsize: the optimal transfer size.
Frsize
:
s
.
Bsize
,
// Bsize translates to Frsize: the minimum transfer size.
}
}
}
}
return
nil
return
nil
...
@@ -58,6 +59,6 @@ func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, c
...
@@ -58,6 +59,6 @@ func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, c
tv
[
1
]
=
timeToTimeval
(
m
)
tv
[
1
]
=
timeToTimeval
(
m
)
}
}
err
:=
syscall
.
Utimes
(
path
,
tv
)
err
:=
syscall
.
Utimes
(
fs
.
GetPath
(
path
)
,
tv
)
return
fuse
.
ToStatus
(
err
)
return
fuse
.
ToStatus
(
err
)
}
}
fuse/test/loopback_darwin_test.go
View file @
0155dffe
...
@@ -10,9 +10,15 @@ import (
...
@@ -10,9 +10,15 @@ import (
func
clearStatfs
(
s
*
syscall
.
Statfs_t
)
{
func
clearStatfs
(
s
*
syscall
.
Statfs_t
)
{
empty
:=
syscall
.
Statfs_t
{}
empty
:=
syscall
.
Statfs_t
{}
s
.
Type
=
0
s
.
Fsid
=
empty
.
Fsid
// FUSE can only set the following fields.
// s.Spare = empty.Spare
empty
.
Blocks
=
s
.
Blocks
// TODO - figure out what this is for.
empty
.
Bfree
=
s
.
Bfree
s
.
Flags
=
0
empty
.
Bavail
=
s
.
Bavail
empty
.
Files
=
s
.
Files
empty
.
Ffree
=
s
.
Ffree
empty
.
Iosize
=
s
.
Iosize
empty
.
Bsize
=
s
.
Bsize
// Clear out the rest.
*
s
=
empty
}
}
unionfs/autounion.go
View file @
0155dffe
...
@@ -301,40 +301,33 @@ func (fs *autoUnionFs) GetXAttr(name string, attr string, context *fuse.Context)
...
@@ -301,40 +301,33 @@ func (fs *autoUnionFs) GetXAttr(name string, attr string, context *fuse.Context)
}
}
func
(
fs
*
autoUnionFs
)
GetAttr
(
path
string
,
context
*
fuse
.
Context
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
func
(
fs
*
autoUnionFs
)
GetAttr
(
path
string
,
context
*
fuse
.
Context
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
if
path
==
""
||
path
==
_CONFIG
||
path
==
_STATUS
{
a
:=
&
fuse
.
Attr
{
a
:=
&
fuse
.
Attr
{
Mode
:
fuse
.
S_IFDIR
|
0755
,
Owner
:
*
fuse
.
CurrentOwner
()
,
}
}
if
path
==
""
||
path
==
_CONFIG
||
path
==
_STATUS
{
a
.
Mode
=
fuse
.
S_IFDIR
|
0755
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
if
path
==
filepath
.
Join
(
_STATUS
,
_VERSION
)
{
if
path
==
filepath
.
Join
(
_STATUS
,
_VERSION
)
{
a
:=
&
fuse
.
Attr
{
a
.
Mode
=
fuse
.
S_IFREG
|
0644
Mode
:
fuse
.
S_IFREG
|
0644
,
a
.
Size
=
uint64
(
len
(
fs
.
options
.
Version
))
Size
:
uint64
(
len
(
fs
.
options
.
Version
)),
}
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
if
path
==
filepath
.
Join
(
_STATUS
,
_DEBUG
)
{
if
path
==
filepath
.
Join
(
_STATUS
,
_DEBUG
)
{
a
:=
&
fuse
.
Attr
{
a
.
Mode
=
fuse
.
S_IFREG
|
0644
Mode
:
fuse
.
S_IFREG
|
0644
,
a
.
Size
=
uint64
(
len
(
fs
.
DebugData
()))
Size
:
uint64
(
len
(
fs
.
DebugData
())),
}
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
if
path
==
filepath
.
Join
(
_STATUS
,
_ROOT
)
{
if
path
==
filepath
.
Join
(
_STATUS
,
_ROOT
)
{
a
:=
&
fuse
.
Attr
{
a
.
Mode
=
syscall
.
S_IFLNK
|
0644
Mode
:
syscall
.
S_IFLNK
|
0644
,
}
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
if
path
==
filepath
.
Join
(
_CONFIG
,
_SCAN_CONFIG
)
{
if
path
==
filepath
.
Join
(
_CONFIG
,
_SCAN_CONFIG
)
{
a
:=
&
fuse
.
Attr
{
a
.
Mode
=
fuse
.
S_IFREG
|
0644
Mode
:
fuse
.
S_IFREG
|
0644
,
}
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
comps
:=
strings
.
Split
(
path
,
string
(
filepath
.
Separator
))
comps
:=
strings
.
Split
(
path
,
string
(
filepath
.
Separator
))
...
@@ -346,9 +339,7 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr,
...
@@ -346,9 +339,7 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr,
return
nil
,
fuse
.
ENOENT
return
nil
,
fuse
.
ENOENT
}
}
a
:=
&
fuse
.
Attr
{
a
.
Mode
=
syscall
.
S_IFLNK
|
0644
Mode
:
syscall
.
S_IFLNK
|
0644
,
}
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
...
...
unionfs/autounion_test.go
View file @
0155dffe
...
@@ -23,6 +23,7 @@ var testAOpts = AutoUnionFsOptions{
...
@@ -23,6 +23,7 @@ var testAOpts = AutoUnionFsOptions{
EntryTimeout
:
entryTtl
,
EntryTimeout
:
entryTtl
,
AttrTimeout
:
entryTtl
,
AttrTimeout
:
entryTtl
,
NegativeTimeout
:
0
,
NegativeTimeout
:
0
,
Debug
:
VerboseTest
(),
},
},
HideReadonly
:
true
,
HideReadonly
:
true
,
Version
:
"version"
,
Version
:
"version"
,
...
@@ -39,7 +40,7 @@ func WriteFile(t *testing.T, name string, contents string) {
...
@@ -39,7 +40,7 @@ func WriteFile(t *testing.T, name string, contents string) {
}
}
}
}
func
setup
(
t
*
testing
.
T
)
(
workdir
string
,
cleanup
func
())
{
func
setup
(
t
*
testing
.
T
)
(
workdir
string
,
server
*
fuse
.
Server
,
cleanup
func
())
{
wd
,
_
:=
ioutil
.
TempDir
(
""
,
""
)
wd
,
_
:=
ioutil
.
TempDir
(
""
,
""
)
err
:=
os
.
Mkdir
(
wd
+
"/mnt"
,
0700
)
err
:=
os
.
Mkdir
(
wd
+
"/mnt"
,
0700
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -66,15 +67,16 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
...
@@ -66,15 +67,16 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
}
}
go
state
.
Serve
()
go
state
.
Serve
()
state
.
WaitMount
()
return
wd
,
func
()
{
return
wd
,
state
,
func
()
{
state
.
Unmount
()
state
.
Unmount
()
os
.
RemoveAll
(
wd
)
os
.
RemoveAll
(
wd
)
}
}
}
}
func
TestDebug
(
t
*
testing
.
T
)
{
func
TestDebug
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
_
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
c
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/status/debug"
)
c
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/status/debug"
)
...
@@ -87,7 +89,7 @@ func TestDebug(t *testing.T) {
...
@@ -87,7 +89,7 @@ func TestDebug(t *testing.T) {
}
}
func
TestVersion
(
t
*
testing
.
T
)
{
func
TestVersion
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
_
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
c
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/status/gounionfs_version"
)
c
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/status/gounionfs_version"
)
...
@@ -100,7 +102,7 @@ func TestVersion(t *testing.T) {
...
@@ -100,7 +102,7 @@ func TestVersion(t *testing.T) {
}
}
func
TestAutoFsSymlink
(
t
*
testing
.
T
)
{
func
TestAutoFsSymlink
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
server
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
err
:=
os
.
Mkdir
(
wd
+
"/store/backing1"
,
0755
)
err
:=
os
.
Mkdir
(
wd
+
"/store/backing1"
,
0755
)
...
@@ -142,15 +144,23 @@ func TestAutoFsSymlink(t *testing.T) {
...
@@ -142,15 +144,23 @@ func TestAutoFsSymlink(t *testing.T) {
t
.
Error
(
"error writing:"
,
err
)
t
.
Error
(
"error writing:"
,
err
)
}
}
// If FUSE supports invalid inode notifications we expect this node to be gone. Otherwise we'll just make sure that it's not reachable.
if
server
.
KernelSettings
()
.
SupportsNotify
(
fuse
.
NOTIFY_INVAL_INODE
)
{
fi
,
_
=
os
.
Lstat
(
wd
+
"/mnt/manual1"
)
fi
,
_
=
os
.
Lstat
(
wd
+
"/mnt/manual1"
)
if
fi
!=
nil
{
if
fi
!=
nil
{
t
.
Error
(
"Should not have file:"
,
fi
)
t
.
Error
(
"Should not have file:"
,
fi
)
}
}
}
else
{
_
,
err
=
ioutil
.
ReadDir
(
wd
+
"/mnt/config
"
)
entries
,
err
=
ioutil
.
ReadDir
(
wd
+
"/mnt
"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
}
for
_
,
e
:=
range
entries
{
if
e
.
Name
()
==
"manual1"
{
t
.
Error
(
"Should not have entry: "
,
e
)
}
}
}
_
,
err
=
os
.
Lstat
(
wd
+
"/mnt/backing1/file1"
)
_
,
err
=
os
.
Lstat
(
wd
+
"/mnt/backing1/file1"
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -159,7 +169,7 @@ func TestAutoFsSymlink(t *testing.T) {
...
@@ -159,7 +169,7 @@ func TestAutoFsSymlink(t *testing.T) {
}
}
func
TestDetectSymlinkedDirectories
(
t
*
testing
.
T
)
{
func
TestDetectSymlinkedDirectories
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
_
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
err
:=
os
.
Mkdir
(
wd
+
"/backing1"
,
0755
)
err
:=
os
.
Mkdir
(
wd
+
"/backing1"
,
0755
)
...
@@ -190,7 +200,7 @@ func TestDetectSymlinkedDirectories(t *testing.T) {
...
@@ -190,7 +200,7 @@ func TestDetectSymlinkedDirectories(t *testing.T) {
}
}
func
TestExplicitScan
(
t
*
testing
.
T
)
{
func
TestExplicitScan
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
_
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
err
:=
os
.
Mkdir
(
wd
+
"/store/backing1"
,
0755
)
err
:=
os
.
Mkdir
(
wd
+
"/store/backing1"
,
0755
)
...
@@ -225,7 +235,7 @@ func TestExplicitScan(t *testing.T) {
...
@@ -225,7 +235,7 @@ func TestExplicitScan(t *testing.T) {
}
}
func
TestCreationChecks
(
t
*
testing
.
T
)
{
func
TestCreationChecks
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setup
(
t
)
wd
,
_
,
clean
:=
setup
(
t
)
defer
clean
()
defer
clean
()
err
:=
os
.
Mkdir
(
wd
+
"/store/foo"
,
0755
)
err
:=
os
.
Mkdir
(
wd
+
"/store/foo"
,
0755
)
...
...
unionfs/unionfs.go
View file @
0155dffe
...
@@ -570,7 +570,7 @@ func (fs *unionFS) Chmod(name string, mode uint32, context *fuse.Context) (code
...
@@ -570,7 +570,7 @@ func (fs *unionFS) Chmod(name string, mode uint32, context *fuse.Context) (code
func
(
fs
*
unionFS
)
Access
(
name
string
,
mode
uint32
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
func
(
fs
*
unionFS
)
Access
(
name
string
,
mode
uint32
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
// We always allow writing.
// We always allow writing.
mode
=
mode
&^
fuse
.
W_OK
mode
=
mode
&^
fuse
.
W_OK
if
name
==
""
{
if
name
==
""
||
name
==
_DROP_CACHE
{
return
fuse
.
OK
return
fuse
.
OK
}
}
r
:=
fs
.
getBranch
(
name
)
r
:=
fs
.
getBranch
(
name
)
...
...
unionfs/unionfs_test.go
View file @
0155dffe
...
@@ -106,6 +106,7 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) {
...
@@ -106,6 +106,7 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) {
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
}
}
go
state
.
Serve
()
go
state
.
Serve
()
state
.
WaitMount
()
return
wd
,
func
()
{
return
wd
,
func
()
{
err
:=
state
.
Unmount
()
err
:=
state
.
Unmount
()
...
@@ -243,8 +244,9 @@ func TestUnionFsChtimes(t *testing.T) {
...
@@ -243,8 +244,9 @@ func TestUnionFsChtimes(t *testing.T) {
}
}
fi
,
err
:=
os
.
Lstat
(
wd
+
"/mnt/file"
)
fi
,
err
:=
os
.
Lstat
(
wd
+
"/mnt/file"
)
stat
:=
fuse
.
ToStatT
(
fi
)
attr
:=
&
fuse
.
Attr
{}
if
stat
.
Atim
.
Sec
!=
82
||
stat
.
Mtim
.
Sec
!=
83
{
attr
.
FromStat
(
fuse
.
ToStatT
(
fi
))
if
attr
.
Atime
!=
82
||
attr
.
Mtime
!=
83
{
t
.
Error
(
"Incorrect timestamp"
,
fi
)
t
.
Error
(
"Incorrect timestamp"
,
fi
)
}
}
}
}
...
@@ -1168,6 +1170,7 @@ func TestUnionFsDisappearing(t *testing.T) {
...
@@ -1168,6 +1170,7 @@ func TestUnionFsDisappearing(t *testing.T) {
}
}
defer
state
.
Unmount
()
defer
state
.
Unmount
()
go
state
.
Serve
()
go
state
.
Serve
()
state
.
WaitMount
()
err
=
ioutil
.
WriteFile
(
wd
+
"/ro/file"
,
[]
byte
(
"blabla"
),
0644
)
err
=
ioutil
.
WriteFile
(
wd
+
"/ro/file"
,
[]
byte
(
"blabla"
),
0644
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -1193,9 +1196,9 @@ func TestUnionFsDisappearing(t *testing.T) {
...
@@ -1193,9 +1196,9 @@ func TestUnionFsDisappearing(t *testing.T) {
t
.
Fatal
(
"write should have failed"
)
t
.
Fatal
(
"write should have failed"
)
}
}
// Restore, and wait for caches to catch up.
// Wait for the caches to purge, and then restore.
wrFs
.
visibleChan
<-
true
time
.
Sleep
((
3
*
entryTtl
)
/
2
)
time
.
Sleep
((
3
*
entryTtl
)
/
2
)
wrFs
.
visibleChan
<-
true
_
,
err
=
ioutil
.
ReadDir
(
wd
+
"/mnt"
)
_
,
err
=
ioutil
.
ReadDir
(
wd
+
"/mnt"
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -1281,41 +1284,6 @@ func TestUnionFsDoubleOpen(t *testing.T) {
...
@@ -1281,41 +1284,6 @@ func TestUnionFsDoubleOpen(t *testing.T) {
}
}
}
}
func
TestUnionFsFdLeak
(
t
*
testing
.
T
)
{
beforeEntries
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
wd
,
clean
:=
setupUfs
(
t
)
err
=
ioutil
.
WriteFile
(
wd
+
"/ro/file"
,
[]
byte
(
"blablabla"
),
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"WriteFile failed: %v"
,
err
)
}
setRecursiveWritable
(
t
,
wd
+
"/ro"
,
false
)
contents
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/file"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile failed: %v"
,
err
)
}
err
=
ioutil
.
WriteFile
(
wd
+
"/mnt/file"
,
contents
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"WriteFile failed: %v"
,
err
)
}
clean
()
afterEntries
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
if
len
(
afterEntries
)
!=
len
(
beforeEntries
)
{
t
.
Errorf
(
"/proc/self/fd changed size: after %v before %v"
,
len
(
beforeEntries
),
len
(
afterEntries
))
}
}
func
TestUnionFsStatFs
(
t
*
testing
.
T
)
{
func
TestUnionFsStatFs
(
t
*
testing
.
T
)
{
wd
,
clean
:=
setupUfs
(
t
)
wd
,
clean
:=
setupUfs
(
t
)
defer
clean
()
defer
clean
()
...
...
unionfs/unionfs_test_linux.go
0 → 100644
View file @
0155dffe
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
unionfs
import
(
"io/ioutil"
)
func
TestUnionFsFdLeak
(
t
*
testing
.
T
)
{
beforeEntries
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
wd
,
clean
:=
setupUfs
(
t
)
err
=
ioutil
.
WriteFile
(
wd
+
"/ro/file"
,
[]
byte
(
"blablabla"
),
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"WriteFile failed: %v"
,
err
)
}
setRecursiveWritable
(
t
,
wd
+
"/ro"
,
false
)
contents
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/file"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile failed: %v"
,
err
)
}
err
=
ioutil
.
WriteFile
(
wd
+
"/mnt/file"
,
contents
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"WriteFile failed: %v"
,
err
)
}
clean
()
afterEntries
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
if
len
(
afterEntries
)
!=
len
(
beforeEntries
)
{
t
.
Errorf
(
"/proc/self/fd changed size: after %v before %v"
,
len
(
beforeEntries
),
len
(
afterEntries
))
}
}
unionfs/unionfs_xattr_test.go
View file @
0155dffe
...
@@ -7,7 +7,6 @@ package unionfs
...
@@ -7,7 +7,6 @@ package unionfs
import
(
import
(
"io/ioutil"
"io/ioutil"
"os"
"os"
"syscall"
"testing"
"testing"
"time"
"time"
...
@@ -76,13 +75,14 @@ func TestXAttrCaching(t *testing.T) {
...
@@ -76,13 +75,14 @@ func TestXAttrCaching(t *testing.T) {
}
}
defer
server
.
Unmount
()
defer
server
.
Unmount
()
go
server
.
Serve
()
go
server
.
Serve
()
server
.
WaitMount
()
if
fi
,
err
:=
os
.
Lstat
(
wd
+
"/mnt"
);
err
!=
nil
||
!
fi
.
IsDir
()
{
if
fi
,
err
:=
os
.
Lstat
(
wd
+
"/mnt"
);
err
!=
nil
||
!
fi
.
IsDir
()
{
t
.
Fatalf
(
"root not readable: %v, %v"
,
err
,
fi
)
t
.
Fatalf
(
"root not readable: %v, %v"
,
err
,
fi
)
}
}
buf
:=
make
([]
byte
,
1024
)
buf
:=
make
([]
byte
,
1024
)
n
,
err
:=
syscall
.
Getxattr
(
wd
+
"/mnt/file"
,
"user.attr"
,
buf
)
n
,
err
:=
Getxattr
(
wd
+
"/mnt/file"
,
"user.attr"
,
buf
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
}
}
...
@@ -91,8 +91,10 @@ func TestXAttrCaching(t *testing.T) {
...
@@ -91,8 +91,10 @@ func TestXAttrCaching(t *testing.T) {
if
got
!=
want
{
if
got
!=
want
{
t
.
Fatalf
(
"Got %q want %q"
,
got
,
err
)
t
.
Fatalf
(
"Got %q want %q"
,
got
,
err
)
}
}
time
.
Sleep
(
entryTtl
/
2
)
n
,
err
=
syscall
.
Getxattr
(
wd
+
"/mnt/file"
,
"user.attr"
,
buf
)
time
.
Sleep
(
entryTtl
/
3
)
n
,
err
=
Getxattr
(
wd
+
"/mnt/file"
,
"user.attr"
,
buf
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
}
}
...
@@ -100,7 +102,21 @@ func TestXAttrCaching(t *testing.T) {
...
@@ -100,7 +102,21 @@ func TestXAttrCaching(t *testing.T) {
if
got
!=
want
{
if
got
!=
want
{
t
.
Fatalf
(
"Got %q want %q"
,
got
,
err
)
t
.
Fatalf
(
"Got %q want %q"
,
got
,
err
)
}
}
server
.
Unmount
()
time
.
Sleep
(
entryTtl
/
3
)
// Make sure that an interceding Getxattr() to a filesystem that doesn't implement GetXAttr() doesn't affect future calls.
Getxattr
(
wd
,
"whatever"
,
buf
)
n
,
err
=
Getxattr
(
wd
+
"/mnt/file"
,
"user.attr"
,
buf
)
if
err
!=
nil
{
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
}
got
=
string
(
buf
[
:
n
])
if
got
!=
want
{
t
.
Fatalf
(
"Got %q want %q"
,
got
,
err
)
}
if
roFS
.
xattrRead
!=
1
{
if
roFS
.
xattrRead
!=
1
{
t
.
Errorf
(
"got xattrRead=%d, want 1"
,
roFS
.
xattrRead
)
t
.
Errorf
(
"got xattrRead=%d, want 1"
,
roFS
.
xattrRead
)
}
}
...
...
unionfs/unionfs_xattr_test_darwin.go
0 → 100644
View file @
0155dffe
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
unionfs
import
(
"syscall"
"unsafe"
)
// Darwin doesn't have support for syscall.Getxattr() so we pull it into its own file and implement it by hand on Darwin.
func
Getxattr
(
path
string
,
attr
string
,
dest
[]
byte
)
(
sz
int
,
err
error
)
{
var
_p0
*
byte
_p0
,
err
=
syscall
.
BytePtrFromString
(
path
)
if
err
!=
nil
{
return
}
var
_p1
*
byte
_p1
,
err
=
syscall
.
BytePtrFromString
(
attr
)
if
err
!=
nil
{
return
}
var
_p2
unsafe
.
Pointer
if
len
(
dest
)
>
0
{
_p2
=
unsafe
.
Pointer
(
&
dest
[
0
])
}
else
{
var
_zero
uintptr
_p2
=
unsafe
.
Pointer
(
&
_zero
)
}
r0
,
_
,
e1
:=
syscall
.
Syscall6
(
syscall
.
SYS_GETXATTR
,
uintptr
(
unsafe
.
Pointer
(
_p0
)),
uintptr
(
unsafe
.
Pointer
(
_p1
)),
uintptr
(
_p2
),
uintptr
(
len
(
dest
)),
0
,
0
)
sz
=
int
(
r0
)
if
e1
!=
0
{
err
=
e1
}
return
}
unionfs/unionfs_xattr_test_linux.go
0 → 100644
View file @
0155dffe
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
unionfs
import
(
"syscall"
)
// Darwin doesn't have support for syscall.Getxattr() so we pull it into its own file and implement it by hand on Darwin.
func
Getxattr
(
path
string
,
attr
string
,
dest
[]
byte
)
(
sz
int
,
err
error
)
{
return
syscall
.
Getxattr
(
path
,
attr
,
dest
)
}
zipfs/multizip.go
View file @
0155dffe
...
@@ -87,6 +87,7 @@ func (fs *MultiZipFs) OpenDir(name string, context *fuse.Context) (stream []fuse
...
@@ -87,6 +87,7 @@ func (fs *MultiZipFs) OpenDir(name string, context *fuse.Context) (stream []fuse
func
(
fs
*
MultiZipFs
)
GetAttr
(
name
string
,
context
*
fuse
.
Context
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
func
(
fs
*
MultiZipFs
)
GetAttr
(
name
string
,
context
*
fuse
.
Context
)
(
*
fuse
.
Attr
,
fuse
.
Status
)
{
a
:=
&
fuse
.
Attr
{}
a
:=
&
fuse
.
Attr
{}
a
.
Owner
=
*
fuse
.
CurrentOwner
()
if
name
==
""
{
if
name
==
""
{
// Should not write in top dir.
// Should not write in top dir.
a
.
Mode
=
fuse
.
S_IFDIR
|
0500
a
.
Mode
=
fuse
.
S_IFDIR
|
0500
...
@@ -137,7 +138,7 @@ func (fs *MultiZipFs) Unlink(name string, context *fuse.Context) (code fuse.Stat
...
@@ -137,7 +138,7 @@ func (fs *MultiZipFs) Unlink(name string, context *fuse.Context) (code fuse.Stat
delete
(
fs
.
zips
,
basename
)
delete
(
fs
.
zips
,
basename
)
delete
(
fs
.
dirZipFileMap
,
basename
)
delete
(
fs
.
dirZipFileMap
,
basename
)
// Drop
lock to ensure that notify doesn't cause
deadlock.
// Drop
the lock to ensure that notify doesn't cause a
deadlock.
fs
.
lock
.
Unlock
()
fs
.
lock
.
Unlock
()
code
=
fs
.
nodeFs
.
UnmountNode
(
root
.
Inode
())
code
=
fs
.
nodeFs
.
UnmountNode
(
root
.
Inode
())
fs
.
lock
.
Lock
()
fs
.
lock
.
Lock
()
...
...
zipfs/multizip_test.go
View file @
0155dffe
...
@@ -11,6 +11,7 @@ import (
...
@@ -11,6 +11,7 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
)
...
@@ -23,7 +24,7 @@ func VerboseTest() bool {
...
@@ -23,7 +24,7 @@ func VerboseTest() bool {
const
testTtl
=
100
*
time
.
Millisecond
const
testTtl
=
100
*
time
.
Millisecond
func
setupMzfs
(
t
*
testing
.
T
)
(
mountPoint
string
,
cleanup
func
())
{
func
setupMzfs
(
t
*
testing
.
T
)
(
mountPoint
string
,
state
*
fuse
.
Server
,
cleanup
func
())
{
fs
:=
NewMultiZipFs
()
fs
:=
NewMultiZipFs
()
mountPoint
,
_
=
ioutil
.
TempDir
(
""
,
""
)
mountPoint
,
_
=
ioutil
.
TempDir
(
""
,
""
)
nfs
:=
pathfs
.
NewPathNodeFs
(
fs
,
nil
)
nfs
:=
pathfs
.
NewPathNodeFs
(
fs
,
nil
)
...
@@ -37,15 +38,16 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
...
@@ -37,15 +38,16 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
}
}
go
state
.
Serve
()
go
state
.
Serve
()
state
.
WaitMount
()
return
mountPoint
,
func
()
{
return
mountPoint
,
state
,
func
()
{
state
.
Unmount
()
state
.
Unmount
()
os
.
RemoveAll
(
mountPoint
)
os
.
RemoveAll
(
mountPoint
)
}
}
}
}
func
TestMultiZipReadonly
(
t
*
testing
.
T
)
{
func
TestMultiZipReadonly
(
t
*
testing
.
T
)
{
mountPoint
,
cleanup
:=
setupMzfs
(
t
)
mountPoint
,
_
,
cleanup
:=
setupMzfs
(
t
)
defer
cleanup
()
defer
cleanup
()
_
,
err
:=
os
.
Create
(
mountPoint
+
"/random"
)
_
,
err
:=
os
.
Create
(
mountPoint
+
"/random"
)
...
@@ -60,7 +62,7 @@ func TestMultiZipReadonly(t *testing.T) {
...
@@ -60,7 +62,7 @@ func TestMultiZipReadonly(t *testing.T) {
}
}
func
TestMultiZipFs
(
t
*
testing
.
T
)
{
func
TestMultiZipFs
(
t
*
testing
.
T
)
{
mountPoint
,
cleanup
:=
setupMzfs
(
t
)
mountPoint
,
server
,
cleanup
:=
setupMzfs
(
t
)
defer
cleanup
()
defer
cleanup
()
zipFile
:=
testZipFile
()
zipFile
:=
testZipFile
()
...
@@ -122,8 +124,22 @@ func TestMultiZipFs(t *testing.T) {
...
@@ -122,8 +124,22 @@ func TestMultiZipFs(t *testing.T) {
t
.
Fatalf
(
"Remove failed: %v"
,
err
)
t
.
Fatalf
(
"Remove failed: %v"
,
err
)
}
}
// If FUSE supports invalid inode notifications we expect this node to be gone. Otherwise we'll just make sure that it's not reachable.
if
server
.
KernelSettings
()
.
SupportsNotify
(
fuse
.
NOTIFY_INVAL_INODE
)
{
fi
,
err
=
os
.
Stat
(
mountPoint
+
"/zipmount"
)
fi
,
err
=
os
.
Stat
(
mountPoint
+
"/zipmount"
)
if
err
==
nil
{
if
err
==
nil
{
t
.
Errorf
(
"stat should fail after unmount, got %#v"
,
fi
)
t
.
Errorf
(
"stat should fail after unmount, got %#v"
,
fi
)
}
}
}
else
{
entries
,
err
=
ioutil
.
ReadDir
(
mountPoint
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir failed: %v"
,
err
)
}
for
_
,
e
:=
range
entries
{
if
e
.
Name
()
==
"zipmount"
{
t
.
Error
(
"Should not have entry: "
,
e
)
}
}
}
}
}
zipfs/zipfs_test.go
View file @
0155dffe
...
@@ -36,6 +36,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
...
@@ -36,6 +36,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
})
})
go
state
.
Serve
()
go
state
.
Serve
()
state
.
WaitMount
()
return
mountPoint
,
func
()
{
return
mountPoint
,
func
()
{
state
.
Unmount
()
state
.
Unmount
()
...
...
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