]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: multiple swift fixes and cleanups
authorYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 14 Oct 2011 20:20:20 +0000 (13:20 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 14 Oct 2011 20:20:20 +0000 (13:20 -0700)
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_formats.cc
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_swift_auth.cc

index 23a2e7de0f36331168a52ad52e9584f0d6b4768e..20fb7a0f88d79ff7d05444e8fea670f160686e0c 100644 (file)
@@ -92,14 +92,47 @@ std::ostream& operator<<(std::ostream& oss, const rgw_err &err)
   return oss;
 }
 
+static bool check_str_end(const char *s)
+{
+  if (!s)
+    return false;
+
+  while (*s) {
+    if (!isspace(*s))
+      return false;
+    s++;
+  }
+  return true;
+}
+
+static bool parse_rfc850(const char *s, struct tm *t)
+{
+  return check_str_end(strptime(s, "%A, %d-%b-%y %H:%M:%S GMT", t));
+}
+
+static bool parse_asctime(const char *s, struct tm *t)
+{
+  return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
+}
+
+static bool parse_rfc1123(const char *s, struct tm *t)
+{
+  return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S GMT", t));
+}
+
+bool parse_rfc2616(const char *s, struct tm *t)
+{
+  return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t);
+}
+
 int parse_time(const char *time_str, time_t *time)
 {
   struct tm tm;
-  memset(&tm, 0, sizeof(struct tm));
-  if (!strptime(time_str, "%a, %d %b %Y %H:%M:%S %Z", &tm))
+
+  if (!parse_rfc2616(time_str, &tm))
     return -EINVAL;
 
-  *time = mktime(&tm);
+  *time = timegm(&tm);
 
   return 0;
 }
index 8b88fc1a438d15dbeb01ea75af671a3862b0c590..de8980f285492f95b8ef91c5319f45e3f17ca859 100644 (file)
@@ -96,6 +96,11 @@ using ceph::crypto::MD5;
   state->bytes_received += olen; \
 } while (0)
 
+#define STATUS_CREATED          1900
+#define STATUS_ACCEPTED         1901
+#define STATUS_NO_CONTENT       1902
+#define STATUS_PARTIAL_CONTENT  1903
+
 #define ERR_INVALID_BUCKET_NAME 2000
 #define ERR_INVALID_OBJECT_NAME 2001
 #define ERR_NO_SUCH_BUCKET      2002
@@ -110,6 +115,9 @@ using ceph::crypto::MD5;
 #define ERR_LENGTH_REQUIRED     2011
 #define ERR_REQUEST_TIME_SKEWED 2012
 #define ERR_BUCKET_EXISTS       2013
+#define ERR_BAD_URL             2014
+#define ERR_PRECONDITION_FAILED 2015
+#define ERR_NOT_MODIFIED        2016
 #define ERR_USER_SUSPENDED      2100
 #define ERR_INTERNAL_ERROR      2200
 
@@ -828,8 +836,10 @@ static inline const char *rgw_obj_category_name(RGWObjCategory category)
   return "unknown";
 }
 
-/** */
+/** time parsing */
 extern int parse_time(const char *time_str, time_t *time);
+extern bool parse_rfc2616(const char *s, struct tm *t);
+
 /** Check if a user has a permission on that ACL */
 extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int user_perm_mask, int perm);
 /** Check if the req_state's user has the necessary permissions
index b392224555ebba6f6d5e52477e80defdce08e39d..092cc028df71d9b446ce281d24e179e90923a103 100644 (file)
@@ -118,6 +118,7 @@ void RGWFormatter_Plain::dump_format(const char *name, const char *fmt, ...)
 {
   char buf[LARGE_SIZE];
   va_list ap;
+  const char *format;
 
   struct plain_stack_entry& entry = stack.back();
 
@@ -133,7 +134,12 @@ void RGWFormatter_Plain::dump_format(const char *name, const char *fmt, ...)
   va_start(ap, fmt);
   vsnprintf(buf, LARGE_SIZE, fmt, ap);
   va_end(ap);
-  write_data("%s\n", buf);
+  if (len)
+    format = "\n%s";
+  else
+    format = "%s";
+
+  write_data(format, buf);
 }
 
 int RGWFormatter_Plain::get_len() const
index cd4eb9194a26debdbfccdee46ac76adce3a65c7f..e4ee1b7f19a4b3ba2abe90d614f2979403ffb404 100644 (file)
@@ -267,7 +267,10 @@ void RGWGetObj::execute()
   if (ret < 0)
     goto done;
 
-  init_common();
+  ret = init_common();
+  if (ret < 0)
+    goto done;
+dout(0) << __FILE__ << ":" << __LINE__ << " unmod_ptr=" << (void *)unmod_ptr << dendl;
 
   obj.init(s->bucket, s->object_str);
   rgwstore->set_atomic(s->obj_ctx, obj);
@@ -315,10 +318,12 @@ int RGWGetObj::init_common()
     mod_ptr = &mod_time;
   }
 
+dout(0) << __FILE__ << ":" << __LINE__ << " if_unmod=" << (void *)if_unmod << dendl;
   if (if_unmod) {
     if (parse_time(if_unmod, &unmod_time) < 0)
       return -EINVAL;
     unmod_ptr = &unmod_time;
+dout(0) << __FILE__ << ":" << __LINE__ << " unmod_ptr=" << (void *)unmod_ptr << dendl;
   }
 
   return 0;
index 815fcb586f43ea339afe24774df0c56c4e9e5a51..293a30fb574f4c63aea9b52961de081442cee116 100644 (file)
@@ -1399,6 +1399,8 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
       goto done_err;
   }
 
+  dout(0) << __FILE__ << ":" << __LINE__ << " mod_ptr=" << (void *)mod_ptr << " unmod_ptr=" << (void *)unmod_ptr << dendl;
+
   /* Convert all times go GMT to make them compatible */
   if (mod_ptr || unmod_ptr) {
     struct tm mtm;
@@ -1410,13 +1412,10 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     }
     ctime = mktime(gmtm);
 
