*/
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,
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;
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,
size_t max_len;
char *etag = NULL;
off_t size;
+ off_t ofs = 0;
+ off_t end = -1;
GetObjState *state = new GetObjState;
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) {
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)
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,
{
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;
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;
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) {
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)
{
int ret, r;
char *data;
- off_t end = -1;
uint64_t total_len, obj_size;
time_t lastmod;
map<string, bufferlist>::iterator iter;
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)
* (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,
RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
RGWRadosCtx *new_ctx = NULL;
RGWObjState *astate = NULL;
+ off_t ofs = 0;
+ off_t end = -1;
map<string, bufferlist>::iterator iter;
}
}
- 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)
GetObjState *state = *(GetObjState **)handle;
RGWObjState *astate = NULL;
- if (end <= 0)
+ if (end < 0)
len = 0;
else
len = end - ofs + 1;
/** 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,
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;