]> git.sur5r.net Git - openldap/blob - servers/slapd/entry.c
Don't include portable.h. Headers can and should assume portable.h
[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 void    entry_free();
14 char    *entry2str();
15
16 static unsigned char    *ebuf;  /* buf returned by entry2str             */
17 static unsigned char    *ecur;  /* pointer to end of currently used ebuf */
18 static int              emaxsize;/* max size of ebuf                     */
19
20 Entry *
21 str2entry( char *s )
22 {
23         int             i;
24         Entry           *e;
25         Attribute       **a;
26         char            *type;
27         char            *value;
28         char            *next;
29         int             vlen, nvals, maxvals;
30         struct berval   bval;
31         struct berval   *vals[2];
32         char            ptype[64];
33
34         /*
35          * In string format, an entry looks like this:
36          *
37          *      <id>\n
38          *      dn: <dn>\n
39          *      [<attr>:[:] <value>\n]
40          *      [<tab><continuedvalue>\n]*
41          *      ...
42          *
43          * If a double colon is used after a type, it means the
44          * following value is encoded as a base 64 string.  This
45          * happens if the value contains a non-printing character
46          * or newline.
47          */
48
49         Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
50                 s ? s : "NULL", 0, 0 );
51
52         e = (Entry *) ch_calloc( 1, sizeof(Entry) );
53         /* initialize reader/writer lock */
54         entry_rdwr_init(e);
55
56         /* check to see if there's an id included */
57         next = s;
58         if ( isdigit( *s ) ) {
59                 e->e_id = atoi( s );
60                 if ( (s = str_getline( &next )) == NULL ) {
61                         Debug( LDAP_DEBUG_TRACE,
62                             "<= str2entry NULL (missing newline after id)\n",
63                             0, 0, 0 );
64                         return( NULL );
65                 }
66         }
67
68         /* dn + attributes */
69         e->e_attrs = NULL;
70         vals[0] = &bval;
71         vals[1] = NULL;
72         ptype[0] = '\0';
73         while ( (s = str_getline( &next )) != NULL ) {
74                 if ( *s == '\n' || *s == '\0' ) {
75                         break;
76                 }
77
78                 if ( str_parse_line( s, &type, &value, &vlen ) != 0 ) {
79                         Debug( LDAP_DEBUG_TRACE,
80                             "<= str2entry NULL (parse_line)\n", 0, 0, 0 );
81                         continue;
82                 }
83
84                 if ( strcasecmp( type, ptype ) != 0 ) {
85                         strncpy( ptype, type, sizeof(ptype) - 1 );
86                         nvals = 0;
87                         maxvals = 0;
88                         a = NULL;
89                 }
90                 if ( strcasecmp( type, "dn" ) == 0 ) {
91                         if ( e->e_dn != NULL ) {
92                                 Debug( LDAP_DEBUG_ANY,
93     "str2entry: entry %d has multiple dns \"%s\" and \"%s\" (second ignored)\n",
94                                     e->e_id, e->e_dn, value );
95                                 continue;
96                         }
97                         e->e_dn = strdup( value );
98                         continue;
99                 }
100
101                 bval.bv_val = value;
102                 bval.bv_len = vlen;
103                 if ( attr_merge_fast( e, type, vals, nvals, 1, &maxvals, &a )
104                     != 0 ) {
105                         Debug( LDAP_DEBUG_TRACE,
106                             "<= str2entry NULL (attr_merge)\n", 0, 0, 0 );
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 %d 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%x\n", 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                 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                         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 }
264