26 /*
27 * ar.c
28 *
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 <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 #include <unistd.h> /* close() */
58
59
60 /*
61 * Defined macros
62 */
63 #ifndef S5EMUL
64 #undef BITSPERBYTE
65 #define BITSPERBYTE 8
206 append_char((int) parenleft_char, &true_member_name);
207 append_string(slash + 1, &true_member_name, FIND_LENGTH);
208 append_char((int) parenright_char, &true_member_name);
209 true_member = GETNAME(true_member_name.buffer.start,
210 FIND_LENGTH);
211 if (true_member->stat.time != file_no_time) {
212 target->stat.time = true_member->stat.time;
213 return target->stat.time;
214 }
215 }
216 }
217 if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
218 if (errno == ENOENT) {
219 target->stat.stat_errno = ENOENT;
220 close_archive(&ar);
221 if (member->body.member.member == NULL) {
222 member->body.member.member = empty_name;
223 }
224 return target->stat.time = file_doesnt_exist;
225 } else {
226 fatal(catgets(catd, 1, 1, "Can't access archive `%s': %s"),
227 member->body.member.library->string_mb,
228 errmsg(errno));
229 }
230 }
231 if (target->stat.time == file_no_time) {
232 if (read_archive_dir(&ar, member->body.member.library,
233 &long_names_table)
234 == failed){
235 fatal(catgets(catd, 1, 2, "Can't access archive `%s': %s"),
236 member->body.member.library->string_mb,
237 errmsg(errno));
238 }
239 }
240 if (member->body.member.entry != NULL) {
241 translate_entry(&ar, target, member,&long_names_table);
242 }
243 close_archive(&ar);
244 if (long_names_table) {
245 retmem_mb(long_names_table);
246 }
247 if (true_member != NULL) {
248 target->stat.time = true_member->stat.time;
249 }
250 if (target->stat.time == file_no_time) {
251 target->stat.time = file_doesnt_exist;
252 }
253 return target->stat.time;
254 }
255
299 arp->first_ar_mem = ftell(arp->fd);
300 return succeeded;
301 }
302 /*
303 * The following values are the default if there is
304 * no symbol directory and long member names.
305 */
306 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
307 arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
308
309 /*
310 * Do we have a symbol table? A symbol table is always
311 * the first member in an archive. In 4.1.x it has the
312 * name __.SYMDEF, in SVr4, it has the name "/ "
313 */
314 /*
315 MBSTOWCS(wcs_buffer, "/ ");
316 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
317 */
318 if (IS_EQUALN(arp->ar_port.ar_name,
319 NOCATGETS("/ "),
320 16)) {
321 if (sscanf(arp->ar_port.ar_size,
322 "%ld",
323 &arp->sym_size) != 1) {
324 return failed;
325 }
326 arp->sym_size += (arp->sym_size & 1); /* round up */
327 if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
328 return failed;
329 }
330 arp->num_symbols = sgetl(buffer);
331 arp->sym_begin = ftell(arp->fd);
332 arp->first_ar_mem = arp->sym_begin +
333 arp->sym_size - sizeof buffer;
334 }
335 return succeeded;
336 }
337 fatal(catgets(catd, 1, 3, "`%s' is not an archive"), filename);
338 /* NOTREACHED */
339 return failed;
340 }
341
342
343 /*
344 * close_archive(arp)
345 *
346 * Parameters:
347 * arp Pointer to ar file description block
348 *
349 * Global variables used:
350 */
351 static void
352 close_archive(register Ar *arp)
353 {
354 if (arp->fd != NULL) {
355 (void) fclose(arp->fd);
356 }
357 }
447 ptr = sgetl(arp->arf_5.arf_size);
448 ptr += (ptr & 1);
449 if (fseek(arp->fd, ptr, 1) != 0) {
450 goto read_error;
451 }
452 }
453 break;
454 case AR_PORT:
455 for (;;) {
456 if ((fread((char *) &arp->ar_port,
457 sizeof arp->ar_port,
458 1,
459 arp->fd) != 1) ||
460 !IS_EQUALN(arp->ar_port.ar_fmag,
461 AR_PORT_END_MAGIC,
462 sizeof arp->ar_port.ar_fmag)) {
463 if (feof(arp->fd)) {
464 return succeeded;
465 }
466 fatal(
467 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
468 library->string_mb,
469 ftell(arp->fd)
470 );
471 }
472 /* If it's a long name, retrieve it from long name table */
473 if (arp->ar_port.ar_name[0] == '/') {
474 /*
475 * "len" is used for hashing the string.
476 * We're using "ar_member_name_len" instead of
477 * the actual name length since it's the longest
478 * string the "ar" command can handle at this
479 * point.
480 */
481 len = ar_member_name_len;
482 sscanf(arp->ar_port.ar_name + 1,
483 "%ld",
484 &offset);
485 q = *long_names_table + offset;
486 } else {
487 q = arp->ar_port.ar_name;
494 !isspace(*q) &&
495 (*q != (int) slash_char);
496 ) {
497 MBTOWC(p, q);
498 p++;
499 q++;
500 }
501 *p++ = (int) parenright_char;
502 *p = (int) nul_char;
503 name = GETNAME(name_string, FIND_LENGTH);
504 name->is_member = library->is_member;
505 member = maybe_append_prop(name, member_prop);
506 member->body.member.library = library;
507 *--p = (int) nul_char;
508 if (member->body.member.member == NULL) {
509 member->body.member.member =
510 GETNAME(member_string, FIND_LENGTH);
511 }
512 if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
513 WCSTOMBS(mbs_buffer, name_string);
514 fatal(catgets(catd, 1, 4, "Bad date field for member `%s' in archive `%s'"),
515 mbs_buffer,
516 library->string_mb);
517 }
518 /*
519 * [tolik] Fix for dmake bug 1234018.
520 */
521 if(name->stat.time == file_no_time) {
522 name->stat.time.tv_sec = date;
523 name->stat.time.tv_nsec = LONG_MAX;
524 }
525 if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
526 WCSTOMBS(mbs_buffer, name_string);
527 fatal(catgets(catd, 1, 5, "Bad size field for member `%s' in archive `%s'"),
528 mbs_buffer,
529 library->string_mb);
530 }
531 ptr += (ptr & 1);
532 if (fseek(arp->fd, ptr, 1) != 0) {
533 goto read_error;
534 }
535 }
536 break;
537 }
538
539 /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
540 read_error:
541 fatal(catgets(catd, 1, 6, "Read error in archive `%s': %s"),
542 library->string_mb,
543 errmsg(errno));
544 /* NOTREACHED */
545 }
546
547
548 /*
549 * process_long_names_member(arp)
550 *
551 * If the archive contains members with names longer
552 * than 15 characters, then it has a special member
553 * with the name "// " that contains a table
554 * of null-terminated long names. This member
555 * is always the first member, after the symbol table
556 * if it exists.
557 *
558 * Parameters:
559 * arp Pointer to ar file description block
560 *
561 * Global variables used:
562 */
563 int
564 process_long_names_member(register Ar *arp, char **long_names_table, char *filename)
565 {
566 Ar_port *ar_member_header;
567 int table_size;
568
569 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
570 return failed;
571 }
572 if ((ar_member_header =
573 (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
574 perror(catgets(catd, 1, 7, "memory allocation failure"));
575 return failed;
576 }
577 int ret = read_member_header(ar_member_header, arp->fd, filename);
578 if (ret == failed) {
579 return failed;
580 } else if(ret == -1) {
581 /* There is no member header - empty archive */
582 return succeeded;
583 }
584 /* Do we have special member containing long names? */
585 if (IS_EQUALN(ar_member_header->ar_name,
586 NOCATGETS("// "),
587 16)){
588 if (sscanf(ar_member_header->ar_size,
589 "%ld",
590 &table_size) != 1) {
591 return failed;
592 }
593 *long_names_table = (char *) malloc(table_size);
594 /* Read the list of long member names into the table */
595 if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
596 return failed;
597 }
598 arp->first_ar_mem = ftell(arp->fd);
599 }
600 return succeeded;
601 }
602
603 /*
604 * translate_entry(arp, target, member)
605 *
606 * Finds the member for one lib.a((entry))
614 */
615 static void
616 translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table)
617 {
618 register int len;
619 register int i;
620 wchar_t *member_string;
621 ar_port_word *offs;
622 int strtablen;
623 char *syms; /* string table */
624 char *csym; /* string table */
625 ar_port_word *offend; /* end of offsets table */
626 int date;
627 register wchar_t *ap;
628 register char *hp;
629 int maxs;
630 int offset;
631 char buffer[4];
632
633 if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
634 fatal(catgets(catd, 1, 8, "Cannot find symbol `%s' in archive `%s'"),
635 member->body.member.entry->string_mb,
636 member->body.member.library->string_mb);
637 }
638
639 if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
640 goto read_error;
641 }
642 member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
643
644 switch (arp->type) {
645 case AR_5:
646 if ((len = member->body.member.entry->hash.length) > 8) {
647 len = 8;
648 }
649 for (i = 0; i < arp->num_symbols; i++) {
650 if (fread((char *) &arp->ars_5,
651 sizeof arp->ars_5,
652 1,
653 arp->fd) != 1) {
654 goto read_error;
709 if (IS_EQUALN(syms,
710 member->body.member.entry->string_mb,
711 maxs)) {
712 if (fseek(arp->fd,
713 (long) *offs,
714 0) != 0) {
715 goto read_error;
716 }
717 if ((fread((char *) &arp->ar_port,
718 sizeof arp->ar_port,
719 1,
720 arp->fd) != 1) ||
721 !IS_EQUALN(arp->ar_port.ar_fmag,
722 AR_PORT_END_MAGIC,
723 sizeof arp->ar_port.ar_fmag)) {
724 goto read_error;
725 }
726 if (sscanf(arp->ar_port.ar_date,
727 "%ld",
728 &date) != 1) {
729 fatal(catgets(catd, 1, 9, "Bad date field for member `%s' in archive `%s'"),
730 arp->ar_port.ar_name,
731 target->string_mb);
732 }
733 /* If it's a long name, retrieve it from long name table */
734 if (arp->ar_port.ar_name[0] == '/') {
735 sscanf(arp->ar_port.ar_name + 1,
736 "%ld",
737 &offset);
738 len = ar_member_name_len;
739 hp = *long_names_table + offset;
740 } else {
741 len = sizeof arp->ar_port.ar_name;
742 hp = arp->ar_port.ar_name;
743 }
744 ap = member_string;
745 while (*hp &&
746 (*hp != (int) slash_char) &&
747 (ap < &member_string[len])) {
748 MBTOWC(ap, hp);
749 ap++;
750 hp++;
751 }
752 *ap = (int) nul_char;
753 member->body.member.member =
754 GETNAME(member_string, FIND_LENGTH);
755 target->stat.time.tv_sec = date;
756 target->stat.time.tv_nsec = LONG_MAX;
757 return;
758 }
759 offs++;
760 while(*syms!='\0') syms++;
761 syms++;
762 }
763 }
764 fatal(catgets(catd, 1, 10, "Cannot find symbol `%s' in archive `%s'"),
765 member->body.member.entry->string_mb,
766 member->body.member.library->string_mb);
767 /*NOTREACHED*/
768
769 read_error:
770 if (ferror(arp->fd)) {
771 fatal(catgets(catd, 1, 11, "Read error in archive `%s': %s"),
772 member->body.member.library->string_mb,
773 errmsg(errno));
774 } else {
775 fatal(catgets(catd, 1, 12, "Read error in archive `%s': Premature EOF"),
776 member->body.member.library->string_mb);
777 }
778 }
779
780 /*
781 * sgetl(buffer)
782 *
783 * The intent here is to provide a means to make the value of
784 * bytes in an io-buffer correspond to the value of a long
785 * in the memory while doing the io a long at a time.
786 * Files written and read in this way are machine-independent.
787 *
788 * Return value:
789 * Long int read from buffer
790 * Parameters:
791 * buffer buffer we need to read long int from
792 *
793 * Global variables used:
794 */
795 static long
818 * fd file descriptor for the archive file.
819 *
820 * Global variables used:
821 */
822 int
823 read_member_header(Ar_port *header, FILE *fd, char* filename)
824 {
825 int num = fread((char *) header, sizeof (Ar_port), 1, fd);
826 if (num != 1 && feof(fd)) {
827 /* There is no member header - empty archive */
828 return -1;
829 }
830 if ((num != 1) ||
831 !IS_EQUALN(
832 AR_PORT_END_MAGIC,
833 header->ar_fmag,
834 sizeof (header->ar_fmag)
835 )
836 ) {
837 fatal(
838 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
839 filename,
840 ftell(fd)
841 );
842 }
843 return succeeded;
844 }
845
|
26 /*
27 * ar.c
28 *
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 <alloca.h> /* alloca() */
43 #include <ar.h>
44 #include <errno.h> /* errno */
45 #include <fcntl.h> /* open() */
46 #include <libintl.h>
47 #include <mk/defs.h>
48 #include <mksh/misc.h> /* retmem_mb() */
49
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
58 #include <unistd.h> /* close() */
59
60
61 /*
62 * Defined macros
63 */
64 #ifndef S5EMUL
65 #undef BITSPERBYTE
66 #define BITSPERBYTE 8
207 append_char((int) parenleft_char, &true_member_name);
208 append_string(slash + 1, &true_member_name, FIND_LENGTH);
209 append_char((int) parenright_char, &true_member_name);
210 true_member = GETNAME(true_member_name.buffer.start,
211 FIND_LENGTH);
212 if (true_member->stat.time != file_no_time) {
213 target->stat.time = true_member->stat.time;
214 return target->stat.time;
215 }
216 }
217 }
218 if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
219 if (errno == ENOENT) {
220 target->stat.stat_errno = ENOENT;
221 close_archive(&ar);
222 if (member->body.member.member == NULL) {
223 member->body.member.member = empty_name;
224 }
225 return target->stat.time = file_doesnt_exist;
226 } else {
227 fatal(gettext("Can't access archive `%s': %s"),
228 member->body.member.library->string_mb,
229 errmsg(errno));
230 }
231 }
232 if (target->stat.time == file_no_time) {
233 if (read_archive_dir(&ar, member->body.member.library,
234 &long_names_table)
235 == failed){
236 fatal(gettext("Can't access archive `%s': %s"),
237 member->body.member.library->string_mb,
238 errmsg(errno));
239 }
240 }
241 if (member->body.member.entry != NULL) {
242 translate_entry(&ar, target, member,&long_names_table);
243 }
244 close_archive(&ar);
245 if (long_names_table) {
246 retmem_mb(long_names_table);
247 }
248 if (true_member != NULL) {
249 target->stat.time = true_member->stat.time;
250 }
251 if (target->stat.time == file_no_time) {
252 target->stat.time = file_doesnt_exist;
253 }
254 return target->stat.time;
255 }
256
300 arp->first_ar_mem = ftell(arp->fd);
301 return succeeded;
302 }
303 /*
304 * The following values are the default if there is
305 * no symbol directory and long member names.
306 */
307 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
308 arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
309
310 /*
311 * Do we have a symbol table? A symbol table is always
312 * the first member in an archive. In 4.1.x it has the
313 * name __.SYMDEF, in SVr4, it has the name "/ "
314 */
315 /*
316 MBSTOWCS(wcs_buffer, "/ ");
317 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
318 */
319 if (IS_EQUALN(arp->ar_port.ar_name,
320 "/ ",
321 16)) {
322 if (sscanf(arp->ar_port.ar_size,
323 "%ld",
324 &arp->sym_size) != 1) {
325 return failed;
326 }
327 arp->sym_size += (arp->sym_size & 1); /* round up */
328 if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
329 return failed;
330 }
331 arp->num_symbols = sgetl(buffer);
332 arp->sym_begin = ftell(arp->fd);
333 arp->first_ar_mem = arp->sym_begin +
334 arp->sym_size - sizeof buffer;
335 }
336 return succeeded;
337 }
338 fatal(gettext("`%s' is not an archive"), filename);
339 /* NOTREACHED */
340 return failed;
341 }
342
343
344 /*
345 * close_archive(arp)
346 *
347 * Parameters:
348 * arp Pointer to ar file description block
349 *
350 * Global variables used:
351 */
352 static void
353 close_archive(register Ar *arp)
354 {
355 if (arp->fd != NULL) {
356 (void) fclose(arp->fd);
357 }
358 }
448 ptr = sgetl(arp->arf_5.arf_size);
449 ptr += (ptr & 1);
450 if (fseek(arp->fd, ptr, 1) != 0) {
451 goto read_error;
452 }
453 }
454 break;
455 case AR_PORT:
456 for (;;) {
457 if ((fread((char *) &arp->ar_port,
458 sizeof arp->ar_port,
459 1,
460 arp->fd) != 1) ||
461 !IS_EQUALN(arp->ar_port.ar_fmag,
462 AR_PORT_END_MAGIC,
463 sizeof arp->ar_port.ar_fmag)) {
464 if (feof(arp->fd)) {
465 return succeeded;
466 }
467 fatal(
468 gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
469 library->string_mb,
470 ftell(arp->fd)
471 );
472 }
473 /* If it's a long name, retrieve it from long name table */
474 if (arp->ar_port.ar_name[0] == '/') {
475 /*
476 * "len" is used for hashing the string.
477 * We're using "ar_member_name_len" instead of
478 * the actual name length since it's the longest
479 * string the "ar" command can handle at this
480 * point.
481 */
482 len = ar_member_name_len;
483 sscanf(arp->ar_port.ar_name + 1,
484 "%ld",
485 &offset);
486 q = *long_names_table + offset;
487 } else {
488 q = arp->ar_port.ar_name;
495 !isspace(*q) &&
496 (*q != (int) slash_char);
497 ) {
498 MBTOWC(p, q);
499 p++;
500 q++;
501 }
502 *p++ = (int) parenright_char;
503 *p = (int) nul_char;
504 name = GETNAME(name_string, FIND_LENGTH);
505 name->is_member = library->is_member;
506 member = maybe_append_prop(name, member_prop);
507 member->body.member.library = library;
508 *--p = (int) nul_char;
509 if (member->body.member.member == NULL) {
510 member->body.member.member =
511 GETNAME(member_string, FIND_LENGTH);
512 }
513 if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
514 WCSTOMBS(mbs_buffer, name_string);
515 fatal(gettext("Bad date field for member `%s' in archive `%s'"),
516 mbs_buffer,
517 library->string_mb);
518 }
519 /*
520 * [tolik] Fix for dmake bug 1234018.
521 */
522 if(name->stat.time == file_no_time) {
523 name->stat.time.tv_sec = date;
524 name->stat.time.tv_nsec = LONG_MAX;
525 }
526 if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
527 WCSTOMBS(mbs_buffer, name_string);
528 fatal(gettext("Bad size field for member `%s' in archive `%s'"),
529 mbs_buffer,
530 library->string_mb);
531 }
532 ptr += (ptr & 1);
533 if (fseek(arp->fd, ptr, 1) != 0) {
534 goto read_error;
535 }
536 }
537 break;
538 }
539
540 /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
541 read_error:
542 fatal(gettext("Read error in archive `%s': %s"),
543 library->string_mb,
544 errmsg(errno));
545 /* NOTREACHED */
546 }
547
548
549 /*
550 * process_long_names_member(arp)
551 *
552 * If the archive contains members with names longer
553 * than 15 characters, then it has a special member
554 * with the name "// " that contains a table
555 * of null-terminated long names. This member
556 * is always the first member, after the symbol table
557 * if it exists.
558 *
559 * Parameters:
560 * arp Pointer to ar file description block
561 *
562 * Global variables used:
563 */
564 int
565 process_long_names_member(register Ar *arp, char **long_names_table, char *filename)
566 {
567 Ar_port *ar_member_header;
568 int table_size;
569
570 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
571 return failed;
572 }
573 if ((ar_member_header =
574 (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
575 perror(gettext("memory allocation failure"));
576 return failed;
577 }
578 int ret = read_member_header(ar_member_header, arp->fd, filename);
579 if (ret == failed) {
580 return failed;
581 } else if(ret == -1) {
582 /* There is no member header - empty archive */
583 return succeeded;
584 }
585 /* Do we have special member containing long names? */
586 if (IS_EQUALN(ar_member_header->ar_name,
587 "// ",
588 16)){
589 if (sscanf(ar_member_header->ar_size,
590 "%ld",
591 &table_size) != 1) {
592 return failed;
593 }
594 *long_names_table = (char *) malloc(table_size);
595 /* Read the list of long member names into the table */
596 if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
597 return failed;
598 }
599 arp->first_ar_mem = ftell(arp->fd);
600 }
601 return succeeded;
602 }
603
604 /*
605 * translate_entry(arp, target, member)
606 *
607 * Finds the member for one lib.a((entry))
615 */
616 static void
617 translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table)
618 {
619 register int len;
620 register int i;
621 wchar_t *member_string;
622 ar_port_word *offs;
623 int strtablen;
624 char *syms; /* string table */
625 char *csym; /* string table */
626 ar_port_word *offend; /* end of offsets table */
627 int date;
628 register wchar_t *ap;
629 register char *hp;
630 int maxs;
631 int offset;
632 char buffer[4];
633
634 if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
635 fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
636 member->body.member.entry->string_mb,
637 member->body.member.library->string_mb);
638 }
639
640 if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
641 goto read_error;
642 }
643 member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
644
645 switch (arp->type) {
646 case AR_5:
647 if ((len = member->body.member.entry->hash.length) > 8) {
648 len = 8;
649 }
650 for (i = 0; i < arp->num_symbols; i++) {
651 if (fread((char *) &arp->ars_5,
652 sizeof arp->ars_5,
653 1,
654 arp->fd) != 1) {
655 goto read_error;
710 if (IS_EQUALN(syms,
711 member->body.member.entry->string_mb,
712 maxs)) {
713 if (fseek(arp->fd,
714 (long) *offs,
715 0) != 0) {
716 goto read_error;
717 }
718 if ((fread((char *) &arp->ar_port,
719 sizeof arp->ar_port,
720 1,
721 arp->fd) != 1) ||
722 !IS_EQUALN(arp->ar_port.ar_fmag,
723 AR_PORT_END_MAGIC,
724 sizeof arp->ar_port.ar_fmag)) {
725 goto read_error;
726 }
727 if (sscanf(arp->ar_port.ar_date,
728 "%ld",
729 &date) != 1) {
730 fatal(gettext("Bad date field for member `%s' in archive `%s'"),
731 arp->ar_port.ar_name,
732 target->string_mb);
733 }
734 /* If it's a long name, retrieve it from long name table */
735 if (arp->ar_port.ar_name[0] == '/') {
736 sscanf(arp->ar_port.ar_name + 1,
737 "%ld",
738 &offset);
739 len = ar_member_name_len;
740 hp = *long_names_table + offset;
741 } else {
742 len = sizeof arp->ar_port.ar_name;
743 hp = arp->ar_port.ar_name;
744 }
745 ap = member_string;
746 while (*hp &&
747 (*hp != (int) slash_char) &&
748 (ap < &member_string[len])) {
749 MBTOWC(ap, hp);
750 ap++;
751 hp++;
752 }
753 *ap = (int) nul_char;
754 member->body.member.member =
755 GETNAME(member_string, FIND_LENGTH);
756 target->stat.time.tv_sec = date;
757 target->stat.time.tv_nsec = LONG_MAX;
758 return;
759 }
760 offs++;
761 while(*syms!='\0') syms++;
762 syms++;
763 }
764 }
765 fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
766 member->body.member.entry->string_mb,
767 member->body.member.library->string_mb);
768 /*NOTREACHED*/
769
770 read_error:
771 if (ferror(arp->fd)) {
772 fatal(gettext("Read error in archive `%s': %s"),
773 member->body.member.library->string_mb,
774 errmsg(errno));
775 } else {
776 fatal(gettext("Read error in archive `%s': Premature EOF"),
777 member->body.member.library->string_mb);
778 }
779 }
780
781 /*
782 * sgetl(buffer)
783 *
784 * The intent here is to provide a means to make the value of
785 * bytes in an io-buffer correspond to the value of a long
786 * in the memory while doing the io a long at a time.
787 * Files written and read in this way are machine-independent.
788 *
789 * Return value:
790 * Long int read from buffer
791 * Parameters:
792 * buffer buffer we need to read long int from
793 *
794 * Global variables used:
795 */
796 static long
819 * fd file descriptor for the archive file.
820 *
821 * Global variables used:
822 */
823 int
824 read_member_header(Ar_port *header, FILE *fd, char* filename)
825 {
826 int num = fread((char *) header, sizeof (Ar_port), 1, fd);
827 if (num != 1 && feof(fd)) {
828 /* There is no member header - empty archive */
829 return -1;
830 }
831 if ((num != 1) ||
832 !IS_EQUALN(
833 AR_PORT_END_MAGIC,
834 header->ar_fmag,
835 sizeof (header->ar_fmag)
836 )
837 ) {
838 fatal(
839 gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
840 filename,
841 ftell(fd)
842 );
843 }
844 return succeeded;
845 }
846
|