2011-04-02 14:24:03 -07:00
|
|
|
// Copyright 2011 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.
|
|
|
|
|
|
|
|
|
|
// Plan 9 system calls.
|
|
|
|
|
// This file is compiled as ordinary Go code,
|
|
|
|
|
// but it is also input to mksyscall,
|
|
|
|
|
// which parses the //sys lines and generates system call stubs.
|
|
|
|
|
// Note that sometimes we use a lowercase //sys name and
|
|
|
|
|
// wrap it in our own nicer implementation.
|
|
|
|
|
|
|
|
|
|
package syscall
|
|
|
|
|
|
2019-02-19 13:03:55 -08:00
|
|
|
import (
|
|
|
|
|
"internal/oserror"
|
|
|
|
|
"unsafe"
|
|
|
|
|
)
|
2011-04-02 14:24:03 -07:00
|
|
|
|
|
|
|
|
const ImplementsGetwd = true
|
2018-02-19 12:34:53 +00:00
|
|
|
const bitSize16 = 2
|
2011-04-02 14:24:03 -07:00
|
|
|
|
|
|
|
|
// ErrorString implements Error's String method by returning itself.
|
2019-08-22 12:40:52 -04:00
|
|
|
//
|
|
|
|
|
// ErrorString values can be tested against error values from the the os package
|
|
|
|
|
// using errors.Is. For example:
|
|
|
|
|
//
|
|
|
|
|
// _, _, err := syscall.Syscall(...)
|
|
|
|
|
// if errors.Is(err, os.ErrNotExist) ...
|
2011-04-02 14:24:03 -07:00
|
|
|
type ErrorString string
|
|
|
|
|
|
2011-11-08 09:06:02 -05:00
|
|
|
func (e ErrorString) Error() string { return string(e) }
|
2011-04-02 14:24:03 -07:00
|
|
|
|
|
|
|
|
// NewError converts s to an ErrorString, which satisfies the Error interface.
|
2011-11-16 17:37:54 -05:00
|
|
|
func NewError(s string) error { return ErrorString(s) }
|
2011-04-02 14:24:03 -07:00
|
|
|
|
2019-02-19 13:03:55 -08:00
|
|
|
func (e ErrorString) Is(target error) bool {
|
|
|
|
|
switch target {
|
|
|
|
|
case oserror.ErrPermission:
|
|
|
|
|
return checkErrMessageContent(e, "permission denied")
|
|
|
|
|
case oserror.ErrExist:
|
|
|
|
|
return checkErrMessageContent(e, "exists", "is a directory")
|
|
|
|
|
case oserror.ErrNotExist:
|
|
|
|
|
return checkErrMessageContent(e, "does not exist", "not found",
|
|
|
|
|
"has been removed", "no parent")
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkErrMessageContent checks if err message contains one of msgs.
|
|
|
|
|
func checkErrMessageContent(e ErrorString, msgs ...string) bool {
|
|
|
|
|
for _, msg := range msgs {
|
|
|
|
|
if contains(string(e), msg) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// contains is a local version of strings.Contains. It knows len(sep) > 1.
|
|
|
|
|
func contains(s, sep string) bool {
|
|
|
|
|
n := len(sep)
|
|
|
|
|
c := sep[0]
|
|
|
|
|
for i := 0; i+n <= len(s); i++ {
|
|
|
|
|
if s[i] == c && s[i:i+n] == sep {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
net, os, syscall: Plan 9: adjust error handling
syscall: Use NewError for all system errors and introduce
some new errors for compatibility with other packages
and proper error handling in net. Also introduce
Temporary and Timeout methods on ErrorString.
net: Make errors from dial, accept, listen functions follow the
OpError standard and discern whether the underlying
error came from syscall. Since Plan 9 uses a correspondence
between file and network operations, all system error
reporting happens through the underlying file operation.
In Go code, we go through package os for file operations,
so there is another level of indirection in error types.
This change allows us to compare the errors with those in
package syscall, when appropriate.
os: Just use the error string already present in package os,
instead of calling out to package syscall.
R=rsc, ality, rminnich, bradfitz
CC=golang-dev
https://golang.org/cl/7398054
2013-02-28 06:43:21 +01:00
|
|
|
func (e ErrorString) Temporary() bool {
|
|
|
|
|
return e == EINTR || e == EMFILE || e.Timeout()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e ErrorString) Timeout() bool {
|
|
|
|
|
return e == EBUSY || e == ETIMEDOUT
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 09:56:51 -07:00
|
|
|
var emptystring string
|
|
|
|
|
|
2012-05-04 03:44:41 -07:00
|
|
|
// A Note is a string describing a process note.
|
|
|
|
|
// It implements the os.Signal interface.
|
|
|
|
|
type Note string
|
|
|
|
|
|
|
|
|
|
func (n Note) Signal() {}
|
|
|
|
|
|
|
|
|
|
func (n Note) String() string {
|
|
|
|
|
return string(n)
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-02 14:24:03 -07:00
|
|
|
var (
|
|
|
|
|
Stdin = 0
|
|
|
|
|
Stdout = 1
|
|
|
|
|
Stderr = 2
|
|
|
|
|
)
|
|
|
|
|
|
2011-08-17 13:28:29 -04:00
|
|
|
// For testing: clients can set this flag to force
|
|
|
|
|
// creation of IPv6 sockets to return EAFNOSUPPORT.
|
|
|
|
|
var SocketDisableIPv6 bool
|
|
|
|
|
|
2011-11-21 09:55:15 -05:00
|
|
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
|
|
|
|
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
|
2011-04-02 14:24:03 -07:00
|
|
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
|
|
|
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
|
|
|
|
|
2016-04-29 17:39:33 +01:00
|
|
|
//go:nosplit
|
2011-04-02 14:24:03 -07:00
|
|
|
func atoi(b []byte) (n uint) {
|
|
|
|
|
n = 0
|
|
|
|
|
for i := 0; i < len(b); i++ {
|
|
|
|
|
n = n*10 + uint(b[i]-'0')
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func cstring(s []byte) string {
|
2011-04-13 15:13:59 -07:00
|
|
|
for i := range s {
|
2011-04-02 14:24:03 -07:00
|
|
|
if s[i] == 0 {
|
|
|
|
|
return string(s[0:i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return string(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func errstr() string {
|
|
|
|
|
var buf [ERRMAX]byte
|
|
|
|
|
|
|
|
|
|
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
|
|
|
|
|
|
|
|
|
|
buf[len(buf)-1] = 0
|
|
|
|
|
return cstring(buf[:])
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func readnum(path string) (uint, error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
var b [12]byte
|
|
|
|
|
|
|
|
|
|
fd, e := Open(path, O_RDONLY)
|
|
|
|
|
if e != nil {
|
|
|
|
|
return 0, e
|
|
|
|
|
}
|
|
|
|
|
defer Close(fd)
|
|
|
|
|
|
|
|
|
|
n, e := Pread(fd, b[:], 0)
|
|
|
|
|
|
|
|
|
|
if e != nil {
|
|
|
|
|
return 0, e
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m := 0
|
|
|
|
|
for ; m < n && b[m] == ' '; m++ {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return atoi(b[m : n-1]), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getpid() (pid int) {
|
|
|
|
|
n, _ := readnum("#c/pid")
|
|
|
|
|
return int(n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getppid() (ppid int) {
|
|
|
|
|
n, _ := readnum("#c/ppid")
|
|
|
|
|
return int(n)
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Read(fd int, p []byte) (n int, err error) {
|
2013-06-10 22:40:35 +04:00
|
|
|
return Pread(fd, p, -1)
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Write(fd int, p []byte) (n int, err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
return Pwrite(fd, p, -1)
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-09 20:51:58 +04:00
|
|
|
var ioSync int64
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
//sys fd2path(fd int, buf []byte) (err error)
|
|
|
|
|
func Fd2path(fd int) (path string, err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
var buf [512]byte
|
|
|
|
|
|
|
|
|
|
e := fd2path(fd, buf[:])
|
|
|
|
|
if e != nil {
|
|
|
|
|
return "", e
|
|
|
|
|
}
|
|
|
|
|
return cstring(buf[:]), nil
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-30 06:14:55 -08:00
|
|
|
//sys pipe(p *[2]int32) (err error)
|
2011-11-16 17:37:54 -05:00
|
|
|
func Pipe(p []int) (err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
if len(p) != 2 {
|
|
|
|
|
return NewError("bad arg in system call")
|
|
|
|
|
}
|
2014-12-30 06:14:55 -08:00
|
|
|
var pp [2]int32
|
2011-04-02 14:24:03 -07:00
|
|
|
err = pipe(&pp)
|
|
|
|
|
p[0] = int(pp[0])
|
|
|
|
|
p[1] = int(pp[1])
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Underlying system call writes to newoffset via pointer.
|
|
|
|
|
// Implemented in assembly to avoid allocation.
|
|
|
|
|
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
newoffset, e := seek(0, fd, offset, whence)
|
|
|
|
|
|
|
|
|
|
if newoffset == -1 {
|
|
|
|
|
err = NewError(e)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Mkdir(path string, mode uint32) (err error) {
|
2018-02-19 12:34:53 +00:00
|
|
|
// If path exists and is not a directory, Create will fail silently.
|
|
|
|
|
// Work around this by rejecting Mkdir if path exists.
|
|
|
|
|
statbuf := make([]byte, bitSize16)
|
|
|
|
|
// Remove any trailing slashes from path, otherwise the Stat will
|
|
|
|
|
// fail with ENOTDIR.
|
|
|
|
|
n := len(path)
|
|
|
|
|
for n > 1 && path[n-1] == '/' {
|
|
|
|
|
n--
|
|
|
|
|
}
|
|
|
|
|
_, err = Stat(path[0:n], statbuf)
|
|
|
|
|
if err == nil {
|
|
|
|
|
return EEXIST
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-02 14:24:03 -07:00
|
|
|
fd, err := Create(path, O_RDONLY, DMDIR|mode)
|
|
|
|
|
|
|
|
|
|
if fd != -1 {
|
|
|
|
|
Close(fd)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Waitmsg struct {
|
|
|
|
|
Pid int
|
|
|
|
|
Time [3]uint32
|
|
|
|
|
Msg string
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-20 13:34:10 +10:00
|
|
|
func (w Waitmsg) Exited() bool { return true }
|
|
|
|
|
func (w Waitmsg) Signaled() bool { return false }
|
|
|
|
|
|
|
|
|
|
func (w Waitmsg) ExitStatus() int {
|
|
|
|
|
if len(w.Msg) == 0 {
|
|
|
|
|
// a normal exit returns no message
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
//sys await(s []byte) (n int, err error)
|
|
|
|
|
func Await(w *Waitmsg) (err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
var buf [512]byte
|
|
|
|
|
var f [5][]byte
|
|
|
|
|
|
|
|
|
|
n, err := await(buf[:])
|
|
|
|
|
|
|
|
|
|
if err != nil || w == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nf := 0
|
|
|
|
|
p := 0
|
|
|
|
|
for i := 0; i < n && nf < len(f)-1; i++ {
|
|
|
|
|
if buf[i] == ' ' {
|
|
|
|
|
f[nf] = buf[p:i]
|
|
|
|
|
p = i + 1
|
|
|
|
|
nf++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f[nf] = buf[p:]
|
|
|
|
|
nf++
|
|
|
|
|
|
|
|
|
|
if nf != len(f) {
|
|
|
|
|
return NewError("invalid wait message")
|
|
|
|
|
}
|
|
|
|
|
w.Pid = int(atoi(f[0]))
|
|
|
|
|
w.Time[0] = uint32(atoi(f[1]))
|
|
|
|
|
w.Time[1] = uint32(atoi(f[2]))
|
|
|
|
|
w.Time[2] = uint32(atoi(f[3]))
|
2011-06-20 13:34:10 +10:00
|
|
|
w.Msg = cstring(f[4])
|
2011-10-31 13:34:59 -04:00
|
|
|
if w.Msg == "''" {
|
|
|
|
|
// await() returns '' for no error
|
|
|
|
|
w.Msg = ""
|
|
|
|
|
}
|
2011-04-02 14:24:03 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Unmount(name, old string) (err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(name, old)
|
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
|
|
|
oldp, err := BytePtrFromString(old)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
oldptr := uintptr(unsafe.Pointer(oldp))
|
2011-04-02 14:24:03 -07:00
|
|
|
|
|
|
|
|
var r0 uintptr
|
2011-11-21 09:55:15 -05:00
|
|
|
var e ErrorString
|
2011-04-02 14:24:03 -07:00
|
|
|
|
|
|
|
|
// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
|
|
|
|
|
if name == "" {
|
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
|
|
|
r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
|
2011-04-02 14:24:03 -07:00
|
|
|
} else {
|
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
|
|
|
namep, err := BytePtrFromString(name)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
|
|
|
|
|
2012-10-01 10:09:08 +10:00
|
|
|
if int32(r0) == -1 {
|
2011-11-21 09:55:15 -05:00
|
|
|
err = e
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Fchdir(fd int) (err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
path, err := Fd2path(fd)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Chdir(path)
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-19 14:52:28 +09:00
|
|
|
type Timespec struct {
|
|
|
|
|
Sec int32
|
|
|
|
|
Nsec int32
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-02 14:24:03 -07:00
|
|
|
type Timeval struct {
|
|
|
|
|
Sec int32
|
|
|
|
|
Usec int32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
|
|
|
|
nsec += 999 // round up to microsecond
|
|
|
|
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
|
|
|
|
tv.Sec = int32(nsec / 1e9)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-09 12:34:06 +02:00
|
|
|
func nsec() int64 {
|
|
|
|
|
var scratch int64
|
|
|
|
|
|
|
|
|
|
r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
|
|
|
|
|
// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
|
|
|
|
|
if r0 == 0 {
|
|
|
|
|
return scratch
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
2014-07-09 12:34:06 +02:00
|
|
|
return int64(r0)
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
|
|
|
|
|
2013-02-26 01:56:08 +01:00
|
|
|
func Gettimeofday(tv *Timeval) error {
|
2014-07-09 12:34:06 +02:00
|
|
|
nsec := nsec()
|
2011-04-02 14:24:03 -07:00
|
|
|
*tv = NsecToTimeval(nsec)
|
2014-07-09 12:34:06 +02:00
|
|
|
return nil
|
2011-04-02 14:24:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Getegid() (egid int) { return -1 }
|
|
|
|
|
func Geteuid() (euid int) { return -1 }
|
|
|
|
|
func Getgid() (gid int) { return -1 }
|
|
|
|
|
func Getuid() (uid int) { return -1 }
|
|
|
|
|
|
2011-11-16 17:37:54 -05:00
|
|
|
func Getgroups() (gids []int, err error) {
|
2011-04-02 14:24:03 -07:00
|
|
|
return make([]int, 0), nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 19:34:56 -08:00
|
|
|
//sys open(path string, mode int) (fd int, err error)
|
|
|
|
|
func Open(path string, mode int) (fd int, err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(path)
|
2015-02-27 19:34:56 -08:00
|
|
|
return open(path, mode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sys create(path string, mode int, perm uint32) (fd int, err error)
|
|
|
|
|
func Create(path string, mode int, perm uint32) (fd int, err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(path)
|
2015-02-27 19:34:56 -08:00
|
|
|
return create(path, mode, perm)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sys remove(path string) (err error)
|
|
|
|
|
func Remove(path string) error {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(path)
|
2015-02-27 19:34:56 -08:00
|
|
|
return remove(path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sys stat(path string, edir []byte) (n int, err error)
|
|
|
|
|
func Stat(path string, edir []byte) (n int, err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(path)
|
2015-02-27 19:34:56 -08:00
|
|
|
return stat(path, edir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sys bind(name string, old string, flag int) (err error)
|
|
|
|
|
func Bind(name string, old string, flag int) (err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(name, old)
|
2015-02-27 19:34:56 -08:00
|
|
|
return bind(name, old, flag)
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-01 17:30:47 +01:00
|
|
|
//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
|
|
|
|
|
func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(old)
|
2015-03-01 17:30:47 +01:00
|
|
|
return mount(fd, afd, old, flag, aname)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 19:34:56 -08:00
|
|
|
//sys wstat(path string, edir []byte) (err error)
|
|
|
|
|
func Wstat(path string, edir []byte) (err error) {
|
2018-02-28 14:29:27 +00:00
|
|
|
fixwd(path)
|
2015-02-27 19:34:56 -08:00
|
|
|
return wstat(path, edir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sys chdir(path string) (err error)
|
2011-11-21 09:55:15 -05:00
|
|
|
//sys Dup(oldfd int, newfd int) (fd int, err error)
|
|
|
|
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
|
|
|
|
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
|
|
|
|
|
//sys Close(fd int) (err error)
|
|
|
|
|
//sys Fstat(fd int, edir []byte) (n int, err error)
|
|
|
|
|
//sys Fwstat(fd int, edir []byte) (err error)
|