mirror of
https://github.com/golang/go.git
synced 2025-05-23 16:31:27 +00:00
state in the FD. This is Darwin only. Next CL will make Readdir use Readdirnames to generate its files and move Readdir into portable code, as well as fix Readdirnames for Linux. R=rsc DELTA=116 (79 added, 12 deleted, 25 changed) OCL=24756 CL=24768
163 lines
3.5 KiB
Go
163 lines
3.5 KiB
Go
// 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"
|
|
|
|
// 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.
|
|
}
|
|
|
|
// FDs are wrappers for file descriptors
|
|
type FD struct {
|
|
fd int64;
|
|
name string;
|
|
dirinfo *DirInfo; // nil unless directory being read
|
|
}
|
|
|
|
func (fd *FD) Fd() int64 {
|
|
return fd.fd
|
|
}
|
|
|
|
func (fd *FD) Name() string {
|
|
return fd.name
|
|
}
|
|
|
|
func NewFD(fd int64, name string) *FD {
|
|
if fd < 0 {
|
|
return nil
|
|
}
|
|
return &FD{fd, name, nil}
|
|
}
|
|
|
|
var (
|
|
Stdin = NewFD(0, "/dev/stdin");
|
|
Stdout = NewFD(1, "/dev/stdout");
|
|
Stderr = NewFD(2, "/dev/stderr");
|
|
)
|
|
|
|
const (
|
|
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;
|
|
)
|
|
|
|
func Open(name string, mode int, flags int) (fd *FD, err *Error) {
|
|
r, e := syscall.Open(name, int64(mode), int64(flags));
|
|
return NewFD(r, name), 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 int, err *Error) {
|
|
if fd == nil {
|
|
return 0, EINVAL
|
|
}
|
|
var r, e int64;
|
|
if len(b) > 0 { // because we access b[0]
|
|
r, e = syscall.Read(fd.fd, &b[0], int64(len(b)));
|
|
if r < 0 {
|
|
r = 0
|
|
}
|
|
}
|
|
return int(r), ErrnoToError(e)
|
|
}
|
|
|
|
func (fd *FD) Write(b []byte) (ret int, err *Error) {
|
|
if fd == nil {
|
|
return 0, EINVAL
|
|
}
|
|
var r, e int64;
|
|
if len(b) > 0 { // because we access b[0]
|
|
r, e = syscall.Write(fd.fd, &b[0], int64(len(b)));
|
|
if r < 0 {
|
|
r = 0
|
|
}
|
|
}
|
|
return int(r), ErrnoToError(e)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (fd *FD) WriteString(s string) (ret int, err *Error) {
|
|
if fd == nil {
|
|
return 0, EINVAL
|
|
}
|
|
r, e := syscall.Write(fd.fd, syscall.StringBytePtr(s), int64(len(s)));
|
|
if r < 0 {
|
|
r = 0
|
|
}
|
|
return int(r), ErrnoToError(e)
|
|
}
|
|
|
|
func Pipe() (fd1 *FD, fd2 *FD, err *Error) {
|
|
var p [2]int64;
|
|
r, e := syscall.Pipe(&p);
|
|
if e != 0 {
|
|
return nil, nil, ErrnoToError(e)
|
|
}
|
|
return NewFD(p[0], "|0"), NewFD(p[1], "|1"), nil
|
|
}
|
|
|
|
func Mkdir(name string, perm int) *Error {
|
|
r, e := syscall.Mkdir(name, int64(perm));
|
|
return ErrnoToError(e)
|
|
}
|
|
|
|
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
|
|
}
|