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