Merge pull request #445 from pkg/bugfix/windows-server-paths

[bugfix] Windows paths don’t work with Server
This commit is contained in:
Cassondra Foesch 2021-06-30 17:18:14 +00:00 committed by GitHub
commit 35cb1f0616
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 15 deletions

View File

@ -2,7 +2,11 @@
package sftp
import "syscall"
import (
"path"
"path/filepath"
"syscall"
)
func fakeFileInfoSys() interface{} {
return &syscall.Dir{}
@ -11,3 +15,20 @@ func fakeFileInfoSys() interface{} {
func testOsSys(sys interface{}) error {
return nil
}
func toLocalPath(p string) string {
lp := filepath.FromSlash(p)
if path.IsAbs(p) {
tmp := lp[1:]
if filepath.IsAbs(tmp) {
// If the FromSlash without any starting slashes is absolute,
// then we have a filepath encoded with a prefix '/'.
// e.g. "/#s/boot" to "#s/boot"
return tmp
}
}
return lp
}

View File

@ -288,9 +288,9 @@ func cleanPath(p string) string {
}
func cleanPathWithBase(base, p string) string {
p = filepath.ToSlash(p)
p = filepath.ToSlash(filepath.Clean(p))
if !path.IsAbs(p) {
return path.Join(base, p)
}
return path.Clean(p)
return p
}

View File

@ -21,3 +21,7 @@ func testOsSys(sys interface{}) error {
}
return nil
}
func toLocalPath(p string) string {
return p
}

View File

@ -1,6 +1,10 @@
package sftp
import "syscall"
import (
"path"
"path/filepath"
"syscall"
)
func fakeFileInfoSys() interface{} {
return syscall.Win32FileAttributeData{}
@ -9,3 +13,32 @@ func fakeFileInfoSys() interface{} {
func testOsSys(sys interface{}) error {
return nil
}
func toLocalPath(p string) string {
lp := filepath.FromSlash(p)
if path.IsAbs(p) {
tmp := lp
for len(tmp) > 0 && tmp[0] == '\\' {
tmp = tmp[1:]
}
if filepath.IsAbs(tmp) {
// If the FromSlash without any starting slashes is absolute,
// then we have a filepath encoded with a prefix '/'.
// e.g. "/C:/Windows" to "C:\\Windows"
return tmp
}
tmp += "\\"
if filepath.IsAbs(tmp) {
// If the FromSlash without any starting slashes but with extra end slash is absolute,
// then we have a filepath encoded with a prefix '/' and a dropped '/' at the end.
// e.g. "/C:" to "C:\\"
return tmp
}
}
return lp
}

View File

@ -175,7 +175,7 @@ func handlePacket(s *Server, p orderedRequest) error {
}
case *sshFxpStatPacket:
// stat the requested file
info, err := os.Stat(p.Path)
info, err := os.Stat(toLocalPath(p.Path))
rpkt = &sshFxpStatResponse{
ID: p.ID,
info: info,
@ -185,7 +185,7 @@ func handlePacket(s *Server, p orderedRequest) error {
}
case *sshFxpLstatPacket:
// stat the requested file
info, err := os.Lstat(p.Path)
info, err := os.Lstat(toLocalPath(p.Path))
rpkt = &sshFxpStatResponse{
ID: p.ID,
info: info,
@ -209,24 +209,24 @@ func handlePacket(s *Server, p orderedRequest) error {
}
case *sshFxpMkdirPacket:
// TODO FIXME: ignore flags field
err := os.Mkdir(p.Path, 0755)
err := os.Mkdir(toLocalPath(p.Path), 0755)
rpkt = statusFromError(p.ID, err)
case *sshFxpRmdirPacket:
err := os.Remove(p.Path)
err := os.Remove(toLocalPath(p.Path))
rpkt = statusFromError(p.ID, err)
case *sshFxpRemovePacket:
err := os.Remove(p.Filename)
err := os.Remove(toLocalPath(p.Filename))
rpkt = statusFromError(p.ID, err)
case *sshFxpRenamePacket:
err := os.Rename(p.Oldpath, p.Newpath)
err := os.Rename(toLocalPath(p.Oldpath), toLocalPath(p.Newpath))
rpkt = statusFromError(p.ID, err)
case *sshFxpSymlinkPacket:
err := os.Symlink(p.Targetpath, p.Linkpath)
err := os.Symlink(toLocalPath(p.Targetpath), toLocalPath(p.Linkpath))
rpkt = statusFromError(p.ID, err)
case *sshFxpClosePacket:
rpkt = statusFromError(p.ID, s.closeHandle(p.Handle))
case *sshFxpReadlinkPacket:
f, err := os.Readlink(p.Path)
f, err := os.Readlink(toLocalPath(p.Path))
rpkt = &sshFxpNamePacket{
ID: p.ID,
NameAttrs: []*sshFxpNameAttr{
@ -241,7 +241,7 @@ func handlePacket(s *Server, p orderedRequest) error {
rpkt = statusFromError(p.ID, err)
}
case *sshFxpRealpathPacket:
f, err := filepath.Abs(p.Path)
f, err := filepath.Abs(toLocalPath(p.Path))
f = cleanPath(f)
rpkt = &sshFxpNamePacket{
ID: p.ID,
@ -257,6 +257,8 @@ func handlePacket(s *Server, p orderedRequest) error {
rpkt = statusFromError(p.ID, err)
}
case *sshFxpOpendirPacket:
p.Path = toLocalPath(p.Path)
if stat, err := os.Stat(p.Path); err != nil {
rpkt = statusFromError(p.ID, err)
} else if !stat.IsDir() {
@ -445,7 +447,7 @@ func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
osFlags |= os.O_EXCL
}
f, err := os.OpenFile(p.Path, osFlags, 0644)
f, err := os.OpenFile(toLocalPath(p.Path), osFlags, 0644)
if err != nil {
return statusFromError(p.ID, err)
}
@ -482,6 +484,8 @@ func (p *sshFxpSetstatPacket) respond(svr *Server) responsePacket {
b := p.Attrs.([]byte)
var err error
p.Path = toLocalPath(p.Path)
debug("setstat name \"%s\"", p.Path)
if (p.Flags & sshFileXferAttrSize) != 0 {
var size uint64

View File

@ -105,5 +105,5 @@ func fromFileMode(mode os.FileMode) uint32 {
const (
s_ISUID = 04000
s_ISGID = 02000
S_ISVTX = 01000
s_ISVTX = 01000
)