Print this page
make: translate using gettext, rather than the unmaintainable catgets


  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