diff --git a/src/lib/clean.bash b/src/lib/clean.bash
index c6e388e6be314c623655b7f189fbf62fcd0f10b9..0f63401c856eb947801fab947107988b23d3f708 100755
--- a/src/lib/clean.bash
+++ b/src/lib/clean.bash
@@ -6,6 +6,10 @@
 
 rm -f $GOROOT/pkg/*
 
-cd math
-bash clean.bash
-cd ..
+for i in os math
+do
+	cd $i
+	make nuke
+	cd ..
+done
+
diff --git a/src/lib/make.bash b/src/lib/make.bash
index a9be5938b8787b2c222855ddbbd5ee0838b3e392..b657a1f01bb77581c1e2fde6dec163047f6ffcf8 100755
--- a/src/lib/make.bash
+++ b/src/lib/make.bash
@@ -14,9 +14,11 @@ do
 	6g -o $GOROOT/pkg/$base.6 $i
 done
 
-echo; echo; echo %%%% making lib/math %%%%; echo
-
-cd math
-bash make.bash
-cd ..
+for i in os math
+do
+	echo; echo; echo %%%% making lib/$i %%%%; echo
+	cd $i
+	make install
+	cd ..
+done
 
diff --git a/src/lib/os/Makefile b/src/lib/os/Makefile
index a9b32713a6a0ca016642cb9459064aeb550905bb..737d876c0f44efbe80c097abba990359e63af8f3 100644
--- a/src/lib/os/Makefile
+++ b/src/lib/os/Makefile
@@ -8,15 +8,20 @@ GC=$(O)g
 PKG=$(GOROOT)/pkg/os.a
 
 O1=\
-	os.$O
+	os_base.$O os_error.$O
+O2=\
+	os_file.$O
 
 install: $(PKG)
 
-$(PKG): a1
+$(PKG): a1 a2
 
 a1: 	$(O1)
 	$(O)ar grc $(PKG) $(O1)
 
+a2: 	$(O2)
+	$(O)ar grc $(PKG) $(O2)
+
 nuke:
 	rm -f *.$(O) *.a $(PKG)
 
diff --git a/src/lib/os/os_base.go b/src/lib/os/os_base.go
new file mode 100644
index 0000000000000000000000000000000000000000..54c2ae26b01a1a1bc9ea18ecec655c2a96d2bbaa
--- /dev/null
+++ b/src/lib/os/os_base.go
@@ -0,0 +1,18 @@
+// 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
+
+// Support types and routines for OS library
+
+export func StringToBytes(b *[]byte, s string) bool {
+	if len(s) >= len(b) {
+		return false
+	}
+	for i := 0; i < len(s); i++ {
+		b[i] = s[i]
+	}
+	b[len(s)] = '\000';	// not necessary - memory is zeroed - but be explicit
+	return true
+}
diff --git a/src/lib/os/os_error.go b/src/lib/os/os_error.go
new file mode 100644
index 0000000000000000000000000000000000000000..2da63da5afb6df43a8f1800a0f4e73a99935a52e
--- /dev/null
+++ b/src/lib/os/os_error.go
@@ -0,0 +1,76 @@
+// 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 "syscall"
+
+// Errors are singleton structures. Use the Print()/String() methods to get their contents --
+// they handle the nil (no error) case.
+export type Error struct {
+	s string
+}
+
+var ErrorTab = new(map[int64] *Error);
+
+export func ErrnoToError(errno int64) *Error {
+	if errno == 0 {
+		return nil
+	}
+	err, ok := ErrorTab[errno]
+	if ok {
+		return err
+	}
+	e := new(Error);
+	e.s = syscall.errstr(errno);
+	ErrorTab[errno] = e;
+	return e;
+}
+export var (
+	ENONE = ErrnoToError(syscall.ENONE);
+	EPERM = ErrnoToError(syscall.EPERM);
+	ENOENT = ErrnoToError(syscall.ENOENT);
+	ESRCH = ErrnoToError(syscall.ESRCH);
+	EINTR = ErrnoToError(syscall.EINTR);
+	EIO = ErrnoToError(syscall.EIO);
+	ENXIO = ErrnoToError(syscall.ENXIO);
+	E2BIG = ErrnoToError(syscall.E2BIG);
+	ENOEXEC = ErrnoToError(syscall.ENOEXEC);
+	EBADF = ErrnoToError(syscall.EBADF);
+	ECHILD = ErrnoToError(syscall.ECHILD);
+	EDEADLK = ErrnoToError(syscall.EDEADLK);
+	ENOMEM = ErrnoToError(syscall.ENOMEM);
+	EACCES = ErrnoToError(syscall.EACCES);
+	EFAULT = ErrnoToError(syscall.EFAULT);
+	ENOTBLK = ErrnoToError(syscall.ENOTBLK);
+	EBUSY = ErrnoToError(syscall.EBUSY);
+	EEXIST = ErrnoToError(syscall.EEXIST);
+	EXDEV = ErrnoToError(syscall.EXDEV);
+	ENODEV = ErrnoToError(syscall.ENODEV);
+	ENOTDIR = ErrnoToError(syscall.ENOTDIR);
+	EISDIR = ErrnoToError(syscall.EISDIR);
+	EINVAL = ErrnoToError(syscall.EINVAL);
+	ENFILE = ErrnoToError(syscall.ENFILE);
+	EMFILE = ErrnoToError(syscall.EMFILE);
+	ENOTTY = ErrnoToError(syscall.ENOTTY);
+	ETXTBSY = ErrnoToError(syscall.ETXTBSY);
+	EFBIG = ErrnoToError(syscall.EFBIG);
+	ENOSPC = ErrnoToError(syscall.ENOSPC);
+	ESPIPE = ErrnoToError(syscall.ESPIPE);
+	EROFS = ErrnoToError(syscall.EROFS);
+	EMLINK = ErrnoToError(syscall.EMLINK);
+	EPIPE = ErrnoToError(syscall.EPIPE);
+	EDOM = ErrnoToError(syscall.EDOM);
+	ERANGE = ErrnoToError(syscall.ERANGE);
+	EAGAIN = ErrnoToError(syscall.EAGAIN);
+)
+const NoError = "No Error"
+
+func (e *Error) String() string {
+	if e == nil {
+		return NoError
+	} else {
+		return e.s
+	}
+}
diff --git a/src/lib/os/os_file.go b/src/lib/os/os_file.go
new file mode 100644
index 0000000000000000000000000000000000000000..7513f800e9c72ac8182fe92f7a1c17f5e933dffd
--- /dev/null
+++ b/src/lib/os/os_file.go
@@ -0,0 +1,74 @@
+// 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 "syscall"
+import os "os"
+
+// FDs are wrappers for file descriptors
+export type FD struct {
+	fd int64
+}
+
+export func NewFD(fd int64) *FD {
+	if fd < 0 {
+		return nil
+	}
+	n := new(FD);
+	n.fd = fd;
+	return n;
+}
+
+export var (
+	Stdin = NewFD(0);
+	Stdout = NewFD(1);
+	Stderr = NewFD(2);
+)
+
+export func Open(name string, mode int64, flags int64) (fd *FD, err *Error) {
+	var buf [512]byte;
+	if !StringToBytes(&buf, name) {
+		return nil, EINVAL
+	}
+	r, e := syscall.open(&buf[0], mode, flags);
+	return NewFD(r), ErrnoToError(e)
+}
+
+func (fd *FD) Close() *Error {
+	if fd == nil {
+		return EINVAL
+	}
+	r, e := syscall.close(fd.fd);
+	fd.fd = -1;  // so it can't be closed again
+	return ErrnoToError(e)
+}
+
+func (fd *FD) Read(b *[]byte) (ret int64, err *Error) {
+	if fd == nil {
+		return -1, EINVAL
+	}
+	r, e := syscall.read(fd.fd, &b[0], int64(len(b)));
+	return r, ErrnoToError(e)
+}
+
+func (fd *FD) Write(b *[]byte) (ret int64, err *Error) {
+	if fd == nil {
+		return -1, EINVAL
+	}
+	r, e := syscall.write(fd.fd, &b[0], int64(len(b)));
+	return r, ErrnoToError(e)
+}
+
+func (fd *FD) WriteString(s string) (ret int64, err *Error) {
+	if fd == nil {
+		return -1, EINVAL
+	}
+	b := new([]byte, len(s)+1);
+	if !StringToBytes(b, s) {
+		return -1, EINVAL
+	}
+	r, e := syscall.write(fd.fd, &b[0], int64(len(s)));
+	return r, ErrnoToError(e)
+}
diff --git a/src/make.bash b/src/make.bash
index f2543b553d21c08b016dc85aac36df0c356c572c..5eeb370a1b554c23d29f55c58d39def4a1ac7cb4 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -12,7 +12,7 @@ do
 	cd ..
 done
 
-for i in cmd runtime lib
+for i in cmd runtime
 do
 	cd $i
 	bash make.bash
@@ -27,3 +27,10 @@ do
 	make install
 	cd ..
 done
+
+for i in lib
+do
+	cd $i
+	bash make.bash
+	cd ..
+done