Index: src/server/get-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/get-eattr.sm,v
retrieving revision 1.15
diff -u -a -p -a -u -r1.15 get-eattr.sm
--- src/server/get-eattr.sm	17 Feb 2007 21:16:47 -0000	1.15
+++ src/server/get-eattr.sm	21 Mar 2007 22:01:41 -0000
@@ -23,6 +23,7 @@
 #include "pvfs2-types.h"
 #include "pvfs2-util.h"
 #include "pint-util.h"
+#include "pint-eattr.h"
 
 static int geteattr_setup_resp(
     PINT_server_op *s_op, job_status_s *js_p);
@@ -85,63 +86,32 @@ machine pvfs2_get_eattr_sm
 static int geteattr_setup_resp(PINT_server_op *s_op, job_status_s *js_p)
 {
     int i, tsz;
-    char reserved_prefix[] = "system.pvfs2.";
-    int reserved_prefix_len = strlen("system.pvfs2.");
-    char* tmp_buffer = NULL;
-    int tmp_len = 0;
-    int ret;
 
     gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr requesting %d keys\n",
             s_op->req->u.geteattr.nkey);
 
     js_p->error_code = 0;
  
-    tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
-    if(!tmp_buffer)
-    {
-        js_p->error_code = -PVFS_ENOMEM;
-        return(1);
-    }
-
     /* iterate through the keys and see if they fall into valid name spaces */
     for(i=0; i<s_op->req->u.geteattr.nkey; i++)
     {
         gossip_debug(GOSSIP_GETEATTR_DEBUG, "geteattr key %d : %s\n", i, 
                 (char *) s_op->req->u.geteattr.key[i].buffer);
-        if(!PINT_eattr_is_prefixed(s_op->req->u.geteattr.key[i].buffer))
+
+        js_p->error_code = PINT_eattr_check_access(
+            &s_op->req->u.geteattr.key[i],
+            NULL);
+        if(js_p->error_code != 0)
         {
-            /* not prefixed: treat this as if the key does not exist */
-            free(tmp_buffer);
-            js_p->error_code = -PVFS_ENOENT;
             return(1);
         }
 
-        /* look for keys in the special "system.pvfs2." prefix and strip the
-         * prefix off; they are stored as keyvals with no prefix within
-         * trove.
-         */
-        if(strncmp(s_op->req->u.geteattr.key[i].buffer, reserved_prefix,
-            reserved_prefix_len) == 0)
-        {
-            ret = sscanf(s_op->req->u.geteattr.key[i].buffer,
-                "system.pvfs2.%s", tmp_buffer);
-            if(ret != 1)
-            {
-                free(tmp_buffer);
-                js_p->error_code = -PVFS_ENOENT;
-                return(1);
-            }
-            tmp_len = strlen(tmp_buffer) + 1;
-            memcpy(s_op->req->u.geteattr.key[i].buffer, tmp_buffer, tmp_len);
-            s_op->req->u.geteattr.key[i].buffer_sz = tmp_len;
-        }
     }
 
     s_op->resp.u.geteattr.val =
         malloc(s_op->req->u.geteattr.nkey*sizeof(PVFS_ds_keyval));
     if (!s_op->resp.u.geteattr.val)
     {
-        free(tmp_buffer);
         js_p->error_code = -PVFS_ENOMEM;
         return(1);
     }
@@ -150,7 +120,6 @@ static int geteattr_setup_resp(PINT_serv
     if (!s_op->resp.u.geteattr.err)
     {
         free(s_op->resp.u.geteattr.val);
-        free(tmp_buffer);
         js_p->error_code = -PVFS_ENOMEM;
         return(1);
     }
@@ -163,7 +132,6 @@ static int geteattr_setup_resp(PINT_serv
         s_op->resp.u.geteattr.nkey = 0;
         free (s_op->resp.u.geteattr.val);
         free (s_op->resp.u.geteattr.err);
-        free(tmp_buffer);
         js_p->error_code = -PVFS_ENOMEM;
         return(1);
     }
@@ -177,7 +145,6 @@ static int geteattr_setup_resp(PINT_serv
             (char *) s_op->u.eattr.buffer + tsz;
         tsz += s_op->req->u.geteattr.valsz[i];
     }
-    free(tmp_buffer);
     return 1;
 }
 
