diff --git a/client.go b/client.go index 9423b4d..3894d39 100644 --- a/client.go +++ b/client.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + iofs "io/fs" "math" "os" "path" @@ -2142,7 +2143,7 @@ func toPflags(f int) uint32 { // setuid, setgid and sticky in m, because we've historically supported those // bits, and we mask off any non-permission bits. func toChmodPerm(m os.FileMode) (perm uint32) { - const mask = os.ModePerm | s_ISUID | s_ISGID | s_ISVTX + const mask = os.ModePerm | iofs.FileMode(s_ISUID|s_ISGID|s_ISVTX) perm = uint32(m & mask) if m&os.ModeSetuid != 0 { diff --git a/client_integration_test.go b/client_integration_test.go index 35ccbea..c9039a5 100644 --- a/client_integration_test.go +++ b/client_integration_test.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + iofs "io/fs" "io/ioutil" "math/rand" "net" @@ -974,7 +975,7 @@ func TestClientSetuid(t *testing.T) { f.Close() const allPerm = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky | - s_ISUID | s_ISGID | s_ISVTX + iofs.FileMode(s_ISUID|s_ISGID|s_ISVTX) for _, c := range []struct { goPerm os.FileMode diff --git a/stat_posix.go b/stat_posix.go index a15b9c3..891b240 100644 --- a/stat_posix.go +++ b/stat_posix.go @@ -1,12 +1,13 @@ -//go:build !plan9 && !zos +//go:build !plan9 // +build !plan9 -// +build !zos package sftp import ( "os" "syscall" + + sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer" ) const EBADF = syscall.EBADF @@ -47,37 +48,37 @@ func translateSyscallError(err error) (uint32, bool) { // isRegular returns true if the mode describes a regular file. func isRegular(mode uint32) bool { - return mode&S_IFMT == syscall.S_IFREG + return sshfx.FileMode(mode)&sshfx.ModeType == sshfx.ModeRegular } // 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: + switch sshfx.FileMode(mode) & sshfx.ModeType { + case sshfx.ModeDevice: fm |= os.ModeDevice - case syscall.S_IFCHR: + case sshfx.ModeCharDevice: fm |= os.ModeDevice | os.ModeCharDevice - case syscall.S_IFDIR: + case sshfx.ModeDir: fm |= os.ModeDir - case syscall.S_IFIFO: + case sshfx.ModeNamedPipe: fm |= os.ModeNamedPipe - case syscall.S_IFLNK: + case sshfx.ModeSymlink: fm |= os.ModeSymlink - case syscall.S_IFREG: + case sshfx.ModeRegular: // nothing to do - case syscall.S_IFSOCK: + case sshfx.ModeSocket: fm |= os.ModeSocket } - if mode&syscall.S_ISUID != 0 { + if sshfx.FileMode(mode)&sshfx.ModeSetUID != 0 { fm |= os.ModeSetuid } - if mode&syscall.S_ISGID != 0 { + if sshfx.FileMode(mode)&sshfx.ModeSetGID != 0 { fm |= os.ModeSetgid } - if mode&syscall.S_ISVTX != 0 { + if sshfx.FileMode(mode)&sshfx.ModeSticky != 0 { fm |= os.ModeSticky } @@ -86,40 +87,40 @@ func toFileMode(mode uint32) os.FileMode { // fromFileMode converts from the os.FileMode specification to sftp filemode bits func fromFileMode(mode os.FileMode) uint32 { - ret := uint32(mode & os.ModePerm) + ret := sshfx.FileMode(mode & os.ModePerm) switch mode & os.ModeType { case os.ModeDevice | os.ModeCharDevice: - ret |= syscall.S_IFCHR + ret |= sshfx.ModeCharDevice case os.ModeDevice: - ret |= syscall.S_IFBLK + ret |= sshfx.ModeDevice case os.ModeDir: - ret |= syscall.S_IFDIR + ret |= sshfx.ModeDir case os.ModeNamedPipe: - ret |= syscall.S_IFIFO + ret |= sshfx.ModeNamedPipe case os.ModeSymlink: - ret |= syscall.S_IFLNK + ret |= sshfx.ModeSymlink case 0: - ret |= syscall.S_IFREG + ret |= sshfx.ModeRegular case os.ModeSocket: - ret |= syscall.S_IFSOCK + ret |= sshfx.ModeSocket } if mode&os.ModeSetuid != 0 { - ret |= syscall.S_ISUID + ret |= sshfx.ModeSetUID } if mode&os.ModeSetgid != 0 { - ret |= syscall.S_ISGID + ret |= sshfx.ModeSetGID } if mode&os.ModeSticky != 0 { - ret |= syscall.S_ISVTX + ret |= sshfx.ModeSticky } - return ret + return uint32(ret) } const ( - s_ISUID = syscall.S_ISUID - s_ISGID = syscall.S_ISGID - s_ISVTX = syscall.S_ISVTX + s_ISUID = uint32(sshfx.ModeSetUID) + s_ISGID = uint32(sshfx.ModeSetGID) + s_ISVTX = uint32(sshfx.ModeSticky) ) diff --git a/stat_zos.go b/stat_zos.go deleted file mode 100644 index 3643e5e..0000000 --- a/stat_zos.go +++ /dev/null @@ -1,137 +0,0 @@ -//go:build zos -// +build zos - -package sftp - -import ( - "os" - "syscall" -) - -const EBADF = syscall.EBADF - -// z/OS syscall constants are not compatible with the stat structure returned -// from the server. Define the OpenBSD ones here instead. -const ( - S_IFMT = 0xF000 - S_IFIFO = 0x1000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFBLK = 0x6000 - S_IFREG = 0x8000 - S_IFLNK = 0xA000 - S_IFSOCK = 0xC000 -) - -func wrapPathError(filepath string, err error) error { - if errno, ok := err.(syscall.Errno); 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.Errno) uint32 { - switch errno { - case 0: - return sshFxOk - case syscall.ENOENT: - return sshFxNoSuchFile - case syscall.EACCES, syscall.EPERM: - 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 -} - -// isRegular returns true if the mode describes a regular file. -func isRegular(mode uint32) bool { - return mode&S_IFMT == 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 S_IFBLK: - fm |= os.ModeDevice - case S_IFCHR: - fm |= os.ModeDevice | os.ModeCharDevice - case S_IFDIR: - fm |= os.ModeDir - case S_IFIFO: - fm |= os.ModeNamedPipe - case S_IFLNK: - fm |= os.ModeSymlink - case S_IFREG: - // nothing to do - case S_IFSOCK: - fm |= os.ModeSocket - } - - if mode&syscall.S_ISUID != 0 { - fm |= os.ModeSetuid - } - if mode&syscall.S_ISGID != 0 { - fm |= os.ModeSetgid - } - if mode&syscall.S_ISVTX != 0 { - fm |= os.ModeSticky - } - - 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 |= S_IFCHR - case os.ModeDevice: - ret |= S_IFBLK - case os.ModeDir: - ret |= S_IFDIR - case os.ModeNamedPipe: - ret |= S_IFIFO - case os.ModeSymlink: - ret |= S_IFLNK - case 0: - ret |= S_IFREG - case os.ModeSocket: - ret |= S_IFSOCK - } - - if mode&os.ModeSetuid != 0 { - ret |= syscall.S_ISUID - } - if mode&os.ModeSetgid != 0 { - ret |= syscall.S_ISGID - } - if mode&os.ModeSticky != 0 { - ret |= syscall.S_ISVTX - } - - return ret -} - -const ( - s_ISUID = syscall.S_ISUID - s_ISGID = syscall.S_ISGID - s_ISVTX = syscall.S_ISVTX -) diff --git a/syscall_fixed.go b/syscall_fixed.go index e844308..0f80dd5 100644 --- a/syscall_fixed.go +++ b/syscall_fixed.go @@ -1,10 +1,9 @@ -//go:build plan9 || windows || (js && wasm) -// +build plan9 windows js,wasm - // Go defines S_IFMT on windows, plan9 and js/wasm as 0x1f000 instead of // 0xf000. None of the the other S_IFxyz values include the "1" (in 0x1f000) // which prevents them from matching the bitmask. package sftp -const S_IFMT = 0xf000 +import sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer" + +const S_IFMT = uint32(sshfx.ModeType) diff --git a/syscall_good.go b/syscall_good.go deleted file mode 100644 index 235d603..0000000 --- a/syscall_good.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !plan9 && !windows && !zos && (!js || !wasm) -// +build !plan9 -// +build !windows -// +build !zos -// +build !js !wasm - -package sftp - -import "syscall" - -const S_IFMT = syscall.S_IFMT