7
7
"errors"
8
8
"fmt"
9
9
"io"
10
+ "io/fs"
10
11
"io/ioutil"
11
12
"os"
12
13
"path/filepath"
@@ -21,6 +22,51 @@ const (
21
22
SftpServerWorkerCount = 8
22
23
)
23
24
25
+ type FileLike interface {
26
+ Stat () (os.FileInfo , error )
27
+ ReadAt (b []byte , off int64 ) (int , error )
28
+ WriteAt (b []byte , off int64 ) (int , error )
29
+ Readdir (int ) ([]os.FileInfo , error )
30
+ Name () string
31
+ Truncate (int64 ) error
32
+ Chmod (mode fs.FileMode ) error
33
+ Chown (uid , gid int ) error
34
+ Close () error
35
+ }
36
+
37
+ type dummyFile struct {
38
+ }
39
+
40
+ func (f * dummyFile ) Stat () (os.FileInfo , error ) {
41
+ return nil , os .ErrPermission
42
+ }
43
+ func (f * dummyFile ) ReadAt (b []byte , off int64 ) (int , error ) {
44
+ return 0 , os .ErrPermission
45
+ }
46
+ func (f * dummyFile ) WriteAt (b []byte , off int64 ) (int , error ) {
47
+ return 0 , os .ErrPermission
48
+ }
49
+ func (f * dummyFile ) Readdir (int ) ([]os.FileInfo , error ) {
50
+ return nil , os .ErrPermission
51
+ }
52
+ func (f * dummyFile ) Name () string {
53
+ return "dummyFile"
54
+ }
55
+ func (f * dummyFile ) Truncate (int64 ) error {
56
+ return os .ErrPermission
57
+ }
58
+ func (f * dummyFile ) Chmod (mode fs.FileMode ) error {
59
+ return os .ErrPermission
60
+ }
61
+ func (f * dummyFile ) Chown (uid , gid int ) error {
62
+ return os .ErrPermission
63
+ }
64
+ func (f * dummyFile ) Close () error {
65
+ return os .ErrPermission
66
+ }
67
+
68
+ var _ = dummyFile {} // ignore unused
69
+
24
70
// Server is an SSH File Transfer Protocol (sftp) server.
25
71
// This is intended to provide the sftp subsystem to an ssh server daemon.
26
72
// This implementation currently supports most of sftp server protocol version 3,
@@ -30,13 +76,13 @@ type Server struct {
30
76
debugStream io.Writer
31
77
readOnly bool
32
78
pktMgr * packetManager
33
- openFiles map [string ]* os. File
79
+ openFiles map [string ]FileLike
34
80
openFilesLock sync.RWMutex
35
81
handleCount int
36
82
workDir string
37
83
}
38
84
39
- func (svr * Server ) nextHandle (f * os. File ) string {
85
+ func (svr * Server ) nextHandle (f FileLike ) string {
40
86
svr .openFilesLock .Lock ()
41
87
defer svr .openFilesLock .Unlock ()
42
88
svr .handleCount ++
@@ -56,7 +102,7 @@ func (svr *Server) closeHandle(handle string) error {
56
102
return EBADF
57
103
}
58
104
59
- func (svr * Server ) getHandle (handle string ) (* os. File , bool ) {
105
+ func (svr * Server ) getHandle (handle string ) (FileLike , bool ) {
60
106
svr .openFilesLock .RLock ()
61
107
defer svr .openFilesLock .RUnlock ()
62
108
f , ok := svr .openFiles [handle ]
@@ -85,7 +131,7 @@ func NewServer(rwc io.ReadWriteCloser, options ...ServerOption) (*Server, error)
85
131
serverConn : svrConn ,
86
132
debugStream : ioutil .Discard ,
87
133
pktMgr : newPktMgr (svrConn ),
88
- openFiles : make (map [string ]* os. File ),
134
+ openFiles : make (map [string ]FileLike ),
89
135
}
90
136
91
137
for _ , o := range options {
@@ -462,7 +508,7 @@ func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
462
508
osFlags |= os .O_EXCL
463
509
}
464
510
465
- f , err := os . OpenFile (svr .toLocalPath (p .Path ), osFlags , 0o644 )
511
+ f , err := openFileLike (svr .toLocalPath (p .Path ), osFlags , 0o644 )
466
512
if err != nil {
467
513
return statusFromError (p .ID , err )
468
514
}
0 commit comments