]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldif2ldbm-bdb2.c
Updated some items
[openldap] / servers / slapd / tools / ldif2ldbm-bdb2.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/string.h>
6 #include <ac/ctype.h>
7 #include <ac/socket.h>
8 #include <ac/unistd.h>
9 #include <ac/wait.h>
10
11 #include <sys/param.h>
12
13 #include "ldapconfig.h"
14 #include "../slap.h"
15 #include "../back-bdb2/back-bdb2.h"
16 #include "ldif.h"
17
18 #define INDEXCMD                "ldif2index-bdb2"
19 #define ID2ENTRYCMD             "ldif2id2entry-bdb2"
20 #define ID2CHILDRENCMD          "ldif2id2children-bdb2"
21 #define MAXARGS                 100
22
23 static void fork_child( char *prog, char *args[] );
24 static void     wait4kids( int nkidval );
25
26 static char     *indexcmd;
27 static char     *tailorfile;
28 static char     *inputfile;
29 static int      maxkids = 1;
30 static int      nkids;
31
32 static void
33 usage( char *name )
34 {
35         fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-j #jobs] [-n databasenumber] [-s sbindir]\n", name );
36         exit( 1 );
37 }
38
39 int
40 main( int argc, char **argv )
41 {
42         int             i, stop, status;
43         char            *linep, *buf, *sbindir;
44         char            *args[MAXARGS];
45         char            buf2[20], buf3[20];
46         char            line[BUFSIZ];
47         char            cmd[MAXPATHLEN];
48         int             lineno, elineno;
49         int             lmax, lcur;
50         int             dbnum;
51         ID              id;
52         int             rc;
53         Backend         *be = NULL;
54         struct ldbminfo *li;
55         struct berval   bv;
56         struct berval   *vals[2];
57         Avlnode         *avltypes = NULL;
58
59         sbindir = DEFAULT_SBINDIR;
60         tailorfile = SLAPD_DEFAULT_CONFIGFILE;
61         dbnum = -1;
62         while ( (i = getopt( argc, argv, "d:e:s:f:i:j:n:" )) != EOF ) {
63                 switch ( i ) {
64                 case 'd':       /* turn on debugging */
65                         ldap_debug = atoi( optarg );
66                         break;
67
68                 case 's':       /* alternate sbindir (index cmd location) */
69                 case 'e':       /* accept -e for backwards compatibility */
70                         sbindir = strdup( optarg );
71                         break;
72
73                 case 'f':       /* specify a tailor file */
74                         tailorfile = strdup( optarg );
75                         break;
76
77                 case 'i':       /* input file */
78                         inputfile = strdup( optarg );
79                         break;
80
81                 case 'j':       /* number of parallel index procs */
82                         maxkids = atoi( optarg );
83                         break;
84
85                 case 'n':       /* which config file db to index */
86                         dbnum = atoi( optarg ) - 1;
87                         break;
88
89                 default:
90                         usage( argv[0] );
91                         break;
92                 }
93         }
94         if ( inputfile == NULL ) {
95                 usage( argv[0] );
96         } else {
97                 if ( freopen( inputfile, "r", stdin ) == NULL ) {
98                         perror( inputfile );
99                         exit( 1 );
100                 }
101         }
102
103         /*
104          * initialize stuff and figure out which backend we're dealing with
105          */
106
107         rc = slap_init(SLAP_TOOL_MODE, "ldif2ldbm");
108         if (rc != 0 ) {
109                 fprintf( stderr, "ldif2ldbm: slap_init failed!\n");
110                 exit(1);
111         }
112
113         read_config( tailorfile );
114
115         if ( dbnum == -1 ) {
116                 for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
117                         if ( strcasecmp( backends[dbnum].be_type, "bdb2" )
118                             == 0 ) {
119                                 break;
120                         }
121                 }
122                 if ( dbnum == nbackends ) {
123                         fprintf( stderr, "No bdb2 database found in config file\n" );
124                         exit( 1 );
125                 }
126         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
127                 fprintf( stderr, "Database number selected via -n is out of range\n" );
128                 fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
129                 exit( 1 );
130         } else if ( strcasecmp( backends[dbnum].be_type, "bdb2" ) != 0 ) {
131                 fprintf( stderr, "Database number %d selected via -n is not an bdb2 database\n", dbnum );
132                 exit( 1 );
133         }
134
135         slap_startup(dbnum);
136
137         be = &backends[dbnum];
138
139         /* disable write sync'ing */
140         li = (struct ldbminfo *) be->be_private;
141         li->li_dbcachewsync = 0;
142
143         /*
144          * generate the id2entry index
145          */
146
147         i = 0;
148         sprintf( cmd, "%s/%s", sbindir, ID2ENTRYCMD );
149         args[i++] = cmd;
150         args[i++] = "-i";
151         args[i++] = inputfile;
152         args[i++] = "-f";
153         args[i++] = tailorfile;
154         args[i++] = "-n";
155         sprintf( buf2, "%d", dbnum+1 );
156         args[i++] = buf2;
157         if ( ldap_debug ) {
158                 sprintf( buf3, "%d", ldap_debug );
159                 args[i++] = "-d";
160                 args[i++] = buf3;
161         }
162         args[i++] = NULL;
163         fork_child( cmd, args );
164
165         /*
166          * generate the dn2id and id2children indexes
167          */
168
169         i = 0;
170         sprintf( cmd, "%s/%s", sbindir, ID2CHILDRENCMD );
171         args[i++] = cmd;
172         args[i++] = "-i";
173         args[i++] = inputfile;
174         args[i++] = "-f";
175         args[i++] = tailorfile;
176         args[i++] = "-n";
177         sprintf( buf2, "%d", dbnum+1 );
178         args[i++] = buf2;
179         if ( ldap_debug ) {
180                 sprintf( buf3, "%d", ldap_debug );
181                 args[i++] = "-d";
182                 args[i++] = buf3;
183         }
184         args[i++] = NULL;
185         fork_child( cmd, args );
186
187         /*
188          * generate the attribute indexes
189          */
190
191         i = 0;
192         sprintf( cmd, "%s/%s", sbindir, INDEXCMD );
193         args[i++] = cmd;
194         args[i++] = "-i";
195         args[i++] = inputfile;
196         args[i++] = "-f";
197         args[i++] = tailorfile;
198         args[i++] = "-n";
199         sprintf( buf2, "%d", dbnum+1 );
200         args[i++] = buf2;
201         if ( ldap_debug ) {
202                 sprintf( buf3, "%d", ldap_debug );
203                 args[i++] = "-d";
204                 args[i++] = buf3;
205         }
206         args[i++] = NULL;               /* will hold the attribute name */
207         args[i++] = NULL;
208
209         id = 0;
210         stop = 0;
211         buf = NULL;
212         lineno = 0;
213         lcur = lmax = 0;
214         vals[0] = &bv;
215         vals[1] = NULL;
216         while ( ! stop ) {
217                 char            *type, *val, *s;
218                 int             vlen, indexmask, syntaxmask;
219                 Datum           key, data;
220
221                 ldbm_datum_init( key );
222                 ldbm_datum_init( data );
223
224                 if ( fgets( line, sizeof(line), stdin ) != NULL ) {
225                         int     len;
226
227                         lineno++;
228                         len = strlen( line );
229                         while ( lcur + len + 1 > lmax ) {
230                                 lmax += BUFSIZ;
231                                 buf = (char *) ch_realloc( buf, lmax );
232                         }
233                         strcpy( buf + lcur, line );
234                         lcur += len;
235                 } else {
236                         stop = 1;
237                 }
238                 if ( line[0] == '\n' || stop && buf && *buf ) {
239                         id++;
240                         s = buf;
241                         elineno = 0;
242                         while ( (linep = ldif_getline( &s )) != NULL ) {
243                                 elineno++;
244                                 if ( ldif_parse_line( linep, &type, &val, &vlen )
245                                     != 0 ) {
246                                         Debug( LDAP_DEBUG_PARSE,
247                             "bad line %d in entry ending at line %d ignored\n",
248                                             elineno, lineno, 0 );
249                                         continue;
250                                 }
251
252                                 if ( !isascii( *type ) || isdigit( *type ) )
253                                         continue;
254
255                                 type = strdup( type );
256                                 if ( avl_insert( &avltypes, type, strcasecmp,
257                                     avl_dup_error ) != 0 ) {
258                                         free( type );
259                                 } else {
260                                         bdb2i_attr_masks( be->be_private, type,
261                                             &indexmask, &syntaxmask );
262                                         if ( indexmask ) {
263                                                 args[i - 2] = type;
264                                                 fork_child( cmd, args );
265                                         }
266                                 }
267                         }
268                         *buf = '\0';
269                         lcur = 0;
270                 }
271         }
272
273         slap_shutdown(dbnum);
274
275         wait4kids( -1 );
276
277         slap_destroy();
278
279         exit( 0 );
280 }
281
282 static void
283 fork_child( char *prog, char *args[] )
284 {
285         int     status, pid;
286
287         wait4kids( maxkids );
288
289         switch ( pid = fork() ) {
290         case 0:         /* child */
291                 execvp( prog, args );
292                 fprintf( stderr, "%s: ", prog );
293                 perror( "execv" );
294                 exit( -1 );
295                 break;
296
297         case -1:        /* trouble */
298                 fprintf( stderr, "Could not fork to run %s\n", prog );
299                 perror( "fork" );
300                 break;
301
302         default:        /* parent */
303                 nkids++;
304                 break;
305         }
306 }
307
308 static void
309 wait4kids( int nkidval )
310 {
311         int             status;
312         unsigned char   *p;
313
314         while ( nkids >= nkidval ) {
315                 wait( &status );
316                 p = (unsigned char *) &status;
317                 if ( p[sizeof(int) - 1] == 0177 ) {
318                         fprintf( stderr,
319                             "stopping: child stopped with signal %d\n",
320                             p[sizeof(int) - 2] );
321                 } else if ( p[sizeof(int) - 1] != 0 ) {
322                         fprintf( stderr, 
323                             "stopping: child terminated with signal %d\n",
324                             p[sizeof(int) - 1] );
325                         exit( p[sizeof(int) - 1] );
326                 } else if ( p[sizeof(int) - 2] != 0 ) {
327                         fprintf( stderr, 
328                             "stopping: child exited with status %d\n",
329                             p[sizeof(int) - 2] );
330                         exit( p[sizeof(int) - 2] );
331                 } else {
332                         nkids--;
333                 }
334         }
335 }