mirror of https://github.com/pkg/sftp.git
				
				
				
			
		
			
				
	
	
		
			110 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| package sftp
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"syscall"
 | |
| )
 | |
| 
 | |
| var EBADF = syscall.NewError("fd out of range or not open")
 | |
| 
 | |
| func wrapPathError(filepath string, err error) error {
 | |
| 	if errno, ok := err.(syscall.ErrorString); ok {
 | |
| 		return &os.PathError{Path: filepath, Err: errno}
 | |
| 	}
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // translateErrno translates a syscall error number to a SFTP error code.
 | |
| func translateErrno(errno syscall.ErrorString) uint32 {
 | |
| 	switch errno {
 | |
| 	case "":
 | |
| 		return sshFxOk
 | |
| 	case syscall.ENOENT:
 | |
| 		return sshFxNoSuchFile
 | |
| 	case syscall.EPERM:
 | |
| 		return sshFxPermissionDenied
 | |
| 	}
 | |
| 
 | |
| 	return sshFxFailure
 | |
| }
 | |
| 
 | |
| func translateSyscallError(err error) (uint32, bool) {
 | |
| 	switch e := err.(type) {
 | |
| 	case syscall.ErrorString:
 | |
| 		return translateErrno(e), true
 | |
| 	case *os.PathError:
 | |
| 		debug("statusFromError,pathError: error is %T %#v", e.Err, e.Err)
 | |
| 		if errno, ok := e.Err.(syscall.ErrorString); ok {
 | |
| 			return translateErrno(errno), true
 | |
| 		}
 | |
| 	}
 | |
| 	return 0, false
 | |
| }
 | |
| 
 | |
| // isRegular returns true if the mode describes a regular file.
 | |
| func isRegular(mode uint32) bool {
 | |
| 	return mode&S_IFMT == syscall.S_IFREG
 | |
| }
 | |
| 
 | |
| // toFileMode converts sftp filemode bits to the os.FileMode specification
 | |
| func toFileMode(mode uint32) os.FileMode {
 | |
| 	var fm = os.FileMode(mode & 0777)
 | |
| 	switch mode & S_IFMT {
 | |
| 	case syscall.S_IFBLK:
 | |
| 		fm |= os.ModeDevice
 | |
| 	case syscall.S_IFCHR:
 | |
| 		fm |= os.ModeDevice | os.ModeCharDevice
 | |
| 	case syscall.S_IFDIR:
 | |
| 		fm |= os.ModeDir
 | |
| 	case syscall.S_IFIFO:
 | |
| 		fm |= os.ModeNamedPipe
 | |
| 	case syscall.S_IFLNK:
 | |
| 		fm |= os.ModeSymlink
 | |
| 	case syscall.S_IFREG:
 | |
| 		// nothing to do
 | |
| 	case syscall.S_IFSOCK:
 | |
| 		fm |= os.ModeSocket
 | |
| 	}
 | |
| 	return fm
 | |
| }
 | |
| 
 | |
| // fromFileMode converts from the os.FileMode specification to sftp filemode bits
 | |
| func fromFileMode(mode os.FileMode) uint32 {
 | |
| 	ret := uint32(0)
 | |
| 
 | |
| 	if mode&os.ModeDevice != 0 {
 | |
| 		if mode&os.ModeCharDevice != 0 {
 | |
| 			ret |= syscall.S_IFCHR
 | |
| 		} else {
 | |
| 			ret |= syscall.S_IFBLK
 | |
| 		}
 | |
| 	}
 | |
| 	if mode&os.ModeDir != 0 {
 | |
| 		ret |= syscall.S_IFDIR
 | |
| 	}
 | |
| 	if mode&os.ModeSymlink != 0 {
 | |
| 		ret |= syscall.S_IFLNK
 | |
| 	}
 | |
| 	if mode&os.ModeNamedPipe != 0 {
 | |
| 		ret |= syscall.S_IFIFO
 | |
| 	}
 | |
| 	if mode&os.ModeSocket != 0 {
 | |
| 		ret |= syscall.S_IFSOCK
 | |
| 	}
 | |
| 
 | |
| 	if mode&os.ModeType == 0 {
 | |
| 		ret |= syscall.S_IFREG
 | |
| 	}
 | |
| 	ret |= uint32(mode & os.ModePerm)
 | |
| 
 | |
| 	return ret
 | |
| }
 | |
| 
 | |
| // Plan 9 doesn't have setuid, setgid or sticky, but a Plan 9 client should
 | |
| // be able to send these bits to a POSIX server.
 | |
| const (
 | |
| 	s_ISUID = 04000
 | |
| 	s_ISGID = 02000
 | |
| 	s_ISVTX = 01000
 | |
| )
 |