}
-int RGWPutMetadata::verify_permission()
+static void populate_with_generic_attrs(const req_state * const s,
+ map<string, bufferlist>& out_attrs)
{
- const bool is_object_op = (!s->object.empty());
- const bool is_bucket_op = (!s->bucket_name_str.empty() && !is_object_op);
+ map<string, string>::const_iterator giter;
- if (is_object_op) {
- if (!verify_object_permission(s, RGW_PERM_WRITE))
- return -EACCES;
- } else if (is_bucket_op) {
- if (!verify_bucket_permission(s, RGW_PERM_WRITE))
- return -EACCES;
+ for (giter = s->generic_attrs.begin(); giter != s->generic_attrs.end(); ++giter) {
+ bufferlist& attrbl = out_attrs[giter->first];
+ const string& val = giter->second;
+ attrbl.clear();
+ attrbl.append(val.c_str(), val.size() + 1);
}
-
- return 0;
}
-void RGWPutMetadata::pre_exec()
+static void prepare_add_del_attrs(const map<string, bufferlist>& orig_attrs,
+ map<string, bufferlist>& out_attrs,
+ map<string, bufferlist>& out_rmattrs)
{
- const bool is_account_op = s->bucket_name_str.empty();
+ map<string, bufferlist>::const_iterator iter;
- if (!is_account_op) {
- rgw_bucket_object_pre_exec(s);
+ for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) {
+ const string& name = iter->first;
+ /* check if the attr is user-defined metadata item */
+ if (name.compare(0, sizeof(RGW_ATTR_META_PREFIX) - 1, RGW_ATTR_META_PREFIX) == 0) {
+ /* for the objects all existing meta attrs have to be removed */
+ out_rmattrs[name] = iter->second;
+ } else if (out_attrs.find(name) == out_attrs.end()) {
+ out_attrs[name] = iter->second;
+ }
}
}
-void RGWPutMetadata::execute()
+static void prepare_add_del_attrs(const map<string, bufferlist>& orig_attrs,
+ const set<string>& rmattr_names,
+ map<string, bufferlist>& out_attrs,
+ map<string, bufferlist>& out_rmattrs)
{
- const char *meta_prefix = RGW_ATTR_META_PREFIX;
- int meta_prefix_len = sizeof(RGW_ATTR_META_PREFIX) - 1;
- map<string, bufferlist> attrs, orig_attrs, rmattrs;
- map<string, bufferlist>::iterator iter;
- bufferlist bl, cors_bl;
- rgw_obj obj;
- RGWObjVersionTracker acct_ot;
+ map<string, bufferlist>::const_iterator iter;
- const bool is_object_op = (!s->object.empty());
- const bool is_bucket_op = (!s->bucket_name_str.empty() && !is_object_op);
+ for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) {
+ const string& name = iter->first;
+ /* check if the attr is user-defined metadata item */
+ if (name.compare(0, strlen(RGW_ATTR_META_PREFIX), RGW_ATTR_META_PREFIX) == 0) {
+ /* for the buckets all existing meta attrs are preserved,
+ except those that are listed in rmattr_names. */
+ if (rmattr_names.find(name) != rmattr_names.end()) {
+ map<string, bufferlist>::iterator aiter = out_attrs.find(name);
+ if (aiter != out_attrs.end()) {
+ out_attrs.erase(aiter);
+ }
+ out_rmattrs[name] = iter->second;
+ }
+ } else if (out_attrs.find(name) == out_attrs.end()) {
+ out_attrs[name] = iter->second;
+ }
+ }
+}
- if (is_object_op || is_bucket_op) {
- obj = rgw_obj(s->bucket, s->object);
- } else {
- string buckets_obj_id;
- rgw_get_buckets_obj(s->user.user_id, buckets_obj_id);
+int RGWPutMetadataAccount::verify_permission()
+{
+ /* FIXME: check perms! */
+ return 0;
+}
- obj = rgw_obj(store->zone.user_uid_pool, buckets_obj_id);
- }
+void RGWPutMetadataAccount::execute()
+{
+ rgw_obj obj;
+ map<string, bufferlist> attrs, orig_attrs, rmattrs;
+ RGWObjVersionTracker acct_op_tracker;
- store->set_atomic(s->obj_ctx, obj);
+ /* Get the name of raw object which stores the metadata in its xattrs. */
+ string buckets_obj_id;
+ rgw_get_buckets_obj(s->user.user_id, buckets_obj_id);
+ obj = rgw_obj(store->zone.user_uid_pool, buckets_obj_id);
ret = get_params();
if (ret < 0) {
return;
}
- RGWObjVersionTracker *ptracker = NULL;
-
- rgw_get_request_metadata(s->cct, s->info, attrs, is_object_op);
+ rgw_get_request_metadata(s->cct, s->info, attrs);
+ rgw_get_user_attrs_by_uid(store, s->user.user_id, orig_attrs, &acct_op_tracker);
+ prepare_add_del_attrs(orig_attrs, rmattr_names, attrs, rmattrs);
+ populate_with_generic_attrs(s, attrs);
- if (is_object_op) {
- /* check if obj exists, read orig attrs */
- ret = get_obj_attrs(store, s, obj, orig_attrs);
- if (ret < 0)
- return;
- } else if (is_bucket_op) {
- ptracker = &s->bucket_info.objv_tracker;
- orig_attrs = s->bucket_attrs;
+ ret = rgw_store_user_attrs(store, s->user.user_id, attrs, &rmattrs, &acct_op_tracker);
+}
- if (!placement_rule.empty() &&
- placement_rule != s->bucket_info.placement_rule) {
- ret = -EEXIST;
- return;
- }
- } else {
- ptracker = &acct_ot;
- rgw_get_user_attrs_by_uid(store, s->user.user_id, orig_attrs, ptracker);
+int RGWPutMetadataBucket::verify_permission()
+{
+ if (!verify_bucket_permission(s, RGW_PERM_WRITE)) {
+ return -EACCES;
}
- for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) {
- const string& name = iter->first;
- /* check if the attr is user-defined metadata item */
- if (name.compare(0, meta_prefix_len, meta_prefix) == 0) {
- if (is_object_op) {
- /* for the objects all existing meta attrs have to be removed */
- rmattrs[name] = iter->second;
- } else {
- /* for the buckets all existing meta attrs are preserved,
- except those that are listed in rmattr_names. */
- if (rmattr_names.find(name) != rmattr_names.end()) {
- map<string, bufferlist>::iterator aiter = attrs.find(name);
- if (aiter != attrs.end()) {
- attrs.erase(aiter);
- }
- rmattrs[name] = iter->second;
- }
- }
- } else if (attrs.find(name) == attrs.end()) {
- attrs[name] = iter->second;
- }
+ return 0;
+}
+
+void RGWPutMetadataBucket::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWPutMetadataBucket::execute()
+{
+ rgw_obj obj(s->bucket, s->object);
+ map<string, bufferlist> attrs, orig_attrs, rmattrs;
+
+ ret = get_params();
+ if (ret < 0) {
+ return;
}
- map<string, string>::iterator giter;
- for (giter = s->generic_attrs.begin(); giter != s->generic_attrs.end(); ++giter) {
- bufferlist& attrbl = attrs[giter->first];
- const string& val = giter->second;
- attrbl.clear();
- attrbl.append(val.c_str(), val.size() + 1);
+ rgw_get_request_metadata(s->cct, s->info, attrs);
+
+ if (!placement_rule.empty() &&
+ placement_rule != s->bucket_info.placement_rule) {
+ ret = -EEXIST;
+ return;
}
+ orig_attrs = s->bucket_attrs;
+ prepare_add_del_attrs(orig_attrs, rmattr_names, attrs, rmattrs);
+ populate_with_generic_attrs(s, attrs);
+
if (has_policy) {
+ bufferlist bl;
policy.encode(bl);
attrs[RGW_ATTR_ACL] = bl;
}
+
if (has_cors) {
- cors_config.encode(cors_bl);
- attrs[RGW_ATTR_CORS] = cors_bl;
+ bufferlist bl;
+ cors_config.encode(bl);
+ attrs[RGW_ATTR_CORS] = bl;
}
- if (is_object_op) {
- ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, ptracker);
- } else if (is_bucket_op) {
- ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, &rmattrs, ptracker);
- } else {
- ret = rgw_store_user_attrs(store, s->user.user_id, attrs, &rmattrs, ptracker);
+
+ ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, &rmattrs,
+ &s->bucket_info.objv_tracker);
+}
+
+int RGWPutMetadataObject::verify_permission()
+{
+ if (!verify_object_permission(s, RGW_PERM_WRITE)) {
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+void RGWPutMetadataObject::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWPutMetadataObject::execute()
+{
+ rgw_obj obj(s->bucket, s->object);
+ map<string, bufferlist> attrs, orig_attrs, rmattrs;
+
+ store->set_atomic(s->obj_ctx, obj);
+
+ ret = get_params();
+ if (ret < 0) {
+ return;
}
+
+ rgw_get_request_metadata(s->cct, s->info, attrs);
+ /* check if obj exists, read orig attrs */
+ ret = get_obj_attrs(store, s, obj, orig_attrs);
+ if (ret < 0) {
+ return;
+ }
+
+ /* Filter currently existing attributes. */
+ prepare_add_del_attrs(orig_attrs, attrs, rmattrs);
+ populate_with_generic_attrs(s, attrs);
+ ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, NULL);
}
int RGWSetTempUrl::verify_permission()
void RGWSetTempUrl::execute()
{
ret = get_params();
- if (ret < 0)
+ if (ret < 0) {
return;
+ }
RGWUserAdminOpState user_op;
user_op.set_user_id(s->user.user_id);
RGW_OP_DELETE_BUCKET,
RGW_OP_PUT_OBJ,
RGW_OP_POST_OBJ,
- RGW_OP_PUT_METADATA,
+ RGW_OP_PUT_METADATA_ACCOUNT,
+ RGW_OP_PUT_METADATA_BUCKET,
+ RGW_OP_PUT_METADATA_OBJECT,
RGW_OP_SET_TEMPURL,
RGW_OP_DELETE_OBJ,
RGW_OP_COPY_OBJ,
virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
};
-class RGWPutMetadata : public RGWOp {
+class RGWPutMetadataAccount : public RGWOp {
+protected:
+ int ret;
+ set<string> rmattr_names;
+ RGWAccessControlPolicy policy;
+
+public:
+ RGWPutMetadataAccount()
+ : ret(0)
+ {}
+
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
+ policy.set_ctx(s->cct);
+ }
+ int verify_permission();
+ void pre_exec() { return; }
+ void execute();
+
+ virtual int get_params() = 0;
+ virtual void send_response() = 0;
+ virtual const string name() { return "put_account_metadata"; }
+ virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_ACCOUNT; }
+ virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
+};
+
+class RGWPutMetadataBucket : public RGWOp {
protected:
int ret;
set<string> rmattr_names;
string placement_rule;
public:
- RGWPutMetadata() {
- has_cors = false;
- has_policy = false;
- ret = 0;
+ RGWPutMetadataBucket()
+ : ret(0), has_policy(false), has_cors(false)
+ {}
+
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
+ policy.set_ctx(s->cct);
}
+ int verify_permission();
+ void pre_exec();
+ void execute();
+
+ virtual int get_params() = 0;
+ virtual void send_response() = 0;
+ virtual const string name() { return "put_bucket_metadata"; }
+ virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_BUCKET; }
+ virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
+};
+
+class RGWPutMetadataObject : public RGWOp {
+protected:
+ int ret;
+ RGWAccessControlPolicy policy;
+ string placement_rule;
+
+public:
+ RGWPutMetadataObject()
+ : ret(0)
+ {}
virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
RGWOp::init(store, s, h);
virtual int get_params() = 0;
virtual void send_response() = 0;
virtual const string name() { return "put_obj_metadata"; }
- virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA; }
+ virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_OBJECT; }
virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
};
#define CONT_REMOVE_ATTR_PREFIX "HTTP_X_REMOVE_CONTAINER_META_"
#define CONT_PUT_ATTR_PREFIX "HTTP_X_CONTAINER_META_"
-int RGWPutMetadata_ObjStore_SWIFT::get_params()
+static void get_rmattrs_from_headers(const req_state * const s,
+ const char * const put_prefix,
+ const char * const del_prefix,
+ set<string>& rmattr_names)
{
- if (s->has_bad_meta)
+ map<string, string, ltstr_nocase>& m = s->info.env->get_map();
+ map<string, string, ltstr_nocase>::const_iterator iter;
+ const size_t put_prefix_len = strlen(put_prefix);
+ const size_t del_prefix_len = strlen(del_prefix);
+
+ for (iter = m.begin(); iter != m.end(); ++iter) {
+ size_t prefix_len = 0;
+ const char * const p = iter->first.c_str();
+
+ if (strncasecmp(p, del_prefix, del_prefix_len) == 0) {
+ /* Explicitly requested removal. */
+ prefix_len = del_prefix_len;
+ } else if ((strncasecmp(p, put_prefix, put_prefix_len) == 0)
+ && iter->second.empty()) {
+ /* Removal requested by putting an empty value. */
+ prefix_len = put_prefix_len;
+ }
+
+ if (prefix_len > 0) {
+ string name(RGW_ATTR_META_PREFIX);
+ name.append(lowercase_dash_http_attr(p + prefix_len));
+ rmattr_names.insert(name);
+ }
+ }
+}
+
+int RGWPutMetadataAccount_ObjStore_SWIFT::get_params()
+{
+ if (s->has_bad_meta) {
return -EINVAL;
+ }
- const bool is_bucket_op = (!s->bucket_name_str.empty() && s->object.empty());
- const bool is_account_op = (s->bucket_name_str.empty());
+ get_rmattrs_from_headers(s, ACCT_PUT_ATTR_PREFIX, ACCT_REMOVE_ATTR_PREFIX, rmattr_names);
+ return 0;
+}
- const char *put_attr_prefix;
- const char *del_attr_prefix;
- if (is_bucket_op) {
- put_attr_prefix = CONT_PUT_ATTR_PREFIX;
- del_attr_prefix = CONT_REMOVE_ATTR_PREFIX;
- } else {
- put_attr_prefix = ACCT_PUT_ATTR_PREFIX;
- del_attr_prefix = ACCT_REMOVE_ATTR_PREFIX;
+void RGWPutMetadataAccount_ObjStore_SWIFT::send_response()
+{
+ if (!ret) {
+ /* FIXME: check the proper HTTP return code. */
+ ret = STATUS_NO_CONTENT;
}
+ set_req_state_err(s, ret);
+ dump_errno(s);
+ end_header(s, this);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
- const size_t put_attr_prefix_len = strlen(put_attr_prefix);
- const size_t del_attr_prefix_len = strlen(del_attr_prefix);
- if (is_bucket_op) {
- int r = get_swift_container_settings(s, store, &policy, &has_policy, &cors_config, &has_cors);
- if (r < 0) {
- return r;
- }
+int RGWPutMetadataBucket_ObjStore_SWIFT::get_params()
+{
+ if (s->has_bad_meta) {
+ return -EINVAL;
}
- if (is_bucket_op || is_account_op) {
- map<string, string, ltstr_nocase>& m = s->info.env->get_map();
- map<string, string, ltstr_nocase>::iterator iter;
- for (iter = m.begin(); iter != m.end(); ++iter) {
- size_t prefix_len = 0;
- const char *p = iter->first.c_str();
- if (strncasecmp(p, del_attr_prefix, del_attr_prefix_len) == 0) {
- // Explicitly requested removal
- prefix_len = del_attr_prefix_len;
- } else if ((strncasecmp(p, put_attr_prefix, put_attr_prefix_len) == 0) && iter->second.empty()) {
- // Removal requested by putting an empty value
- prefix_len = put_attr_prefix_len;
- }
- if (prefix_len > 0) {
- string name(RGW_ATTR_META_PREFIX);
- name.append(lowercase_dash_http_attr(p + prefix_len));
- rmattr_names.insert(name);
- }
- }
+ int r = get_swift_container_settings(s, store, &policy, &has_policy, &cors_config, &has_cors);
+ if (r < 0) {
+ return r;
+ }
+
+ get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX, CONT_REMOVE_ATTR_PREFIX, rmattr_names);
+ placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+ return 0;
+}
+
+void RGWPutMetadataBucket_ObjStore_SWIFT::send_response()
+{
+ if (!ret) {
+ ret = STATUS_NO_CONTENT;
}
+ set_req_state_err(s, ret);
+ dump_errno(s);
+ end_header(s, this);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
- if (!is_account_op) {
- placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+int RGWPutMetadataObject_ObjStore_SWIFT::get_params()
+{
+ if (s->has_bad_meta) {
+ return -EINVAL;
}
+ placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
return 0;
}
-void RGWPutMetadata_ObjStore_SWIFT::send_response()
+void RGWPutMetadataObject_ObjStore_SWIFT::send_response()
{
if (!ret) {
- /* Return 204 when post metadata on a container */
- if (s->object.empty())
- ret = STATUS_NO_CONTENT;
- else
- ret = STATUS_ACCEPTED;
+ ret = STATUS_ACCEPTED;
}
set_req_state_err(s, ret);
- if (!s->err.is_err())
+ if (!s->err.is_err()) {
dump_content_length(s, 0);
+ }
dump_errno(s);
end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
if (temp_url) {
return new RGWSetTempUrl_ObjStore_SWIFT;
}
- return new RGWPutMetadata_ObjStore_SWIFT;
+ return new RGWPutMetadataAccount_ObjStore_SWIFT;
}
RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::get_obj_op(bool get_data)
RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_post()
{
- return new RGWPutMetadata_ObjStore_SWIFT;
+ return new RGWPutMetadataBucket_ObjStore_SWIFT;
}
RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_options()
RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_post()
{
- return new RGWPutMetadata_ObjStore_SWIFT;
+ return new RGWPutMetadataObject_ObjStore_SWIFT;
}
RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_copy()