2008-09-11 14:03:46 -06:00
|
|
|
// 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"
|
|
|
|
|
2009-02-10 12:27:45 -07:00
|
|
|
// Auxiliary information if the FD describes a directory
|
|
|
|
type DirInfo struct { // TODO(r): 6g bug means this can't be private
|
|
|
|
buf []byte; // buffer for directory I/O
|
|
|
|
nbuf int64; // length of buf; return value from Getdirentries
|
|
|
|
bufp int64; // location of next record in buf.
|
|
|
|
}
|
|
|
|
|
2008-09-11 14:03:46 -06:00
|
|
|
// FDs are wrappers for file descriptors
|
2009-01-20 15:40:40 -07:00
|
|
|
type FD struct {
|
2009-02-06 18:54:26 -07:00
|
|
|
fd int64;
|
|
|
|
name string;
|
2009-02-10 12:27:45 -07:00
|
|
|
dirinfo *DirInfo; // nil unless directory being read
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
|
|
|
|
2009-02-06 18:54:26 -07:00
|
|
|
func (fd *FD) Fd() int64 {
|
|
|
|
return fd.fd
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fd *FD) Name() string {
|
|
|
|
return fd.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFD(fd int64, name string) *FD {
|
2008-09-11 14:03:46 -06:00
|
|
|
if fd < 0 {
|
|
|
|
return nil
|
|
|
|
}
|
2009-02-10 12:27:45 -07:00
|
|
|
return &FD{fd, name, nil}
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
var (
|
2009-02-06 18:54:26 -07:00
|
|
|
Stdin = NewFD(0, "/dev/stdin");
|
|
|
|
Stdout = NewFD(1, "/dev/stdout");
|
|
|
|
Stderr = NewFD(2, "/dev/stderr");
|
2008-09-11 14:03:46 -06:00
|
|
|
)
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
const (
|
2008-09-11 16:09:10 -06:00
|
|
|
O_RDONLY = syscall.O_RDONLY;
|
|
|
|
O_WRONLY = syscall.O_WRONLY;
|
|
|
|
O_RDWR = syscall.O_RDWR;
|
|
|
|
O_APPEND = syscall.O_APPEND;
|
|
|
|
O_ASYNC = syscall.O_ASYNC;
|
|
|
|
O_CREAT = syscall.O_CREAT;
|
|
|
|
O_NOCTTY = syscall.O_NOCTTY;
|
|
|
|
O_NONBLOCK = syscall.O_NONBLOCK;
|
|
|
|
O_NDELAY = O_NONBLOCK;
|
|
|
|
O_SYNC = syscall.O_SYNC;
|
|
|
|
O_TRUNC = syscall.O_TRUNC;
|
|
|
|
)
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func Open(name string, mode int, flags int) (fd *FD, err *Error) {
|
2009-01-16 12:36:44 -07:00
|
|
|
r, e := syscall.Open(name, int64(mode), int64(flags));
|
2009-02-06 18:54:26 -07:00
|
|
|
return NewFD(r, name), ErrnoToError(e)
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (fd *FD) Close() *Error {
|
|
|
|
if fd == nil {
|
|
|
|
return EINVAL
|
|
|
|
}
|
2009-02-06 18:54:26 -07:00
|
|
|
r, e := syscall.Close(fd.fd);
|
|
|
|
fd.fd = -1; // so it can't be closed again
|
2008-09-11 14:03:46 -06:00
|
|
|
return ErrnoToError(e)
|
|
|
|
}
|
|
|
|
|
2008-12-18 23:37:22 -07:00
|
|
|
func (fd *FD) Read(b []byte) (ret int, err *Error) {
|
2008-09-11 14:03:46 -06:00
|
|
|
if fd == nil {
|
2008-11-18 23:32:01 -07:00
|
|
|
return 0, EINVAL
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
2008-11-14 16:13:29 -07:00
|
|
|
var r, e int64;
|
|
|
|
if len(b) > 0 { // because we access b[0]
|
2009-02-06 18:54:26 -07:00
|
|
|
r, e = syscall.Read(fd.fd, &b[0], int64(len(b)));
|
2008-11-18 23:32:01 -07:00
|
|
|
if r < 0 {
|
|
|
|
r = 0
|
|
|
|
}
|
2008-11-14 16:13:29 -07:00
|
|
|
}
|
2008-09-12 17:42:53 -06:00
|
|
|
return int(r), ErrnoToError(e)
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
|
|
|
|
2008-12-18 23:37:22 -07:00
|
|
|
func (fd *FD) Write(b []byte) (ret int, err *Error) {
|
2008-09-11 14:03:46 -06:00
|
|
|
if fd == nil {
|
2008-11-18 23:32:01 -07:00
|
|
|
return 0, EINVAL
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
2008-11-14 16:13:29 -07:00
|
|
|
var r, e int64;
|
|
|
|
if len(b) > 0 { // because we access b[0]
|
2009-02-06 18:54:26 -07:00
|
|
|
r, e = syscall.Write(fd.fd, &b[0], int64(len(b)));
|
2008-11-18 23:32:01 -07:00
|
|
|
if r < 0 {
|
|
|
|
r = 0
|
|
|
|
}
|
2008-11-14 16:13:29 -07:00
|
|
|
}
|
2008-09-12 17:42:53 -06:00
|
|
|
return int(r), ErrnoToError(e)
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
|
|
|
|
2009-02-10 12:27:45 -07:00
|
|
|
func (fd *FD) Seek(offset int64, whence int) (ret int64, err *Error) {
|
|
|
|
r, e := syscall.Seek(fd.fd, offset, int64(whence));
|
|
|
|
if e != 0 {
|
|
|
|
return -1, ErrnoToError(e)
|
|
|
|
}
|
|
|
|
if fd.dirinfo != nil && r != 0 {
|
|
|
|
return -1, ErrnoToError(syscall.EISDIR)
|
|
|
|
}
|
|
|
|
return r, nil
|
|
|
|
}
|
|
|
|
|
2008-09-12 17:42:53 -06:00
|
|
|
func (fd *FD) WriteString(s string) (ret int, err *Error) {
|
2008-09-11 14:03:46 -06:00
|
|
|
if fd == nil {
|
2008-11-18 23:32:01 -07:00
|
|
|
return 0, EINVAL
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
2009-02-06 18:54:26 -07:00
|
|
|
r, e := syscall.Write(fd.fd, syscall.StringBytePtr(s), int64(len(s)));
|
2008-11-18 23:32:01 -07:00
|
|
|
if r < 0 {
|
|
|
|
r = 0
|
|
|
|
}
|
2008-09-12 17:42:53 -06:00
|
|
|
return int(r), ErrnoToError(e)
|
2008-09-11 14:03:46 -06:00
|
|
|
}
|
2008-09-26 15:31:17 -06:00
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func Pipe() (fd1 *FD, fd2 *FD, err *Error) {
|
2008-10-07 13:31:31 -06:00
|
|
|
var p [2]int64;
|
2009-01-16 12:36:44 -07:00
|
|
|
r, e := syscall.Pipe(&p);
|
2008-09-26 15:31:17 -06:00
|
|
|
if e != 0 {
|
|
|
|
return nil, nil, ErrnoToError(e)
|
|
|
|
}
|
2009-02-06 18:54:26 -07:00
|
|
|
return NewFD(p[0], "|0"), NewFD(p[1], "|1"), nil
|
2008-09-26 15:31:17 -06:00
|
|
|
}
|
2008-10-09 01:15:37 -06:00
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func Mkdir(name string, perm int) *Error {
|
2009-01-16 12:36:44 -07:00
|
|
|
r, e := syscall.Mkdir(name, int64(perm));
|
2008-10-09 01:15:37 -06:00
|
|
|
return ErrnoToError(e)
|
|
|
|
}
|
2009-02-06 18:54:26 -07:00
|
|
|
|
|
|
|
func Stat(name string) (dir *Dir, err *Error) {
|
|
|
|
stat := new(syscall.Stat_t);
|
|
|
|
r, e := syscall.Stat(name, stat);
|
|
|
|
if e != 0 {
|
|
|
|
return nil, ErrnoToError(e)
|
|
|
|
}
|
|
|
|
return dirFromStat(name, new(Dir), stat), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Fstat(fd *FD) (dir *Dir, err *Error) {
|
|
|
|
stat := new(syscall.Stat_t);
|
|
|
|
r, e := syscall.Fstat(fd.fd, stat);
|
|
|
|
if e != 0 {
|
|
|
|
return nil, ErrnoToError(e)
|
|
|
|
}
|
|
|
|
return dirFromStat(fd.name, new(Dir), stat), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Lstat(name string) (dir *Dir, err *Error) {
|
|
|
|
stat := new(syscall.Stat_t);
|
|
|
|
r, e := syscall.Lstat(name, stat);
|
|
|
|
if e != 0 {
|
|
|
|
return nil, ErrnoToError(e)
|
|
|
|
}
|
|
|
|
return dirFromStat(name, new(Dir), stat), nil
|
|
|
|
}
|