1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
17 isReadonlyError
= func(err error
) bool { return err
== syscall
.EROFS
}
20 func checkUidGid(t
*testing
.T
, path
string, uid
, gid
int) {
21 dir
, err
:= Lstat(path
)
23 t
.Fatalf("Lstat %q (looking for uid/gid %d/%d): %s", path
, uid
, gid
, err
)
25 sys
:= dir
.Sys().(*syscall
.Stat_t
)
26 if int(sys
.Uid
) != uid
{
27 t
.Errorf("Lstat %q: uid %d want %d", path
, sys
.Uid
, uid
)
29 if int(sys
.Gid
) != gid
{
30 t
.Errorf("Lstat %q: gid %d want %d", path
, sys
.Gid
, gid
)
34 func TestChown(t
*testing
.T
) {
35 // Chown is not supported under windows or Plan 9.
36 // Plan9 provides a native ChownPlan9 version instead.
37 if runtime
.GOOS
== "windows" || runtime
.GOOS
== "plan9" {
38 t
.Skipf("%s does not support syscall.Chown", runtime
.GOOS
)
40 // Use TempDir() to make sure we're on a local file system,
41 // so that the group ids returned by Getgroups will be allowed
42 // on the file. On NFS, the Getgroups groups are
44 f
:= newFile("TestChown", t
)
45 defer Remove(f
.Name())
49 t
.Fatalf("stat %s: %s", f
.Name(), err
)
52 // Can't change uid unless root, but can try
53 // changing the group id. First try our current group.
56 if err
= Chown(f
.Name(), -1, gid
); err
!= nil {
57 t
.Fatalf("chown %s -1 %d: %s", f
.Name(), gid
, err
)
59 sys
:= dir
.Sys().(*syscall
.Stat_t
)
60 checkUidGid(t
, f
.Name(), int(sys
.Uid
), gid
)
62 // Then try all the auxiliary groups.
63 groups
, err
:= Getgroups()
65 t
.Fatalf("getgroups: %s", err
)
67 t
.Log("groups: ", groups
)
68 for _
, g
:= range groups
{
69 if err
= Chown(f
.Name(), -1, g
); err
!= nil {
70 t
.Fatalf("chown %s -1 %d: %s", f
.Name(), g
, err
)
72 checkUidGid(t
, f
.Name(), int(sys
.Uid
), g
)
74 // change back to gid to test fd.Chown
75 if err
= f
.Chown(-1, gid
); err
!= nil {
76 t
.Fatalf("fchown %s -1 %d: %s", f
.Name(), gid
, err
)
78 checkUidGid(t
, f
.Name(), int(sys
.Uid
), gid
)
82 func TestFileChown(t
*testing
.T
) {
83 // Fchown is not supported under windows or Plan 9.
84 if runtime
.GOOS
== "windows" || runtime
.GOOS
== "plan9" {
85 t
.Skipf("%s does not support syscall.Fchown", runtime
.GOOS
)
87 // Use TempDir() to make sure we're on a local file system,
88 // so that the group ids returned by Getgroups will be allowed
89 // on the file. On NFS, the Getgroups groups are
91 f
:= newFile("TestFileChown", t
)
92 defer Remove(f
.Name())
96 t
.Fatalf("stat %s: %s", f
.Name(), err
)
99 // Can't change uid unless root, but can try
100 // changing the group id. First try our current group.
103 if err
= f
.Chown(-1, gid
); err
!= nil {
104 t
.Fatalf("fchown %s -1 %d: %s", f
.Name(), gid
, err
)
106 sys
:= dir
.Sys().(*syscall
.Stat_t
)
107 checkUidGid(t
, f
.Name(), int(sys
.Uid
), gid
)
109 // Then try all the auxiliary groups.
110 groups
, err
:= Getgroups()
112 t
.Fatalf("getgroups: %s", err
)
114 t
.Log("groups: ", groups
)
115 for _
, g
:= range groups
{
116 if err
= f
.Chown(-1, g
); err
!= nil {
117 t
.Fatalf("fchown %s -1 %d: %s", f
.Name(), g
, err
)
119 checkUidGid(t
, f
.Name(), int(sys
.Uid
), g
)
121 // change back to gid to test fd.Chown
122 if err
= f
.Chown(-1, gid
); err
!= nil {
123 t
.Fatalf("fchown %s -1 %d: %s", f
.Name(), gid
, err
)
125 checkUidGid(t
, f
.Name(), int(sys
.Uid
), gid
)
129 func TestLchown(t
*testing
.T
) {
130 // Lchown is not supported under windows or Plan 9.
131 if runtime
.GOOS
== "windows" || runtime
.GOOS
== "plan9" {
132 t
.Skipf("%s does not support syscall.Lchown", runtime
.GOOS
)
134 // Use TempDir() to make sure we're on a local file system,
135 // so that the group ids returned by Getgroups will be allowed
136 // on the file. On NFS, the Getgroups groups are
137 // basically useless.
138 f
:= newFile("TestLchown", t
)
139 defer Remove(f
.Name())
143 t
.Fatalf("stat %s: %s", f
.Name(), err
)
146 linkname
:= f
.Name() + "2"
147 if err
:= Symlink(f
.Name(), linkname
); err
!= nil {
148 t
.Fatalf("link %s -> %s: %v", f
.Name(), linkname
, err
)
150 defer Remove(linkname
)
152 // Can't change uid unless root, but can try
153 // changing the group id. First try our current group.
156 if err
= Lchown(linkname
, -1, gid
); err
!= nil {
157 t
.Fatalf("lchown %s -1 %d: %s", linkname
, gid
, err
)
159 sys
:= dir
.Sys().(*syscall
.Stat_t
)
160 checkUidGid(t
, linkname
, int(sys
.Uid
), gid
)
162 // Then try all the auxiliary groups.
163 groups
, err
:= Getgroups()
165 t
.Fatalf("getgroups: %s", err
)
167 t
.Log("groups: ", groups
)
168 for _
, g
:= range groups
{
169 if err
= Lchown(linkname
, -1, g
); err
!= nil {
170 t
.Fatalf("lchown %s -1 %d: %s", linkname
, g
, err
)
172 checkUidGid(t
, linkname
, int(sys
.Uid
), g
)
174 // Check that link target's gid is unchanged.
175 checkUidGid(t
, f
.Name(), int(sys
.Uid
), int(sys
.Gid
))