Skip to content

Commit

Permalink
Merge pull request #445 from pkg/bugfix/windows-server-paths
Browse files Browse the repository at this point in the history
[bugfix] Windows paths don’t work with Server
  • Loading branch information
puellanivis authored Jun 30, 2021
2 parents ac2cd6e + 7161824 commit 35cb1f0
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 15 deletions.
23 changes: 22 additions & 1 deletion request-plan9.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

package sftp

import "syscall"
import (
"path"
"path/filepath"
"syscall"
)

func fakeFileInfoSys() interface{} {
return &syscall.Dir{}
Expand All @@ -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
}
4 changes: 2 additions & 2 deletions request-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
4 changes: 4 additions & 0 deletions request-unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ func testOsSys(sys interface{}) error {
}
return nil
}

func toLocalPath(p string) string {
return p
}
35 changes: 34 additions & 1 deletion request_windows.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sftp

import "syscall"
import (
"path"
"path/filepath"
"syscall"
)

func fakeFileInfoSys() interface{} {
return syscall.Win32FileAttributeData{}
Expand All @@ -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
}
24 changes: 14 additions & 10 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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{
Expand All @@ -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,
Expand All @@ -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() {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion stat_plan9.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ func fromFileMode(mode os.FileMode) uint32 {
const (
s_ISUID = 04000
s_ISGID = 02000
S_ISVTX = 01000
s_ISVTX = 01000
)

0 comments on commit 35cb1f0

Please sign in to comment.