-    r = -ECANCELED;
     if (mod_ptr) {
       dout(10) << "If-Modified-Since: " << *mod_ptr << " Last-Modified: " << ctime << dendl;
       if (ctime < *mod_ptr) {
-        err->http_ret = 304;
-        err->s3_code = "NotModified";
-
+        r = -ERR_NOT_MODIFIED;
         goto done_err;
       }
     }
@@ -1424,8 +1423,7 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     if (unmod_ptr) {
       dout(10) << "If-UnModified-Since: " << *unmod_ptr << " Last-Modified: " << ctime << dendl;
       if (ctime > *unmod_ptr) {
-        err->http_ret = 412;
-        err->s3_code = "PreconditionFailed";
+        r = -ERR_PRECONDITION_FAILED;
         goto done_err;
       }
     }
@@ -1435,12 +1433,10 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     if (r < 0)
       goto done_err;
 
-    r = -ECANCELED;
     if (if_match) {
       dout(10) << "ETag: " << etag.c_str() << " " << " If-Match: " << if_match << dendl;
       if (strcmp(if_match, etag.c_str())) {
-        err->http_ret = 412;
-        err->s3_code = "PreconditionFailed";
+        r = -ERR_PRECONDITION_FAILED;
         goto done_err;
       }
     }
@@ -1448,8 +1444,7 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     if (if_nomatch) {
       dout(10) << "ETag: " << etag.c_str() << " " << " If-NoMatch: " << if_nomatch << dendl;
       if (strcmp(if_nomatch, etag.c_str()) == 0) {
-        err->http_ret = 304;
-        err->s3_code = "NotModified";
+        r = -ERR_NOT_MODIFIED;
         goto done_err;
       }
     }
index 14dd3a9224ff11ef9619e47cfd15ddc98d4b9584..e562593e9fe995a041e5b545bc007fde0f127397 100644 (file)
@@ -28,10 +28,11 @@ struct rgw_html_errors {
 
 const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
     { 0, 200, "" },
-    { 201, 201, "Created" },
-    { 202, 202, "Accepted" },
-    { 204, 204, "NoContent" },
-    { 206, 206, "" },
+    { STATUS_CREATED, 201, "Created" },
+    { STATUS_ACCEPTED, 202, "Accepted" },
+    { STATUS_NO_CONTENT, 204, "NoContent" },
+    { STATUS_PARTIAL_CONTENT, 206, "" },
+    { ERR_NOT_MODIFIED, 304, "NotModified" },
     { EINVAL, 400, "InvalidArgument" },
     { ERR_INVALID_DIGEST, 400, "InvalidDigest" },
     { ERR_BAD_DIGEST, 400, "BadDigest" },
@@ -53,6 +54,7 @@ const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
     { ETIMEDOUT, 408, "RequestTimeout" },
     { EEXIST, 409, "BucketAlreadyExists" },
     { ENOTEMPTY, 409, "BucketNotEmpty" },
+    { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" },
     { ERANGE, 416, "InvalidRange" },
     { ERR_INTERNAL_ERROR, 500, "InternalError" },
 };
@@ -61,6 +63,7 @@ const static struct rgw_html_errors RGW_HTML_SWIFT_ERRORS[] = {
     { EACCES, 401, "AccessDenied" },
     { EPERM, 401, "AccessDenied" },
     { ERR_USER_SUSPENDED, 401, "UserSuspended" },
+    { ERR_BAD_URL, 412, "Bad URL" },
 };
 
 #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -202,7 +205,7 @@ void end_header(struct req_state *s, const char *content_type)
     dump_start(s);
     s->formatter->open_object_section("Error");
     if (!s->err.s3_code.empty())
-      s->formatter->dump_format("Code", "%s", s->err.s3_code.c_str());
+      s->formatter->dump_string("Code", s->err.s3_code.c_str());
     if (!s->err.message.empty())
       s->formatter->dump_format("Message", s->err.message.c_str());
     s->formatter->close_section();
@@ -237,6 +240,7 @@ int RGWGetObj_REST::get_params()
   range_str = s->env->get("HTTP_RANGE");
   if_mod = s->env->get("HTTP_IF_MODIFIED_SINCE");
   if_unmod = s->env->get("HTTP_IF_UNMODIFIED_SINCE");
+dout(0) << __FILE__ << ":" << __LINE__ << " if_unmod=" << (void *)if_unmod << dendl;
   if_match = s->env->get("HTTP_IF_MATCH");
   if_nomatch = s->env->get("HTTP_IF_NONE_MATCH");
 
@@ -396,7 +400,7 @@ static void next_tok(string& str, string& tok, char delim)
   }
 }
 
