]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: fix accept-range for suffix format, other related issues
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 8 Nov 2011 01:07:40 +0000 (17:07 -0800)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 8 Nov 2011 01:08:22 +0000 (17:08 -0800)
src/rgw/rgw_access.h
src/rgw/rgw_fs.cc
src/rgw/rgw_fs.h
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_tools.cc

index 21f597d534b773d8b7aeb9840c3f5becca91eff2..071fba65a1b3472d12979b529329bd6a37aaade5 100644 (file)
@@ -162,7 +162,7 @@ public:
  */
   virtual int prepare_get_obj(void *ctx,
             rgw_obj& obj,
-            off_t ofs, off_t *end,
+            off_t *ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
             const time_t *unmod_ptr,
index 1fbcb2b12d1844ee4342800ae9154e0eaea9a60d..21b82f656803919df35ebc4f2a71c0fb6ac2da35 100644 (file)
@@ -313,7 +313,7 @@ int RGWFS::copy_obj(void *ctx, rgw_obj& dest_obj,
   time_t lastmod;
 
   map<string, bufferlist> attrset;
-  ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
+  ret = prepare_get_obj(ctx, src_obj, &ofs, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
                         if_match, if_nomatch, &total_len, &obj_size, &handle, err);
   if (ret < 0)
     return ret;
@@ -459,7 +459,7 @@ int RGWFS::set_attr(void *ctx, rgw_obj& obj,
 
 int RGWFS::prepare_get_obj(void *ctx,
             rgw_obj& obj,
-            off_t ofs, off_t *end,
+            off_t *pofs, off_t *pend,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
             const time_t *unmod_ptr,
@@ -481,6 +481,8 @@ int RGWFS::prepare_get_obj(void *ctx,
   size_t max_len;
   char *etag = NULL;
   off_t size;
+  off_t ofs = 0;
+  off_t end = -1;
 
 
   GetObjState *state = new GetObjState;
@@ -504,11 +506,6 @@ int RGWFS::prepare_get_obj(void *ctx,
 
   size = st.st_size;
 
-  if (*end < 0)
-    *end = size - 1;
-
-  max_len = *end + 1 - ofs;
-
   r = -ECANCELED;
   if (mod_ptr) {
     if (st.st_mtime < *mod_ptr) {
@@ -552,6 +549,35 @@ int RGWFS::prepare_get_obj(void *ctx,
 
   free(etag);
 
+  if (pofs)
+    ofs = *pofs;
+  if (pend)
+    end = *pend;
+
+  if (ofs < 0) {
+    ofs += size;
+    end = size - 1;
+  } else if (end < 0) {
+    end = size - 1;
+  }
+
+  if (size > 0) {
+    if (ofs >= (off_t)size) {
+      r = -ERANGE;
+      goto done_err;
+    }
+
+    if (end >= size) {
+      end = size - 1;
+    }
+  }
+
+  max_len = end + 1 - ofs;
+
+  if (pofs)
+    *pofs = ofs;
+  if (pend)
+    *pend = end;
   if (total_size)
     *total_size = (max_len > 0 ? max_len : 0);
   if (obj_size)
index 69b11218042d7bcfe98e60c62495e2b91a163327..96ea95c3d35d3187808777e7dafdacbff6d3a4b4 100644 (file)
@@ -44,7 +44,7 @@ public:
 
   int prepare_get_obj(void *ctx,
             rgw_obj& obj,
-            off_t ofs, off_t *end,
+            off_t *ofs, off_t *end,
            map<std::string, bufferlist> *attrs,
             const time_t *mod_ptr,
             const time_t *unmod_ptr,
index 36ded6f4cb4ef750f44ce1a87972be5ae1a1d97a..5fcf2efc3e3d4f83722fe3a5a2097ca5d3d1aba4 100644 (file)
@@ -53,25 +53,44 @@ static int parse_range(const char *range, off_t& ofs, off_t& end)
 {
   int r = -ERANGE;
   string s(range);
-  int pos = s.find("bytes=");
   string ofs_str;
   string end_str;
-
-  if (pos < 0)
-    goto done;
-
-  s = s.substr(pos + 6); /* size of("bytes=")  */
+  int pos = s.find("bytes=");
+  if (pos < 0) {
+    pos = 0;
+    while (isspace(s[pos]))
+      pos++;
+    int end = pos;
+    while (isalpha(s[end]))
+      end++;
+    if (strncasecmp(s.c_str(), "bytes", end - pos) != 0)
+      return 0;
+    while (isspace(s[end]))
+      end++;
+    if (s[end] != '=')
+      return 0;
+    s = s.substr(end + 1);
+  } else {
+    s = s.substr(pos + 6); /* size of("bytes=")  */
+  }
   pos = s.find('-');
   if (pos < 0)
     goto done;
 
   ofs_str = s.substr(0, pos);
   end_str = s.substr(pos + 1);
-  if (ofs_str.length())
-    ofs = atoll(ofs_str.c_str());
-
-  if (end_str.length())
+  if (end_str.length()) {
     end = atoll(end_str.c_str());
+    if (end < 0)
+      goto done;
+  }
+
+  if (ofs_str.length()) {
+    ofs = atoll(ofs_str.c_str());
+  } else { // RFC2616 suffix-byte-range-spec
+    ofs = -end;
+    end = -1;
+  }
 
   dout(10) << "parse_range ofs=" << ofs << " end=" << end << dendl;
 
@@ -166,7 +185,7 @@ static int get_policy_from_attr(void *ctx, RGWAccessControlPolicy *policy, rgw_o
 static int get_obj_attrs(struct req_state *s, rgw_obj& obj, map<string, bufferlist>& attrs)
 {
   void *handle;
-  int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, 0, NULL, &attrs, NULL,
+  int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, NULL, NULL, &attrs, NULL,
                                       NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err);
   rgwstore->finish_get_obj(&handle);
   return ret;
@@ -274,17 +293,23 @@ void RGWGetObj::execute()
   if (ret < 0)
     goto done;
 
+dout(0) << __FILE__ << ":" << __LINE__ << ": ofs=" << ofs << " end=" << end << " total_len=" << total_len << dendl;
+
   obj.init(s->bucket, s->object_str);
   rgwstore->set_atomic(s->obj_ctx, obj);
-  ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, ofs, &end, &attrs, mod_ptr,
+  ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, &ofs, &end, &attrs, mod_ptr,
                                   unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &s->obj_size, &handle, &s->err);
   if (ret < 0)
     goto done;
+dout(0) << __FILE__ << ":" << __LINE__ << ": ofs=" << ofs << " end=" << end << " total_len=" << total_len << dendl;
+
+  start = ofs;
 
   if (!get_data || ofs > end)
     goto done;
 
   while (ofs <= end) {
+dout(0) << __FILE__ << ":" << __LINE__ << ": ofs=" << ofs << " end=" << end << " total_len=" << total_len << dendl;
     data = NULL;
     ret = rgwstore->get_obj(s->obj_ctx, &handle, obj, &data, ofs, end);
     if (ret < 0) {
@@ -312,7 +337,6 @@ int RGWGetObj::init_common()
     int r = parse_range(range_str, ofs, end);
     if (r < 0)
       return r;
-    start = ofs;
   }
   if (if_mod) {
     if (parse_time(if_mod, &mod_time) < 0)
index 0d6e903e4e029ae9d315c5ebeddb5088b54165f5..f67447004c03a563b9a5c3d3f3912a617f9f5d80 100644 (file)
@@ -778,7 +778,6 @@ int RGWRados::copy_obj(void *ctx,
 {
   int ret, r;
   char *data;
-  off_t end = -1;
   uint64_t total_len, obj_size;
   time_t lastmod;
   map<string, bufferlist>::iterator iter;
@@ -796,13 +795,14 @@ int RGWRados::copy_obj(void *ctx,
   void *handle = NULL;
 
   map<string, bufferlist> attrset;
-  ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset,
+  off_t ofs = 0;
+  off_t end = -1;
+  ret = prepare_get_obj(ctx, src_obj, &ofs, &end, &attrset,
                 mod_ptr, unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &obj_size, &handle, err);
 
   if (ret < 0)
     return ret;
 
-  off_t ofs = 0;
   do {
     ret = get_obj(ctx, &handle, src_obj, &data, ofs, end);
     if (ret < 0)
@@ -1276,7 +1276,7 @@ int RGWRados::set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl
  *          (if get_data==false) length of the object
  */
 int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
-            off_t ofs, off_t *end,
+            off_t *pofs, off_t *pend,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
             const time_t *unmod_ptr,
@@ -1297,6 +1297,8 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
   RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
   RGWRadosCtx *new_ctx = NULL;
   RGWObjState *astate = NULL;
+  off_t ofs = 0;
+  off_t end = -1;
 
   map<string, bufferlist>::iterator iter;
 
@@ -1388,11 +1390,36 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     }
   }
 
-  if (end && *end < 0)
-    *end = astate->size - 1;
+  if (pofs)
+    ofs = *pofs;
+  if (pend)
+    end = *pend;
+
+  if (ofs < 0) {
+    ofs += astate->size;
+    if (ofs < 0)
+      ofs = 0;
+    end = astate->size - 1;
+  } else if (end < 0) {
+    end = astate->size - 1;
+  }
+
+  if (astate->size > 0) {
+    if (ofs >= (off_t)astate->size) {
+      r = -ERANGE;
+      goto done_err;
+    }
+    if (end >= astate->size) {
+      end = astate->size - 1;
+    }
+  }
 
+  if (pofs)
+    *pofs = ofs;
+  if (pend)
+    *pend = end;
   if (total_size)
-    *total_size = (ofs <= *end ? *end + 1 - ofs : 0);
+    *total_size = (ofs <= end ? end + 1 - ofs : 0);
   if (obj_size)
     *obj_size = astate->size;
   if (lastmod)
@@ -1595,7 +1622,7 @@ int RGWRados::get_obj(void *ctx, void **handle, rgw_obj& obj,
   GetObjState *state = *(GetObjState **)handle;
   RGWObjState *astate = NULL;
 
-  if (end <= 0)
+  if (end < 0)
     len = 0;
   else
     len = end - ofs + 1;
index 8c95f116063d2956ba9fff28f98b0929887dc0b2..a77d3fc099c4d086eec7ab59a7898421cbb15cd4 100644 (file)
@@ -252,7 +252,7 @@ public:
 
   /** Get data about an object out of RADOS and into memory. */
   virtual int prepare_get_obj(void *ctx, rgw_obj& obj,
-            off_t ofs, off_t *end,
+            off_t *ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
             const time_t *unmod_ptr,
index 57576abc2b5d52e70a4b846dbb87da8c8860f172..35c4e3951fab702699b1bc0705349f879ebb522c 100644 (file)
@@ -38,7 +38,7 @@ int rgw_get_obj(void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl)
   bufferlist::iterator iter;
   int request_len = READ_CHUNK_LEN;
   rgw_obj obj(bucket, key);
-  ret = rgwstore->prepare_get_obj(ctx, obj, 0, NULL, NULL, NULL,
+  ret = rgwstore->prepare_get_obj(ctx, obj, NULL, NULL, NULL, NULL,
                                   NULL, NULL, NULL, NULL, NULL, NULL, &handle, &err);
   if (ret < 0)
     return ret;