29 * Deal with the lib.a(member.o) and lib.a((entry-point)) notations
30 *
31 * Look inside archives for notations a(b) and a((b))
32 * a(b) is file member b in archive a
33 * a((b)) is entry point b in object archive a
34 *
35 * For 6.0, create a make which can understand all archive
36 * formats. This is kind of tricky, and <ar.h> isnt any help.
37 */
38
39 /*
40 * Included files
41 */
42 #include <avo/avo_alloca.h> /* alloca() */
43 #include <ar.h>
44 #include <errno.h> /* errno */
45 #include <fcntl.h> /* open() */
46 #include <mk/defs.h>
47 #include <mksh/misc.h> /* retmem_mb() */
48
49 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
50 struct ranlib {
51 union {
52 off_t ran_strx; /* string table index of */
53 char *ran_name; /* symbol defined by */
54 } ran_un;
55 off_t ran_off; /* library member at this offset */
56 };
57 #else
58 #include <ranlib.h>
59 #endif
60
61 #if defined(linux)
62 #include <ctype.h> /* isspace */
63 #else
64 #include <unistd.h> /* close() */
65 #endif
66
67
68 /*
69 * Defined macros
70 */
71 #ifndef S5EMUL
72 #undef BITSPERBYTE
73 #define BITSPERBYTE 8
74 #endif
75
76 /*
77 * Defines for all the different archive formats. See next comment
78 * block for justification for not using <ar.h>s versions.
79 */
271 * filename The name of the archive we need to read
272 * arp Pointer to ar file description block
273 *
274 * Global variables used:
275 */
276 static Boolean
277 open_archive(char *filename, register Ar *arp)
278 {
279 int fd;
280 char mag_5[AR_5_MAGIC_LENGTH];
281 char mag_port[AR_PORT_MAGIC_LENGTH];
282 char buffer[4];
283
284 arp->fd = NULL;
285 fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
286 if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
287 return failed;
288 }
289 (void) fcntl(fileno(arp->fd), F_SETFD, 1);
290
291 #if !defined(SUN5_0) && !defined(linux) //XXX
292 /* Read enough of the archive to distinguish between the formats */
293 if (fread(mag_5, AR_5_MAGIC_LENGTH, 1, arp->fd) != 1) {
294 return failed;
295 }
296 if (IS_EQUALN(mag_5, AR_5_MAGIC, AR_5_MAGIC_LENGTH)) {
297 arp->type = AR_5;
298 /* Must read in header to set necessary info */
299 if (fseek(arp->fd, 0L, 0) != 0 ||
300 fread((char *) &arp->arh_5, sizeof (Arh_5), 1, arp->fd) !=
301 1) {
302 return failed;
303 }
304 arp->sym_begin = ftell(arp->fd);
305 arp->num_symbols = sgetl(arp->arh_5.ar_syms);
306 arp->first_ar_mem = arp->sym_begin +
307 sizeof (Ars_5) * arp->num_symbols;
308 arp->sym_size = 0L;
309 return succeeded;
310 }
311 if (fseek(arp->fd, 0L, 0) != 0) {
312 return failed;
313 }
314 #endif
315 if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
316 return failed;
317 }
318 if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
319 arp->type = AR_PORT;
320 /*
321 * Read in first member header to find out if there is
322 * a symbol definition table.
323 */
324
325 int ret = read_member_header(&arp->ar_port, arp->fd, filename);
326 if (ret == failed) {
327 return failed;
328 } else if(ret == -1) {
329 /* There is no member header - empty archive */
330 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
331 arp->first_ar_mem = ftell(arp->fd);
332 return succeeded;
333 }
334 /*
335 * The following values are the default if there is
336 * no symbol directory and long member names.
337 */
338 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
339 arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
340
341 /*
342 * Do we have a symbol table? A symbol table is always
343 * the first member in an archive. In 4.1.x it has the
344 * name __.SYMDEF, in SVr4, it has the name "/ "
345 */
346 /*
347 #ifdef SUN5_0
348 MBSTOWCS(wcs_buffer, NOCATGETS("/ "));
349 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
350 #else
351 MBSTOWCS(wcs_buffer, NOCATGETS("__.SYMDEF "));
352 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
353 #endif
354 */
355 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
356 if (IS_EQUALN(arp->ar_port.ar_name,
357 NOCATGETS("/ "),
358 16)) {
359 #else
360 if (IS_EQUALN(arp->ar_port.ar_name,
361 NOCATGETS("__.SYMDEF "),
362 16)) {
363 #endif
364 if (sscanf(arp->ar_port.ar_size,
365 "%ld",
366 &arp->sym_size) != 1) {
367 return failed;
368 }
369 arp->sym_size += (arp->sym_size & 1); /* round up */
370 if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
371 return failed;
372 }
373 arp->num_symbols = sgetl(buffer);
374 arp->sym_begin = ftell(arp->fd);
375 arp->first_ar_mem = arp->sym_begin +
376 arp->sym_size - sizeof buffer;
377 }
378 return succeeded;
379 }
380 fatal(catgets(catd, 1, 3, "`%s' is not an archive"), filename);
381 /* NOTREACHED */
382 return failed;
383 }
399 }
400 }
401
402 /*
403 * read_archive_dir(arp, library, long_names_table)
404 *
405 * Reads the directory of an archive and enters all
406 * the members into the make symboltable in lib(member) format
407 * with their dates.
408 *
409 * Parameters:
410 * arp Pointer to ar file description block
411 * library Name of lib to enter members for.
412 * Used to form "lib(member)" string.
413 * long_names_table table that contains list of members
414 * with names > 15 characters long
415 *
416 * Global variables used:
417 */
418 static Boolean
419 #if defined(SUN5_0) || defined(linux) //XXX
420 read_archive_dir(register Ar *arp, Name library, char **long_names_table)
421 #else
422 read_archive_dir(register Ar *arp, Name library, char **)
423 #endif
424 {
425 wchar_t *name_string;
426 wchar_t *member_string;
427 register long len;
428 register wchar_t *p;
429 register char *q;
430 register Name name;
431 Property member;
432 long ptr;
433 long date;
434
435 #if defined(SUN5_0) || defined(linux) //XXX
436 int offset;
437
438 /*
439 * If any of the members has a name > 15 chars,
440 * it will be found here.
441 */
442 if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
443 return failed;
444 }
445 #endif
446 name_string = ALLOC_WC((int) (library->hash.length +
447 (int) ar_member_name_len * 2));
448 (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
449 member_string = name_string + library->hash.length;
450 *member_string++ = (int) parenleft_char;
451
452 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
453 goto read_error;
454 }
455 /* Read the directory using the appropriate format */
456 switch (arp->type) {
457 case AR_5:
458 for (;;) {
459 if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
460 != 1) {
461 if (feof(arp->fd)) {
462 return succeeded;
463 }
464 break;
465 }
501 }
502 break;
503 case AR_PORT:
504 for (;;) {
505 if ((fread((char *) &arp->ar_port,
506 sizeof arp->ar_port,
507 1,
508 arp->fd) != 1) ||
509 !IS_EQUALN(arp->ar_port.ar_fmag,
510 AR_PORT_END_MAGIC,
511 sizeof arp->ar_port.ar_fmag)) {
512 if (feof(arp->fd)) {
513 return succeeded;
514 }
515 fatal(
516 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
517 library->string_mb,
518 ftell(arp->fd)
519 );
520 }
521 #if defined(SUN5_0) || defined(linux) //XXX
522 /* If it's a long name, retrieve it from long name table */
523 if (arp->ar_port.ar_name[0] == '/') {
524 /*
525 * "len" is used for hashing the string.
526 * We're using "ar_member_name_len" instead of
527 * the actual name length since it's the longest
528 * string the "ar" command can handle at this
529 * point.
530 */
531 len = ar_member_name_len;
532 sscanf(arp->ar_port.ar_name + 1,
533 "%ld",
534 &offset);
535 q = *long_names_table + offset;
536 } else {
537 q = arp->ar_port.ar_name;
538 len = sizeof arp->ar_port.ar_name;
539 }
540 #else
541 q = arp->ar_port.ar_name;
542 len = sizeof arp->ar_port.ar_name;
543 #endif
544
545 for (p = member_string;
546 (len > 0) &&
547 (*q != (int) nul_char) &&
548 !isspace(*q) &&
549 (*q != (int) slash_char);
550 ) {
551 MBTOWC(p, q);
552 p++;
553 q++;
554 }
555 *p++ = (int) parenright_char;
556 *p = (int) nul_char;
557 name = GETNAME(name_string, FIND_LENGTH);
558 name->is_member = library->is_member;
559 member = maybe_append_prop(name, member_prop);
560 member->body.member.library = library;
561 *--p = (int) nul_char;
562 if (member->body.member.member == NULL) {
563 member->body.member.member =
767 (long) *offs,
768 0) != 0) {
769 goto read_error;
770 }
771 if ((fread((char *) &arp->ar_port,
772 sizeof arp->ar_port,
773 1,
774 arp->fd) != 1) ||
775 !IS_EQUALN(arp->ar_port.ar_fmag,
776 AR_PORT_END_MAGIC,
777 sizeof arp->ar_port.ar_fmag)) {
778 goto read_error;
779 }
780 if (sscanf(arp->ar_port.ar_date,
781 "%ld",
782 &date) != 1) {
783 fatal(catgets(catd, 1, 9, "Bad date field for member `%s' in archive `%s'"),
784 arp->ar_port.ar_name,
785 target->string_mb);
786 }
787 #if defined(SUN5_0) || defined(linux) //XXX
788 /* If it's a long name, retrieve it from long name table */
789 if (arp->ar_port.ar_name[0] == '/') {
790 sscanf(arp->ar_port.ar_name + 1,
791 "%ld",
792 &offset);
793 len = ar_member_name_len;
794 hp = *long_names_table + offset;
795 } else {
796 len = sizeof arp->ar_port.ar_name;
797 hp = arp->ar_port.ar_name;
798 }
799 #else
800 hp = arp->ar_port.ar_name;
801 #endif
802 ap = member_string;
803 while (*hp &&
804 (*hp != (int) slash_char) &&
805 (ap < &member_string[len])) {
806 MBTOWC(ap, hp);
807 ap++;
808 hp++;
809 }
810 *ap = (int) nul_char;
811 member->body.member.member =
812 GETNAME(member_string, FIND_LENGTH);
813 target->stat.time.tv_sec = date;
814 target->stat.time.tv_nsec = LONG_MAX;
815 return;
816 }
817 offs++;
818 while(*syms!='\0') syms++;
819 syms++;
820 }
821 }
|
29 * Deal with the lib.a(member.o) and lib.a((entry-point)) notations
30 *
31 * Look inside archives for notations a(b) and a((b))
32 * a(b) is file member b in archive a
33 * a((b)) is entry point b in object archive a
34 *
35 * For 6.0, create a make which can understand all archive
36 * formats. This is kind of tricky, and <ar.h> isnt any help.
37 */
38
39 /*
40 * Included files
41 */
42 #include <avo/avo_alloca.h> /* alloca() */
43 #include <ar.h>
44 #include <errno.h> /* errno */
45 #include <fcntl.h> /* open() */
46 #include <mk/defs.h>
47 #include <mksh/misc.h> /* retmem_mb() */
48
49 struct ranlib {
50 union {
51 off_t ran_strx; /* string table index of */
52 char *ran_name; /* symbol defined by */
53 } ran_un;
54 off_t ran_off; /* library member at this offset */
55 };
56
57 #if defined(linux)
58 #include <ctype.h> /* isspace */
59 #else
60 #include <unistd.h> /* close() */
61 #endif
62
63
64 /*
65 * Defined macros
66 */
67 #ifndef S5EMUL
68 #undef BITSPERBYTE
69 #define BITSPERBYTE 8
70 #endif
71
72 /*
73 * Defines for all the different archive formats. See next comment
74 * block for justification for not using <ar.h>s versions.
75 */
267 * filename The name of the archive we need to read
268 * arp Pointer to ar file description block
269 *
270 * Global variables used:
271 */
272 static Boolean
273 open_archive(char *filename, register Ar *arp)
274 {
275 int fd;
276 char mag_5[AR_5_MAGIC_LENGTH];
277 char mag_port[AR_PORT_MAGIC_LENGTH];
278 char buffer[4];
279
280 arp->fd = NULL;
281 fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
282 if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
283 return failed;
284 }
285 (void) fcntl(fileno(arp->fd), F_SETFD, 1);
286
287 if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
288 return failed;
289 }
290 if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
291 arp->type = AR_PORT;
292 /*
293 * Read in first member header to find out if there is
294 * a symbol definition table.
295 */
296
297 int ret = read_member_header(&arp->ar_port, arp->fd, filename);
298 if (ret == failed) {
299 return failed;
300 } else if(ret == -1) {
301 /* There is no member header - empty archive */
302 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
303 arp->first_ar_mem = ftell(arp->fd);
304 return succeeded;
305 }
306 /*
307 * The following values are the default if there is
308 * no symbol directory and long member names.
309 */
310 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
311 arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
312
313 /*
314 * Do we have a symbol table? A symbol table is always
315 * the first member in an archive. In 4.1.x it has the
316 * name __.SYMDEF, in SVr4, it has the name "/ "
317 */
318 /*
319 MBSTOWCS(wcs_buffer, "/ ");
320 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
321 */
322 if (IS_EQUALN(arp->ar_port.ar_name,
323 NOCATGETS("/ "),
324 16)) {
325 if (sscanf(arp->ar_port.ar_size,
326 "%ld",
327 &arp->sym_size) != 1) {
328 return failed;
329 }
330 arp->sym_size += (arp->sym_size & 1); /* round up */
331 if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
332 return failed;
333 }
334 arp->num_symbols = sgetl(buffer);
335 arp->sym_begin = ftell(arp->fd);
336 arp->first_ar_mem = arp->sym_begin +
337 arp->sym_size - sizeof buffer;
338 }
339 return succeeded;
340 }
341 fatal(catgets(catd, 1, 3, "`%s' is not an archive"), filename);
342 /* NOTREACHED */
343 return failed;
344 }
360 }
361 }
362
363 /*
364 * read_archive_dir(arp, library, long_names_table)
365 *
366 * Reads the directory of an archive and enters all
367 * the members into the make symboltable in lib(member) format
368 * with their dates.
369 *
370 * Parameters:
371 * arp Pointer to ar file description block
372 * library Name of lib to enter members for.
373 * Used to form "lib(member)" string.
374 * long_names_table table that contains list of members
375 * with names > 15 characters long
376 *
377 * Global variables used:
378 */
379 static Boolean
380 read_archive_dir(register Ar *arp, Name library, char **long_names_table)
381 {
382 wchar_t *name_string;
383 wchar_t *member_string;
384 register long len;
385 register wchar_t *p;
386 register char *q;
387 register Name name;
388 Property member;
389 long ptr;
390 long date;
391
392 int offset;
393
394 /*
395 * If any of the members has a name > 15 chars,
396 * it will be found here.
397 */
398 if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
399 return failed;
400 }
401 name_string = ALLOC_WC((int) (library->hash.length +
402 (int) ar_member_name_len * 2));
403 (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
404 member_string = name_string + library->hash.length;
405 *member_string++ = (int) parenleft_char;
406
407 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
408 goto read_error;
409 }
410 /* Read the directory using the appropriate format */
411 switch (arp->type) {
412 case AR_5:
413 for (;;) {
414 if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
415 != 1) {
416 if (feof(arp->fd)) {
417 return succeeded;
418 }
419 break;
420 }
456 }
457 break;
458 case AR_PORT:
459 for (;;) {
460 if ((fread((char *) &arp->ar_port,
461 sizeof arp->ar_port,
462 1,
463 arp->fd) != 1) ||
464 !IS_EQUALN(arp->ar_port.ar_fmag,
465 AR_PORT_END_MAGIC,
466 sizeof arp->ar_port.ar_fmag)) {
467 if (feof(arp->fd)) {
468 return succeeded;
469 }
470 fatal(
471 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
472 library->string_mb,
473 ftell(arp->fd)
474 );
475 }
476 /* If it's a long name, retrieve it from long name table */
477 if (arp->ar_port.ar_name[0] == '/') {
478 /*
479 * "len" is used for hashing the string.
480 * We're using "ar_member_name_len" instead of
481 * the actual name length since it's the longest
482 * string the "ar" command can handle at this
483 * point.
484 */
485 len = ar_member_name_len;
486 sscanf(arp->ar_port.ar_name + 1,
487 "%ld",
488 &offset);
489 q = *long_names_table + offset;
490 } else {
491 q = arp->ar_port.ar_name;
492 len = sizeof arp->ar_port.ar_name;
493 }
494
495 for (p = member_string;
496 (len > 0) &&
497 (*q != (int) nul_char) &&
498 !isspace(*q) &&
499 (*q != (int) slash_char);
500 ) {
501 MBTOWC(p, q);
502 p++;
503 q++;
504 }
505 *p++ = (int) parenright_char;
506 *p = (int) nul_char;
507 name = GETNAME(name_string, FIND_LENGTH);
508 name->is_member = library->is_member;
509 member = maybe_append_prop(name, member_prop);
510 member->body.member.library = library;
511 *--p = (int) nul_char;
512 if (member->body.member.member == NULL) {
513 member->body.member.member =
717 (long) *offs,
718 0) != 0) {
719 goto read_error;
720 }
721 if ((fread((char *) &arp->ar_port,
722 sizeof arp->ar_port,
723 1,
724 arp->fd) != 1) ||
725 !IS_EQUALN(arp->ar_port.ar_fmag,
726 AR_PORT_END_MAGIC,
727 sizeof arp->ar_port.ar_fmag)) {
728 goto read_error;
729 }
730 if (sscanf(arp->ar_port.ar_date,
731 "%ld",
732 &date) != 1) {
733 fatal(catgets(catd, 1, 9, "Bad date field for member `%s' in archive `%s'"),
734 arp->ar_port.ar_name,
735 target->string_mb);
736 }
737 /* If it's a long name, retrieve it from long name table */
738 if (arp->ar_port.ar_name[0] == '/') {
739 sscanf(arp->ar_port.ar_name + 1,
740 "%ld",
741 &offset);
742 len = ar_member_name_len;
743 hp = *long_names_table + offset;
744 } else {
745 len = sizeof arp->ar_port.ar_name;
746 hp = arp->ar_port.ar_name;
747 }
748 ap = member_string;
749 while (*hp &&
750 (*hp != (int) slash_char) &&
751 (ap < &member_string[len])) {
752 MBTOWC(ap, hp);
753 ap++;
754 hp++;
755 }
756 *ap = (int) nul_char;
757 member->body.member.member =
758 GETNAME(member_string, FIND_LENGTH);
759 target->stat.time.tv_sec = date;
760 target->stat.time.tv_nsec = LONG_MAX;
761 return;
762 }
763 offs++;
764 while(*syms!='\0') syms++;
765 syms++;
766 }
767 }
|