summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-10-21 14:17:12 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-10-21 16:25:19 -0700
commitcbf8f9a51737e7d89fb0ec0832b50fd47c35b08d (patch)
treee201483a649489be68f103bbf750efded696731c
parent1376d2379ac2ac3a4fe17fd1bbcf2a8588c7459b (diff)
downloadceph-cbf8f9a51737e7d89fb0ec0832b50fd47c35b08d.tar.gz
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>
-rw-r--r--src/rgw/rgw_common.h2
-rw-r--r--src/rgw/rgw_op.cc4
-rw-r--r--src/rgw/rgw_op.h5
-rw-r--r--src/rgw/rgw_rest.cc3
-rw-r--r--src/rgw/rgw_rest_swift.cc60
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);
}