]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/limits.c
silence warning
[openldap] / servers / slapd / limits.c
index ecd68f497eed863a8a007edf807ab5d673255e3e..53b0db9e0671ad6e24b02b46ceeb80e2655472c7 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2008 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 
+#include <ac/ctype.h>
 #include <ac/regex.h>
 #include <ac/string.h>
 
@@ -67,6 +68,7 @@ limits_get(
        struct slap_limits_set  **limit
 )
 {
+       static struct berval empty_dn = BER_BVC( "" );
        struct slap_limits **lm;
        struct berval           *ndns[2];
 
@@ -95,12 +97,19 @@ limits_get(
                unsigned        isthis = type == SLAP_LIMITS_TYPE_THIS;
                struct berval *ndn = ndns[isthis];
 
+               if ( style == SLAP_LIMITS_ANY )
+                       goto found_any;
+
+               if ( BER_BVISEMPTY( ndn ) ) {
+                       if ( style == SLAP_LIMITS_ANONYMOUS )
+                               goto found_nodn;
+                       if ( !isthis )
+                               continue;
+                       ndn = &empty_dn;
+               }
+
                switch ( style ) {
                case SLAP_LIMITS_EXACT:
-                       if ( BER_BVISEMPTY( ndn ) ) {
-                               break;
-                       }
-
                        if ( type == SLAP_LIMITS_TYPE_GROUP ) {
                                int     rc = backend_group( op, NULL,
                                                &lm[0]->lm_pat, ndn,
@@ -121,10 +130,6 @@ limits_get(
                case SLAP_LIMITS_CHILDREN: {
                        ber_len_t d;
                        
-                       if ( BER_BVISEMPTY( ndn ) ) {
-                               break;
-                       }
-
                        /* ndn shorter than lm_pat */
                        if ( ndn->bv_len < lm[0]->lm_pat.bv_len ) {
                                break;
@@ -159,33 +164,19 @@ limits_get(
                }
 
                case SLAP_LIMITS_REGEX:
-                       if ( BER_BVISEMPTY( ndn ) ) {
-                               break;
-                       }
                        if ( regexec( &lm[0]->lm_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) {
                                goto found_dn;
                        }
                        break;
 
                case SLAP_LIMITS_ANONYMOUS:
-                       if ( BER_BVISEMPTY( ndn ) ) {
-                               goto found;
-                       }
                        break;
 
                case SLAP_LIMITS_USERS:
-                       if ( !BER_BVISEMPTY( ndn ) ) {
-                               goto found;
-                       }
-                       break;
-
-               case SLAP_LIMITS_ANY:
-                       *limit = &lm[0]->lm_limits;
-                       return( 0 );
-
-               found:
+               found_nodn:
                        Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=%s match=%s\n",
                                dn_source[isthis], limits2str( style ), 0 );
+               found_any:
                        *limit = &lm[0]->lm_limits;
                        return( 0 );
 
@@ -258,7 +249,6 @@ limits_add(
        case SLAP_LIMITS_ONE:
        case SLAP_LIMITS_SUBTREE:
        case SLAP_LIMITS_CHILDREN:
-               lm->lm_flags = style | type;
                {
                        int rc;
                        struct berval bv;
@@ -274,7 +264,6 @@ limits_add(
                break;
                
        case SLAP_LIMITS_REGEX:
-               lm->lm_flags = style | type;
                ber_str2bv( pattern, 0, 1, &lm->lm_pat );
                if ( regcomp( &lm->lm_regex, lm->lm_pat.bv_val, 
                                        REG_EXTENDED | REG_ICASE ) ) {
@@ -287,7 +276,6 @@ limits_add(
        case SLAP_LIMITS_ANONYMOUS:
        case SLAP_LIMITS_USERS:
        case SLAP_LIMITS_ANY:
-               lm->lm_flags = style | type;
                BER_BVZERO( &lm->lm_pat );
                break;
        }
@@ -301,6 +289,7 @@ limits_add(
                break;
        }
 
+       lm->lm_flags = style | type;
        lm->lm_limits = *limit;
 
        i = 0;
@@ -457,28 +446,26 @@ limits_parse(
                        {
                                flags = SLAP_LIMITS_ANONYMOUS;
                                pattern = NULL;
+
+                       } else {
+                               /* force error below */
+                               if ( *pattern == '=' )
+                                       --pattern;
                        }
                }
 
                /* pre-check the data */
-               switch ( flags ) {
-               case SLAP_LIMITS_ANONYMOUS:
-               case SLAP_LIMITS_USERS:
-
-                       /* no need for pattern */
-                       pattern = NULL;
-                       break;
-
-               default:
+               if ( pattern != NULL ) {
                        if ( pattern[0] != '=' ) {
                                Debug( LDAP_DEBUG_ANY,
-                                       "%s : line %d: missing '=' in "
+                                       "%s : line %d: %s in "
                                        "\"dn[.{this|self}][.{exact|base"
-                                       "|onelevel|subtree|children|regex}]"
-                                       "=<pattern>\" in "
-                                       "\"limits <pattern> <limits>\" "
-                                       "line.\n%s",
-                                       fname, lineno, "" );
+                                       "|onelevel|subtree|children|regex"
+                                       "|anonymous}]=<pattern>\" in "
+                                       "\"limits <pattern> <limits>\" line.\n",
+                                       fname, lineno,
+                                       isalnum( (unsigned char)pattern[0] )
+                                       ? "unknown DN modifier" : "missing '='" );
                                return( -1 );
                        }
 
@@ -490,7 +477,7 @@ limits_parse(
                                flags = SLAP_LIMITS_ANY;
                                pattern = NULL;
 
-                       } else if ( flags == SLAP_LIMITS_REGEX
+                       } else if ( (flags & SLAP_LIMITS_MASK) == SLAP_LIMITS_REGEX
                                        && strcmp( pattern, ".*" ) == 0 ) {
                                flags = SLAP_LIMITS_ANY;
                                pattern = NULL;
@@ -887,42 +874,49 @@ limits_parse_one(
        return 0;
 }
 
-#define WHATSLEFT      ( buflen - ( ptr - bv->bv_val ) )
+/* Helper macros for limits_unparse() and limits_unparse_one():
+ * Write to ptr, but not past bufEnd.  Move ptr past the new text.
+ * Return (success && enough room ? 0 : -1).
+ */
+#define ptr_APPEND_BV(bv) /* Append a \0-terminated berval */ \
+       (WHATSLEFT <= (bv).bv_len ? -1 : \
+        ((void) (ptr = lutil_strcopy( ptr, (bv).bv_val )), 0))
+#define ptr_APPEND_LIT(str) /* Append a string literal */ \
+       (WHATSLEFT <= STRLENOF( "" str "" ) ? -1 : \
+        ((void) (ptr = lutil_strcopy( ptr, str )), 0))
+#define ptr_APPEND_FMT(args) /* Append formatted text */ \
+       (WHATSLEFT <= (tmpLen = snprintf args) ? -1 : ((void) (ptr += tmpLen), 0))
+#define ptr_APPEND_FMT1(fmt, arg) ptr_APPEND_FMT(( ptr, WHATSLEFT, fmt, arg ))
+#define WHATSLEFT ((ber_len_t) (bufEnd - ptr))
 
 /* Caller must provide an adequately sized buffer in bv */
 int
 limits_unparse( struct slap_limits *lim, struct berval *bv, ber_len_t buflen )
 {
        struct berval btmp;
-       char *ptr;
-       int type, lm, dntypelen;
+       char *ptr, *bufEnd;                     /* Updated/used by ptr_APPEND_*()/WHATSLEFT */
+       ber_len_t tmpLen;                       /* Used by ptr_APPEND_FMT*() */
+       unsigned type, style;
+       int rc = 0;
 
        if ( !bv || !bv->bv_val ) return -1;
 
        ptr = bv->bv_val;
+       bufEnd = ptr + buflen;
        type = lim->lm_flags & SLAP_LIMITS_TYPE_MASK;
 
        if ( type == SLAP_LIMITS_TYPE_GROUP ) {
-               if ( WHATSLEFT <= STRLENOF( "group/" "/" "=\"" "\"" )
-                               + lim->lm_group_oc->soc_cname.bv_len
-                               + lim->lm_group_ad->ad_cname.bv_len
-                               + lim->lm_pat.bv_len ) return -1;
-
-               ptr = lutil_strcopy( ptr, "group/" );
-               ptr = lutil_strcopy( ptr, lim->lm_group_oc->soc_cname.bv_val );
-               *ptr++ = '/';
-               ptr = lutil_strcopy( ptr, lim->lm_group_ad->ad_cname.bv_val );
-               ptr = lutil_strcopy( ptr, "=\"" );
-               ptr = lutil_strcopy( ptr, lim->lm_pat.bv_val );
-               *ptr++ = '"';
+               rc = ptr_APPEND_FMT(( ptr, WHATSLEFT, "group/%s/%s=\"%s\"",
+                       lim->lm_group_oc->soc_cname.bv_val,
+                       lim->lm_group_ad->ad_cname.bv_val,
+                       lim->lm_pat.bv_val ));
        } else {
-               lm = lim->lm_flags & SLAP_LIMITS_MASK;
-               switch( lm ) {
+               style = lim->lm_flags & SLAP_LIMITS_MASK;
+               switch( style ) {
                case SLAP_LIMITS_ANONYMOUS:
                case SLAP_LIMITS_USERS:
                case SLAP_LIMITS_ANY:
-                       if ( WHATSLEFT <= lmpats[lm].bv_len ) return -1;
-                       ptr = lutil_strcopy( ptr, lmpats[lm].bv_val );
+                       rc = ptr_APPEND_BV( lmpats[style] );
                        break;
                case SLAP_LIMITS_UNDEFINED:
                case SLAP_LIMITS_EXACT:
@@ -930,30 +924,23 @@ limits_unparse( struct slap_limits *lim, struct berval *bv, ber_len_t buflen )
                case SLAP_LIMITS_SUBTREE:
                case SLAP_LIMITS_CHILDREN:
                case SLAP_LIMITS_REGEX:
-                       dntypelen = type == SLAP_LIMITS_TYPE_SELF
-                               ? STRLENOF( "dn." ) : STRLENOF( "dn.this." );
-                       if ( WHATSLEFT <= dntypelen + STRLENOF( "=" "\"" "\"" )
-                                       + lmpats[lm].bv_len + lim->lm_pat.bv_len ) return -1;
-                       ptr = lutil_strncopy( ptr, "dn.this.", dntypelen );
-                       ptr = lutil_strcopy( ptr, lmpats[lm].bv_val );
-                       *ptr++ = '=';
-                       *ptr++ = '"';
-                       ptr = lutil_strcopy( ptr, lim->lm_pat.bv_val );
-                       *ptr++ = '"';
+                       rc = ptr_APPEND_FMT(( ptr, WHATSLEFT, "dn.%s%s=\"%s\"",
+                               type == SLAP_LIMITS_TYPE_SELF ? "" : "this.",
+                               lmpats[style].bv_val, lim->lm_pat.bv_val ));
                        break;
                }
        }
-       bv->bv_len = ptr - bv->bv_val;
-       btmp.bv_val = ptr;
-       btmp.bv_len = 0;
-       if ( limits_unparse_one( &lim->lm_limits,
-                       SLAP_LIMIT_SIZE|SLAP_LIMIT_TIME,
-                       &btmp, WHATSLEFT ) )
-       {
-               return -1;
+       if ( rc == 0 ) {
+               bv->bv_len = ptr - bv->bv_val;
+               btmp.bv_val = ptr;
+               btmp.bv_len = 0;
+               rc = limits_unparse_one( &lim->lm_limits,
+                       SLAP_LIMIT_SIZE | SLAP_LIMIT_TIME,
+                       &btmp, WHATSLEFT );
+               if ( rc == 0 )
+                       bv->bv_len += btmp.bv_len;
        }
-       bv->bv_len += btmp.bv_len;
-       return 0;
+       return rc;
 }
 
 /* Caller must provide an adequately sized buffer in bv */
@@ -964,11 +951,13 @@ limits_unparse_one(
        struct berval   *bv,
        ber_len_t               buflen )
 {
-       char *ptr;
+       char *ptr, *bufEnd;                     /* Updated/used by ptr_APPEND_*()/WHATSLEFT */
+       ber_len_t tmpLen;                       /* Used by ptr_APPEND_FMT*() */
 
        if ( !bv || !bv->bv_val ) return -1;
 
        ptr = bv->bv_val;
+       bufEnd = ptr + buflen;
 
        if ( which & SLAP_LIMIT_SIZE ) {
                if ( lim->lms_s_soft != SLAPD_DEFAULT_SIZELIMIT ) {
@@ -980,79 +969,49 @@ limits_unparse_one(
                                goto s_hard;
                        /* If there's also a hard limit, fully qualify this one */
                        } else if ( lim->lms_s_hard ) {
-                               if ( WHATSLEFT <= STRLENOF( " size.soft=" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, " size.soft=" );
+                               if ( ptr_APPEND_LIT( " size.soft=" ) ) return -1;
 
                        /* If doing both size & time, qualify this */
                        } else if ( which & SLAP_LIMIT_TIME ) {
-                               if ( WHATSLEFT <= STRLENOF( " size=" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, " size=" );
+                               if ( ptr_APPEND_LIT( " size=" ) ) return -1;
                        }
 
-                       if ( lim->lms_s_soft == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_soft );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( lim->lms_s_soft == -1
+                                       ? ptr_APPEND_LIT( "unlimited " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_s_soft ) )
+                               return -1;
                }
 s_hard:
                if ( lim->lms_s_hard ) {
-                       if ( WHATSLEFT <= STRLENOF( " size.hard=" ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " size.hard=" );
-                       if ( lim->lms_s_hard == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_hard );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( ptr_APPEND_LIT( " size.hard=" ) ) return -1;
+                       if ( lim->lms_s_hard == -1
+                                       ? ptr_APPEND_LIT( "unlimited " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_s_hard ) )
+                               return -1;
                }
                if ( lim->lms_s_unchecked != -1 ) {
-                       if ( WHATSLEFT <= STRLENOF( " size.unchecked=" ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " size.unchecked=" );
-                       if ( lim->lms_s_unchecked == 0 ) {
-                               if ( WHATSLEFT <= STRLENOF( "disabled" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "disabled" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_unchecked );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( ptr_APPEND_LIT( " size.unchecked=" ) ) return -1;
+                       if ( lim->lms_s_unchecked == 0
+                                       ? ptr_APPEND_LIT( "disabled " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_s_unchecked ) )
+                               return -1;
                }
                if ( lim->lms_s_pr_hide ) {
-                       if ( WHATSLEFT <= STRLENOF( " size.pr=noEstimate " ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " size.pr=noEstimate " );
+                       if ( ptr_APPEND_LIT( " size.pr=noEstimate " ) ) return -1;
                }
                if ( lim->lms_s_pr ) {
-                       if ( WHATSLEFT <= STRLENOF( " size.pr=" ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " size.pr=" );
-                       if ( lim->lms_s_pr == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_pr );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( ptr_APPEND_LIT( " size.pr=" ) ) return -1;
+                       if ( lim->lms_s_pr == -1
+                                       ? ptr_APPEND_LIT( "unlimited " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_s_pr ) )
+                               return -1;
                }
                if ( lim->lms_s_pr_total ) {
-                       if ( WHATSLEFT <= STRLENOF( " size.prtotal=" ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " size.prtotal=" );
-                       if ( lim->lms_s_pr_total == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else if ( lim->lms_s_pr_total == -2 ) {
-                               if ( WHATSLEFT <= STRLENOF( "disabled" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "disabled" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_s_pr_total );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( ptr_APPEND_LIT( " size.prtotal=" ) ) return -1;
+                       if ( lim->lms_s_pr_total  == -1 ? ptr_APPEND_LIT( "unlimited " )
+                               : lim->lms_s_pr_total == -2 ? ptr_APPEND_LIT( "disabled " )
+                               : ptr_APPEND_FMT1( "%d ", lim->lms_s_pr_total ) )
+                               return -1;
                }
        }
 
@@ -1067,36 +1026,25 @@ s_hard:
 
                        /* If there's also a hard limit, fully qualify this one */
                        } else if ( lim->lms_t_hard ) {
-                               if ( WHATSLEFT <= STRLENOF( " time.soft=" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, " time.soft=" );
+                               if ( ptr_APPEND_LIT( " time.soft=" ) ) return -1;
 
                        /* If doing both size & time, qualify this */
                        } else if ( which & SLAP_LIMIT_SIZE ) {
-                               if ( WHATSLEFT <= STRLENOF( " time=" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, " time=" );
+                               if ( ptr_APPEND_LIT( " time=" ) ) return -1;
                        }
 
-                       if ( lim->lms_t_soft == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_t_soft );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( lim->lms_t_soft == -1
+                                       ? ptr_APPEND_LIT( "unlimited " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_t_soft ) )
+                               return -1;
                }
 t_hard:
                if ( lim->lms_t_hard ) {
-                       if ( WHATSLEFT <= STRLENOF( " time.hard=" ) ) return -1;
-                       ptr = lutil_strcopy( ptr, " time.hard=" );
-                       if ( lim->lms_t_hard == -1 ) {
-                               if ( WHATSLEFT <= STRLENOF( "unlimited" ) ) return -1;
-                               ptr = lutil_strcopy( ptr, "unlimited" );
-                       } else {
-                               ptr += snprintf( ptr, WHATSLEFT, "%d", lim->lms_t_hard );
-                               if ( WHATSLEFT < 0 ) return -1;
-                       }
-                       *ptr++ = ' ';
+                       if ( ptr_APPEND_LIT( " time.hard=" ) ) return -1;
+                       if ( lim->lms_t_hard == -1
+                                       ? ptr_APPEND_LIT( "unlimited " )
+                                       : ptr_APPEND_FMT1( "%d ", lim->lms_t_hard ) )
+                               return -1;
                }
        }
        if ( ptr != bv->bv_val ) {
@@ -1376,6 +1324,19 @@ limits_check( Operation *op, SlapReply *rs )
        return 0;
 }
 
+void
+limits_free_one( 
+       struct slap_limits      *lm )
+{
+       if ( ( lm->lm_flags & SLAP_LIMITS_MASK ) == SLAP_LIMITS_REGEX )
+               regfree( &lm->lm_regex );
+
+       if ( !BER_BVISNULL( &lm->lm_pat ) )
+               ch_free( lm->lm_pat.bv_val );
+
+       ch_free( lm );
+}
+
 void
 limits_destroy( 
        struct slap_limits      **lm )
@@ -1387,25 +1348,7 @@ limits_destroy(
        }
 
        for ( i = 0; lm[ i ]; i++ ) {
-               switch ( lm[ i ]->lm_flags & SLAP_LIMITS_MASK ) {
-               case SLAP_LIMITS_REGEX:
-                       regfree( &lm[ i ]->lm_regex );
-                       break;
-
-               case SLAP_LIMITS_EXACT:
-               case SLAP_LIMITS_ONE:
-               case SLAP_LIMITS_SUBTREE:
-               case SLAP_LIMITS_CHILDREN:
-                       if ( !BER_BVISNULL( &lm[ i ]->lm_pat ) ) {
-                               ch_free( lm[ i ]->lm_pat.bv_val );
-                       }
-                       break;
-
-               default:
-                       break;
-               }
-
-               ch_free( lm[ i ] );
+               limits_free_one( lm[ i ] );
        }
 
        ch_free( lm );