stat_plan9.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package sftp
  2. import (
  3. "os"
  4. "syscall"
  5. )
  6. var EBADF = syscall.NewError("fd out of range or not open")
  7. func wrapPathError(filepath string, err error) error {
  8. if errno, ok := err.(syscall.ErrorString); ok {
  9. return &os.PathError{Path: filepath, Err: errno}
  10. }
  11. return err
  12. }
  13. // translateErrno translates a syscall error number to a SFTP error code.
  14. func translateErrno(errno syscall.ErrorString) uint32 {
  15. switch errno {
  16. case "":
  17. return sshFxOk
  18. case syscall.ENOENT:
  19. return sshFxNoSuchFile
  20. case syscall.EPERM:
  21. return sshFxPermissionDenied
  22. }
  23. return sshFxFailure
  24. }
  25. func translateSyscallError(err error) (uint32, bool) {
  26. switch e := err.(type) {
  27. case syscall.ErrorString:
  28. return translateErrno(e), true
  29. case *os.PathError:
  30. debug("statusFromError,pathError: error is %T %#v", e.Err, e.Err)
  31. if errno, ok := e.Err.(syscall.ErrorString); ok {
  32. return translateErrno(errno), true
  33. }
  34. }
  35. return 0, false
  36. }
  37. // isRegular returns true if the mode describes a regular file.
  38. func isRegular(mode uint32) bool {
  39. return mode&S_IFMT == syscall.S_IFREG
  40. }
  41. // toFileMode converts sftp filemode bits to the os.FileMode specification
  42. func toFileMode(mode uint32) os.FileMode {
  43. var fm = os.FileMode(mode & 0777)
  44. switch mode & S_IFMT {
  45. case syscall.S_IFBLK:
  46. fm |= os.ModeDevice
  47. case syscall.S_IFCHR:
  48. fm |= os.ModeDevice | os.ModeCharDevice
  49. case syscall.S_IFDIR:
  50. fm |= os.ModeDir
  51. case syscall.S_IFIFO:
  52. fm |= os.ModeNamedPipe
  53. case syscall.S_IFLNK:
  54. fm |= os.ModeSymlink
  55. case syscall.S_IFREG:
  56. // nothing to do
  57. case syscall.S_IFSOCK:
  58. fm |= os.ModeSocket
  59. }
  60. return fm
  61. }
  62. // fromFileMode converts from the os.FileMode specification to sftp filemode bits
  63. func fromFileMode(mode os.FileMode) uint32 {
  64. ret := uint32(mode & os.ModePerm)
  65. switch mode & os.ModeType {
  66. case os.ModeDevice | os.ModeCharDevice:
  67. ret |= syscall.S_IFCHR
  68. case os.ModeDevice:
  69. ret |= syscall.S_IFBLK
  70. case os.ModeDir:
  71. ret |= syscall.S_IFDIR
  72. case os.ModeNamedPipe:
  73. ret |= syscall.S_IFIFO
  74. case os.ModeSymlink:
  75. ret |= syscall.S_IFLNK
  76. case 0:
  77. ret |= syscall.S_IFREG
  78. case os.ModeSocket:
  79. ret |= syscall.S_IFSOCK
  80. }
  81. return ret
  82. }
  83. // Plan 9 doesn't have setuid, setgid or sticky, but a Plan 9 client should
  84. // be able to send these bits to a POSIX server.
  85. const (
  86. s_ISUID = 04000
  87. s_ISGID = 02000
  88. s_ISVTX = 01000
  89. )