-void init_entities_from_header(struct req_state *s)
+static int init_entities_from_header(struct req_state *s)
 {
   string req;
   string first;
@@ -430,7 +434,8 @@ void init_entities_from_header(struct req_state *s)
     } else {
       s->host_bucket = NULL;
     }
-  } else s->host_bucket = NULL;
+  } else
+    s->host_bucket = NULL;
 
   const char *req_name = s->path_name;
   const char *p;
@@ -465,10 +470,25 @@ void init_entities_from_header(struct req_state *s)
       }
     }
   } else {
+    if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+      s->prot_flags |= RGW_REST_SWIFT;
+      delete s->formatter;
+      s->format = 0;
+      s->formatter = new RGWFormatter_Plain;
+      return -ERR_BAD_URL;
+    }
     first = req;
   }
 
   if (s->prot_flags & RGW_REST_SWIFT) {
+    /* verify that the request_uri conforms with what's expected */
+    char buf[g_conf->rgw_swift_url_prefix.length() + 16];
+    int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
+    if (s->path_name_url[0] != '/' ||
+        s->path_name_url.compare(0, blen, buf) !=  0) {
+      return -ENOENT;
+    }
+
     s->format = 0;
     delete s->formatter;
     s->formatter = new RGWFormatter_Plain;
@@ -529,6 +549,7 @@ void init_entities_from_header(struct req_state *s)
   }
 done:
   s->formatter->reset();
+  return 0;
 }
 
 static void line_unfold(const char *line, string& sdest)
@@ -747,7 +768,10 @@ int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx)
   else
     s->op = OP_UNKNOWN;
 
-  init_entities_from_header(s);
+  ret = init_entities_from_header(s);
+  if (ret)
+    return ret;
+
   switch (s->op) {
   case OP_PUT:
     if (s->object && !s->args.sub_resource_exists("acl")) {
@@ -765,14 +789,6 @@ int RGWHandler_REST::preprocess(struct req_state *s, FCGX_Request *fcgx)
     break;
   }
 
-  if (s->prot_flags & RGW_REST_SWIFT) {
-    char buf[g_conf->rgw_swift_url_prefix.length() + 16];
-    int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
-    if (s->path_name_url[0] != '/' ||
-        s->path_name_url.compare(0, blen, buf) !=  0)
-      ret = -ENOENT;
-  }
-
   if (ret)
     return ret;
 
index f8c63b95bbd0130462d55ff5f486eaa9e35bf492..e79ff7240fa8f4f1ceea9f7b1d2ecec0d2063c4d 100644 (file)
@@ -72,7 +72,7 @@ int RGWGetObj_REST_S3::send_response(void *handle)
   }
 
   if (range_str && !ret)
-    ret = 206; /* partial content */
+    ret = STATUS_PARTIAL_CONTENT;
 done:
   set_req_state_err(s, ret);
 
