os: implement virtual filesystem support
This allows applications to mount filesystems in the os package. This is useful for mounting external flash filesystems, for example.
Этот коммит содержится в:
родитель
e907db1481
коммит
6bcb40fe01
8 изменённых файлов: 336 добавлений и 95 удалений
157
src/os/file.go
157
src/os/file.go
|
@ -10,49 +10,119 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Portable analogs of some common system call errors.
|
// Portable analogs of some common system call errors.
|
||||||
|
// Note that these are exported for use in the Filesystem interface.
|
||||||
var (
|
var (
|
||||||
errUnsupported = errors.New("operation not supported")
|
ErrUnsupported = errors.New("operation not supported")
|
||||||
notImplemented = errors.New("os: not implemented")
|
ErrNotImplemented = errors.New("operation not implemented")
|
||||||
|
ErrNotExist = errors.New("file not found")
|
||||||
|
ErrExist = errors.New("file exists")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
|
// Mkdir creates a directory. If the operation fails, it will return an error of
|
||||||
// standard output, and standard error file descriptors.
|
// type *PathError.
|
||||||
var (
|
func Mkdir(path string, perm FileMode) error {
|
||||||
Stdin = &File{0, "/dev/stdin"}
|
fs, suffix := findMount(path)
|
||||||
Stdout = &File{1, "/dev/stdout"}
|
if fs == nil {
|
||||||
Stderr = &File{2, "/dev/stderr"}
|
return &PathError{"mkdir", path, ErrNotExist}
|
||||||
)
|
}
|
||||||
|
err := fs.Mkdir(suffix, perm)
|
||||||
|
if err != nil {
|
||||||
|
return &PathError{"mkdir", path, err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes a file or (empty) directory. If the operation fails, it will
|
||||||
|
// return an error of type *PathError.
|
||||||
|
func Remove(path string) error {
|
||||||
|
fs, suffix := findMount(path)
|
||||||
|
if fs == nil {
|
||||||
|
return &PathError{"remove", path, ErrNotExist}
|
||||||
|
}
|
||||||
|
err := fs.Remove(suffix)
|
||||||
|
if err != nil {
|
||||||
|
return &PathError{"remove", path, err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// File represents an open file descriptor.
|
// File represents an open file descriptor.
|
||||||
type File struct {
|
type File struct {
|
||||||
fd uintptr
|
handle FileHandle
|
||||||
name string
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the file with which it was opened.
|
||||||
|
func (f *File) Name() string {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenFile opens the named file. If the operation fails, the returned error
|
||||||
|
// will be of type *PathError.
|
||||||
|
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
|
||||||
|
fs, suffix := findMount(name)
|
||||||
|
if fs == nil {
|
||||||
|
return nil, &PathError{"open", name, ErrNotExist}
|
||||||
|
}
|
||||||
|
handle, err := fs.OpenFile(suffix, flag, perm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &PathError{"open", name, err}
|
||||||
|
}
|
||||||
|
return &File{name: name, handle: handle}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the file named for reading.
|
||||||
|
func Open(name string) (*File, error) {
|
||||||
|
return OpenFile(name, O_RDONLY, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates the named file, overwriting it if it already exists.
|
||||||
|
func Create(name string) (*File, error) {
|
||||||
|
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads up to len(b) bytes from the File. It returns the number of bytes
|
||||||
|
// read and any error encountered. At end of file, Read returns 0, io.EOF.
|
||||||
|
func (f *File) Read(b []byte) (n int, err error) {
|
||||||
|
n, err = f.handle.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
err = &PathError{"read", f.name, err}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes len(b) bytes to the File. It returns the number of bytes written
|
||||||
|
// and an error, if any. Write returns a non-nil error when n != len(b).
|
||||||
|
func (f *File) Write(b []byte) (n int, err error) {
|
||||||
|
n, err = f.handle.Write(b)
|
||||||
|
if err != nil {
|
||||||
|
err = &PathError{"write", f.name, err}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the File, rendering it unusable for I/O.
|
||||||
|
func (f *File) Close() (err error) {
|
||||||
|
err = f.handle.Close()
|
||||||
|
if err != nil {
|
||||||
|
err = &PathError{"close", f.name, err}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readdir is a stub, not yet implemented
|
// Readdir is a stub, not yet implemented
|
||||||
func (f *File) Readdir(n int) ([]FileInfo, error) {
|
func (f *File) Readdir(n int) ([]FileInfo, error) {
|
||||||
return nil, notImplemented
|
return nil, &PathError{"readdir", f.name, ErrNotImplemented}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readdirnames is a stub, not yet implemented
|
// Readdirnames is a stub, not yet implemented
|
||||||
func (f *File) Readdirnames(n int) (names []string, err error) {
|
func (f *File) Readdirnames(n int) (names []string, err error) {
|
||||||
return nil, notImplemented
|
return nil, &PathError{"readdirnames", f.name, ErrNotImplemented}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat is a stub, not yet implemented
|
// Stat is a stub, not yet implemented
|
||||||
func (f *File) Stat() (FileInfo, error) {
|
func (f *File) Stat() (FileInfo, error) {
|
||||||
return nil, notImplemented
|
return nil, &PathError{"stat", f.name, ErrNotImplemented}
|
||||||
}
|
|
||||||
|
|
||||||
// NewFile returns a new File with the given file descriptor and name.
|
|
||||||
func NewFile(fd uintptr, name string) *File {
|
|
||||||
return &File{fd, name}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fd returns the integer Unix file descriptor referencing the open file. The
|
|
||||||
// file descriptor is valid only until f.Close is called.
|
|
||||||
func (f *File) Fd() uintptr {
|
|
||||||
return f.fd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -72,32 +142,8 @@ type PathError struct {
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
|
func (e *PathError) Error() string {
|
||||||
|
return e.Op + " " + e.Path + ": " + e.Err.Error()
|
||||||
// Open is a super simple stub function (for now), only capable of opening stdin, stdout, and stderr
|
|
||||||
func Open(name string) (*File, error) {
|
|
||||||
fd := uintptr(999)
|
|
||||||
switch name {
|
|
||||||
case "/dev/stdin":
|
|
||||||
fd = 0
|
|
||||||
case "/dev/stdout":
|
|
||||||
fd = 1
|
|
||||||
case "/dev/stderr":
|
|
||||||
fd = 2
|
|
||||||
default:
|
|
||||||
return nil, &PathError{"open", name, notImplemented}
|
|
||||||
}
|
|
||||||
return &File{fd, name}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenFile is a stub, passing through to the stub Open() call
|
|
||||||
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
|
|
||||||
return Open(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create is a stub, passing through to the stub Open() call
|
|
||||||
func Create(name string) (*File, error) {
|
|
||||||
return Open(name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileMode uint32
|
type FileMode uint32
|
||||||
|
@ -155,12 +201,12 @@ type FileInfo interface {
|
||||||
|
|
||||||
// Stat is a stub, not yet implemented
|
// Stat is a stub, not yet implemented
|
||||||
func Stat(name string) (FileInfo, error) {
|
func Stat(name string) (FileInfo, error) {
|
||||||
return nil, notImplemented
|
return nil, &PathError{"stat", name, ErrNotImplemented}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lstat is a stub, not yet implemented
|
// Lstat is a stub, not yet implemented
|
||||||
func Lstat(name string) (FileInfo, error) {
|
func Lstat(name string) (FileInfo, error) {
|
||||||
return nil, notImplemented
|
return nil, &PathError{"lstat", name, ErrNotImplemented}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getwd is a stub (for now), always returning an empty string
|
// Getwd is a stub (for now), always returning an empty string
|
||||||
|
@ -178,11 +224,6 @@ func TempDir() string {
|
||||||
return "/tmp"
|
return "/tmp"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mkdir is a stub, not yet implemented
|
|
||||||
func Mkdir(name string, perm FileMode) error {
|
|
||||||
return notImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExist is a stub (for now), always returning false
|
// IsExist is a stub (for now), always returning false
|
||||||
func IsExist(err error) bool {
|
func IsExist(err error) bool {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -6,28 +6,44 @@ import (
|
||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
|
||||||
|
// standard output, and standard error file descriptors.
|
||||||
|
var (
|
||||||
|
Stdin = &File{stdioFileHandle(0), "/dev/stdin"}
|
||||||
|
Stdout = &File{stdioFileHandle(1), "/dev/stdout"}
|
||||||
|
Stderr = &File{stdioFileHandle(2), "/dev/stderr"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// isOS indicates whether we're running on a real operating system with
|
||||||
|
// filesystem support.
|
||||||
|
const isOS = false
|
||||||
|
|
||||||
|
// stdioFileHandle represents one of stdin, stdout, or stderr depending on the
|
||||||
|
// number. It implements the FileHandle interface.
|
||||||
|
type stdioFileHandle uint8
|
||||||
|
|
||||||
// Read is unsupported on this system.
|
// Read is unsupported on this system.
|
||||||
func (f *File) Read(b []byte) (n int, err error) {
|
func (f stdioFileHandle) Read(b []byte) (n int, err error) {
|
||||||
return 0, errUnsupported
|
return 0, ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the output. It returns the number of bytes
|
// Write writes len(b) bytes to the output. It returns the number of bytes
|
||||||
// written or an error if this file is not stdout or stderr.
|
// written or an error if this file is not stdout or stderr.
|
||||||
func (f *File) Write(b []byte) (n int, err error) {
|
func (f stdioFileHandle) Write(b []byte) (n int, err error) {
|
||||||
switch f.fd {
|
switch f {
|
||||||
case Stdout.fd, Stderr.fd:
|
case 1, 2: // stdout, stderr
|
||||||
for _, c := range b {
|
for _, c := range b {
|
||||||
putchar(c)
|
putchar(c)
|
||||||
}
|
}
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
default:
|
default:
|
||||||
return 0, errUnsupported
|
return 0, ErrUnsupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close is unsupported on this system.
|
// Close is unsupported on this system.
|
||||||
func (f *File) Close() error {
|
func (f stdioFileHandle) Close() error {
|
||||||
return errUnsupported
|
return ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname putchar runtime.putchar
|
//go:linkname putchar runtime.putchar
|
||||||
|
|
|
@ -6,19 +6,105 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Mount the host filesystem at the root directory. This is what most
|
||||||
|
// programs will be expecting.
|
||||||
|
Mount("/", unixFilesystem{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
|
||||||
|
// standard output, and standard error file descriptors.
|
||||||
|
var (
|
||||||
|
Stdin = &File{unixFileHandle(0), "/dev/stdin"}
|
||||||
|
Stdout = &File{unixFileHandle(1), "/dev/stdout"}
|
||||||
|
Stderr = &File{unixFileHandle(2), "/dev/stderr"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// isOS indicates whether we're running on a real operating system with
|
||||||
|
// filesystem support.
|
||||||
|
const isOS = true
|
||||||
|
|
||||||
|
// unixFilesystem is an empty handle for a Unix/Linux filesystem. All operations
|
||||||
|
// are relative to the current working directory.
|
||||||
|
type unixFilesystem struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs unixFilesystem) Mkdir(path string, perm FileMode) error {
|
||||||
|
return handleSyscallError(syscall.Mkdir(path, uint32(perm)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs unixFilesystem) Remove(path string) error {
|
||||||
|
return handleSyscallError(syscall.Unlink(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs unixFilesystem) OpenFile(path string, flag int, perm FileMode) (FileHandle, error) {
|
||||||
|
// Map os package flags to syscall flags.
|
||||||
|
syscallFlag := 0
|
||||||
|
if flag&O_RDONLY != 0 {
|
||||||
|
syscallFlag |= syscall.O_RDONLY
|
||||||
|
}
|
||||||
|
if flag&O_WRONLY != 0 {
|
||||||
|
syscallFlag |= syscall.O_WRONLY
|
||||||
|
}
|
||||||
|
if flag&O_RDWR != 0 {
|
||||||
|
syscallFlag |= syscall.O_RDWR
|
||||||
|
}
|
||||||
|
if flag&O_APPEND != 0 {
|
||||||
|
syscallFlag |= syscall.O_APPEND
|
||||||
|
}
|
||||||
|
if flag&O_CREATE != 0 {
|
||||||
|
syscallFlag |= syscall.O_CREAT
|
||||||
|
}
|
||||||
|
if flag&O_EXCL != 0 {
|
||||||
|
syscallFlag |= syscall.O_EXCL
|
||||||
|
}
|
||||||
|
if flag&O_SYNC != 0 {
|
||||||
|
syscallFlag |= syscall.O_SYNC
|
||||||
|
}
|
||||||
|
if flag&O_TRUNC != 0 {
|
||||||
|
syscallFlag |= syscall.O_TRUNC
|
||||||
|
}
|
||||||
|
fp, err := syscall.Open(path, syscallFlag, uint32(perm))
|
||||||
|
return unixFileHandle(fp), handleSyscallError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unixFileHandle is a Unix file pointer with associated methods that implement
|
||||||
|
// the FileHandle interface.
|
||||||
|
type unixFileHandle uintptr
|
||||||
|
|
||||||
// Read reads up to len(b) bytes from the File. It returns the number of bytes
|
// Read reads up to len(b) bytes from the File. It returns the number of bytes
|
||||||
// read and any error encountered. At end of file, Read returns 0, io.EOF.
|
// read and any error encountered. At end of file, Read returns 0, io.EOF.
|
||||||
func (f *File) Read(b []byte) (n int, err error) {
|
func (f unixFileHandle) Read(b []byte) (n int, err error) {
|
||||||
return syscall.Read(int(f.fd), b)
|
n, err = syscall.Read(int(f), b)
|
||||||
|
err = handleSyscallError(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the File. It returns the number of bytes written
|
// Write writes len(b) bytes to the File. It returns the number of bytes written
|
||||||
// and an error, if any. Write returns a non-nil error when n != len(b).
|
// and an error, if any. Write returns a non-nil error when n != len(b).
|
||||||
func (f *File) Write(b []byte) (n int, err error) {
|
func (f unixFileHandle) Write(b []byte) (n int, err error) {
|
||||||
return syscall.Write(int(f.fd), b)
|
n, err = syscall.Write(int(f), b)
|
||||||
|
err = handleSyscallError(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the File, rendering it unusable for I/O.
|
// Close closes the File, rendering it unusable for I/O.
|
||||||
func (f *File) Close() error {
|
func (f unixFileHandle) Close() error {
|
||||||
return syscall.Close(int(f.fd))
|
return handleSyscallError(syscall.Close(int(f)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleSyscallError converts syscall errors into regular os package errors.
|
||||||
|
// The err parameter must be either nil or of type syscall.Errno.
|
||||||
|
func handleSyscallError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch err.(syscall.Errno) {
|
||||||
|
case syscall.EEXIST:
|
||||||
|
return ErrExist
|
||||||
|
case syscall.ENOENT:
|
||||||
|
return ErrNotExist
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
85
src/os/filesystem.go
Обычный файл
85
src/os/filesystem.go
Обычный файл
|
@ -0,0 +1,85 @@
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// mounts lists the mount points currently mounted in the filesystem provided by
|
||||||
|
// the os package. To resolve a path to a mount point, it is scanned from top to
|
||||||
|
// bottom looking for the first prefix match.
|
||||||
|
var mounts []mountPoint
|
||||||
|
|
||||||
|
type mountPoint struct {
|
||||||
|
// prefix is a filesystem prefix, that always starts and ends with a forward
|
||||||
|
// slash. To denote the root filesystem, use a single slash: "/".
|
||||||
|
// This allows fast checking whether a path lies within a mount point.
|
||||||
|
prefix string
|
||||||
|
|
||||||
|
// filesystem is the Filesystem implementation that is mounted at this mount
|
||||||
|
// point.
|
||||||
|
filesystem Filesystem
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filesystem provides an interface for generic filesystem drivers mounted in
|
||||||
|
// the os package. The errors returned must be one of the os.Err* errors, or a
|
||||||
|
// custom error if one doesn't exist. It should not be a *PathError because
|
||||||
|
// errors will be wrapped with a *PathError by the filesystem abstraction.
|
||||||
|
//
|
||||||
|
// WARNING: this interface is not finalized and may change in a future version.
|
||||||
|
type Filesystem interface {
|
||||||
|
// OpenFile opens the named file.
|
||||||
|
OpenFile(name string, flag int, perm FileMode) (FileHandle, error)
|
||||||
|
|
||||||
|
// Mkdir creates a new directoy with the specified permission (before
|
||||||
|
// umask). Some filesystems may not support directories or permissions.
|
||||||
|
Mkdir(name string, perm FileMode) error
|
||||||
|
|
||||||
|
// Remove removes the named file or (empty) directory.
|
||||||
|
Remove(name string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileHandle is an interface that should be implemented by filesystems
|
||||||
|
// implementing the Filesystem interface.
|
||||||
|
//
|
||||||
|
// WARNING: this interface is not finalized and may change in a future version.
|
||||||
|
type FileHandle interface {
|
||||||
|
// Read reads up to len(b) bytes from the file.
|
||||||
|
Read(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Write writes up to len(b) bytes to the file.
|
||||||
|
Write(b []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Close closes the file, making it unusable for further writes.
|
||||||
|
Close() (err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// findMount returns the appropriate (mounted) filesystem to use for a given
|
||||||
|
// filename plus the path relative to that filesystem.
|
||||||
|
func findMount(path string) (Filesystem, string) {
|
||||||
|
for i := len(mounts) - 1; i >= 0; i-- {
|
||||||
|
mount := mounts[i]
|
||||||
|
if strings.HasPrefix(path, mount.prefix) {
|
||||||
|
return mount.filesystem, path[len(mount.prefix)-1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isOS {
|
||||||
|
// Assume that the first entry in the mounts slice is the OS filesystem
|
||||||
|
// at the root of the directory tree. Use it as-is, to support relative
|
||||||
|
// paths.
|
||||||
|
return mounts[0].filesystem, path
|
||||||
|
}
|
||||||
|
return nil, path
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount mounts the given filesystem in the filesystem abstraction layer of the
|
||||||
|
// os package. It is not possible to unmount filesystems. Filesystems added
|
||||||
|
// later will override earlier filesystems.
|
||||||
|
//
|
||||||
|
// The provided prefix must start and end with a forward slash. This is true for
|
||||||
|
// the root directory ("/") for example.
|
||||||
|
func Mount(prefix string, filesystem Filesystem) {
|
||||||
|
if prefix[0] != '/' || prefix[len(prefix)-1] != '/' {
|
||||||
|
panic("os.Mount: invalid prefix")
|
||||||
|
}
|
||||||
|
mounts = append(mounts, mountPoint{prefix, filesystem})
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
// This file defines errno and constants to match the darwin libsystem ABI.
|
// This file defines errno and constants to match the darwin libsystem ABI.
|
||||||
// Values have been determined experimentally by compiling some C code on macOS
|
// Values have been copied from src/syscall/zerrors_darwin_amd64.go.
|
||||||
// with Clang and looking at the resulting LLVM IR.
|
|
||||||
|
|
||||||
// This function returns the error location in the darwin ABI.
|
// This function returns the error location in the darwin ABI.
|
||||||
// Discovered by compiling the following code using Clang:
|
// Discovered by compiling the following code using Clang:
|
||||||
|
@ -24,28 +23,34 @@ func getErrno() Errno {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ENOENT Errno = 2
|
ENOENT Errno = 0x2
|
||||||
EINTR Errno = 4
|
EEXIST Errno = 0x11
|
||||||
EMFILE Errno = 24
|
EINTR Errno = 0x4
|
||||||
EAGAIN Errno = 35
|
EMFILE Errno = 0x18
|
||||||
ETIMEDOUT Errno = 60
|
EAGAIN Errno = 0x23
|
||||||
ENOSYS Errno = 78
|
ETIMEDOUT Errno = 0x3c
|
||||||
|
ENOSYS Errno = 0x4e
|
||||||
EWOULDBLOCK Errno = EAGAIN
|
EWOULDBLOCK Errno = EAGAIN
|
||||||
)
|
)
|
||||||
|
|
||||||
type Signal int
|
type Signal int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SIGCHLD Signal = 20
|
SIGCHLD Signal = 0x14
|
||||||
SIGINT Signal = 2
|
SIGINT Signal = 0x2
|
||||||
SIGKILL Signal = 9
|
SIGKILL Signal = 0x9
|
||||||
SIGTRAP Signal = 5
|
SIGTRAP Signal = 0x5
|
||||||
SIGQUIT Signal = 3
|
SIGQUIT Signal = 0x3
|
||||||
SIGTERM Signal = 15
|
SIGTERM Signal = 0xf
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
O_RDONLY = 0
|
O_RDONLY = 0x0
|
||||||
O_WRONLY = 1
|
O_WRONLY = 0x1
|
||||||
O_RDWR = 2
|
O_RDWR = 0x2
|
||||||
|
O_APPEND = 0x8
|
||||||
|
O_SYNC = 0x80
|
||||||
|
O_CREAT = 0x200
|
||||||
|
O_TRUNC = 0x400
|
||||||
|
O_EXCL = 0x800
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,6 +31,14 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
|
||||||
return 0, ENOSYS // TODO
|
return 0, ENOSYS // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Mkdir(path string, mode uint32) (err error) {
|
||||||
|
return ENOSYS // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unlink(path string) (err error) {
|
||||||
|
return ENOSYS // TODO
|
||||||
|
}
|
||||||
|
|
||||||
func Kill(pid int, sig Signal) (err error) {
|
func Kill(pid int, sig Signal) (err error) {
|
||||||
return ENOSYS // TODO
|
return ENOSYS // TODO
|
||||||
}
|
}
|
||||||
|
|
6
testdata/stdlib.go
предоставленный
6
testdata/stdlib.go
предоставленный
|
@ -9,9 +9,9 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// package os, fmt
|
// package os, fmt
|
||||||
fmt.Println("stdin: ", os.Stdin.Fd())
|
fmt.Println("stdin: ", os.Stdin.Name())
|
||||||
fmt.Println("stdout:", os.Stdout.Fd())
|
fmt.Println("stdout:", os.Stdout.Name())
|
||||||
fmt.Println("stderr:", os.Stderr.Fd())
|
fmt.Println("stderr:", os.Stderr.Name())
|
||||||
|
|
||||||
// package math/rand
|
// package math/rand
|
||||||
fmt.Println("pseudorandom number:", rand.Int31())
|
fmt.Println("pseudorandom number:", rand.Int31())
|
||||||
|
|
6
testdata/stdlib.txt
предоставленный
6
testdata/stdlib.txt
предоставленный
|
@ -1,6 +1,6 @@
|
||||||
stdin: 0
|
stdin: /dev/stdin
|
||||||
stdout: 1
|
stdout: /dev/stdout
|
||||||
stderr: 2
|
stderr: /dev/stderr
|
||||||
pseudorandom number: 1298498081
|
pseudorandom number: 1298498081
|
||||||
strings.IndexByte: 2
|
strings.IndexByte: 2
|
||||||
strings.Replace: An-example-string
|
strings.Replace: An-example-string
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче