42 lines
1.1 KiB
Go
42 lines
1.1 KiB
Go
|
//go:build !windows && !plan9 && !js && !linux
|
||
|
|
||
|
package local
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"syscall"
|
||
|
|
||
|
"golang.org/x/sys/unix"
|
||
|
)
|
||
|
|
||
|
const haveLChmod = true
|
||
|
|
||
|
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
|
||
|
//
|
||
|
// Borrowed from the syscall source since it isn't public.
|
||
|
func syscallMode(i os.FileMode) (o uint32) {
|
||
|
o |= uint32(i.Perm())
|
||
|
if i&os.ModeSetuid != 0 {
|
||
|
o |= syscall.S_ISUID
|
||
|
}
|
||
|
if i&os.ModeSetgid != 0 {
|
||
|
o |= syscall.S_ISGID
|
||
|
}
|
||
|
if i&os.ModeSticky != 0 {
|
||
|
o |= syscall.S_ISVTX
|
||
|
}
|
||
|
return o
|
||
|
}
|
||
|
|
||
|
// lChmod changes the mode of the named file to mode. If the file is a symbolic
|
||
|
// link, it changes the link, not the target. If there is an error,
|
||
|
// it will be of type *PathError.
|
||
|
func lChmod(name string, mode os.FileMode) error {
|
||
|
// NB linux does not support AT_SYMLINK_NOFOLLOW as a parameter to fchmodat
|
||
|
// and returns ENOTSUP if you try, so we don't support this on linux
|
||
|
if e := unix.Fchmodat(unix.AT_FDCWD, name, syscallMode(mode), unix.AT_SYMLINK_NOFOLLOW); e != nil {
|
||
|
return &os.PathError{Op: "lChmod", Path: name, Err: e}
|
||
|
}
|
||
|
return nil
|
||
|
}
|