#define ERR_UNPROCESSABLE_ENTITY 2018
#define ERR_TOO_LARGE 2019
#define ERR_TOO_MANY_BUCKETS 2020
+#define ERR_INVALID_REQUEST 2021
#define ERR_USER_SUSPENDED 2100
#define ERR_INTERNAL_ERROR 2200
attrs[RGW_ATTR_ACL] = aclbl;
rgw_get_request_metadata(s, attrs);
+ if (s->content_type) {
+ bufferlist bl;
+ bl.append(s->content_type, strlen(s->content_type) + 1);
+ attrs[RGW_ATTR_CONTENT_TYPE] = bl;
+ }
+
return 0;
}
unmod_ptr,
if_match,
if_nomatch,
+ replace_attrs,
attrs, RGW_OBJ_CATEGORY_MAIN, &s->err);
done:
void RGWInitMultipart::execute()
{
- bufferlist bl;
bufferlist aclbl;
map<string, bufferlist> attrs;
rgw_obj obj;
attrs[RGW_ATTR_ACL] = aclbl;
if (s->content_type) {
+ bufferlist bl;
bl.append(s->content_type, strlen(s->content_type) + 1);
attrs[RGW_ATTR_CONTENT_TYPE] = bl;
}
rgw_bucket dest_bucket;
string dest_object;
time_t mtime;
+ bool replace_attrs;
int init_common();
src_bucket.clear();
src_object.clear();
mtime = 0;
+ replace_attrs = false;
dest_policy.set_ctx(s->cct);
}
int verify_permission();
}
/**
* Copy an object.
- * dest_bucket: the bucket to copy into
* dest_obj: the object to copy into
- * src_bucket: the bucket to copy from
* src_obj: the object to copy from
- * mod_ptr, unmod_ptr, if_match, if_nomatch: as used in get_obj
- * attrs: these are placed on the new object IN ADDITION to
- * (or overwriting) any attrs copied from the original object
+ * attrs: if replace_attrs is set then these are placed on the new object
* err: stores any errors resulting from the get of the original object
* Returns: 0 on success, -ERR# otherwise.
*/
const time_t *unmod_ptr,
const char *if_match,
const char *if_nomatch,
- map<string, bufferlist>& attrs, /* in/out */
+ bool replace_attrs,
+ map<string, bufferlist>& attrs,
RGWObjCategory category,
struct rgw_err *err)
{
}
manifest.obj_size = ofs;
- for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
- attrset[iter->first] = iter->second;
+ if (replace_attrs) {
+ attrset = attrs;
}
- attrs = attrset;
- ret = rgwstore->put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, false, NULL, &first_chunk, &manifest);
+ ret = rgwstore->put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, false, NULL, &first_chunk, &manifest);
if (mtime)
obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL);
/**
* Copy an object.
- * dest_bucket: the bucket to copy into
* dest_obj: the object to copy into
- * src_bucket: the bucket to copy from
* src_obj: the object to copy from
- * mod_ptr, unmod_ptr, if_match, if_nomatch: as used in get_obj
- * attrs: these are placed on the new object IN ADDITION to
- * (or overwriting) any attrs copied from the original object
+ * attrs: if replace_attrs is set then these are placed on the new object
* err: stores any errors resulting from the get of the original object
* Returns: 0 on success, -ERR# otherwise.
*/
const time_t *unmod_ptr,
const char *if_match,
const char *if_nomatch,
+ bool replace_attrs,
map<std::string, bufferlist>& attrs,
RGWObjCategory category,
struct rgw_err *err);
{ STATUS_PARTIAL_CONTENT, 206, "" },
{ ERR_NOT_MODIFIED, 304, "NotModified" },
{ EINVAL, 400, "InvalidArgument" },
+ { ERR_INVALID_REQUEST, 400, "InvalidRequest" },
{ ERR_INVALID_DIGEST, 400, "InvalidDigest" },
{ ERR_BAD_DIGEST, 400, "BadDigest" },
{ ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" },
dest_bucket_name = s->bucket.name;
dest_object = s->object_str;
+ const char *md_directive = s->env->get("HTTP_X_AMZ_METADATA_DIRECTIVE");
+ if (md_directive) {
+ if (strcasecmp(md_directive, "COPY") == 0) {
+ replace_attrs = false;
+ } else if (strcasecmp(md_directive, "REPLACE") == 0) {
+ replace_attrs = true;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ if ((dest_bucket_name.compare(src_bucket_name) == 0) &&
+ (dest_object.compare(src_object) == 0) &&
+ !replace_attrs) {
+ /* can only copy object into itself if replacing attrs */
+ return -ERR_INVALID_REQUEST;
+ }
return 0;
}