// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
+// vim: ts=8 sw=2 smarttab ft=cpp
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
-#include "include/assert.h"
+#include "include/ceph_assert.h"
#include "ceph_ver.h"
#include "common/Formatter.h"
#include "rgw_cors_swift.h"
#include "rgw_formats.h"
#include "rgw_client_io.h"
+#include "rgw_compression.h"
#include "rgw_auth.h"
#include "rgw_swift_auth.h"
#include "rgw_request.h"
#include "rgw_process.h"
+#include "rgw_zone.h"
+
+#include "services/svc_zone.h"
+
#include <array>
#include <sstream>
#include <memory>
prefix = s->info.args.get("prefix");
marker = s->info.args.get("marker");
end_marker = s->info.args.get("end_marker");
+ wants_reversed = s->info.args.exists("reverse");
- string limit_str = s->info.args.get("limit");
+ if (wants_reversed) {
+ std::swap(marker, end_marker);
+ }
+
+ std::string limit_str = s->info.args.get("limit");
if (!limit_str.empty()) {
- string err;
+ std::string err;
long l = strict_strtol(limit_str.c_str(), 10, &err);
if (!err.empty()) {
return -EINVAL;
}
static void dump_account_metadata(struct req_state * const s,
- const uint32_t buckets_count,
- const uint64_t buckets_object_count,
- const uint64_t buckets_size,
- const uint64_t buckets_size_rounded,
+ const RGWUsageStats& global_stats,
+ const std::map<std::string, RGWUsageStats> &policies_stats,
/* const */map<string, bufferlist>& attrs,
const RGWQuotaInfo& quota,
const RGWAccessControlPolicy_SWIFTAcct &policy)
/* Adding X-Timestamp to keep align with Swift API */
dump_header(s, "X-Timestamp", ceph_clock_now());
- dump_header(s, "X-Account-Container-Count", buckets_count);
- dump_header(s, "X-Account-Object-Count", buckets_object_count);
- dump_header(s, "X-Account-Bytes-Used", buckets_size);
- dump_header(s, "X-Account-Bytes-Used-Actual", buckets_size_rounded);
+ dump_header(s, "X-Account-Container-Count", global_stats.buckets_count);
+ dump_header(s, "X-Account-Object-Count", global_stats.objects_count);
+ dump_header(s, "X-Account-Bytes-Used", global_stats.bytes_used);
+ dump_header(s, "X-Account-Bytes-Used-Actual", global_stats.bytes_used_rounded);
+
+ for (const auto& kv : policies_stats) {
+ const auto& policy_name = camelcase_dash_http_attr(kv.first);
+ const auto& policy_stats = kv.second;
+
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Container-Count", policy_stats.buckets_count);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Object-Count", policy_stats.objects_count);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Bytes-Used", policy_stats.bytes_used);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Bytes-Used-Actual", policy_stats.bytes_used_rounded);
+ }
/* Dump TempURL-related stuff */
if (s->perm_mask == RGW_PERM_FULL_CONTROL) {
- auto iter = s->user->temp_url_keys.find(0);
- if (iter != std::end(s->user->temp_url_keys) && ! iter->second.empty()) {
+ auto iter = s->user->get_info().temp_url_keys.find(0);
+ if (iter != std::end(s->user->get_info().temp_url_keys) && ! iter->second.empty()) {
dump_header(s, "X-Account-Meta-Temp-Url-Key", iter->second);
}
- iter = s->user->temp_url_keys.find(1);
- if (iter != std::end(s->user->temp_url_keys) && ! iter->second.empty()) {
+ iter = s->user->get_info().temp_url_keys.find(1);
+ if (iter != std::end(s->user->get_info().temp_url_keys) && ! iter->second.empty()) {
dump_header(s, "X-Account-Meta-Temp-Url-Key-2", iter->second);
}
}
if (! s->cct->_conf->rgw_swift_enforce_content_length) {
/* Adding account stats in the header to keep align with Swift API */
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
dump_errno(s);
+ dump_header(s, "Accept-Ranges", "bytes");
end_header(s, NULL, NULL, NO_CONTENT_LENGTH, true);
}
if (! op_ret) {
dump_start(s);
s->formatter->open_array_section_with_attrs("account",
- FormatterAttrs("name", s->user->display_name.c_str(), NULL));
+ FormatterAttrs("name", s->user->get_display_name().c_str(), NULL));
sent_data = true;
}
}
-void RGWListBuckets_ObjStore_SWIFT::send_response_data(RGWUserBuckets& buckets)
+void RGWListBuckets_ObjStore_SWIFT::handle_listing_chunk(rgw::sal::RGWBucketList&& buckets)
+{
+ if (wants_reversed) {
+ /* Just store in the reversal buffer. Its content will be handled later,
+ * in send_response_end(). */
+ reverse_buffer.emplace(std::begin(reverse_buffer), std::move(buckets));
+ } else {
+ return send_response_data(buckets);
+ }
+}
+
+void RGWListBuckets_ObjStore_SWIFT::send_response_data(rgw::sal::RGWBucketList& buckets)
{
if (! sent_data) {
return;
* in applying the filter earlier as we really need to go through all
* entries regardless of it (the headers like X-Account-Container-Count
* aren't affected by specifying prefix). */
- const std::map<std::string, RGWBucketEnt>& m = buckets.get_buckets();
+ const std::map<std::string, rgw::sal::RGWBucket*>& m = buckets.get_buckets();
for (auto iter = m.lower_bound(prefix);
iter != m.end() && boost::algorithm::starts_with(iter->first, prefix);
++iter) {
- const RGWBucketEnt& obj = iter->second;
+ dump_bucket_entry(*iter->second);
+ }
+}
- s->formatter->open_object_section("container");
- s->formatter->dump_string("name", obj.bucket.name);
- if (need_stats) {
- s->formatter->dump_int("count", obj.count);
- s->formatter->dump_int("bytes", obj.size);
- }
- s->formatter->close_section();
- if (! s->cct->_conf->rgw_swift_enforce_content_length) {
- rgw_flush_formatter(s, s->formatter);
- }
+void RGWListBuckets_ObjStore_SWIFT::dump_bucket_entry(const rgw::sal::RGWBucket& obj)
+{
+ s->formatter->open_object_section("container");
+ s->formatter->dump_string("name", obj.get_name());
+
+ if (need_stats) {
+ s->formatter->dump_int("count", obj.get_count());
+ s->formatter->dump_int("bytes", obj.get_size());
+ }
+
+ s->formatter->close_section();
+
+ if (! s->cct->_conf->rgw_swift_enforce_content_length) {
+ rgw_flush_formatter(s, s->formatter);
+ }
+}
+
+void RGWListBuckets_ObjStore_SWIFT::send_response_data_reversed(rgw::sal::RGWBucketList& buckets)
+{
+ if (! sent_data) {
+ return;
+ }
+
+ /* Take care of the prefix parameter of Swift API. There is no business
+ * in applying the filter earlier as we really need to go through all
+ * entries regardless of it (the headers like X-Account-Container-Count
+ * aren't affected by specifying prefix). */
+ std::map<std::string, rgw::sal::RGWBucket*>& m = buckets.get_buckets();
+
+ auto iter = m.rbegin();
+ for (/* initialized above */;
+ iter != m.rend() && !boost::algorithm::starts_with(iter->first, prefix);
+ ++iter) {
+ /* NOP */;
+ }
+
+ for (/* iter carried */;
+ iter != m.rend() && boost::algorithm::starts_with(iter->first, prefix);
+ ++iter) {
+ dump_bucket_entry(*iter->second);
}
}
void RGWListBuckets_ObjStore_SWIFT::send_response_end()
{
+ if (wants_reversed) {
+ for (auto& buckets : reverse_buffer) {
+ send_response_data_reversed(buckets);
+ }
+ }
+
if (sent_data) {
s->formatter->close_section();
}
if (s->cct->_conf->rgw_swift_enforce_content_length) {
/* Adding account stats in the header to keep align with Swift API */
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
dump_errno(s);
- end_header(s, NULL, NULL, s->formatter->get_len(), true);
+ end_header(s, nullptr, nullptr, s->formatter->get_len(), true);
}
if (sent_data || s->cct->_conf->rgw_swift_enforce_content_length) {
marker = s->info.args.get("marker");
end_marker = s->info.args.get("end_marker");
max_keys = s->info.args.get("limit");
+
+ // non-standard
+ s->info.args.get_bool("allow_unordered", &allow_unordered, false);
+
+ delimiter = s->info.args.get("delimiter");
+
op_ret = parse_max_keys();
if (op_ret < 0) {
return op_ret;
}
+ // S3 behavior is to silently cap the max-keys.
+ // Swift behavior is to abort.
if (max > default_max)
return -ERR_PRECONDITION_FAILED;
- delimiter = s->info.args.get("delimiter");
-
string path_args;
if (s->info.args.exists("path")) { // should handle empty path
path_args = s->info.args.get("path");
}
static void dump_container_metadata(struct req_state *,
- const RGWBucketEnt&,
+ const rgw::sal::RGWBucket*,
const RGWQuotaInfo&,
const RGWBucketWebsiteConf&);
dump_container_metadata(s, bucket, bucket_quota,
s->bucket_info.website_conf);
- s->formatter->open_array_section_with_attrs("container", FormatterAttrs("name", s->bucket.name.c_str(), NULL));
+ s->formatter->open_array_section_with_attrs("container",
+ FormatterAttrs("name",
+ s->bucket.name.c_str(),
+ NULL));
while (iter != objs.end() || pref_iter != common_prefixes.end()) {
bool do_pref = false;
else
do_pref = true;
- if (do_objs && (marker.empty() || marker < key)) {
+ if (do_objs && (allow_unordered || marker.empty() || marker < key)) {
if (key.name.compare(path) == 0)
goto next;
}
rgw_flush_formatter_and_reset(s, s->formatter);
-}
+} // RGWListBucket_ObjStore_SWIFT::send_response
static void dump_container_metadata(struct req_state *s,
- const RGWBucketEnt& bucket,
+ const rgw::sal::RGWBucket* bucket,
const RGWQuotaInfo& quota,
const RGWBucketWebsiteConf& ws_conf)
{
/* Adding X-Timestamp to keep align with Swift API */
dump_header(s, "X-Timestamp", utime_t(s->bucket_info.creation_time));
- dump_header(s, "X-Container-Object-Count", bucket.count);
- dump_header(s, "X-Container-Bytes-Used", bucket.size);
- dump_header(s, "X-Container-Bytes-Used-Actual", bucket.size_rounded);
+ dump_header(s, "X-Container-Object-Count", bucket->get_count());
+ dump_header(s, "X-Container-Bytes-Used", bucket->get_size());
+ dump_header(s, "X-Container-Bytes-Used-Actual", bucket->get_size_rounded());
if (s->object.empty()) {
auto swift_policy = \
if (write_acl.size()) {
dump_header(s, "X-Container-Write", write_acl);
}
- if (!s->bucket_info.placement_rule.empty()) {
- dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule);
+ if (!s->bucket_info.placement_rule.name.empty()) {
+ dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule.name);
}
+ dump_header(s, "X-Storage-Class", s->bucket_info.placement_rule.get_storage_class());
/* Dump user-defined metadata items and generic attrs. */
const size_t PREFIX_LEN = sizeof(RGW_ATTR_META_PREFIX) - 1;
if (ws_conf.listing_enabled) {
dump_header(s, "X-Container-Meta-Web-Listings", "true");
}
+
+ /* Dump bucket's modification time. Compliance with the Swift API really
+ * needs that. */
+ dump_last_modified(s, s->bucket_mtime);
}
void RGWStatAccount_ObjStore_SWIFT::execute()
{
RGWStatAccount_ObjStore::execute();
- op_ret = rgw_get_user_attrs_by_uid(store, s->user->user_id, attrs);
+ op_ret = store->ctl()->user->get_attrs_by_uid(s->user->get_id(), &attrs, s->yield);
}
void RGWStatAccount_ObjStore_SWIFT::send_response()
if (op_ret >= 0) {
op_ret = STATUS_NO_CONTENT;
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
}
static int get_swift_container_settings(req_state * const s,
- RGWRados * const store,
+ rgw::sal::RGWRadosStore * const store,
RGWAccessControlPolicy * const policy,
bool * const has_policy,
uint32_t * rw_mask,
RGWCORSConfiguration * const cors_config,
bool * const has_cors)
{
- string read_list, write_list;
-
- const char * const read_attr = s->info.env->get("HTTP_X_CONTAINER_READ");
- if (read_attr) {
- read_list = read_attr;
- }
- const char * const write_attr = s->info.env->get("HTTP_X_CONTAINER_WRITE");
- if (write_attr) {
- write_list = write_attr;
- }
+ const char * const read_list = s->info.env->get("HTTP_X_CONTAINER_READ");
+ const char * const write_list = s->info.env->get("HTTP_X_CONTAINER_WRITE");
*has_policy = false;
- if (read_attr || write_attr) {
+ if (read_list || write_list) {
RGWAccessControlPolicy_SWIFT swift_policy(s->cct);
- const auto r = swift_policy.create(store,
- s->user->user_id,
- s->user->display_name,
+ const auto r = swift_policy.create(store->ctl()->user,
+ s->user->get_id(),
+ s->user->get_display_name(),
read_list,
write_list,
*rw_mask);
}
if (!has_policy) {
- policy.create_default(s->user->user_id, s->user->display_name);
+ policy.create_default(s->user->get_id(), s->user->get_display_name());
}
- location_constraint = store->get_zonegroup().api_name;
+ location_constraint = store->svc()->zone->get_zonegroup().api_name;
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", "");
+ placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
return get_swift_versioning_settings(s, swift_ver_location);
}
+static inline int handle_metadata_errors(req_state* const s, const int op_ret)
+{
+ if (op_ret == -EFBIG) {
+ /* Handle the custom error message of exceeding maximum custom attribute
+ * (stored as xattr) size. */
+ const auto error_message = boost::str(
+ boost::format("Metadata value longer than %lld")
+ % s->cct->_conf.get_val<Option::size_t>("rgw_max_attr_size"));
+ set_req_state_err(s, EINVAL, error_message);
+ return -EINVAL;
+ } else if (op_ret == -E2BIG) {
+ const auto error_message = boost::str(
+ boost::format("Too many metadata items; max %lld")
+ % s->cct->_conf.get_val<uint64_t>("rgw_max_attrs_num_in_req"));
+ set_req_state_err(s, EINVAL, error_message);
+ return -EINVAL;
+ }
+
+ return op_ret;
+}
+
void RGWCreateBucket_ObjStore_SWIFT::send_response()
{
- if (! op_ret)
- op_ret = STATUS_CREATED;
- else if (op_ret == -ERR_BUCKET_EXISTS)
- op_ret = STATUS_ACCEPTED;
- set_req_state_err(s, op_ret);
+ const auto meta_ret = handle_metadata_errors(s, op_ret);
+ if (meta_ret != op_ret) {
+ op_ret = meta_ret;
+ } else {
+ if (!op_ret) {
+ op_ret = STATUS_CREATED;
+ } else if (op_ret == -ERR_BUCKET_EXISTS) {
+ op_ret = STATUS_ACCEPTED;
+ }
+ set_req_state_err(s, op_ret);
+ }
+
dump_errno(s);
/* Propose ending HTTP header with 0 Content-Length header. */
end_header(s, NULL, NULL, 0);
}
}
+int RGWPutObj_ObjStore_SWIFT::update_slo_segment_size(rgw_slo_entry& entry) {
+
+ int r = 0;
+ const string& path = entry.path;
+
+ /* If the path starts with slashes, strip them all. */
+ const size_t pos_init = path.find_first_not_of('/');
+
+ if (pos_init == string::npos) {
+ return -EINVAL;
+ }
+
+ const size_t pos_sep = path.find('/', pos_init);
+ if (pos_sep == string::npos) {
+ return -EINVAL;
+ }
+
+ string bucket_name = path.substr(pos_init, pos_sep - pos_init);
+ string obj_name = path.substr(pos_sep + 1);
+
+ rgw_bucket bucket;
+
+ if (bucket_name.compare(s->bucket.name) != 0) {
+ RGWBucketInfo bucket_info;
+ map<string, bufferlist> bucket_attrs;
+ r = store->getRados()->get_bucket_info(store->svc(), s->user->get_id().tenant,
+ bucket_name, bucket_info, nullptr,
+ s->yield, &bucket_attrs);
+ if (r < 0) {
+ ldpp_dout(this, 0) << "could not get bucket info for bucket="
+ << bucket_name << dendl;
+ return r;
+ }
+ bucket = bucket_info.bucket;
+ } else {
+ bucket = s->bucket;
+ }
+
+ /* fetch the stored size of the seg (or error if not valid) */
+ rgw_obj_key slo_key(obj_name);
+ rgw_obj slo_seg(bucket, slo_key);
+
+ /* no prefetch */
+ RGWObjectCtx obj_ctx(store);
+ obj_ctx.set_atomic(slo_seg);
+
+ RGWRados::Object op_target(store->getRados(), s->bucket_info, obj_ctx, slo_seg);
+ RGWRados::Object::Read read_op(&op_target);
+
+ bool compressed;
+ RGWCompressionInfo cs_info;
+ map<std::string, buffer::list> attrs;
+ uint64_t size_bytes{0};
+
+ read_op.params.attrs = &attrs;
+ read_op.params.obj_size = &size_bytes;
+
+ r = read_op.prepare(s->yield);
+ if (r < 0) {
+ return r;
+ }
+
+ r = rgw_compression_info_from_attrset(attrs, compressed, cs_info);
+ if (r < 0) {
+ return -EIO;
+ }
+
+ if (compressed) {
+ size_bytes = cs_info.orig_size;
+ }
+
+ /* "When the PUT operation sees the multipart-manifest=put query
+ * parameter, it reads the request body and verifies that each
+ * segment object exists and that the sizes and ETags match. If
+ * there is a mismatch, the PUT operation fails."
+ */
+ if (entry.size_bytes &&
+ (entry.size_bytes != size_bytes)) {
+ return -EINVAL;
+ }
+
+ entry.size_bytes = size_bytes;
+
+ return 0;
+} /* RGWPutObj_ObjStore_SWIFT::update_slo_segment_sizes */
+
int RGWPutObj_ObjStore_SWIFT::get_params()
{
if (s->has_bad_meta) {
if (!s->length) {
const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
if (!encoding || strcmp(encoding, "chunked") != 0) {
- ldout(s->cct, 20) << "neither length nor chunked encoding" << dendl;
+ ldpp_dout(this, 20) << "neither length nor chunked encoding" << dendl;
return -ERR_LENGTH_REQUIRED;
}
supplied_etag = s->info.env->get("HTTP_ETAG");
if (!s->generic_attrs.count(RGW_ATTR_CONTENT_TYPE)) {
- ldout(s->cct, 5) << "content type wasn't provided, trying to guess" << dendl;
+ ldpp_dout(this, 5) << "content type wasn't provided, trying to guess" << dendl;
const char *suffix = strrchr(s->object.name.c_str(), '.');
if (suffix) {
suffix++;
}
}
- policy.create_default(s->user->user_id, s->user->display_name);
+ policy.create_default(s->user->get_id(), s->user->get_display_name());
int r = get_delete_at_param(s, delete_at);
if (r < 0) {
- ldout(s->cct, 5) << "ERROR: failed to get Delete-At param" << dendl;
+ ldpp_dout(this, 5) << "ERROR: failed to get Delete-At param" << dendl;
return r;
}
string multipart_manifest = s->info.args.get("multipart-manifest", &exists);
if (exists) {
if (multipart_manifest != "put") {
- ldout(s->cct, 5) << "invalid multipart-manifest http param: " << multipart_manifest << dendl;
+ ldpp_dout(this, 5) << "invalid multipart-manifest http param: " << multipart_manifest << dendl;
return -EINVAL;
}
slo_info = new RGWSLOInfo;
- int r = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len, &slo_info->raw_data, &slo_info->raw_data_len);
+ int r = 0;
+ std::tie(r, slo_info->raw_data) = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len);
if (r < 0) {
- ldout(s->cct, 5) << "failed to read input for slo r=" << r << dendl;
+ ldpp_dout(this, 5) << "failed to read input for slo r=" << r << dendl;
return r;
}
if ((int64_t)slo_info->entries.size() > s->cct->_conf->rgw_max_slo_entries) {
- ldout(s->cct, 5) << "too many entries in slo request: " << slo_info->entries.size() << dendl;
+ ldpp_dout(this, 5) << "too many entries in slo request: " << slo_info->entries.size() << dendl;
return -EINVAL;
}
MD5 etag_sum;
uint64_t total_size = 0;
- for (const auto& entry : slo_info->entries) {
- etag_sum.Update((const byte *)entry.etag.c_str(),
+ for (auto& entry : slo_info->entries) {
+ etag_sum.Update((const unsigned char *)entry.etag.c_str(),
entry.etag.length());
+
+ /* if size_bytes == 0, it should be replaced with the
+ * real segment size (which could be 0); this follows from the
+ * fact that Swift requires all segments to exist, but permits
+ * the size_bytes element to be omitted from the SLO manifest, see
+ * https://docs.openstack.org/swift/latest/api/large_objects.html
+ */
+ r = update_slo_segment_size(entry);
+ if (r < 0) {
+ return r;
+ }
+
total_size += entry.size_bytes;
- ldout(s->cct, 20) << "slo_part: " << entry.path
+ ldpp_dout(this, 20) << "slo_part: " << entry.path
<< " size=" << entry.size_bytes
<< " etag=" << entry.etag
<< dendl;
complete_etag(etag_sum, &lo_etag);
slo_info->total_size = total_size;
- ofs = slo_info->raw_data_len;
+ ofs = slo_info->raw_data.length();
}
return RGWPutObj_ObjStore::get_params();
void RGWPutObj_ObjStore_SWIFT::send_response()
{
- if (! op_ret) {
- op_ret = STATUS_CREATED;
+ const auto meta_ret = handle_metadata_errors(s, op_ret);
+ if (meta_ret) {
+ op_ret = meta_ret;
+ } else {
+ if (!op_ret) {
+ op_ret = STATUS_CREATED;
+ }
+ set_req_state_err(s, op_ret);
}
if (! lo_etag.empty()) {
}
static int get_swift_account_settings(req_state * const s,
- RGWRados * const store,
+ rgw::sal::RGWRadosStore * const store,
RGWAccessControlPolicy_SWIFTAcct * const policy,
bool * const has_policy)
{
const char * const acl_attr = s->info.env->get("HTTP_X_ACCOUNT_ACCESS_CONTROL");
if (acl_attr) {
RGWAccessControlPolicy_SWIFTAcct swift_acct_policy(s->cct);
- const bool r = swift_acct_policy.create(store,
- s->user->user_id,
- s->user->display_name,
+ const bool r = swift_acct_policy.create(store->ctl()->user,
+ s->user->get_id(),
+ s->user->get_display_name(),
string(acl_attr));
if (r != true) {
return -EINVAL;
void RGWPutMetadataAccount_ObjStore_SWIFT::send_response()
{
- if (! op_ret) {
- op_ret = STATUS_NO_CONTENT;
+ const auto meta_ret = handle_metadata_errors(s, op_ret);
+ if (meta_ret != op_ret) {
+ op_ret = meta_ret;
+ } else {
+ if (!op_ret) {
+ op_ret = STATUS_NO_CONTENT;
+ }
+ set_req_state_err(s, op_ret);
}
- set_req_state_err(s, op_ret);
+
dump_errno(s);
end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
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", "");
+ placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
return get_swift_versioning_settings(s, swift_ver_location);
}
void RGWPutMetadataBucket_ObjStore_SWIFT::send_response()
{
- if (!op_ret && (op_ret != -EINVAL)) {
- op_ret = STATUS_NO_CONTENT;
+ const auto meta_ret = handle_metadata_errors(s, op_ret);
+ if (meta_ret != op_ret) {
+ op_ret = meta_ret;
+ } else {
+ if (!op_ret && (op_ret != -EINVAL)) {
+ op_ret = STATUS_NO_CONTENT;
+ }
+ set_req_state_err(s, op_ret);
}
- set_req_state_err(s, op_ret);
+
dump_errno(s);
end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
/* Handle Swift object expiration. */
int r = get_delete_at_param(s, delete_at);
if (r < 0) {
- ldout(s->cct, 5) << "ERROR: failed to get Delete-At param" << dendl;
+ ldpp_dout(this, 5) << "ERROR: failed to get Delete-At param" << dendl;
return r;
}
- placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
dlo_manifest = s->info.env->get("HTTP_X_OBJECT_MANIFEST");
return 0;
void RGWPutMetadataObject_ObjStore_SWIFT::send_response()
{
- if (! op_ret) {
- op_ret = STATUS_ACCEPTED;
+ const auto meta_ret = handle_metadata_errors(s, op_ret);
+ if (meta_ret != op_ret) {
+ op_ret = meta_ret;
+ } else {
+ if (!op_ret) {
+ op_ret = STATUS_ACCEPTED;
+ }
+ set_req_state_err(s, op_ret);
}
- set_req_state_err(s, op_ret);
+
if (!s->is_err()) {
dump_content_length(s, 0);
}
+
dump_errno(s);
end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
{
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_CONTENT_TYPE);
if (iter != attrs.end()) {
- content_type = iter->second.c_str();
+ content_type = rgw_bl_str(iter->second);
}
}
-static void dump_object_metadata(struct req_state * const s,
- map<string, bufferlist> attrs)
+static void dump_object_metadata(const DoutPrefixProvider* dpp, struct req_state * const s,
+ const map<string, bufferlist>& attrs)
{
map<string, string> response_attrs;
const auto aiter = rgw_to_http_attrs.find(name);
if (aiter != std::end(rgw_to_http_attrs)) {
- response_attrs[aiter->second] = kv.second.c_str();
+ response_attrs[aiter->second] = rgw_bl_str(kv.second);
} else if (strcmp(name, RGW_ATTR_SLO_UINDICATOR) == 0) {
- // this attr has an extra length prefix from ::encode() in prior versions
+ // this attr has an extra length prefix from encode() in prior versions
dump_header(s, "X-Object-Meta-Static-Large-Object", "True");
} else if (strncmp(name, RGW_ATTR_META_PREFIX,
sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
if (iter != std::end(attrs)) {
utime_t delete_at;
try {
- ::decode(delete_at, iter->second);
+ decode(delete_at, iter->second);
if (!delete_at.is_zero()) {
dump_header(s, "X-Delete-At", delete_at.sec());
}
} catch (buffer::error& err) {
- ldout(s->cct, 0) << "ERROR: cannot decode object's " RGW_ATTR_DELETE_AT
+ ldpp_dout(dpp, 0) << "ERROR: cannot decode object's " RGW_ATTR_DELETE_AT
" attr, ignoring"
<< dendl;
}
int RGWCopyObj_ObjStore_SWIFT::init_dest_policy()
{
- dest_policy.create_default(s->user->user_id, s->user->display_name);
+ dest_policy.create_default(s->user->get_id(), s->user->get_display_name());
return 0;
}
int r = get_delete_at_param(s, delete_at);
if (r < 0) {
- ldout(s->cct, 5) << "ERROR: failed to get Delete-At param" << dendl;
+ ldpp_dout(this, 5) << "ERROR: failed to get Delete-At param" << dendl;
return r;
}
/* Dump X-Copied-From-Account. */
/* XXX tenant */
- dump_header(s, "X-Copied-From-Account", url_encode(s->user->user_id.id));
+ dump_header(s, "X-Copied-From-Account", url_encode(s->user->get_id().id));
/* Dump X-Copied-From-Last-Modified. */
dump_time_header(s, "X-Copied-From-Last-Modified", src_mtime);
dump_last_modified(s, mtime);
dump_copy_info();
get_contype_from_attrs(attrs, content_type);
- dump_object_metadata(s, attrs);
+ dump_object_metadata(this, s, attrs);
end_header(s, this, !content_type.empty() ? content_type.c_str()
: "binary/octet-stream");
} else {
} else {
auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
- dump_etag(s, iter->second);
+ dump_etag(s, iter->second.to_str());
}
}
get_contype_from_attrs(attrs, content_type);
- dump_object_metadata(s, attrs);
+ dump_object_metadata(this, s, attrs);
}
end_header(s, this, !content_type.empty() ? content_type.c_str()
while (cioin.getline(buf, sizeof(buf))) {
string path_str(buf);
- ldout(s->cct, 20) << "extracted Bulk Delete entry: " << path_str << dendl;
+ ldpp_dout(this, 20) << "extracted Bulk Delete entry: " << path_str << dendl;
RGWBulkDelete::acct_path_t path;
RGWBulkUploadOp_ObjStore_SWIFT::create_stream()
{
class SwiftStreamGetter : public StreamGetter {
+ const DoutPrefixProvider* dpp;
const size_t conlen;
size_t curpos;
req_state* const s;
public:
- SwiftStreamGetter(req_state* const s, const size_t conlen)
- : conlen(conlen),
+ SwiftStreamGetter(const DoutPrefixProvider* dpp, req_state* const s, const size_t conlen)
+ : dpp(dpp),
+ conlen(conlen),
curpos(0),
s(s) {
}
static_cast<size_t>(s->cct->_conf->rgw_max_chunk_size);
const size_t max_to_read = std::min({ want, conlen - curpos, max_chunk_size });
- ldout(s->cct, 20) << "bulk_upload: get_at_most max_to_read="
+ ldpp_dout(dpp, 20) << "bulk_upload: get_at_most max_to_read="
<< max_to_read
<< ", dst.c_str()=" << reinterpret_cast<intptr_t>(dst.c_str()) << dendl;
}
ssize_t get_exactly(size_t want, ceph::bufferlist& dst) override {
- ldout(s->cct, 20) << "bulk_upload: get_exactly want=" << want << dendl;
+ ldpp_dout(dpp, 20) << "bulk_upload: get_exactly want=" << want << dendl;
/* FIXME: do this in a loop. */
const auto ret = get_at_most(want, dst);
- ldout(s->cct, 20) << "bulk_upload: get_exactly ret=" << ret << dendl;
+ ldpp_dout(dpp, 20) << "bulk_upload: get_exactly ret=" << ret << dendl;
if (ret < 0) {
return ret;
} else if (static_cast<size_t>(ret) != want) {
op_ret = -EINVAL;
return nullptr;
} else {
- ldout(s->cct, 20) << "bulk upload: create_stream for length="
+ ldpp_dout(this, 20) << "bulk upload: create_stream for length="
<< s->length << dendl;
const size_t conlen = atoll(s->length);
- return std::unique_ptr<SwiftStreamGetter>(new SwiftStreamGetter(s, conlen));
+ return std::unique_ptr<SwiftStreamGetter>(new SwiftStreamGetter(this, s, conlen));
}
}
<< R"(<!DOCTYPE cross-domain-policy SYSTEM )"
<< R"("http://www.adobe.com/xml/dtds/cross-domain-policy.dtd" >)" << "\n"
<< R"(<cross-domain-policy>)" << "\n"
- << g_conf->rgw_cross_domain_policy << "\n"
+ << g_conf()->rgw_cross_domain_policy << "\n"
<< R"(</cross-domain-policy>)";
dump_body(s, ss.str());
if (!swiftinfo_sig.empty() &&
!swiftinfo_expires.empty() &&
- !is_expired(swiftinfo_expires, s->cct)) {
+ !is_expired(swiftinfo_expires, this)) {
is_admin_info_enabled = true;
}
s->formatter->close_section();
}
else {
- pair.second.list_data(*(s->formatter), *(s->cct->_conf), *store);
+ pair.second.list_data(*(s->formatter), s->cct->_conf, *store->getRados());
}
}
}
void RGWInfo_ObjStore_SWIFT::list_swift_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("swift");
- formatter.dump_int("max_file_size", config.rgw_max_put_size);
+ formatter.dump_int("max_file_size", config->rgw_max_put_size);
formatter.dump_int("container_listing_limit", RGW_LIST_BUCKETS_LIMIT_MAX);
string ceph_version(CEPH_GIT_NICE_VER);
formatter.dump_string("version", ceph_version);
- formatter.dump_int("max_meta_name_length", 81);
+
+ const size_t max_attr_name_len = \
+ g_conf().get_val<Option::size_t>("rgw_max_attr_name_len");
+ if (max_attr_name_len) {
+ const size_t meta_name_limit = \
+ max_attr_name_len - strlen(RGW_ATTR_PREFIX RGW_AMZ_META_PREFIX);
+ formatter.dump_int("max_meta_name_length", meta_name_limit);
+ }
+
+ const size_t meta_value_limit = g_conf().get_val<Option::size_t>("rgw_max_attr_size");
+ if (meta_value_limit) {
+ formatter.dump_int("max_meta_value_length", meta_value_limit);
+ }
+
+ const size_t meta_num_limit = \
+ g_conf().get_val<uint64_t>("rgw_max_attrs_num_in_req");
+ if (meta_num_limit) {
+ formatter.dump_int("max_meta_count", meta_num_limit);
+ }
formatter.open_array_section("policies");
- RGWZoneGroup& zonegroup = store.get_zonegroup();
+ const RGWZoneGroup& zonegroup = store.svc.zone->get_zonegroup();
for (const auto& placement_targets : zonegroup.placement_targets) {
formatter.open_object_section("policy");
- if (placement_targets.second.name.compare(zonegroup.default_placement) == 0)
+ if (placement_targets.second.name.compare(zonegroup.default_placement.name) == 0)
formatter.dump_bool("default", true);
formatter.dump_string("name", placement_targets.second.name.c_str());
formatter.close_section();
}
void RGWInfo_ObjStore_SWIFT::list_tempauth_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("tempauth");
formatter.close_section();
}
void RGWInfo_ObjStore_SWIFT::list_tempurl_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("tempurl");
}
void RGWInfo_ObjStore_SWIFT::list_slo_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("slo");
- formatter.dump_int("max_manifest_segments", config.rgw_max_slo_entries);
+ formatter.dump_int("max_manifest_segments", config->rgw_max_slo_entries);
formatter.close_section();
}
-bool RGWInfo_ObjStore_SWIFT::is_expired(const std::string& expires, CephContext* cct)
+bool RGWInfo_ObjStore_SWIFT::is_expired(const std::string& expires, const DoutPrefixProvider *dpp)
{
string err;
const utime_t now = ceph_clock_now();
const uint64_t expiration = (uint64_t)strict_strtoll(expires.c_str(),
10, &err);
if (!err.empty()) {
- ldout(cct, 5) << "failed to parse siginfo_expires: " << err << dendl;
+ ldpp_dout(dpp, 5) << "failed to parse siginfo_expires: " << err << dendl;
return true;
}
if (expiration <= (uint64_t)now.sec()) {
- ldout(cct, 5) << "siginfo expired: " << expiration << " <= " << now.sec() << dendl;
+ ldpp_dout(dpp, 5) << "siginfo expired: " << expiration << " <= " << now.sec() << dendl;
return true;
}
}
-void RGWFormPost::init(RGWRados* const store,
+void RGWFormPost::init(rgw::sal::RGWRadosStore* const store,
req_state* const s,
RGWHandler* const dialect_handler)
{
static_cast<uint64_t>(strict_strtoll(max_str.c_str(), 10, &err));
if (! err.empty()) {
- ldout(s->cct, 5) << "failed to parse FormPost's max_file_size: " << err
+ ldpp_dout(this, 5) << "failed to parse FormPost's max_file_size: " << err
<< dendl;
return 0;
}
static_cast<uint64_t>(strict_strtoll(expires.c_str(), 10, &err));
if (! err.empty()) {
- dout(5) << "failed to parse FormPost's expires: " << err << dendl;
+ ldpp_dout(this, 5) << "failed to parse FormPost's expires: " << err << dendl;
return false;
}
const utime_t now = ceph_clock_now();
if (expires_timestamp <= static_cast<uint64_t>(now.sec())) {
- dout(5) << "FormPost form expired: "
+ ldpp_dout(this, 5) << "FormPost form expired: "
<< expires_timestamp << " <= " << now.sec() << dendl;
return false;
}
const std::string form_signature = get_part_str(ctrl_parts, "signature");
try {
- get_owner_info(s, *s->user);
+ get_owner_info(s, s->user->get_info());
s->auth.identity = rgw::auth::transform_old_authinfo(s);
} catch (...) {
- ldout(s->cct, 5) << "cannot get user_info of account's owner" << dendl;
+ ldpp_dout(this, 5) << "cannot get user_info of account's owner" << dendl;
return false;
}
- for (const auto& kv : s->user->temp_url_keys) {
+ for (const auto& kv : s->user->get_info().temp_url_keys) {
const int temp_url_key_num = kv.first;
const string& temp_url_key = kv.second;
const auto local_sig = sig_helper.get_signature();
- ldout(s->cct, 20) << "FormPost signature [" << temp_url_key_num << "]"
+ ldpp_dout(this, 20) << "FormPost signature [" << temp_url_key_num << "]"
<< " (calculated): " << local_sig << dendl;
if (sig_helper.is_equal_to(form_signature)) {
return true;
} else {
- ldout(s->cct, 5) << "FormPost's signature mismatch: "
+ ldpp_dout(this, 5) << "FormPost's signature mismatch: "
<< local_sig << " != " << form_signature << dendl;
}
}
* now. It will be initialized in RGWHandler_REST_SWIFT::postauth_init(). */
const string& bucket_name = s->init_state.url_bucket;
+ auto user_ctl = store->ctl()->user;
+
/* TempURL in Formpost only requires that bucket name is specified. */
if (bucket_name.empty()) {
throw -EPERM;
if (uid.tenant.empty()) {
const rgw_user tenanted_uid(uid.id, uid.id);
- if (rgw_get_user_info_by_uid(store, tenanted_uid, uinfo) >= 0) {
+ if (user_ctl->get_info_by_uid(tenanted_uid, &uinfo, s->yield) >= 0) {
/* Succeeded. */
bucket_tenant = uinfo.user_id.tenant;
found = true;
}
}
- if (!found && rgw_get_user_info_by_uid(store, uid, uinfo) < 0) {
+ if (!found && user_ctl->get_info_by_uid(uid, &uinfo, s->yield) < 0) {
throw -EPERM;
} else {
bucket_tenant = uinfo.user_id.tenant;
/* Need to get user info of bucket owner. */
RGWBucketInfo bucket_info;
- int ret = store->get_bucket_info(*static_cast<RGWObjectCtx *>(s->obj_ctx),
+ int ret = store->getRados()->get_bucket_info(store->svc(),
bucket_tenant, bucket_name,
- bucket_info, nullptr);
+ bucket_info, nullptr, s->yield);
if (ret < 0) {
throw ret;
}
- ldout(s->cct, 20) << "temp url user (bucket owner): " << bucket_info.owner
+ ldpp_dout(this, 20) << "temp url user (bucket owner): " << bucket_info.owner
<< dendl;
- if (rgw_get_user_info_by_uid(store, bucket_info.owner, owner_info) < 0) {
+ if (user_ctl->get_info_by_uid(bucket_info.owner, &owner_info, s->yield) < 0) {
throw -EPERM;
}
}
return ret;
}
- policy.create_default(s->user->user_id, s->user->display_name);
+ policy.create_default(s->user->get_id(), s->user->get_display_name());
/* Let's start parsing the HTTP body by parsing each form part step-
* by-step till encountering the first part with file data. */
return ret;
}
- if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
- ldout(s->cct, 20) << "read part header -- part.name="
+ if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) {
+ ldpp_dout(this, 20) << "read part header -- part.name="
<< part.name << dendl;
for (const auto& pair : part.fields) {
- ldout(s->cct, 20) << "field.name=" << pair.first << dendl;
- ldout(s->cct, 20) << "field.val=" << pair.second.val << dendl;
- ldout(s->cct, 20) << "field.params:" << dendl;
+ ldpp_dout(this, 20) << "field.name=" << pair.first << dendl;
+ ldpp_dout(this, 20) << "field.val=" << pair.second.val << dendl;
+ ldpp_dout(this, 20) << "field.params:" << dendl;
for (const auto& param_pair : pair.second.params) {
- ldout(s->cct, 20) << " " << param_pair.first
+ ldpp_dout(this, 20) << " " << param_pair.first
<< " -> " << param_pair.second << dendl;
}
}
class RGWGetErrorPage : public RGWGetObj_ObjStore_SWIFT {
public:
- RGWGetErrorPage(RGWRados* const store,
+ RGWGetErrorPage(rgw::sal::RGWRadosStore* const store,
RGWHandler_REST* const handler,
req_state* const s,
const int http_ret) {
class RGWMovedPermanently: public RGWOp {
const std::string location;
public:
- RGWMovedPermanently(const std::string& location)
+ explicit RGWMovedPermanently(const std::string& location)
: location(location) {
}
end_header(s, this);
}
- const string name() override {
+ const char* name() const override {
return "RGWMovedPermanently";
}
};
public:
/* Taking prefix_override by value to leverage std::string r-value ref
* ctor and thus avoid extra memory copying/increasing ref counter. */
- RGWWebsiteListing(std::string prefix_override)
+ explicit RGWWebsiteListing(std::string prefix_override)
: prefix_override(std::move(prefix_override)) {
}
};
/* First, get attrset of the object we'll try to retrieve. */
RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
- obj_ctx.obj.set_atomic(obj);
- obj_ctx.obj.set_prefetch_data(obj);
+ obj_ctx.set_atomic(obj);
+ obj_ctx.set_prefetch_data(obj);
RGWObjState* state = nullptr;
- if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
+ if (store->getRados()->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false, s->yield) < 0) {
return false;
}
return subdir_marker == content_type && state->size <= 1;
}
-bool RGWSwiftWebsiteHandler::is_index_present(const std::string& index)
+bool RGWSwiftWebsiteHandler::is_index_present(const std::string& index) const
{
rgw_obj obj(s->bucket, index);
RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
- obj_ctx.obj.set_atomic(obj);
- obj_ctx.obj.set_prefetch_data(obj);
+ obj_ctx.set_atomic(obj);
+ obj_ctx.set_prefetch_data(obj);
RGWObjState* state = nullptr;
- if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
+ if (store->getRados()->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false, s->yield) < 0) {
return false;
}
int RGWSwiftWebsiteHandler::retarget_bucket(RGWOp* op, RGWOp** new_op)
{
- ldout(s->cct, 10) << "Starting retarget" << dendl;
+ ldpp_dout(s, 10) << "Starting retarget" << dendl;
RGWOp* op_override = nullptr;
/* In Swift static web content is served if the request is anonymous or
int RGWSwiftWebsiteHandler::retarget_object(RGWOp* op, RGWOp** new_op)
{
- ldout(s->cct, 10) << "Starting object retarget" << dendl;
+ ldpp_dout(s, 10) << "Starting object retarget" << dendl;
RGWOp* op_override = nullptr;
/* In Swift static web content is served if the request is anonymous or
}
-int RGWHandler_REST_SWIFT::authorize()
+int RGWHandler_REST_SWIFT::authorize(const DoutPrefixProvider *dpp)
{
- return rgw::auth::Strategy::apply(auth_strategy, s);
+ return rgw::auth::Strategy::apply(dpp, auth_strategy, s);
}
int RGWHandler_REST_SWIFT::postauth_init()
struct req_init_state* t = &s->init_state;
/* XXX Stub this until Swift Auth sets account into URL. */
- s->bucket_tenant = s->user->user_id.tenant;
+ s->bucket_tenant = s->user->get_tenant();
s->bucket_name = t->url_bucket;
dout(10) << "s->object=" <<
<< dendl;
int ret;
- ret = validate_tenant_name(s->bucket_tenant);
+ ret = rgw_validate_tenant_name(s->bucket_tenant);
if (ret)
return ret;
ret = validate_bucket_name(s->bucket_name);
* We don't allow cross-tenant copy at present. It requires account
* names in the URL for Swift.
*/
- s->src_tenant_name = s->user->user_id.tenant;
+ s->src_tenant_name = s->user->get_tenant();
s->src_bucket_name = t->src_bucket;
ret = validate_bucket_name(s->src_bucket_name);
int RGWHandler_REST_SWIFT::validate_bucket_name(const string& bucket)
{
- int ret = RGWHandler_REST::validate_bucket_name(bucket);
- if (ret < 0)
- return ret;
+ const size_t len = bucket.size();
- int len = bucket.size();
+ if (len > MAX_BUCKET_NAME_LEN) {
+ /* Bucket Name too long. Generate custom error message and bind it
+ * to an R-value reference. */
+ const auto msg = boost::str(
+ boost::format("Container name length of %lld longer than %lld")
+ % len % int(MAX_BUCKET_NAME_LEN));
+ set_req_state_err(s, ERR_INVALID_BUCKET_NAME, msg);
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ const auto ret = RGWHandler_REST::validate_bucket_name(bucket);
+ if (ret < 0) {
+ return ret;
+ }
if (len == 0)
return 0;
const char *s = bucket.c_str();
- for (int i = 0; i < len; ++i, ++s) {
+ for (size_t i = 0; i < len; ++i, ++s) {
if (*(unsigned char *)s == 0xff)
return -ERR_INVALID_BUCKET_NAME;
+ if (*(unsigned char *)s == '/')
+ return -ERR_INVALID_BUCKET_NAME;
}
return 0;
}
if ('\0' == req_name[0]) {
- return g_conf->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
+ return g_conf()->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
}
req = req_name;
size_t pos = req.find('/');
- if (std::string::npos != pos && g_conf->rgw_swift_url_prefix != "/") {
- bool cut_url = g_conf->rgw_swift_url_prefix.length();
+ if (std::string::npos != pos && g_conf()->rgw_swift_url_prefix != "/") {
+ bool cut_url = g_conf()->rgw_swift_url_prefix.length();
first = req.substr(0, pos);
- if (first.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ if (first.compare(g_conf()->rgw_swift_url_prefix) == 0) {
if (cut_url) {
/* Rewind to the "v1/..." part. */
next_tok(req, first, '/');
}
}
- } else if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ } else if (req.compare(g_conf()->rgw_swift_url_prefix) == 0) {
s->formatter = new RGWFormatter_Plain;
return -ERR_BAD_URL;
} else {
}
std::string tenant_path;
- if (! g_conf->rgw_swift_tenant_name.empty()) {
+ if (! g_conf()->rgw_swift_tenant_name.empty()) {
tenant_path = "/AUTH_";
- tenant_path.append(g_conf->rgw_swift_tenant_name);
+ tenant_path.append(g_conf()->rgw_swift_tenant_name);
}
/* verify that the request_uri conforms with what's expected */
- char buf[g_conf->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
+ char buf[g_conf()->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
int blen;
- if (g_conf->rgw_swift_url_prefix == "/") {
+ if (g_conf()->rgw_swift_url_prefix == "/") {
blen = sprintf(buf, "/v1%s", tenant_path.c_str());
} else {
blen = sprintf(buf, "/%s/v1%s",
- g_conf->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
+ g_conf()->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
}
if (strncmp(reqbuf, buf, blen) != 0) {
next_tok(req, ver, '/');
- if (!tenant_path.empty() || g_conf->rgw_swift_account_in_url) {
+ if (!tenant_path.empty() || g_conf()->rgw_swift_account_in_url) {
string account_name;
next_tok(req, account_name, '/');
return 0;
}
-int RGWHandler_REST_SWIFT::init(RGWRados* store, struct req_state* s,
+int RGWHandler_REST_SWIFT::init(rgw::sal::RGWRadosStore* store, struct req_state* s,
rgw::io::BasicClient *cio)
{
struct req_init_state *t = &s->init_state;
s->dialect = "swift";
- const char *copy_source = s->info.env->get("HTTP_X_COPY_FROM");
- if (copy_source) {
+ std::string copy_source = s->info.env->get("HTTP_X_COPY_FROM", "");
+ if (! copy_source.empty()) {
bool result = RGWCopyObj::parse_copy_location(copy_source, t->src_bucket,
s->src_object);
if (!result)
}
if (s->op == OP_COPY) {
- const char *req_dest = s->info.env->get("HTTP_DESTINATION");
- if (!req_dest)
+ std::string req_dest = s->info.env->get("HTTP_DESTINATION", "");
+ if (req_dest.empty())
return -ERR_BAD_URL;
- string dest_bucket_name;
+ std::string dest_bucket_name;
rgw_obj_key dest_obj_key;
bool result =
RGWCopyObj::parse_copy_location(req_dest, dest_bucket_name,
if (!result)
return -ERR_BAD_URL;
- string dest_object = dest_obj_key.name;
+ std::string dest_object = dest_obj_key.name;
/* convert COPY operation into PUT */
t->src_bucket = t->url_bucket;
s->op = OP_PUT;
}
+ s->info.storage_class = s->info.env->get("HTTP_X_OBJECT_STORAGE_CLASS", "");
+
return RGWHandler_REST::init(store, s, cio);
}
{
int ret = RGWHandler_REST_SWIFT::init_from_header(s, frontend_prefix);
if (ret < 0) {
- ldout(s->cct, 10) << "init_from_header returned err=" << ret << dendl;
+ ldpp_dout(s, 10) << "init_from_header returned err=" << ret << dendl;
return nullptr;
}