From cbf8f9a51737e7d89fb0ec0832b50fd47c35b08d Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Mon, 21 Oct 2013 14:17:12 -0700 Subject: [PATCH] rgw: turn swift COPY into PUT Fixes: #6606 The swift COPY operation is unique in a sense that it's a write operation that has its destination not set by the URI target, but by a different HTTP header. This is problematic as there are some hidden assumptions in the code that the specified bucket/object in the URI is the operation target. E.g., certain initialization functions, quota, etc. Instead of creating a specialized code everywhere for this case just turn it into a regular copy operation, that is, a PUT with a specified copy source. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_common.h | 2 ++ src/rgw/rgw_op.cc | 4 +-- src/rgw/rgw_op.h | 5 ++-- src/rgw/rgw_rest.cc | 3 +- src/rgw/rgw_rest_swift.cc | 60 ++++++++++++++++++++++++--------------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index baf60001a8b..2aaa5b6af8c 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -825,6 +825,8 @@ struct req_state { rgw_bucket bucket; string bucket_name_str; string object_str; + string src_bucket_name; + string src_object; ACLOwner bucket_owner; ACLOwner owner; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 2e07e3fcde6..efdd9981a7f 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -339,7 +339,7 @@ static int rgw_build_policies(RGWRados *store, struct req_state *s, bool only_bu s->local_source = store->region.equals(region); } } - + if (s->bucket_name_str.size()) { s->bucket_exists = true; if (s->bucket_instance_id.empty()) { @@ -1706,8 +1706,6 @@ bool RGWCopyObj::parse_copy_location(const char *src, string& bucket_name, strin url_decode(url_src, dec_src); src = dec_src.c_str(); - ldout(s->cct, 15) << "decoded obj=" << src << dendl; - if (*src == '/') ++src; string str(src); diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index eee5ea99065..41ee2e88f9b 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -460,9 +460,6 @@ protected: int init_common(); -protected: - bool parse_copy_location(const char *src, string& bucket_name, string& object); - public: RGWCopyObj() { if_mod = NULL; @@ -482,6 +479,8 @@ public: last_ofs = 0; } + static bool parse_copy_location(const char *src, string& bucket_name, string& object); + virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) { RGWOp::init(store, s, h); dest_policy.set_ctx(s->cct); diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 4aa1d401211..87ad92dfdf7 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -1060,6 +1060,7 @@ int RGWHandler_ObjStore::read_permissions(RGWOp *op_obj) break; case OP_PUT: case OP_POST: + case OP_COPY: /* is it a 'multi-object delete' request? */ if (s->info.request_params == "delete") { only_bucket = true; @@ -1077,8 +1078,6 @@ int RGWHandler_ObjStore::read_permissions(RGWOp *op_obj) case OP_DELETE: only_bucket = true; break; - case OP_COPY: // op itself will read and verify the permissions - return 0; case OP_OPTIONS: only_bucket = true; break; diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 651c4635d37..58e60978c45 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -451,28 +451,10 @@ int RGWCopyObj_ObjStore_SWIFT::get_params() if_match = s->info.env->get("HTTP_COPY_IF_MATCH"); if_nomatch = s->info.env->get("HTTP_COPY_IF_NONE_MATCH"); - if (s->op == OP_COPY) { - const char *req_dest = s->info.env->get("HTTP_DESTINATION"); - if (!req_dest) - return -ERR_BAD_URL; - - ret = parse_copy_location(req_dest, dest_bucket_name, dest_object); - if (!ret) - return -ERR_BAD_URL; - src_bucket_name = s->bucket_name; - src_object = s->object_str; - } else { - const char *req_src = s->copy_source; - if (!req_src) - return -ERR_BAD_URL; - - ret = parse_copy_location(req_src, src_bucket_name, src_object); - if (!ret) - return -ERR_BAD_URL; - - dest_bucket_name = s->bucket_name; - dest_object = s->object_str; - } + src_bucket_name = s->src_bucket_name; + src_object = s->src_object; + dest_bucket_name = s->bucket_name; + dest_object = s->object_str; return 0; } @@ -701,7 +683,7 @@ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_put() if (is_acl_op()) { return new RGWPutACLs_ObjStore_SWIFT; } - if (!s->copy_source) + if (s->src_bucket_name.empty()) return new RGWPutObj_ObjStore_SWIFT; else return new RGWCopyObj_ObjStore_SWIFT; @@ -883,9 +865,41 @@ int RGWHandler_ObjStore_SWIFT::init(RGWRados *store, struct req_state *s, RGWCli return ret; s->copy_source = s->info.env->get("HTTP_X_COPY_FROM"); + if (s->copy_source) { + ret = RGWCopyObj::parse_copy_location(s->copy_source, s->src_bucket_name, s->src_object); + if (!ret) + return -ERR_BAD_URL; + } s->dialect = "swift"; + if (s->op == OP_COPY) { + const char *req_dest = s->info.env->get("HTTP_DESTINATION"); + if (!req_dest) + return -ERR_BAD_URL; + + string dest_bucket_name; + string dest_object; + ret = RGWCopyObj::parse_copy_location(req_dest, dest_bucket_name, dest_object); + if (!ret) + return -ERR_BAD_URL; + + if (dest_bucket_name != s->bucket_name_str) { + ret = validate_bucket_name(dest_bucket_name.c_str()); + if (ret < 0) + return ret; + } + + /* convert COPY operation into PUT */ + s->src_bucket_name = s->bucket_name_str; + s->src_object = s->object_str; + s->bucket_name_str = dest_bucket_name; + free(s->bucket_name); + s->bucket_name = strdup(s->bucket_name_str.c_str()); + s->object_str = dest_object; + s->op = OP_PUT; + } + return RGWHandler_ObjStore::init(store, s, cio); }