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 <yehuda@inktank.com>
This commit is contained in:
Yehuda Sadeh 2013-10-21 14:17:12 -07:00
parent 1376d2379a
commit cbf8f9a517
5 changed files with 43 additions and 31 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}