Start using new errors package (#8207)

master
Harshavardhana 5 years ago committed by kannappanr
parent e12f52e2c6
commit a7be313230
  1. 24
      cmd/gateway/hdfs/gateway-hdfs.go
  2. 4
      cmd/http-tracer.go
  3. 87
      cmd/posix-errors.go
  4. 17
      cmd/posix.go
  5. 30
      cmd/ui-errors-utils.go
  6. 16
      cmd/utils.go
  7. 24
      cmd/utils_test.go
  8. 7
      pkg/lock/lock_nix.go
  9. 7
      pkg/lock/lock_solaris.go

@ -18,6 +18,7 @@ package hdfs
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"net" "net"
@ -280,7 +281,7 @@ func hdfsToObjectErr(ctx context.Context, err error, params ...string) error {
return minio.PrefixAccessDenied{Bucket: bucket, Object: object} return minio.PrefixAccessDenied{Bucket: bucket, Object: object}
} }
return minio.BucketAlreadyOwnedByYou{Bucket: bucket} return minio.BucketAlreadyOwnedByYou{Bucket: bucket}
case isSysErrNotEmpty(err): case errors.Is(err, syscall.ENOTEMPTY):
if object != "" { if object != "" {
return minio.PrefixAccessDenied{Bucket: bucket, Object: 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) 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, // deleteObject deletes a file path if its empty. If it's successfully deleted,
// it will recursively move up the tree, deleting empty parent directories // 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. // 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. // Attempt to remove path.
if err := n.clnt.Remove(deletePath); err != nil { if err := n.clnt.Remove(deletePath); err != nil {
switch { if errors.Is(err, syscall.ENOTEMPTY) {
case err == syscall.ENOTEMPTY:
case isSysErrNotEmpty(err):
// Ignore errors if the directory is not empty. The server relies on // Ignore errors if the directory is not empty. The server relies on
// this functionality, and sometimes uses recursion that should not // this functionality, and sometimes uses recursion that should not
// error on parent directories. // error on parent directories.
return nil return nil
default:
return err
} }
return err
} }
// Trailing slash is removed when found to ensure // Trailing slash is removed when found to ensure

@ -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()) name := getOpName(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name())
// Setup a http request body recorder // 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("Content-Length", strconv.Itoa(int(r.ContentLength)))
reqHeaders.Set("Host", r.Host) reqHeaders.Set("Host", r.Host)
for _, enc := range r.TransferEncoding { 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{ rs := trace.ResponseInfo{
Time: time.Now().UTC(), Time: time.Now().UTC(),
Headers: cloneHeader(respBodyRecorder.Header()), Headers: respBodyRecorder.Header().Clone(),
StatusCode: respBodyRecorder.statusCode, StatusCode: respBodyRecorder.statusCode,
Body: respBodyRecorder.Body(), Body: respBodyRecorder.Body(),
} }

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

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

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

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

@ -30,30 +30,6 @@ import (
"testing" "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. // Tests maximum object size.
func TestMaxObjectSize(t *testing.T) { func TestMaxObjectSize(t *testing.T) {
sizes := []struct { sizes := []struct {

@ -19,7 +19,6 @@
package lock package lock
import ( import (
"fmt"
"os" "os"
"syscall" "syscall"
) )
@ -39,7 +38,11 @@ func lockedOpenFile(path string, flag int, perm os.FileMode, lockType int) (*Loc
case syscall.O_RDWR | syscall.O_CREAT: case syscall.O_RDWR | syscall.O_CREAT:
lockType |= syscall.LOCK_EX lockType |= syscall.LOCK_EX
default: 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) f, err := os.OpenFile(path, flag|syscall.O_SYNC, perm)

@ -19,7 +19,6 @@
package lock package lock
import ( import (
"fmt"
"os" "os"
"syscall" "syscall"
) )
@ -39,7 +38,11 @@ func lockedOpenFile(path string, flag int, perm os.FileMode, rlockType int) (*Lo
case syscall.O_RDWR | syscall.O_CREAT: case syscall.O_RDWR | syscall.O_CREAT:
lockType = syscall.F_WRLCK lockType = syscall.F_WRLCK
default: 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{ var lock = syscall.Flock_t{

Loading…
Cancel
Save