]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
s3: handle 'get bucket' opereation
authorYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 12 Jun 2009 21:28:59 +0000 (14:28 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 12 Jun 2009 22:44:07 +0000 (15:44 -0700)
src/Makefile.am
src/s3/s3access.h
src/s3/s3gw.c [deleted file]
src/s3/s3gw.cc [new file with mode: 0644]

index f0dec0793a31f8688d3b9029b45ffbac6f77ce83..e7517932ee74cac5bdd7374cb10082169c82ce15 100644 (file)
@@ -123,7 +123,7 @@ testradospp_LDADD = librados.la libcrush.la
 radosacl_SOURCES = radosacl.cc
 radosacl_LDADD = librados.la libcrush.la
 
-s3gw_SOURCES = s3/s3gw.c s3/s3fs.c
+s3gw_SOURCES = s3/s3gw.cc s3/s3fs.c
 s3gw_LDADD = librados.la libcrush.la -lfcgi
 ## object classes
 
index e16f4f72d58f0031ae6c89bcc94dfb70fd92f9db..db2f801cbbc893f806772a1237d8f52b9cf6cce2 100644 (file)
@@ -1,9 +1,17 @@
 #ifndef __S3ACCESS_H
 #define __S3ACCESS_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef void *S3AccessHandle;
 
 int list_buckets_init(const char *id, S3AccessHandle *handle);
 int list_buckets_next(const char *id, char *buf, int size, S3AccessHandle *handle);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/src/s3/s3gw.c b/src/s3/s3gw.c
deleted file mode 100644 (file)
index 0789b59..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "fcgiapp.h"
-
-#include "s3access.h"
-
-
-struct req_state {
-   FCGX_Stream *in;
-   FCGX_Stream *out;
-   int indent;
-};
-
-static void init_state(struct req_state *s, FCGX_Stream *in, FCGX_Stream *out)
-{
-  s->in = in;
-  s->out = out;
-  s->indent = 0;
-}
-
-static void buf_to_hex(const unsigned char *buf, int len, char *str)
-{
-  int i;
-  str[0] = '\0';
-  for (i = 0; i < len; i++) {
-    sprintf(&str[i*2], "%02x", (int)buf[i]);
-  }
-}
-
-static void open_section(struct req_state *s, const char *name)
-{
-  FCGX_FPrintF(s->out, "%*s<%s>\n", s->indent, "", name);
-  ++s->indent;
-}
-
-static void close_section(struct req_state *s, const char *name)
-{
-  --s->indent;
-  FCGX_FPrintF(s->out, "%*s</%s>\n", s->indent, "", name);
-}
-
-static void dump_value(struct req_state *s, const char *name, const char *val)
-{
-  FCGX_FPrintF(s->out, "%*s<%s>%s</%s>\n", s->indent, "", name, val, name);
-}
-
-static void dump_entry(struct req_state *s, const char *val)
-{
-  FCGX_FPrintF(s->out, "%*s<?%s?>\n", s->indent, "", val);
-}
-
-
-
-static void dump_owner(struct req_state *s, const char *id, int id_size, const char *name)
-{
-  char id_str[id_size*2 + 1];
-
-  buf_to_hex((const unsigned char *)id, id_size, id_str);
-
-  open_section(s, "Owner");
-  dump_value(s, "ID", id_str);
-  dump_value(s, "DisplayName", name);
-  close_section(s, "Owner");
-}
-
-static void dump_start(struct req_state *s)
-{
-  dump_entry(s, "xml version=\"1.0\" encoding=\"UTF-8\"");
-}
-
-static void list_all_buckets_start(struct req_state *s)
-{
-  open_section(s, "ListAllMyBucketsResult");
-}
-
-static void list_all_buckets_end(struct req_state *s)
-{
-  close_section(s, "ListAllMyBucketsResult");
-}
-
-
-static void dump_bucket(struct req_state *s, const char *name, const char *date)
-{
-  open_section(s, "Bucket");
-  dump_value(s, "Name", name);
-  dump_value(s, "CreationDate", date);
-  close_section(s, "Bucket");
-}
-
-void do_retrieve(struct req_state *s, const char *path_name)
-{
-  unsigned long long id = 0x0123456789ABCDEF;
-  S3AccessHandle handle;
-  int r;
-#define BUF_SIZE 256
-  char buf[BUF_SIZE];
-  dump_start(s);
-  list_all_buckets_start(s);
-  dump_owner(s, (const char *)&id, sizeof(id), "foobi");
-  r = list_buckets_init((const char *)&id, &handle);
-  open_section(s, "Buckets");
-  while (r >= 0) {
-    r = list_buckets_next((const char *)&id, buf, BUF_SIZE, &handle);
-    if (r < 0)
-      continue;
-    dump_bucket(s, buf, "123123");
-  }
-  close_section(s, "Buckets");
-  list_all_buckets_end(s);
-}
-
-int main(void)
-{
-  int i, scale;
-  FCGX_Stream *in, *out, *err;
-  FCGX_ParamArray envp;
-  struct req_state s;
-
-  while (FCGX_Accept(&in, &out, &err, &envp) >= 0) 
-  {
-    char *method;
-    char* path_name;
-
-    FCGX_FPrintF(out,"Content-type: text/plain\r\n\r\n");      
-
-    method = FCGX_GetParam("REQUEST_METHOD",envp);
-    if (!method)
-      continue;
-
-    path_name = FCGX_GetParam("SCRIPT_NAME",envp);
-    if (!path_name)  /* really shouldn't happen.. */
-      continue;
-
-    init_state(&s, in, out);
-
-    if (strcmp(method, "GET") == 0)
-      do_retrieve(&s, path_name);
-  }
-  return 0;
-}
diff --git a/src/s3/s3gw.cc b/src/s3/s3gw.cc
new file mode 100644 (file)
index 0000000..cde1a9e
--- /dev/null
@@ -0,0 +1,292 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "fcgiapp.h"
+
+#include "s3access.h"
+
+#include <map>
+#include <string>
+#include <iostream>
+
+using namespace std;
+
+
+struct req_state {
+   FCGX_Stream *in;
+   FCGX_Stream *out;
+   int indent;
+   const char *path_name;
+   const char *host;
+   const char *method;
+   const char *query;
+};
+
+
+class NameVal
+{
+   string str;
+   string name;
+   string val;
+ public:
+    NameVal(string nv) : str(nv) {}
+
+    int parse();
+
+    string& get_name() { return name; }
+    string& get_val() { return val; }
+};
+
+int NameVal::parse()
+{
+  int delim_pos = str.find('=');
+
+  if (delim_pos < 0)
+    return -1;
+
+  name = str.substr(0, delim_pos);
+  val = str.substr(delim_pos + 1);
+
+  cout << "parsed: name=" << name << " val=" << val << std::endl;
+  return 0; 
+}
+
+class XMLArgs
+{
+  string str, empty_str;
+  map<string, string> val_map;
+ public:
+   XMLArgs(string s) : str(s) {}
+   int parse();
+   string& get(string& name);
+   string& get(const char *name);
+};
+
+int XMLArgs::parse()
+{
+  int pos, fpos;
+  bool end = false;
+  if (str[pos] == '?') pos++;
+
+  while (!end) {
+    fpos = str.find('&', pos);
+    if (fpos  < pos) {
+       end = true;
+       fpos = str.size(); 
+    }
+    NameVal nv(str.substr(pos, fpos - pos));
+    if (nv.parse() >= 0) {
+      val_map[nv.get_name()] = nv.get_val();
+    }
+
+    pos = fpos + 1;  
+  }
+
+  return 0;
+}
+
+string& XMLArgs::get(string& name)
+{
+  map<string, string>::iterator iter;
+  iter = val_map.find(name);
+  if (iter == val_map.end())
+    return empty_str;
+  return iter->second;
+}
+
+string& XMLArgs::get(const char *name)
+{
+  string s(name);
+  return get(s);
+}
+
+static void init_state(struct req_state *s, FCGX_ParamArray envp, FCGX_Stream *in, FCGX_Stream *out)
+{
+  s->in = in;
+  s->out = out;
+  s->indent = 0;
+  s->path_name = FCGX_GetParam("SCRIPT_NAME", envp);
+  s->method = FCGX_GetParam("REQUEST_METHOD", envp);
+  s->host = FCGX_GetParam("HTTP_HOST", envp);
+  s->query = FCGX_GetParam("QUERY_STRING", envp);
+  
+}
+
+static void buf_to_hex(const unsigned char *buf, int len, char *str)
+{
+  int i;
+  str[0] = '\0';
+  for (i = 0; i < len; i++) {
+    sprintf(&str[i*2], "%02x", (int)buf[i]);
+  }
+}
+
+static void open_section(struct req_state *s, const char *name)
+{
+  FCGX_FPrintF(s->out, "%*s<%s>\n", s->indent, "", name);
+  ++s->indent;
+}
+
+static void close_section(struct req_state *s, const char *name)
+{
+  --s->indent;
+  FCGX_FPrintF(s->out, "%*s</%s>\n", s->indent, "", name);
+}
+
+static void dump_value(struct req_state *s, const char *name, const char *val)
+{
+  FCGX_FPrintF(s->out, "%*s<%s>%s</%s>\n", s->indent, "", name, val, name);
+}
+
+static void dump_entry(struct req_state *s, const char *val)
+{
+  FCGX_FPrintF(s->out, "%*s<?%s?>\n", s->indent, "", val);
+}
+
+
+
+static void dump_owner(struct req_state *s, const char *id, int id_size, const char *name)
+{
+  char id_str[id_size*2 + 1];
+
+  buf_to_hex((const unsigned char *)id, id_size, id_str);
+
+  open_section(s, "Owner");
+  dump_value(s, "ID", id_str);
+  dump_value(s, "DisplayName", name);
+  close_section(s, "Owner");
+}
+
+static void dump_start(struct req_state *s)
+{
+  dump_entry(s, "xml version=\"1.0\" encoding=\"UTF-8\"");
+}
+
+static void list_all_buckets_start(struct req_state *s)
+{
+  open_section(s, "ListAllMyBucketsResult");
+}
+
+static void list_all_buckets_end(struct req_state *s)
+{
+  close_section(s, "ListAllMyBucketsResult");
+}
+
+
+static void dump_bucket(struct req_state *s, const char *name, const char *date)
+{
+  open_section(s, "Bucket");
+  dump_value(s, "Name", name);
+  dump_value(s, "CreationDate", date);
+  close_section(s, "Bucket");
+}
+
+void do_list_buckets(struct req_state *s)
+{
+  unsigned long long id = 0x0123456789ABCDEF;
+  S3AccessHandle handle;
+  int r;
+#define BUF_SIZE 256
+  char buf[BUF_SIZE];
+  list_all_buckets_start(s);
+  dump_owner(s, (const char *)&id, sizeof(id), "foobi");
+  r = list_buckets_init((const char *)&id, &handle);
+  open_section(s, "Buckets");
+  while (r >= 0) {
+    r = list_buckets_next((const char *)&id, buf, BUF_SIZE, &handle);
+    if (r < 0)
+      continue;
+    dump_bucket(s, buf, "123123");
+  }
+  close_section(s, "Buckets");
+  list_all_buckets_end(s);
+}
+
+void do_list_objects(struct req_state *s)
+{
+  int pos;
+  string bucket, host_str;
+  string prefix, marker, max_keys, delimiter;
+  const char *p;
+  unsigned long long id = 0x0123456789ABCDEF;
+
+  if (s->path_name[0] == '/') {
+    string tmp = s->path_name;
+    bucket = tmp.substr(1);
+    p = s->query;
+  } else if (s->path_name [0] == '?') {
+    if (!s->host)
+      return;
+    host_str = s->host;
+    pos = host_str.find('.');
+    if (pos >= 0) {
+      bucket = host_str.substr(pos);
+    } else {
+      bucket = host_str;
+    }
+    p = s->path_name;
+  } else {
+    return;
+  }
+
+  XMLArgs args(p);
+  args.parse();
+
+  prefix = args.get("prefix");
+  marker = args.get("marker");
+  max_keys = args.get("max-keys");
+  delimiter = args.get("delimiter");
+
+  open_section(s, "ListBucketResult");
+  dump_value(s, "Name", bucket.c_str()); 
+  if (!prefix.empty())
+    dump_value(s, "Prefix", prefix.c_str());
+  if (!marker.empty())
+    dump_value(s, "Marker", marker.c_str());
+  if (!max_keys.empty())
+    dump_value(s, "MaxKeys", max_keys.c_str());
+  if (!delimiter.empty())
+    dump_value(s, "Delimiter", delimiter.c_str());
+  open_section(s, "Contents");
+  dump_value(s, "Key", "Nelson");
+  dump_value(s, "LastModified", "2006-01-01T12:00:00.000Z");
+  dump_value(s, "ETag", "&quot;828ef3fdfa96f00ad9f27c383fc9ac7f&quot;");
+  dump_value(s, "Size", "5");
+  dump_value(s, "StorageClass", "STANDARD");
+  dump_owner(s, (const char *)&id, sizeof(id), "foobi");
+  close_section(s, "Contents");
+  close_section(s, "ListBucketResult");
+  //if (args.get("name"))
+}
+
+void do_retrieve(struct req_state *s)
+{
+  dump_start(s);
+  if (strcmp(s->path_name, "/") == 0)
+    do_list_buckets(s);
+  else
+    do_list_objects(s);
+}
+
+int main(void)
+{
+  FCGX_Stream *in, *out, *err;
+  FCGX_ParamArray envp;
+  struct req_state s;
+
+  while (FCGX_Accept(&in, &out, &err, &envp) >= 0) 
+  {
+    FCGX_FPrintF(out,"Content-type: text/plain\r\n\r\n");      
+
+    init_state(&s, envp, in, out);
+
+    if (!s.method)
+      continue;
+
+    if (strcmp(s.method, "GET") == 0)
+      do_retrieve(&s);
+  }
+  return 0;
+}
+