Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / export / cfgexport.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 * cfgexport - load/configure the EXPORT kernel extension
12 */
13 #include <afsconfig.h>
14 #include <afs/param.h>
15
16
17 #include <errno.h>
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/device.h>
22 #include <sys/sysconfig.h>
23 #include <sys/uio.h>
24 #include <sys/xcoff.h>
25 #include <sys/ldr.h>
26 #include <setjmp.h>
27 #include <signal.h>
28 #include "export.h"
29 #include "sym.h"
30
31 extern char *malloc(), *optarg;
32 extern int sysconfig(int cmd, void *arg, int len);
33
34 int debug = 0;
35 char *syms = "/unix";
36 char *xstrings;
37
38 #include "AFS_component_version_number.c"
39
40 main(argc, argv)
41 char **argv;
42 {
43 int add, del, opts;
44 int c;
45 char *file;
46 mid_t kmid;
47 struct cfg_load cload;
48 struct cfg_kmod cmod;
49 struct k_conf conf;
50 FILE *fp;
51
52 #ifdef AFS_AIX32_ENV
53 /*
54 * The following signal action for AIX is necessary so that in case of a
55 * crash (i.e. core is generated) we can include the user's data section
56 * in the core dump. Unfortunately, by default, only a partial core is
57 * generated which, in many cases, isn't too useful.
58 */
59 struct sigaction nsa;
60
61 sigemptyset(&nsa.sa_mask);
62 nsa.sa_handler = SIG_DFL;
63 nsa.sa_flags = SA_FULLDUMP;
64 sigaction(SIGSEGV, &nsa, NULL);
65 #endif
66 add = del = 0;
67
68 while ((c = getopt(argc, argv, "a:s:Z:d:")) != EOF) {
69 switch (c) {
70 case 'Z': /* Zdebug option */
71 ++debug;
72 break;
73
74 case 'a':
75 add = 1;
76 file = optarg;
77 if (!file)
78 usage();
79 break;
80
81 case 'd':
82 del = 1;
83 file = optarg;
84 if (!file)
85 usage();
86 break;
87
88 case 's':
89 syms = optarg;
90 break;
91
92 default:
93 usage();
94 break;
95 }
96 }
97
98 if (!add && !del)
99 usage();
100
101 if (add) {
102 char *buf[1024];
103 char PidFile[256];
104
105 buf[0] = "execerror";
106 buf[1] = "cfgexport";
107 get_syms(&conf, syms);
108
109 cload.path = file;
110 if (sysconfig(SYS_KLOAD, &cload, sizeof(cload)) == -1) {
111 loadquery(L_GETMESSAGES, &buf[2], sizeof buf - 8);
112 execvp("/etc/execerror", buf);
113 perror("SYS_KLOAD");
114 exit(1);
115 }
116
117 cmod.kmid = cload.kmid;
118 cmod.cmd = CFG_INIT;
119 cmod.mdiptr = (caddr_t) & conf;
120 cmod.mdilen = sizeof(conf);
121
122 if (sysconfig(SYS_CFGKMOD, &cmod, sizeof(cmod)) == -1) {
123 perror("SYS_CFGKMOD");
124 cload.kmid = cload.kmid;
125 sysconfig(SYS_KULOAD, &cload, sizeof(cload));
126 exit(1);
127 }
128 #ifdef notdef
129 printf("cfgexport -d 0x%x # to remove EXPORT\n", cload.kmid);
130 #endif
131 strcpy(PidFile, file);
132 strcat(PidFile, ".kmid");
133 fp = fopen(PidFile, "w");
134 if (fp) {
135 (void)fprintf(fp, "%d\n", cload.kmid);
136 (void)fclose(fp);
137 } else {
138 printf("Can't open for write file %s (error=%d); ignored\n",
139 PidFile, errno);
140 }
141 exit(0);
142 } else if (del) {
143 char PidFile[256];
144
145 strcpy(PidFile, file);
146 strcat(PidFile, ".kmid");
147 fp = fopen(PidFile, "r");
148 if (!fp) {
149 printf("Can't read %s file (error=%d); aborting\n", PidFile,
150 errno);
151 exit(1);
152 }
153 (void)fscanf(fp, "%d\n", &kmid);
154 (void)fclose(fp);
155 unlink(PidFile);
156 cmod.kmid = kmid;
157 cmod.cmd = CFG_TERM;
158 cmod.mdiptr = NULL;
159 cmod.mdilen = 0;
160
161 if (sysconfig(SYS_CFGKMOD, &cmod, sizeof(cmod)) == -1) {
162 perror("SYS_CFGKMOD");
163 exit(1);
164 }
165
166 cload.kmid = kmid;
167 if (sysconfig(SYS_KULOAD, &cload, sizeof(cload)) == -1) {
168 perror("SYS_KULOAD");
169 exit(1);
170 }
171 exit(0);
172 }
173 }
174
175 usage()
176 {
177
178 error("usage: cfgexport [-a mod_file [-s symbols]] [-d mod_file]\n");
179 }
180
181 /*
182 * get_syms - get kernel symbol table info.
183 *
184 * Input:
185 * conf - ^ to EXPORT extension configuration struct
186 * syms - ^ to name of file containing XCOFF symbols
187 */
188 get_syms(conf, syms)
189 struct k_conf *conf;
190 char *syms;
191 {
192 sym_t *k_symtab, *ksp;
193 struct syment *x_symtab, *xsp, *xsq;
194 char *kstrings;
195 struct xcoffhdr hdr; /* XCOFF header from symbol file */
196 sym_t k_sym; /* export version of symbol */
197 struct syment xcoff_sym; /* xcoff version of symbol */
198 int i, nsyms, nksyms, nxsyms = 0;
199 int xstr_size, kstr_size;
200 FILE *fp;
201 int xsym_compar();
202
203 if (syms == NULL)
204 sys_error("syms is NULL");
205 fp = fopen(syms, "r");
206 if (fp == NULL)
207 sys_error(syms);
208
209 if (fread(&hdr, sizeof(hdr), 1, fp) != 1)
210 sys_error(syms);
211
212 if (hdr.filehdr.f_nsyms == 0)
213 error("%s: no symbols", syms);
214
215 switch (hdr.filehdr.f_magic) {
216 case U802WRMAGIC:
217 case U802ROMAGIC:
218 case U802TOCMAGIC:
219 case U800WRMAGIC:
220 case U800ROMAGIC:
221 case U800TOCMAGIC:
222 #ifdef __XCOFF64__
223 case U64_TOCMAGIC:
224 #endif
225 break;
226
227 default:
228 error("%s: funny magic number 0%o", syms, hdr.filehdr.f_magic);
229 }
230
231 nsyms = hdr.filehdr.f_nsyms;
232 if (debug)
233 printf("nsyms = %d\n", nsyms);
234
235 x_symtab = malloc(nsyms * SYMESZ);
236 if (!x_symtab)
237 error("no memory for symbol table");
238
239 /*
240 * try to snarf the string table: should be just past the
241 * symbol table: first 4 bytes is length of rest.
242 */
243 if (fseek(fp, hdr.filehdr.f_symptr + nsyms * SYMESZ, 0) < 0)
244 sys_error("%s: seek to strtab", syms);
245
246 if (fread(&xstr_size, sizeof(xstr_size), 1, fp) != 1)
247 error("%s: reading string table size", syms);
248
249 xstrings = malloc(xstr_size + sizeof(xstr_size));
250 if (!xstrings)
251 error("no memory for string table");
252
253 /*
254 * seek back to the start of the strings
255 */
256 if (fseek(fp, hdr.filehdr.f_symptr + nsyms * SYMESZ, 0) < 0)
257 sys_error("%s: seek to strtab", syms);
258
259 if (fread(xstrings, sizeof(*xstrings), xstr_size, fp) != xstr_size)
260 error("%s: reading string table");
261
262 /*
263 * now seek back to the start of the symbol table, and read it
264 * all in.
265 */
266 if (fseek(fp, hdr.filehdr.f_symptr, 0) < 0)
267 sys_error("%s: seek to symtab", syms);
268
269 xsp = &x_symtab[0];
270
271 for (i = nxsyms = 0; i < nsyms; ++i) {
272 char name[16], *p;
273
274 if (fread(&xcoff_sym, SYMESZ, 1, fp) != 1)
275 error("%s: reading symbol entry", syms);
276
277 #ifdef __XCOFF64__
278 p = xstrings + xcoff_sym.n_offset;
279 #else
280 if (xcoff_sym.n_zeroes == 0) {
281 /*
282 * Need to relocate string table offset
283 */
284 p = xcoff_sym.n_nptr = xstrings + xcoff_sym.n_offset;
285 } else {
286 strncpy(name, xcoff_sym.n_name, 8);
287
288 p = name, p[8] = 0;
289 }
290 #endif
291
292 if (debug > 2)
293 dump_xsym(&xcoff_sym);
294
295 switch (xcoff_sym.n_sclass) {
296 case C_EXT: /* external */
297 case C_HIDEXT: /* hidden external (sic) */
298 /*
299 * filtre out the ones with the strange names
300 */
301 if (strchr(p, '@') || strchr(p, '$') || p[0] == 0)
302 break;
303
304 *xsp++ = xcoff_sym;
305 ++nxsyms;
306
307 if (debug > 1)
308 dump_xsym(&xcoff_sym);
309
310 break;
311 }
312
313 if (xcoff_sym.n_numaux) {
314 fseek(fp, xcoff_sym.n_numaux * AUXESZ, 1);
315 i += xcoff_sym.n_numaux;
316 }
317 }
318
319 fclose(fp);
320
321 /*
322 * sort the symbol table
323 */
324 qsort((char *)x_symtab, nxsyms, sizeof(*x_symtab), xsym_compar);
325
326 /*
327 * we will need no more than `nxsyms' symbols.
328 */
329 k_symtab = malloc(nxsyms * sizeof(sym_t));
330 if (!k_symtab)
331 error("no memory for EXPORT symbol table");
332
333 /*
334 * uniquify it, and xlate to funny EXPORT format
335 */
336 xsp = xsq = x_symtab;
337 ksp = k_symtab;
338 kstrings = 0;
339 kstr_size = 0;
340 nksyms = 0;
341
342 memset(xsq = &xcoff_sym, 0, sizeof(*xsq));
343
344 for (i = 1; i < nxsyms; ++i, xsq = xsp++) {
345 #ifdef __XCOFF64__
346 if (xsp->n_offset != xsq->n_offset || xsp->n_value != xsq->n_value) {
347 #else
348 if (xsp->n_zeroes != xsq->n_zeroes || xsp->n_offset != xsq->n_offset
349 || xsp->n_value != xsq->n_value) {
350 #endif
351 xlate_xtok(xsp, ksp++, &kstrings, &kstr_size);
352 ++nksyms;
353 }
354 }
355
356 /*
357 * place the symbol table info into the `conf' data structure
358 *
359 * XXXXX: for today only, leave the string table the same.
360 */
361 conf->nsyms = nksyms;
362 conf->symt_sz = nksyms * sizeof(sym_t);
363 conf->str_sz = kstr_size;
364 conf->symtab = (caddr_t) k_symtab;
365 conf->strtab = kstrings;
366 }
367
368
369 /*
370 * xlate_xtok - xlate XCOFF to EXPORT format
371 *
372 * Input:
373 * xp - ^ to XCOFF symbol
374 * kp - ^ to EXPORT symbol save area
375 * strp - ^ to ^ to EXPORT string table
376 * szp - ^ to EXPORT string table size
377 */
378 #define SYMBUFSIZE 1048576
379 xlate_xtok(xp, kp, strp, szp)
380 struct syment *xp;
381 sym_t *kp;
382 char **strp;
383 uint *szp;
384 {
385 int len;
386 static char *export_strings = NULL, *prev = "";
387 static left, offset, sz;
388
389 if (!export_strings) {
390 export_strings = malloc(sz = SYMBUFSIZE);
391 if (!export_strings)
392 error("no memory for EXPORT string table");
393
394 *strp = export_strings;
395 *szp = offset = sizeof(uint);
396 left = SYMBUFSIZE - offset;
397
398 export_strings += offset;
399
400 *(uint *) export_strings = 0; /* initial 4 bytes */
401 }
402 #ifdef __XCOFF64__
403 if (strcmp(prev, xstrings + xp->n_offset) == 0) {
404 /*
405 * same name as previous entry: just use previous
406 */
407 kp->n_offset = offset - strlen(*strp + xp->n_offset) - 1;
408 } else
409 if (find_suffix
410 (xstrings + xp->n_offset, *strp, offset, &kp->n_offset)) {
411 /*
412 * found a string that we are a suffix of
413 */
414 ;
415 } else {
416 /*
417 * need to add to our string table
418 */
419 len = strlen(xstrings + xp->n_offset) + 1;
420 while (len >= left) {
421 fprintf(stderr, "cfgexport: Out of memory. Increase SYMBUFSIZE and recompile\n");
422 exit(1);
423 #if 0
424 /* Something is broken with this code, after being here
425 cfgexport segfaults */
426 export_strings = (char *)realloc(*strp, sz += SYMBUFSIZE);
427 if (!export_strings)
428 error("no memory for EXPORT string table");
429 *strp = export_strings;
430 left += SYMBUFSIZE;
431 prev = ""; /* lazy */
432 #endif
433 }
434
435 strcpy(prev = *strp + offset, xstrings + xp->n_offset);
436
437 kp->n_offset = offset;
438 offset += len;
439 left -= len;
440 *szp += len;
441 }
442 #else
443 if (kp->n_zeroes = xp->n_zeroes) { /* sic */
444 kp->n_zeroes = xp->n_zeroes;
445 kp->n_offset = xp->n_offset;
446 } else if (strcmp(prev, xp->n_nptr) == 0) {
447 /*
448 * same name as previous entry: just use previous
449 */
450 kp->n_offset = offset - strlen(xp->n_nptr) - 1;
451 } else if (find_suffix(xp->n_nptr, *strp, offset, &kp->n_offset)) {
452 /*
453 * found a string that we are a suffix of
454 */
455 ;
456 } else {
457 /*
458 * need to add to our string table
459 */
460 len = strlen(xp->n_nptr) + 1;
461 while (len >= left) {
462 export_strings = realloc(*strp, sz += SYMBUFSIZE);
463 if (!export_strings)
464 error("no memory for EXPORT string table");
465 *strp = export_strings;
466 left += SYMBUFSIZE;
467 prev = ""; /* lazy */
468 }
469
470 strcpy(prev = *strp + offset, xp->n_nptr);
471
472 kp->n_offset = offset;
473 offset += len;
474 left -= len;
475 *szp += len;
476 }
477 #endif
478
479 kp->n_value = xp->n_value;
480
481 if (debug)
482 dump_ksym(kp, *strp);
483 }
484
485 /*
486 * find_suffix - look for a string that arg string is suffix of
487 *
488 * Input:
489 * p - ^ to string we hope is a suffix of another
490 * strings - ^ to string table
491 * max - max offset of valid string in strings
492 * offp - ^ to place to store offset, if containing string found
493 *
494 * Returns:
495 * 0 - no containing string found
496 * !0 - string found of which `p' is a suffix
497 *
498 * NOTE:
499 * This is rather inefficient.
500 */
501 find_suffix(p, strings, max, offp)
502 char *p, *strings;
503 uint *offp;
504 {
505 char *q, *e;
506 int len = strlen(p) - 1;
507
508 strings += sizeof(uint);
509 max -= sizeof(uint);
510
511 for (e = strings + max; e > strings;) {
512 /*
513 * adjust `e' to point at last non-blank
514 */
515 if (*e == 0) {
516 --e;
517 continue;
518 }
519
520 for (q = p + len; q > p && *q == *e;)
521 --q, --e;
522
523 if (*q == *e) {
524 if (debug)
525 printf("found_suffix: %s\n", p);
526 return *offp = e - strings + sizeof(uint);
527 }
528
529 if (*e)
530 while (*e && e > strings)
531 --e;
532 }
533
534 return 0;
535 }
536
537 /*
538 * xsym_compar - compare two XCOFF symbol table entries
539 *
540 * If the names are the same, sort by descending storage class, so that
541 * C_EXT < C_HIDEXT;
542 */
543 xsym_compar(xp, xq)
544 struct syment *xp, *xq;
545 {
546 char *p, *q;
547 int compar;
548
549 #ifndef __XCOFF64__
550 p = (xp->n_zeroes ? xp->n_name : xp->n_nptr);
551 q = (xq->n_zeroes ? xq->n_name : xq->n_nptr);
552
553 if (xp->n_zeroes || xq->n_zeroes)
554 compar = strncmp(p, q, 8);
555 else
556 #else
557 p = xstrings + xp->n_offset;
558 q = xstrings + xq->n_offset;
559 #endif
560 compar = strcmp(p, q);
561
562 if (compar == 0)
563 compar = xp->n_sclass - xq->n_sclass;
564
565 return compar;
566 }
567
568 /*
569 * dump_xsym - print to XCOFF symbol
570 */
571 dump_xsym(xsp)
572 struct syment *xsp;
573 {
574
575 #ifndef __XCOFF64__
576 if (xsp->n_zeroes)
577 printf
578 ("nptr <%-8.8s %8.8s> val %8.8x sc# %4.4x type %4.4x sclass %2.2x naux %2.2x\n",
579 xsp->n_name, "", xsp->n_value, xsp->n_scnum & 0xffff,
580 xsp->n_type, xsp->n_sclass, xsp->n_numaux);
581 else
582 #endif
583 printf
584 ("nptr <%-17.17s> val %8.8x sc# %4.4x type %4.4x sclass %2.2x naux %2.2x\n"
585 #ifdef __XCOFF64__
586 , xstrings + xsp->n_offset
587 #else
588 , xsp->n_nptr
589 #endif
590 , xsp->n_value, xsp->n_scnum & 0xffff, xsp->n_type,
591 xsp->n_sclass, xsp->n_numaux);
592 }
593
594 dump_ksym(ksp, strings)
595 sym_t *ksp;
596 char *strings;
597 {
598
599 #ifndef __XCOFF64__
600 if (ksp->n_zeroes)
601 printf("%8.8x %-8.8s\n", ksp->n_value, ksp->n_name);
602 else
603 #endif
604 printf("%8.8x %s\n", ksp->n_value, ksp->n_offset + strings);
605 }
606
607 error(p, a, b, c, d, e)
608 char *p;
609 {
610
611 fprintf(stderr, p, a, b, c, d, e);
612 fprintf(stderr, "\n");
613 exit(1);
614 }
615
616 sys_error(p, a, b, c, d, e)
617 char *p;
618 {
619
620 fprintf(stderr, p, a, b, c, d, e);
621 perror(": ");
622 exit(1);
623 }
624
625 warn(p, a, b, c, d, e)
626 char *p;
627 {
628
629 fprintf(stderr, p, a, b, c, d, e);
630 fprintf(stderr, "\n");
631 }