From 4827496234dec2f750a511cda9c5909f0ff0bd8f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 8 Mar 2019 12:54:39 +0000 Subject: [PATCH] webdav: fix race when creating directories - fixes #3035 Before this change a race condition existed in mkdir - the directory was attempted to be created - the parent didn't exist so it failed - the parent was created - the directory was created again The last step failed as the directory was created in a different thread. This was fixed by checking the error messages of MKCOL for both directory creations, rather than only the first. --- backend/webdav/webdav.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/backend/webdav/webdav.go b/backend/webdav/webdav.go index 91205b00f..96b8a053b 100644 --- a/backend/webdav/webdav.go +++ b/backend/webdav/webdav.go @@ -644,10 +644,18 @@ func (f *Fs) _mkdir(dirPath string) error { Path: dirPath, NoResponse: true, } - return f.pacer.Call(func() (bool, error) { + err := f.pacer.Call(func() (bool, error) { resp, err := f.srv.Call(&opts) return shouldRetry(resp, err) }) + if apiErr, ok := err.(*api.Error); ok { + // already exists + // owncloud returns 423/StatusLocked if the create is already in progress + if apiErr.StatusCode == http.StatusMethodNotAllowed || apiErr.StatusCode == http.StatusNotAcceptable || apiErr.StatusCode == http.StatusLocked { + return nil + } + } + return err } // mkdir makes the directory and parents using native paths @@ -655,12 +663,7 @@ func (f *Fs) mkdir(dirPath string) error { // defer log.Trace(dirPath, "")("") err := f._mkdir(dirPath) if apiErr, ok := err.(*api.Error); ok { - // already exists - // owncloud returns 423/StatusLocked if the create is already in progress - if apiErr.StatusCode == http.StatusMethodNotAllowed || apiErr.StatusCode == http.StatusNotAcceptable || apiErr.StatusCode == http.StatusLocked { - return nil - } - // parent does not exist + // parent does not exist so create it first then try again if apiErr.StatusCode == http.StatusConflict { err = f.mkParentDir(dirPath) if err == nil {