stat_posix.go 2.5 KB

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