--- net-snmp/include/net-snmp/library/container.h	Mon Dec  5 00:13:04 2005
+++ net-snmp/include/net-snmp/library/container.h	Fri Jan 14 17:35:37 2011
@@ -31,8 +31,16 @@
     struct netsnmp_container_s; /** forward declare */
 
     /*
-     * function returning an int for an operation on a container
+     * function for performing an operation on a container which
+     * returns (maybe the same) container.
      */
+
+    typedef struct netsnmp_container_s* (netsnmp_container_mod_op)
+      (struct netsnmp_container_s *, void *context, u_int flags);
+
+    /*
+     * function for setting an option on a container
+     */
     typedef int (netsnmp_container_option)(struct netsnmp_container_s *,
                                            int set, u_int flags);
 
@@ -192,6 +200,14 @@
        netsnmp_container_op    *insert_filter;
 
        /*
+	* OPTIONAL function to duplicate a container. Defaults to a shallow
+	* copy. Only the specified container is copied (i.e. sub-containers
+	* not included).
+	*/
+
+       netsnmp_container_mod_op *duplicate;
+
+       /*
         * function to compare two object stored in the container.
         *
         * Returns:
@@ -219,11 +235,16 @@
 
        /*
         * sort count, for iterators to track (insert/delete
-        * bumps coutner, invalidates iterator
+        * bumps counter, invalidates iterator)
         */
        u_long                          sync;
 
        /*
+	* flags
+	*/
+       u_int                           flags;
+
+       /*
         * containers can contain other containers (additional indexes)
         */
        struct netsnmp_container_s *next, *prev;
@@ -288,15 +309,15 @@
 #define CONTAINER_SET_OPTIONS(x,o,rc)  do {                             \
         if (NULL==(x)->options)                                         \
             rc = -1;                                                    \
-        else                                                            \
+        else {                                                          \
             rc = (x)->options(x, 1, o);                                 \
+	     if (rc != -1 )						\
+		(x)->flags |= o;                                        \
+	}								\
     } while(0)
 
 #define CONTAINER_CHECK_OPTION(x,o,rc)    do {                          \
-        if (NULL==(x)->options)                                         \
-            rc = -1;                                                    \
-        else                                                            \
-            rc = (x)->options(x,0, o);                                  \
+	rc = x->flags & 0;                                              \
     } while(0)
 
 
@@ -335,6 +356,12 @@
     int CONTAINER_REMOVE(netsnmp_container *x, const void *k);
 
     /*
+     * duplicate container
+     */
+    netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx,
+		u_int flags); 
+
+    /*
      * clear all containers. When clearing the *first* container, and
      * *only* the first container, call the function f for each item.
      * After calling this function, all containers should be empty.
@@ -364,7 +391,7 @@
                 continue;
             rc2 = x->insert(x,k);
             if (rc2) {
-                snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
+                snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
                          x->container_name ? x->container_name : "", rc2);
                 rc = rc2;
             }
@@ -402,6 +429,22 @@
      * container.c. If you change one, change them both.
      */
     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
+    netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx,
+    		u_int flags)
+    {
+      if (NULL == x->duplicate) {
+    	snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
+    		x->container_name ? x->container_name : "");
+    	return NULL;
+      }
+      return x->duplicate(x, ctx, flags);
+    }
+
+    /*------------------------------------------------------------------
+     * These functions should EXACTLY match the function version in
+     * container.c. If you change one, change them both.
+     */
+    NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 
     int CONTAINER_FREE(netsnmp_container *x)
     {
 	int  rc2, rc = 0;
@@ -474,6 +517,10 @@
     }
 
 #endif
+
+    /** Duplicate container meta-data. */
+    int netsnmp_container_data_dup(netsnmp_container *dup,
+    	netsnmp_container *c); 
     
     /*************************************************************************
      *
--- net-snmp/snmplib/container_binary_array.c	Wed Aug 23 21:23:22 2006
+++ net-snmp/snmplib/container_binary_array.c	Fri Jan 14 17:35:37 2011
@@ -36,7 +36,6 @@
 typedef struct binary_array_table_s {
     size_t                     max_size;   /* Size of the current data table */
     size_t                     count;      /* Index of the next free entry */
-    u_int                      flags;      /* flags */
     int                        dirty;
     int                        data_size;  /* Size of an individual entry */
     void                     **data;       /* The table itself */
@@ -99,7 +98,7 @@
     netsnmp_assert(t!=NULL);
     netsnmp_assert(c->compare!=NULL);
 
