]> 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)
committerSage Weil <sage@inktank.com>
Fri, 13 Dec 2013 22:42:32 +0000 (14:42 -0800)
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>
(cherry picked from commit cbf8f9a51737e7d89fb0ec0832b50fd47c35b08d)

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 3368e9756154df446eaff2afa2e2a9cd5cbfa3f1..8446201320f59912407b61332376fb4330651206 100644 (file)
@@ -807,6 +807,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 e45cc2704bed9b0004c08916ab74ed1e8db8ed66..8261ac87fa54da7069c6d9eae6bb6a3bc28cf449 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()) {
@@ -1652,8 +1652,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 948a11830c2c152e7e46e77c3b970c50107b9b53..eb3799c07f6412d2bc95164ec7b0e21b7ba2f9e0 100644 (file)
@@ -448,9 +448,6 @@ protected:
 
   int init_common();
 
-protected:
-  bool parse_copy_location(const char *src, string& bucket_name, string& object);
-
 public:
   RGWCopyObj() {
     if_mod = NULL;
@@ -470,6 +467,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);
 }