@@ -177,7 +177,7 @@ void RGWDeleteBucket_REST_S3::send_response()
 {
   int r = ret;
   if (!r)
-    r = 204;
+    r = STATUS_NO_CONTENT;
 
   set_req_state_err(s, r);
   dump_errno(s);
@@ -200,7 +200,7 @@ void RGWDeleteObj_REST_S3::send_response()
 {
   int r = ret;
   if (!r)
-    r = 204;
+    r = STATUS_NO_CONTENT;
 
   set_req_state_err(s, r);
   dump_errno(s);
@@ -291,7 +291,7 @@ void RGWAbortMultipart_REST_S3::send_response()
 {
   int r = ret;
   if (!r)
-    r = 204;
+    r = STATUS_NO_CONTENT;
 
   set_req_state_err(s, r);
   dump_errno(s);
@@ -528,39 +528,6 @@ static void get_canon_resource(struct req_state *s, string& dest)
   dout(10) << "get_canon_resource(): dest=" << dest << dendl;
 }
 
-static bool check_str_end(const char *s)
-{
-  if (!s)
-    return false;
-
-  while (*s) {
-    if (!isspace(*s))
-      return false;
-    s++;
-  }
-  return true;
-}
-
-static bool parse_rfc850(const char *s, struct tm *t)
-{
-  return check_str_end(strptime(s, "%A, %d-%b-%y %H:%M:%S GMT", t));
-}
-
-static bool parse_asctime(const char *s, struct tm *t)
-{
-  return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
-}
-
-static bool parse_rfc1123(const char *s, struct tm *t)
-{
-  return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S GMT", t));
-}
-
-static bool parse_rfc2616(const char *s, struct tm *t)
-{
-  return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t);
-}
-
 static inline bool is_base64_for_content_md5(unsigned char c) {
   return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
 }
index 67a2a33275f76b2c70dcc084138a032defaf8b72..cf2dc4c188d8dad3bc90e86ba0d43cc5b7b53ae1 100644 (file)
@@ -40,7 +40,7 @@ void RGWListBuckets_REST_SWIFT::send_response()
   s->formatter->close_section();
 
   if (!ret && s->formatter->get_len() == 0)
-    ret = 204;
+    ret = STATUS_NO_CONTENT;
 
   set_req_state_err(s, ret);
   dump_errno(s);
@@ -100,7 +100,7 @@ void RGWListBucket_REST_SWIFT::send_response()
   s->formatter->close_section();
 
   if (!ret && s->formatter->get_len() == 0)
-    ret = 204;
+    ret = STATUS_NO_CONTENT;
   else if (ret > 0)
     ret = 0;
 
@@ -140,7 +140,7 @@ static void dump_account_metadata(struct req_state *s, uint32_t buckets_count,
 void RGWStatAccount_REST_SWIFT::send_response()
 {
   if (ret >= 0) {
-    ret = 204;
+    ret = STATUS_NO_CONTENT;
     dump_account_metadata(s, buckets_count, buckets_objcount, buckets_size);
   }
 
@@ -154,7 +154,7 @@ void RGWStatAccount_REST_SWIFT::send_response()
 void RGWStatBucket_REST_SWIFT::send_response()
 {
   if (ret >= 0) {
-    ret = 204;
+    ret = STATUS_NO_CONTENT;
     dump_container_metadata(s, bucket);
   }
 
@@ -168,9 +168,9 @@ void RGWStatBucket_REST_SWIFT::send_response()
 void RGWCreateBucket_REST_SWIFT::send_response()
 {
   if (!ret)
-    ret = 201; // "created"
+    ret = STATUS_CREATED;
   else if (ret == -ERR_BUCKET_EXISTS)
-    ret = 202;
+    ret = STATUS_ACCEPTED;
   set_req_state_err(s, ret);
   dump_errno(s);
   end_header(s);
@@ -181,7 +181,7 @@ void RGWDeleteBucket_REST_SWIFT::send_response()
 {
   int r = ret;
   if (!r)
-    r = 204;
+    r = STATUS_NO_CONTENT;
 
   set_req_state_err(s, r);
   dump_errno(s);
@@ -192,7 +192,7 @@ void RGWDeleteBucket_REST_SWIFT::send_response()
 void RGWPutObj_REST_SWIFT::send_response()
 {
   if (!ret)
-    ret = 201; // "created"
+    ret = STATUS_CREATED;
   dump_etag(s, etag.c_str());
   set_req_state_err(s, ret);
   dump_errno(s);
@@ -204,7 +204,7 @@ void RGWDeleteObj_REST_SWIFT::send_response()
 {
   int r = ret;
   if (!r)
-    r = 204;
+    r = STATUS_NO_CONTENT;
 
   set_req_state_err(s, r);
   dump_errno(s);
@@ -248,7 +248,7 @@ int RGWGetObj_REST_SWIFT::send_response(void *handle)
   }
 
   if (range_str && !ret)
-    ret = 206; /* partial content */
+    ret = -STATUS_PARTIAL_CONTENT;
 
   if (ret)
     set_req_state_err(s, ret);
index 8305a0299c37219a3dff9b70091c7107539ee926..fe85b436673d1cc93244f5f9f8e0ec7756fe9577 100644 (file)
@@ -178,7 +178,7 @@ void RGW_SWIFT_Auth_Get::execute()
     CGI_PRINTF(s, "X-Storage-Token: AUTH_rgwtk%s\n", buf);
   }
 
-  ret = 204;
+  ret = STATUS_NO_CONTENT;
 
 done:
   set_req_state_err(s, ret);