library os: openFileNolog
This commit is contained in:
@@ -532,7 +532,7 @@ func ignoreName(name string) bool {
|
|||||||
func supportedInternal(name string) bool {
|
func supportedInternal(name string) bool {
|
||||||
return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") ||
|
return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") ||
|
||||||
strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") ||
|
strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") ||
|
||||||
strings.HasPrefix(name, "syscall/execenv.")
|
strings.HasPrefix(name, "syscall/unix.") || strings.HasPrefix(name, "syscall/execenv.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -753,6 +753,7 @@ var hasAltPkg = map[string]none{
|
|||||||
"internal/oserror": {},
|
"internal/oserror": {},
|
||||||
"internal/reflectlite": {},
|
"internal/reflectlite": {},
|
||||||
"internal/syscall/execenv": {},
|
"internal/syscall/execenv": {},
|
||||||
|
"internal/syscall/unix": {},
|
||||||
"math": {},
|
"math": {},
|
||||||
"math/cmplx": {},
|
"math/cmplx": {},
|
||||||
"reflect": {},
|
"reflect": {},
|
||||||
|
|||||||
15
internal/lib/internal/syscall/unix/nonblocking_js.go
Normal file
15
internal/lib/internal/syscall/unix/nonblocking_js.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build js && wasm
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
func IsNonblock(fd int) (nonblocking bool, err error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasNonblockFlag(flag int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
23
internal/lib/internal/syscall/unix/nonblocking_unix.go
Normal file
23
internal/lib/internal/syscall/unix/nonblocking_unix.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/c/syscall"
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func IsNonblock(fd int) (nonblocking bool, err error) {
|
||||||
|
flag, e1 := Fcntl(fd, syscall.F_GETFL, 0)
|
||||||
|
if e1 != nil {
|
||||||
|
return false, e1
|
||||||
|
}
|
||||||
|
return flag&syscall.O_NONBLOCK != 0, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func HasNonblockFlag(flag int) bool {
|
||||||
|
return flag&syscall.O_NONBLOCK != 0
|
||||||
|
}
|
||||||
37
internal/lib/internal/syscall/unix/nonblocking_wasip1.go
Normal file
37
internal/lib/internal/syscall/unix/nonblocking_wasip1.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/c/syscall"
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
_ "unsafe" // for go:linkname
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsNonblock(fd int) (nonblocking bool, err error) {
|
||||||
|
flags, e1 := fd_fdstat_get_flags(fd)
|
||||||
|
if e1 != nil {
|
||||||
|
return false, e1
|
||||||
|
}
|
||||||
|
return flags&syscall.FDFLAG_NONBLOCK != 0, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func HasNonblockFlag(flag int) bool {
|
||||||
|
return flag&syscall.FDFLAG_NONBLOCK != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
// This helper is implemented in the syscall package. It means we don't have
|
||||||
|
// to redefine the fd_fdstat_get host import or the fdstat struct it
|
||||||
|
// populates.
|
||||||
|
//
|
||||||
|
//-go:linkname fd_fdstat_get_flags syscall.fd_fdstat_get_flags
|
||||||
|
func fd_fdstat_get_flags(fd int) (uint32, error)
|
||||||
|
*/
|
||||||
22
internal/lib/internal/syscall/unix/unix.go
Normal file
22
internal/lib/internal/syscall/unix/unix.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
@@ -208,7 +208,6 @@ func (f *File) WriteString(s string) (n int, err error) {
|
|||||||
panic("todo: os.(*File).WriteString")
|
panic("todo: os.(*File).WriteString")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
|
// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
|
||||||
func setStickyBit(name string) error {
|
func setStickyBit(name string) error {
|
||||||
fi, err := Stat(name)
|
fi, err := Stat(name)
|
||||||
@@ -217,7 +216,6 @@ func setStickyBit(name string) error {
|
|||||||
}
|
}
|
||||||
return Chmod(name, fi.Mode()|ModeSticky)
|
return Chmod(name, fi.Mode()|ModeSticky)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Open opens the named file for reading. If successful, methods on
|
// Open opens the named file for reading. If successful, methods on
|
||||||
// the returned file can be used for reading; the associated file
|
// the returned file can be used for reading; the associated file
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
|
|||||||
panic("todo: os.(*File).pwrite")
|
panic("todo: os.(*File).pwrite")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
|
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
|
||||||
func syscallMode(i FileMode) (o uint32) {
|
func syscallMode(i FileMode) (o uint32) {
|
||||||
o |= uint32(i.Perm())
|
o |= uint32(i.Perm())
|
||||||
@@ -65,6 +64,7 @@ func syscallMode(i FileMode) (o uint32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
// See docs in file.go:Chmod.
|
// See docs in file.go:Chmod.
|
||||||
func chmod(name string, mode FileMode) error {
|
func chmod(name string, mode FileMode) error {
|
||||||
longName := fixLongPath(name)
|
longName := fixLongPath(name)
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ package os
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/lib/internal/syscall/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fd returns the integer Unix file descriptor referencing the open file.
|
// Fd returns the integer Unix file descriptor referencing the open file.
|
||||||
@@ -30,15 +33,6 @@ func (f *File) Fd() uintptr {
|
|||||||
return f.fd
|
return f.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFile returns a new File with the given file descriptor and
|
|
||||||
// name. The returned value will be nil if fd is not a valid file
|
|
||||||
// descriptor. On Unix systems, if the file descriptor is in
|
|
||||||
// non-blocking mode, NewFile will attempt to return a pollable File
|
|
||||||
// (one for which the SetDeadline methods work).
|
|
||||||
//
|
|
||||||
// After passing it to NewFile, fd may become invalid under the same
|
|
||||||
// conditions described in the comments of the Fd method, and the same
|
|
||||||
// constraints apply.
|
|
||||||
func NewFile(fd uintptr, name string) *File {
|
func NewFile(fd uintptr, name string) *File {
|
||||||
return &File{fd: fd, name: name}
|
return &File{fd: fd, name: name}
|
||||||
}
|
}
|
||||||
@@ -113,6 +107,83 @@ const (
|
|||||||
kindNoPoll
|
kindNoPoll
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// newFile is like NewFile, but if called from OpenFile or Pipe
|
||||||
|
// (as passed in the kind parameter) it tries to add the file to
|
||||||
|
// the runtime poller.
|
||||||
|
func newFile(fd int, name string, kind newFileKind) *File {
|
||||||
|
f := &File{
|
||||||
|
fd: uintptr(fd),
|
||||||
|
name: name,
|
||||||
|
stdoutOrErr: fd == 1 || fd == 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock
|
||||||
|
|
||||||
|
// If the caller passed a non-blocking filedes (kindNonBlock),
|
||||||
|
// we assume they know what they are doing so we allow it to be
|
||||||
|
// used with kqueue.
|
||||||
|
if kind == kindOpenFile {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd":
|
||||||
|
var st syscall.Stat_t
|
||||||
|
err := ignoringEINTR(func() error {
|
||||||
|
return syscall.Fstat(fd, &st)
|
||||||
|
})
|
||||||
|
typ := st.Mode & syscall.S_IFMT
|
||||||
|
// Don't try to use kqueue with regular files on *BSDs.
|
||||||
|
// On FreeBSD a regular file is always
|
||||||
|
// reported as ready for writing.
|
||||||
|
// On Dragonfly, NetBSD and OpenBSD the fd is signaled
|
||||||
|
// only once as ready (both read and write).
|
||||||
|
// Issue 19093.
|
||||||
|
// Also don't add directories to the netpoller.
|
||||||
|
if err == nil && (typ == syscall.S_IFREG || typ == syscall.S_IFDIR) {
|
||||||
|
pollable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// In addition to the behavior described above for regular files,
|
||||||
|
// on Darwin, kqueue does not work properly with fifos:
|
||||||
|
// closing the last writer does not cause a kqueue event
|
||||||
|
// for any readers. See issue #24164.
|
||||||
|
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && typ == syscall.S_IFIFO {
|
||||||
|
pollable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearNonBlock := false
|
||||||
|
if pollable {
|
||||||
|
if kind == kindNonBlock {
|
||||||
|
// The descriptor is already in non-blocking mode.
|
||||||
|
// We only set f.nonblock if we put the file into
|
||||||
|
// non-blocking mode.
|
||||||
|
} else if err := syscall.SetNonblock(fd, true); err == nil {
|
||||||
|
f.nonblock = true
|
||||||
|
clearNonBlock = true
|
||||||
|
} else {
|
||||||
|
pollable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An error here indicates a failure to register
|
||||||
|
// with the netpoll system. That can happen for
|
||||||
|
// a file descriptor that is not supported by
|
||||||
|
// epoll/kqueue; for example, disk files on
|
||||||
|
// Linux systems. We assume that any real error
|
||||||
|
// will show up in later I/O.
|
||||||
|
// We do restore the blocking behavior if it was set by us.
|
||||||
|
if pollErr := f.pfd.Init("file", pollable); pollErr != nil && clearNonBlock {
|
||||||
|
if err := syscall.SetNonblock(fd, false); err == nil {
|
||||||
|
f.nonblock = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.SetFinalizer(f.file, (*file).close)
|
||||||
|
*/
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// func sigpipe() // implemented in package runtime
|
// func sigpipe() // implemented in package runtime
|
||||||
|
|
||||||
@@ -135,7 +206,48 @@ const DevNull = "/dev/null"
|
|||||||
// openFileNolog is the Unix implementation of OpenFile.
|
// openFileNolog is the Unix implementation of OpenFile.
|
||||||
// Changes here should be reflected in openFdAt, if relevant.
|
// Changes here should be reflected in openFdAt, if relevant.
|
||||||
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
|
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
|
||||||
panic("todo: os.openFileNolog")
|
setSticky := false
|
||||||
|
if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
|
||||||
|
if _, err := Stat(name); IsNotExist(err) {
|
||||||
|
setSticky = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r int
|
||||||
|
for {
|
||||||
|
var e error
|
||||||
|
r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
|
||||||
|
if e == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have to check EINTR here, per issues 11180 and 39237.
|
||||||
|
if e == syscall.EINTR {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &PathError{Op: "open", Path: name, Err: e}
|
||||||
|
}
|
||||||
|
|
||||||
|
// open(2) itself won't handle the sticky bit on *BSD and Solaris
|
||||||
|
if setSticky {
|
||||||
|
setStickyBit(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's a race here with fork/exec, which we are
|
||||||
|
// content to live with. See ../syscall/exec_unix.go.
|
||||||
|
if !supportsCloseOnExec {
|
||||||
|
syscall.CloseOnExec(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := kindOpenFile
|
||||||
|
if unix.HasNonblockFlag(flag) {
|
||||||
|
kind = kindNonBlock
|
||||||
|
panic("todo: os.openFileNolog: unix.HasNonblockFlag")
|
||||||
|
}
|
||||||
|
|
||||||
|
f := newFile(r, name, kind)
|
||||||
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tempDir() string {
|
func tempDir() string {
|
||||||
|
|||||||
11
internal/lib/os/sticky_bsd.go
Normal file
11
internal/lib/os/sticky_bsd.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris || wasip1
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
// According to sticky(8), neither open(2) nor mkdir(2) will create
|
||||||
|
// a file with the sticky bit set.
|
||||||
|
const supportsCreateWithStickyBit = false
|
||||||
9
internal/lib/os/sticky_nonbsd.go
Normal file
9
internal/lib/os/sticky_nonbsd.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !aix && !darwin && !dragonfly && !freebsd && !js && !netbsd && !openbsd && !solaris && !wasip1
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
const supportsCreateWithStickyBit = true
|
||||||
11
internal/lib/os/sys_js.go
Normal file
11
internal/lib/os/sys_js.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build js && wasm
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
// supportsCloseOnExec reports whether the platform supports the
|
||||||
|
// O_CLOEXEC flag.
|
||||||
|
const supportsCloseOnExec = false
|
||||||
14
internal/lib/os/sys_unix.go
Normal file
14
internal/lib/os/sys_unix.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
// supportsCloseOnExec reports whether the platform supports the
|
||||||
|
// O_CLOEXEC flag.
|
||||||
|
// On Darwin, the O_CLOEXEC flag was introduced in OS X 10.7 (Darwin 11.0.0).
|
||||||
|
// See https://support.apple.com/kb/HT1633.
|
||||||
|
// On FreeBSD, the O_CLOEXEC flag was introduced in version 8.3.
|
||||||
|
const supportsCloseOnExec = true
|
||||||
11
internal/lib/os/sys_wasip1.go
Normal file
11
internal/lib/os/sys_wasip1.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build wasip1
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
// supportsCloseOnExec reports whether the platform supports the
|
||||||
|
// O_CLOEXEC flag.
|
||||||
|
const supportsCloseOnExec = false
|
||||||
@@ -19,10 +19,11 @@ func Getpagesize() int { return syscall.Getpagesize() }
|
|||||||
|
|
||||||
// File represents an open file descriptor.
|
// File represents an open file descriptor.
|
||||||
type File struct {
|
type File struct {
|
||||||
fd uintptr
|
fd uintptr
|
||||||
name string
|
name string
|
||||||
appendMode bool
|
appendMode bool
|
||||||
nonblock bool
|
nonblock bool
|
||||||
|
stdoutOrErr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// write writes len(b) bytes to the File.
|
// write writes len(b) bytes to the File.
|
||||||
|
|||||||
Reference in New Issue
Block a user