From d10126a622d2e9010b5250d1bcec6acb51b4ce24 Mon Sep 17 00:00:00 2001 From: Christopher Nielsen Date: Thu, 15 Dec 2011 12:19:19 -0500 Subject: [PATCH] os: OS-dependent bits to support NetBSD. R=golang-dev, jsing CC=golang-dev https://golang.org/cl/5482068 --- include/libc.h | 2 +- src/libmach/netbsd.c | 46 +++++++++++++ src/pkg/net/fd_netbsd.go | 115 ++++++++++++++++++++++++++++++++ src/pkg/net/interface_netbsd.go | 14 ++++ src/pkg/net/tcpsock_posix.go | 2 +- src/pkg/os/stat_netbsd.go | 56 ++++++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 src/libmach/netbsd.c create mode 100644 src/pkg/net/fd_netbsd.go create mode 100644 src/pkg/net/interface_netbsd.go create mode 100644 src/pkg/os/stat_netbsd.go diff --git a/include/libc.h b/include/libc.h index 0b50eb3c5fd..b464cb4c63e 100644 --- a/include/libc.h +++ b/include/libc.h @@ -187,7 +187,7 @@ extern void sysfatal(char*, ...); #define DMWRITE 0x2 /* mode bit for write permission */ #define DMEXEC 0x1 /* mode bit for execute permission */ -#ifdef RFMEM /* FreeBSD, OpenBSD */ +#ifdef RFMEM /* FreeBSD, OpenBSD, NetBSD */ #undef RFFDG #undef RFNOTEG #undef RFPROC diff --git a/src/libmach/netbsd.c b/src/libmach/netbsd.c new file mode 100644 index 00000000000..03e08d9e8d4 --- /dev/null +++ b/src/libmach/netbsd.c @@ -0,0 +1,46 @@ +// This is stubbed out for the moment. Will revisit when the time comes. +#include +#include +#include +#include + +int +ctlproc(int pid, char *msg) +{ + sysfatal("ctlproc unimplemented in NetBSD"); + return -1; +} + +char* +proctextfile(int pid) +{ + sysfatal("proctextfile unimplemented in NetBSD"); + return nil; +} + +char* +procstatus(int pid) +{ + sysfatal("procstatus unimplemented in NetBSD"); + return nil; +} + +Map* +attachproc(int pid, Fhdr *fp) +{ + sysfatal("attachproc unimplemented in NetBSD"); + return nil; +} + +void +detachproc(Map *m) +{ + sysfatal("detachproc unimplemented in NetBSD"); +} + +int +procthreadpids(int pid, int *p, int np) +{ + sysfatal("procthreadpids unimplemented in NetBSD"); + return -1; +} diff --git a/src/pkg/net/fd_netbsd.go b/src/pkg/net/fd_netbsd.go new file mode 100644 index 00000000000..e52ac356b9f --- /dev/null +++ b/src/pkg/net/fd_netbsd.go @@ -0,0 +1,115 @@ +// 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. + +// Waiting for FDs via kqueue/kevent. + +package net + +import ( + "os" + "syscall" +) + +type pollster struct { + kq int + eventbuf [10]syscall.Kevent_t + events []syscall.Kevent_t + + // An event buffer for AddFD/DelFD. + // Must hold pollServer lock. + kbuf [1]syscall.Kevent_t +} + +func newpollster() (p *pollster, err error) { + p = new(pollster) + if p.kq, err = syscall.Kqueue(); err != nil { + return nil, os.NewSyscallError("kqueue", err) + } + p.events = p.eventbuf[0:0] + return p, nil +} + +func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { + // pollServer is locked. + + var kmode int + if mode == 'r' { + kmode = syscall.EVFILT_READ + } else { + kmode = syscall.EVFILT_WRITE + } + ev := &p.kbuf[0] + // EV_ADD - add event to kqueue list + // EV_ONESHOT - delete the event the first time it triggers + flags := syscall.EV_ADD + if !repeat { + flags |= syscall.EV_ONESHOT + } + syscall.SetKevent(ev, fd, kmode, flags) + + n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) + if e != nil { + return false, os.NewSyscallError("kevent", e) + } + if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode { + return false, os.NewSyscallError("kqueue phase error", e) + } + if ev.Data != 0 { + return false, syscall.Errno(int(ev.Data)) + } + return false, nil +} + +func (p *pollster) DelFD(fd int, mode int) { + // pollServer is locked. + + var kmode int + if mode == 'r' { + kmode = syscall.EVFILT_READ + } else { + kmode = syscall.EVFILT_WRITE + } + ev := &p.kbuf[0] + // EV_DELETE - delete event from kqueue list + syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE) + syscall.Kevent(p.kq, p.kbuf[:], nil, nil) +} + +func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) { + var t *syscall.Timespec + for len(p.events) == 0 { + if nsec > 0 { + if t == nil { + t = new(syscall.Timespec) + } + *t = syscall.NsecToTimespec(nsec) + } + + s.Unlock() + nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t) + s.Lock() + + if e != nil { + if e == syscall.EINTR { + continue + } + return -1, 0, os.NewSyscallError("kevent", e) + } + if nn == 0 { + return -1, 0, nil + } + p.events = p.eventbuf[0:nn] + } + ev := &p.events[0] + p.events = p.events[1:] + fd = int(ev.Ident) + if ev.Filter == syscall.EVFILT_READ { + mode = 'r' + } else { + mode = 'w' + } + return fd, mode, nil +} + +func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) } diff --git a/src/pkg/net/interface_netbsd.go b/src/pkg/net/interface_netbsd.go new file mode 100644 index 00000000000..4150e9ad5d1 --- /dev/null +++ b/src/pkg/net/interface_netbsd.go @@ -0,0 +1,14 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Network interface identification for NetBSD + +package net + +// If the ifindex is zero, interfaceMulticastAddrTable returns +// addresses for all network interfaces. Otherwise it returns +// addresses for a specific interface. +func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { + return nil, nil +} diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go index 44890ba66bb..a7c09c73ed5 100644 --- a/src/pkg/net/tcpsock_posix.go +++ b/src/pkg/net/tcpsock_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin freebsd linux openbsd windows +// +build darwin freebsd linux netbsd openbsd windows // TCP sockets diff --git a/src/pkg/os/stat_netbsd.go b/src/pkg/os/stat_netbsd.go new file mode 100644 index 00000000000..66189a6b9ba --- /dev/null +++ b/src/pkg/os/stat_netbsd.go @@ -0,0 +1,56 @@ +// 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 ( + "syscall" + "time" +) + +func sameFile(fs1, fs2 *FileStat) bool { + sys1 := fs1.Sys.(*syscall.Stat_t) + sys2 := fs2.Sys.(*syscall.Stat_t) + return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino +} + +func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { + fs := &FileStat{ + name: basename(name), + size: int64(st.Size), + modTime: timespecToTime(st.Mtim), + Sys: st, + } + fs.mode = FileMode(st.Mode & 0777) + switch st.Mode & syscall.S_IFMT { + case syscall.S_IFBLK, syscall.S_IFCHR: + fs.mode |= ModeDevice + case syscall.S_IFDIR: + fs.mode |= ModeDir + case syscall.S_IFIFO: + fs.mode |= ModeNamedPipe + case syscall.S_IFLNK: + fs.mode |= ModeSymlink + case syscall.S_IFREG: + // nothing to do + case syscall.S_IFSOCK: + fs.mode |= ModeSocket + } + if st.Mode&syscall.S_ISGID != 0 { + fs.mode |= ModeSetgid + } + if st.Mode&syscall.S_ISUID != 0 { + fs.mode |= ModeSetuid + } + return fs +} + +func timespecToTime(ts syscall.Timespec) time.Time { + return time.Unix(int64(ts.Sec), int64(ts.Nsec)) +} + +// For testing. +func atime(fi FileInfo) time.Time { + return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atim) +}