summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libc.h2
-rw-r--r--src/libmach/netbsd.c46
-rw-r--r--src/pkg/net/fd_netbsd.go115
-rw-r--r--src/pkg/net/interface_netbsd.go14
-rw-r--r--src/pkg/net/tcpsock_posix.go2
-rw-r--r--src/pkg/os/stat_netbsd.go56
6 files changed, 233 insertions, 2 deletions
diff --git a/include/libc.h b/include/libc.h
index 0b50eb3c5..b464cb4c6 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 000000000..03e08d9e8
--- /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 <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+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 000000000..e52ac356b
--- /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 000000000..4150e9ad5
--- /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 44890ba66..a7c09c73e 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 000000000..66189a6b9
--- /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)
+}