mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Start using new errors package (#8207)
This commit is contained in:
parent
e12f52e2c6
commit
a7be313230
@ -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
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
11
cmd/posix.go
11
cmd/posix.go
@ -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:
|
||||
} else if errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.EISDIR) {
|
||||
return nil, errFileNotFound
|
||||
default:
|
||||
if isSysErrHandleInvalid(pathErr.Err) {
|
||||
} else if isSysErrHandleInvalid(err) {
|
||||
// This case is special and needs to be handled for windows.
|
||||
return nil, errFileNotFound
|
||||
}
|
||||
}
|
||||
return nil, pathErr
|
||||
} else if isSysErrIO(err) {
|
||||
return nil, errFaultyDisk
|
||||
}
|
||||
|
@ -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()}
|
||||
}
|
||||
|
16
cmd/utils.go
16
cmd/utils.go
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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{
|
||||
|
Loading…
Reference in New Issue
Block a user