Skip to content

Commit 85d0b56

Browse files
committed
fix: make exclusive SFTP creates atomic
1 parent aeb8a65 commit 85d0b56

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

sftp/handler.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,20 @@ func (h *Handler) Filewrite(request *sftp.Request) (io.WriterAt, error) {
124124
if !h.can(permission) {
125125
return nil, sftp.ErrSSHFxPermissionDenied
126126
}
127-
if exists && flags.Creat && flags.Excl {
127+
openFlags := os.O_RDWR | os.O_TRUNC
128+
if flags.Creat && flags.Excl {
128129
// SSH_FXF_CREAT with SSH_FXF_EXCL is an exclusive create request.
129-
return nil, os.ErrExist
130+
if exists {
131+
return nil, os.ErrExist
132+
}
133+
openFlags = os.O_RDWR | os.O_CREATE | os.O_EXCL
130134
}
131-
f, err := h.fs.Touch(request.Filepath, os.O_RDWR|os.O_TRUNC)
135+
f, err := h.fs.Touch(request.Filepath, openFlags)
132136
if err != nil {
137+
if errors.Is(err, os.ErrExist) {
138+
// Preserve exclusive-create semantics if the file appeared after the pre-check.
139+
return nil, os.ErrExist
140+
}
133141
l.WithField("flags", request.Flags).WithField("error", err).Error("failed to open existing file on system")
134142
return nil, sftp.ErrSSHFxFailure
135143
}

0 commit comments

Comments
 (0)