Skip to content

Commit 218c0d4

Browse files
committed
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.
1 parent f01c355 commit 218c0d4

File tree

4 files changed

+27
-3
lines changed

4 files changed

+27
-3
lines changed

request-server.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding"
66
"io"
7+
"os"
78
"path"
89
"path/filepath"
910
"strconv"
@@ -173,8 +174,18 @@ func (rs *RequestServer) packetWorker(
173174
rpkt = cleanPacketPath(pkt)
174175
case *sshFxpOpendirPacket:
175176
request := requestFromPacket(ctx, pkt)
176-
handle := rs.nextRequest(request)
177-
rpkt = sshFxpHandlePacket{pkt.id(), handle}
177+
rpkt = request.call(rs.Handlers, pkt)
178+
request.close()
179+
if stat, ok := rpkt.(*sshFxpStatResponse); ok {
180+
if stat.info.IsDir() {
181+
request := requestFromPacket(ctx, pkt)
182+
handle := rs.nextRequest(request)
183+
rpkt = sshFxpHandlePacket{pkt.id(), handle}
184+
} else {
185+
rpkt = statusFromError(pkt, &os.PathError{
186+
Path: request.Filepath, Err: syscall.ENOTDIR})
187+
}
188+
}
178189
case *sshFxpOpenPacket:
179190
request := requestFromPacket(ctx, pkt)
180191
handle := rs.nextRequest(request)

request-server_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ func TestRequestReaddir(t *testing.T) {
355355
_, err := putTestFile(p.cli, fname, fname)
356356
assert.Nil(t, err)
357357
}
358+
_, err := p.cli.ReadDir("/foo_01")
359+
assert.Equal(t, &StatusError{Code: ssh_FX_FAILURE,
360+
msg: " /foo_01: not a directory"}, err)
361+
_, err = p.cli.ReadDir("/does_not_exist")
362+
assert.Equal(t, os.ErrNotExist, err)
358363
di, err := p.cli.ReadDir("/")
359364
assert.Nil(t, err)
360365
assert.Len(t, di, 100)

request.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,10 @@ func requestMethod(p requestPacket) (method string) {
338338
method = "Put"
339339
case *sshFxpReaddirPacket:
340340
method = "List"
341-
case *sshFxpOpenPacket, *sshFxpOpendirPacket:
341+
case *sshFxpOpenPacket:
342342
method = "Open"
343+
case *sshFxpOpendirPacket:
344+
method = "Stat"
343345
case *sshFxpSetstatPacket, *sshFxpFsetstatPacket:
344346
method = "Setstat"
345347
case *sshFxpRenamePacket:

server.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ func handlePacket(s *Server, p interface{}) error {
240240
}},
241241
})
242242
case *sshFxpOpendirPacket:
243+
if stat, err := os.Stat(p.Path); err != nil {
244+
return s.sendError(p, err)
245+
} else if !stat.IsDir() {
246+
return s.sendError(p, &os.PathError{
247+
Path: p.Path, Err: syscall.ENOTDIR})
248+
}
243249
return sshFxpOpenPacket{
244250
ID: p.ID,
245251
Path: p.Path,

0 commit comments

Comments
 (0)