]> git.sur5r.net Git - openldap/blob - servers/slapd/entry.c
Wrap db2 mutex with -DHAVE_BERKELEY_DB2 (should be hidden in -lldbm) ITS#35
[openldap] / servers / slapd / entry.c
1 /* entry.c - routines for dealing with entries */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/ctype.h>
8 #include <ac/socket.h>
9 #include <ac/string.h>
10
11 #include "slap.h"
12
13 static unsigned char    *ebuf;  /* buf returned by entry2str             */
14 static unsigned char    *ecur;  /* pointer to end of currently used ebuf */
15 static int              emaxsize;/* max size of ebuf                     */
16
17 Entry *
18 str2entry( char *s )
19 {
20         int             i;
21         Entry           *e;
22         Attribute       **a;
23         char            *type;
24         char            *value;
25         char            *next;
26         int             vlen, nvals, maxvals;
27         struct berval   bval;
28         struct berval   *vals[2];
29         char            ptype[64];
30
31         /*
32          * In string format, an entry looks like this:
33          *
34          *      <id>\n
35          *      dn: <dn>\n
36          *      [<attr>:[:] <value>\n]
37          *      [<tab><continuedvalue>\n]*
38          *      ...
39          *
40          * If a double colon is used after a type, it means the
41          * following value is encoded as a base 64 string.  This
42          * happens if the value contains a non-printing character
43          * or newline.
44          */
45
46         Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
47                 s ? s : "NULL", 0, 0 );
48
49         e = (Entry *) ch_calloc( 1, sizeof(Entry) );
50
51         /* check to see if there's an id included */
52         next = s;
53         if ( isdigit( *s ) ) {
54                 e->e_id = atoi( s );
55                 if ( (s = ldif_getline( &next )) == NULL ) {
56                         Debug( LDAP_DEBUG_TRACE,
57                             "<= str2entry NULL (missing newline after id)\n",
58                             0, 0, 0 );
59                         free( e );
60                         return( NULL );
61                 }
62         }
63
64         /* initialize reader/writer lock */
65         entry_rdwr_init(e);
66
67         /* dn + attributes */
68         e->e_attrs = NULL;
69         vals[0] = &bval;
70         vals[1] = NULL;
71         ptype[0] = '\0';
72         while ( (s = ldif_getline( &next )) != NULL ) {
73                 if ( *s == '\n' || *s == '\0' ) {
74                         break;
75                 }
76
77                 if ( ldif_parse_line( s, &type, &value, &vlen ) != 0 ) {
78                         Debug( LDAP_DEBUG_TRACE,
79                             "<= str2entry NULL (parse_line)\n", 0, 0, 0 );
80                         continue;
81                 }
82
83                 if ( strcasecmp( type, ptype ) != 0 ) {
84                         strncpy( ptype, type, sizeof(ptype) - 1 );
85                         nvals = 0;
86                         maxvals = 0;
87                         a = NULL;
88                 }
89                 if ( strcasecmp( type, "dn" ) == 0 ) {
90                         if ( e->e_dn != NULL ) {
91                                 Debug( LDAP_DEBUG_ANY,
92  "str2entry: entry %lu has multiple dns \"%s\" and \"%s\" (second ignored)\n",
93                                     e->e_id, e->e_dn, value );
94                                 continue;
95                         }
96                         e->e_dn = ch_strdup( value );
97                         continue;
98                 }
99
100                 bval.bv_val = value;
101                 bval.bv_len = vlen;
102                 if ( attr_merge_fast( e, type, vals, nvals, 1, &maxvals, &a )
103                     != 0 ) {
104                         Debug( LDAP_DEBUG_TRACE,
105                             "<= str2entry NULL (attr_merge)\n", 0, 0, 0 );
106                         entry_free( e );
107                         return( NULL );
108                 }
109                 nvals++;
110         }
111
112         /* check to make sure there was a dn: line */
113         if ( e->e_dn == NULL ) {
114                 Debug( LDAP_DEBUG_ANY, "str2entry: entry %lu has no dn\n",
115                     e->e_id, 0, 0 );
116                 entry_free( e );
117                 return( NULL );
118         }
119
120         Debug(LDAP_DEBUG_TRACE, "<= str2entry 0x%lx\n", (unsigned long)e, 0,0);
121
122         return( e );
123 }
124
125 #define GRABSIZE        BUFSIZ
126
127 #define MAKE_SPACE( n ) { \
128                 while ( ecur + (n) > ebuf + emaxsize ) { \
129                         int     offset; \
130                         offset = (int) (ecur - ebuf); \
131                         ebuf = (unsigned char *) ch_realloc( (char *) ebuf, \
132                             emaxsize + GRABSIZE ); \
133                         emaxsize += GRABSIZE; \
134                         ecur = ebuf + offset; \
135                 } \
136 }
137
138 char *
139 entry2str(
140     Entry       *e,
141     int         *len,
142     int         printid
143 )
144 {
145         Attribute       *a;
146         struct berval   *bv;
147         int             i, tmplen;
148
149         /*
150          * In string format, an entry looks like this:
151          *      <id>\n
152          *      dn: <dn>\n
153          *      [<attr>: <value>\n]*
154          */
155
156         ecur = ebuf;
157
158         if ( printid ) {
159                 /* id + newline */
160                 MAKE_SPACE( 10 );
161                 sprintf( (char *) ecur, "%ld\n", e->e_id );
162                 ecur = (unsigned char *) strchr( (char *) ecur, '\0' );
163         }
164
165         /* put the dn */
166         if ( e->e_dn != NULL ) {
167                 /* put "dn: <dn>" */
168                 tmplen = strlen( e->e_dn );
169                 MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen ));
170                 ldif_put_type_and_value( (char **) &ecur, "dn", e->e_dn, tmplen );
171         }
172
173         /* put the attributes */
174         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
175                 /* put "<type>:[:] <value>" line for each value */
176                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
177                         bv = a->a_vals[i];
178                         tmplen = strlen( a->a_type );
179                         MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len ));
180                         ldif_put_type_and_value( (char **) &ecur, a->a_type,
181                             bv->bv_val, bv->bv_len );
182                 }
183         }
184         MAKE_SPACE( 1 );
185         *ecur = '\0';
186         *len = ecur - ebuf;
187
188         return( (char *) ebuf );
189 }
190
191 void
192 entry_free( Entry *e )
193 {
194         int             i;
195         Attribute       *a, *next;
196
197         /* XXX check that no reader/writer locks exist */
198 #ifdef LDAP_DEBUG
199         assert( !pthread_rdwr_wchk_np(&e->e_rdwr) &&
200                 !pthread_rdwr_rchk_np(&e->e_rdwr) );
201 #endif
202
203         if ( e->e_dn != NULL ) {
204                 free( e->e_dn );
205         }
206         for ( a = e->e_attrs; a != NULL; a = next ) {
207                 next = a->a_next;
208                 attr_free( a );
209         }
210         free( e );
211 }
212
213 int
214 entry_rdwr_lock(Entry *e, int rw)
215 {
216         Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
217                 rw ? "w" : "r", e->e_id, 0);
218         if (rw)
219                 return pthread_rdwr_wlock_np(&e->e_rdwr);
220         else
221                 return pthread_rdwr_rlock_np(&e->e_rdwr);
222 }
223
224 int
225 entry_rdwr_rlock(Entry *e)
226 {
227         return entry_rdwr_lock( e, 0 );
228 }
229
230 int
231 entry_rdwr_wlock(Entry *e)
232 {
233         return entry_rdwr_lock( e, 1 );
234 }
235
236 int
237 entry_rdwr_unlock(Entry *e, int rw)
238 {
239         Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
240                 rw ? "w" : "r", e->e_id, 0);
241         if (rw)
242                 return pthread_rdwr_wunlock_np(&e->e_rdwr);
243         else
244                 return pthread_rdwr_runlock_np(&e->e_rdwr);
245 }
246
247 int
248 entry_rdwr_runlock(Entry *e)
249 {
250         return entry_rdwr_unlock( e, 0 );
251 }
252
253 int
254 entry_rdwr_wunlock(Entry *e)
255 {
256         return entry_rdwr_unlock( e, 1 );
257 }
258
259 int
260 entry_rdwr_init(Entry *e)
261 {
262         return pthread_rdwr_init_np(&e->e_rdwr, NULL);
263 }