github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/errors.go (about)

     1  //
     2  //  Copyright 2021 The AVFS authors
     3  //
     4  //  Licensed under the Apache License, Version 2.0 (the "License");
     5  //  you may not use this file except in compliance with the License.
     6  //  You may obtain a copy of the License at
     7  //
     8  //  	http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  //  Unless required by applicable law or agreed to in writing, software
    11  //  distributed under the License is distributed on an "AS IS" BASIS,
    12  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  //  See the License for the specific language governing permissions and
    14  //  limitations under the License.
    15  //
    16  
    17  package avfs
    18  
    19  import (
    20  	"io/fs"
    21  	"reflect"
    22  	"strconv"
    23  )
    24  
    25  // AlreadyExistsGroupError is returned when the group name already exists.
    26  type AlreadyExistsGroupError string
    27  
    28  func (e AlreadyExistsGroupError) Error() string {
    29  	return "group: group " + string(e) + " already exists"
    30  }
    31  
    32  // AlreadyExistsUserError is returned when the user name already exists.
    33  type AlreadyExistsUserError string
    34  
    35  func (e AlreadyExistsUserError) Error() string {
    36  	return "user: user " + string(e) + " already exists"
    37  }
    38  
    39  // UnknownError is returned when there is an unknown error.
    40  type UnknownError string
    41  
    42  func (e UnknownError) Error() string {
    43  	return "unknown error " + reflect.TypeOf(e).String() + " : '" + string(e) + "'"
    44  }
    45  
    46  // UnknownGroupError is returned by LookupGroup when a group cannot be found.
    47  type UnknownGroupError string
    48  
    49  func (e UnknownGroupError) Error() string {
    50  	return "group: unknown group " + string(e)
    51  }
    52  
    53  // UnknownGroupIdError is returned by LookupGroupId when a group cannot be found.
    54  type UnknownGroupIdError int
    55  
    56  func (e UnknownGroupIdError) Error() string {
    57  	return "group: unknown groupid " + strconv.Itoa(int(e))
    58  }
    59  
    60  // UnknownUserError is returned by Lookup when a user cannot be found.
    61  type UnknownUserError string
    62  
    63  func (e UnknownUserError) Error() string {
    64  	return "user: unknown user " + string(e)
    65  }
    66  
    67  // UnknownUserIdError is returned by LookupUserId when a user cannot be found.
    68  type UnknownUserIdError int
    69  
    70  func (e UnknownUserIdError) Error() string {
    71  	return "user: unknown userid " + strconv.Itoa(int(e))
    72  }
    73  
    74  // ErrorIdentifier is the interface that wraps the Is method of an error.
    75  type ErrorIdentifier interface {
    76  	error
    77  
    78  	// Is returns true if the error can be treated as equivalent to a target error.
    79  	// target is one of fs.ErrPermission, fs.ErrExist, fs.ErrNotExist.
    80  	Is(target error) bool
    81  }
    82  
    83  const customErrorBase = 2 << 30
    84  
    85  type CustomError uintptr
    86  
    87  //go:generate stringer -type CustomError -linecomment -output errors_custom.go
    88  
    89  const (
    90  	ErrNegativeOffset      CustomError = customErrorBase + 1 // negative offset
    91  	ErrFileClosing         CustomError = customErrorBase + 2 // use of closed file
    92  	ErrPatternHasSeparator CustomError = customErrorBase + 3 // pattern contains path separator
    93  	ErrVolumeAlreadyExists CustomError = customErrorBase + 4 // Volume already exists.
    94  	ErrVolumeNameInvalid   CustomError = customErrorBase + 5 // Volume name is invalid.
    95  	ErrVolumeWindows       CustomError = customErrorBase + 6 // Volumes are available for Windows only.
    96  )
    97  
    98  func (i CustomError) Error() string {
    99  	return i.String()
   100  }
   101  
   102  // LinuxError replaces syscall.Errno for Linux operating systems.
   103  type LinuxError uintptr
   104  
   105  //go:generate stringer -type LinuxError -linecomment -output errors_forlinux.go
   106  
   107  // Errors for Linux operating systems.
   108  // See https://github.com/torvalds/linux/blob/master/tools/include/uapi/asm-generic/errno-base.h
   109  const (
   110  	ErrBadFileDesc     LinuxError = errEBADF     // bad file descriptor
   111  	ErrCrossDevLink    LinuxError = errEXDEV     // invalid cross-device link
   112  	ErrDirNotEmpty     LinuxError = errENOTEMPTY // directory not empty
   113  	ErrFileExists      LinuxError = errEEXIST    // file exists
   114  	ErrInvalidArgument LinuxError = errEINVAL    // invalid argument
   115  	ErrIsADirectory    LinuxError = errEISDIR    // is a directory
   116  	ErrNoSuchFileOrDir LinuxError = errENOENT    // no such file or directory
   117  	ErrNotADirectory   LinuxError = errENOTDIR   // not a directory
   118  	ErrOpNotPermitted  LinuxError = errEPERM     // operation not permitted
   119  	ErrPermDenied      LinuxError = errEACCES    // permission denied
   120  	ErrTooManySymlinks LinuxError = errELOOP     // too many levels of symbolic links
   121  
   122  	errEACCES    = 0xd
   123  	errEBADF     = 0x9
   124  	errEEXIST    = 0x11
   125  	errEINVAL    = 0x16
   126  	errEISDIR    = 0x15
   127  	errENOENT    = 0x2
   128  	errELOOP     = 0x28
   129  	errENOTDIR   = 0x14
   130  	errENOTEMPTY = 0x27
   131  	errEPERM     = 0x1
   132  	errEXDEV     = 0x12
   133  )
   134  
   135  // Error returns the error string of the Linux operating system.
   136  func (i LinuxError) Error() string {
   137  	return i.String()
   138  }
   139  
   140  // Is returns true if the LinuxError can be treated as equivalent to a target error.
   141  // target is one of fs.ErrPermission, fs.ErrExist, fs.ErrNotExist.
   142  func (i LinuxError) Is(target error) bool {
   143  	switch target {
   144  	case fs.ErrPermission:
   145  		return i == ErrPermDenied || i == ErrOpNotPermitted
   146  	case fs.ErrExist:
   147  		return i == ErrFileExists || i == ErrDirNotEmpty
   148  	case fs.ErrNotExist:
   149  		return i == ErrNoSuchFileOrDir
   150  	}
   151  
   152  	return false
   153  }
   154  
   155  // WindowsError replaces syscall.Errno for Windows operating systems.
   156  type WindowsError uintptr
   157  
   158  //go:generate stringer -type WindowsError -linecomment -output errors_forwindows.go
   159  
   160  // Errors for Windows operating systems.
   161  // See https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
   162  const (
   163  	ErrWinAccessDenied     WindowsError = 5          // Access is denied.
   164  	ErrWinAlreadyExists    WindowsError = 183        // Cannot create a file when that file already exists.
   165  	ErrWinBadNetPath       WindowsError = 53         // Bad network path.
   166  	ErrWinDirNameInvalid   WindowsError = 0x10B      // The directory name is invalid.
   167  	ErrWinDirNotEmpty      WindowsError = 145        // The directory is not empty.
   168  	ErrWinFileExists       WindowsError = 80         // The file exists.
   169  	ErrWinFileNotFound     WindowsError = 2          // The system cannot find the file specified.
   170  	ErrWinIncorrectFunc    WindowsError = 1          // Incorrect function.
   171  	ErrWinIsADirectory     WindowsError = 21         // is a directory
   172  	ErrWinNegativeSeek     WindowsError = 0x83       // An attempt was made to move the file pointer before the beginning of the file.
   173  	ErrWinNotReparsePoint  WindowsError = 4390       // The file or directory is not a reparse point.
   174  	ErrWinInvalidHandle    WindowsError = 6          // The handle is invalid.
   175  	ErrWinSharingViolation WindowsError = 32         // The process cannot access the file because it is being used by another process.
   176  	ErrWinNotSupported     WindowsError = 0x20000082 // not supported by windows
   177  	ErrWinPathNotFound     WindowsError = 3          // The system cannot find the path specified.
   178  	ErrWinPrivilegeNotHeld WindowsError = 1314       // A required privilege is not held by the client.
   179  )
   180  
   181  // Error returns the error string of the Windows operating system.
   182  func (i WindowsError) Error() string {
   183  	return i.String()
   184  }
   185  
   186  // Is returns true if the WindowsError can be treated as equivalent to a target error.
   187  // target is one of fs.ErrPermission, fs.ErrExist, fs.ErrNotExist.
   188  func (i WindowsError) Is(target error) bool {
   189  	switch target {
   190  	case fs.ErrPermission:
   191  		return i == ErrWinAccessDenied
   192  	case fs.ErrExist:
   193  		return i == ErrWinAlreadyExists || i == ErrWinDirNotEmpty || i == ErrWinFileExists
   194  	case fs.ErrNotExist:
   195  		return i == ErrWinFileNotFound || i == ErrWinBadNetPath || i == ErrWinPathNotFound
   196  	}
   197  
   198  	return false
   199  }
   200  
   201  // Errors regroups errors depending on the OS emulated.
   202  type Errors struct {
   203  	BadFileDesc     error // bad file descriptor.
   204  	DirNotEmpty     error // Directory not empty.
   205  	FileExists      error // File exists.
   206  	InvalidArgument error // invalid argument
   207  	IsADirectory    error // File Is a directory.
   208  	NoSuchDir       error // No such directory.
   209  	NoSuchFile      error // No such file.
   210  	NotADirectory   error // Not a directory.
   211  	OpNotPermitted  error // operation not permitted.
   212  	PermDenied      error // Permission denied.
   213  	TooManySymlinks error // Too many levels of symbolic links.
   214  }
   215  
   216  // SetOSType sets errors depending on the operating system.
   217  func (e *Errors) SetOSType(osType OSType) {
   218  	switch osType {
   219  	case OsWindows:
   220  		e.BadFileDesc = ErrWinAccessDenied
   221  		e.DirNotEmpty = ErrWinDirNotEmpty
   222  		e.FileExists = ErrWinFileExists
   223  		e.InvalidArgument = ErrWinNegativeSeek
   224  		e.IsADirectory = ErrWinIsADirectory
   225  		e.NoSuchDir = ErrWinPathNotFound
   226  		e.NoSuchFile = ErrWinFileNotFound
   227  		e.NotADirectory = ErrWinPathNotFound
   228  		e.OpNotPermitted = ErrWinNotSupported
   229  		e.PermDenied = ErrWinAccessDenied
   230  		e.TooManySymlinks = ErrTooManySymlinks
   231  	default:
   232  		e.BadFileDesc = ErrBadFileDesc
   233  		e.DirNotEmpty = ErrDirNotEmpty
   234  		e.FileExists = ErrFileExists
   235  		e.InvalidArgument = ErrInvalidArgument
   236  		e.IsADirectory = ErrIsADirectory
   237  		e.NoSuchDir = ErrNoSuchFileOrDir
   238  		e.NoSuchFile = ErrNoSuchFileOrDir
   239  		e.NotADirectory = ErrNotADirectory
   240  		e.OpNotPermitted = ErrOpNotPermitted
   241  		e.PermDenied = ErrPermDenied
   242  		e.TooManySymlinks = ErrTooManySymlinks
   243  	}
   244  }