]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: turn swift COPY into PUT
authorYehuda Sadeh <yehuda@inktank.com>
Mon, 21 Oct 2013 21:17:12 +0000 (14:17 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Mon, 21 Oct 2013 23:25:19 +0000 (16:25 -0700)
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>
src/rgw/rgw_common.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_swift.cc

index baf60001a8bb4bdc9843c2d82cc9fddadea0cf0b..2aaa5b6af8cbd64d09663d7e339f6061ffc35350 100644 (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;
 
index 2e07e3fcde6b02f8b731471ab7dd3fd16813fb56..efdd9981a7f905d51ef483324817df438e9c4388 100644 (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);
index eee5ea9906533a9d2edf31ef3cf0cbcf3f1f95f0..41ee2e88f9b9dc8855d0b9bbe2fd3eb8d2e705e1 100644 (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);
index 4aa1d40121108f15b43fa84662c8c0ca3521bf2a..87ad92dfdf704cd6ba6fe7e0090d6ddf361933fa 100644 (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;
index 651c4635d3788e1c121c073850e2c1861e605d0b..58e60978c45c1870307f6349e3c6b67625d7fa6a 100644 (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);
 }