Skip to content

Commit 5123f57

Browse files
committed
fix: make exclusive SFTP creates atomic
1 parent 639ad43 commit 5123f57

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
@@ -148,12 +148,20 @@ func (h *Handler) Filewrite(request *sftp.Request) (io.WriterAt, error) {
148148
if !h.can(permission) {
149149
return nil, sftp.ErrSSHFxPermissionDenied
150150
}
151-
if exists && flags.Creat && flags.Excl {
151+
openFlags := os.O_RDWR | os.O_TRUNC
152+
if flags.Creat && flags.Excl {
152153
// SSH_FXF_CREAT with SSH_FXF_EXCL is an exclusive create request.
153-
return nil, os.ErrExist
154+
if exists {
155+
return nil, os.ErrExist
156+
}
157+
openFlags = os.O_RDWR | os.O_CREATE | os.O_EXCL
154158
}
155-
f, err := h.fs.Touch(request.Filepath, os.O_RDWR|os.O_TRUNC)
159+
f, err := h.fs.Touch(request.Filepath, openFlags)
156160
if err != nil {
161+
if errors.Is(err, os.ErrExist) {
162+
// Preserve exclusive-create semantics if the file appeared after the pre-check.
163+
return nil, os.ErrExist
164+
}
157165
l.WithField("flags", request.Flags).WithField("error", err).Error("failed to open existing file on system")
158166
return nil, sftp.ErrSSHFxFailure
159167
}

0 commit comments

Comments
 (0)