github.com/pkg/sftp@v1.13.6/stat_posix.go (about)

     1  //go:build !plan9
     2  // +build !plan9
     3  
     4  package sftp
     5  
     6  import (
     7  	"os"
     8  	"syscall"
     9  )
    10  
    11  const EBADF = syscall.EBADF
    12  
    13  func wrapPathError(filepath string, err error) error {
    14  	if errno, ok := err.(syscall.Errno); ok {
    15  		return &os.PathError{Path: filepath, Err: errno}
    16  	}
    17  	return err
    18  }
    19  
    20  // translateErrno translates a syscall error number to a SFTP error code.
    21  func translateErrno(errno syscall.Errno) uint32 {
    22  	switch errno {
    23  	case 0:
    24  		return sshFxOk
    25  	case syscall.ENOENT:
    26  		return sshFxNoSuchFile
    27  	case syscall.EACCES, syscall.EPERM:
    28  		return sshFxPermissionDenied
    29  	}
    30  
    31  	return sshFxFailure
    32  }
    33  
    34  func translateSyscallError(err error) (uint32, bool) {
    35  	switch e := err.(type) {
    36  	case syscall.Errno:
    37  		return translateErrno(e), true
    38  	case *os.PathError:
    39  		debug("statusFromError,pathError: error is %T %#v", e.Err, e.Err)
    40  		if errno, ok := e.Err.(syscall.Errno); ok {
    41  			return translateErrno(errno), true
    42  		}
    43  	}
    44  	return 0, false
    45  }
    46  
    47  // isRegular returns true if the mode describes a regular file.
    48  func isRegular(mode uint32) bool {
    49  	return mode&S_IFMT == syscall.S_IFREG
    50  }
    51  
    52  // toFileMode converts sftp filemode bits to the os.FileMode specification
    53  func toFileMode(mode uint32) os.FileMode {
    54  	var fm = os.FileMode(mode & 0777)
    55  
    56  	switch mode & S_IFMT {
    57  	case syscall.S_IFBLK:
    58  		fm |= os.ModeDevice
    59  	case syscall.S_IFCHR:
    60  		fm |= os.ModeDevice | os.ModeCharDevice
    61  	case syscall.S_IFDIR:
    62  		fm |= os.ModeDir
    63  	case syscall.S_IFIFO:
    64  		fm |= os.ModeNamedPipe
    65  	case syscall.S_IFLNK:
    66  		fm |= os.ModeSymlink
    67  	case syscall.S_IFREG:
    68  		// nothing to do
    69  	case syscall.S_IFSOCK:
    70  		fm |= os.ModeSocket
    71  	}
    72  
    73  	if mode&syscall.S_ISUID != 0 {
    74  		fm |= os.ModeSetuid
    75  	}
    76  	if mode&syscall.S_ISGID != 0 {
    77  		fm |= os.ModeSetgid
    78  	}
    79  	if mode&syscall.S_ISVTX != 0 {
    80  		fm |= os.ModeSticky
    81  	}
    82  
    83  	return fm
    84  }
    85  
    86  // fromFileMode converts from the os.FileMode specification to sftp filemode bits
    87  func fromFileMode(mode os.FileMode) uint32 {
    88  	ret := uint32(mode & os.ModePerm)
    89  
    90  	switch mode & os.ModeType {
    91  	case os.ModeDevice | os.ModeCharDevice:
    92  		ret |= syscall.S_IFCHR
    93  	case os.ModeDevice:
    94  		ret |= syscall.S_IFBLK
    95  	case os.ModeDir:
    96  		ret |= syscall.S_IFDIR
    97  	case os.ModeNamedPipe:
    98  		ret |= syscall.S_IFIFO
    99  	case os.ModeSymlink:
   100  		ret |= syscall.S_IFLNK
   101  	case 0:
   102  		ret |= syscall.S_IFREG
   103  	case os.ModeSocket:
   104  		ret |= syscall.S_IFSOCK
   105  	}
   106  
   107  	if mode&os.ModeSetuid != 0 {
   108  		ret |= syscall.S_ISUID
   109  	}
   110  	if mode&os.ModeSetgid != 0 {
   111  		ret |= syscall.S_ISGID
   112  	}
   113  	if mode&os.ModeSticky != 0 {
   114  		ret |= syscall.S_ISVTX
   115  	}
   116  
   117  	return ret
   118  }
   119  
   120  const (
   121  	s_ISUID = syscall.S_ISUID
   122  	s_ISGID = syscall.S_ISGID
   123  	s_ISVTX = syscall.S_ISVTX
   124  )