Start using new errors package (#8207)

This commit is contained in:
Harshavardhana 2019-09-11 10:21:43 -07:00 committed by kannappanr
parent e12f52e2c6
commit a7be313230
9 changed files with 63 additions and 153 deletions

View File

@ -18,6 +18,7 @@ package hdfs
import (
"context"
"errors"
"fmt"
"io"
"net"
@ -280,7 +281,7 @@ func hdfsToObjectErr(ctx context.Context, err error, params ...string) error {
return minio.PrefixAccessDenied{Bucket: bucket, Object: object}
}
return minio.BucketAlreadyOwnedByYou{Bucket: bucket}
case isSysErrNotEmpty(err):
case errors.Is(err, syscall.ENOTEMPTY):
if object != "" {
return minio.PrefixAccessDenied{Bucket: bucket, Object: object}
}
@ -387,20 +388,6 @@ func (n *hdfsObjects) ListObjects(ctx context.Context, bucket, prefix, marker, d
return minio.ListObjects(ctx, n, bucket, prefix, marker, delimiter, maxKeys, n.listPool, n.listDirFactory(), getObjectInfo, getObjectInfo)
}
// Check if the given error corresponds to ENOTEMPTY for unix
// and ERROR_DIR_NOT_EMPTY for windows (directory not empty).
func isSysErrNotEmpty(err error) bool {
if err == syscall.ENOTEMPTY {
return true
}
if pathErr, ok := err.(*os.PathError); ok {
if pathErr.Err == syscall.ENOTEMPTY {
return true
}
}
return false
}
// deleteObject deletes a file path if its empty. If it's successfully deleted,
// it will recursively move up the tree, deleting empty parent directories
// until it finds one with files in it. Returns nil for a non-empty directory.
@ -411,16 +398,13 @@ func (n *hdfsObjects) deleteObject(basePath, deletePath string) error {
// Attempt to remove path.
if err := n.clnt.Remove(deletePath); err != nil {
switch {
case err == syscall.ENOTEMPTY:
case isSysErrNotEmpty(err):
if errors.Is(err, syscall.ENOTEMPTY) {
// Ignore errors if the directory is not empty. The server relies on
// this functionality, and sometimes uses recursion that should not
// error on parent directories.
return nil
default:
return err
}
return err
}
// Trailing slash is removed when found to ensure

View File

@ -175,7 +175,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ
name := getOpName(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name())
// Setup a http request body recorder
reqHeaders := cloneHeader(r.Header)
reqHeaders := r.Header.Clone()
reqHeaders.Set("Content-Length", strconv.Itoa(int(r.ContentLength)))
reqHeaders.Set("Host", r.Host)
for _, enc := range r.TransferEncoding {
@ -211,7 +211,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ
rs := trace.ResponseInfo{
Time: time.Now().UTC(),
Headers: cloneHeader(respBodyRecorder.Header()),
Headers: respBodyRecorder.Header().Clone(),
StatusCode: respBodyRecorder.statusCode,
Body: respBodyRecorder.Body(),
}

View File

@ -17,6 +17,7 @@
package cmd
import (
"errors"
"os"
"runtime"
"syscall"
@ -24,86 +25,54 @@ import (
// Function not implemented error
func isSysErrNoSys(err error) bool {
if err == syscall.ENOSYS {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.ENOSYS
return errors.Is(err, syscall.ENOSYS)
}
// Not supported error
func isSysErrOpNotSupported(err error) bool {
if err == syscall.EOPNOTSUPP {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.EOPNOTSUPP
return errors.Is(err, syscall.EOPNOTSUPP)
}
// No space left on device error
func isSysErrNoSpace(err error) bool {
if err == syscall.ENOSPC {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.ENOSPC
return errors.Is(err, syscall.ENOSPC)
}
// Input/output error
func isSysErrIO(err error) bool {
if err == syscall.EIO {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.EIO
return errors.Is(err, syscall.EIO)
}
// Check if the given error corresponds to EISDIR (is a directory).
func isSysErrIsDir(err error) bool {
if err == syscall.EISDIR {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.EISDIR
return errors.Is(err, syscall.EISDIR)
}
// Check if the given error corresponds to ENOTDIR (is not a directory).
func isSysErrNotDir(err error) bool {
if err == syscall.ENOTDIR {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.ENOTDIR
return errors.Is(err, syscall.ENOTDIR)
}
// Check if the given error corresponds to the ENAMETOOLONG (name too long).
func isSysErrTooLong(err error) bool {
if err == syscall.ENAMETOOLONG {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && pathErr.Err == syscall.ENAMETOOLONG
return errors.Is(err, syscall.ENAMETOOLONG)
}
// Check if the given error corresponds to ENOTEMPTY for unix
// and ERROR_DIR_NOT_EMPTY for windows (directory not empty).
func isSysErrNotEmpty(err error) bool {
if err == syscall.ENOTEMPTY {
if errors.Is(err, syscall.ENOTEMPTY) {
return true
}
if pathErr, ok := err.(*os.PathError); ok {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
if runtime.GOOS == globalWindowsOSName {
if errno, _ok := pathErr.Err.(syscall.Errno); _ok && errno == 0x91 {
var errno syscall.Errno
if errors.As(pathErr.Err, &errno) {
// ERROR_DIR_NOT_EMPTY
return true
return errno == 0x91
}
}
if pathErr.Err == syscall.ENOTEMPTY {
return true
}
}
return false
}
@ -113,10 +82,12 @@ func isSysErrPathNotFound(err error) bool {
if runtime.GOOS != globalWindowsOSName {
return false
}
if pathErr, ok := err.(*os.PathError); ok {
if errno, _ok := pathErr.Err.(syscall.Errno); _ok && errno == 0x03 {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
var errno syscall.Errno
if errors.As(pathErr.Err, &errno) {
// ERROR_PATH_NOT_FOUND
return true
return errno == 0x03
}
}
return false
@ -128,20 +99,22 @@ func isSysErrHandleInvalid(err error) bool {
return false
}
// Check if err contains ERROR_INVALID_HANDLE errno
errno, ok := err.(syscall.Errno)
return ok && errno == 0x6
var pathErr *os.PathError
if errors.As(err, &pathErr) {
var errno syscall.Errno
if errors.As(pathErr.Err, &errno) {
// ERROR_PATH_NOT_FOUND
return errno == 0x6
}
}
return false
}
func isSysErrCrossDevice(err error) bool {
e, ok := err.(*os.LinkError)
return ok && e.Err == syscall.EXDEV
return errors.Is(err, syscall.EXDEV)
}
// Check if given error corresponds to too many open files
func isSysErrTooManyFiles(err error) bool {
if err == syscall.ENFILE || err == syscall.EMFILE {
return true
}
pathErr, ok := err.(*os.PathError)
return ok && (pathErr.Err == syscall.ENFILE || pathErr.Err == syscall.EMFILE)
return errors.Is(err, syscall.ENFILE) || errors.Is(err, syscall.EMFILE)
}

View File

@ -19,6 +19,7 @@ package cmd
import (
"context"
"encoding/hex"
"errors"
"io"
"io/ioutil"
"os"
@ -845,17 +846,11 @@ func (s *posix) ReadAll(volume, path string) (buf []byte, err error) {
return nil, errFileNotFound
} else if os.IsPermission(err) {
return nil, errFileAccessDenied
} else if pathErr, ok := err.(*os.PathError); ok {
switch pathErr.Err {
case syscall.ENOTDIR, syscall.EISDIR:
return nil, errFileNotFound
default:
if isSysErrHandleInvalid(pathErr.Err) {
// This case is special and needs to be handled for windows.
return nil, errFileNotFound
}
}
return nil, pathErr
} else if errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.EISDIR) {
return nil, errFileNotFound
} else if isSysErrHandleInvalid(err) {
// This case is special and needs to be handled for windows.
return nil, errFileNotFound
} else if isSysErrIO(err) {
return nil, errFaultyDisk
}

View File

@ -17,9 +17,9 @@
package cmd
import (
"errors"
"fmt"
"io"
"net"
"os"
"syscall"
)
@ -80,27 +80,15 @@ func errorToUIErr(err error) uiErr {
}
// Show a generic message for known golang errors
switch e := err.(type) {
case *net.OpError:
if e.Op == "listen" {
if oe, ok := e.Err.(*os.SyscallError); ok {
if oe.Err == syscall.EADDRINUSE {
return uiErrPortAlreadyInUse(e).Msg("Specified port '" + e.Addr.String() + "' is already in use")
} else if oe.Err == syscall.EACCES {
return uiErrPortAccess(e).Msg("Insufficient permissions to use specified port '" + e.Addr.String() + "'")
}
}
}
case *os.PathError:
if os.IsPermission(e) {
return uiErrNoPermissionsToAccessDirFiles(e).Msg("Insufficient permissions to access path, `" + e.Path + "`")
}
}
switch err {
case io.ErrUnexpectedEOF:
if errors.Is(err, syscall.EADDRINUSE) {
return uiErrPortAlreadyInUse(err).Msg("Specified port is already in use")
} else if errors.Is(err, syscall.EACCES) {
return uiErrPortAccess(err).Msg("Insufficient permissions to use specified port")
} else if os.IsPermission(err) {
return uiErrNoPermissionsToAccessDirFiles(err).Msg("Insufficient permissions to access path")
} else if errors.Is(err, io.ErrUnexpectedEOF) {
return uiErrUnexpectedDataContent(err)
default:
} else {
// Failed to identify what type of error this, return a simple UI error
return uiErr{msg: err.Error()}
}

View File

@ -53,25 +53,13 @@ func IsErrIgnored(err error, ignoredErrs ...error) bool {
// IsErr returns whether given error is exact error.
func IsErr(err error, errs ...error) bool {
for _, exactErr := range errs {
if err == exactErr {
if errors.Is(err, exactErr) {
return true
}
}
return false
}
// make a copy of http.Header
func cloneHeader(h http.Header) http.Header {
h2 := make(http.Header, len(h))
for k, vv := range h {
vv2 := make([]string, len(vv))
copy(vv2, vv)
h2[k] = vv2
}
return h2
}
func request2BucketObjectName(r *http.Request) (bucketName, objectName string) {
path, err := getResource(r.URL.Path, r.Host, globalDomainNames)
if err != nil {
@ -289,7 +277,7 @@ var globalProfiler minioProfiler
// dump the request into a string in JSON format.
func dumpRequest(r *http.Request) string {
header := cloneHeader(r.Header)
header := r.Header.Clone()
header.Set("Host", r.Host)
// Replace all '%' to '%%' so that printer format parser
// to ignore URL encoded values.

View File

@ -30,30 +30,6 @@ import (
"testing"
)
// Tests http.Header clone.
func TestCloneHeader(t *testing.T) {
headers := []http.Header{
{
"Content-Type": {"text/html; charset=UTF-8"},
"Content-Length": {"0"},
},
{
"Content-Length": {"0", "1", "2"},
},
{
"Expires": {"-1"},
"Content-Length": {"0"},
"Content-Encoding": {"gzip"},
},
}
for i, header := range headers {
clonedHeader := cloneHeader(header)
if !reflect.DeepEqual(header, clonedHeader) {
t.Errorf("Test %d failed", i+1)
}
}
}
// Tests maximum object size.
func TestMaxObjectSize(t *testing.T) {
sizes := []struct {

View File

@ -19,7 +19,6 @@
package lock
import (
"fmt"
"os"
"syscall"
)
@ -39,7 +38,11 @@ func lockedOpenFile(path string, flag int, perm os.FileMode, lockType int) (*Loc
case syscall.O_RDWR | syscall.O_CREAT:
lockType |= syscall.LOCK_EX
default:
return nil, fmt.Errorf("Unsupported flag (%d)", flag)
return nil, &os.PathError{
Op: "open",
Path: path,
Err: syscall.EINVAL,
}
}
f, err := os.OpenFile(path, flag|syscall.O_SYNC, perm)

View File

@ -19,7 +19,6 @@
package lock
import (
"fmt"
"os"
"syscall"
)
@ -39,7 +38,11 @@ func lockedOpenFile(path string, flag int, perm os.FileMode, rlockType int) (*Lo
case syscall.O_RDWR | syscall.O_CREAT:
lockType = syscall.F_WRLCK
default:
return nil, fmt.Errorf("Unsupported flag (%d)", flag)
return nil, &os.PathError{
Op: "open",
Path: path,
Err: syscall.EINVAL,
}
}
var lock = syscall.Flock_t{