mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
os: implement File.Chmod on Windows
Fixes: #39606 Change-Id: I4def67ef18bd3ff866b140f6e76cdabe5d51a1c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/250077 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
parent
07c1788357
commit
d7384f3612
@ -29,17 +29,6 @@ func (fd *FD) Shutdown(how int) error {
|
||||
return syscall.Shutdown(fd.Sysfd, how)
|
||||
}
|
||||
|
||||
// Fchmod wraps syscall.Fchmod.
|
||||
func (fd *FD) Fchmod(mode uint32) error {
|
||||
if err := fd.incref(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.decref()
|
||||
return ignoringEINTR(func() error {
|
||||
return syscall.Fchmod(fd.Sysfd, mode)
|
||||
})
|
||||
}
|
||||
|
||||
// Fchown wraps syscall.Fchown.
|
||||
func (fd *FD) Fchown(uid, gid int) error {
|
||||
if err := fd.incref(); err != nil {
|
||||
|
@ -437,6 +437,17 @@ func (fd *FD) ReadDirent(buf []byte) (int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fchmod wraps syscall.Fchmod.
|
||||
func (fd *FD) Fchmod(mode uint32) error {
|
||||
if err := fd.incref(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.decref()
|
||||
return ignoringEINTR(func() error {
|
||||
return syscall.Fchmod(fd.Sysfd, mode)
|
||||
})
|
||||
}
|
||||
|
||||
// Fchdir wraps syscall.Fchdir.
|
||||
func (fd *FD) Fchdir() error {
|
||||
if err := fd.incref(); err != nil {
|
||||
|
@ -886,6 +886,33 @@ func (fd *FD) FindNextFile(data *syscall.Win32finddata) error {
|
||||
return syscall.FindNextFile(fd.Sysfd, data)
|
||||
}
|
||||
|
||||
// Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
|
||||
func (fd *FD) Fchmod(mode uint32) error {
|
||||
if err := fd.incref(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.decref()
|
||||
|
||||
var d syscall.ByHandleFileInformation
|
||||
if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
|
||||
return err
|
||||
}
|
||||
attrs := d.FileAttributes
|
||||
if mode&syscall.S_IWRITE != 0 {
|
||||
attrs &^= syscall.FILE_ATTRIBUTE_READONLY
|
||||
} else {
|
||||
attrs |= syscall.FILE_ATTRIBUTE_READONLY
|
||||
}
|
||||
if attrs == d.FileAttributes {
|
||||
return nil
|
||||
}
|
||||
|
||||
var du windows.FILE_BASIC_INFO
|
||||
du.FileAttributes = attrs
|
||||
l := uint32(unsafe.Sizeof(d))
|
||||
return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, uintptr(unsafe.Pointer(&du)), l)
|
||||
}
|
||||
|
||||
// Fchdir wraps syscall.Fchdir.
|
||||
func (fd *FD) Fchdir() error {
|
||||
if err := fd.incref(); err != nil {
|
||||
|
@ -131,6 +131,14 @@ type IpAdapterAddresses struct {
|
||||
/* more fields might be present here. */
|
||||
}
|
||||
|
||||
type FILE_BASIC_INFO struct {
|
||||
CreationTime syscall.Filetime
|
||||
LastAccessTime syscall.Filetime
|
||||
LastWriteTime syscall.Filetime
|
||||
ChangedTime syscall.Filetime
|
||||
FileAttributes uint32
|
||||
}
|
||||
|
||||
const (
|
||||
IfOperStatusUp = 1
|
||||
IfOperStatusDown = 2
|
||||
@ -145,6 +153,7 @@ const (
|
||||
//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
|
||||
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
|
||||
//sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
|
||||
//sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
|
||||
|
||||
const (
|
||||
WSA_FLAG_OVERLAPPED = 0x01
|
||||
|
@ -71,6 +71,7 @@ var (
|
||||
procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups")
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
|
||||
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
|
||||
)
|
||||
|
||||
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
|
||||
@ -81,6 +82,18 @@ func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapter
|
||||
return
|
||||
}
|
||||
|
||||
func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
|
||||
if r1 == 0 {
|
||||
|
@ -1099,29 +1099,34 @@ func checkMode(t *testing.T, path string, mode FileMode) {
|
||||
if err != nil {
|
||||
t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
|
||||
}
|
||||
if dir.Mode()&0777 != mode {
|
||||
if dir.Mode()&ModePerm != mode {
|
||||
t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChmod(t *testing.T) {
|
||||
// Chmod is not supported under windows.
|
||||
if runtime.GOOS == "windows" {
|
||||
return
|
||||
}
|
||||
f := newFile("TestChmod", t)
|
||||
defer Remove(f.Name())
|
||||
defer f.Close()
|
||||
// Creation mode is read write
|
||||
|
||||
if err := Chmod(f.Name(), 0456); err != nil {
|
||||
t.Fatalf("chmod %s 0456: %s", f.Name(), err)
|
||||
fm := FileMode(0456)
|
||||
if runtime.GOOS == "windows" {
|
||||
fm = FileMode(0444) // read-only file
|
||||
}
|
||||
checkMode(t, f.Name(), 0456)
|
||||
if err := Chmod(f.Name(), fm); err != nil {
|
||||
t.Fatalf("chmod %s %#o: %s", f.Name(), fm, err)
|
||||
}
|
||||
checkMode(t, f.Name(), fm)
|
||||
|
||||
if err := f.Chmod(0123); err != nil {
|
||||
t.Fatalf("chmod %s 0123: %s", f.Name(), err)
|
||||
fm = FileMode(0123)
|
||||
if runtime.GOOS == "windows" {
|
||||
fm = FileMode(0666) // read-write file
|
||||
}
|
||||
checkMode(t, f.Name(), 0123)
|
||||
if err := f.Chmod(fm); err != nil {
|
||||
t.Fatalf("chmod %s %#o: %s", f.Name(), fm, err)
|
||||
}
|
||||
checkMode(t, f.Name(), fm)
|
||||
}
|
||||
|
||||
func checkSize(t *testing.T, f *File, size int64) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user