mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
update Go tree to use new syscall package.
R=r DELTA=713 (109 added, 386 deleted, 218 changed) OCL=29707 CL=29722
This commit is contained in:
parent
278b1ab053
commit
9e0fec9c9c
|
@ -10,11 +10,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
fd int64; // file descriptor number
|
fd int; // file descriptor number
|
||||||
name string; // file name at Open time
|
name string; // file name at Open time
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFile(fd int64, name string) *File {
|
func newFile(fd int, name string) *File {
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ var (
|
||||||
Stderr = newFile(2, "/dev/stderr");
|
Stderr = newFile(2, "/dev/stderr");
|
||||||
)
|
)
|
||||||
|
|
||||||
func Open(name string, mode int64, perm int64) (file *File, err os.Error) {
|
func Open(name string, mode int, perm int) (file *File, err os.Error) {
|
||||||
r, e := syscall.Open(name, mode, perm);
|
r, e := syscall.Open(name, mode, perm);
|
||||||
return newFile(r, name), os.ErrnoToError(e)
|
return newFile(r, name), os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
@ -36,16 +36,16 @@ func (file *File) Close() os.Error {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return os.EINVAL
|
return os.EINVAL
|
||||||
}
|
}
|
||||||
r, e := syscall.Close(file.fd);
|
e := syscall.Close(file.fd);
|
||||||
file.fd = -1; // so it can't be closed again
|
file.fd = -1; // so it can't be closed again
|
||||||
return nil
|
return os.ErrnoToError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *File) Read(b []byte) (ret int, err os.Error) {
|
func (file *File) Read(b []byte) (ret int, err os.Error) {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return -1, os.EINVAL
|
return -1, os.EINVAL
|
||||||
}
|
}
|
||||||
r, e := syscall.Read(file.fd, &b[0], int64(len(b)));
|
r, e := syscall.Read(file.fd, b);
|
||||||
return int(r), os.ErrnoToError(e)
|
return int(r), os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func (file *File) Write(b []byte) (ret int, err os.Error) {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return -1, os.EINVAL
|
return -1, os.EINVAL
|
||||||
}
|
}
|
||||||
r, e := syscall.Write(file.fd, &b[0], int64(len(b)));
|
r, e := syscall.Write(file.fd, b);
|
||||||
return int(r), os.ErrnoToError(e)
|
return int(r), os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ function testitpipe {
|
||||||
|
|
||||||
|
|
||||||
testit helloworld "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
|
testit helloworld "" "Hello, world; or Καλημέρα κόσμε; or こんにちは 世界"
|
||||||
testit helloworld3 "" "hello, world can't open file; err=No such file or directory"
|
testit helloworld3 "" "hello, world can't open file; err=no such file or directory"
|
||||||
testit echo "hello, world" "hello, world"
|
testit echo "hello, world" "hello, world"
|
||||||
testit sum "" "6"
|
testit sum "" "6"
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ Error:
|
||||||
// Setting options to 0 waits for p to exit;
|
// Setting options to 0 waits for p to exit;
|
||||||
// other options cause Wait to return for other
|
// other options cause Wait to return for other
|
||||||
// process events; see package os for details.
|
// process events; see package os for details.
|
||||||
func (p *Cmd) Wait(options uint64) (*os.Waitmsg, os.Error) {
|
func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
|
||||||
if p.Pid < 0 {
|
if p.Pid < 0 {
|
||||||
return nil, os.EINVAL;
|
return nil, os.EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# license that can be found in the LICENSE file.
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
# DO NOT EDIT. Automatically generated by gobuild.
|
# DO NOT EDIT. Automatically generated by gobuild.
|
||||||
# gobuild -m dnsclient.go dnsconfig.go dnsmsg.go fd.go fd_${GOOS}.go ip.go net.go net_${GOOS}.go parse.go port.go >Makefile
|
# gobuild -m dnsclient.go dnsconfig.go dnsmsg.go fd.go fd_${GOOS}.go ip.go net.go parse.go port.go >Makefile
|
||||||
|
|
||||||
D=
|
D=
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ O2=\
|
||||||
O3=\
|
O3=\
|
||||||
dnsconfig.$O\
|
dnsconfig.$O\
|
||||||
fd.$O\
|
fd.$O\
|
||||||
net_$(GOOS).$O\
|
|
||||||
|
|
||||||
O4=\
|
O4=\
|
||||||
net.$O\
|
net.$O\
|
||||||
|
@ -72,7 +71,7 @@ a2: $(O2)
|
||||||
rm -f $(O2)
|
rm -f $(O2)
|
||||||
|
|
||||||
a3: $(O3)
|
a3: $(O3)
|
||||||
$(AR) grc _obj$D/net.a dnsconfig.$O fd.$O net_$(GOOS).$O
|
$(AR) grc _obj$D/net.a dnsconfig.$O fd.$O
|
||||||
rm -f $(O3)
|
rm -f $(O3)
|
||||||
|
|
||||||
a4: $(O4)
|
a4: $(O4)
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
// Network file descriptor.
|
// Network file descriptor.
|
||||||
type netFD struct {
|
type netFD struct {
|
||||||
// immutable until Close
|
// immutable until Close
|
||||||
fd int64;
|
fd int;
|
||||||
file *os.File;
|
file *os.File;
|
||||||
cr chan *netFD;
|
cr chan *netFD;
|
||||||
cw chan *netFD;
|
cw chan *netFD;
|
||||||
|
@ -37,28 +37,6 @@ type netFD struct {
|
||||||
ncr, ncw int;
|
ncr, ncw int;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make reads and writes on fd return EAGAIN instead of blocking.
|
|
||||||
func setNonblock(fd int64) os.Error {
|
|
||||||
flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
|
|
||||||
if e != 0 {
|
|
||||||
return os.ErrnoToError(e)
|
|
||||||
}
|
|
||||||
flags, e = syscall.Fcntl(fd, syscall.F_SETFL, flags | syscall.O_NONBLOCK);
|
|
||||||
if e != 0 {
|
|
||||||
return os.ErrnoToError(e)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make reads/writes blocking; last gasp, so no error checking.
|
|
||||||
func setBlock(fd int64) {
|
|
||||||
flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
|
|
||||||
if e != 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
syscall.Fcntl(fd, syscall.F_SETFL, flags & ^syscall.O_NONBLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A pollServer helps FDs determine when to retry a non-blocking
|
// A pollServer helps FDs determine when to retry a non-blocking
|
||||||
// read or write after they get EAGAIN. When an FD needs to wait,
|
// read or write after they get EAGAIN. When an FD needs to wait,
|
||||||
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
|
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
|
||||||
|
@ -91,7 +69,7 @@ func setBlock(fd int64) {
|
||||||
type pollServer struct {
|
type pollServer struct {
|
||||||
cr, cw chan *netFD; // buffered >= 1
|
cr, cw chan *netFD; // buffered >= 1
|
||||||
pr, pw *os.File;
|
pr, pw *os.File;
|
||||||
pending map[int64] *netFD;
|
pending map[int] *netFD;
|
||||||
poll *pollster; // low-level OS hooks
|
poll *pollster; // low-level OS hooks
|
||||||
deadline int64; // next deadline (nsec since 1970)
|
deadline int64; // next deadline (nsec since 1970)
|
||||||
}
|
}
|
||||||
|
@ -104,23 +82,26 @@ func newPollServer() (s *pollServer, err os.Error) {
|
||||||
if s.pr, s.pw, err = os.Pipe(); err != nil {
|
if s.pr, s.pw, err = os.Pipe(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err = setNonblock(s.pr.Fd()); err != nil {
|
var e int;
|
||||||
|
if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
|
||||||
|
Errno:
|
||||||
|
err = os.ErrnoToError(e);
|
||||||
Error:
|
Error:
|
||||||
s.pr.Close();
|
s.pr.Close();
|
||||||
s.pw.Close();
|
s.pw.Close();
|
||||||
return nil, err
|
return nil, err;
|
||||||
}
|
}
|
||||||
if err = setNonblock(s.pw.Fd()); err != nil {
|
if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 {
|
||||||
goto Error
|
goto Errno;
|
||||||
}
|
}
|
||||||
if s.poll, err = newpollster(); err != nil {
|
if s.poll, err = newpollster(); err != nil {
|
||||||
goto Error
|
goto Error;
|
||||||
}
|
}
|
||||||
if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
|
if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
|
||||||
s.poll.Close();
|
s.poll.Close();
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
s.pending = make(map[int64] *netFD);
|
s.pending = make(map[int] *netFD);
|
||||||
go s.Run();
|
go s.Run();
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
@ -168,7 +149,7 @@ func (s *pollServer) AddFD(fd *netFD, mode int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *pollServer) LookupFD(fd int64, mode int) *netFD {
|
func (s *pollServer) LookupFD(fd int, mode int) *netFD {
|
||||||
key := fd << 1;
|
key := fd << 1;
|
||||||
if mode == 'w' {
|
if mode == 'w' {
|
||||||
key++;
|
key++;
|
||||||
|
@ -318,12 +299,12 @@ func _StartServer() {
|
||||||
pollserver = p
|
pollserver = p
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFD(fd int64, net, laddr, raddr string) (f *netFD, err os.Error) {
|
func newFD(fd int, net, laddr, raddr string) (f *netFD, err os.Error) {
|
||||||
if pollserver == nil {
|
if pollserver == nil {
|
||||||
once.Do(_StartServer);
|
once.Do(_StartServer);
|
||||||
}
|
}
|
||||||
if err = setNonblock(fd); err != nil {
|
if e := syscall.SetNonblock(fd, true); e != 0 {
|
||||||
return nil, err
|
return nil, os.ErrnoToError(e);
|
||||||
}
|
}
|
||||||
f = new(netFD);
|
f = new(netFD);
|
||||||
f.fd = fd;
|
f.fd = fd;
|
||||||
|
@ -347,7 +328,7 @@ func (fd *netFD) Close() os.Error {
|
||||||
// we can handle the extra OS processes.
|
// we can handle the extra OS processes.
|
||||||
// Otherwise we'll need to use the pollserver
|
// Otherwise we'll need to use the pollserver
|
||||||
// for Close too. Sigh.
|
// for Close too. Sigh.
|
||||||
setBlock(fd.file.Fd());
|
syscall.SetNonblock(fd.file.Fd(), false);
|
||||||
|
|
||||||
e := fd.file.Close();
|
e := fd.file.Close();
|
||||||
fd.file = nil;
|
fd.file = nil;
|
||||||
|
@ -406,9 +387,9 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
|
||||||
return nn, err
|
return nn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err os.Error)
|
func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error)
|
||||||
|
|
||||||
func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err os.Error) {
|
func (fd *netFD) accept() (nfd *netFD, err os.Error) {
|
||||||
if fd == nil || fd.file == nil {
|
if fd == nil || fd.file == nil {
|
||||||
return nil, os.EINVAL
|
return nil, os.EINVAL
|
||||||
}
|
}
|
||||||
|
@ -417,9 +398,10 @@ func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err os.Error) {
|
||||||
// It is okay to hold the lock across syscall.Accept
|
// It is okay to hold the lock across syscall.Accept
|
||||||
// because we have put fd.fd into non-blocking mode.
|
// because we have put fd.fd into non-blocking mode.
|
||||||
syscall.ForkLock.RLock();
|
syscall.ForkLock.RLock();
|
||||||
var s, e int64;
|
var s, e int;
|
||||||
|
var sa syscall.Sockaddr;
|
||||||
for {
|
for {
|
||||||
s, e = syscall.Accept(fd.fd, sa);
|
s, sa, e = syscall.Accept(fd.fd);
|
||||||
if e != syscall.EAGAIN {
|
if e != syscall.EAGAIN {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -434,7 +416,7 @@ func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err os.Error) {
|
||||||
syscall.CloseOnExec(s);
|
syscall.CloseOnExec(s);
|
||||||
syscall.ForkLock.RUnlock();
|
syscall.ForkLock.RUnlock();
|
||||||
|
|
||||||
raddr, err1 := sockaddrToHostPort(sa);
|
raddr, err1 := sockaddrToString(sa);
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
raddr = "invalid-address";
|
raddr = "invalid-address";
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,14 @@ import (
|
||||||
var kqueuePhaseError = &Error{"kqueue phase error"}
|
var kqueuePhaseError = &Error{"kqueue phase error"}
|
||||||
|
|
||||||
type pollster struct {
|
type pollster struct {
|
||||||
kq int64;
|
kq int;
|
||||||
eventbuf [10]syscall.Kevent_t;
|
eventbuf [10]syscall.Kevent_t;
|
||||||
events []syscall.Kevent_t;
|
events []syscall.Kevent_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
func newpollster() (p *pollster, err os.Error) {
|
func newpollster() (p *pollster, err os.Error) {
|
||||||
p = new(pollster);
|
p = new(pollster);
|
||||||
var e int64;
|
var e int;
|
||||||
if p.kq, e = syscall.Kqueue(); e != 0 {
|
if p.kq, e = syscall.Kqueue(); e != 0 {
|
||||||
return nil, os.ErrnoToError(e)
|
return nil, os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func newpollster() (p *pollster, err os.Error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error {
|
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
|
||||||
var kmode int16;
|
var kmode int16;
|
||||||
if mode == 'r' {
|
if mode == 'r' {
|
||||||
kmode = syscall.EVFILT_READ
|
kmode = syscall.EVFILT_READ
|
||||||
|
@ -39,7 +39,7 @@ func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error {
|
||||||
}
|
}
|
||||||
var events [1]syscall.Kevent_t;
|
var events [1]syscall.Kevent_t;
|
||||||
ev := &events[0];
|
ev := &events[0];
|
||||||
ev.Ident = fd;
|
ev.Ident = uint64(fd);
|
||||||
ev.Filter = kmode;
|
ev.Filter = kmode;
|
||||||
|
|
||||||
// EV_ADD - add event to kqueue list
|
// EV_ADD - add event to kqueue list
|
||||||
|
@ -55,16 +55,16 @@ func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error {
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return os.ErrnoToError(e)
|
return os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
if n != 1 || (ev.Flags & syscall.EV_ERROR) == 0 || ev.Ident != fd || ev.Filter != kmode {
|
if n != 1 || (ev.Flags & syscall.EV_ERROR) == 0 || ev.Ident != uint64(fd) || ev.Filter != kmode {
|
||||||
return kqueuePhaseError
|
return kqueuePhaseError
|
||||||
}
|
}
|
||||||
if ev.Data != 0 {
|
if ev.Data != 0 {
|
||||||
return os.ErrnoToError(ev.Data)
|
return os.ErrnoToError(int(ev.Data))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) DelFD(fd int64, mode int) {
|
func (p *pollster) DelFD(fd int, mode int) {
|
||||||
var kmode int16;
|
var kmode int16;
|
||||||
if mode == 'r' {
|
if mode == 'r' {
|
||||||
kmode = syscall.EVFILT_READ
|
kmode = syscall.EVFILT_READ
|
||||||
|
@ -73,7 +73,7 @@ func (p *pollster) DelFD(fd int64, mode int) {
|
||||||
}
|
}
|
||||||
var events [1]syscall.Kevent_t;
|
var events [1]syscall.Kevent_t;
|
||||||
ev := &events[0];
|
ev := &events[0];
|
||||||
ev.Ident = fd;
|
ev.Ident = uint64(fd);
|
||||||
ev.Filter = kmode;
|
ev.Filter = kmode;
|
||||||
|
|
||||||
// EV_DELETE - delete event from kqueue list
|
// EV_DELETE - delete event from kqueue list
|
||||||
|
@ -83,7 +83,7 @@ func (p *pollster) DelFD(fd int64, mode int) {
|
||||||
syscall.Kevent(p.kq, &events, &events, nil);
|
syscall.Kevent(p.kq, &events, &events, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
|
||||||
var t *syscall.Timespec;
|
var t *syscall.Timespec;
|
||||||
for len(p.events) == 0 {
|
for len(p.events) == 0 {
|
||||||
if nsec > 0 {
|
if nsec > 0 {
|
||||||
|
@ -91,7 +91,8 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
||||||
t = new(syscall.Timespec);
|
t = new(syscall.Timespec);
|
||||||
}
|
}
|
||||||
t.Sec = nsec / 1e9;
|
t.Sec = nsec / 1e9;
|
||||||
t.Nsec = uint64(nsec % 1e9);
|
t.Nsec = int64(nsec % 1e9);
|
||||||
|
// *t = syscall.NsecToTimespec(nsec);
|
||||||
}
|
}
|
||||||
nn, e := syscall.Kevent(p.kq, nil, &p.eventbuf, t);
|
nn, e := syscall.Kevent(p.kq, nil, &p.eventbuf, t);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
|
@ -107,7 +108,7 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
||||||
}
|
}
|
||||||
ev := &p.events[0];
|
ev := &p.events[0];
|
||||||
p.events = p.events[1:len(p.events)];
|
p.events = p.events[1:len(p.events)];
|
||||||
fd = ev.Ident;
|
fd = int(ev.Ident);
|
||||||
if ev.Filter == syscall.EVFILT_READ {
|
if ev.Filter == syscall.EVFILT_READ {
|
||||||
mode = 'r'
|
mode = 'r'
|
||||||
} else {
|
} else {
|
||||||
|
@ -117,6 +118,5 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) Close() os.Error {
|
func (p *pollster) Close() os.Error {
|
||||||
r, e := syscall.Close(p.kq);
|
return os.ErrnoToError(syscall.Close(p.kq))
|
||||||
return os.ErrnoToError(e)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,27 +18,27 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type pollster struct {
|
type pollster struct {
|
||||||
epfd int64;
|
epfd int;
|
||||||
|
|
||||||
// Events we're already waiting for
|
// Events we're already waiting for
|
||||||
events map[int64] uint32;
|
events map[int] uint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
func newpollster() (p *pollster, err os.Error) {
|
func newpollster() (p *pollster, err os.Error) {
|
||||||
p = new(pollster);
|
p = new(pollster);
|
||||||
var e int64;
|
var e int;
|
||||||
|
|
||||||
// The arg to epoll_create is a hint to the kernel
|
// The arg to epoll_create is a hint to the kernel
|
||||||
// about the number of FDs we will care about.
|
// about the number of FDs we will care about.
|
||||||
// We don't know.
|
// We don't know.
|
||||||
if p.epfd, e = syscall.Epoll_create(16); e != 0 {
|
if p.epfd, e = syscall.EpollCreate(16); e != 0 {
|
||||||
return nil, os.ErrnoToError(e)
|
return nil, os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
p.events = make(map[int64] uint32);
|
p.events = make(map[int] uint32);
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error {
|
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
|
||||||
var ev syscall.EpollEvent;
|
var ev syscall.EpollEvent;
|
||||||
var already bool;
|
var already bool;
|
||||||
ev.Fd = int32(fd);
|
ev.Fd = int32(fd);
|
||||||
|
@ -52,20 +52,20 @@ func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error {
|
||||||
ev.Events |= writeFlags;
|
ev.Events |= writeFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
var op int64;
|
var op int;
|
||||||
if already {
|
if already {
|
||||||
op = syscall.EPOLL_CTL_MOD;
|
op = syscall.EPOLL_CTL_MOD;
|
||||||
} else {
|
} else {
|
||||||
op = syscall.EPOLL_CTL_ADD;
|
op = syscall.EPOLL_CTL_ADD;
|
||||||
}
|
}
|
||||||
if e := syscall.Epoll_ctl(p.epfd, op, fd, &ev); e != 0 {
|
if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 {
|
||||||
return os.ErrnoToError(e)
|
return os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
p.events[fd] = ev.Events;
|
p.events[fd] = ev.Events;
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) StopWaiting(fd int64, bits uint) {
|
func (p *pollster) StopWaiting(fd int, bits uint) {
|
||||||
events, already := p.events[fd];
|
events, already := p.events[fd];
|
||||||
if !already {
|
if !already {
|
||||||
print("Epoll unexpected fd=", fd, "\n");
|
print("Epoll unexpected fd=", fd, "\n");
|
||||||
|
@ -86,19 +86,19 @@ func (p *pollster) StopWaiting(fd int64, bits uint) {
|
||||||
var ev syscall.EpollEvent;
|
var ev syscall.EpollEvent;
|
||||||
ev.Fd = int32(fd);
|
ev.Fd = int32(fd);
|
||||||
ev.Events = events;
|
ev.Events = events;
|
||||||
if e := syscall.Epoll_ctl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
|
if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
|
||||||
print("Epoll modify fd=", fd, ": ", os.ErrnoToError(e).String(), "\n");
|
print("Epoll modify fd=", fd, ": ", os.ErrnoToError(e).String(), "\n");
|
||||||
}
|
}
|
||||||
p.events[fd] = events;
|
p.events[fd] = events;
|
||||||
} else {
|
} else {
|
||||||
if e := syscall.Epoll_ctl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
|
if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
|
||||||
print("Epoll delete fd=", fd, ": ", os.ErrnoToError(e).String(), "\n");
|
print("Epoll delete fd=", fd, ": ", os.ErrnoToError(e).String(), "\n");
|
||||||
}
|
}
|
||||||
p.events[fd] = 0, false;
|
p.events[fd] = 0, false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) DelFD(fd int64, mode int) {
|
func (p *pollster) DelFD(fd int, mode int) {
|
||||||
if mode == 'r' {
|
if mode == 'r' {
|
||||||
p.StopWaiting(fd, readFlags);
|
p.StopWaiting(fd, readFlags);
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,17 +106,17 @@ func (p *pollster) DelFD(fd int64, mode int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
|
||||||
// Get an event.
|
// Get an event.
|
||||||
var evarray [1]syscall.EpollEvent;
|
var evarray [1]syscall.EpollEvent;
|
||||||
ev := &evarray[0];
|
ev := &evarray[0];
|
||||||
var msec int64 = -1;
|
var msec int = -1;
|
||||||
if nsec > 0 {
|
if nsec > 0 {
|
||||||
msec = (nsec + 1e6 - 1)/1e6;
|
msec = int((nsec + 1e6 - 1)/1e6);
|
||||||
}
|
}
|
||||||
n, e := syscall.Epoll_wait(p.epfd, &evarray, msec);
|
n, e := syscall.EpollWait(p.epfd, &evarray, msec);
|
||||||
for e == syscall.EAGAIN || e == syscall.EINTR {
|
for e == syscall.EAGAIN || e == syscall.EINTR {
|
||||||
n, e = syscall.Epoll_wait(p.epfd, &evarray, msec);
|
n, e = syscall.EpollWait(p.epfd, &evarray, msec);
|
||||||
}
|
}
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return -1, 0, os.ErrnoToError(e);
|
return -1, 0, os.ErrnoToError(e);
|
||||||
|
@ -124,7 +124,7 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return -1, 0, nil;
|
return -1, 0, nil;
|
||||||
}
|
}
|
||||||
fd = int64(ev.Fd);
|
fd = int(ev.Fd);
|
||||||
|
|
||||||
if ev.Events & writeFlags != 0 {
|
if ev.Events & writeFlags != 0 {
|
||||||
p.StopWaiting(fd, writeFlags);
|
p.StopWaiting(fd, writeFlags);
|
||||||
|
@ -146,6 +146,5 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pollster) Close() os.Error {
|
func (p *pollster) Close() os.Error {
|
||||||
r, e := syscall.Close(p.epfd);
|
return os.ErrnoToError(syscall.Close(p.epfd));
|
||||||
return os.ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,12 @@ func kernelSupportsIPv6() bool {
|
||||||
|
|
||||||
var preferIPv4 = !kernelSupportsIPv6()
|
var preferIPv4 = !kernelSupportsIPv6()
|
||||||
|
|
||||||
|
// TODO(rsc): if syscall.OS == "linux", we're supposd to read
|
||||||
|
// /proc/sys/net/core/somaxconn,
|
||||||
|
// to take advantage of kernels that have raised the limit.
|
||||||
|
func listenBacklog() int {
|
||||||
|
return syscall.SOMAXCONN
|
||||||
|
}
|
||||||
|
|
||||||
func LookupHost(name string) (cname string, addrs []string, err os.Error)
|
func LookupHost(name string) (cname string, addrs []string, err os.Error)
|
||||||
|
|
||||||
|
@ -212,20 +218,48 @@ func hostPortToIP(net, hostport, mode string) (ip IP, iport int, err os.Error) {
|
||||||
return addr, p, nil
|
return addr, p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert socket address into "host:port".
|
func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error) {
|
||||||
func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err os.Error) {
|
switch a := sa.(type) {
|
||||||
switch sa.Family {
|
case *syscall.SockaddrInet4:
|
||||||
case syscall.AF_INET, syscall.AF_INET6:
|
return joinHostPort(IP(&a.Addr).String(), strconv.Itoa(a.Port)), nil;
|
||||||
addr, port, e := sockaddrToIP(sa);
|
case *syscall.SockaddrInet6:
|
||||||
if e != nil {
|
return joinHostPort(IP(&a.Addr).String(), strconv.Itoa(a.Port)), nil;
|
||||||
return "", e
|
case *syscall.SockaddrUnix:
|
||||||
}
|
return a.Name, nil;
|
||||||
host := addr.String();
|
|
||||||
return joinHostPort(host, strconv.Itoa(port)), nil;
|
|
||||||
default:
|
|
||||||
return "", UnknownSocketFamily
|
|
||||||
}
|
}
|
||||||
return "", nil // not reached
|
return "", UnknownSocketFamily
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) {
|
||||||
|
switch family {
|
||||||
|
case syscall.AF_INET:
|
||||||
|
if ip = ip.To4(); ip == nil {
|
||||||
|
return nil, os.EINVAL
|
||||||
|
}
|
||||||
|
s := new(syscall.SockaddrInet4);
|
||||||
|
for i := 0; i < IPv4len; i++ {
|
||||||
|
s.Addr[i] = ip[i];
|
||||||
|
}
|
||||||
|
s.Port = port;
|
||||||
|
return s, nil;
|
||||||
|
case syscall.AF_INET6:
|
||||||
|
// IPv4 callers use 0.0.0.0 to mean "announce on any available address".
|
||||||
|
// In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0",
|
||||||
|
// which it refuses to do. Rewrite to the IPv6 all zeros.
|
||||||
|
if p4 := ip.To4(); p4 != nil && p4[0] == 0 && p4[1] == 0 && p4[2] == 0 && p4[3] == 0 {
|
||||||
|
ip = IPzero;
|
||||||
|
}
|
||||||
|
if ip = ip.To16(); ip == nil {
|
||||||
|
return nil, os.EINVAL
|
||||||
|
}
|
||||||
|
s := new(syscall.SockaddrInet6);
|
||||||
|
for i := 0; i < IPv6len; i++ {
|
||||||
|
s.Addr[i] = ip[i];
|
||||||
|
}
|
||||||
|
s.Port = port;
|
||||||
|
return s, nil;
|
||||||
|
}
|
||||||
|
return nil, os.EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boolean to int.
|
// Boolean to int.
|
||||||
|
@ -237,7 +271,7 @@ func boolint(b bool) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic socket creation.
|
// Generic socket creation.
|
||||||
func socket(net, laddr, raddr string, f, p, t int64, la, ra *syscall.Sockaddr) (fd *netFD, err os.Error) {
|
func socket(net, laddr, raddr string, f, p, t int, la, ra syscall.Sockaddr) (fd *netFD, err os.Error) {
|
||||||
// See ../syscall/exec.go for description of ForkLock.
|
// See ../syscall/exec.go for description of ForkLock.
|
||||||
syscall.ForkLock.RLock();
|
syscall.ForkLock.RLock();
|
||||||
s, e := syscall.Socket(f, p, t);
|
s, e := syscall.Socket(f, p, t);
|
||||||
|
@ -249,11 +283,11 @@ func socket(net, laddr, raddr string, f, p, t int64, la, ra *syscall.Sockaddr) (
|
||||||
syscall.ForkLock.RUnlock();
|
syscall.ForkLock.RUnlock();
|
||||||
|
|
||||||
// Allow reuse of recently-used addresses.
|
// Allow reuse of recently-used addresses.
|
||||||
syscall.Setsockopt_int(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1);
|
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1);
|
||||||
|
|
||||||
var r int64;
|
var r int64;
|
||||||
if la != nil {
|
if la != nil {
|
||||||
r, e = syscall.Bind(s, la);
|
e = syscall.Bind(s, la);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
syscall.Close(s);
|
syscall.Close(s);
|
||||||
return nil, os.ErrnoToError(e)
|
return nil, os.ErrnoToError(e)
|
||||||
|
@ -261,7 +295,7 @@ func socket(net, laddr, raddr string, f, p, t int64, la, ra *syscall.Sockaddr) (
|
||||||
}
|
}
|
||||||
|
|
||||||
if ra != nil {
|
if ra != nil {
|
||||||
r, e = syscall.Connect(s, ra);
|
e = syscall.Connect(s, ra);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
syscall.Close(s);
|
syscall.Close(s);
|
||||||
return nil, os.ErrnoToError(e)
|
return nil, os.ErrnoToError(e)
|
||||||
|
@ -291,7 +325,7 @@ func (c *connBase) File() *os.File {
|
||||||
return c.fd.file;
|
return c.fd.file;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) sysFD() int64 {
|
func (c *connBase) sysFD() int {
|
||||||
if c == nil || c.fd == nil {
|
if c == nil || c.fd == nil {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -335,20 +369,21 @@ func (c *connBase) Close() os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func setsockopt_int(fd, level, opt int64, value int) os.Error {
|
func setsockoptInt(fd, level, opt int, value int) os.Error {
|
||||||
return os.ErrnoToError(syscall.Setsockopt_int(fd, level, opt, value));
|
return os.ErrnoToError(syscall.SetsockoptInt(fd, level, opt, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt_tv(fd, level, opt int64, nsec int64) os.Error {
|
func setsockoptNsec(fd, level, opt int, nsec int64) os.Error {
|
||||||
return os.ErrnoToError(syscall.Setsockopt_tv(fd, level, opt, nsec));
|
var tv = syscall.NsecToTimeval(nsec);
|
||||||
|
return os.ErrnoToError(syscall.SetsockoptTimeval(fd, level, opt, &tv));
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetReadBuffer(bytes int) os.Error {
|
func (c *connBase) SetReadBuffer(bytes int) os.Error {
|
||||||
return setsockopt_int(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes);
|
return setsockoptInt(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetWriteBuffer(bytes int) os.Error {
|
func (c *connBase) SetWriteBuffer(bytes int) os.Error {
|
||||||
return setsockopt_int(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes);
|
return setsockoptInt(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetReadTimeout(nsec int64) os.Error {
|
func (c *connBase) SetReadTimeout(nsec int64) os.Error {
|
||||||
|
@ -369,7 +404,7 @@ func (c *connBase) SetTimeout(nsec int64) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetReuseAddr(reuse bool) os.Error {
|
func (c *connBase) SetReuseAddr(reuse bool) os.Error {
|
||||||
return setsockopt_int(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse));
|
return setsockoptInt(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse));
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) BindToDevice(dev string) os.Error {
|
func (c *connBase) BindToDevice(dev string) os.Error {
|
||||||
|
@ -378,22 +413,30 @@ func (c *connBase) BindToDevice(dev string) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetDontRoute(dontroute bool) os.Error {
|
func (c *connBase) SetDontRoute(dontroute bool) os.Error {
|
||||||
return setsockopt_int(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute));
|
return setsockoptInt(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute));
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetKeepAlive(keepalive bool) os.Error {
|
func (c *connBase) SetKeepAlive(keepalive bool) os.Error {
|
||||||
return setsockopt_int(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive));
|
return setsockoptInt(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive));
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connBase) SetLinger(sec int) os.Error {
|
func (c *connBase) SetLinger(sec int) os.Error {
|
||||||
e := syscall.Setsockopt_linger(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_LINGER, sec);
|
var l syscall.Linger;
|
||||||
|
if sec >= 0 {
|
||||||
|
l.Onoff = 1;
|
||||||
|
l.Linger = int32(sec);
|
||||||
|
} else {
|
||||||
|
l.Onoff = 0;
|
||||||
|
l.Linger = 0;
|
||||||
|
}
|
||||||
|
e := syscall.SetsockoptLinger(c.sysFD(), syscall.SOL_SOCKET, syscall.SO_LINGER, &l);
|
||||||
return os.ErrnoToError(e);
|
return os.ErrnoToError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Internet sockets (TCP, UDP)
|
// Internet sockets (TCP, UDP)
|
||||||
|
|
||||||
func internetSocket(net, laddr, raddr string, proto int64, mode string) (fd *netFD, err os.Error) {
|
func internetSocket(net, laddr, raddr string, proto int, mode string) (fd *netFD, err os.Error) {
|
||||||
// Parse addresses (unless they are empty).
|
// Parse addresses (unless they are empty).
|
||||||
var lip, rip IP;
|
var lip, rip IP;
|
||||||
var lport, rport int;
|
var lport, rport int;
|
||||||
|
@ -430,25 +473,22 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string) (fd *net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cvt func(addr IP, port int) (sa *syscall.Sockaddr, err os.Error);
|
var family int;
|
||||||
var family int64;
|
|
||||||
if vers == 4 {
|
if vers == 4 {
|
||||||
cvt = v4ToSockaddr;
|
|
||||||
family = syscall.AF_INET
|
family = syscall.AF_INET
|
||||||
} else {
|
} else {
|
||||||
cvt = v6ToSockaddr;
|
|
||||||
family = syscall.AF_INET6
|
family = syscall.AF_INET6
|
||||||
}
|
}
|
||||||
|
|
||||||
var la, ra *syscall.Sockaddr;
|
var la, ra syscall.Sockaddr;
|
||||||
if lip != nil {
|
if lip != nil {
|
||||||
la, lerr = cvt(lip, lport);
|
la, lerr = ipToSockaddr(family, lip, lport);
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
return nil, lerr
|
return nil, lerr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rip != nil {
|
if rip != nil {
|
||||||
ra, rerr = cvt(rip, rport);
|
ra, rerr = ipToSockaddr(family, rip, rport);
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
return nil, rerr
|
return nil, rerr
|
||||||
}
|
}
|
||||||
|
@ -471,7 +511,7 @@ func (c *ConnTCP) SetNoDelay(nodelay bool) os.Error {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return os.EINVAL
|
return os.EINVAL
|
||||||
}
|
}
|
||||||
return setsockopt_int(c.sysFD(), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(nodelay))
|
return setsockoptInt(c.sysFD(), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(nodelay))
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConnTCP(fd *netFD, raddr string) *ConnTCP {
|
func newConnTCP(fd *netFD, raddr string) *ConnTCP {
|
||||||
|
@ -535,7 +575,7 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err os.Error) {
|
||||||
// Unix domain sockets
|
// Unix domain sockets
|
||||||
|
|
||||||
func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error) {
|
func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error) {
|
||||||
var proto int64;
|
var proto int;
|
||||||
switch net {
|
switch net {
|
||||||
default:
|
default:
|
||||||
return nil, UnknownNetwork;
|
return nil, UnknownNetwork;
|
||||||
|
@ -545,7 +585,7 @@ func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error)
|
||||||
proto = syscall.SOCK_DGRAM;
|
proto = syscall.SOCK_DGRAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
var la, ra *syscall.Sockaddr;
|
var la, ra syscall.Sockaddr;
|
||||||
switch mode {
|
switch mode {
|
||||||
case "dial":
|
case "dial":
|
||||||
if laddr != "" {
|
if laddr != "" {
|
||||||
|
@ -554,19 +594,13 @@ func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error)
|
||||||
if raddr == "" {
|
if raddr == "" {
|
||||||
return nil, MissingAddress;
|
return nil, MissingAddress;
|
||||||
}
|
}
|
||||||
ra, err = unixToSockaddr(raddr);
|
ra = &syscall.SockaddrUnix{Name: raddr};
|
||||||
if err != nil {
|
|
||||||
return nil, err;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "listen":
|
case "listen":
|
||||||
if laddr == "" {
|
if laddr == "" {
|
||||||
return nil, MissingAddress;
|
return nil, MissingAddress;
|
||||||
}
|
}
|
||||||
la, err = unixToSockaddr(laddr);
|
la = &syscall.SockaddrUnix{Name: laddr};
|
||||||
if err != nil {
|
|
||||||
return nil, err;
|
|
||||||
}
|
|
||||||
if raddr != "" {
|
if raddr != "" {
|
||||||
return nil, BadAddress;
|
return nil, BadAddress;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +670,7 @@ func ListenUnix(net, laddr string) (l *ListenerUnix, err os.Error) {
|
||||||
}
|
}
|
||||||
fd = fd1;
|
fd = fd1;
|
||||||
}
|
}
|
||||||
r, e1 := syscall.Listen(fd.fd, 8); // listenBacklog());
|
e1 := syscall.Listen(fd.fd, 8); // listenBacklog());
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
syscall.Close(fd.fd);
|
syscall.Close(fd.fd);
|
||||||
return nil, os.ErrnoToError(e1);
|
return nil, os.ErrnoToError(e1);
|
||||||
|
@ -650,17 +684,11 @@ func (l *ListenerUnix) AcceptUnix() (c *ConnUnix, raddr string, err os.Error) {
|
||||||
if l == nil || l.fd == nil || l.fd.fd < 0 {
|
if l == nil || l.fd == nil || l.fd.fd < 0 {
|
||||||
return nil, "", os.EINVAL
|
return nil, "", os.EINVAL
|
||||||
}
|
}
|
||||||
var sa syscall.Sockaddr;
|
fd, e := l.fd.accept();
|
||||||
fd, e := l.fd.Accept(&sa);
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, "", e
|
return nil, "", e
|
||||||
}
|
}
|
||||||
raddr, err = sockaddrToUnix(&sa);
|
return newConnUnix(fd, fd.raddr), raddr, nil
|
||||||
if err != nil {
|
|
||||||
fd.Close();
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
return newConnUnix(fd, raddr), raddr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept implements the Accept method in the Listener interface;
|
// Accept implements the Accept method in the Listener interface;
|
||||||
|
@ -765,7 +793,7 @@ func ListenTCP(net, laddr string) (l *ListenerTCP, err os.Error) {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
r, e1 := syscall.Listen(fd.fd, listenBacklog());
|
e1 := syscall.Listen(fd.fd, listenBacklog());
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
syscall.Close(fd.fd);
|
syscall.Close(fd.fd);
|
||||||
return nil, os.ErrnoToError(e1)
|
return nil, os.ErrnoToError(e1)
|
||||||
|
@ -781,17 +809,11 @@ func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err os.Error) {
|
||||||
if l == nil || l.fd == nil || l.fd.fd < 0 {
|
if l == nil || l.fd == nil || l.fd.fd < 0 {
|
||||||
return nil, "", os.EINVAL
|
return nil, "", os.EINVAL
|
||||||
}
|
}
|
||||||
var sa syscall.Sockaddr;
|
fd, e := l.fd.accept();
|
||||||
fd, e := l.fd.Accept(&sa);
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, "", e
|
return nil, "", e
|
||||||
}
|
}
|
||||||
raddr, err = sockaddrToHostPort(&sa);
|
return newConnTCP(fd, fd.raddr), fd.raddr, nil
|
||||||
if err != nil {
|
|
||||||
fd.Close();
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
return newConnTCP(fd, raddr), raddr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept implements the Accept method in the Listener interface;
|
// Accept implements the Accept method in the Listener interface;
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net";
|
|
||||||
"os";
|
|
||||||
"syscall";
|
|
||||||
"unsafe";
|
|
||||||
)
|
|
||||||
|
|
||||||
func v4ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
p = p.To4();
|
|
||||||
if p == nil || port < 0 || port > 0xFFFF {
|
|
||||||
return nil, os.EINVAL
|
|
||||||
}
|
|
||||||
sa := new(syscall.SockaddrInet4);
|
|
||||||
sa.Len = syscall.SizeofSockaddrInet4;
|
|
||||||
sa.Family = syscall.AF_INET;
|
|
||||||
sa.Port[0] = byte(port>>8);
|
|
||||||
sa.Port[1] = byte(port);
|
|
||||||
for i := 0; i < IPv4len; i++ {
|
|
||||||
sa.Addr[i] = p[i]
|
|
||||||
}
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
p = p.To16();
|
|
||||||
if p == nil || port < 0 || port > 0xFFFF {
|
|
||||||
return nil, os.EINVAL
|
|
||||||
}
|
|
||||||
sa := new(syscall.SockaddrInet6);
|
|
||||||
sa.Len = syscall.SizeofSockaddrInet6;
|
|
||||||
sa.Family = syscall.AF_INET6;
|
|
||||||
sa.Port[0] = byte(port>>8);
|
|
||||||
sa.Port[1] = byte(port);
|
|
||||||
for i := 0; i < IPv6len; i++ {
|
|
||||||
sa.Addr[i] = p[i]
|
|
||||||
}
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sockaddrToIP(sa1 *syscall.Sockaddr) (p IP, port int, err os.Error) {
|
|
||||||
switch sa1.Family {
|
|
||||||
case syscall.AF_INET:
|
|
||||||
sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1));
|
|
||||||
a := IP(&sa.Addr).To16();
|
|
||||||
if a == nil {
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
|
|
||||||
case syscall.AF_INET6:
|
|
||||||
sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1));
|
|
||||||
a := IP(&sa.Addr).To16();
|
|
||||||
if a == nil {
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return nil, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
|
|
||||||
default:
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return nil, 0, nil // not reached
|
|
||||||
}
|
|
||||||
|
|
||||||
func listenBacklog() int64 {
|
|
||||||
return syscall.SOMAXCONN
|
|
||||||
}
|
|
||||||
|
|
||||||
func unixToSockaddr(name string) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
sa := new(syscall.SockaddrUnix);
|
|
||||||
n := len(name);
|
|
||||||
if n >= len(sa.Path) || n == 0 {
|
|
||||||
return nil, os.EINVAL;
|
|
||||||
}
|
|
||||||
sa.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL
|
|
||||||
sa.Family = syscall.AF_UNIX;
|
|
||||||
for i := 0; i < len(name); i++ {
|
|
||||||
sa.Path[i] = name[i];
|
|
||||||
}
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
func sockaddrToUnix(sa1 *syscall.Sockaddr) (string, os.Error) {
|
|
||||||
if sa1.Family != syscall.AF_UNIX || sa1.Len < 3 || sa1.Len > syscall.SizeofSockaddrUnix {
|
|
||||||
return "", os.EINVAL;
|
|
||||||
}
|
|
||||||
sa := (*syscall.SockaddrUnix)(unsafe.Pointer(sa1));
|
|
||||||
n := int(sa.Len) - 3; // subtract leading Family, Len, terminating NUL
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
if sa.Path[i] == 0 {
|
|
||||||
// found early NUL; assume Len is overestimating
|
|
||||||
n = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(sa.Path[0:n]), nil;
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net";
|
|
||||||
"os";
|
|
||||||
"syscall";
|
|
||||||
"unsafe";
|
|
||||||
)
|
|
||||||
|
|
||||||
func v4ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
p = p.To4();
|
|
||||||
if p == nil || port < 0 || port > 0xFFFF {
|
|
||||||
return nil, os.EINVAL
|
|
||||||
}
|
|
||||||
sa := new(syscall.SockaddrInet4);
|
|
||||||
sa.Family = syscall.AF_INET;
|
|
||||||
sa.Port[0] = byte(port>>8);
|
|
||||||
sa.Port[1] = byte(port);
|
|
||||||
for i := 0; i < IPv4len; i++ {
|
|
||||||
sa.Addr[i] = p[i]
|
|
||||||
}
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
p = p.To16();
|
|
||||||
if p == nil || port < 0 || port > 0xFFFF {
|
|
||||||
return nil, os.EINVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPv4 callers use 0.0.0.0 to mean "announce on any available address".
|
|
||||||
// In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0",
|
|
||||||
// which it refuses to do. Rewrite to the IPv6 all zeros.
|
|
||||||
if p4 := p.To4(); p4 != nil && p4[0] == 0 && p4[1] == 0 && p4[2] == 0 && p4[3] == 0 {
|
|
||||||
p = IPzero;
|
|
||||||
}
|
|
||||||
|
|
||||||
sa := new(syscall.SockaddrInet6);
|
|
||||||
sa.Family = syscall.AF_INET6;
|
|
||||||
sa.Port[0] = byte(port>>8);
|
|
||||||
sa.Port[1] = byte(port);
|
|
||||||
for i := 0; i < IPv6len; i++ {
|
|
||||||
sa.Addr[i] = p[i]
|
|
||||||
}
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sockaddrToIP(sa1 *syscall.Sockaddr) (p IP, port int, err os.Error) {
|
|
||||||
switch sa1.Family {
|
|
||||||
case syscall.AF_INET:
|
|
||||||
sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1));
|
|
||||||
a := IP(&sa.Addr).To16();
|
|
||||||
if a == nil {
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
|
|
||||||
case syscall.AF_INET6:
|
|
||||||
sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1));
|
|
||||||
a := IP(&sa.Addr).To16();
|
|
||||||
if a == nil {
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
|
|
||||||
default:
|
|
||||||
return nil, 0, os.EINVAL
|
|
||||||
}
|
|
||||||
return nil, 0, nil // not reached
|
|
||||||
}
|
|
||||||
|
|
||||||
func listenBacklog() int64 {
|
|
||||||
// TODO: Read the limit from /proc/sys/net/core/somaxconn,
|
|
||||||
// to take advantage of kernels that have raised the limit.
|
|
||||||
return syscall.SOMAXCONN
|
|
||||||
}
|
|
||||||
|
|
||||||
func unixToSockaddr(name string) (sa1 *syscall.Sockaddr, err os.Error) {
|
|
||||||
sa := new(syscall.SockaddrUnix);
|
|
||||||
n := len(name);
|
|
||||||
if n >= len(sa.Path) || n == 0 {
|
|
||||||
return nil, os.EINVAL;
|
|
||||||
}
|
|
||||||
sa.Family = syscall.AF_UNIX;
|
|
||||||
for i := 0; i < len(name); i++ {
|
|
||||||
sa.Path[i] = name[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case: @ in first position indicates
|
|
||||||
// an abstract socket, which has no file system
|
|
||||||
// representation and starts with a NUL byte
|
|
||||||
// when talking to the kernel about it.
|
|
||||||
if sa.Path[0] == '@' {
|
|
||||||
sa.Path[0] = 0;
|
|
||||||
}
|
|
||||||
sa.Length = 1 + int64(n) + 1; // family, name, \0
|
|
||||||
|
|
||||||
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
func sockaddrToUnix(sa1 *syscall.Sockaddr) (string, os.Error) {
|
|
||||||
if sa1.Family != syscall.AF_UNIX {
|
|
||||||
return "", os.EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sa := (*syscall.SockaddrUnix)(unsafe.Pointer(sa1));
|
|
||||||
|
|
||||||
// @ special case (see comment in unixToSockaddr).
|
|
||||||
if sa.Path[0] == 0 {
|
|
||||||
// Not friendly to overwrite in place but
|
|
||||||
// okay in an internal function.
|
|
||||||
// The caller doesn't care if we do.
|
|
||||||
sa.Path[0] = '@';
|
|
||||||
}
|
|
||||||
|
|
||||||
// count length of path
|
|
||||||
n := 0;
|
|
||||||
for n < len(sa.Path) && sa.Path[n] != 0 {
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return string(sa.Path[0:n]), nil;
|
|
||||||
}
|
|
|
@ -30,7 +30,7 @@ func testTimeout(t *testing.T, network, addr string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTmeoutUDP(t *testing.T) {
|
func TestTimeoutUDP(t *testing.T) {
|
||||||
testTimeout(t, "udp", "127.0.0.1:53");
|
testTimeout(t, "udp", "127.0.0.1:53");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# license that can be found in the LICENSE file.
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
# DO NOT EDIT. Automatically generated by gobuild.
|
# DO NOT EDIT. Automatically generated by gobuild.
|
||||||
# gobuild -m dir_${GOARCH}_${GOOS}.go env.go error.go file.go path.go proc_${GOOS}.go stat_${GOARCH}_${GOOS}.go time.go types.go exec.go user.go getwd.go >Makefile
|
# gobuild -m dir_${GOARCH}_${GOOS}.go env.go error.go file.go path.go stat_${GOARCH}_${GOOS}.go time.go types.go exec.go proc.go getwd.go >Makefile
|
||||||
|
|
||||||
D=
|
D=
|
||||||
|
|
||||||
|
@ -41,16 +41,15 @@ coverage: packages
|
||||||
|
|
||||||
O1=\
|
O1=\
|
||||||
error.$O\
|
error.$O\
|
||||||
proc_$(GOOS).$O\
|
|
||||||
types.$O\
|
types.$O\
|
||||||
|
|
||||||
O2=\
|
O2=\
|
||||||
env.$O\
|
proc.$O\
|
||||||
stat_$(GOARCH)_$(GOOS).$O\
|
stat_$(GOARCH)_$(GOOS).$O\
|
||||||
time.$O\
|
time.$O\
|
||||||
user.$O\
|
|
||||||
|
|
||||||
O3=\
|
O3=\
|
||||||
|
env.$O\
|
||||||
file.$O\
|
file.$O\
|
||||||
|
|
||||||
O4=\
|
O4=\
|
||||||
|
@ -64,15 +63,15 @@ phases: a1 a2 a3 a4
|
||||||
_obj$D/os.a: phases
|
_obj$D/os.a: phases
|
||||||
|
|
||||||
a1: $(O1)
|
a1: $(O1)
|
||||||
$(AR) grc _obj$D/os.a error.$O proc_$(GOOS).$O types.$O
|
$(AR) grc _obj$D/os.a error.$O types.$O
|
||||||
rm -f $(O1)
|
rm -f $(O1)
|
||||||
|
|
||||||
a2: $(O2)
|
a2: $(O2)
|
||||||
$(AR) grc _obj$D/os.a env.$O stat_$(GOARCH)_$(GOOS).$O time.$O user.$O
|
$(AR) grc _obj$D/os.a proc.$O stat_$(GOARCH)_$(GOOS).$O time.$O
|
||||||
rm -f $(O2)
|
rm -f $(O2)
|
||||||
|
|
||||||
a3: $(O3)
|
a3: $(O3)
|
||||||
$(AR) grc _obj$D/os.a file.$O
|
$(AR) grc _obj$D/os.a env.$O file.$O
|
||||||
rm -f $(O3)
|
rm -f $(O3)
|
||||||
|
|
||||||
a4: $(O4)
|
a4: $(O4)
|
||||||
|
|
|
@ -32,25 +32,31 @@ func readdirnames(file *File, count int) (names []string, err Error) {
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int64;
|
var errno int;
|
||||||
// Final argument is (basep *int64) and the syscall doesn't take nil.
|
d.bufp = 0;
|
||||||
d.nbuf, errno = syscall.Getdirentries(file.fd, &d.buf[0], int64(len(d.buf)), new(int64));
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
if d.nbuf < 0 {
|
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr));
|
||||||
|
if errno != 0 {
|
||||||
|
d.nbuf = 0;
|
||||||
return names, ErrnoToError(errno)
|
return names, ErrnoToError(errno)
|
||||||
}
|
}
|
||||||
if d.nbuf == 0 {
|
if d.nbuf == 0 {
|
||||||
break // EOF
|
break // EOF
|
||||||
}
|
}
|
||||||
d.bufp = 0;
|
|
||||||
}
|
}
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
||||||
d.bufp += int64(dirent.Reclen);
|
if dirent.Reclen == 0 {
|
||||||
|
d.bufp = d.nbuf;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
d.bufp += int(dirent.Reclen);
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var name = string(dirent.Name[0:dirent.Namlen]);
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
||||||
|
var name = string(bytes[0:dirent.Namlen]);
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,8 @@ func readdirnames(file *File, count int) (names []string, err Error) {
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int64;
|
var errno int;
|
||||||
dbuf := (*syscall.Dirent)(unsafe.Pointer(&d.buf[0]));
|
d.nbuf, errno = syscall.Getdents(file.fd, d.buf);
|
||||||
d.nbuf, errno = syscall.Getdents(file.fd, dbuf, int64(len(d.buf)));
|
|
||||||
if d.nbuf < 0 {
|
if d.nbuf < 0 {
|
||||||
return names, ErrnoToError(errno)
|
return names, ErrnoToError(errno)
|
||||||
}
|
}
|
||||||
|
@ -55,11 +54,12 @@ func readdirnames(file *File, count int) (names []string, err Error) {
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
||||||
d.bufp += int64(dirent.Reclen);
|
d.bufp += int(dirent.Reclen);
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var name = string(dirent.Name[0:clen(&dirent.Name)]);
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
||||||
|
var name = string(bytes[0:clen(bytes)]);
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,12 @@ func NewError(s string) Error {
|
||||||
// wrappers to convert the error number into an Error.
|
// wrappers to convert the error number into an Error.
|
||||||
type Errno int64
|
type Errno int64
|
||||||
func (e Errno) String() string {
|
func (e Errno) String() string {
|
||||||
return syscall.Errstr(int64(e))
|
return syscall.Errstr(int(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrnoToError converts errno to an Error (underneath, an Errno).
|
// ErrnoToError converts errno to an Error (underneath, an Errno).
|
||||||
// It returns nil for the "no error" errno.
|
// It returns nil for the "no error" errno.
|
||||||
func ErrnoToError(errno int64) Error {
|
func ErrnoToError(errno int) Error {
|
||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ func ErrnoToError(errno int64) Error {
|
||||||
|
|
||||||
// Commonly known Unix errors.
|
// Commonly known Unix errors.
|
||||||
var (
|
var (
|
||||||
ENONE Error = Errno(syscall.ENONE);
|
|
||||||
EPERM Error = Errno(syscall.EPERM);
|
EPERM Error = Errno(syscall.EPERM);
|
||||||
ENOENT Error = Errno(syscall.ENOENT);
|
ENOENT Error = Errno(syscall.ENOENT);
|
||||||
ESRCH Error = Errno(syscall.ESRCH);
|
ESRCH Error = Errno(syscall.ESRCH);
|
||||||
|
|
|
@ -20,7 +20,7 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File
|
||||||
(pid int, err Error)
|
(pid int, err Error)
|
||||||
{
|
{
|
||||||
// Create array of integer (system) fds.
|
// Create array of integer (system) fds.
|
||||||
intfd := make([]int64, len(fd));
|
intfd := make([]int, len(fd));
|
||||||
for i, f := range(fd) {
|
for i, f := range(fd) {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
intfd[i] = -1;
|
intfd[i] = -1;
|
||||||
|
@ -64,20 +64,20 @@ const (
|
||||||
WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited.
|
WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited.
|
||||||
WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported.
|
WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported.
|
||||||
WUNTRACED = WSTOPPED;
|
WUNTRACED = WSTOPPED;
|
||||||
WRUSAGE = 1<<60; // Record resource usage.
|
WRUSAGE = 1<<30; // Record resource usage.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wait waits for process pid to exit or stop, and then returns a
|
// Wait waits for process pid to exit or stop, and then returns a
|
||||||
// Waitmsg describing its status and an Error, if any. The options
|
// Waitmsg describing its status and an Error, if any. The options
|
||||||
// (WNOHANG etc.) affect the behavior of the Wait call.
|
// (WNOHANG etc.) affect the behavior of the Wait call.
|
||||||
func Wait(pid int, options uint64) (w *Waitmsg, err Error) {
|
func Wait(pid int, options int) (w *Waitmsg, err Error) {
|
||||||
var status syscall.WaitStatus;
|
var status syscall.WaitStatus;
|
||||||
var rusage *syscall.Rusage;
|
var rusage *syscall.Rusage;
|
||||||
if options & WRUSAGE != 0 {
|
if options & WRUSAGE != 0 {
|
||||||
rusage = new(syscall.Rusage);
|
rusage = new(syscall.Rusage);
|
||||||
options ^= WRUSAGE;
|
options ^= WRUSAGE;
|
||||||
}
|
}
|
||||||
pid1, e := syscall.Wait4(int64(pid), &status, int64(options), rusage);
|
pid1, e := syscall.Wait4(pid, &status, options, rusage);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, ErrnoToError(e);
|
return nil, ErrnoToError(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +14,20 @@ import (
|
||||||
// Auxiliary information if the File describes a directory
|
// Auxiliary information if the File describes a directory
|
||||||
type dirInfo struct {
|
type dirInfo struct {
|
||||||
buf []byte; // buffer for directory I/O
|
buf []byte; // buffer for directory I/O
|
||||||
nbuf int64; // length of buf; return value from Getdirentries
|
nbuf int; // length of buf; return value from Getdirentries
|
||||||
bufp int64; // location of next record in buf.
|
bufp int; // location of next record in buf.
|
||||||
}
|
}
|
||||||
|
|
||||||
// File represents an open file descriptor.
|
// File represents an open file descriptor.
|
||||||
type File struct {
|
type File struct {
|
||||||
fd int64;
|
fd int;
|
||||||
name string;
|
name string;
|
||||||
dirinfo *dirInfo; // nil unless directory being read
|
dirinfo *dirInfo; // nil unless directory being read
|
||||||
nepipe int; // number of consecutive EPIPE in Write
|
nepipe int; // number of consecutive EPIPE in Write
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fd returns the integer Unix file descriptor referencing the open file.
|
// Fd returns the integer Unix file descriptor referencing the open file.
|
||||||
func (file *File) Fd() int64 {
|
func (file *File) Fd() int {
|
||||||
return file.fd
|
return file.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func (file *File) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFile returns a new File with the given file descriptor and name.
|
// NewFile returns a new File with the given file descriptor and name.
|
||||||
func NewFile(file int64, name string) *File {
|
func NewFile(file int, name string) *File {
|
||||||
if file < 0 {
|
if file < 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ const (
|
||||||
// if applicable. If successful, methods on the returned File can be used for I/O.
|
// if applicable. If successful, methods on the returned File can be used for I/O.
|
||||||
// It returns the File and an Error, if any.
|
// It returns the File and an Error, if any.
|
||||||
func Open(name string, flag int, perm int) (file *File, err Error) {
|
func Open(name string, flag int, perm int) (file *File, err Error) {
|
||||||
r, e := syscall.Open(name, int64(flag | syscall.O_CLOEXEC), int64(perm));
|
r, e := syscall.Open(name, flag | syscall.O_CLOEXEC, perm);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, ErrnoToError(e);
|
return nil, ErrnoToError(e);
|
||||||
}
|
}
|
||||||
|
@ -92,9 +92,9 @@ func (file *File) Close() Error {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
r, e := syscall.Close(file.fd);
|
err := ErrnoToError(syscall.Close(file.fd));
|
||||||
file.fd = -1; // so it can't be closed again
|
file.fd = -1; // so it can't be closed again
|
||||||
return ErrnoToError(e)
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads up to len(b) bytes from the File.
|
// Read reads up to len(b) bytes from the File.
|
||||||
|
@ -105,14 +105,11 @@ func (file *File) Read(b []byte) (ret int, err Error) {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
var r, e int64;
|
n, e := syscall.Read(file.fd, b);
|
||||||
if len(b) > 0 { // because we access b[0]
|
if n < 0 {
|
||||||
r, e = syscall.Read(file.fd, &b[0], int64(len(b)));
|
n = 0;
|
||||||
if r < 0 {
|
|
||||||
r = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return int(r), ErrnoToError(e)
|
return n, ErrnoToError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the File.
|
// Write writes len(b) bytes to the File.
|
||||||
|
@ -122,12 +119,9 @@ func (file *File) Write(b []byte) (ret int, err Error) {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
var r, e int64;
|
n, e := syscall.Write(file.fd, b);
|
||||||
if len(b) > 0 { // because we access b[0]
|
if n < 0 {
|
||||||
r, e = syscall.Write(file.fd, &b[0], int64(len(b)));
|
n = 0
|
||||||
if r < 0 {
|
|
||||||
r = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if e == syscall.EPIPE {
|
if e == syscall.EPIPE {
|
||||||
file.nepipe++;
|
file.nepipe++;
|
||||||
|
@ -137,7 +131,7 @@ func (file *File) Write(b []byte) (ret int, err Error) {
|
||||||
} else {
|
} else {
|
||||||
file.nepipe = 0;
|
file.nepipe = 0;
|
||||||
}
|
}
|
||||||
return int(r), ErrnoToError(e)
|
return n, ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek sets the offset for the next Read or Write on file to offset, interpreted
|
// Seek sets the offset for the next Read or Write on file to offset, interpreted
|
||||||
|
@ -145,7 +139,7 @@ func (file *File) Write(b []byte) (ret int, err Error) {
|
||||||
// relative to the current offset, and 2 means relative to the end.
|
// relative to the current offset, and 2 means relative to the end.
|
||||||
// It returns the new offset and an Error, if any.
|
// It returns the new offset and an Error, if any.
|
||||||
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
|
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
|
||||||
r, e := syscall.Seek(file.fd, offset, int64(whence));
|
r, e := syscall.Seek(file.fd, offset, whence);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return -1, ErrnoToError(e)
|
return -1, ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
@ -161,7 +155,9 @@ func (file *File) WriteString(s string) (ret int, err Error) {
|
||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
r, e := syscall.Write(file.fd, syscall.StringBytePtr(s), int64(len(s)));
|
b := syscall.StringByteSlice(s);
|
||||||
|
b = b[0:len(b)-1];
|
||||||
|
r, e := syscall.Write(file.fd, b);
|
||||||
if r < 0 {
|
if r < 0 {
|
||||||
r = 0
|
r = 0
|
||||||
}
|
}
|
||||||
|
@ -171,11 +167,11 @@ func (file *File) WriteString(s string) (ret int, err Error) {
|
||||||
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
||||||
// It returns the files and an Error, if any.
|
// It returns the files and an Error, if any.
|
||||||
func Pipe() (r *File, w *File, err Error) {
|
func Pipe() (r *File, w *File, err Error) {
|
||||||
var p [2]int64;
|
var p [2]int;
|
||||||
|
|
||||||
// See ../syscall/exec.go for description of lock.
|
// See ../syscall/exec.go for description of lock.
|
||||||
syscall.ForkLock.RLock();
|
syscall.ForkLock.RLock();
|
||||||
ret, e := syscall.Pipe(&p);
|
e := syscall.Pipe(&p);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
syscall.ForkLock.RUnlock();
|
syscall.ForkLock.RUnlock();
|
||||||
return nil, nil, ErrnoToError(e)
|
return nil, nil, ErrnoToError(e)
|
||||||
|
@ -190,8 +186,7 @@ func Pipe() (r *File, w *File, err Error) {
|
||||||
// Mkdir creates a new directory with the specified name and permission bits.
|
// Mkdir creates a new directory with the specified name and permission bits.
|
||||||
// It returns an error, if any.
|
// It returns an error, if any.
|
||||||
func Mkdir(name string, perm int) Error {
|
func Mkdir(name string, perm int) Error {
|
||||||
r, e := syscall.Mkdir(name, int64(perm));
|
return ErrnoToError(syscall.Mkdir(name, perm));
|
||||||
return ErrnoToError(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a Dir structure describing the named file and an error, if any.
|
// Stat returns a Dir structure describing the named file and an error, if any.
|
||||||
|
@ -201,13 +196,13 @@ func Mkdir(name string, perm int) Error {
|
||||||
// the link itself and has dir.FollowedSymlink set to false.
|
// the link itself and has dir.FollowedSymlink set to false.
|
||||||
func Stat(name string) (dir *Dir, err Error) {
|
func Stat(name string) (dir *Dir, err Error) {
|
||||||
var lstat, stat syscall.Stat_t;
|
var lstat, stat syscall.Stat_t;
|
||||||
r, e := syscall.Lstat(name, &lstat);
|
e := syscall.Lstat(name, &lstat);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, ErrnoToError(e);
|
return nil, ErrnoToError(e);
|
||||||
}
|
}
|
||||||
statp := &lstat;
|
statp := &lstat;
|
||||||
if lstat.Mode & syscall.S_IFMT == syscall.S_IFLNK {
|
if lstat.Mode & syscall.S_IFMT == syscall.S_IFLNK {
|
||||||
r, e := syscall.Stat(name, &stat);
|
e := syscall.Stat(name, &stat);
|
||||||
if e == 0 {
|
if e == 0 {
|
||||||
statp = &stat;
|
statp = &stat;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +214,7 @@ func Stat(name string) (dir *Dir, err Error) {
|
||||||
// It returns the Dir and an error, if any.
|
// It returns the Dir and an error, if any.
|
||||||
func (file *File) Stat() (dir *Dir, err Error) {
|
func (file *File) Stat() (dir *Dir, err Error) {
|
||||||
var stat syscall.Stat_t;
|
var stat syscall.Stat_t;
|
||||||
r, e := syscall.Fstat(file.fd, &stat);
|
e := syscall.Fstat(file.fd, &stat);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, ErrnoToError(e)
|
return nil, ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
@ -231,7 +226,7 @@ func (file *File) Stat() (dir *Dir, err Error) {
|
||||||
// symbolic link. Lstat makes no attempt to follow the link.
|
// symbolic link. Lstat makes no attempt to follow the link.
|
||||||
func Lstat(name string) (dir *Dir, err Error) {
|
func Lstat(name string) (dir *Dir, err Error) {
|
||||||
var stat syscall.Stat_t;
|
var stat syscall.Stat_t;
|
||||||
r, e := syscall.Lstat(name, &stat);
|
e := syscall.Lstat(name, &stat);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, ErrnoToError(e)
|
return nil, ErrnoToError(e)
|
||||||
}
|
}
|
||||||
|
@ -280,15 +275,13 @@ func (file *File) Readdir(count int) (dirs []Dir, err Error) {
|
||||||
|
|
||||||
// Chdir changes the current working directory to the named directory.
|
// Chdir changes the current working directory to the named directory.
|
||||||
func Chdir(dir string) Error {
|
func Chdir(dir string) Error {
|
||||||
r, e := syscall.Chdir(dir);
|
return ErrnoToError(syscall.Chdir(dir));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chdir changes the current working directory to the file,
|
// Chdir changes the current working directory to the file,
|
||||||
// which must be a directory.
|
// which must be a directory.
|
||||||
func (f *File) Chdir() Error {
|
func (f *File) Chdir() Error {
|
||||||
r, e := syscall.Fchdir(f.fd);
|
return ErrnoToError(syscall.Fchdir(f.fd));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the named file or directory.
|
// Remove removes the named file or directory.
|
||||||
|
@ -297,11 +290,11 @@ func Remove(name string) Error {
|
||||||
// whether name is a file or directory.
|
// whether name is a file or directory.
|
||||||
// Try both: it is cheaper on average than
|
// Try both: it is cheaper on average than
|
||||||
// doing a Stat plus the right one.
|
// doing a Stat plus the right one.
|
||||||
r, e := syscall.Unlink(name);
|
e := syscall.Unlink(name);
|
||||||
if e == 0 {
|
if e == 0 {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
r1, e1 := syscall.Rmdir(name);
|
e1 := syscall.Rmdir(name);
|
||||||
if e1 == 0 {
|
if e1 == 0 {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -323,26 +316,25 @@ func Remove(name string) Error {
|
||||||
|
|
||||||
// Link creates a hard link.
|
// Link creates a hard link.
|
||||||
func Link(oldname, newname string) Error {
|
func Link(oldname, newname string) Error {
|
||||||
r, e := syscall.Link(oldname, newname);
|
return ErrnoToError(syscall.Link(oldname, newname));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Symlink creates a symbolic link.
|
// Symlink creates a symbolic link.
|
||||||
func Symlink(oldname, newname string) Error {
|
func Symlink(oldname, newname string) Error {
|
||||||
r, e := syscall.Symlink(oldname, newname);
|
return ErrnoToError(syscall.Symlink(oldname, newname));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readlink reads the contents of a symbolic link: the destination of
|
// Readlink reads the contents of a symbolic link: the destination of
|
||||||
// the link. It returns the contents and an Error, if any.
|
// the link. It returns the contents and an Error, if any.
|
||||||
func Readlink(name string) (string, Error) {
|
func Readlink(name string) (string, Error) {
|
||||||
for len := int64(128); ; len *= 2 {
|
for len := 128; ; len *= 2 {
|
||||||
b := make([]byte, len);
|
b := make([]byte, len);
|
||||||
r, e := syscall.Readlink(name, &b[0], len);
|
n, e := syscall.Readlink(name, b);
|
||||||
if r == -1 {
|
if e != 0 {
|
||||||
return "", ErrnoToError(e);
|
return "", ErrnoToError(e);
|
||||||
} else if r < len {
|
}
|
||||||
return string(b[0:r]), nil;
|
if n < len {
|
||||||
|
return string(b[0:n]), nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Silence 6g.
|
// Silence 6g.
|
||||||
|
@ -352,47 +344,40 @@ func Readlink(name string) (string, Error) {
|
||||||
// Chmod changes the mode of the named file to mode.
|
// Chmod changes the mode of the named file to mode.
|
||||||
// If the file is a symbolic link, it changes the uid and gid of the link's target.
|
// If the file is a symbolic link, it changes the uid and gid of the link's target.
|
||||||
func Chmod(name string, mode int) Error {
|
func Chmod(name string, mode int) Error {
|
||||||
r, e := syscall.Chmod(name, int64(mode));
|
return ErrnoToError(syscall.Chmod(name, mode));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chmod changes the mode of the file to mode.
|
// Chmod changes the mode of the file to mode.
|
||||||
func (f *File) Chmod(mode int) Error {
|
func (f *File) Chmod(mode int) Error {
|
||||||
r, e := syscall.Fchmod(f.fd, int64(mode));
|
return ErrnoToError(syscall.Fchmod(f.fd, mode));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown changes the numeric uid and gid of the named file.
|
// Chown changes the numeric uid and gid of the named file.
|
||||||
// If the file is a symbolic link, it changes the uid and gid of the link's target.
|
// If the file is a symbolic link, it changes the uid and gid of the link's target.
|
||||||
func Chown(name string, uid, gid int) Error {
|
func Chown(name string, uid, gid int) Error {
|
||||||
r, e := syscall.Chown(name, int64(uid), int64(gid));
|
return ErrnoToError(syscall.Chown(name, uid, gid));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lchown changes the numeric uid and gid of the named file.
|
// Lchown changes the numeric uid and gid of the named file.
|
||||||
// If the file is a symbolic link, it changes the uid and gid of the link itself.
|
// If the file is a symbolic link, it changes the uid and gid of the link itself.
|
||||||
func Lchown(name string, uid, gid int) Error {
|
func Lchown(name string, uid, gid int) Error {
|
||||||
r, e := syscall.Lchown(name, int64(uid), int64(gid));
|
return ErrnoToError(syscall.Lchown(name, uid, gid));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown changes the numeric uid and gid of the named file.
|
// Chown changes the numeric uid and gid of the named file.
|
||||||
func (f *File) Chown(uid, gid int) Error {
|
func (f *File) Chown(uid, gid int) Error {
|
||||||
r, e := syscall.Fchown(f.fd, int64(uid), int64(gid));
|
return ErrnoToError(syscall.Fchown(f.fd, uid, gid));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
// Truncate changes the size of the named file.
|
||||||
// If the file is a symbolic link, it changes the size of the link's target.
|
// If the file is a symbolic link, it changes the size of the link's target.
|
||||||
func Truncate(name string, size int64) Error {
|
func Truncate(name string, size int64) Error {
|
||||||
r, e := syscall.Truncate(name, size);
|
return ErrnoToError(syscall.Truncate(name, size));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the file.
|
// Truncate changes the size of the file.
|
||||||
// It does not change the I/O offset.
|
// It does not change the I/O offset.
|
||||||
func (f *File) Truncate(size int64) Error {
|
func (f *File) Truncate(size int64) Error {
|
||||||
r, e := syscall.Ftruncate(f.fd, size);
|
return ErrnoToError(syscall.Ftruncate(f.fd, size));
|
||||||
return ErrnoToError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
src/lib/os/proc.go
Normal file
50
src/lib/os/proc.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright 2009 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.
|
||||||
|
|
||||||
|
// Process etc.
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall";
|
||||||
|
"os";
|
||||||
|
"unsafe";
|
||||||
|
)
|
||||||
|
|
||||||
|
var Args []string; // provided by runtime
|
||||||
|
var Envs []string; // provided by runtime
|
||||||
|
|
||||||
|
|
||||||
|
// Getuid returns the numeric user id of the caller.
|
||||||
|
func Getuid() int {
|
||||||
|
return syscall.Getuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Geteuid returns the numeric effective user id of the caller.
|
||||||
|
func Geteuid() int {
|
||||||
|
return syscall.Geteuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getgid returns the numeric group id of the caller.
|
||||||
|
func Getgid() int {
|
||||||
|
return syscall.Getgid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getegid returns the numeric effective group id of the caller.
|
||||||
|
func Getegid() int {
|
||||||
|
return syscall.Getegid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
|
||||||
|
func Getgroups() ([]int, os.Error) {
|
||||||
|
gids, errno := syscall.Getgroups();
|
||||||
|
return gids, ErrnoToError(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit causes the current program to exit with the given status code.
|
||||||
|
// Conventionally, code zero indicates success, non-zero an error.
|
||||||
|
func Exit(code int) {
|
||||||
|
syscall.Exit(code);
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
package os
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os";
|
|
||||||
"syscall";
|
|
||||||
)
|
|
||||||
|
|
||||||
var Args []string; // provided by runtime
|
|
||||||
var Envs []string; // provided by runtime
|
|
||||||
|
|
||||||
// Exit causes the current program to exit with the given status code.
|
|
||||||
// Conventionally, code zero indicates success, non-zero an error.
|
|
||||||
func Exit(code int) {
|
|
||||||
syscall.Syscall(syscall.SYS_EXIT, int64(code), 0, 0)
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,12 +21,12 @@ func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Uid = stat.Uid;
|
dir.Uid = stat.Uid;
|
||||||
dir.Gid = stat.Gid;
|
dir.Gid = stat.Gid;
|
||||||
dir.Rdev = uint64(stat.Rdev);
|
dir.Rdev = uint64(stat.Rdev);
|
||||||
dir.Size = stat.Size;
|
dir.Size = uint64(stat.Size);
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize);
|
||||||
dir.Blocks = stat.Blocks;
|
dir.Blocks = uint64(stat.Blocks);
|
||||||
dir.Atime_ns = uint64(stat.Atime.Sec) * 1e9 + stat.Atime.Nsec;
|
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec));
|
||||||
dir.Mtime_ns = uint64(stat.Mtime.Sec) * 1e9 + stat.Mtime.Nsec;
|
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec));
|
||||||
dir.Ctime_ns = uint64(stat.Ctime.Sec) * 1e9 + stat.Atime.Nsec;
|
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec));
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:len(name)];
|
name = name[i+1:len(name)];
|
||||||
|
|
|
@ -24,9 +24,9 @@ func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Size = uint64(stat.Size);
|
dir.Size = uint64(stat.Size);
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize);
|
||||||
dir.Blocks = uint64(stat.Blocks);
|
dir.Blocks = uint64(stat.Blocks);
|
||||||
dir.Atime_ns = uint64(stat.Atime.Sec) * 1e9 + stat.Atime.Nsec;
|
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim));
|
||||||
dir.Mtime_ns = uint64(stat.Mtime.Sec) * 1e9 + stat.Mtime.Nsec;
|
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim));
|
||||||
dir.Ctime_ns = uint64(stat.Ctime.Sec) * 1e9 + stat.Atime.Nsec;
|
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim));
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:len(name)];
|
name = name[i+1:len(name)];
|
||||||
|
|
|
@ -15,11 +15,10 @@ import (
|
||||||
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of
|
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of
|
||||||
// time is the Unix epoch.
|
// time is the Unix epoch.
|
||||||
func Time() (sec int64, nsec int64, err Error) {
|
func Time() (sec int64, nsec int64, err Error) {
|
||||||
var errno int64;
|
var tv syscall.Timeval;
|
||||||
sec, nsec, errno = syscall.Gettimeofday();
|
if errno := syscall.Gettimeofday(&tv); errno != 0 {
|
||||||
if errno != 0 {
|
|
||||||
return 0, 0, ErrnoToError(errno)
|
return 0, 0, ErrnoToError(errno)
|
||||||
}
|
}
|
||||||
return sec, nsec, nil
|
return int64(tv.Sec), int64(tv.Usec)*1000, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
// User ids etc.
|
|
||||||
|
|
||||||
package os
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall";
|
|
||||||
"os";
|
|
||||||
"unsafe";
|
|
||||||
)
|
|
||||||
|
|
||||||
// Getuid returns the numeric user id of the caller.
|
|
||||||
func Getuid() int {
|
|
||||||
u, r2, e := syscall.Syscall(syscall.SYS_GETUID, 0, 0, 0);
|
|
||||||
return int(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Geteuid returns the numeric effective user id of the caller.
|
|
||||||
func Geteuid() int {
|
|
||||||
u, r2, e := syscall.Syscall(syscall.SYS_GETEUID, 0, 0, 0);
|
|
||||||
return int(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getgid returns the numeric group id of the caller.
|
|
||||||
func Getgid() int {
|
|
||||||
g, r2, e := syscall.Syscall(syscall.SYS_GETGID, 0, 0, 0);
|
|
||||||
return int(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getegid returns the numeric effective group id of the caller.
|
|
||||||
func Getegid() int {
|
|
||||||
g, r2, e := syscall.Syscall(syscall.SYS_GETEGID, 0, 0, 0);
|
|
||||||
return int(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
|
|
||||||
func Getgroups() ([]int, os.Error) {
|
|
||||||
// first call asks how many there are.
|
|
||||||
r1, r2, err := syscall.Syscall(syscall.SYS_GETGROUPS, 0, 0, 0);
|
|
||||||
if err != 0 {
|
|
||||||
return nil, ErrnoToError(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check group count.
|
|
||||||
// On Linux, max is 1<<16; on BSD, OS X, max is 16.
|
|
||||||
if r1 < 0 || r1 > 1<<20 {
|
|
||||||
return nil, EINVAL;
|
|
||||||
}
|
|
||||||
a := make([]int, r1);
|
|
||||||
if r1 > 0 {
|
|
||||||
tmp := make([]uint32, r1);
|
|
||||||
r1, r2, err = syscall.Syscall(syscall.SYS_GETGROUPS, r1, int64(uintptr(unsafe.Pointer(&tmp[0]))), 0);
|
|
||||||
if err != 0 {
|
|
||||||
return nil, ErrnoToError(err);
|
|
||||||
}
|
|
||||||
for i := 0; i < len(a); i++ {
|
|
||||||
a[i] = int(tmp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return a[0:r1], nil;
|
|
||||||
}
|
|
|
@ -13,10 +13,5 @@ import (
|
||||||
// Sleep pauses the current goroutine for ns nanoseconds.
|
// Sleep pauses the current goroutine for ns nanoseconds.
|
||||||
// It returns os.EINTR if interrupted.
|
// It returns os.EINTR if interrupted.
|
||||||
func Sleep(ns int64) os.Error {
|
func Sleep(ns int64) os.Error {
|
||||||
var tv syscall.Timeval;
|
return os.ErrnoToError(syscall.Sleep(ns));
|
||||||
syscall.Nstotimeval(ns, &tv);
|
|
||||||
r1, r2, err := syscall.Syscall6(syscall.SYS_SELECT, 0, 0, 0, 0,
|
|
||||||
int64(uintptr(unsafe.Pointer(&tv))), 0);
|
|
||||||
return os.ErrnoToError(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,7 @@ package main
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
func getpid() int64 {
|
|
||||||
r1, r2, err := syscall.Syscall(syscall.SYS_GETPID, 0, 0, 0);
|
|
||||||
return r1;
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
syscall.Syscall(syscall.SYS_KILL, getpid(), syscall.SIGCHLD, 0);
|
syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGCHLD, 0);
|
||||||
println("survived SIGCHLD");
|
println("survived SIGCHLD");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue