mirror of
https://github.com/minio/minio.git
synced 2024-12-23 21:55:53 -05:00
Avoid testing on system errors strings in posix (#2583)
This commit is contained in:
parent
7cc77eba45
commit
d936ed90ae
89
cmd/posix-errors.go
Normal file
89
cmd/posix-errors.go
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Check if the given error corresponds to ENOTDIR (is not a directory)
|
||||
func isSysErrNotDir(err error) bool {
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
switch pathErr.Err {
|
||||
case syscall.ENOTDIR:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the given error corresponds to EISDIR (is a directory)
|
||||
func isSysErrIsDir(err error) bool {
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
switch pathErr.Err {
|
||||
case syscall.EISDIR:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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 pathErr, ok := err.(*os.PathError); ok {
|
||||
if runtime.GOOS == "windows" {
|
||||
if errno, _ok := pathErr.Err.(syscall.Errno); _ok && errno == 0x91 {
|
||||
// ERROR_DIR_NOT_EMPTY
|
||||
return true
|
||||
}
|
||||
}
|
||||
switch pathErr.Err {
|
||||
case syscall.ENOTEMPTY:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the given error corresponds to the specific ERROR_PATH_NOT_FOUND for windows
|
||||
func isSysErrPathNotFound(err error) bool {
|
||||
if runtime.GOOS != "windows" {
|
||||
return false
|
||||
}
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
if errno, _ok := pathErr.Err.(syscall.Errno); _ok && errno == 0x03 {
|
||||
// ERROR_PATH_NOT_FOUND
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the given error corresponds to the specific ERROR_INVALID_HANDLE for windows
|
||||
func isSysErrHandleInvalid(err error) bool {
|
||||
if runtime.GOOS != "windows" {
|
||||
return false
|
||||
}
|
||||
// Check if err contains ERROR_INVALID_HANDLE errno
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == 0x6 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
23
cmd/posix.go
23
cmd/posix.go
@ -339,12 +339,7 @@ func (s *posix) DeleteVol(volume string) (err error) {
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if strings.Contains(err.Error(), "directory is not empty") {
|
||||
// On windows the string is slightly different, handle it here.
|
||||
return errVolumeNotEmpty
|
||||
} else if strings.Contains(err.Error(), "directory not empty") {
|
||||
// Hopefully for all other operating systems, this is
|
||||
// assumed to be consistent.
|
||||
} else if isSysErrNotEmpty(err) {
|
||||
return errVolumeNotEmpty
|
||||
}
|
||||
return err
|
||||
@ -439,7 +434,7 @@ func (s *posix) ReadAll(volume, path string) (buf []byte, err error) {
|
||||
case syscall.ENOTDIR, syscall.EISDIR:
|
||||
return nil, errFileNotFound
|
||||
default:
|
||||
if strings.Contains(pathErr.Err.Error(), "The handle is invalid") {
|
||||
if isSysErrHandleInvalid(pathErr.Err) {
|
||||
// This case is special and needs to be handled for windows.
|
||||
return nil, errFileNotFound
|
||||
}
|
||||
@ -498,7 +493,7 @@ func (s *posix) ReadFile(volume string, path string, offset int64, buf []byte) (
|
||||
return 0, errFileNotFound
|
||||
} else if os.IsPermission(err) {
|
||||
return 0, errFileAccessDenied
|
||||
} else if strings.Contains(err.Error(), "not a directory") {
|
||||
} else if isSysErrNotDir(err) {
|
||||
return 0, errFileAccessDenied
|
||||
}
|
||||
return 0, err
|
||||
@ -575,9 +570,9 @@ func (s *posix) AppendFile(volume, path string, buf []byte) (err error) {
|
||||
// with mode 0777 mkdir honors system umask.
|
||||
if err = mkdirAll(filepath.Dir(filePath), 0777); err != nil {
|
||||
// File path cannot be verified since one of the parents is a file.
|
||||
if strings.Contains(err.Error(), "not a directory") {
|
||||
if isSysErrNotDir(err) {
|
||||
return errFileAccessDenied
|
||||
} else if runtime.GOOS == "windows" && strings.Contains(err.Error(), "system cannot find the path specified") {
|
||||
} else if isSysErrPathNotFound(err) {
|
||||
// Add specific case for windows.
|
||||
return errFileAccessDenied
|
||||
}
|
||||
@ -589,7 +584,7 @@ func (s *posix) AppendFile(volume, path string, buf []byte) (err error) {
|
||||
w, err := os.OpenFile(preparePath(filePath), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
// File path cannot be verified since one of the parents is a file.
|
||||
if strings.Contains(err.Error(), "not a directory") {
|
||||
if isSysErrNotDir(err) {
|
||||
return errFileAccessDenied
|
||||
}
|
||||
return err
|
||||
@ -645,7 +640,7 @@ func (s *posix) StatFile(volume, path string) (file FileInfo, err error) {
|
||||
}
|
||||
|
||||
// File path cannot be verified since one of the parents is a file.
|
||||
if strings.Contains(err.Error(), "not a directory") {
|
||||
if isSysErrNotDir(err) {
|
||||
return FileInfo{}, errFileNotFound
|
||||
}
|
||||
|
||||
@ -804,9 +799,9 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e
|
||||
// Creates all the parent directories, with mode 0777 mkdir honors system umask.
|
||||
if err = mkdirAll(preparePath(slashpath.Dir(dstFilePath)), 0777); err != nil {
|
||||
// File path cannot be verified since one of the parents is a file.
|
||||
if strings.Contains(err.Error(), "not a directory") {
|
||||
if isSysErrNotDir(err) {
|
||||
return errFileAccessDenied
|
||||
} else if strings.Contains(err.Error(), "The system cannot find the path specified.") && runtime.GOOS == "windows" {
|
||||
} else if isSysErrPathNotFound(err) {
|
||||
// This is a special case should be handled only for
|
||||
// windows, because windows API does not return "not a
|
||||
// directory" error message. Handle this specifically here.
|
||||
|
@ -18,7 +18,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -901,7 +900,7 @@ func TestReadFile(t *testing.T) {
|
||||
return &os.PathError{
|
||||
Op: "seek",
|
||||
Path: preparePath(slashpath.Join(path, "success-vol", "myobject")),
|
||||
Err: errors.New("An attempt was made to move the file pointer before the beginning of the file."),
|
||||
Err: syscall.Errno(0x83), // ERROR_NEGATIVE_SEEK
|
||||
}
|
||||
}
|
||||
return &os.PathError{
|
||||
@ -953,7 +952,24 @@ func TestReadFile(t *testing.T) {
|
||||
if err != nil && testCase.expectedErr != nil {
|
||||
// Validate if the type string of the errors are an exact match.
|
||||
if err.Error() != testCase.expectedErr.Error() {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
} else {
|
||||
var resultErrno, expectErrno uintptr
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
resultErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if pathErr, ok := testCase.expectedErr.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
expectErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if !(expectErrno != 0 && resultErrno != 0 && expectErrno == resultErrno) {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Err unexpected EOF special case, where we verify we have provided a larger
|
||||
// buffer than the data itself, but the results are in-fact valid. So we validate
|
||||
|
Loading…
Reference in New Issue
Block a user