Commit ccede3e8 authored by Rob Pike's avatar Rob Pike

make syscall use strings for file names

tweak os to adjust
move StringToBytes into syscall, at least for now

this program still works:

	package main

	import os "os"

	func main() {
		os.Stdout.WriteString("hello, world\n");
		a, b := os.NewFD(77).WriteString("no way");
		os.Stdout.WriteString(b.String() + "\n");
	}

R=rsc
DELTA=263  (59 added, 176 deleted, 28 changed)
OCL=15153
CL=15153
parent c80b06a5
...@@ -8,11 +8,11 @@ GC=$(O)g ...@@ -8,11 +8,11 @@ GC=$(O)g
PKG=$(GOROOT)/pkg/os.a PKG=$(GOROOT)/pkg/os.a
O1=\ O1=\
os_base.$O os_error.$O os_error.$O
O2=\ O2=\
os_file.$O os_file.$O
install: $(PKG) install: nuke $(PKG)
$(PKG): a1 a2 $(PKG): a1 a2
......
// 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"
// Support types and routines for OS library
// FDs are wrappers for file descriptors
export type FD struct {
fd int64
}
// 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
}
export func NewFD(fd int64) *FD {
if fd < 0 {
return nil
}
n := new(FD); // TODO(r): how about return &FD{fd} ?
n.fd = fd;
return n;
}
export var (
Stdin = NewFD(0);
Stdout = NewFD(1);
Stderr = NewFD(2);
)
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
}
var ErrorTab = new(map[int64] *Error);
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);
)
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)
}
const NoError = "No Error"
func (e *Error) String() string {
if e == nil {
return NoError
} else {
return e.s
}
}
func (e *Error) Print() {
Stderr.WriteString(e.String())
}
// 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
}
...@@ -6,8 +6,8 @@ package os ...@@ -6,8 +6,8 @@ package os
import syscall "syscall" import syscall "syscall"
// Errors are singleton structures. Use the Print()/String() methods to get their contents -- // Errors are singleton structures. Use the String() method to get their contents --
// they handle the nil (no error) case. // it handles the nil (no error) case.
export type Error struct { export type Error struct {
s string s string
} }
......
...@@ -28,11 +28,7 @@ export var ( ...@@ -28,11 +28,7 @@ export var (
) )
export func Open(name string, mode int64, flags int64) (fd *FD, err *Error) { export func Open(name string, mode int64, flags int64) (fd *FD, err *Error) {
var buf [512]byte; r, e := syscall.open(name, mode, flags);
if !StringToBytes(&buf, name) {
return nil, EINVAL
}
r, e := syscall.open(&buf[0], mode, flags);
return NewFD(r), ErrnoToError(e) return NewFD(r), ErrnoToError(e)
} }
...@@ -66,7 +62,7 @@ func (fd *FD) WriteString(s string) (ret int64, err *Error) { ...@@ -66,7 +62,7 @@ func (fd *FD) WriteString(s string) (ret int64, err *Error) {
return -1, EINVAL return -1, EINVAL
} }
b := new([]byte, len(s)+1); b := new([]byte, len(s)+1);
if !StringToBytes(b, s) { if !syscall.StringToBytes(b, s) {
return -1, EINVAL return -1, EINVAL
} }
r, e := syscall.write(fd.fd, &b[0], int64(len(s))); r, e := syscall.write(fd.fd, &b[0], int64(len(s)));
......
...@@ -8,23 +8,31 @@ CC=$(O)c ...@@ -8,23 +8,31 @@ CC=$(O)c
AS=$(O)a AS=$(O)a
GC=$(O)g GC=$(O)g
PKG=syscall.a PKG=$(GOROOT)/pkg/syscall.a
OFILES=\ O1=\
syscall.$O \ syscall.$O \
errstr_$(GOOS).$O \ errstr_$(GOOS).$O \
O2=\
file_$(GOARCH)_$(GOOS).$O \ file_$(GOARCH)_$(GOOS).$O \
syscall_$(GOARCH)_$(GOOS).$O \ syscall_$(GOARCH)_$(GOOS).$O \
install: $(PKG) install: nuke $(PKG)
cp $(PKG) $(GOROOT)/pkg/$(PKG)
$(PKG): a1 a2
a1: $(O1)
$(O)ar grc $(PKG) $(O1)
rm *.6
$(PKG): $(OFILES) a2: $(O2)
$(O)ar grc $(PKG) $(OFILES) $(O)ar grc $(PKG) $(O2)
rm *.6
nuke: nuke:
rm -f *.$(O) *.a $(GOROOT)/pkg/$(PKG) rm -f *.$(O) *.a $(PKG)
clean: clean:
rm -f *.$(O) *.a rm -f *.$(O) *.a
......
...@@ -65,15 +65,25 @@ const ( ...@@ -65,15 +65,25 @@ const (
O_TRUNC = 0x400; O_TRUNC = 0x400;
) )
export func open(name *byte, mode int64, flags int64) (ret int64, errno int64) { const NameBufsize = 512
export func open(name string, mode int64, perm int64) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSOPEN = 5; const SYSOPEN = 5;
r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(name), mode, flags); r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(&namebuf[0]), mode, perm);
return r1, err; return r1, err;
} }
export func creat(name *byte, mode int64) (ret int64, errno int64) { export func creat(name string, perm int64) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSOPEN = 5; const SYSOPEN = 5;
r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(name), mode, O_CREAT|O_WRONLY|O_TRUNC); r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(&namebuf[0]), O_CREAT|O_WRONLY|O_TRUNC, perm);
return r1, err; return r1, err;
} }
...@@ -106,9 +116,13 @@ export func pipe(fds *[2]int64) (ret int64, errno int64) { ...@@ -106,9 +116,13 @@ export func pipe(fds *[2]int64) (ret int64, errno int64) {
return 0, 0; return 0, 0;
} }
export func stat(name *byte, buf *Stat) (ret int64, errno int64) { export func stat(name string, buf *Stat) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSSTAT = 338; const SYSSTAT = 338;
r1, r2, err := syscall.Syscall(SYSSTAT, AddrToInt(name), StatToInt(buf), 0); r1, r2, err := syscall.Syscall(SYSSTAT, AddrToInt(&namebuf[0]), StatToInt(buf), 0);
return r1, err; return r1, err;
} }
...@@ -124,8 +138,12 @@ export func fstat(fd int64, buf *Stat) (ret int64, errno int64) { ...@@ -124,8 +138,12 @@ export func fstat(fd int64, buf *Stat) (ret int64, errno int64) {
return r1, err; return r1, err;
} }
export func unlink(name *byte) (ret int64, errno int64) { export func unlink(name string) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSUNLINK = 10; const SYSUNLINK = 10;
r1, r2, err := syscall.Syscall(SYSUNLINK, AddrToInt(name), 0, 0); r1, r2, err := syscall.Syscall(SYSUNLINK, AddrToInt(&namebuf[0]), 0, 0);
return r1, err; return r1, err;
} }
...@@ -66,15 +66,25 @@ const ( ...@@ -66,15 +66,25 @@ const (
O_TRUNC = 0x200; O_TRUNC = 0x200;
) )
export func open(name *byte, mode int64, flags int64) (ret int64, errno int64) { const NameBufsize = 512
export func open(name string, mode int64, perm int64) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSOPEN = 2; const SYSOPEN = 2;
r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(name), mode, flags); r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(&namebuf[0]), mode, perm);
return r1, err; return r1, err;
} }
export func creat(name *byte, mode int64) (ret int64, errno int64) { export func creat(name string, perm int64) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSOPEN = 2; const SYSOPEN = 2;
r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(name), mode, O_CREAT|O_WRONLY|O_TRUNC); r1, r2, err := syscall.Syscall(SYSOPEN, AddrToInt(&namebuf[0]), O_CREAT|O_WRONLY|O_TRUNC, perm);
return r1, err; return r1, err;
} }
...@@ -108,9 +118,13 @@ export func pipe(fds *[2]int64) (ret int64, errno int64) { ...@@ -108,9 +118,13 @@ export func pipe(fds *[2]int64) (ret int64, errno int64) {
return 0, 0; return 0, 0;
} }
export func stat(name *byte, buf *Stat) (ret int64, errno int64) { export func stat(name string, buf *Stat) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSSTAT = 4; const SYSSTAT = 4;
r1, r2, err := syscall.Syscall(SYSSTAT, AddrToInt(name), StatToInt(buf), 0); r1, r2, err := syscall.Syscall(SYSSTAT, AddrToInt(&namebuf[0]), StatToInt(buf), 0);
return r1, err; return r1, err;
} }
...@@ -126,8 +140,12 @@ export func fstat(fd int64, buf *Stat) (ret int64, errno int64) { ...@@ -126,8 +140,12 @@ export func fstat(fd int64, buf *Stat) (ret int64, errno int64) {
return r1, err; return r1, err;
} }
export func unlink(name *byte) (ret int64, errno int64) { export func unlink(name string) (ret int64, errno int64) {
var namebuf [NameBufsize]byte;
if !StringToBytes(&namebuf, name) {
return -1, syscall.ENAMETOOLONG
}
const SYSUNLINK = 87; const SYSUNLINK = 87;
r1, r2, err := syscall.Syscall(SYSUNLINK, AddrToInt(name), 0, 0); r1, r2, err := syscall.Syscall(SYSUNLINK, AddrToInt(&namebuf[0]), 0, 0);
return r1, err; return r1, err;
} }
...@@ -11,3 +11,17 @@ package syscall ...@@ -11,3 +11,17 @@ package syscall
export func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); export func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
export func AddrToInt(b *byte) int64; export func AddrToInt(b *byte) int64;
/*
* Used to convert file names to byte arrays for passing to kernel,
* but useful elsewhere too.
*/
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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment