Skip to content
Snippets Groups Projects
file.go 4.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • Rob Pike's avatar
    Rob Pike committed
    // 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.
    }
    
    
    Rob Pike's avatar
    Rob Pike committed
    // FDs are wrappers for file descriptors
    
    Russ Cox's avatar
    Russ Cox committed
    type FD struct {
    
    Rob Pike's avatar
    Rob Pike committed
    	fd int64;
    	name	string;
    
    	dirinfo	*dirInfo;	// nil unless directory being read
    
    Rob Pike's avatar
    Rob Pike committed
    func (fd *FD) Fd() int64 {
    	return fd.fd
    }
    
    func (fd *FD) Name() string {
    	return fd.name
    }
    
    func NewFD(fd int64, name string) *FD {
    
    Rob Pike's avatar
    Rob Pike committed
    	if fd < 0 {
    		return nil
    	}
    
    	return &FD(fd, name, nil)
    
    Russ Cox's avatar
    Russ Cox committed
    var (
    
    Rob Pike's avatar
    Rob Pike committed
    	Stdin = NewFD(0, "/dev/stdin");
    	Stdout = NewFD(1, "/dev/stdout");
    	Stderr = NewFD(2, "/dev/stderr");
    
    Russ Cox's avatar
    Russ Cox committed
    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;
    )
    
    
    Russ Cox's avatar
    Russ Cox committed
    func Open(name string, mode int, flags int) (fd *FD, err *Error) {
    
    Rob Pike's avatar
    Rob Pike committed
    	r, e := syscall.Open(name, int64(mode), int64(flags));
    
    Rob Pike's avatar
    Rob Pike committed
    	return NewFD(r, name), ErrnoToError(e)
    
    Rob Pike's avatar
    Rob Pike committed
    }
    
    func (fd *FD) Close() *Error {
    	if fd == nil {
    		return EINVAL
    	}
    
    Rob Pike's avatar
    Rob Pike committed
    	r, e := syscall.Close(fd.fd);
    	fd.fd = -1;  // so it can't be closed again
    
    Rob Pike's avatar
    Rob Pike committed
    	return ErrnoToError(e)
    }
    
    
    Russ Cox's avatar
    Russ Cox committed
    func (fd *FD) Read(b []byte) (ret int, err *Error) {
    
    Rob Pike's avatar
    Rob Pike committed
    	if fd == nil {
    
    Rob Pike's avatar
    Rob Pike committed
    	}
    
    	var r, e int64;
    	if len(b) > 0 {  // because we access b[0]
    
    Rob Pike's avatar
    Rob Pike committed
    		r, e = syscall.Read(fd.fd, &b[0], int64(len(b)));
    
    Russ Cox's avatar
    Russ Cox committed
    	return int(r), ErrnoToError(e)
    
    Russ Cox's avatar
    Russ Cox committed
    func (fd *FD) Write(b []byte) (ret int, err *Error) {
    
    Rob Pike's avatar
    Rob Pike committed
    	if fd == nil {
    
    Rob Pike's avatar
    Rob Pike committed
    	}
    
    	var r, e int64;
    	if len(b) > 0 {  // because we access b[0]
    
    Rob Pike's avatar
    Rob Pike committed
    		r, e = syscall.Write(fd.fd, &b[0], int64(len(b)));
    
    Russ Cox's avatar
    Russ Cox committed
    	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
    }
    
    
    Russ Cox's avatar
    Russ Cox committed
    func (fd *FD) WriteString(s string) (ret int, err *Error) {
    
    Rob Pike's avatar
    Rob Pike committed
    	if fd == nil {
    
    Rob Pike's avatar
    Rob Pike committed
    	r, e := syscall.Write(fd.fd, syscall.StringBytePtr(s), int64(len(s)));
    
    Russ Cox's avatar
    Russ Cox committed
    	return int(r), ErrnoToError(e)
    
    Russ Cox's avatar
    Russ Cox committed
    
    
    Russ Cox's avatar
    Russ Cox committed
    func Pipe() (fd1 *FD, fd2 *FD, err *Error) {
    
    	var p [2]int64;
    
    Rob Pike's avatar
    Rob Pike committed
    	r, e := syscall.Pipe(&p);
    
    Russ Cox's avatar
    Russ Cox committed
    	if e != 0 {
    		return nil, nil, ErrnoToError(e)
    	}
    
    Rob Pike's avatar
    Rob Pike committed
    	return NewFD(p[0], "|0"), NewFD(p[1], "|1"), nil
    
    Russ Cox's avatar
    Russ Cox committed
    }
    
    Cary Hull's avatar
    Cary Hull committed
    
    
    Russ Cox's avatar
    Russ Cox committed
    func Mkdir(name string, perm int) *Error {
    
    Rob Pike's avatar
    Rob Pike committed
    	r, e := syscall.Mkdir(name, int64(perm));
    
    Cary Hull's avatar
    Cary Hull committed
    	return ErrnoToError(e)
    }
    
    Rob Pike's avatar
    Rob Pike committed
    
    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
    }
    
    
    // Non-portable function defined in operating-system-dependent file.
    func Readdirnames(fd *FD, count int) (names []string, err *os.Error)
    
    // Negative count means read until EOF.
    func Readdir(fd *FD, count int) (dirs []Dir, err *os.Error) {
    	dirname := fd.name;
    	if dirname == "" {
    		dirname = ".";
    	}
    	dirname += "/";
    	names, err1 := Readdirnames(fd, count);
    	if err1 != nil {
    		return nil, err1
    	}
    	dirs = make([]Dir, len(names));
    	for i, filename := range names {
    		dirp, err := Stat(dirname + filename);
    		if dirp ==  nil || err != nil {
    			dirs[i].Name = filename	// rest is already zeroed out
    		} else {
    			dirs[i] = *dirp
    		}
    	}
    	return
    }