2019-06-20 02:48:39 +08:00
|
|
|
//go:build !plan9
|
2020-09-11 00:11:47 +08:00
|
|
|
// +build !plan9
|
|
|
|
|
|
|
|
package sftp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
const EBADF = syscall.EBADF
|
|
|
|
|
|
|
|
func wrapPathError(filepath string, err error) error {
|
2020-09-16 06:43:45 +08:00
|
|
|
if errno, ok := err.(syscall.Errno); ok {
|
2020-09-17 17:54:29 +08:00
|
|
|
return &os.PathError{Path: filepath, Err: errno}
|
2020-09-11 00:11:47 +08:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// translateErrno translates a syscall error number to a SFTP error code.
|
|
|
|
func translateErrno(errno syscall.Errno) uint32 {
|
|
|
|
switch errno {
|
|
|
|
case 0:
|
|
|
|
return sshFxOk
|
|
|
|
case syscall.ENOENT:
|
|
|
|
return sshFxNoSuchFile
|
2019-06-20 02:48:39 +08:00
|
|
|
case syscall.EACCES, syscall.EPERM:
|
2020-09-11 00:11:47 +08:00
|
|
|
return sshFxPermissionDenied
|
|
|
|
}
|
|
|
|
|
|
|
|
return sshFxFailure
|
|
|
|
}
|
|
|
|
|
|
|
|
func translateSyscallError(err error) (uint32, bool) {
|
|
|
|
switch e := err.(type) {
|
|
|
|
case syscall.Errno:
|
|
|
|
return translateErrno(e), true
|
|
|
|
case *os.PathError:
|
|
|
|
debug("statusFromError,pathError: error is %T %#v", e.Err, e.Err)
|
|
|
|
if errno, ok := e.Err.(syscall.Errno); ok {
|
|
|
|
return translateErrno(errno), true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
2021-04-27 00:51:04 +08:00
|
|
|
// isRegular returns true if the mode describes a regular file.
|
|
|
|
func isRegular(mode uint32) bool {
|
|
|
|
return mode&S_IFMT == syscall.S_IFREG
|
|
|
|
}
|
|
|
|
|
2020-09-11 00:11:47 +08:00
|
|
|
// toFileMode converts sftp filemode bits to the os.FileMode specification
|
|
|
|
func toFileMode(mode uint32) os.FileMode {
|
|
|
|
var fm = os.FileMode(mode & 0777)
|
2021-08-11 21:10:07 +08:00
|
|
|
|
2020-09-11 00:11:47 +08:00
|
|
|
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
|
|
|
|
}
|
2021-08-11 21:10:07 +08:00
|
|
|
|
2020-09-11 00:11:47 +08:00
|
|
|
if mode&syscall.S_ISUID != 0 {
|
|
|
|
fm |= os.ModeSetuid
|
|
|
|
}
|
2021-08-11 21:10:07 +08:00
|
|
|
if mode&syscall.S_ISGID != 0 {
|
|
|
|
fm |= os.ModeSetgid
|
|
|
|
}
|
2020-09-11 00:11:47 +08:00
|
|
|
if mode&syscall.S_ISVTX != 0 {
|
|
|
|
fm |= os.ModeSticky
|
|
|
|
}
|
2021-08-11 21:10:07 +08:00
|
|
|
|
2020-09-11 00:11:47 +08:00
|
|
|
return fm
|
|
|
|
}
|
|
|
|
|
|
|
|
// fromFileMode converts from the os.FileMode specification to sftp filemode bits
|
|
|
|
func fromFileMode(mode os.FileMode) uint32 {
|
2021-08-11 21:10:07 +08:00
|
|
|
ret := uint32(mode & os.ModePerm)
|
2020-09-11 00:11:47 +08:00
|
|
|
|
2021-08-11 21:10:07 +08:00
|
|
|
switch mode & os.ModeType {
|
|
|
|
case os.ModeDevice | os.ModeCharDevice:
|
|
|
|
ret |= syscall.S_IFCHR
|
|
|
|
case os.ModeDevice:
|
|
|
|
ret |= syscall.S_IFBLK
|
|
|
|
case os.ModeDir:
|
2020-09-11 00:11:47 +08:00
|
|
|
ret |= syscall.S_IFDIR
|
2021-08-11 21:10:07 +08:00
|
|
|
case os.ModeNamedPipe:
|
|
|
|
ret |= syscall.S_IFIFO
|
|
|
|
case os.ModeSymlink:
|
2020-09-11 00:11:47 +08:00
|
|
|
ret |= syscall.S_IFLNK
|
2021-08-11 21:10:07 +08:00
|
|
|
case 0:
|
|
|
|
ret |= syscall.S_IFREG
|
|
|
|
case os.ModeSocket:
|
|
|
|
ret |= syscall.S_IFSOCK
|
2020-09-11 00:11:47 +08:00
|
|
|
}
|
2021-08-11 21:10:07 +08:00
|
|
|
|
|
|
|
if mode&os.ModeSetuid != 0 {
|
|
|
|
ret |= syscall.S_ISUID
|
2020-09-11 00:11:47 +08:00
|
|
|
}
|
|
|
|
if mode&os.ModeSetgid != 0 {
|
|
|
|
ret |= syscall.S_ISGID
|
|
|
|
}
|
|
|
|
if mode&os.ModeSticky != 0 {
|
|
|
|
ret |= syscall.S_ISVTX
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
Support os.Mode{Setuid,Setgid,Sticky} in Chmod
Previously, these bits were ignored by Chmod, which sent the numerical
value of the mode argument as-is to the server. As a result, callers had
to supply POSIX values for setuid, setgid and sticky to Chmod.
The new version supports both the POSIX values and the Go values.
Also added a note to the docs to clarify that the umask is not
subtracted from the mode, and why that is. The only portable way to get
the umask is to set it, then reset it, but that's racy. On Linux, we
could parse /proc/self/status, but that doesn't work portably and will
fail where /proc is not available (some Docker containers, notably).
2021-03-12 00:37:08 +08:00
|
|
|
|
|
|
|
const (
|
|
|
|
s_ISUID = syscall.S_ISUID
|
|
|
|
s_ISGID = syscall.S_ISGID
|
|
|
|
s_ISVTX = syscall.S_ISVTX
|
|
|
|
)
|