From 9e0fec9c9c6b3d621dd64c943b050920cb8407e7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 1 Jun 2009 22:14:39 -0700 Subject: [PATCH] update Go tree to use new syscall package. R=r DELTA=713 (109 added, 386 deleted, 218 changed) OCL=29707 CL=29722 --- doc/progs/file.go | 14 +-- doc/progs/run | 2 +- src/lib/exec/exec.go | 2 +- src/lib/net/Makefile | 5 +- src/lib/net/fd.go | 62 +++++-------- src/lib/net/fd_darwin.go | 26 +++--- src/lib/net/fd_linux.go | 39 ++++---- src/lib/net/net.go | 152 ++++++++++++++++++-------------- src/lib/net/net_darwin.go | 100 --------------------- src/lib/net/net_linux.go | 124 -------------------------- src/lib/net/timeout_test.go | 2 +- src/lib/os/Makefile | 13 ++- src/lib/os/dir_amd64_darwin.go | 20 +++-- src/lib/os/dir_amd64_linux.go | 10 +-- src/lib/os/error.go | 5 +- src/lib/os/exec.go | 8 +- src/lib/os/file.go | 107 ++++++++++------------ src/lib/os/proc.go | 50 +++++++++++ src/lib/os/proc_darwin.go | 20 ----- src/lib/os/stat_amd64_darwin.go | 10 +-- src/lib/os/stat_amd64_linux.go | 6 +- src/lib/os/time.go | 7 +- src/lib/os/user.go | 64 -------------- src/lib/time/sleep.go | 7 +- test/sigchld.go | 7 +- 25 files changed, 292 insertions(+), 570 deletions(-) delete mode 100644 src/lib/net/net_darwin.go delete mode 100644 src/lib/net/net_linux.go create mode 100644 src/lib/os/proc.go delete mode 100644 src/lib/os/proc_darwin.go delete mode 100644 src/lib/os/user.go diff --git a/doc/progs/file.go b/doc/progs/file.go index 0f9a4a9f8b..ff796c5653 100644 --- a/doc/progs/file.go +++ b/doc/progs/file.go @@ -10,11 +10,11 @@ import ( ) type File struct { - fd int64; // file descriptor number + fd int; // file descriptor number name string; // file name at Open time } -func newFile(fd int64, name string) *File { +func newFile(fd int, name string) *File { if fd < 0 { return nil } @@ -27,7 +27,7 @@ var ( 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); return newFile(r, name), os.ErrnoToError(e) } @@ -36,16 +36,16 @@ func (file *File) Close() os.Error { if file == nil { return os.EINVAL } - r, e := syscall.Close(file.fd); + e := syscall.Close(file.fd); 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) { if file == nil { 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) } @@ -53,7 +53,7 @@ func (file *File) Write(b []byte) (ret int, err os.Error) { if file == nil { 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) } diff --git a/doc/progs/run b/doc/progs/run index c02a632d05..7b9ebfa80c 100755 --- a/doc/progs/run +++ b/doc/progs/run @@ -46,7 +46,7 @@ function testitpipe { 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 sum "" "6" diff --git a/src/lib/exec/exec.go b/src/lib/exec/exec.go index 29f25df651..c2b7bdd59b 100644 --- a/src/lib/exec/exec.go +++ b/src/lib/exec/exec.go @@ -139,7 +139,7 @@ Error: // Setting options to 0 waits for p to exit; // other options cause Wait to return for other // 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 { return nil, os.EINVAL; } diff --git a/src/lib/net/Makefile b/src/lib/net/Makefile index efd6b3ef11..0bbc4a0db3 100644 --- a/src/lib/net/Makefile +++ b/src/lib/net/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. # 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= @@ -51,7 +51,6 @@ O2=\ O3=\ dnsconfig.$O\ fd.$O\ - net_$(GOOS).$O\ O4=\ net.$O\ @@ -72,7 +71,7 @@ a2: $(O2) rm -f $(O2) 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) a4: $(O4) diff --git a/src/lib/net/fd.go b/src/lib/net/fd.go index ddfed67853..9404ed0bd4 100644 --- a/src/lib/net/fd.go +++ b/src/lib/net/fd.go @@ -17,7 +17,7 @@ import ( // Network file descriptor. type netFD struct { // immutable until Close - fd int64; + fd int; file *os.File; cr chan *netFD; cw chan *netFD; @@ -37,28 +37,6 @@ type netFD struct { 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 // 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 @@ -91,7 +69,7 @@ func setBlock(fd int64) { type pollServer struct { cr, cw chan *netFD; // buffered >= 1 pr, pw *os.File; - pending map[int64] *netFD; + pending map[int] *netFD; poll *pollster; // low-level OS hooks 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 { 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: s.pr.Close(); s.pw.Close(); - return nil, err + return nil, err; } - if err = setNonblock(s.pw.Fd()); err != nil { - goto Error + if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 { + goto Errno; } if s.poll, err = newpollster(); err != nil { - goto Error + goto Error; } if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { s.poll.Close(); goto Error } - s.pending = make(map[int64] *netFD); + s.pending = make(map[int] *netFD); go s.Run(); 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; if mode == 'w' { key++; @@ -318,12 +299,12 @@ func _StartServer() { 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 { once.Do(_StartServer); } - if err = setNonblock(fd); err != nil { - return nil, err + if e := syscall.SetNonblock(fd, true); e != 0 { + return nil, os.ErrnoToError(e); } f = new(netFD); f.fd = fd; @@ -347,7 +328,7 @@ func (fd *netFD) Close() os.Error { // we can handle the extra OS processes. // Otherwise we'll need to use the pollserver // for Close too. Sigh. - setBlock(fd.file.Fd()); + syscall.SetNonblock(fd.file.Fd(), false); e := fd.file.Close(); fd.file = nil; @@ -406,9 +387,9 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) { 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 { 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 // because we have put fd.fd into non-blocking mode. syscall.ForkLock.RLock(); - var s, e int64; + var s, e int; + var sa syscall.Sockaddr; for { - s, e = syscall.Accept(fd.fd, sa); + s, sa, e = syscall.Accept(fd.fd); if e != syscall.EAGAIN { break; } @@ -434,7 +416,7 @@ func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err os.Error) { syscall.CloseOnExec(s); syscall.ForkLock.RUnlock(); - raddr, err1 := sockaddrToHostPort(sa); + raddr, err1 := sockaddrToString(sa); if err1 != nil { raddr = "invalid-address"; } diff --git a/src/lib/net/fd_darwin.go b/src/lib/net/fd_darwin.go index cfc873fc91..3d1025d516 100644 --- a/src/lib/net/fd_darwin.go +++ b/src/lib/net/fd_darwin.go @@ -15,14 +15,14 @@ import ( var kqueuePhaseError = &Error{"kqueue phase error"} type pollster struct { - kq int64; + kq int; eventbuf [10]syscall.Kevent_t; events []syscall.Kevent_t; } func newpollster() (p *pollster, err os.Error) { p = new(pollster); - var e int64; + var e int; if p.kq, e = syscall.Kqueue(); e != 0 { return nil, os.ErrnoToError(e) } @@ -30,7 +30,7 @@ func newpollster() (p *pollster, err os.Error) { 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; if mode == 'r' { 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; ev := &events[0]; - ev.Ident = fd; + ev.Ident = uint64(fd); ev.Filter = kmode; // 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 { 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 } if ev.Data != 0 { - return os.ErrnoToError(ev.Data) + return os.ErrnoToError(int(ev.Data)) } return nil } -func (p *pollster) DelFD(fd int64, mode int) { +func (p *pollster) DelFD(fd int, mode int) { var kmode int16; if mode == 'r' { kmode = syscall.EVFILT_READ @@ -73,7 +73,7 @@ func (p *pollster) DelFD(fd int64, mode int) { } var events [1]syscall.Kevent_t; ev := &events[0]; - ev.Ident = fd; + ev.Ident = uint64(fd); ev.Filter = kmode; // 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); } -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; for len(p.events) == 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.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); if e != 0 { @@ -107,7 +108,7 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) { } ev := &p.events[0]; p.events = p.events[1:len(p.events)]; - fd = ev.Ident; + fd = int(ev.Ident); if ev.Filter == syscall.EVFILT_READ { mode = 'r' } else { @@ -117,6 +118,5 @@ func (p *pollster) WaitFD(nsec int64) (fd int64, mode int, err os.Error) { } func (p *pollster) Close() os.Error { - r, e := syscall.Close(p.kq); - return os.ErrnoToError(e) + return os.ErrnoToError(syscall.Close(p.kq)) } diff --git a/src/lib/net/fd_linux.go b/src/lib/net/fd_linux.go index 78a1670e1f..bd822589ee 100644 --- a/src/lib/net/fd_linux.go +++ b/src/lib/net/fd_linux.go @@ -18,27 +18,27 @@ const ( ) type pollster struct { - epfd int64; + epfd int; // Events we're already waiting for - events map[int64] uint32; + events map[int] uint32; } func newpollster() (p *pollster, err os.Error) { p = new(pollster); - var e int64; + var e int; // The arg to epoll_create is a hint to the kernel // about the number of FDs we will care about. // 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) } - p.events = make(map[int64] uint32); + p.events = make(map[int] uint32); 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 already bool; ev.Fd = int32(fd); @@ -52,20 +52,20 @@ func (p *pollster) AddFD(fd int64, mode int, repeat bool) os.Error { ev.Events |= writeFlags; } - var op int64; + var op int; if already { op = syscall.EPOLL_CTL_MOD; } else { 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) } p.events[fd] = ev.Events; return nil } -func (p *pollster) StopWaiting(fd int64, bits uint) { +func (p *pollster) StopWaiting(fd int, bits uint) { events, already := p.events[fd]; if !already { print("Epoll unexpected fd=", fd, "\n"); @@ -86,19 +86,19 @@ func (p *pollster) StopWaiting(fd int64, bits uint) { var ev syscall.EpollEvent; ev.Fd = int32(fd); 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"); } p.events[fd] = events; } 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"); } p.events[fd] = 0, false; } } -func (p *pollster) DelFD(fd int64, mode int) { +func (p *pollster) DelFD(fd int, mode int) { if mode == 'r' { p.StopWaiting(fd, readFlags); } 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. var evarray [1]syscall.EpollEvent; ev := &evarray[0]; - var msec int64 = -1; + var msec int = -1; 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 { - n, e = syscall.Epoll_wait(p.epfd, &evarray, msec); + n, e = syscall.EpollWait(p.epfd, &evarray, msec); } if e != 0 { 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 { return -1, 0, nil; } - fd = int64(ev.Fd); + fd = int(ev.Fd); if ev.Events & writeFlags != 0 { 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 { - r, e := syscall.Close(p.epfd); - return os.ErrnoToError(e); + return os.ErrnoToError(syscall.Close(p.epfd)); } diff --git a/src/lib/net/net.go b/src/lib/net/net.go index d1000bfead..5c442e6a45 100644 --- a/src/lib/net/net.go +++ b/src/lib/net/net.go @@ -113,6 +113,12 @@ func kernelSupportsIPv6() bool { 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) @@ -212,20 +218,48 @@ func hostPortToIP(net, hostport, mode string) (ip IP, iport int, err os.Error) { return addr, p, nil } -// Convert socket address into "host:port". -func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err os.Error) { - switch sa.Family { - case syscall.AF_INET, syscall.AF_INET6: - addr, port, e := sockaddrToIP(sa); - if e != nil { - return "", e - } - host := addr.String(); - return joinHostPort(host, strconv.Itoa(port)), nil; - default: - return "", UnknownSocketFamily +func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error) { + switch a := sa.(type) { + case *syscall.SockaddrInet4: + return joinHostPort(IP(&a.Addr).String(), strconv.Itoa(a.Port)), nil; + case *syscall.SockaddrInet6: + return joinHostPort(IP(&a.Addr).String(), strconv.Itoa(a.Port)), nil; + case *syscall.SockaddrUnix: + return a.Name, nil; } - 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. @@ -237,7 +271,7 @@ func boolint(b bool) int { } // 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. syscall.ForkLock.RLock(); 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(); // 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; if la != nil { - r, e = syscall.Bind(s, la); + e = syscall.Bind(s, la); if e != 0 { syscall.Close(s); 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 { - r, e = syscall.Connect(s, ra); + e = syscall.Connect(s, ra); if e != 0 { syscall.Close(s); return nil, os.ErrnoToError(e) @@ -291,7 +325,7 @@ func (c *connBase) File() *os.File { return c.fd.file; } -func (c *connBase) sysFD() int64 { +func (c *connBase) sysFD() int { if c == nil || c.fd == nil { return -1; } @@ -335,20 +369,21 @@ func (c *connBase) Close() os.Error { } -func setsockopt_int(fd, level, opt int64, value int) os.Error { - return os.ErrnoToError(syscall.Setsockopt_int(fd, level, opt, value)); +func setsockoptInt(fd, level, opt int, value int) os.Error { + return os.ErrnoToError(syscall.SetsockoptInt(fd, level, opt, value)); } -func setsockopt_tv(fd, level, opt int64, nsec int64) os.Error { - return os.ErrnoToError(syscall.Setsockopt_tv(fd, level, opt, nsec)); +func setsockoptNsec(fd, level, opt int, nsec int64) os.Error { + var tv = syscall.NsecToTimeval(nsec); + return os.ErrnoToError(syscall.SetsockoptTimeval(fd, level, opt, &tv)); } 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 { - 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 { @@ -369,7 +404,7 @@ func (c *connBase) SetTimeout(nsec int64) 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 { @@ -378,22 +413,30 @@ func (c *connBase) BindToDevice(dev string) 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 { - 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 { - 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); } // 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). var lip, rip IP; 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 int64; + var family int; if vers == 4 { - cvt = v4ToSockaddr; family = syscall.AF_INET } else { - cvt = v6ToSockaddr; family = syscall.AF_INET6 } - var la, ra *syscall.Sockaddr; + var la, ra syscall.Sockaddr; if lip != nil { - la, lerr = cvt(lip, lport); + la, lerr = ipToSockaddr(family, lip, lport); if lerr != nil { return nil, lerr } } if rip != nil { - ra, rerr = cvt(rip, rport); + ra, rerr = ipToSockaddr(family, rip, rport); if rerr != nil { return nil, rerr } @@ -471,7 +511,7 @@ func (c *ConnTCP) SetNoDelay(nodelay bool) os.Error { if c == nil { 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 { @@ -535,7 +575,7 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err os.Error) { // Unix domain sockets func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error) { - var proto int64; + var proto int; switch net { default: return nil, UnknownNetwork; @@ -545,7 +585,7 @@ func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error) proto = syscall.SOCK_DGRAM; } - var la, ra *syscall.Sockaddr; + var la, ra syscall.Sockaddr; switch mode { case "dial": if laddr != "" { @@ -554,19 +594,13 @@ func unixSocket(net, laddr, raddr string, mode string) (fd *netFD, err os.Error) if raddr == "" { return nil, MissingAddress; } - ra, err = unixToSockaddr(raddr); - if err != nil { - return nil, err; - } + ra = &syscall.SockaddrUnix{Name: raddr}; case "listen": if laddr == "" { return nil, MissingAddress; } - la, err = unixToSockaddr(laddr); - if err != nil { - return nil, err; - } + la = &syscall.SockaddrUnix{Name: laddr}; if raddr != "" { return nil, BadAddress; } @@ -636,7 +670,7 @@ func ListenUnix(net, laddr string) (l *ListenerUnix, err os.Error) { } fd = fd1; } - r, e1 := syscall.Listen(fd.fd, 8); // listenBacklog()); + e1 := syscall.Listen(fd.fd, 8); // listenBacklog()); if e1 != 0 { syscall.Close(fd.fd); 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 { return nil, "", os.EINVAL } - var sa syscall.Sockaddr; - fd, e := l.fd.Accept(&sa); + fd, e := l.fd.accept(); if e != nil { return nil, "", e } - raddr, err = sockaddrToUnix(&sa); - if err != nil { - fd.Close(); - return nil, "", err - } - return newConnUnix(fd, raddr), raddr, nil + return newConnUnix(fd, fd.raddr), raddr, nil } // 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 { return nil, e } - r, e1 := syscall.Listen(fd.fd, listenBacklog()); + e1 := syscall.Listen(fd.fd, listenBacklog()); if e1 != 0 { syscall.Close(fd.fd); 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 { return nil, "", os.EINVAL } - var sa syscall.Sockaddr; - fd, e := l.fd.Accept(&sa); + fd, e := l.fd.accept(); if e != nil { return nil, "", e } - raddr, err = sockaddrToHostPort(&sa); - if err != nil { - fd.Close(); - return nil, "", err - } - return newConnTCP(fd, raddr), raddr, nil + return newConnTCP(fd, fd.raddr), fd.raddr, nil } // Accept implements the Accept method in the Listener interface; diff --git a/src/lib/net/net_darwin.go b/src/lib/net/net_darwin.go deleted file mode 100644 index 50e19d6142..0000000000 --- a/src/lib/net/net_darwin.go +++ /dev/null @@ -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; -} diff --git a/src/lib/net/net_linux.go b/src/lib/net/net_linux.go deleted file mode 100644 index 4127867430..0000000000 --- a/src/lib/net/net_linux.go +++ /dev/null @@ -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; -} diff --git a/src/lib/net/timeout_test.go b/src/lib/net/timeout_test.go index 8ad4f54277..e08ce88ce7 100644 --- a/src/lib/net/timeout_test.go +++ b/src/lib/net/timeout_test.go @@ -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"); } diff --git a/src/lib/os/Makefile b/src/lib/os/Makefile index 50a06d92b5..5272e88ad4 100644 --- a/src/lib/os/Makefile +++ b/src/lib/os/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. # 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= @@ -41,16 +41,15 @@ coverage: packages O1=\ error.$O\ - proc_$(GOOS).$O\ types.$O\ O2=\ - env.$O\ + proc.$O\ stat_$(GOARCH)_$(GOOS).$O\ time.$O\ - user.$O\ O3=\ + env.$O\ file.$O\ O4=\ @@ -64,15 +63,15 @@ phases: a1 a2 a3 a4 _obj$D/os.a: phases 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) 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) a3: $(O3) - $(AR) grc _obj$D/os.a file.$O + $(AR) grc _obj$D/os.a env.$O file.$O rm -f $(O3) a4: $(O4) diff --git a/src/lib/os/dir_amd64_darwin.go b/src/lib/os/dir_amd64_darwin.go index 681a710d1b..2803ecee27 100644 --- a/src/lib/os/dir_amd64_darwin.go +++ b/src/lib/os/dir_amd64_darwin.go @@ -32,25 +32,31 @@ func readdirnames(file *File, count int) (names []string, err Error) { for count != 0 { // Refill the buffer if necessary if d.bufp >= d.nbuf { - var errno int64; - // Final argument is (basep *int64) and the syscall doesn't take nil. - d.nbuf, errno = syscall.Getdirentries(file.fd, &d.buf[0], int64(len(d.buf)), new(int64)); - if d.nbuf < 0 { + var errno int; + d.bufp = 0; + // Final argument is (basep *uintptr) and the syscall doesn't take nil. + d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); + if errno != 0 { + d.nbuf = 0; return names, ErrnoToError(errno) } if d.nbuf == 0 { break // EOF } - d.bufp = 0; } // Drain the buffer for count != 0 && d.bufp < d.nbuf { 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. 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 continue } diff --git a/src/lib/os/dir_amd64_linux.go b/src/lib/os/dir_amd64_linux.go index 67eae30ff3..05b3d4c65d 100644 --- a/src/lib/os/dir_amd64_linux.go +++ b/src/lib/os/dir_amd64_linux.go @@ -41,9 +41,8 @@ func readdirnames(file *File, count int) (names []string, err Error) { for count != 0 { // Refill the buffer if necessary if d.bufp >= d.nbuf { - var errno int64; - dbuf := (*syscall.Dirent)(unsafe.Pointer(&d.buf[0])); - d.nbuf, errno = syscall.Getdents(file.fd, dbuf, int64(len(d.buf))); + var errno int; + d.nbuf, errno = syscall.Getdents(file.fd, d.buf); if d.nbuf < 0 { return names, ErrnoToError(errno) } @@ -55,11 +54,12 @@ func readdirnames(file *File, count int) (names []string, err Error) { // Drain the buffer for count != 0 && d.bufp < d.nbuf { 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. 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 continue } diff --git a/src/lib/os/error.go b/src/lib/os/error.go index 7784656274..718499b212 100644 --- a/src/lib/os/error.go +++ b/src/lib/os/error.go @@ -27,12 +27,12 @@ func NewError(s string) Error { // wrappers to convert the error number into an Error. type Errno int64 func (e Errno) String() string { - return syscall.Errstr(int64(e)) + return syscall.Errstr(int(e)) } // ErrnoToError converts errno to an Error (underneath, an Errno). // It returns nil for the "no error" errno. -func ErrnoToError(errno int64) Error { +func ErrnoToError(errno int) Error { if errno == 0 { return nil } @@ -41,7 +41,6 @@ func ErrnoToError(errno int64) Error { // Commonly known Unix errors. var ( - ENONE Error = Errno(syscall.ENONE); EPERM Error = Errno(syscall.EPERM); ENOENT Error = Errno(syscall.ENOENT); ESRCH Error = Errno(syscall.ESRCH); diff --git a/src/lib/os/exec.go b/src/lib/os/exec.go index 9f0f01e0a8..d283c72670 100644 --- a/src/lib/os/exec.go +++ b/src/lib/os/exec.go @@ -20,7 +20,7 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File (pid int, err Error) { // Create array of integer (system) fds. - intfd := make([]int64, len(fd)); + intfd := make([]int, len(fd)); for i, f := range(fd) { if f == nil { intfd[i] = -1; @@ -64,20 +64,20 @@ const ( WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited. WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported. 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 // Waitmsg describing its status and an Error, if any. The options // (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 rusage *syscall.Rusage; if options & WRUSAGE != 0 { rusage = new(syscall.Rusage); options ^= WRUSAGE; } - pid1, e := syscall.Wait4(int64(pid), &status, int64(options), rusage); + pid1, e := syscall.Wait4(pid, &status, options, rusage); if e != 0 { return nil, ErrnoToError(e); } diff --git a/src/lib/os/file.go b/src/lib/os/file.go index 7aa6632c77..1562b1b0e4 100644 --- a/src/lib/os/file.go +++ b/src/lib/os/file.go @@ -14,20 +14,20 @@ import ( // Auxiliary information if the File describes a directory type dirInfo struct { buf []byte; // buffer for directory I/O - nbuf int64; // length of buf; return value from Getdirentries - bufp int64; // location of next record in buf. + nbuf int; // length of buf; return value from Getdirentries + bufp int; // location of next record in buf. } // File represents an open file descriptor. type File struct { - fd int64; + fd int; name string; dirinfo *dirInfo; // nil unless directory being read nepipe int; // number of consecutive EPIPE in Write } // Fd returns the integer Unix file descriptor referencing the open file. -func (file *File) Fd() int64 { +func (file *File) Fd() int { return file.fd } @@ -37,7 +37,7 @@ func (file *File) Name() string { } // 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 { return nil } @@ -72,7 +72,7 @@ const ( // if applicable. If successful, methods on the returned File can be used for I/O. // It returns the File and an Error, if any. 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 { return nil, ErrnoToError(e); } @@ -92,9 +92,9 @@ func (file *File) Close() Error { if file == nil { return EINVAL } - r, e := syscall.Close(file.fd); + err := ErrnoToError(syscall.Close(file.fd)); 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. @@ -105,14 +105,11 @@ func (file *File) Read(b []byte) (ret int, err Error) { if file == nil { return 0, EINVAL } - var r, e int64; - if len(b) > 0 { // because we access b[0] - r, e = syscall.Read(file.fd, &b[0], int64(len(b))); - if r < 0 { - r = 0 - } + n, e := syscall.Read(file.fd, b); + if n < 0 { + n = 0; } - return int(r), ErrnoToError(e) + return n, ErrnoToError(e); } // 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 { return 0, EINVAL } - var r, e int64; - if len(b) > 0 { // because we access b[0] - r, e = syscall.Write(file.fd, &b[0], int64(len(b))); - if r < 0 { - r = 0 - } + n, e := syscall.Write(file.fd, b); + if n < 0 { + n = 0 } if e == syscall.EPIPE { file.nepipe++; @@ -137,7 +131,7 @@ func (file *File) Write(b []byte) (ret int, err Error) { } else { 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 @@ -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. // It returns the new offset and an Error, if any. 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 { return -1, ErrnoToError(e) } @@ -161,7 +155,9 @@ func (file *File) WriteString(s string) (ret int, err Error) { if file == nil { 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 { 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. // It returns the files and an Error, if any. func Pipe() (r *File, w *File, err Error) { - var p [2]int64; + var p [2]int; // See ../syscall/exec.go for description of lock. syscall.ForkLock.RLock(); - ret, e := syscall.Pipe(&p); + e := syscall.Pipe(&p); if e != 0 { syscall.ForkLock.RUnlock(); 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. // It returns an error, if any. func Mkdir(name string, perm int) Error { - r, e := syscall.Mkdir(name, int64(perm)); - return ErrnoToError(e) + return ErrnoToError(syscall.Mkdir(name, perm)); } // 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. func Stat(name string) (dir *Dir, err Error) { var lstat, stat syscall.Stat_t; - r, e := syscall.Lstat(name, &lstat); + e := syscall.Lstat(name, &lstat); if e != 0 { return nil, ErrnoToError(e); } statp := &lstat; if lstat.Mode & syscall.S_IFMT == syscall.S_IFLNK { - r, e := syscall.Stat(name, &stat); + e := syscall.Stat(name, &stat); if e == 0 { statp = &stat; } @@ -219,7 +214,7 @@ func Stat(name string) (dir *Dir, err Error) { // It returns the Dir and an error, if any. func (file *File) Stat() (dir *Dir, err Error) { var stat syscall.Stat_t; - r, e := syscall.Fstat(file.fd, &stat); + e := syscall.Fstat(file.fd, &stat); if e != 0 { 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. func Lstat(name string) (dir *Dir, err Error) { var stat syscall.Stat_t; - r, e := syscall.Lstat(name, &stat); + e := syscall.Lstat(name, &stat); if e != 0 { 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. func Chdir(dir string) Error { - r, e := syscall.Chdir(dir); - return ErrnoToError(e); + return ErrnoToError(syscall.Chdir(dir)); } // Chdir changes the current working directory to the file, // which must be a directory. func (f *File) Chdir() Error { - r, e := syscall.Fchdir(f.fd); - return ErrnoToError(e); + return ErrnoToError(syscall.Fchdir(f.fd)); } // Remove removes the named file or directory. @@ -297,11 +290,11 @@ func Remove(name string) Error { // whether name is a file or directory. // Try both: it is cheaper on average than // doing a Stat plus the right one. - r, e := syscall.Unlink(name); + e := syscall.Unlink(name); if e == 0 { return nil; } - r1, e1 := syscall.Rmdir(name); + e1 := syscall.Rmdir(name); if e1 == 0 { return nil; } @@ -323,26 +316,25 @@ func Remove(name string) Error { // Link creates a hard link. func Link(oldname, newname string) Error { - r, e := syscall.Link(oldname, newname); - return ErrnoToError(e); + return ErrnoToError(syscall.Link(oldname, newname)); } // Symlink creates a symbolic link. func Symlink(oldname, newname string) Error { - r, e := syscall.Symlink(oldname, newname); - return ErrnoToError(e); + return ErrnoToError(syscall.Symlink(oldname, newname)); } // Readlink reads the contents of a symbolic link: the destination of // the link. It returns the contents and an Error, if any. func Readlink(name string) (string, Error) { - for len := int64(128); ; len *= 2 { + for len := 128; ; len *= 2 { b := make([]byte, len); - r, e := syscall.Readlink(name, &b[0], len); - if r == -1 { + n, e := syscall.Readlink(name, b); + if e != 0 { return "", ErrnoToError(e); - } else if r < len { - return string(b[0:r]), nil; + } + if n < len { + return string(b[0:n]), nil; } } // Silence 6g. @@ -352,47 +344,40 @@ func Readlink(name string) (string, Error) { // 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. func Chmod(name string, mode int) Error { - r, e := syscall.Chmod(name, int64(mode)); - return ErrnoToError(e); + return ErrnoToError(syscall.Chmod(name, mode)); } // Chmod changes the mode of the file to mode. func (f *File) Chmod(mode int) Error { - r, e := syscall.Fchmod(f.fd, int64(mode)); - return ErrnoToError(e); + return ErrnoToError(syscall.Fchmod(f.fd, mode)); } // 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. func Chown(name string, uid, gid int) Error { - r, e := syscall.Chown(name, int64(uid), int64(gid)); - return ErrnoToError(e); + return ErrnoToError(syscall.Chown(name, uid, gid)); } // 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. func Lchown(name string, uid, gid int) Error { - r, e := syscall.Lchown(name, int64(uid), int64(gid)); - return ErrnoToError(e); + return ErrnoToError(syscall.Lchown(name, uid, gid)); } // Chown changes the numeric uid and gid of the named file. func (f *File) Chown(uid, gid int) Error { - r, e := syscall.Fchown(f.fd, int64(uid), int64(gid)); - return ErrnoToError(e); + return ErrnoToError(syscall.Fchown(f.fd, uid, gid)); } // Truncate changes the size of the named file. // If the file is a symbolic link, it changes the size of the link's target. func Truncate(name string, size int64) Error { - r, e := syscall.Truncate(name, size); - return ErrnoToError(e); + return ErrnoToError(syscall.Truncate(name, size)); } // Truncate changes the size of the file. // It does not change the I/O offset. func (f *File) Truncate(size int64) Error { - r, e := syscall.Ftruncate(f.fd, size); - return ErrnoToError(e); + return ErrnoToError(syscall.Ftruncate(f.fd, size)); } diff --git a/src/lib/os/proc.go b/src/lib/os/proc.go new file mode 100644 index 0000000000..d2fd6493eb --- /dev/null +++ b/src/lib/os/proc.go @@ -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); +} + diff --git a/src/lib/os/proc_darwin.go b/src/lib/os/proc_darwin.go deleted file mode 100644 index bae977b1f7..0000000000 --- a/src/lib/os/proc_darwin.go +++ /dev/null @@ -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) -} - diff --git a/src/lib/os/stat_amd64_darwin.go b/src/lib/os/stat_amd64_darwin.go index e72d76f917..1771ca160b 100644 --- a/src/lib/os/stat_amd64_darwin.go +++ b/src/lib/os/stat_amd64_darwin.go @@ -21,12 +21,12 @@ func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { dir.Uid = stat.Uid; dir.Gid = stat.Gid; dir.Rdev = uint64(stat.Rdev); - dir.Size = stat.Size; + dir.Size = uint64(stat.Size); dir.Blksize = uint64(stat.Blksize); - dir.Blocks = stat.Blocks; - dir.Atime_ns = uint64(stat.Atime.Sec) * 1e9 + stat.Atime.Nsec; - dir.Mtime_ns = uint64(stat.Mtime.Sec) * 1e9 + stat.Mtime.Nsec; - dir.Ctime_ns = uint64(stat.Ctime.Sec) * 1e9 + stat.Atime.Nsec; + dir.Blocks = uint64(stat.Blocks); + dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); + dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); + dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); for i := len(name) - 1; i >= 0; i-- { if name[i] == '/' { name = name[i+1:len(name)]; diff --git a/src/lib/os/stat_amd64_linux.go b/src/lib/os/stat_amd64_linux.go index e1beb16667..9b30181784 100644 --- a/src/lib/os/stat_amd64_linux.go +++ b/src/lib/os/stat_amd64_linux.go @@ -24,9 +24,9 @@ func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { dir.Size = uint64(stat.Size); dir.Blksize = uint64(stat.Blksize); dir.Blocks = uint64(stat.Blocks); - dir.Atime_ns = uint64(stat.Atime.Sec) * 1e9 + stat.Atime.Nsec; - dir.Mtime_ns = uint64(stat.Mtime.Sec) * 1e9 + stat.Mtime.Nsec; - dir.Ctime_ns = uint64(stat.Ctime.Sec) * 1e9 + stat.Atime.Nsec; + dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); + dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); + dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); for i := len(name) - 1; i >= 0; i-- { if name[i] == '/' { name = name[i+1:len(name)]; diff --git a/src/lib/os/time.go b/src/lib/os/time.go index 7e268a0c7f..3eee243cc5 100644 --- a/src/lib/os/time.go +++ b/src/lib/os/time.go @@ -15,11 +15,10 @@ import ( // time is thus 1e9*sec+nsec, in nanoseconds. The zero of // time is the Unix epoch. func Time() (sec int64, nsec int64, err Error) { - var errno int64; - sec, nsec, errno = syscall.Gettimeofday(); - if errno != 0 { + var tv syscall.Timeval; + if errno := syscall.Gettimeofday(&tv); errno != 0 { return 0, 0, ErrnoToError(errno) } - return sec, nsec, nil + return int64(tv.Sec), int64(tv.Usec)*1000, err; } diff --git a/src/lib/os/user.go b/src/lib/os/user.go deleted file mode 100644 index 194aa50e44..0000000000 --- a/src/lib/os/user.go +++ /dev/null @@ -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; -} diff --git a/src/lib/time/sleep.go b/src/lib/time/sleep.go index f1f0d11ae1..3bb76cf475 100644 --- a/src/lib/time/sleep.go +++ b/src/lib/time/sleep.go @@ -13,10 +13,5 @@ import ( // Sleep pauses the current goroutine for ns nanoseconds. // It returns os.EINTR if interrupted. func Sleep(ns int64) os.Error { - var tv syscall.Timeval; - 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); + return os.ErrnoToError(syscall.Sleep(ns)); } - diff --git a/test/sigchld.go b/test/sigchld.go index 417b833c70..5b95314df6 100644 --- a/test/sigchld.go +++ b/test/sigchld.go @@ -8,12 +8,7 @@ package main import "syscall" -func getpid() int64 { - r1, r2, err := syscall.Syscall(syscall.SYS_GETPID, 0, 0, 0); - return r1; -} - 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"); }