diff --git a/cmd/fs-v1-helpers.go b/cmd/fs-v1-helpers.go index f00d732e4..e06fcf554 100644 --- a/cmd/fs-v1-helpers.go +++ b/cmd/fs-v1-helpers.go @@ -280,7 +280,7 @@ func fsOpenFile(ctx context.Context, readPath string, offset int64) (io.ReadClos } // Stat to get the size of the file at path. - st, err := os.Stat(readPath) + st, err := fr.Stat() if err != nil { err = osErrToFSFileErr(err) if err != errFileNotFound { @@ -386,6 +386,26 @@ func fsFAllocate(fd int, offset int64, len int64) (err error) { return nil } +// Renames source path to destination path, fails if the destination path +// parents are not already created. +func fsSimpleRenameFile(ctx context.Context, sourcePath, destPath string) error { + if err := checkPathLength(sourcePath); err != nil { + logger.LogIf(ctx, err) + return err + } + if err := checkPathLength(destPath); err != nil { + logger.LogIf(ctx, err) + return err + } + + if err := os.Rename(sourcePath, destPath); err != nil { + logger.LogIf(ctx, err) + return osErrToFSFileErr(err) + } + + return nil +} + // Renames source path to destination path, creates all the // missing parents if they don't exist. func fsRenameFile(ctx context.Context, sourcePath, destPath string) error { diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index 0f66be404..a137aaa10 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -152,7 +152,7 @@ func (fs *FSObjects) ListMultipartUploads(ctx context.Context, bucket, object, k return result, toObjectErr(err) } - // S3 spec says uploaIDs should be sorted based on initiated time. ModTime of fs.json + // S3 spec says uploadIDs should be sorted based on initiated time. ModTime of fs.json // is the creation time of the uploadID, hence we will use that. var uploads []MultipartInfo for _, uploadID := range uploadIDs { @@ -326,7 +326,11 @@ func (fs *FSObjects) PutObjectPart(ctx context.Context, bucket, object, uploadID partPath := pathJoin(uploadIDDir, fs.encodePartFile(partID, etag, data.ActualSize())) - if err = fsRenameFile(ctx, tmpPartPath, partPath); err != nil { + // Make sure not to create parent directories if they don't exist - the upload might have been aborted. + if err = fsSimpleRenameFile(ctx, tmpPartPath, partPath); err != nil { + if err == errFileNotFound || err == errFileAccessDenied { + return pi, InvalidUploadID{UploadID: uploadID} + } return pi, toObjectErr(err, minioMetaMultipartBucket, partPath) } diff --git a/cmd/os-reliable.go b/cmd/os-reliable.go index 669bce6ca..410bcc2d3 100644 --- a/cmd/os-reliable.go +++ b/cmd/os-reliable.go @@ -156,11 +156,11 @@ func renameAll(srcFilePath, dstFilePath string) (err error) { // Reliably retries os.RenameAll if for some reason os.RenameAll returns // syscall.ENOENT (parent does not exist). func reliableRename(srcFilePath, dstFilePath string) (err error) { + if err = reliableMkdirAll(path.Dir(dstFilePath), 0777); err != nil { + return err + } i := 0 for { - if err = reliableMkdirAll(path.Dir(dstFilePath), 0777); err != nil { - return err - } // After a successful parent directory create attempt a renameAll. if err = os.Rename(srcFilePath, dstFilePath); err != nil { // Retry only for the first retryable error.