mirror of https://github.com/pkg/sftp.git
Opendir return an error status when not found
The initial Opendir packet is supposed to repond with an error status if the directory wasn't found. It was just returning a handle without checking, now it does a Stat on the path and only returns the handle if the Stat is successful and it indicates it is a directory, otherwise it returns an error.
This commit is contained in:
parent
f01c3557dc
commit
218c0d4148
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding"
|
"encoding"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -173,8 +174,18 @@ func (rs *RequestServer) packetWorker(
|
||||||
rpkt = cleanPacketPath(pkt)
|
rpkt = cleanPacketPath(pkt)
|
||||||
case *sshFxpOpendirPacket:
|
case *sshFxpOpendirPacket:
|
||||||
request := requestFromPacket(ctx, pkt)
|
request := requestFromPacket(ctx, pkt)
|
||||||
handle := rs.nextRequest(request)
|
rpkt = request.call(rs.Handlers, pkt)
|
||||||
rpkt = sshFxpHandlePacket{pkt.id(), handle}
|
request.close()
|
||||||
|
if stat, ok := rpkt.(*sshFxpStatResponse); ok {
|
||||||
|
if stat.info.IsDir() {
|
||||||
|
request := requestFromPacket(ctx, pkt)
|
||||||
|
handle := rs.nextRequest(request)
|
||||||
|
rpkt = sshFxpHandlePacket{pkt.id(), handle}
|
||||||
|
} else {
|
||||||
|
rpkt = statusFromError(pkt, &os.PathError{
|
||||||
|
Path: request.Filepath, Err: syscall.ENOTDIR})
|
||||||
|
}
|
||||||
|
}
|
||||||
case *sshFxpOpenPacket:
|
case *sshFxpOpenPacket:
|
||||||
request := requestFromPacket(ctx, pkt)
|
request := requestFromPacket(ctx, pkt)
|
||||||
handle := rs.nextRequest(request)
|
handle := rs.nextRequest(request)
|
||||||
|
|
|
@ -355,6 +355,11 @@ func TestRequestReaddir(t *testing.T) {
|
||||||
_, err := putTestFile(p.cli, fname, fname)
|
_, err := putTestFile(p.cli, fname, fname)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
_, err := p.cli.ReadDir("/foo_01")
|
||||||
|
assert.Equal(t, &StatusError{Code: ssh_FX_FAILURE,
|
||||||
|
msg: " /foo_01: not a directory"}, err)
|
||||||
|
_, err = p.cli.ReadDir("/does_not_exist")
|
||||||
|
assert.Equal(t, os.ErrNotExist, err)
|
||||||
di, err := p.cli.ReadDir("/")
|
di, err := p.cli.ReadDir("/")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Len(t, di, 100)
|
assert.Len(t, di, 100)
|
||||||
|
|
|
@ -338,8 +338,10 @@ func requestMethod(p requestPacket) (method string) {
|
||||||
method = "Put"
|
method = "Put"
|
||||||
case *sshFxpReaddirPacket:
|
case *sshFxpReaddirPacket:
|
||||||
method = "List"
|
method = "List"
|
||||||
case *sshFxpOpenPacket, *sshFxpOpendirPacket:
|
case *sshFxpOpenPacket:
|
||||||
method = "Open"
|
method = "Open"
|
||||||
|
case *sshFxpOpendirPacket:
|
||||||
|
method = "Stat"
|
||||||
case *sshFxpSetstatPacket, *sshFxpFsetstatPacket:
|
case *sshFxpSetstatPacket, *sshFxpFsetstatPacket:
|
||||||
method = "Setstat"
|
method = "Setstat"
|
||||||
case *sshFxpRenamePacket:
|
case *sshFxpRenamePacket:
|
||||||
|
|
|
@ -240,6 +240,12 @@ func handlePacket(s *Server, p interface{}) error {
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
case *sshFxpOpendirPacket:
|
case *sshFxpOpendirPacket:
|
||||||
|
if stat, err := os.Stat(p.Path); err != nil {
|
||||||
|
return s.sendError(p, err)
|
||||||
|
} else if !stat.IsDir() {
|
||||||
|
return s.sendError(p, &os.PathError{
|
||||||
|
Path: p.Path, Err: syscall.ENOTDIR})
|
||||||
|
}
|
||||||
return sshFxpOpenPacket{
|
return sshFxpOpenPacket{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
Path: p.Path,
|
Path: p.Path,
|
||||||
|
|
Loading…
Reference in New Issue