| 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(mode & os.ModePerm) |
| |
| switch mode & os.ModeType { |
| case os.ModeDevice | os.ModeCharDevice: |
| ret |= syscall.S_IFCHR |
| case os.ModeDevice: |
| ret |= syscall.S_IFBLK |
| case os.ModeDir: |
| ret |= syscall.S_IFDIR |
| case os.ModeNamedPipe: |
| ret |= syscall.S_IFIFO |
| case os.ModeSymlink: |
| ret |= syscall.S_IFLNK |
| case 0: |
| ret |= syscall.S_IFREG |
| case os.ModeSocket: |
| ret |= syscall.S_IFSOCK |
| } |
| |
| 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 |
| ) |