]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
filestore: escape the xattr chunk names
authorYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 25 Oct 2010 23:35:48 +0000 (16:35 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 25 Oct 2010 23:36:24 +0000 (16:36 -0700)
src/os/FileStore.cc

index 37d3e6fab90d6269572d985601bfb5ad6f9e64a5..06cd6bc402d0ad8e70f9d72c80af163210815611 100644 (file)
@@ -132,15 +132,69 @@ int sys_listxattr(const char *fn, char *names, size_t len)
 static void get_raw_xattr_name(const char *name, int i, char *raw_name, int raw_len)
 {
   int r;
+  int pos = 0;
+
+  while (*name) {
+    switch (*name) {
+    case '@': /* escape it */
+      pos += 2;
+      assert (pos < raw_len - 1);
+      *raw_name = '@';
+      raw_name++;
+      *raw_name = '@';
+      break;
+    default:
+      pos++;
+      assert(pos < raw_len - 1);
+      *raw_name = *name;
+      break;
+    }
+    name++;
+    raw_name++;
+  }
 
-  if (!i)
-    r = snprintf(raw_name, raw_len, "%s", name);
-  else
-    r = snprintf(raw_name, raw_len, "%s@%d", name, i);
-
-  assert(r < raw_len);
+  if (!i) {
+    *raw_name = '\0';
+  } else {
+    r = snprintf(raw_name, raw_len, "@%d", i);
+    assert(r < raw_len - pos);
+  }
 }
 
+static int translate_raw_name(const char *raw_name, char *name, int name_len, bool *is_first)
+{
+  int pos = 0;
+
+  generic_dout(0) << "translate_raw_name raw_name=" << raw_name << dendl;
+  const char *n = name;
+
+  *is_first = true;
+  while (*raw_name) {
+    switch (*raw_name) {
+    case '@': /* escape it */
+      raw_name++;
+      if (!*raw_name)
+        break;
+      if (*raw_name != '@') {
+        *is_first = false;
+        goto done;
+      }
+
+    /* fall through */
+    default:
+      *name = *raw_name;
+      break;
+    }
+    pos++;
+    assert(pos < name_len);
+    name++;
+    raw_name++;
+  }
+done:
+  *name = '\0';
+  generic_dout(0) << "translate_raw_name name=" << n << dendl;
+  return pos;
+}
 
 int do_getxattr_len(const char *fn, const char *name)
 {
@@ -278,14 +332,18 @@ int do_listxattr(const char *fn, char *names, size_t len) {
   char *dest_end = names + len;
 
   while (p < end) {
+    char name[ATTR_MAX_NAME_LEN * 2 + 16];
     int attr_len = strlen(p);
-    if (!strchr(p, '@')) {
-      if (dest + attr_len > dest_end) {
+    bool is_first;
+    int name_len = translate_raw_name(p, name, sizeof(name), &is_first);
+    if (is_first)  {
+      generic_dout(0) << "dest+name_len=" << (void *)(dest+name_len) << " dest_end=" << (void *)dest_end << dendl;
+      if (dest + name_len > dest_end) {
         r = -ERANGE;
         goto done;
       }
-      strcpy(dest, p);
-      dest += attr_len + 1;
+      strcpy(dest, name);
+      dest += name_len + 1;
     }
     p += attr_len + 1;
   }