1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  *      Copyright (c) 1988 AT&T
  28  *        All Rights Reserved
  29  *
  30  */
  31 
  32 #include <sys/sendfile.h>
  33 #include "inc.h"
  34 #include "gelf.h"
  35 
  36 /*
  37  * List of archive members, accessed globally by cmd and file.
  38  */
  39 ARFILE  *listhead, *listend;
  40 
  41 /*
  42  * Type used to manage string tables. Archives can have two of these:
  43  *
  44  * sym_strtbl: String table included at the end of the symbol table
  45  *      archive member, following the offset array.
  46  *
  47  * long_strtbl: String table used to hold member names that exceed 15
  48  *      characters in length, found in the long names archive member.
  49  */
  50 typedef struct {
  51         char    *base;          /* Base of string table memory */
  52         size_t  used;           /* # bytes used from allocation */
  53         size_t  size;           /* Size of allocation */
  54 } ARSTRTBL;
  55 
  56 static ARSTRTBL sym_strtbl;
  57 static ARSTRTBL long_strtbl;
  58 
  59 
  60 /*
  61  * Name and file descriptor used when creating a new archive.
  62  * If this variable references an open file when exit_cleanup()
  63  * executes, it will close and remove the file, preventing incomplete
  64  * temporary files from being left behind in the case of a failure
  65  * or interruption.
  66  */
  67 static struct {
  68         int             fd;     /* -1, or open file descriptor */
  69         const char      *path;  /* Path to open file */
  70 } ar_outfile;
  71 
  72 /*
  73  * The ar file format requires objects to be padded to an even size.
  74  * We do that, but it turns out to be beneficial to go farther.
  75  *
  76  * ld(1) accesses archives by mmapping them into memory. If the mapped
  77  * objects (member data) have the proper alignment, we can access them
  78  * directly. If the data alignment is wrong, libelf "slides" them over the
  79  * archive header to correct the misalignment. This is expensive in time
  80  * (to copy memory) and space (it causes swap to be allocated by the system
  81  * to back the now-modified pages). Hence, we really want to ensure that
  82  * the alignment is right.
  83  *
  84  * We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects
  85  * at 8-byte. More recently, an elf section type has appeared that has
  86  * 8-byte alignment requirements (SUNW_move) even in 32-bit objects. So,
  87  * the current strategy is to align all objects to 8-bytes.
  88  *
  89  * There are two important things to consider when setting this value:
  90  *      1) If a new elf section that ld(1) accesses in memory appears
  91  *         with a greater than 8-byte alignment requirement, this value
  92  *         will need to be raised. Or, alternatively, the entire approach may
  93  *         need reconsideration.
  94  *      2) The size of this padding must be smaller than the size of the
  95  *         smallest possible ELF section. Otherwise, the logic contained
  96  *         in recover_padding() can be tricked.
  97  */
  98 #define PADSZ 8
  99 
 100 /*
 101  * Forward Declarations
 102  */
 103 static void             arwrite(const char *, int, const char *, size_t);
 104 static size_t           mklong_tab();
 105 static size_t           mksymtab(const char *, ARFILEP **, int *);
 106 static const char       *make_tmpname(const char *);
 107 static size_t           sizeof_symtbl(size_t, int, size_t);
 108 static void             savelongname(ARFILE *);
 109 static void             savename(char *);
 110 static int              search_sym_tab(const char *, ARFILE *, Elf *,
 111                             Elf_Scn *, size_t *, ARFILEP **, size_t *);
 112 static size_t           sizeofmembers(size_t);
 113 static char             *sputl32(uint32_t, char *);
 114 static char             *sputl64(uint64_t, char *);
 115 static void             strtbl_pad(ARSTRTBL *, size_t, int);
 116 static char             *trimslash(char *s);
 117 static void             writesymtab(const char *, int fd, size_t, ARFILEP *,
 118                             size_t);
 119 
 120 
 121 /*
 122  * Function to be called on exit to clean up incomplete new archive.
 123  */
 124 static void
 125 exit_cleanup(void)
 126 {
 127         if (ar_outfile.fd != -1) {
 128                 /* Both of these system calls are Async-Signal-Safe */
 129                 (void)  close(ar_outfile.fd);
 130                 (void) unlink(ar_outfile.path);
 131         }
 132 }
 133 
 134 /*
 135  * Open an existing archive.
 136  */
 137 int
 138 getaf(Cmd_info *cmd_info)
 139 {
 140         Elf_Cmd cmd;
 141         int fd;
 142         char *arnam = cmd_info->arnam;
 143 
 144         if (elf_version(EV_CURRENT) == EV_NONE) {
 145                 (void) fprintf(stderr, MSG_INTL(MSG_ELF_VERSION),
 146                     elf_errmsg(-1));
 147                 exit(1);
 148         }
 149 
 150         if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) {
 151                 int err = errno;
 152 
 153                 if (err == ENOENT) {
 154                         /* archive does not exist yet, may have to create one */
 155                         return (fd);
 156                 } else {
 157                         /* problem other than "does not exist" */
 158                         (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
 159                             arnam, strerror(err));
 160                         exit(1);
 161                 }
 162         }
 163 
 164         cmd = ELF_C_READ;
 165         cmd_info->arf = elf_begin(fd, cmd, (Elf *)0);
 166 
 167         if (elf_kind(cmd_info->arf) != ELF_K_AR) {
 168                 (void) fprintf(stderr, MSG_INTL(MSG_NOT_ARCHIVE), arnam);
 169                 if (cmd_info->opt_flgs & (a_FLAG | b_FLAG))
 170                         (void) fprintf(stderr, MSG_INTL(MSG_USAGE_06),
 171                             cmd_info->ponam);
 172                 exit(1);
 173         }
 174         return (fd);
 175 }
 176 
 177 /*
 178  * Given a value, and a pad alignment, return the number of bytes
 179  * required to pad the value to the next alignment boundary.
 180  */
 181 static size_t
 182 pad(size_t n, size_t align)
 183 {
 184         size_t r;
 185 
 186         r = n % align;
 187         if (r)
 188                 r = align - r;
 189 
 190         return (r);
 191 }
 192 
 193 /*
 194  * If the current archive item is an ELF object, then ar(1) may have added
 195  * newline padding at the end in order to bring the following object
 196  * into PADSZ alignment within the file. This padding cannot be
 197  * distinguished from data using the information kept in the member header.
 198  * This routine examines the objects, using knowledge of
 199  * ELF and how our tools lay out objects to determine whether padding was
 200  * added to an archive item. If so, it adjusts the st_size and
 201  * st_padding fields of the file argument to reflect it.
 202  */
 203 static void
 204 recover_padding(Elf *elf, ARFILE *file)
 205 {
 206         size_t          extent;
 207         size_t          padding;
 208         GElf_Ehdr       ehdr;
 209 
 210 
 211         /* ar(1) only pads objects, so bail if not looking at one */
 212         if (gelf_getclass(elf) == ELFCLASSNONE)
 213                 return;
 214 
 215         /*
 216          * libelf always puts the section header array at the end
 217          * of the object, and all of our compilers and other tools
 218          * use libelf or follow this convention. So, it is extremely
 219          * likely that the section header array is at the end of this
 220          * object: Find the address at the end of the array and compare
 221          * it to the archive ar_size. If they are within PADSZ bytes, then
 222          * we've found the end, and the difference is padding (We assume
 223          * that no ELF section can fit into PADSZ bytes).
 224          */
 225         extent = gelf_getehdr(elf, &ehdr)
 226             ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0;
 227 
 228         /*
 229          * If the extent exceeds the end of the archive member
 230          * (negative padding), then we don't know what is going on
 231          * and simply leave things alone.
 232          */
 233         if (extent > file->ar_size)
 234                 return;
 235 
 236         padding = file->ar_size - extent;
 237         if (padding >= PADSZ) {
 238                 /*
 239                  * The section header array is not at the end of the object.
 240                  * Traverse the section headers and look for the one with
 241                  * the highest used address. If this address is within
 242                  * PADSZ bytes of ar_size, then this is the end of the object.
 243                  */
 244                 Elf_Scn *scn = NULL;
 245 
 246                 do {
 247                         scn = elf_nextscn(elf, scn);
 248                         if (scn) {
 249                                 GElf_Shdr shdr;
 250 
 251                                 if (gelf_getshdr(scn, &shdr)) {
 252                                         size_t t;
 253 
 254                                         t = shdr.sh_offset + shdr.sh_size;
 255                                         if (t > extent)
 256                                                 extent = t;
 257                                 }
 258                         }
 259                 } while (scn);
 260 
 261                 if (extent > file->ar_size)
 262                         return;
 263                 padding = file->ar_size - extent;
 264         }
 265 
 266         /*
 267          * Now, test the padding. We only act on padding in the range
 268          * (0 < pad < PADSZ) (ar(1) will never add more than this). A pad
 269          * of 0 requires no action, and any other size above (PADSZ-1) means
 270          * that we don't understand the layout of this object, and as such,
 271          * cannot do anything.
 272          *
 273          * If the padding is in range, and the raw data for the
 274          * object is available, then we perform one additional sanity
 275          * check before moving forward: ar(1) always pads with newline
 276          * characters. If anything else is seen, it is not padding so
 277          * leave it alone.
 278          */
 279         if (padding < PADSZ) {
 280                 if (file->ar_contents) {
 281                         size_t cnt = padding;
 282                         char *p = file->ar_contents + extent;
 283 
 284                         while (cnt--) {
 285                                 if (*p++ != '\n') {   /* No padding */
 286                                         padding = 0;
 287                                         break;
 288                                 }
 289                         }
 290                 }
 291 
 292                 /* Remove the padding from the size */
 293                 file->ar_size -= padding;
 294                 file->ar_padding = padding;
 295         }
 296 }
 297 
 298 /*
 299  * Each call to getfile() returns the next unread archive member
 300  * from the archive opened by getaf(). Returns NULL if no more
 301  * archive members are left.
 302  */
 303 ARFILE *
 304 getfile(Cmd_info *cmd_info)
 305 {
 306         Elf_Arhdr *mem_header = NULL;
 307         ARFILE  *file;
 308         char *tmp_rawname, *file_rawname;
 309         Elf *elf;
 310         char *arnam = cmd_info->arnam;
 311         int fd = cmd_info->afd;
 312         Elf *arf = cmd_info->arf;
 313 
 314         if (fd == -1)
 315                 return (NULL); /* the archive doesn't exist */
 316 
 317         while (mem_header == NULL) {
 318                 if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0)
 319                         return (NULL);  /* archive is empty or have hit end */
 320 
 321                 if ((mem_header = elf_getarhdr(elf)) == NULL) {
 322                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_MALARCHIVE),
 323                             arnam, EC_XWORD(elf_getbase(elf)), elf_errmsg(-1));
 324                         exit(1);
 325                 }
 326 
 327                 /* Ignore special members like the symbol and string tables */
 328                 if (mem_header->ar_name[0] == '/') {
 329                         (void) elf_next(elf);
 330                         (void) elf_end(elf);
 331                         mem_header = NULL;
 332                 }
 333         }
 334 
 335         /*
 336          * NOTE:
 337          *      The mem_header->ar_name[] is set to a NULL string
 338          *      if the archive member header has some error.
 339          *      (See elf_getarhdr() man page.)
 340          *      It is set to NULL for example, the ar command reads
 341          *      the archive files created by SunOS 4.1 system.
 342          *      See c block comment in cmd.c, "Incompatible Archive Header".
 343          */
 344         file = newfile();
 345         (void) strncpy(file->ar_name, mem_header->ar_name, SNAME);
 346 
 347         if ((file->ar_longname = malloc(strlen(mem_header->ar_name) + 1))
 348             == NULL) {
 349                 int err = errno;
 350                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
 351                 exit(1);
 352         }
 353         (void) strcpy(file->ar_longname, mem_header->ar_name);
 354         if ((file->ar_rawname = malloc(strlen(mem_header->ar_rawname) + 1))
 355             == NULL) {
 356                 int err = errno;
 357                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
 358                 exit(1);
 359         }
 360         tmp_rawname = mem_header->ar_rawname;
 361         file_rawname = file->ar_rawname;
 362         while (!isspace(*tmp_rawname) &&
 363             ((*file_rawname = *tmp_rawname) != '\0')) {
 364                 file_rawname++;
 365                 tmp_rawname++;
 366         }
 367         if (!(*tmp_rawname == '\0'))
 368                 *file_rawname = '\0';
 369 
 370         file->ar_date = mem_header->ar_date;
 371         file->ar_uid  = mem_header->ar_uid;
 372         file->ar_gid  = mem_header->ar_gid;
 373         file->ar_mode = (unsigned long) mem_header->ar_mode;
 374         file->ar_size = mem_header->ar_size;
 375 
 376         /* reverse logic */
 377         if ((cmd_info->opt_flgs & (t_FLAG | s_FLAG)) != t_FLAG) {
 378                 size_t ptr;
 379                 file->ar_flag = F_ELFRAW;
 380                 if ((file->ar_contents = elf_rawfile(elf, &ptr))
 381                     == NULL) {
 382                         if (ptr != 0) {
 383                                 (void) fprintf(stderr,
 384                                     MSG_INTL(MSG_ELF_RAWFILE), elf_errmsg(-1));
 385                                 exit(1);
 386                         }
 387                 }
 388                 file->ar_elf = elf;
 389         }
 390 
 391         recover_padding(elf, file);
 392 
 393         (void) elf_next(elf);
 394         return (file);
 395 }
 396 
 397 /*
 398  * Allocate a new archive member descriptor and add it to the list.
 399  */
 400 ARFILE *
 401 newfile(void)
 402 {
 403         static ARFILE   *buffer =  NULL;
 404         static size_t   count = 0;
 405         ARFILE          *fileptr;
 406 
 407         if (count == 0) {
 408                 if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE)))
 409                     == NULL) {
 410                         int err = errno;
 411                         (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
 412                             strerror(err));
 413                         exit(1);
 414                 }
 415                 count = CHUNK;
 416         }
 417         count--;
 418         fileptr = buffer++;
 419 
 420         if (listhead)
 421                 listend->ar_next = fileptr;
 422         else
 423                 listhead = fileptr;
 424         listend = fileptr;
 425         return (fileptr);
 426 }
 427 
 428 static char *
 429 trimslash(char *s)
 430 {
 431         static char buf[SNAME];
 432 
 433         (void) strncpy(buf, trim(s), SNAME - 2);
 434         buf[SNAME - 2] = '\0';
 435         return (strcat(buf, MSG_ORIG(MSG_STR_SLASH)));
 436 }
 437 
 438 char *
 439 trim(char *s)
 440 {
 441         char *p1, *p2;
 442 
 443         for (p1 = s; *p1; p1++)
 444                 ;
 445         while (p1 > s) {
 446                 if (*--p1 != '/')
 447                         break;
 448                 *p1 = 0;
 449         }
 450         p2 = s;
 451         for (p1 = s; *p1; p1++)
 452                 if (*p1 == '/')
 453                         p2 = p1 + 1;
 454         return (p2);
 455 }
 456 
 457 
 458 /*
 459  * Find all the global symbols exported by ELF archive members, and
 460  * build a list associating each one with the archive member that
 461  * provides it.
 462  *
 463  * exit:
 464  *      *symlist is set to the list of symbols. If any ELF object was
 465  *      found, *found_obj is set to TRUE (1). Returns the number of symbols
 466  *      located.
 467  */
 468 static size_t
 469 mksymtab(const char *arname, ARFILEP **symlist, int *found_obj)
 470 {
 471         ARFILE          *fptr;
 472         size_t          mem_offset = 0;
 473         Elf             *elf;
 474         Elf_Scn         *scn;
 475         GElf_Ehdr       ehdr;
 476         int             newfd;
 477         size_t          nsyms = 0;
 478         int             class = 0;
 479         Elf_Data        *data;
 480         size_t          num_errs = 0;
 481 
 482         newfd = 0;
 483         for (fptr = listhead; fptr; fptr = fptr->ar_next) {
 484                 /* determine if file is coming from the archive or not */
 485                 if ((fptr->ar_elf != NULL) && (fptr->ar_pathname == NULL)) {
 486                         /*
 487                          * I can use the saved elf descriptor.
 488                          */
 489                         elf = fptr->ar_elf;
 490                 } else if ((fptr->ar_elf == NULL) &&
 491                     (fptr->ar_pathname != NULL)) {
 492 #ifdef _LP64
 493                         /*
 494                          * The archive member header ar_size field is 10
 495                          * decimal digits, sufficient to represent a 32-bit
 496                          * value, but not a 64-bit one. Hence, we reject
 497                          * attempts to insert a member larger than 4GB.
 498                          *
 499                          * One obvious way to extend the format without altering
 500                          * the ar_hdr struct is to use the same mechanism used
 501                          * for ar_name: Put the size string into the long name
 502                          * string table and write a string /xxx into ar_size,
 503                          * where xxx is the string table offset.
 504                          *
 505                          * At the time of this writing (June 2010), the largest
 506                          * relocatable objects are measured in 10s or 100s
 507                          * of megabytes, so we still have many years to go
 508                          * before this becomes limiting. By that time, it may
 509                          * turn out that a completely new archive format is
 510                          * a better solution, as the current format has many
 511                          * warts and inefficiencies. In the meantime, we
 512                          * won't burden the current implementation with support
 513                          * for a bandaid feature that will have little use.
 514                          */
 515                         if (fptr->ar_size > 0xffffffff) {
 516                                 (void) fprintf(stderr,
 517                                     MSG_INTL(MSG_ERR_MEMBER4G),
 518                                     fptr->ar_pathname);
 519                                 num_errs++;
 520                                 continue;
 521                         }
 522 #endif
 523                         if ((newfd  =
 524                             open(fptr->ar_pathname, O_RDONLY)) == -1) {
 525                                 int err = errno;
 526                                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
 527                                     fptr->ar_pathname, strerror(err));
 528                                 num_errs++;
 529                                 continue;
 530                         }
 531 
 532                         if ((elf = elf_begin(newfd,
 533                             ELF_C_READ, (Elf *)0)) == 0) {
 534                                 (void) fprintf(stderr,
 535                                     MSG_INTL(MSG_ELF_BEGIN_FILE),
 536                                     fptr->ar_pathname, elf_errmsg(-1));
 537                                 (void) close(newfd);
 538                                 newfd = 0;
 539                                 num_errs++;
 540                                 continue;
 541                         }
 542                         if (elf_kind(elf) == ELF_K_AR) {
 543                                 if (newfd) {
 544                                         (void) close(newfd);
 545                                         newfd = 0;
 546                                 }
 547                                 (void) elf_end(elf);
 548                                 continue;
 549                         }
 550                 } else {
 551                         (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01));
 552                         exit(1);
 553                 }
 554                 if (gelf_getehdr(elf, &ehdr) != 0) {
 555                         if ((class = gelf_getclass(elf)) == ELFCLASS64) {
 556                                 fptr->ar_flag |= F_CLASS64;
 557                         } else if (class == ELFCLASS32)
 558                                 fptr->ar_flag |= F_CLASS32;
 559                         scn = elf_getscn(elf, ehdr.e_shstrndx);
 560                         if (scn == NULL) {
 561                                 if (fptr->ar_pathname != NULL)
 562                                         (void) fprintf(stderr,
 563                                             MSG_INTL(MSG_ELF_GETSCN_FILE),
 564                                             fptr->ar_pathname, elf_errmsg(-1));
 565                                 else
 566                                         (void) fprintf(stderr,
 567                                             MSG_INTL(MSG_ELF_GETSCN_AR),
 568                                             arname, fptr->ar_longname,
 569                                             elf_errmsg(-1));
 570                                 num_errs++;
 571                                 if (newfd) {
 572                                         (void) close(newfd);
 573                                         newfd = 0;
 574                                 }
 575                                 (void) elf_end(elf);
 576                                 continue;
 577                         }
 578 
 579                         data = 0;
 580                         data = elf_getdata(scn, data);
 581                         if (data == NULL) {
 582                                 if (fptr->ar_pathname != NULL)
 583                                         (void) fprintf(stderr,
 584                                             MSG_INTL(MSG_ELF_GETDATA_FILE),
 585                                             fptr->ar_pathname, elf_errmsg(-1));
 586                                 else
 587                                         (void) fprintf(stderr,
 588                                             MSG_INTL(MSG_ELF_GETDATA_AR),
 589                                             arname, fptr->ar_longname,
 590                                             elf_errmsg(-1));
 591                                 num_errs++;
 592                                 if (newfd) {
 593                                         (void) close(newfd);
 594                                         newfd = 0;
 595                                 }
 596                                 (void) elf_end(elf);
 597                                 continue;
 598                         }
 599                         if (data->d_size == 0) {
 600                                 if (fptr->ar_pathname != NULL)
 601                                         (void) fprintf(stderr,
 602                                             MSG_INTL(MSG_W_ELF_NODATA_FILE),
 603                                             fptr->ar_pathname);
 604                                 else
 605                                         (void) fprintf(stderr,
 606                                             MSG_INTL(MSG_W_ELF_NODATA_AR),
 607                                             arname, fptr->ar_longname);
 608                                 if (newfd) {
 609                                         (void) close(newfd);
 610                                         newfd = 0;
 611                                 }
 612                                 (void) elf_end(elf);
 613                                 num_errs++;
 614                                 continue;
 615                         }
 616 
 617                         /* loop through sections to find symbol table */
 618                         scn = 0;
 619                         while ((scn = elf_nextscn(elf, scn)) != 0) {
 620                                 GElf_Shdr shdr;
 621                                 if (gelf_getshdr(scn, &shdr) == NULL) {
 622                                         /* BEGIN CSTYLED */
 623                                         if (fptr->ar_pathname != NULL)
 624                                             (void) fprintf(stderr,
 625                                                 MSG_INTL(MSG_ELF_GETDATA_FILE),
 626                                                 fptr->ar_pathname,
 627                                                 elf_errmsg(-1));
 628                                         else
 629                                             (void) fprintf(stderr,
 630                                                 MSG_INTL(MSG_ELF_GETDATA_AR),
 631                                                 arname, fptr->ar_longname,
 632                                                 elf_errmsg(-1));
 633                                         /* END CSTYLED */
 634                                         if (newfd) {
 635                                                 (void) close(newfd);
 636                                                 newfd = 0;
 637                                         }
 638                                         num_errs++;
 639                                         (void) elf_end(elf);
 640                                         continue;
 641                                 }
 642                                 *found_obj = 1;
 643                                 if (shdr.sh_type == SHT_SYMTAB)
 644                                         if (search_sym_tab(arname, fptr, elf,
 645                                             scn, &nsyms, symlist,
 646                                             &num_errs) == -1) {
 647                                                 if (newfd) {
 648                                                         (void) close(newfd);
 649                                                         newfd = 0;
 650                                                 }
 651                                                 continue;
 652                                         }
 653                         }
 654                 }
 655                 mem_offset += sizeof (struct ar_hdr) + fptr->ar_size;
 656                 if (fptr->ar_size & 01)
 657                         mem_offset++;
 658                 (void) elf_end(elf);
 659                 if (newfd) {
 660                         (void) close(newfd);
 661                         newfd = 0;
 662                 }
 663         }
 664         if (num_errs)
 665                 exit(1);
 666 
 667         if (found_obj) {
 668                 if (nsyms == 0) {
 669                         /*
 670                          * It is possible, though rare, to have ELF objects
 671                          * that do not export any global symbols. Presumably
 672                          * such objects operate via their .init/.fini
 673                          * sections. In this case, we produce an empty
 674                          * symbol table, so that applications that rely
 675                          * on a successful call to elf_getarsym() to determine
 676                          * if ELF objects are present will succeed. To do this,
 677                          * we require a small empty symbol string table.
 678                          */
 679                         strtbl_pad(&sym_strtbl, 4, '\0');
 680                 } else {
 681                         /*
 682                          * Historical behavior is to pad string tables
 683                          * to a multiple of 4.
 684                          */
 685                         strtbl_pad(&sym_strtbl, pad(sym_strtbl.used, 4), '\0');
 686                 }
 687 
 688         }
 689 
 690         return (nsyms);
 691 }
 692 
 693 /*
 694  * Output a member header.
 695  */
 696 /*ARGSUSED*/
 697 static void
 698 write_member_header(const char *filename, int fd, int is_elf,
 699     const char *name, time_t timestamp, uid_t uid, gid_t gid, mode_t mode,
 700     size_t size)
 701 {
 702         char    buf[sizeof (struct ar_hdr) + 1];
 703         int     len;
 704 
 705         len = snprintf(buf, sizeof (buf), MSG_ORIG(MSG_MH_FORMAT), name,
 706             EC_WORD(timestamp), EC_WORD(uid), EC_WORD(gid), EC_WORD(mode),
 707             EC_XWORD(size), ARFMAG);
 708 
 709         /*
 710          * If snprintf() reports that it needed more space than we gave
 711          * it, it means that the caller fed us a long name, which is a
 712          * fatal internal error.
 713          */
 714         if (len != sizeof (struct ar_hdr)) {
 715                 (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_02));
 716                 exit(1);
 717         }
 718 
 719         arwrite(filename, fd, buf, len);
 720 
 721         /*
 722          * We inject inter-member padding to ensure that ELF object
 723          * member data is aligned on PADSZ. If this is a debug build,
 724          * verify that the computations were right.
 725          */
 726         assert(!is_elf || (pad(lseek(fd, 0, SEEK_CUR), PADSZ) == 0));
 727 }
 728 
 729 /*
 730  * Write the archive symbol table member to the output archive file.
 731  *
 732  * note:
 733  *      sizeofmembers() must have been called to establish member offset
 734  *      and padding values before writesymtab() is used.
 735  */
 736 static void
 737 writesymtab(const char *filename, int fd, size_t nsyms, ARFILEP *symlist,
 738     size_t eltsize)
 739 {
 740         size_t  i, j;
 741         ARFILEP *ptr;
 742         size_t  tblsize;
 743         char    *buf, *dst;
 744         int     is64 = (eltsize == 8);
 745 
 746         /*
 747          * We require a buffer large enough to hold a symbol table count,
 748          * plus one offset for each symbol.
 749          */
 750         tblsize = (nsyms + 1) * eltsize;
 751         if ((buf = dst = malloc(tblsize)) == NULL) {
 752                 int err = errno;
 753                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
 754                 exit(1);
 755         }
 756 
 757         write_member_header(filename, fd, 0,
 758             (is64 ? MSG_ORIG(MSG_STR_SYM64) : MSG_ORIG(MSG_STR_SLASH)),
 759             time(0), 0, 0, 0, tblsize + sym_strtbl.used);
 760 
 761         dst = is64 ? sputl64(nsyms, dst) : sputl32(nsyms, dst);
 762 
 763         for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) {
 764                 if (!j) {
 765                         j = SYMCHUNK;
 766                         ptr = (ARFILEP *)*ptr;
 767                 }
 768                 dst = is64 ? sputl64((*ptr)->ar_offset, dst) :
 769                     sputl32((*ptr)->ar_offset, dst);
 770         }
 771         arwrite(filename, fd, buf, tblsize);
 772         free(buf);
 773         arwrite(filename, fd, sym_strtbl.base, sym_strtbl.used);
 774 }
 775 
 776 /*
 777  * Grow the size of the given string table so that there is room
 778  * for at least need bytes.
 779  *
 780  * entry:
 781  *      strtbl - String table to grow
 782  *      need - Amount of space required by caller
 783  */
 784 static void
 785 strtbl_alloc(ARSTRTBL *strtbl, size_t need)
 786 {
 787 #define STRTBL_INITSZ   8196
 788 
 789         /*
 790          * On 32-bit systems, we require a larger integer type in order
 791          * to avoid overflow and wraparound when doing our computations.
 792          */
 793         uint64_t        need64 = need;
 794         uint64_t        used64 = strtbl->used;
 795         uint64_t        size64 = strtbl->size;
 796         uint64_t        target = need64 + used64;
 797 
 798         int             sys32, tbl32;
 799 
 800         if (target <= size64)
 801                 return;
 802 
 803         /*
 804          * Detect 32-bit system. We might usually do this with the preprocessor,
 805          * but it can serve as a predicate in tests that also apply to 64-bit
 806          * systems.
 807          */
 808         sys32 = (sizeof (size_t) == 4);
 809 
 810         /*
 811          * The symbol string table can be larger than 32-bits on a 64-bit
 812          * system. However, the long name table must stay below that limit.
 813          * The reason for this is that there is not enough room in the ar_name
 814          * field of the member header to represent 64-bit offsets.
 815          */
 816         tbl32 = (strtbl == &long_strtbl);
 817 
 818         /*
 819          * If request is larger than 4GB and we can't do it because we
 820          * are a 32-bit program, or because the table is format limited,
 821          * we can go no further.
 822          */
 823         if ((target > 0xffffffff) && (sys32 || tbl32))
 824                 goto limit_fail;
 825 
 826         /* Default starting size */
 827         if (strtbl->base == NULL)
 828                 size64 = STRTBL_INITSZ;
 829 
 830         /*
 831          * Our strategy is to double the size until we find a size that
 832          * exceeds the request. However, if this table cannot exceed 4GB,
 833          * then once we exceed 2GB, we switch to a strategy of taking the
 834          * current request and rounding it up to STRTBL_INITSZ.
 835          */
 836         while (target > size64) {
 837                 if ((target > 0x7fffffff) && (sys32 || tbl32)) {
 838                         size64 = ((target + STRTBL_INITSZ) / STRTBL_INITSZ) *
 839                             STRTBL_INITSZ;
 840 
 841                         /*
 842                          * If we are so close to the line that this small
 843                          * increment exceeds 4GB, give it up.
 844                          */
 845                         if ((size64 > 0xffffffff) && (sys32 || tbl32))
 846                                 goto limit_fail;
 847 
 848                         break;
 849                 }
 850 
 851                 size64 *= 2;
 852         }
 853 
 854         strtbl->base = realloc(strtbl->base, size64);
 855         if (strtbl->base == NULL) {
 856                 int err = errno;
 857                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
 858                 exit(1);
 859         }
 860         strtbl->size = (size_t)size64;
 861         return;
 862 
 863 limit_fail:
 864         /*
 865          * Control comes here if we are unable to allocate more than 4GB of
 866          * memory for the string table due to one of the following reasons:
 867          *
 868          * - A 32-bit process is attempting to be larger than 4GB
 869          *
 870          * - A 64-bit process is attempting to grow the long names string
 871          *      table beyond the ar format limit of 32-bits.
 872          */
 873         if (sys32)
 874                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
 875         else
 876                 (void) fprintf(stderr, MSG_INTL(MSG_ERR_LONGSTRTBLSZ));
 877         exit(1);
 878 
 879 #undef STRTBL_INITSZ
 880 }
 881 
 882 /*
 883  * Add the specified number of pad characters to the end of the
 884  * given string table.
 885  *
 886  * entry:
 887  *      strtbl - String table to pad
 888  *      n - # of pad characters to add
 889  *      ch - Pad character to use
 890  */
 891 static void
 892 strtbl_pad(ARSTRTBL *strtbl, size_t n, int ch)
 893 {
 894         if (n == 0)
 895                 return;
 896 
 897         if ((n + strtbl->used) > strtbl->size)
 898                 strtbl_alloc(strtbl, n);
 899 
 900         while (n--)
 901                 strtbl->base[strtbl->used++] = ch;
 902 }
 903 
 904 /*
 905  * Enter a symbol name into the symbol string table.
 906  */
 907 static void
 908 savename(char *symbol)
 909 {
 910         size_t need;
 911 
 912         need = strlen(symbol) + 1;
 913         if ((need + sym_strtbl.used) > sym_strtbl.size)
 914                 strtbl_alloc(&sym_strtbl, need);
 915 
 916         (void) strcpy(sym_strtbl.base + sym_strtbl.used, symbol);
 917         sym_strtbl.used += need;
 918 }
 919 
 920 /*
 921  * Prepare an archive member with a long (>15 characters) name for
 922  * the output archive.
 923  *
 924  * entry:
 925  *      fptr - pointer to archive member with long name
 926  *
 927  * exit:
 928  *      The long name is entered into the long name string table,
 929  *      and fptr->ar_name has been replaced with the special /xxx
 930  *      name used to indicate that the real name is in the string table
 931  *      at offset xxx.
 932  */
 933 static void
 934 savelongname(ARFILE *fptr)
 935 {
 936         size_t  len, need;
 937         char    *p;
 938 
 939         /* Size of new item to add */
 940         len = strlen(fptr->ar_longname);
 941         need = len + 2;
 942 
 943         /* Ensure there's room */
 944         if ((need + long_strtbl.used) > long_strtbl.size)
 945                 strtbl_alloc(&long_strtbl, need);
 946 
 947         /*
 948          * Generate the index string to be written into the member header
 949          *
 950          * This will not overflow the ar_name field because that field is
 951          * 16 characters in size, and a 32-bit unsigned value can be formatted
 952          * in 10 characters. Allowing a character for the leading '/', and one
 953          * for the NULL termination, that leaves us with 4 extra spaces.
 954          */
 955         (void) snprintf(fptr->ar_name, sizeof (fptr->ar_name),
 956             MSG_ORIG(MSG_FMT_LLINT), EC_XWORD(long_strtbl.used));
 957 
 958         /*
 959          * Enter long name into reserved spot, terminated with a slash
 960          * and a newline character.
 961          */
 962         p = long_strtbl.base + long_strtbl.used;
 963         long_strtbl.used += need;
 964         (void) strcpy(p, fptr->ar_longname);
 965         p += len;
 966         *p++ = '/';
 967         *p++ = '\n';
 968 }
 969 
 970 /*
 971  * Determine if the archive we're about to write will exceed the
 972  * 32-bit limit of 4GB.
 973  *
 974  * entry:
 975  *      mksymtab() and mklong_tab() have been called to set up
 976  *      the string tables.
 977  *
 978  * exit:
 979  *      Returns TRUE (1) if the 64-bit symbol table is needed, and
 980  *      FALSE (0) otherwise.
 981  *
 982  */
 983 static int
 984 require64(size_t nsyms, int found_obj, size_t longnames)
 985 {
 986         ARFILE          *fptr;
 987         uint64_t        size;
 988 
 989         /*
 990          * If there are more than 4GB symbols, we have to use
 991          * the 64-bit form. Note that longnames cannot exceed 4GB
 992          * because that symbol table is limited to a length of 4GB by
 993          * the archive format.
 994          */
 995         if (nsyms > 0xffffffff)
 996                 return (1);
 997 
 998         /*
 999          * Make a worst case estimate for the size of the resulting
1000          * archive by assuming full padding between members.
1001          */
1002         size =  SARMAG;
1003         if (longnames)
1004                 size += sizeof (struct ar_hdr) + long_strtbl.used + PADSZ;
1005 
1006         if (found_obj)
1007                 size += sizeof_symtbl(nsyms, found_obj, 4) + PADSZ;
1008 
1009         if (size > 0xffffffff)
1010                 return (1);
1011 
1012         for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1013                 size += sizeof (struct ar_hdr) + fptr->ar_size + PADSZ;
1014 
1015                 if (size > 0xffffffff)
1016                         return (1);
1017         }
1018 
1019         /* 32-bit symbol table will suffice */
1020         return (0);
1021 }
1022 
1023 void
1024 writefile(Cmd_info *cmd_info)
1025 {
1026         ARFILE          *fptr;
1027         ARFILEP         *symlist = 0;
1028         size_t          longnames;
1029         size_t          nsyms;
1030         int             new_archive = 0;
1031         char            *name = cmd_info->arnam;
1032         size_t          arsize; /* Size of magic # and special members */
1033         size_t          symtbl_eltsize = 4;
1034         int             found_obj = 0;
1035         int             fd;
1036         off_t           off;
1037         struct stat     stbuf, ar_stbuf;
1038         char            pad_bytes[PADSZ];
1039         size_t          pad_cnt;
1040         int             is_elf;
1041 
1042         /*
1043          * Gather the list of symbols and associate each one to the
1044          * ARFILE descriptor of the object it belongs to. At the same
1045          * time, tag each ELF object with the appropriate F_CLASSxx
1046          * flag.
1047          */
1048         nsyms = mksymtab(name, &symlist, &found_obj);
1049 
1050         /* Generate the string table for long member names */
1051         longnames = mklong_tab();
1052 
1053         /*
1054          * Will this archive exceed 4GB? If we're a 32-bit process, we can't
1055          * do it. If we're a 64-bit process, then we'll have to use a
1056          * 64-bit symbol table.
1057          */
1058         if (require64(nsyms, found_obj, longnames)) {
1059 #ifdef _LP64
1060                 symtbl_eltsize = 8;
1061 #else
1062                 (void) fprintf(stderr, MSG_INTL(MSG_TOOBIG4G));
1063                 exit(1);
1064 #endif
1065         }
1066 
1067         /*
1068          * If the user requested it, use the 64-bit symbol table even if
1069          * a 32-bit one would suffice. 32-bit tables are more portable and
1070          * take up less room, so this feature is primarily for testing.
1071          */
1072         if (cmd_info->opt_flgs & S_FLAG)
1073                 symtbl_eltsize = 8;
1074 
1075         /*
1076          * If the first non-special archive member is an ELF object, then we
1077          * need to arrange for its data to have an alignment of PADSZ. The
1078          * preceeding special member will be the symbol table, or the long
1079          * name string table. We pad the string table that precedes the
1080          * ELF member in order to achive the desired alignment.
1081          */
1082         is_elf = listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64));
1083         arsize = SARMAG;
1084         if (found_obj) {
1085                 arsize += sizeof_symtbl(nsyms, found_obj, symtbl_eltsize);
1086                 if (is_elf && (longnames == 0)) {
1087                         pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
1088                         strtbl_pad(&sym_strtbl, pad_cnt, '\0');
1089                         arsize += pad_cnt;
1090                 }
1091         }
1092         if (longnames > 0) {
1093                 arsize += sizeof (struct ar_hdr) + long_strtbl.used;
1094                 if (is_elf) {
1095                         pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
1096                         strtbl_pad(&long_strtbl, pad_cnt, '\0');
1097                         arsize += pad_cnt;
1098                 }
1099         }
1100 
1101         /*
1102          * For each user visible (non-special) archive member, determine
1103          * the header offset, and the size of any required padding.
1104          */
1105         (void) sizeofmembers(arsize);
1106 
1107         /*
1108          * Is this a new archive, or are we updating an existing one?
1109          *
1110          * A subtlety here is that POSIX says we are not supposed
1111          * to replace a non-writable file. The only 100% reliable test
1112          * against this is to open the file for non-destructive
1113          * write access. If the open succeeds, we are clear to
1114          * replace it, and if not, then the error generated is
1115          * the error we need to report.
1116          */
1117         if ((fd = open(name, O_RDWR)) < 0) {
1118                 int     err = errno;
1119 
1120                 if (err != ENOENT) {
1121                         (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1122                             name, strerror(err));
1123                         exit(1);
1124                 }
1125                 new_archive = 1;
1126                 if ((cmd_info->opt_flgs & c_FLAG) == 0) {
1127                         (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_CREATE),
1128                             cmd_info->arnam);
1129                 }
1130         } else {
1131                 /* Capture mode and owner information to apply to replacement */
1132                 if (fstat(fd, &ar_stbuf) < 0) {
1133                         int err = errno;
1134                         (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT),
1135                             name, strerror(err));
1136                         (void) close(fd);
1137                         exit(1);
1138                 }
1139                 (void) close(fd);
1140                 new_archive = 0;
1141         }
1142 
1143 
1144         /*
1145          * Register exit handler function to clean up after us if we exit
1146          * before completing the new archive. atexit() is defined as
1147          * only being able to fail due to memory exhaustion.
1148          */
1149         if (atexit(exit_cleanup) != 0) {
1150                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
1151                 exit(1);
1152         }
1153 
1154         /*
1155          * If a new archive, create it in place. If updating an archive,
1156          * create the replacement under a temporary name and then rename it
1157          * into place.
1158          */
1159         ar_outfile.path = new_archive ? name : make_tmpname(name);
1160         ar_outfile.fd = open(ar_outfile.path, O_RDWR|O_CREAT|O_LARGEFILE, 0666);
1161         if (ar_outfile.fd == -1) {
1162                 int err = errno;
1163                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1164                     ar_outfile.path, strerror(err));
1165                 exit(1);
1166         }
1167 
1168         /* Output magic string */
1169         arwrite(name, ar_outfile.fd, ARMAG, SARMAG);
1170 
1171         /*
1172          * The symbol table member is always first if present. Note that
1173          * writesymtab() uses the member offsets computed by sizeofmembers()
1174          * above.
1175          */
1176         if (found_obj)
1177                 writesymtab(name, ar_outfile.fd, nsyms, symlist,
1178                     symtbl_eltsize);
1179 
1180         if (longnames) {
1181                 write_member_header(name, ar_outfile.fd, 0,
1182                     MSG_ORIG(MSG_STR_DSLASH), time(0), 0, 0, 0,
1183                     long_strtbl.used);
1184                 arwrite(name, ar_outfile.fd, long_strtbl.base,
1185                     long_strtbl.used);
1186         }
1187 
1188         /*
1189          * The accuracy of the symbol table depends on our having calculated
1190          * the size of the archive accurately to this point. If this is a
1191          * debug build, verify it.
1192          */
1193         assert(arsize == lseek(ar_outfile.fd, 0, SEEK_CUR));
1194 
1195 #ifndef XPG4
1196         if (cmd_info->opt_flgs & v_FLAG) {
1197                 (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_WRITE),
1198                     cmd_info->arnam);
1199         }
1200 #endif
1201 
1202         /*
1203          * Fill pad_bytes array with newline characters. This array
1204          * is used to supply padding bytes at the end of ELF objects.
1205          * There can never be more tha PADSZ such bytes, so this number
1206          * will always suffice.
1207          */
1208         for (pad_cnt = 0; pad_cnt < PADSZ; pad_cnt++)
1209                 pad_bytes[pad_cnt] = '\n';
1210 
1211         for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1212                 /*
1213                  * We computed the expected offset for each ELF member and
1214                  * used those offsets to fill the symbol table. If this is
1215                  * a debug build, verify that the computed offset was right.
1216                  */
1217                 is_elf = (fptr->ar_flag & (F_CLASS32 | F_CLASS64)) != 0;
1218                 assert(!is_elf ||
1219                     (fptr->ar_offset == lseek(ar_outfile.fd, 0, SEEK_CUR)));
1220 
1221                 /*
1222                  * NOTE:
1223                  * The mem_header->ar_name[] is set to a NULL string
1224                  * if the archive member header has some error.
1225                  * (See elf_getarhdr() man page.)
1226                  * It is set to NULL for example, the ar command reads
1227                  * the archive files created by SunOS 4.1 system.
1228                  * See c block comment in cmd.c, "Incompatible Archive Header".
1229                  */
1230                 if (fptr->ar_name[0] == 0) {
1231                         fptr->ar_longname = fptr->ar_rawname;
1232                         (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME);
1233                 }
1234                 write_member_header(name, ar_outfile.fd, is_elf,
1235                     (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) ?
1236                     trimslash(fptr->ar_longname) : fptr->ar_name,
1237                     EC_WORD(fptr->ar_date), fptr->ar_uid, fptr->ar_gid,
1238                     fptr->ar_mode, fptr->ar_size + fptr->ar_padding);
1239 
1240 
1241                 if ((fptr->ar_flag & F_ELFRAW) == 0) {
1242                         /*
1243                          * The file doesn't come from the archive, and is
1244                          * therefore not already in memory(fptr->ar_contents)
1245                          * so open it and do a direct file-to-file transfer of
1246                          * its contents. We use the sendfile() system call
1247                          * to make the kernel do the transfer, so we don't have
1248                          * to buffer data in process, and we trust that the
1249                          * kernel will use an optimal transfer strategy.
1250                          */
1251                         if ((fd = open(fptr->ar_pathname, O_RDONLY)) == -1) {
1252                                 int err = errno;
1253                                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1254                                     fptr->ar_longname, strerror(err));
1255                                 exit(1);
1256                         }
1257                         if (stat(fptr->ar_pathname, &stbuf) < 0) {
1258                                 int err = errno;
1259                                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1260                                     fptr->ar_longname, strerror(err));
1261                                 (void) close(fd);
1262                                 exit(1);
1263                         }
1264                         off = 0;
1265                         if (sendfile(ar_outfile.fd, fd, &off,
1266                             stbuf.st_size) != stbuf.st_size) {
1267                                 int err = errno;
1268                                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
1269                                     name, strerror(err));
1270                                 exit(2);
1271                         }
1272                         (void) close(fd);
1273                 } else {
1274                         /* Archive member is in memory. Write it out */
1275                         arwrite(name, ar_outfile.fd, fptr->ar_contents,
1276                             fptr->ar_size);
1277                 }
1278 
1279                 /*
1280                  * All archive members are padded to at least a boundary of 2.
1281                  * The expression ((fptr->ar_size & 0x1) != 0) yields 1 for
1282                  * odd boundaries, and 0 for even ones. To this, we add
1283                  * whatever padding is needed for ELF objects.
1284                  */
1285                 pad_cnt = ((fptr->ar_size & 0x1) != 0) + fptr->ar_padding;
1286                 if (pad_cnt > 0)
1287                         arwrite(name, ar_outfile.fd, pad_bytes, pad_cnt);
1288         }
1289 
1290         /*
1291          * All archive output is done.
1292          */
1293         if (close(ar_outfile.fd) < 0) {
1294                 int err = errno;
1295                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_CLOSE), ar_outfile.path,
1296                     strerror(err));
1297                 exit(1);
1298         }
1299         ar_outfile.fd = -1;     /* Prevent removal on exit */
1300         (void) elf_end(cmd_info->arf);
1301         (void) close(cmd_info->afd);
1302 
1303         /*
1304          * If updating an existing archive, rename the new version on
1305          * top of the original.
1306          */
1307         if (!new_archive) {
1308                 /*
1309                  * Prevent the replacement of the original archive from
1310                  * being interrupted, to lower the possibility of an
1311                  * interrupt destroying a pre-existing archive.
1312                  */
1313                 establish_sighandler(SIG_IGN);
1314 
1315                 if (rename(ar_outfile.path, name) < 0) {
1316                         int err = errno;
1317                         (void) fprintf(stderr, MSG_INTL(MSG_SYS_RENAME),
1318                             ar_outfile.path, name, strerror(err));
1319                         (void) unlink(ar_outfile.path);
1320                         exit(1);
1321                 }
1322                 (void) chmod(name, ar_stbuf.st_mode & 0777);
1323                 if (chown(name, ar_stbuf.st_uid, ar_stbuf.st_gid) >= 0)
1324                         (void) chmod(name, ar_stbuf.st_mode & 07777);
1325 
1326         }
1327 }
1328 
1329 /*
1330  * Examine all the archive members, enter any member names longer than
1331  * 15 characters into the long name string table, and count the number
1332  * of names found.
1333  *
1334  * Returns the size of the resulting archive member, including the
1335  * member header.
1336  */
1337 static size_t
1338 mklong_tab(void)
1339 {
1340         ARFILE  *fptr;
1341         size_t longnames = 0;
1342 
1343         for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1344                 if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) {
1345                         longnames++;
1346                         savelongname(fptr);
1347                 }
1348         }
1349 
1350         /* round up table that keeps the long filenames */
1351         if (longnames > 0)
1352                 strtbl_pad(&long_strtbl, pad(long_strtbl.used, 4), '\n');
1353 
1354         return (longnames);
1355 }
1356 
1357 /*
1358  * Write 32/64-bit words into buffer in archive symbol table
1359  * standard byte order (MSB).
1360  */
1361 static char *
1362 sputl32(uint32_t n, char *cp)
1363 {
1364         *cp++ = n >> 24;
1365         *cp++ = n >> 16;
1366         *cp++ = n >> 8;
1367 
1368         *cp++ = n & 255;
1369 
1370         return (cp);
1371 }
1372 
1373 static char *
1374 sputl64(uint64_t n, char *cp)
1375 {
1376         *cp++ = n >> 56;
1377         *cp++ = n >> 48;
1378         *cp++ = n >> 40;
1379         *cp++ = n >> 32;
1380 
1381         *cp++ = n >> 24;
1382         *cp++ = n >> 16;
1383         *cp++ = n >> 8;
1384 
1385         *cp++ = n & 255;
1386 
1387         return (cp);
1388 }
1389 
1390 static int
1391 search_sym_tab(const char *arname, ARFILE *fptr, Elf *elf, Elf_Scn *scn,
1392         size_t *nsyms, ARFILEP **symlist, size_t *num_errs)
1393 {
1394         Elf_Data *str_data, *sym_data; /* string table, symbol table */
1395         Elf_Scn *str_scn;
1396         GElf_Sxword no_of_symbols;
1397         GElf_Shdr shdr;
1398         int counter;
1399         int str_shtype;
1400         char *symname;
1401         static ARFILEP *sym_ptr = 0;
1402         static ARFILEP *nextsym = NULL;
1403         static int syms_left = 0;
1404         char *fname = fptr->ar_pathname;
1405 
1406         (void) gelf_getshdr(scn, &shdr);
1407         str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */
1408         if (str_scn == NULL) {
1409                 if (fname != NULL)
1410                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
1411                             fname, elf_errmsg(-1));
1412                 else
1413                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
1414                             arname, fptr->ar_longname, elf_errmsg(-1));
1415                 (*num_errs)++;
1416                 return (-1);
1417         }
1418 
1419         no_of_symbols = shdr.sh_size / shdr.sh_entsize;
1420         if (no_of_symbols == -1) {
1421                 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_01));
1422                 return (-1);
1423         }
1424 
1425         (void) gelf_getshdr(str_scn, &shdr);
1426         str_shtype = shdr.sh_type;
1427         if (str_shtype == -1) {
1428                 if (fname != NULL)
1429                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
1430                             fname, elf_errmsg(-1));
1431                 else
1432                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
1433                             arname, fptr->ar_longname, elf_errmsg(-1));
1434                 (*num_errs)++;
1435                 return (-1);
1436         }
1437 
1438         /* This test must happen before testing the string table. */
1439         if (no_of_symbols == 1)
1440                 return (0);     /* no symbols; 0th symbol is the non-symbol */
1441 
1442         if (str_shtype != SHT_STRTAB) {
1443                 if (fname != NULL)
1444                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_FILE),
1445                             fname);
1446                 else
1447                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_AR),
1448                             arname, fptr->ar_longname);
1449                 return (0);
1450         }
1451         str_data = 0;
1452         if ((str_data = elf_getdata(str_scn, str_data)) == 0) {
1453                 if (fname != NULL)
1454                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_FILE),
1455                             fname);
1456                 else
1457                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_AR),
1458                             arname, fptr->ar_longname);
1459                 return (0);
1460         }
1461         if (str_data->d_size == 0) {
1462                 if (fname != NULL)
1463                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_FILE),
1464                             fname);
1465                 else
1466                         (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_AR),
1467                             arname, fptr->ar_longname);
1468                 return (0);
1469         }
1470         sym_data = 0;
1471         if ((sym_data = elf_getdata(scn, sym_data)) == NULL) {
1472                 if (fname != NULL)
1473                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_FILE),
1474                             fname, elf_errmsg(-1));
1475                 else
1476                         (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_AR),
1477                             arname, fptr->ar_longname, elf_errmsg(-1));
1478                 return (0);
1479         }
1480 
1481         /* start at 1, first symbol entry is ignored */
1482         for (counter = 1; counter < no_of_symbols; counter++) {
1483                 GElf_Sym sym;
1484                 (void) gelf_getsym(sym_data, counter, &sym);
1485 
1486                 symname = (char *)(str_data->d_buf) + sym.st_name;
1487 
1488                 if (((GELF_ST_BIND(sym.st_info) == STB_GLOBAL) ||
1489                     (GELF_ST_BIND(sym.st_info) == STB_WEAK)) &&
1490                     (sym.st_shndx != SHN_UNDEF)) {
1491                         if (!syms_left) {
1492                                 sym_ptr = malloc((SYMCHUNK+1)
1493                                     * sizeof (ARFILEP));
1494                                 if (sym_ptr == NULL) {
1495                                         int err = errno;
1496                                         (void) fprintf(stderr,
1497                                             MSG_INTL(MSG_MALLOC),
1498                                             strerror(err));
1499                                         exit(1);
1500                                 }
1501                                 syms_left = SYMCHUNK;
1502                                 if (nextsym)
1503                                         *nextsym = (ARFILEP)sym_ptr;
1504                                 else
1505                                         *symlist = sym_ptr;
1506                                 nextsym = sym_ptr;
1507                         }
1508                         sym_ptr = nextsym;
1509                         nextsym++;
1510                         syms_left--;
1511                         (*nsyms)++;
1512                         *sym_ptr = fptr;
1513                         savename(symname);      /* put name in the archiver's */
1514                                                 /* symbol table string table */
1515                 }
1516         }
1517         return (0);
1518 }
1519 
1520 /*
1521  * Get the output file size
1522  */
1523 static size_t
1524 sizeofmembers(size_t psum)
1525 {
1526         size_t  sum = 0;
1527         ARFILE  *fptr;
1528         size_t  hdrsize = sizeof (struct ar_hdr);
1529 
1530         for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1531                 fptr->ar_offset = psum + sum;
1532                 sum += fptr->ar_size;
1533                 if (fptr->ar_size & 01)
1534                         sum++;
1535                 sum += hdrsize;
1536 
1537                 /*
1538                  * If the current item, and the next item are both ELF
1539                  * objects, then add padding to current item so that the
1540                  * data in the next item will have PADSZ alignment.
1541                  *
1542                  * In any other case, set the padding to 0. If the
1543                  * item comes from another archive, it may be carrying
1544                  * a non-zero padding value from that archive that does
1545                  * not apply to the one we are about to build.
1546                  */
1547                 if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) &&
1548                     fptr->ar_next &&
1549                     (fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) {
1550                         fptr->ar_padding = pad(psum + sum + hdrsize, PADSZ);
1551                         sum += fptr->ar_padding;
1552                 } else {
1553                         fptr->ar_padding = 0;
1554                 }
1555         }
1556         return (sum);
1557 }
1558 
1559 /*
1560  * Compute the size of the symbol table archive member.
1561  *
1562  * entry:
1563  *      nsyms - # of symbols in the table
1564  *      found_obj - TRUE if the archive contains any ELF objects
1565  *      eltsize - Size of the integer type to use for the symbol
1566  *              table. 4 for 32-bit tables, and 8 for 64-bit tables.
1567  */
1568 static size_t
1569 sizeof_symtbl(size_t nsyms, int found_obj, size_t eltsize)
1570 {
1571         size_t sum = 0;
1572 
1573         if (found_obj) {
1574                 /* Member header, symbol count, and one slot per symbol */
1575                 sum += sizeof (struct ar_hdr) + ((nsyms + 1) * eltsize);
1576                 sum += sym_strtbl.used;
1577         }
1578 
1579         return (sum);
1580 }
1581 
1582 static void
1583 arwrite(const char *name, int nfd, const char *dst, size_t size) {
1584         if (write(nfd, dst, size) != size) {
1585                 int err = errno;
1586                 (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
1587                     name, strerror(err));
1588                 exit(2);
1589         }
1590 }
1591 
1592 static const char *
1593 make_tmpname(const char *filename) {
1594         char    *slash, *tmpname;
1595         size_t  prefix_cnt = 0;
1596 
1597         /*
1598          * If there is a path prefix in front of the filename, we
1599          * want to put the temporary file in the same directory.
1600          * Determine the length of the path.
1601          */
1602         slash = strrchr(filename, '/');
1603         if (slash != NULL)
1604                 prefix_cnt = slash - filename + 1;
1605         tmpname = malloc(prefix_cnt + MSG_STR_MKTEMP_SIZE + 1);
1606         if (tmpname == NULL) {
1607                 int err = errno;
1608                 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
1609                 exit(1);
1610         }
1611 
1612         if (prefix_cnt > 0)
1613                 (void) strncpy(tmpname, filename, prefix_cnt);
1614         (void) strcpy(tmpname + prefix_cnt, MSG_ORIG(MSG_STR_MKTEMP));
1615         (void) mktemp(tmpname);
1616 
1617         return (tmpname);
1618 }