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
b8a2eda4
Commit
b8a2eda4
authored
Mar 23, 2019
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nodefs: make everything compile on darwin
parent
c6e7e60f
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
242 additions
and
192 deletions
+242
-192
nodefs/bridge.go
nodefs/bridge.go
+1
-2
nodefs/constants.go
nodefs/constants.go
+3
-0
nodefs/loopback.go
nodefs/loopback.go
+4
-23
nodefs/loopback_darwin.go
nodefs/loopback_darwin.go
+35
-0
nodefs/loopback_linux.go
nodefs/loopback_linux.go
+18
-0
nodefs/loopback_linux_test.go
nodefs/loopback_linux_test.go
+179
-0
nodefs/simple_test.go
nodefs/simple_test.go
+2
-167
No files found.
nodefs/bridge.go
View file @
b8a2eda4
...
@@ -12,7 +12,6 @@ import (
...
@@ -12,7 +12,6 @@ import (
"time"
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
"golang.org/x/sys/unix"
)
)
func
errnoToStatus
(
errno
syscall
.
Errno
)
fuse
.
Status
{
func
errnoToStatus
(
errno
syscall
.
Errno
)
fuse
.
Status
{
...
@@ -393,7 +392,7 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName
...
@@ -393,7 +392,7 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName
if
mops
,
ok
:=
p1
.
ops
.
(
MutableDirOperations
);
ok
{
if
mops
,
ok
:=
p1
.
ops
.
(
MutableDirOperations
);
ok
{
errno
:=
mops
.
Rename
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
},
oldName
,
p2
.
ops
,
newName
,
input
.
Flags
)
errno
:=
mops
.
Rename
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
},
oldName
,
p2
.
ops
,
newName
,
input
.
Flags
)
if
errno
==
0
{
if
errno
==
0
{
if
input
.
Flags
&
unix
.
RENAME_EXCHANGE
!=
0
{
if
input
.
Flags
&
RENAME_EXCHANGE
!=
0
{
p1
.
ExchangeChild
(
oldName
,
p2
,
newName
)
p1
.
ExchangeChild
(
oldName
,
p2
,
newName
)
}
else
{
}
else
{
p1
.
MvChild
(
oldName
,
p2
,
newName
,
true
)
p1
.
MvChild
(
oldName
,
p2
,
newName
,
true
)
...
...
nodefs/constants.go
View file @
b8a2eda4
...
@@ -17,3 +17,6 @@ func ToErrno(err error) syscall.Errno {
...
@@ -17,3 +17,6 @@ func ToErrno(err error) syscall.Errno {
s
:=
fuse
.
ToStatus
(
err
)
s
:=
fuse
.
ToStatus
(
err
)
return
syscall
.
Errno
(
s
)
return
syscall
.
Errno
(
s
)
}
}
// RENAME_EXCHANGE is a flag argument for renameat2()
const
RENAME_EXCHANGE
=
0x2
nodefs/loopback.go
View file @
b8a2eda4
...
@@ -11,7 +11,6 @@ import (
...
@@ -11,7 +11,6 @@ import (
"syscall"
"syscall"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
"golang.org/x/sys/unix"
)
)
type
loopbackRoot
struct
{
type
loopbackRoot
struct
{
...
@@ -135,7 +134,7 @@ func toLoopbackNode(op Operations) *loopbackNode {
...
@@ -135,7 +134,7 @@ func toLoopbackNode(op Operations) *loopbackNode {
func
(
n
*
loopbackNode
)
Rename
(
ctx
context
.
Context
,
name
string
,
newParent
Operations
,
newName
string
,
flags
uint32
)
syscall
.
Errno
{
func
(
n
*
loopbackNode
)
Rename
(
ctx
context
.
Context
,
name
string
,
newParent
Operations
,
newName
string
,
flags
uint32
)
syscall
.
Errno
{
newParentLoopback
:=
toLoopbackNode
(
newParent
)
newParentLoopback
:=
toLoopbackNode
(
newParent
)
if
flags
&
unix
.
RENAME_EXCHANGE
!=
0
{
if
flags
&
RENAME_EXCHANGE
!=
0
{
return
n
.
renameExchange
(
name
,
newParentLoopback
,
newName
)
return
n
.
renameExchange
(
name
,
newParentLoopback
,
newName
)
}
}
...
@@ -154,10 +153,10 @@ func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr {
...
@@ -154,10 +153,10 @@ func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr {
// device number of the root, so a loopback FS that does not
// device number of the root, so a loopback FS that does not
// encompass multiple mounts will reflect the inode numbers of
// encompass multiple mounts will reflect the inode numbers of
// the underlying filesystem
// the underlying filesystem
swapped
:=
(
st
.
Dev
<<
32
)
|
(
st
.
Dev
>>
32
)
swapped
:=
(
uint64
(
st
.
Dev
)
<<
32
)
|
(
uint64
(
st
.
Dev
)
>>
32
)
swappedRootDev
:=
(
r
.
rootDev
<<
32
)
|
(
r
.
rootDev
>>
32
)
swappedRootDev
:=
(
r
.
rootDev
<<
32
)
|
(
r
.
rootDev
>>
32
)
return
NodeAttr
{
return
NodeAttr
{
Mode
:
st
.
Mode
,
Mode
:
uint32
(
st
.
Mode
)
,
Gen
:
1
,
Gen
:
1
,
// This should work well for traditional backing FSes,
// This should work well for traditional backing FSes,
// not so much for other go-fuse FS-es
// not so much for other go-fuse FS-es
...
@@ -279,24 +278,6 @@ func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.Att
...
@@ -279,24 +278,6 @@ func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.Att
return
OK
return
OK
}
}
func
(
n
*
loopbackNode
)
CopyFileRange
(
ctx
context
.
Context
,
fhIn
FileHandle
,
offIn
uint64
,
out
*
Inode
,
fhOut
FileHandle
,
offOut
uint64
,
len
uint64
,
flags
uint64
)
(
uint32
,
syscall
.
Errno
)
{
lfIn
,
ok
:=
fhIn
.
(
*
loopbackFile
)
if
!
ok
{
return
0
,
syscall
.
ENOTSUP
}
lfOut
,
ok
:=
fhOut
.
(
*
loopbackFile
)
if
!
ok
{
return
0
,
syscall
.
ENOTSUP
}
signedOffIn
:=
int64
(
offIn
)
signedOffOut
:=
int64
(
offOut
)
count
,
err
:=
unix
.
CopyFileRange
(
lfIn
.
fd
,
&
signedOffIn
,
lfOut
.
fd
,
&
signedOffOut
,
int
(
len
),
int
(
flags
))
return
uint32
(
count
),
ToErrno
(
err
)
}
// NewLoopback returns a root node for a loopback file system whose
// NewLoopback returns a root node for a loopback file system whose
// root is at the given root.
// root is at the given root.
func
NewLoopbackRoot
(
root
string
)
(
DirOperations
,
error
)
{
func
NewLoopbackRoot
(
root
string
)
(
DirOperations
,
error
)
{
...
@@ -308,7 +289,7 @@ func NewLoopbackRoot(root string) (DirOperations, error) {
...
@@ -308,7 +289,7 @@ func NewLoopbackRoot(root string) (DirOperations, error) {
n
:=
&
loopbackRoot
{
n
:=
&
loopbackRoot
{
root
:
root
,
root
:
root
,
rootDev
:
st
.
Dev
,
rootDev
:
uint64
(
st
.
Dev
)
,
}
}
n
.
rootNode
=
n
n
.
rootNode
=
n
return
n
,
nil
return
n
,
nil
...
...
nodefs/loopback_darwin.go
0 → 100644
View file @
b8a2eda4
// Copyright 2019 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
nodefs
import
(
"context"
"syscall"
"time"
)
func
(
n
*
loopbackNode
)
GetXAttr
(
ctx
context
.
Context
,
attr
string
,
dest
[]
byte
)
(
uint32
,
syscall
.
Errno
)
{
return
0
,
syscall
.
ENOSYS
}
func
(
n
*
loopbackNode
)
SetXAttr
(
ctx
context
.
Context
,
attr
string
,
data
[]
byte
,
flags
uint32
)
syscall
.
Errno
{
return
syscall
.
ENOSYS
}
func
(
n
*
loopbackNode
)
RemoveXAttr
(
ctx
context
.
Context
,
attr
string
)
syscall
.
Errno
{
return
syscall
.
ENOSYS
}
func
(
n
*
loopbackNode
)
ListXAttr
(
ctx
context
.
Context
,
dest
[]
byte
)
(
uint32
,
syscall
.
Errno
)
{
return
0
,
syscall
.
ENOSYS
}
func
(
n
*
loopbackNode
)
renameExchange
(
name
string
,
newparent
*
loopbackNode
,
newName
string
)
syscall
.
Errno
{
return
syscall
.
ENOSYS
}
func
(
f
*
loopbackFile
)
utimens
(
a
*
time
.
Time
,
m
*
time
.
Time
)
syscall
.
Errno
{
return
syscall
.
ENOSYS
// XXX
}
nodefs/loopback_linux.go
View file @
b8a2eda4
...
@@ -59,3 +59,21 @@ func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newN
...
@@ -59,3 +59,21 @@ func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newN
return
ToErrno
(
unix
.
Renameat2
(
fd1
,
name
,
fd2
,
newName
,
unix
.
RENAME_EXCHANGE
))
return
ToErrno
(
unix
.
Renameat2
(
fd1
,
name
,
fd2
,
newName
,
unix
.
RENAME_EXCHANGE
))
}
}
func
(
n
*
loopbackNode
)
CopyFileRange
(
ctx
context
.
Context
,
fhIn
FileHandle
,
offIn
uint64
,
out
*
Inode
,
fhOut
FileHandle
,
offOut
uint64
,
len
uint64
,
flags
uint64
)
(
uint32
,
syscall
.
Errno
)
{
lfIn
,
ok
:=
fhIn
.
(
*
loopbackFile
)
if
!
ok
{
return
0
,
syscall
.
ENOTSUP
}
lfOut
,
ok
:=
fhOut
.
(
*
loopbackFile
)
if
!
ok
{
return
0
,
syscall
.
ENOTSUP
}
signedOffIn
:=
int64
(
offIn
)
signedOffOut
:=
int64
(
offOut
)
count
,
err
:=
unix
.
CopyFileRange
(
lfIn
.
fd
,
&
signedOffIn
,
lfOut
.
fd
,
&
signedOffOut
,
int
(
len
),
int
(
flags
))
return
uint32
(
count
),
ToErrno
(
err
)
}
nodefs/loopback_linux_test.go
0 → 100644
View file @
b8a2eda4
// Copyright 2019 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
nodefs
import
(
"bytes"
"io/ioutil"
"os"
"reflect"
"syscall"
"testing"
"github.com/kylelemons/godebug/pretty"
"golang.org/x/sys/unix"
)
func
TestRenameExchange
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
if
err
:=
os
.
Mkdir
(
tc
.
origDir
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
tc
.
writeOrig
(
"file"
,
"hello"
,
0644
)
tc
.
writeOrig
(
"dir/file"
,
"x"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 1: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dir"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 2: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
var
before1
,
before2
unix
.
Stat_t
if
err
:=
unix
.
Fstatat
(
f1
,
"file"
,
&
before1
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Fstatat
(
f2
,
"file"
,
&
before2
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Renameat2
(
f1
,
"file"
,
f2
,
"file"
,
unix
.
RENAME_EXCHANGE
);
err
!=
nil
{
t
.
Errorf
(
"rename EXCHANGE: %v"
,
err
)
}
var
after1
,
after2
unix
.
Stat_t
if
err
:=
unix
.
Fstatat
(
f1
,
"file"
,
&
after1
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Fstatat
(
f2
,
"file"
,
&
after2
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
clearCtime
:=
func
(
s
*
unix
.
Stat_t
)
{
s
.
Ctim
.
Sec
=
0
s
.
Ctim
.
Nsec
=
0
}
clearCtime
(
&
after1
)
clearCtime
(
&
after2
)
clearCtime
(
&
before2
)
clearCtime
(
&
before1
)
if
diff
:=
pretty
.
Compare
(
after1
,
before2
);
diff
!=
""
{
t
.
Errorf
(
"after1, before2: %s"
,
diff
)
}
if
!
reflect
.
DeepEqual
(
after2
,
before1
)
{
t
.
Errorf
(
"after2, before1: %#v, %#v"
,
after2
,
before1
)
}
}
func
TestRenameNoOverwrite
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
if
err
:=
os
.
Mkdir
(
tc
.
origDir
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
tc
.
writeOrig
(
"file"
,
"hello"
,
0644
)
tc
.
writeOrig
(
"dir/file"
,
"x"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 1: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dir"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 2: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
if
err
:=
unix
.
Renameat2
(
f1
,
"file"
,
f2
,
"file"
,
unix
.
RENAME_NOREPLACE
);
err
==
nil
{
t
.
Errorf
(
"rename NOREPLACE succeeded"
)
}
else
if
err
!=
syscall
.
EEXIST
{
t
.
Errorf
(
"got %v (%T) want EEXIST"
,
err
,
err
)
}
}
func
TestXAttr
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
tc
.
writeOrig
(
"file"
,
""
,
0644
)
buf
:=
make
([]
byte
,
1024
)
attr
:=
"user.xattrtest"
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
==
syscall
.
ENOTSUP
{
t
.
Skip
(
"$TMP does not support xattrs. Rerun this test with a $TMPDIR override"
)
}
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
!=
syscall
.
ENODATA
{
t
.
Fatalf
(
"got %v want ENOATTR"
,
err
)
}
value
:=
[]
byte
(
"value"
)
if
err
:=
syscall
.
Setxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
value
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Setxattr: %v"
,
err
)
}
sz
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
)
if
err
!=
nil
{
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
}
if
bytes
.
Compare
(
buf
[
:
sz
],
value
)
!=
0
{
t
.
Fatalf
(
"Getxattr got %q want %q"
,
buf
[
:
sz
],
value
)
}
if
err
:=
syscall
.
Removexattr
(
tc
.
mntDir
+
"/file"
,
attr
);
err
!=
nil
{
t
.
Fatalf
(
"Removexattr: %v"
,
err
)
}
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
!=
syscall
.
ENODATA
{
t
.
Fatalf
(
"got %v want ENOATTR"
,
err
)
}
}
func
TestCopyFileRange
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
tc
.
writeOrig
(
"src"
,
"01234567890123456789"
,
0644
)
tc
.
writeOrig
(
"dst"
,
"abcdefghijabcdefghij"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/src"
,
syscall
.
O_RDONLY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open src: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dst"
,
syscall
.
O_RDWR
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open dst: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
srcOff
:=
int64
(
5
)
dstOff
:=
int64
(
7
)
if
sz
,
err
:=
unix
.
CopyFileRange
(
f1
,
&
srcOff
,
f2
,
&
dstOff
,
3
,
0
);
err
!=
nil
||
sz
!=
3
{
t
.
Fatalf
(
"CopyFileRange: %d,%v"
,
sz
,
err
)
}
if
err
:=
syscall
.
Close
(
f1
);
err
!=
nil
{
t
.
Fatalf
(
"Close src: %v"
,
err
)
}
if
err
:=
syscall
.
Close
(
f2
);
err
!=
nil
{
t
.
Fatalf
(
"Close dst: %v"
,
err
)
}
c
,
err
:=
ioutil
.
ReadFile
(
tc
.
mntDir
+
"/dst"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
want
:=
"abcdefg567abcdefghij"
got
:=
string
(
c
)
if
got
!=
want
{
t
.
Errorf
(
"got %q want %q"
,
got
,
want
)
}
}
nodefs/simple_test.go
View file @
b8a2eda4
...
@@ -17,11 +17,8 @@ import (
...
@@ -17,11 +17,8 @@ import (
"testing"
"testing"
"time"
"time"
"golang.org/x/sys/unix"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/kylelemons/godebug/pretty"
)
)
type
testCase
struct
{
type
testCase
struct
{
...
@@ -118,7 +115,7 @@ func TestBasic(t *testing.T) {
...
@@ -118,7 +115,7 @@ func TestBasic(t *testing.T) {
}
}
stat
:=
fuse
.
ToStatT
(
fi
)
stat
:=
fuse
.
ToStatT
(
fi
)
if
got
,
want
:=
stat
.
Mode
,
uint32
(
fuse
.
S_IFREG
|
0644
);
got
!=
want
{
if
got
,
want
:=
uint32
(
stat
.
Mode
)
,
uint32
(
fuse
.
S_IFREG
|
0644
);
got
!=
want
{
t
.
Errorf
(
"got mode %o, want %o"
,
got
,
want
)
t
.
Errorf
(
"got mode %o, want %o"
,
got
,
want
)
}
}
...
@@ -164,7 +161,7 @@ func TestFile(t *testing.T) {
...
@@ -164,7 +161,7 @@ func TestFile(t *testing.T) {
}
}
stat
:=
fuse
.
ToStatT
(
fi
)
stat
:=
fuse
.
ToStatT
(
fi
)
if
got
,
want
:=
stat
.
Mode
,
uint32
(
fuse
.
S_IFREG
|
0755
);
got
!=
want
{
if
got
,
want
:=
uint32
(
stat
.
Mode
)
,
uint32
(
fuse
.
S_IFREG
|
0755
);
got
!=
want
{
t
.
Errorf
(
"Fstat: got mode %o, want %o"
,
got
,
want
)
t
.
Errorf
(
"Fstat: got mode %o, want %o"
,
got
,
want
)
}
}
...
@@ -301,91 +298,6 @@ func TestRenameDestNoExist(t *testing.T) {
...
@@ -301,91 +298,6 @@ func TestRenameDestNoExist(t *testing.T) {
testRenameOverwrite
(
t
,
false
)
testRenameOverwrite
(
t
,
false
)
}
}
func
TestRenameNoOverwrite
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
if
err
:=
os
.
Mkdir
(
tc
.
origDir
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
tc
.
writeOrig
(
"file"
,
"hello"
,
0644
)
tc
.
writeOrig
(
"dir/file"
,
"x"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 1: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dir"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 2: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
if
err
:=
unix
.
Renameat2
(
f1
,
"file"
,
f2
,
"file"
,
unix
.
RENAME_NOREPLACE
);
err
==
nil
{
t
.
Errorf
(
"rename NOREPLACE succeeded"
)
}
else
if
err
!=
syscall
.
EEXIST
{
t
.
Errorf
(
"got %v (%T) want EEXIST"
,
err
,
err
)
}
}
func
TestRenameExchange
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
if
err
:=
os
.
Mkdir
(
tc
.
origDir
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
tc
.
writeOrig
(
"file"
,
"hello"
,
0644
)
tc
.
writeOrig
(
"dir/file"
,
"x"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 1: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dir"
,
syscall
.
O_DIRECTORY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"open 2: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
var
before1
,
before2
unix
.
Stat_t
if
err
:=
unix
.
Fstatat
(
f1
,
"file"
,
&
before1
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Fstatat
(
f2
,
"file"
,
&
before2
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Renameat2
(
f1
,
"file"
,
f2
,
"file"
,
unix
.
RENAME_EXCHANGE
);
err
!=
nil
{
t
.
Errorf
(
"rename EXCHANGE: %v"
,
err
)
}
var
after1
,
after2
unix
.
Stat_t
if
err
:=
unix
.
Fstatat
(
f1
,
"file"
,
&
after1
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
if
err
:=
unix
.
Fstatat
(
f2
,
"file"
,
&
after2
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Fstatat: %v"
,
err
)
}
clearCtime
:=
func
(
s
*
unix
.
Stat_t
)
{
s
.
Ctim
.
Sec
=
0
s
.
Ctim
.
Nsec
=
0
}
clearCtime
(
&
after1
)
clearCtime
(
&
after2
)
clearCtime
(
&
before2
)
clearCtime
(
&
before1
)
if
diff
:=
pretty
.
Compare
(
after1
,
before2
);
diff
!=
""
{
t
.
Errorf
(
"after1, before2: %s"
,
diff
)
}
if
!
reflect
.
DeepEqual
(
after2
,
before1
)
{
t
.
Errorf
(
"after2, before1: %#v, %#v"
,
after2
,
before1
)
}
}
func
TestNlinkZero
(
t
*
testing
.
T
)
{
func
TestNlinkZero
(
t
*
testing
.
T
)
{
// xfstest generic/035.
// xfstest generic/035.
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
...
@@ -598,41 +510,6 @@ func TestStatFs(t *testing.T) {
...
@@ -598,41 +510,6 @@ func TestStatFs(t *testing.T) {
}
}
}
}
func
TestXAttr
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
tc
.
writeOrig
(
"file"
,
""
,
0644
)
buf
:=
make
([]
byte
,
1024
)
attr
:=
"user.xattrtest"
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
==
syscall
.
ENOTSUP
{
t
.
Skip
(
"$TMP does not support xattrs. Rerun this test with a $TMPDIR override"
)
}
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
!=
syscall
.
ENODATA
{
t
.
Fatalf
(
"got %v want ENOATTR"
,
err
)
}
value
:=
[]
byte
(
"value"
)
if
err
:=
syscall
.
Setxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
value
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Setxattr: %v"
,
err
)
}
sz
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
)
if
err
!=
nil
{
t
.
Fatalf
(
"Getxattr: %v"
,
err
)
}
if
bytes
.
Compare
(
buf
[
:
sz
],
value
)
!=
0
{
t
.
Fatalf
(
"Getxattr got %q want %q"
,
buf
[
:
sz
],
value
)
}
if
err
:=
syscall
.
Removexattr
(
tc
.
mntDir
+
"/file"
,
attr
);
err
!=
nil
{
t
.
Fatalf
(
"Removexattr: %v"
,
err
)
}
if
_
,
err
:=
syscall
.
Getxattr
(
tc
.
mntDir
+
"/file"
,
attr
,
buf
);
err
!=
syscall
.
ENODATA
{
t
.
Fatalf
(
"got %v want ENOATTR"
,
err
)
}
}
func
TestGetAttrParallel
(
t
*
testing
.
T
)
{
func
TestGetAttrParallel
(
t
*
testing
.
T
)
{
// We grab a file-handle to provide to the API so rename+fstat
// We grab a file-handle to provide to the API so rename+fstat
// can be handled correctly. Here, test that closing and
// can be handled correctly. Here, test that closing and
...
@@ -679,45 +556,3 @@ func TestGetAttrParallel(t *testing.T) {
...
@@ -679,45 +556,3 @@ func TestGetAttrParallel(t *testing.T) {
}
}
// XXX test mknod.
// XXX test mknod.
func
TestCopyFileRange
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
tc
.
writeOrig
(
"src"
,
"01234567890123456789"
,
0644
)
tc
.
writeOrig
(
"dst"
,
"abcdefghijabcdefghij"
,
0644
)
f1
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/src"
,
syscall
.
O_RDONLY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open src: %v"
,
err
)
}
defer
syscall
.
Close
(
f1
)
f2
,
err
:=
syscall
.
Open
(
tc
.
mntDir
+
"/dst"
,
syscall
.
O_RDWR
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open dst: %v"
,
err
)
}
defer
syscall
.
Close
(
f2
)
srcOff
:=
int64
(
5
)
dstOff
:=
int64
(
7
)
if
sz
,
err
:=
unix
.
CopyFileRange
(
f1
,
&
srcOff
,
f2
,
&
dstOff
,
3
,
0
);
err
!=
nil
||
sz
!=
3
{
t
.
Fatalf
(
"CopyFileRange: %d,%v"
,
sz
,
err
)
}
if
err
:=
syscall
.
Close
(
f1
);
err
!=
nil
{
t
.
Fatalf
(
"Close src: %v"
,
err
)
}
if
err
:=
syscall
.
Close
(
f2
);
err
!=
nil
{
t
.
Fatalf
(
"Close dst: %v"
,
err
)
}
c
,
err
:=
ioutil
.
ReadFile
(
tc
.
mntDir
+
"/dst"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
want
:=
"abcdefg567abcdefghij"
got
:=
string
(
c
)
if
got
!=
want
{
t
.
Errorf
(
"got %q want %q"
,
got
,
want
)
}
}
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