Index: src/server/list-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/list-eattr.sm,v
retrieving revision 1.9
diff -u -a -p -a -u -r1.9 list-eattr.sm
--- src/server/list-eattr.sm	17 Feb 2007 21:16:48 -0000	1.9
+++ src/server/list-eattr.sm	21 Mar 2007 22:01:41 -0000
@@ -23,6 +23,7 @@
 #include "pvfs2-types.h"
 #include "pvfs2-util.h"
 #include "pint-util.h"
+#include "pint-eattr.h"
 
 static int listeattr_setup_resp(
     PINT_server_op *s_op, job_status_s *js_p);
@@ -182,10 +183,6 @@ static int listeattr_check_resp(PINT_ser
 {
     int num_found = 0;
     int i = 0;
-    char* tmp_buffer = NULL;
-    char translate_prefix[] = "system.pvfs2.";
-    int translate_prefix_len = strlen("system.pvfs2.");
-    int ret = 0;
 
     /* Nothing was requested? then fill token to hold the max available keys */
     if (s_op->resp.u.listeattr.nkey == 0)
@@ -212,52 +209,21 @@ static int listeattr_check_resp(PINT_ser
         return(1);
     }
   
-    tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
-    if(!tmp_buffer)
-    {
-        js_p->error_code = -PVFS_ENOMEM;
-        return(1);
-    }
-
     /* iterate through the keys that we found */
     for(i=0; i<num_found; i++)
     {
-        /* check to see if it is prefixed into a supported name space */
-        if(!PINT_eattr_is_prefixed(s_op->resp.u.listeattr.key[i].buffer))
+        js_p->error_code = PINT_eattr_list_access(
+            &s_op->resp.u.listeattr.key[i],
+            NULL);
+        if(js_p->error_code != 0)
         {
-            /* we need to tack on a "system.pvfs2." prefix */
-
-            /* find out if the key size requested is large enough */
-            if((translate_prefix_len + s_op->resp.u.listeattr.key[i].read_sz) >
-                s_op->req->u.listeattr.keysz[i])
-            {
-                /* NOTE: trying to mimic the semantics of
-                 * trove_keyval_iterate_keys(): it will also report an
-                 * overall error if one of the key buffers is to small,
-                 * though the choice of error code may be different.
-                 */
-                free(tmp_buffer);
-                js_p->error_code = -PVFS_EMSGSIZE;
-                return(1);
-            }
-
-            /* add a prefix onto the key and adjust sizes accordingly */
-            /* NOTE: this will have to change if we ever permit non-string
-             * keys (which would break using them for xattrs anyway)
-             */
-            ret = sprintf(tmp_buffer,
-                "%s%s", translate_prefix,
-                (char*)s_op->resp.u.listeattr.key[i].buffer);
-            memcpy(s_op->resp.u.listeattr.key[i].buffer, tmp_buffer,
-                (ret+1));
-            s_op->resp.u.listeattr.key[i].read_sz += translate_prefix_len;
+            return 1;
         }
 
         s_op->resp.u.listeattr.key[i].buffer_sz =
             s_op->resp.u.listeattr.key[i].read_sz;
     }    
 
-    free(tmp_buffer);
     js_p->error_code = 0;
     return(1);
 }
Index: src/server/module.mk.in
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/module.mk.in,v
retrieving revision 1.47
diff -u -a -p -a -u -r1.47 module.mk.in
--- src/server/module.mk.in	13 Sep 2006 20:22:58 -0000	1.47
+++ src/server/module.mk.in	21 Mar 2007 22:01:41 -0000
@@ -42,7 +42,8 @@ ifdef BUILD_SERVER
 
 	# c files that should be added to server library
 	SERVERSRC += \
-		$(SERVER_SMCGEN)
+		$(SERVER_SMCGEN) \
+		$(DIR)/pint-eattr.c
 
 	# track generate .c files to remove during dist clean, etc. 
 		SMCGEN += $(SERVER_SMCGEN)
Index: src/server/pint-eattr.c
===================================================================
RCS file: src/server/pint-eattr.c
diff -N src/server/pint-eattr.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/server/pint-eattr.c	21 Mar 2007 22:01:41 -0000
@@ -0,0 +1,259 @@
+/* 
+ * (C) 2001 Clemson University and The University of Chicago 
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "pvfs2.h"
+#include "pint-eattr.h"
+#include "pvfs2-req-proto.h"
+
+#define PVFS_EATTR_NS_SYSTEM_PVFS2 "system.pvfs2."
+
+/* extended attribute name spaces supported in PVFS2 */
+struct PINT_eattr_check
+{
+    const char * ns;
+    int ret;
+    int (* check) (PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+};
+
+/* PINT_eattr_strip_prefix
+ *
+ * Remove the 'system.pvfs2.' prefix from attributes before querying.
+ * These specific attributes are stored without the prefix.
+ */
+static int PINT_eattr_strip_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+static struct PINT_eattr_check PINT_eattr_access[] =
+{
+    {"system.pvfs2.", 0, PINT_eattr_strip_prefix},
+    {"system.", 0, NULL},
+    {"user.", 0, NULL},
+    {"trusted.", 0, NULL},
+    {"security.", 0, NULL},
+    {NULL, -PVFS_ENOENT, NULL}
+};
+
+/* PINT_eattr_system_verify
+ *
+ * Check the eattrs with system. namespace prefixes.  Right now this
+ * only checks that acls are formatted properly.
+ */
+static int PINT_eattr_system_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v);
+
+/* We provide namespace structures that include error codes
+ * or checking functions.  For an extended attribute, the
+ * namespace is checked by iterating from top to bottom
+ * through this list.  If a namespace matches and the error
+ * code is non-zero, the error code is returned, otherwise,
+ * the checking function is called (if non-null).  If none of the namespaces
+ * in the list match (or the eattr isn't prefixed with
+ * a namespace, the last entry in the list is triggered,
+ * and EOPNOTSUPP is returned.  Since we don't allow
+ * eattrs with system.pvfs2. prefixes to be set by the
+ * set-eattr operation, we return EINVAL in that case.
+ */
+static struct PINT_eattr_check PINT_eattr_namespaces[] =
+{
+    {"system.pvfs2.", -PVFS_EINVAL, NULL},
+    {"system.", 0, PINT_eattr_system_verify},
+    {"user.", 0, NULL},
+    {"trusted.", 0, NULL},
+    {"security.", 0, NULL},
+    {NULL, -PVFS_EOPNOTSUPP, NULL}
+};
+
+static int PINT_eattr_verify_acl_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* Used to verify that acls are correctly formatted before plopping
+ * them in storage
+ */
+static struct PINT_eattr_check PINT_eattr_system[] =
+{
+    {"system.posix_acl_access", 0, PINT_eattr_verify_acl_access},
+    {NULL, 0, NULL}};
+
+static int PINT_eattr_add_pvfs_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* check that the eattr in the list matches a valid namespace.  If
+ * it doesn't, assume its in the system.pvfs2. namespace, and tack
+ * on that prefix (using the PINT_eattr_add_pvfs_prefix function).
+ */
+static struct PINT_eattr_check PINT_eattr_list[] =
+{
+    {"system.", 0, NULL},
+    {"user.", 0, NULL},
+    {"trusted.", 0, NULL},
+    {"security.", 0, NULL},
+    {NULL, 0, PINT_eattr_add_pvfs_prefix}
+};
+
+/* PINT_eattr_verify
+ *
+ * Useful as a basic function that does verification given an array of
+ * extended attribute checking structures.  It essentially iterates
+ * through the array and compares the key's buffer with each element.
+ * If one matches, it uses the other fields in that checking structure
+ * to verify the eattr.
+ */
+static inline int PINT_eattr_verify(
+    struct PINT_eattr_check * eattr_array,
+    PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+int PINT_eattr_check_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+    return PINT_eattr_verify(PINT_eattr_access, key, val);
+}
+
+static int PINT_eattr_strip_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+    char * tmp_buffer = NULL;
+    int tmp_len;
+    int ret;
+
+    tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
+    if(!tmp_buffer)
+    {
+        return -PVFS_ENOMEM;
+    }
+
+    /* look for keys in the special "system.pvfs2." prefix and strip the
+     * prefix off; they are stored as keyvals with no prefix within
+     * trove.
+     */
+    ret = sscanf(key->buffer,
+                 PVFS_EATTR_NS_SYSTEM_PVFS2 "%s", tmp_buffer);
+    if(ret != 1)
+    {
+        free(tmp_buffer);
+        return -PVFS_ENOENT;
+    }
+
+    tmp_len = strlen(tmp_buffer) + 1;
+    memcpy(key->buffer, tmp_buffer, tmp_len);
+    key->buffer_sz = tmp_len;
+    free(tmp_buffer);
+    return 0;
+}
+
+static inline int PINT_eattr_verify(
+    struct PINT_eattr_check * eattr_array,
+    PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+    int i = 0;
+    while(1)
+    {
+        /* if we get to the NULL ns at the end of the list, return
+         * the error code
+         */
+        if(!eattr_array[i].ns)
+        {
+            return eattr_array[i].ret;
+        }
+
+        if(strncmp(eattr_array[i].ns, key->buffer,
+            strlen(eattr_array[i].ns)) == 0)
+        {
+            /* if the return value for this namespace is non-zero,
+             * return that value
+             */
+            if(eattr_array[i].ret != 0)
+            {
+                return eattr_array[i].ret;
+            }
+
+            /* if the checking function for this namespace is non-null,
+             * invoke that checking function and return the result.
+             */
+            if(eattr_array[i].check)
+            {
+                return eattr_array[i].check(key, val);
+            }
+
+            /* looks like the namespace is otherwise acceptable */
+            return 0;
+        }
+        i++;
+    }
+
+    /* this shouldn't be possible */
+    return(0);
+}
+
+int PINT_eattr_system_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v)
+{
+    return PINT_eattr_verify(PINT_eattr_system, k, v);
+}
+
+int PINT_eattr_namespace_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v)
+{
+    return PINT_eattr_verify(PINT_eattr_namespaces, k, v);
+}
+
+static int PINT_eattr_verify_acl_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+
+    assert(!strcmp(key->buffer, "system.posix_acl_access"));
+
+    /* verify that the acl is formatted properly.  Right now
+     * all we can do is make sure the size matches a non-zero
+     * number of pvfs acl entries
+     */
+    if(val->buffer_sz == 0 || val->buffer_sz % sizeof(pvfs2_acl_entry) != 0)
+    {
+        return -PVFS_EINVAL;
+    }
+
+    return 0;
+}
+
+int PINT_eattr_list_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+    return PINT_eattr_verify(PINT_eattr_list, key, val);
+}
+
+/* PINT_eattr_add_pvfs_prefix
+ *
+ * Tack on the system.pvfs2. prefix to any eattrs that don't have it.
+ * This is used by the eattr list operation for pvfs specific attributes,
+ * such as 'dh' (datafile handles) or 'md' (metafile distribution).
+ */
+static int PINT_eattr_add_pvfs_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+    char * tmp_buffer = NULL;
+    int ret;
+
+    if(key->buffer_sz < (key->read_sz + sizeof(PVFS_EATTR_NS_SYSTEM_PVFS2)))
+    {
+        return -PVFS_EMSGSIZE;
+    }
+
+    tmp_buffer = (char*)malloc(key->read_sz + sizeof(PVFS_EATTR_NS_SYSTEM_PVFS2));
+    if(!tmp_buffer)
+    {
+        return -PVFS_ENOMEM;
+    }
+
+    ret = sprintf(tmp_buffer, "%.*s%s",
+                  key->read_sz, (char *)key->buffer, PVFS_EATTR_NS_SYSTEM_PVFS2);
+    memcpy(key->buffer, tmp_buffer, ret+1);
+    key->read_sz = ret+1;
+
+    free(tmp_buffer);
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  mode: c
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
Index: src/server/pint-eattr.h
===================================================================
RCS file: src/server/pint-eattr.h
diff -N src/server/pint-eattr.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/server/pint-eattr.h	21 Mar 2007 22:01:41 -0000
@@ -0,0 +1,41 @@
+/* 
+ * (C) 2001 Clemson University and The University of Chicago 
+ *
+ * See COPYING in top-level directory.
+ */
+
+/* Extended Attributes
+ *
+ * These functions provide checking of extended attributes formats
+ * and namespaces
+ */
+
+/* PINT_eattr_list_verify
+ *
+ * Verify the extended attribute using the check access structure array
+ */
+int PINT_eattr_list_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* PINT_eattr_check_access
+ *
+ * Check that a request extended attribute is correctly formatted and
+ * within a valid namespace
+ */
+int PINT_eattr_check_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* PINT_eattr_namespace_verify
+ *
+ * Checks that the eattr has a valid namespace that PVFS accepts
+ */
+int PINT_eattr_namespace_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v);
+
+/*
+ * Local variables:
+ *  mode: c
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
+
Index: src/server/pvfs2-server.c
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.c,v
retrieving revision 1.234
diff -u -a -p -a -u -r1.234 pvfs2-server.c
--- src/server/pvfs2-server.c	12 Mar 2007 22:20:29 -0000	1.234
+++ src/server/pvfs2-server.c	21 Mar 2007 22:01:41 -0000
@@ -123,16 +123,6 @@ PINT_server_trove_keys_s Trove_Common_Ke
     {SYMLINK_TARGET_KEYSTR, SYMLINK_TARGET_KEYLEN}
 };
 
-/* extended attribute name spaces supported in PVFS2 */
-const char *PINT_eattr_namespaces[] =
-{
-    "system.",
-    "user.",
-    "trusted.",
-    "security.",
-    NULL
-};
-
 /* These three are used continuously in our wait loop.  They could be
  * relatively large, so rather than allocate them on the stack, we'll
  * make them dynamically allocated globals.
Index: src/server/pvfs2-server.h
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.h,v
retrieving revision 1.145
diff -u -a -p -a -u -r1.145 pvfs2-server.h
--- src/server/pvfs2-server.h	21 Mar 2007 15:35:22 -0000	1.145
+++ src/server/pvfs2-server.h	21 Mar 2007 22:01:41 -0000
@@ -104,29 +104,6 @@ extern struct PINT_server_req_params PIN
 
 const char* PINT_map_server_op_to_string(enum PVFS_server_op op);
 
-extern const char *PINT_eattr_namespaces[];
-/* PINT_eattr_is_prefixed()
- *
- * This function will check to see if a given xattr key falls into the set of
- * name spaces that PVFS2 supports
- *
- * returns 1 if the prefix is supported, 0 otherwise
- */
-static inline int PINT_eattr_is_prefixed(char* key_name)
-{
-    int i = 0;
-    while(PINT_eattr_namespaces[i])
-    {
-        if(strncmp(PINT_eattr_namespaces[i], key_name,
-            strlen(PINT_eattr_namespaces[i])) == 0)
-        {
-            return(1);
-        }
-        i++;
-    }
-    return(0);
-}
-
 /* used to keep a random, but handy, list of keys around */
 typedef struct PINT_server_trove_keys
 {
Index: src/server/set-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/set-eattr.sm,v
retrieving revision 1.14
diff -u -a -p -a -u -r1.14 set-eattr.sm
--- src/server/set-eattr.sm	17 Feb 2007 21:16:48 -0000	1.14
+++ src/server/set-eattr.sm	21 Mar 2007 22:01:41 -0000
@@ -13,6 +13,7 @@
 #include "pvfs2-internal.h"
 #include "pvfs2-util.h"
 #include "pint-util.h"
+#include "pint-eattr.h"
 
 static int seteattr_verify_eattribs(
     PINT_server_op *s_op, job_status_s *js_p);
@@ -68,11 +69,8 @@ static int seteattr_verify_eattribs(
     PINT_server_op *s_op, job_status_s *js_p)
 {
     PVFS_object_attr *a_p = NULL;
-    int i;
-    char reserved_prefix[] = "system.pvfs2.";
-    int reserved_prefix_len = strlen("system.pvfs2.");
-
     a_p = &s_op->attr;
+    int i;
 
     js_p->error_code = 0;
 
@@ -86,25 +84,15 @@ static int seteattr_verify_eattribs(
     /* iterate through the keys that are being written */
     for (i = 0; i < s_op->req->u.seteattr.nkey; i++)
     {
-        /* make sure that they all fall into a supported name space */
-        if(!PINT_eattr_is_prefixed(s_op->req->u.seteattr.key[i].buffer))
-        {
-            /* emulating return code seen on ext3 */
-            js_p->error_code = -PVFS_EOPNOTSUPP;
-            return 1;
-        }
-
-        /* don't allow anyone to set things in the system.pvfs2 name space */
-        if(strncmp(s_op->req->u.seteattr.key[i].buffer, reserved_prefix,
-            reserved_prefix_len) == 0)
+        js_p->error_code = PINT_eattr_namespace_verify(
+            &s_op->req->u.seteattr.key[i],
+            &s_op->req->u.seteattr.val[i]);
+        if(!js_p->error_code)
         {
-            /* what error code make sense here? */
-            js_p->error_code = -PVFS_EINVAL;
             return 1;
         }
     }
 
-    js_p->error_code = 0;
     return 1;
 }
 
