]> git.sur5r.net Git - openldap/blobdiff - libraries/librewrite/var.c
Merge remote-tracking branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / libraries / librewrite / var.c
index e701655a86241c0871fda40b7ad7f7a4bdf01f0e..a155d3f7c1af18ca091cf59ea8ac142ba9f4d45d 100644 (file)
@@ -1,26 +1,21 @@
-/******************************************************************************
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
+ * Copyright 2000-2013 The OpenLDAP Foundation.
  * All rights reserved.
  *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to alter it and redistribute it, subject
- * to the following restrictions:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
  *
- * 1. The author is not responsible for the consequences of use of this
- * software, no matter how awful, even if they arise from flaws in it.
- *
- * 2. The origin of this software must not be misrepresented, either by
- * explicit claim or by omission.  Since few users ever read sources,
- * credits should appear in the documentation.
- *
- * 3. Altered versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.  Since few users
- * ever read sources, credits should appear in the documentation.
- * 
- * 4. This notice may not be removed or altered.
- *
- ******************************************************************************/
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENT:
+ * This work was initially developed by Pierangelo Masarati for
+ * inclusion in OpenLDAP Software.
+ */
 
 #include <portable.h>
 
@@ -70,6 +65,39 @@ rewrite_var_dup(
        return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
 }
 
+/*
+ * Frees a var
+ */
+static void 
+rewrite_var_free(
+               void *v_var
+)
+{
+       struct rewrite_var *var = v_var;
+       assert( var != NULL );
+
+       assert( var->lv_name != NULL );
+       assert( var->lv_value.bv_val != NULL );
+
+       if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
+               free( var->lv_name );
+       if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
+               free( var->lv_value.bv_val );
+       free( var );
+}
+
+/*
+ * Deletes a var tree
+ */
+int
+rewrite_var_delete(
+               Avlnode *tree
+)
+{
+       avl_free( tree, rewrite_var_free );
+       return REWRITE_SUCCESS;
+}
+
 /*
  * Finds a var
  */
@@ -88,51 +116,120 @@ rewrite_var_find(
                        ( caddr_t )&var, rewrite_var_cmp );
 }
 
+int
+rewrite_var_replace(
+               struct rewrite_var *var,
+               const char *value,
+               int flags
+)
+{
+       ber_len_t       len;
+
+       assert( value != NULL );
+
+       len = strlen( value );
+
+       if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
+               if ( flags & REWRITE_VAR_COPY_VALUE ) {
+                       if ( len <= var->lv_value.bv_len ) {
+                               AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
+
+                       } else {
+                               free( var->lv_value.bv_val );
+                               var->lv_value.bv_val = strdup( value );
+                       }
+
+               } else {
+                       free( var->lv_value.bv_val );
+                       var->lv_value.bv_val = (char *)value;
+                       var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
+               }
+
+       } else {
+               if ( flags & REWRITE_VAR_COPY_VALUE ) {
+                       var->lv_value.bv_val = strdup( value );
+                       var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+
+               } else {
+                       var->lv_value.bv_val = (char *)value;
+               }
+       }
+
+       if ( var->lv_value.bv_val == NULL ) {
+               return -1;
+       }
+
+       var->lv_value.bv_len = len;
+
+       return 0;
+}
+
 /*
  * Inserts a newly created var
  */
 struct rewrite_var *
-rewrite_var_insert(
+rewrite_var_insert_f(
                Avlnode **tree,
                const char *name,
-               const char *value
+               const char *value,
+               int flags
 )
 {
        struct rewrite_var *var;
-       int rc;
+       int rc = 0;
 
        assert( tree != NULL );
        assert( name != NULL );
        assert( value != NULL );
        
+       var = rewrite_var_find( *tree, name );
+       if ( var != NULL ) {
+               if ( flags & REWRITE_VAR_UPDATE ) {
+                       (void)rewrite_var_replace( var, value, flags );
+                       goto cleanup;
+               }
+               rc = -1;
+               goto cleanup;
+       }
+
        var = calloc( sizeof( struct rewrite_var ), 1 );
        if ( var == NULL ) {
                return NULL;
        }
+
        memset( var, 0, sizeof( struct rewrite_var ) );
-       var->lv_name = ( char * )strdup( name );
-       if ( var->lv_name == NULL ) {
-               rc = -1;
-               goto cleanup;
+
+       if ( flags & REWRITE_VAR_COPY_NAME ) {
+               var->lv_name = strdup( name );
+               if ( var->lv_name == NULL ) {
+                       rc = -1;
+                       goto cleanup;
+               }
+               var->lv_flags |= REWRITE_VAR_COPY_NAME;
+
+       } else {
+               var->lv_name = (char *)name;
        }
-       var->lv_value.bv_val = strdup( value );
-       if ( var->lv_value.bv_val == NULL ) {
-               rc = -1;
-               goto cleanup;
+
+       if ( flags & REWRITE_VAR_COPY_VALUE ) {
+               var->lv_value.bv_val = strdup( value );
+               if ( var->lv_value.bv_val == NULL ) {
+                       rc = -1;
+                       goto cleanup;
+               }
+               var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+               
+       } else {
+               var->lv_value.bv_val = (char *)value;
        }
        var->lv_value.bv_len = strlen( value );
        rc = avl_insert( tree, ( caddr_t )var,
                        rewrite_var_cmp, rewrite_var_dup );
-       if ( rc != 0 ) { 
-               rc = -1;
-               goto cleanup;
-       }
 
 cleanup:;
-       if ( rc != 0 ) {
-               free( var->lv_name );
-               free( var->lv_value.bv_val );
-               free( var );
+       if ( rc != 0 && var ) {
+               avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
+               rewrite_var_free( var );
                var = NULL;
        }
 
@@ -143,11 +240,11 @@ cleanup:;
  * Sets/inserts a var
  */
 struct rewrite_var *
-rewrite_var_set(
+rewrite_var_set_f(
                Avlnode **tree,
                const char *name,
                const char *value,
-               int insert
+               int flags
 )
 {
        struct rewrite_var *var;
@@ -158,49 +255,19 @@ rewrite_var_set(
        
        var = rewrite_var_find( *tree, name );
        if ( var == NULL ) {
-               if ( insert ) {
-                       return rewrite_var_insert( tree, name, value );
+               if ( flags & REWRITE_VAR_INSERT ) {
+                       return rewrite_var_insert_f( tree, name, value, flags );
+
                } else {
                        return NULL;
                }
+
        } else {
                assert( var->lv_value.bv_val != NULL );
 
-               free( var->lv_value.bv_val );
-               var->lv_value.bv_val = ( char * )value;
-               var->lv_value.bv_len = strlen( value );
+               (void)rewrite_var_replace( var, value, flags );
        }
 
        return var;
 }
 
-/*
- * Frees a var
- */
-static void 
-rewrite_var_free(
-               void *v_var
-)
-{
-       struct rewrite_var *var = v_var;
-       assert( var != NULL );
-
-       assert( var->lv_name != NULL );
-       assert( var->lv_value.bv_val != NULL );
-
-       free( var->lv_name );
-       free( var->lv_value.bv_val );
-}
-
-/*
- * Deletes a var tree
- */
-int
-rewrite_var_delete(
-               Avlnode *tree
-)
-{
-       avl_free( tree, rewrite_var_free );
-       return REWRITE_SUCCESS;
-}
-