rgw: copy swift versioned object to destination if overwritten

Only allow if target bucket owner is the source bucket owner.

Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
This commit is contained in:
Yehuda Sadeh 2016-03-01 16:46:47 -08:00
parent 2ae6d54f10
commit 54ea09c362
2 changed files with 88 additions and 2 deletions

View File

@ -5651,6 +5651,76 @@ int RGWRados::BucketShard::init(rgw_bucket& _bucket, rgw_obj& obj)
}
int RGWRados::swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state,
rgw_user& user)
{
if (!bucket_info.has_swift_versioning() || bucket_info.swift_ver_location.empty()) {
return 0;
}
if (!state->exists) {
return 0;
}
string client_id;
string op_id;
rgw_obj& obj = source->get_obj();
const string& src_name = obj.get_object();
char buf[src_name.size() + 32];
snprintf(buf, sizeof(buf), "%03d%s%lld.%06d", (int)src_name.size(), src_name.c_str(), (long long)state->mtime, 0);
RGWBucketInfo dest_bucket_info;
int r = get_bucket_info(source->get_ctx(), bucket_info.bucket.tenant, bucket_info.swift_ver_location, dest_bucket_info, NULL, NULL);
if (r < 0) {
ldout(cct, 10) << "failed to read dest bucket info: r=" << r << dendl;
return r;
}
if (dest_bucket_info.owner != bucket_info.owner) {
return -EPERM;
}
rgw_obj dest_obj(dest_bucket_info.bucket, buf);
string no_zone;
r = copy_obj(source->get_ctx(),
user,
client_id,
op_id,
NULL, /* req_info *info */
no_zone,
dest_obj,
obj,
dest_bucket_info,
bucket_info,
NULL, /* time_t *src_mtime */
NULL, /* time_t *mtime */
NULL, /* const time_t *mod_ptr */
NULL, /* const time_t *unmod_ptr */
NULL, /* const char *if_match */
NULL, /* const char *if_nomatch */
RGWRados::ATTRSMOD_NONE,
true, /* bool copy_if_newer */
state->attrset,
RGW_OBJ_CATEGORY_MAIN,
0, /* uint64_t olh_epoch */
0, /* time_t delete_at */
NULL, /* string *version_id */
NULL, /* string *ptag */
NULL, /* string *petag */
NULL, /* struct rgw_err *err */
NULL, /* void (*progress_cb)(off_t, void *) */
NULL); /* void *progress_data */
if (r == -ECANCELED || r == -ENOENT) { /* has already been overwritten, meaning another rgw process already copied it out */
return 0;
}
return r;
}
/**
* Write/overwrite an object to the bucket storage.
* bucket: the bucket to store the object in
@ -5779,13 +5849,20 @@ int RGWRados::Object::Write::write_meta(uint64_t size,
bool versioned_op = (target->versioning_enabled() || is_olh || versioned_target);
RGWRados::Bucket bop(store, target->get_bucket_info());
RGWBucketInfo& bucket_info = target->get_bucket_info();
RGWRados::Bucket bop(store, bucket_info);
RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state);
if (versioned_op) {
index_op.set_bilog_flags(RGW_BILOG_FLAG_VERSIONED_OP);
}
r = store->swift_versioning_copy(bucket_info, target, state, meta.owner);
if (r < 0) {
goto done_cancel;
}
r = index_op.prepare(CLS_RGW_OP_ADD);
if (r < 0)
return r;
@ -7362,11 +7439,18 @@ int RGWRados::Object::Delete::delete_obj()
bool ret_not_existed = (!state->exists);
RGWRados::Bucket bop(store, target->get_bucket_info());
RGWBucketInfo& bucket_info = target->get_bucket_info();
RGWRados::Bucket bop(store, bucket_info);
RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state);
index_op.set_bilog_flags(params.bilog_flags);
r = store->swift_versioning_copy(bucket_info, target, state, params.bucket_owner);
if (r < 0) {
return r;
}
r = index_op.prepare(CLS_RGW_OP_DEL);
if (r < 0)
return r;

View File

@ -2448,6 +2448,8 @@ public:
struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data);
int swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state,
rgw_user& user);
int copy_obj_to_remote_dest(RGWObjState *astate,
map<string, bufferlist>& src_attrs,
RGWRados::Object::Read& read_op,