From 2e99232a044393e70fc8e478d45e0131d37d42dc Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 11 Jun 2020 15:29:19 +0100 Subject: [PATCH] s3: Make a new "unset" state for acl to work around bug in b2 s3 interface B2 has started rejecting uploads from rclone with the error message Backblaze does not support the 'x-amz-acl' header This introduces a new "unset" value. If `acl` or `bucket_acl` is set to `unset` then rclone will omit the ACL header from the request. See: https://forum.rclone.org/t/s3-acl-issues-on-backblaze-with-multi-part-upload/16850 --- backend/s3/s3.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/s3/s3.go b/backend/s3/s3.go index 304eafb05..bedfd6da9 100644 --- a/backend/s3/s3.go +++ b/backend/s3/s3.go @@ -1020,7 +1020,10 @@ This ACL is used for creating objects and if bucket_acl isn't set, for creating For more info visit https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl Note that this ACL is applied when server-side copying objects as S3 -doesn't copy the ACL from the source but rather writes a fresh one.`, +doesn't copy the ACL from the source but rather writes a fresh one. + +If the ACL is set as the string "unset" then rclone won't set the ACL +header so it will use the default of the cloud provider.`, Examples: []fs.OptionExample{{ Value: "default", Help: "Owner gets Full_CONTROL.\nNo one else has access rights (default).", @@ -1990,6 +1993,9 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e if opt.ACL == "" { opt.ACL = "private" } + if opt.ACL == "unset" { + opt.ACL = "" + } if opt.BucketACL == "" { opt.BucketACL = opt.ACL } @@ -2526,7 +2532,9 @@ func (f *Fs) makeBucket(ctx context.Context, bucket string) error { return f.cache.Create(bucket, func() error { req := s3.CreateBucketInput{ Bucket: &bucket, - ACL: &f.opt.BucketACL, + } + if f.opt.BucketACL != "" { + req.ACL = &f.opt.BucketACL } if f.opt.LocationConstraint != "" { req.CreateBucketConfiguration = &s3.CreateBucketConfiguration{ @@ -2591,7 +2599,9 @@ func pathEscape(s string) string { // method func (f *Fs) copy(ctx context.Context, req *s3.CopyObjectInput, dstBucket, dstPath, srcBucket, srcPath string, src *Object) error { req.Bucket = &dstBucket - req.ACL = &f.opt.ACL + if f.opt.ACL != "" { + req.ACL = &f.opt.ACL + } req.Key = &dstPath source := pathEscape(path.Join(srcBucket, srcPath)) req.CopySource = &source @@ -3673,11 +3683,13 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op mimeType := fs.MimeType(ctx, src) req := s3.PutObjectInput{ Bucket: &bucket, - ACL: &o.fs.opt.ACL, Key: &bucketPath, ContentType: &mimeType, Metadata: metadata, } + if o.fs.opt.ACL != "" { + req.ACL = &o.fs.opt.ACL + } if md5sum != "" { req.ContentMD5 = &md5sum }