Index: /trunk/Nebulous/nebclient/src/nebclient.c
===================================================================
--- /trunk/Nebulous/nebclient/src/nebclient.c	(revision 21460)
+++ /trunk/Nebulous/nebclient/src/nebclient.c	(revision 21461)
@@ -4,5 +4,5 @@
  * Copyright (C) 2005  Joshua Hoblitt
  *
- * $Id: nebclient.c,v 1.56 2008-12-14 22:48:35 eugene Exp $
+ * $Id: nebclient.c,v 1.57 2009-02-13 02:45:47 jhoblitt Exp $
  */
 
@@ -336,5 +336,4 @@
 bool nebSetXattr(nebServer *server, const char *key, const char *name, const char *value, nebCR flag)
 {
-
     REQUIRE_SERVER;
 
@@ -363,4 +362,99 @@
     if (!response) {
         nebSetErr(server, "can not set xattr");
+        return false;
+    }
+
+    return true;
+}
+
+
+char *nebGetXattr(nebServer *server, const char *key, const char *name) 
+{
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+        return false;
+    }
+    if (!name) {
+        nebSetErr(server, "parameter 'name' may not be NULL");
+        return false;
+    }
+
+    struct ns1__getxattr_USCOREobjectResponse response;
+    if (soap_call_ns1__getxattr_USCOREobject(server->soap, server->endpoint,
+        NULL, (char *)key, (char *)name, (char **)&response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return false;
+    }
+
+    if (!(char *)response.result) {
+        nebSetErr(server, "server returned no result");
+        return NULL;
+    }
+
+    char *value = xmalloc(strlen((char *)response.result) + 1);
+    strcpy(value, (char *)response.result);
+
+    return value;
+}
+
+
+int nebListXattr(nebServer *server, const char *key, char ***xattrs)
+{
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+        return false;
+    }
+
+    struct ns1__listxattr_USCOREobjectResponse response;
+    if (soap_call_ns1__listxattr_USCOREobject(server->soap, server->endpoint,
+        NULL, (char *)key, &response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return false;
+    }
+
+    int resultElements = response.result->__size;
+
+    if (xattrs) {
+        char **resultArray = response.result->__ptr;
+        *xattrs = xmalloc(resultElements * sizeof(char *));
+        if (resultElements) {
+            for (int i = 0; i < resultElements; i++) {
+                *xattrs[i] = xmalloc(strlen(resultArray[i]) + 1);
+                strcpy(*xattrs[i], resultArray[i]);
+            }
+
+        }
+    }
+
+    return resultElements;
+}
+
+
+bool nebRemoveXattr(nebServer *server, const char *key, const char *name)
+{
+    REQUIRE_SERVER;
+
+    if (!key) {
+        nebSetErr(server, "parameter 'key' may not be NULL");
+        return false;
+    }
+    if (!name) {
+        nebSetErr(server, "parameter 'name' may not be NULL");
+        return false;
+    }
+
+    int response;
+    if (soap_call_ns1__removexattr_USCOREobject(server->soap, server->endpoint,
+        NULL, (char *)key, (char *)name, &response) != SOAP_OK) {
+        nebSetServerErr(server);
+        return false;
+    }
+
+    if (!response) {
+        nebSetErr(server, "can not remove xattr");
         return false;
     }
Index: /trunk/Nebulous/nebclient/src/nebclient.h
===================================================================
--- /trunk/Nebulous/nebclient/src/nebclient.h	(revision 21460)
+++ /trunk/Nebulous/nebclient/src/nebclient.h	(revision 21461)
@@ -4,5 +4,5 @@
  * Copyright (C) 2005  Joshua Hoblitt
  *
- * $Id: nebclient.h,v 1.38 2008-12-14 22:48:35 eugene Exp $
+ * $Id: nebclient.h,v 1.39 2009-02-13 02:45:47 jhoblitt Exp $
  */
 
@@ -155,4 +155,34 @@
 );
 
+/** Get an Xattr on a storage object
+ *
+ * @return true on success
+ */
+char *nebGetXattr(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *name                    ///< xattr name
+);
+
+/** Get an Xattr on a storage object
+ *
+ * @return true on success
+ */
+int nebListXattr(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    char ***xattrs                      ///< array of xattr names
+);
+
+/** Remove an Xattr from a storage object
+ *
+ * @return true on success
+ */
+bool nebRemoveXattr(
+    nebServer *server,                  ///< nebServer object
+    const char *key,                    ///< storage object key (name)
+    const char *name                    ///< xattr name
+);
+
 /** Lists all instances of a storage object
  *
Index: /trunk/Nebulous/nebclient/tests/tests.c
===================================================================
--- /trunk/Nebulous/nebclient/tests/tests.c	(revision 21460)
+++ /trunk/Nebulous/nebclient/tests/tests.c	(revision 21461)
@@ -2,4 +2,5 @@
 #include <stdlib.h>
 #include <unistd.h>
+#include <string.h>
 #include <stdbool.h>
 
@@ -19,5 +20,5 @@
     char            *key = "foobarbaz";
 
-    plan_tests(24);
+    plan_tests(28);
 
     if (getenv("NEB_SERVER")) {
@@ -96,4 +97,13 @@
     neb_ok(server, nebSetXattr(server, key, "user.copies", "2",  NEB_CREATE), "set user.copies xattr");
 
+    char *copies = nebGetXattr(server, key, "user.copies");
+    neb_ok(server, strcmp(copies, "2") == 0, "get user.copies xattr");
+    char **xattrs = NULL;
+    int n_xattrs = nebListXattr(server, key, &xattrs);
+    printf("# %s\n\n", xattrs[0]);
+    neb_ok(server, n_xattrs == 1, "count of xattrs");
+    neb_ok(server, strcmp(xattrs[0], "user.copies") == 0, "user.copies xattr exists");
+    neb_ok(server, nebRemoveXattr(server, key, "user.copies"), "remove user.copies xattr");
+
     {
         nebObjectInstances *locations = NULL;
