// 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" // An Error can represent any printable error condition. type Error interface { String() string } // A helper type that can be embedded or wrapped to simplify satisfying // Error. type ErrorString string func (e *ErrorString) String() string { return *e } // _Error is a structure wrapping a string describing an error. // Errors are singleton structures, created by NewError, so their addresses can // be compared to test for equality. A nil Error pointer means ``no error''. // Use the String() method to get the contents; it handles the nil case. // The Error type is intended for use by any package that wishes to define // error strings. type _Error struct { s string } // Indexed by errno. // If we worry about syscall speed (only relevant on failure), we could // make it an array, but it's probably not important. var errorTab = make(map[int64] Error); // Table of all known errors in system. Use the same error string twice, // get the same *os._Error. var errorStringTab = make(map[string] Error); // These functions contain a race if two goroutines add identical // errors simultaneously but the consequences are unimportant. // NewError allocates an Error object, but if s has been seen before, // shares the _Error associated with that message. func NewError(s string) Error { if s == "" { return nil } err, ok := errorStringTab[s]; if ok { return err } err = &_Error{s}; errorStringTab[s] = err; return err; } // ErrnoToError calls NewError to create an _Error object for the string // associated with Unix error code errno. func ErrnoToError(errno int64) Error { if errno == 0 { return nil } // Quick lookup by errno. err, ok := errorTab[errno]; if ok { return err } err = NewError(syscall.Errstr(errno)); errorTab[errno] = err; return err; } // Commonly known Unix errors. var ( // TODO(r): // 1. these become type ENONE struct { ErrorString } // 2. create private instances of each type: var eNONE ENONE(ErrnoToString(syscall.ENONE)); // 3. put them in a table // 4. ErrnoToError uses the table. its error case ECATCHALL("%d") 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); ) // String returns the string associated with the _Error. func (e *_Error) String() string { if e == nil { return "No _Error" } return e.s }