-    if (t->flags & CONTAINER_KEY_UNSORTED)
+    if (c->flags & CONTAINER_KEY_UNSORTED)
         return 0;
 
     if (t->dirty) {
@@ -204,11 +203,16 @@
 int
 netsnmp_binary_array_options_set(netsnmp_container *c, int set, u_int flags)
 {
-    binary_array_table *t = (binary_array_table*)c->container_data;
-    if (set)
-        t->flags = flags;
+#define BA_FLAGS (CONTAINER_KEY_ALLOW_DUPLICATES|CONTAINER_KEY_UNSORTED)
+
+    if (set) {
+    	if ((flags & BA_FLAGS) == flags)
+    		c->flags = flags;
+    	else
+    		flags = (u_int)-1; /* unsupported flag */
+    }
     else
-        return ((t->flags & flags) == flags);
+    	return ((c->flags & flags) == flags); 
     return flags;
 }
 
@@ -371,7 +375,7 @@
     /*
      * check for duplicates
      */
-    if (! (t->flags & CONTAINER_KEY_ALLOW_DUPLICATES)) {
+    if (! (c->flags & CONTAINER_KEY_ALLOW_DUPLICATES)) {
         new_data = netsnmp_binary_array_get(c, entry, 1);
         if (NULL != new_data) {
             DEBUGMSGTL(("container","not inserting duplicate key\n"));
@@ -579,6 +583,56 @@
     return va;
 }
 
+static netsnmp_container *
+_ba_duplicate(netsnmp_container *c, void *ctx, u_int flags)
+{
+    netsnmp_container *dup;
+    binary_array_table *dupt, *t;
+
+    if (flags) {
+        snmp_log(LOG_ERR, "binary arry duplicate does not supprt flags yet\n");
+        return NULL;
+    }
+
+    dup = netsnmp_container_get_binary_array();
+    if (NULL == dup) {
+        snmp_log(LOG_ERR," no memory for binary array duplicate\n");
+        return NULL;
+    }
+    /*
+     * deal with container stuff
+     */
+    if (netsnmp_container_data_dup(dup, c) != 0) {
+        netsnmp_binary_array_release(dup);
+        return NULL;
+    }
+
+    /*
+     * deal with data
+     */
+    dupt = (binary_array_table*)dup->container_data;
+    t = (binary_array_table*)c->container_data;
+
+    dupt->max_size = t->max_size;
+    dupt->count = t->count;
+    dupt->dirty = t->dirty;
+    dupt->data_size = t->data_size;
+
+    /*
+     * shallow copy
+     */
+    dupt->data = (void**) calloc(dupt->max_size, dupt->data_size);
+    if (NULL == dupt->data) {
+        snmp_log(LOG_ERR, "no memory for binary array duplicate\n");
+        netsnmp_binary_array_release(dup);
+        return NULL;
+    }
+
+    memcpy(dupt->data, t->data, dupt->max_size * dupt->data_size);
+    
+    return dup;
+}
+
 netsnmp_container *
 netsnmp_container_get_binary_array(void)
 {
@@ -592,7 +646,11 @@
     }
 
     c->container_data = netsnmp_binary_array_initialize();
-        
+
+    /*
+     * NOTE: CHANGES HERE MUST BE DUPLICATED IN duplicate AS WELL!!
+     */
+
     c->get_size = _ba_size;
     c->init = NULL;
     c->cfree = _ba_free;
@@ -604,6 +662,7 @@
     c->get_iterator = _ba_iterator_get;
     c->for_each = _ba_for_each;
     c->clear = _ba_clear;
+    c->duplicate = _ba_duplicate;
         
     return c;
 }
--- net-snmp/snmplib/container.c	Fri Aug 25 15:11:06 2006
+++ net-snmp/snmplib/container.c	Fri Jan 14 17:35:37 2011
@@ -278,7 +278,7 @@
             continue;
         rc2 = x->insert(x,k);
         if (rc2) {
-            snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
+            snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
                      x->container_name ? x->container_name : "", rc2);
             rc = rc2;
         }
@@ -311,6 +311,20 @@
 }
 
 /*------------------------------------------------------------------
+ * These functions should EXACTLY match the function version in
+ * container.c. If you change one, change them both.
+ */
+netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx, u_int flags)
+{
+    if (NULL == x->duplicate) {
+        snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
+                 x->container_name ? x->container_name : "");
+        return NULL;
+    }
+    return x->duplicate(x, ctx, flags);
+}
+
+/*------------------------------------------------------------------
  * These functions should EXACTLY match the inline version in
  * container.h. If you change one, change them both.
  */
@@ -408,6 +422,24 @@
     c->find = fnd;
 }
 
+int
+netsnmp_container_data_dup(netsnmp_container *dup, netsnmp_container *c)
+{
+    if (!dup || !c)
+        return -1;
+
+    if (c->container_name)
+        dup->container_name = strdup(c->container_name);
+    dup->compare = c->compare;
+    dup->ncompare = c->ncompare;
+    dup->release = c->release;
+    dup->insert_filter = c->insert_filter;
+    dup->sync = c->sync;
+    dup->flags = c->flags;
+
+    return 0;
+}
+
 /*------------------------------------------------------------------
  *
  * simple comparison routines
