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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 1988 AT&T 28 * All Rights Reserved 29 * 30 */ 31 32 #include "gelf.h" 33 #include "inc.h" 34 #include "extern.h" 35 36 static char *str_base; /* start of string table for names */ 37 static char *str_top; /* pointer to next available location */ 38 static char *str_base1, *str_top1; 39 static int pad_symtab; /* # of bytes by which to pad symbol table */ 40 41 42 /* 43 * The ar file format requires objects to be padded to an even size. 44 * We do that, but it turns out to be beneficial to go farther. 45 * 46 * ld(1) accesses archives by mmapping them into memory. If the mapped 47 * objects have the proper alignment, we can access them directly. If the 48 * alignment is wrong, libelf "slides" them so that they are also accessible. 49 * This is expensive in time (to copy memory) and space (it causes swap 50 * to be allocated by the system to back the now-modified pages). Hence, we 51 * really want to ensure that the alignment is right. 52 * 53 * We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects 54 * at 8-byte. More recently, an elf section type has appeared that has 55 * 8-byte alignment requirements (SUNW_move) even in 32-bit objects. So, 56 * the current strategy is to align all objects to 8-bytes. 57 * 58 * There are two important things to consider when setting this value: 59 * 1) If a new elf section that ld(1) accesses in memory appears 60 * with a greater than 8-byte alignment requirement, this value 61 * will need to be raised. Or, alternatively, the entire approach may 62 * need reconsideration. 63 * 2) The size of this padding must be smaller than the size of the 64 * smallest possible ELF section. Otherwise, the logic contained 65 * in recover_padding() can be tricked. 66 */ 67 #define PADSZ 8 68 69 /* 70 * Function Prototypes 71 */ 72 static long mklong_tab(int *); 73 static char *trimslash(char *s); 74 75 static long mksymtab(ARFILEP **, int *); 76 static int writesymtab(char *, long, ARFILEP *); 77 static void savename(char *); 78 static void savelongname(ARFILE *, char *); 79 static void sputl(long, char *); 80 81 static char *writelargefile(Cmd_info *cmd_info, long long_tab_size, 82 int longnames, ARFILEP *symlist, long nsyms, int found_obj, 83 int new_archive); 84 85 static int sizeofmembers(); 86 static int sizeofnewarchive(int, int); 87 88 static int search_sym_tab(ARFILE *, Elf *, Elf_Scn *, 89 long *, ARFILEP **, int *); 90 91 92 int 93 getaf(Cmd_info *cmd_info) 94 { 95 Elf_Cmd cmd; 96 int fd; 97 char *arnam = cmd_info->arnam; 98 99 if (elf_version(EV_CURRENT) == EV_NONE) { 100 error_message(ELF_VERSION_ERROR, 101 LIBELF_ERROR, elf_errmsg(-1)); 102 exit(1); 103 } 104 105 if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) { 106 if (errno == ENOENT) { 107 /* archive does not exist yet, may have to create one */ 108 return (fd); 109 } else { 110 /* problem other than "does not exist" */ 111 error_message(SYS_OPEN_ERROR, 112 SYSTEM_ERROR, strerror(errno), arnam); 113 exit(1); 114 } 115 } 116 117 cmd = ELF_C_READ; 118 cmd_info->arf = elf_begin(fd, cmd, (Elf *)0); 119 120 if (elf_kind(cmd_info->arf) != ELF_K_AR) { 121 error_message(NOT_ARCHIVE_ERROR, 122 PLAIN_ERROR, (char *)0, arnam); 123 if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) 124 error_message(USAGE_06_ERROR, 125 PLAIN_ERROR, (char *)0, cmd_info->ponam); 126 exit(1); 127 } 128 return (fd); 129 } 130 131 /* 132 * Given a size, return the number of bytes required to round it 133 * up to the next PADSZ boundary. 134 */ 135 static int 136 pad(int n) 137 { 138 int r; 139 140 r = n % PADSZ; 141 if (r) 142 r = PADSZ - r; 143 144 return (r); 145 } 146 147 /* 148 * If the current archive item is an object, then ar(1) may have added 149 * newline padding at the end in order to bring the following object 150 * into PADSZ alignment within the file. This padding cannot be 151 * distinguished from data using the information kept in the ar headers. 152 * This routine examines the objects, using knowledge of 153 * ELF and how our tools lay out objects to determine whether padding was 154 * added to an archive item. If so, it adjusts the st_size and 155 * st_padding fields of the file argument to reflect it. 156 */ 157 static void 158 recover_padding(Elf *elf, ARFILE *file) 159 { 160 long extent; 161 long padding; 162 GElf_Ehdr ehdr; 163 164 165 /* ar(1) only pads objects, so bail if not looking at one */ 166 if (gelf_getclass(elf) == ELFCLASSNONE) 167 return; 168 169 /* 170 * libelf always puts the section header array at the end 171 * of the object, and all of our compilers and other tools 172 * use libelf or follow this convention. So, it is extremely 173 * likely that the section header array is at the end of this 174 * object: Find the address at the end of the array and compare 175 * it to the archive ar_size. If they are within PADSZ bytes, then 176 * we've found the end, and the difference is padding (We assume 177 * that no ELF section can fit into PADSZ bytes). 178 */ 179 extent = gelf_getehdr(elf, &ehdr) 180 ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0; 181 padding = file->ar_size - extent; 182 183 if ((padding < 0) || (padding >= PADSZ)) { 184 /* 185 * The section header array is not at the end of the object. 186 * Traverse the section headers and look for the one with 187 * the highest used address. If this address is within 188 * PADSZ bytes of ar_size, then this is the end of the object. 189 */ 190 Elf_Scn *scn = 0; 191 192 do { 193 scn = elf_nextscn(elf, scn); 194 if (scn) { 195 GElf_Shdr shdr; 196 197 if (gelf_getshdr(scn, &shdr)) { 198 long t = shdr.sh_offset + shdr.sh_size; 199 if (t > extent) 200 extent = t; 201 } 202 } 203 } while (scn); 204 } 205 206 /* 207 * Now, test the padding. We only act on padding in the range 208 * (0 < pad < PADSZ) (ar(1) will never add more than this). A pad 209 * of 0 requires no action, and any other size above (PADSZ-1) means 210 * that we don't understand the layout of this object, and as such, 211 * cannot do anything. 212 * 213 * If the padding is in range, and the raw data for the 214 * object is available, then we perform one additional sanity 215 * check before moving forward: ar(1) always pads with newline 216 * characters. If anything else is seen, it is not padding so 217 * leave it alone. 218 */ 219 if ((padding > 0) && (padding < PADSZ)) { 220 if (file->ar_contents) { 221 long cnt = padding; 222 char *p = file->ar_contents + extent; 223 224 while (cnt--) { 225 if (*p++ != '\n') { /* No padding */ 226 padding = 0; 227 break; 228 } 229 } 230 } 231 232 /* Remove the padding from the size */ 233 file->ar_size -= padding; 234 file->ar_padding = padding; 235 } 236 } 237 238 ARFILE * 239 getfile(Cmd_info *cmd_info) 240 { 241 Elf_Arhdr *mem_header; 242 ARFILE *file; 243 char *tmp_rawname, *file_rawname; 244 Elf *elf; 245 char *arnam = cmd_info->arnam; 246 int fd = cmd_info->afd; 247 Elf *arf = cmd_info->arf; 248 249 if (fd == -1) 250 return (NULL); /* the archive doesn't exist */ 251 252 if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 253 return (NULL); /* the archive is empty or have hit the end */ 254 255 if ((mem_header = elf_getarhdr(elf)) == NULL) { 256 error_message(ELF_MALARCHIVE_ERROR, 257 LIBELF_ERROR, elf_errmsg(-1), 258 arnam, elf_getbase(elf)); 259 exit(1); 260 } 261 262 /* zip past special members like the symbol and string table members */ 263 264 while (strncmp(mem_header->ar_name, "/", 1) == 0 || 265 strncmp(mem_header->ar_name, "//", 2) == 0) { 266 (void) elf_next(elf); 267 (void) elf_end(elf); 268 if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 269 return (NULL); 270 /* the archive is empty or have hit the end */ 271 if ((mem_header = elf_getarhdr(elf)) == NULL) { 272 error_message(ELF_MALARCHIVE_ERROR, 273 LIBELF_ERROR, elf_errmsg(-1), 274 arnam, elf_getbase(elf)); 275 exit(0); 276 } 277 } 278 279 /* 280 * NOTE: 281 * The mem_header->ar_name[] is set to a NULL string 282 * if the archive member header has some error. 283 * (See elf_getarhdr() man page.) 284 * It is set to NULL for example, the ar command reads 285 * the archive files created by SunOS 4.1 system. 286 * See c block comment in cmd.c, "Incompatible Archive Header". 287 */ 288 file = newfile(); 289 (void) strncpy(file->ar_name, mem_header->ar_name, SNAME); 290 291 if ((file->ar_longname 292 = malloc(strlen(mem_header->ar_name) + 1)) 293 == NULL) { 294 error_message(MALLOC_ERROR, 295 PLAIN_ERROR, (char *)0); 296 exit(1); 297 } 298 (void) strcpy(file->ar_longname, mem_header->ar_name); 299 if ((file->ar_rawname 300 = malloc(strlen(mem_header->ar_rawname) + 1)) 301 == NULL) { 302 error_message(MALLOC_ERROR, 303 PLAIN_ERROR, (char *)0); 304 exit(1); 305 } 306 tmp_rawname = mem_header->ar_rawname; 307 file_rawname = file->ar_rawname; 308 while (!isspace(*tmp_rawname) && 309 ((*file_rawname = *tmp_rawname) != '\0')) { 310 file_rawname++; 311 tmp_rawname++; 312 } 313 if (!(*tmp_rawname == '\0')) 314 *file_rawname = '\0'; 315 316 file->ar_date = mem_header->ar_date; 317 file->ar_uid = mem_header->ar_uid; 318 file->ar_gid = mem_header->ar_gid; 319 file->ar_mode = (unsigned long) mem_header->ar_mode; 320 file->ar_size = mem_header->ar_size; 321 322 /* reverse logic */ 323 if (!(opt_FLAG(cmd_info, t_FLAG) && !opt_FLAG(cmd_info, s_FLAG))) { 324 size_t ptr; 325 file->ar_flag = F_ELFRAW; 326 if ((file->ar_contents = elf_rawfile(elf, &ptr)) 327 == NULL) { 328 if (ptr != 0) { 329 error_message(ELF_RAWFILE_ERROR, 330 LIBELF_ERROR, elf_errmsg(-1)); 331 exit(1); 332 } 333 } 334 file->ar_elf = elf; 335 } 336 337 recover_padding(elf, file); 338 339 (void) elf_next(elf); 340 return (file); 341 } 342 343 ARFILE * 344 newfile(void) 345 { 346 static ARFILE *buffer = NULL; 347 static int count = 0; 348 ARFILE *fileptr; 349 350 if (count == 0) { 351 if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE))) 352 == NULL) { 353 error_message(MALLOC_ERROR, 354 PLAIN_ERROR, (char *)0); 355 exit(1); 356 } 357 count = CHUNK; 358 } 359 count--; 360 fileptr = buffer++; 361 362 if (listhead) 363 listend->ar_next = fileptr; 364 else 365 listhead = fileptr; 366 listend = fileptr; 367 return (fileptr); 368 } 369 370 static char * 371 trimslash(char *s) 372 { 373 static char buf[SNAME]; 374 375 (void) strncpy(buf, trim(s), SNAME - 2); 376 buf[SNAME - 2] = '\0'; 377 return (strcat(buf, "/")); 378 } 379 380 char * 381 trim(char *s) 382 { 383 char *p1, *p2; 384 385 for (p1 = s; *p1; p1++) 386 ; 387 while (p1 > s) { 388 if (*--p1 != '/') 389 break; 390 *p1 = 0; 391 } 392 p2 = s; 393 for (p1 = s; *p1; p1++) 394 if (*p1 == '/') 395 p2 = p1 + 1; 396 return (p2); 397 } 398 399 400 static long 401 mksymtab(ARFILEP **symlist, int *found_obj) 402 { 403 ARFILE *fptr; 404 long mem_offset = 0; 405 Elf *elf; 406 Elf_Scn *scn; 407 GElf_Ehdr ehdr; 408 int newfd; 409 long nsyms = 0; 410 int class = 0; 411 Elf_Data *data; 412 int num_errs = 0; 413 414 newfd = 0; 415 for (fptr = listhead; fptr; fptr = fptr->ar_next) { 416 /* determine if file is coming from the archive or not */ 417 if ((fptr->ar_elf != 0) && (fptr->ar_pathname == NULL)) { 418 /* 419 * I can use the saved elf descriptor. 420 */ 421 elf = fptr->ar_elf; 422 } else if ((fptr->ar_elf == 0) && 423 (fptr->ar_pathname != NULL)) { 424 if ((newfd = 425 open(fptr->ar_pathname, O_RDONLY)) == -1) { 426 error_message(SYS_OPEN_ERROR, 427 SYSTEM_ERROR, strerror(errno), 428 fptr->ar_pathname); 429 num_errs++; 430 continue; 431 } 432 433 if ((elf = elf_begin(newfd, 434 ELF_C_READ, (Elf *)0)) == 0) { 435 if (fptr->ar_pathname != NULL) 436 error_message(ELF_BEGIN_02_ERROR, 437 LIBELF_ERROR, elf_errmsg(-1), 438 fptr->ar_pathname); 439 else 440 error_message(ELF_BEGIN_03_ERROR, 441 LIBELF_ERROR, elf_errmsg(-1)); 442 (void) close(newfd); 443 newfd = 0; 444 num_errs++; 445 continue; 446 } 447 if (elf_kind(elf) == ELF_K_AR) { 448 if (fptr->ar_pathname != NULL) 449 error_message(ARCHIVE_IN_ARCHIVE_ERROR, 450 PLAIN_ERROR, (char *)0, 451 fptr->ar_pathname); 452 else 453 error_message(ARCHIVE_USAGE_ERROR, 454 PLAIN_ERROR, (char *)0); 455 if (newfd) { 456 (void) close(newfd); 457 newfd = 0; 458 } 459 (void) elf_end(elf); 460 continue; 461 } 462 } else { 463 error_message(INTERNAL_01_ERROR, 464 PLAIN_ERROR, (char *)0); 465 exit(1); 466 } 467 if (gelf_getehdr(elf, &ehdr) != 0) { 468 if ((class = gelf_getclass(elf)) == ELFCLASS64) { 469 fptr->ar_flag |= F_CLASS64; 470 } else if (class == ELFCLASS32) 471 fptr->ar_flag |= F_CLASS32; 472 scn = elf_getscn(elf, ehdr.e_shstrndx); 473 if (scn == NULL) { 474 if (fptr->ar_pathname != NULL) 475 error_message(ELF_GETSCN_01_ERROR, 476 LIBELF_ERROR, elf_errmsg(-1), 477 fptr->ar_pathname); 478 else 479 error_message(ELF_GETSCN_02_ERROR, 480 LIBELF_ERROR, elf_errmsg(-1)); 481 num_errs++; 482 if (newfd) { 483 (void) close(newfd); 484 newfd = 0; 485 } 486 (void) elf_end(elf); 487 continue; 488 } 489 490 data = 0; 491 data = elf_getdata(scn, data); 492 if (data == NULL) { 493 if (fptr->ar_pathname != NULL) 494 error_message(ELF_GETDATA_01_ERROR, 495 LIBELF_ERROR, elf_errmsg(-1), 496 fptr->ar_pathname); 497 else 498 error_message(ELF_GETDATA_02_ERROR, 499 LIBELF_ERROR, elf_errmsg(-1)); 500 num_errs++; 501 if (newfd) { 502 (void) close(newfd); 503 newfd = 0; 504 } 505 (void) elf_end(elf); 506 continue; 507 } 508 if (data->d_size == 0) { 509 if (fptr->ar_pathname != NULL) 510 error_message(W_ELF_NO_DATA_01_ERROR, 511 PLAIN_ERROR, (char *)0, 512 fptr->ar_pathname); 513 else 514 error_message(W_ELF_NO_DATA_02_ERROR, 515 PLAIN_ERROR, (char *)0); 516 if (newfd) { 517 (void) close(newfd); 518 newfd = 0; 519 } 520 (void) elf_end(elf); 521 num_errs++; 522 continue; 523 } 524 525 /* loop through sections to find symbol table */ 526 scn = 0; 527 while ((scn = elf_nextscn(elf, scn)) != 0) { 528 GElf_Shdr shdr; 529 if (gelf_getshdr(scn, &shdr) == NULL) { 530 if (fptr->ar_pathname != NULL) 531 error_message( 532 ELF_GETDATA_01_ERROR, 533 LIBELF_ERROR, 534 elf_errmsg(-1), 535 fptr->ar_pathname); 536 else 537 error_message( 538 ELF_GETDATA_02_ERROR, 539 LIBELF_ERROR, 540 elf_errmsg(-1)); 541 if (newfd) { 542 (void) close(newfd); 543 newfd = 0; 544 } 545 num_errs++; 546 (void) elf_end(elf); 547 continue; 548 } 549 *found_obj = 1; 550 if (shdr.sh_type == SHT_SYMTAB) 551 if (search_sym_tab(fptr, elf, 552 scn, &nsyms, symlist, 553 &num_errs) == -1) { 554 if (newfd) { 555 (void) close(newfd); 556 newfd = 0; 557 } 558 continue; 559 } 560 } 561 } 562 mem_offset += sizeof (struct ar_hdr) + fptr->ar_size; 563 if (fptr->ar_size & 01) 564 mem_offset++; 565 (void) elf_end(elf); 566 if (newfd) { 567 (void) close(newfd); 568 newfd = 0; 569 } 570 } /* for */ 571 if (num_errs) 572 exit(1); 573 return (nsyms); 574 } 575 576 /* 577 * This routine writes an archive symbol table for the 578 * output archive file. The symbol table is built if 579 * there was at least one object file specified. 580 * In rare case, there could be no symbol. 581 * In this case, str_top and str_base can not be used to 582 * make the string table. So the routine adjust the size 583 * and make a dummy string table. String table is needed 584 * by elf_getarsym(). 585 */ 586 static int 587 writesymtab(char *dst, long nsyms, ARFILEP *symlist) 588 { 589 char buf1[sizeof (struct ar_hdr) + 1]; 590 char *buf2, *bptr; 591 int i, j; 592 ARFILEP *ptr; 593 long sym_tab_size = 0; 594 int sum = 0; 595 596 /* 597 * patch up archive pointers and write the symbol entries 598 */ 599 while ((str_top - str_base) & 03) /* round up string table */ 600 *str_top++ = '\0'; 601 sym_tab_size = (nsyms +1) * 4 + sizeof (char) * (str_top - str_base); 602 if (nsyms == 0) 603 sym_tab_size += 4; 604 sym_tab_size += pad_symtab; 605 606 (void) sprintf(buf1, FORMAT, SYMDIRNAME, time(0), (unsigned)0, 607 (unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG); 608 609 if (strlen(buf1) != sizeof (struct ar_hdr)) { 610 error_message(INTERNAL_02_ERROR); 611 exit(1); 612 } 613 614 if ((buf2 = malloc(4 * (nsyms + 1))) == NULL) { 615 error_message(MALLOC_ERROR); 616 error_message(DIAG_01_ERROR, errno); 617 exit(1); 618 } 619 sputl(nsyms, buf2); 620 bptr = buf2 + 4; 621 622 for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) { 623 if (!j) { 624 j = SYMCHUNK; 625 ptr = (ARFILEP *)*ptr; 626 } 627 sputl((*ptr)->ar_offset, bptr); 628 bptr += 4; 629 } 630 (void) memcpy(dst, buf1, sizeof (struct ar_hdr)); 631 dst += sizeof (struct ar_hdr); 632 sum += sizeof (struct ar_hdr); 633 634 (void) memcpy(dst, buf2, (nsyms + 1) * 4); 635 dst += (nsyms + 1)*4; 636 sum += (nsyms + 1)*4; 637 638 if (nsyms != 0) { 639 (void) memcpy(dst, str_base, (str_top - str_base)); 640 dst += str_top - str_base; 641 sum += str_top - str_base; 642 } else { 643 /* 644 * Writing a dummy string table. 645 */ 646 int i; 647 for (i = 0; i < 4; i++) 648 *dst++ = 0; 649 sum += 4; 650 } 651 652 /* 653 * The first member file is an ELF object. We need to make 654 * sure it will be placed at the PADSZ byte boundary. 655 */ 656 if (pad_symtab) { 657 int i; 658 for (i = 0; i < pad_symtab; i++) 659 *dst++ = 0; 660 sum += pad_symtab; 661 } 662 663 free(buf2); 664 return (sum); 665 } 666 667 static void 668 savename(char *symbol) 669 { 670 static int str_length = BUFSIZ * 5; 671 char *p, *s; 672 unsigned int i; 673 int diff; 674 675 diff = 0; 676 if (str_base == (char *)0) { 677 /* no space allocated yet */ 678 if ((str_base = malloc((unsigned)str_length)) == NULL) { 679 error_message(MALLOC_ERROR, 680 PLAIN_ERROR, (char *)0); 681 exit(1); 682 } 683 str_top = str_base; 684 } 685 686 p = str_top; 687 str_top += strlen(symbol) + 1; 688 689 if (str_top > str_base + str_length) { 690 char *old_base = str_base; 691 692 do 693 str_length += BUFSIZ * 2; 694 while (str_top > str_base + str_length) 695 ; 696 if ((str_base = (char *)realloc(str_base, str_length)) == 697 NULL) { 698 error_message(MALLOC_ERROR, 699 PLAIN_ERROR, (char *)0); 700 exit(1); 701 } 702 /* 703 * Re-adjust other pointers 704 */ 705 diff = str_base - old_base; 706 p += diff; 707 } 708 for (i = 0, s = symbol; i < strlen(symbol) && *s != '\0'; i++) { 709 *p++ = *s++; 710 } 711 *p++ = '\0'; 712 str_top = p; 713 } 714 715 static void 716 savelongname(ARFILE *fptr, char *ptr_index) 717 { 718 static int str_length = BUFSIZ * 5; 719 char *p, *s; 720 unsigned int i; 721 int diff; 722 static int bytes_used; 723 int index; 724 char ptr_index1[SNAME-1]; 725 726 diff = 0; 727 if (str_base1 == (char *)0) { 728 /* no space allocated yet */ 729 if ((str_base1 = malloc((unsigned)str_length)) 730 == NULL) { 731 error_message(MALLOC_ERROR, 732 PLAIN_ERROR, (char *)0); 733 exit(1); 734 } 735 str_top1 = str_base1; 736 } 737 738 p = str_top1; 739 str_top1 += strlen(fptr->ar_longname) + 2; 740 741 index = bytes_used; 742 (void) sprintf(ptr_index1, "%d", index); /* holds digits */ 743 (void) sprintf(ptr_index, FNFORMAT, SYMDIRNAME); 744 ptr_index[1] = '\0'; 745 (void) strcat(ptr_index, ptr_index1); 746 (void) strcpy(fptr->ar_name, ptr_index); 747 bytes_used += strlen(fptr->ar_longname) + 2; 748 749 if (str_top1 > str_base1 + str_length) { 750 char *old_base = str_base1; 751 752 do 753 str_length += BUFSIZ * 2; 754 while (str_top1 > str_base1 + str_length) 755 ; 756 if ((str_base1 = (char *)realloc(str_base1, str_length)) 757 == NULL) { 758 error_message(MALLOC_ERROR, 759 PLAIN_ERROR, (char *)0); 760 exit(1); 761 } 762 /* 763 * Re-adjust other pointers 764 */ 765 diff = str_base1 - old_base; 766 p += diff; 767 } 768 for (i = 0, s = fptr->ar_longname; 769 i < strlen(fptr->ar_longname) && *s != '\0'; i++) { 770 *p++ = *s++; 771 } 772 *p++ = '/'; 773 *p++ = '\n'; 774 str_top1 = p; 775 } 776 777 char * 778 writefile(Cmd_info *cmd_info) 779 { 780 ARFILE * fptr; 781 ARFILEP *symlist = 0; 782 int i; 783 int longnames = 0; 784 long long_tab_size = 0; 785 long nsyms; 786 int new_archive = 0; 787 char *name = cmd_info->arnam; 788 int arsize; 789 char *dst; 790 char *tmp_dst; 791 int nfd; 792 int found_obj = 0; 793 794 long_tab_size = mklong_tab(&longnames); 795 nsyms = mksymtab(&symlist, &found_obj); 796 797 for (i = 0; signum[i]; i++) 798 /* started writing, cannot interrupt */ 799 (void) signal(signum[i], SIG_IGN); 800 801 802 /* Is this a new archive? */ 803 if ((access(cmd_info->arnam, 0) < 0) && (errno == ENOENT)) { 804 new_archive = 1; 805 if (!opt_FLAG(cmd_info, c_FLAG)) { 806 error_message(BER_MES_CREATE_ERROR, 807 PLAIN_ERROR, (char *)0, cmd_info->arnam); 808 } 809 } else 810 new_archive = 0; 811 812 /* 813 * Calculate the size of the new archive 814 */ 815 arsize = sizeofnewarchive(nsyms, longnames); 816 817 /* 818 * Dummy symtab ? 819 */ 820 if (nsyms == 0 && found_obj != 0) 821 /* 822 * 4 + 4 = First 4 bytes to keep the number of symbols. 823 * The second 4 bytes for string table. 824 */ 825 arsize += sizeof (struct ar_hdr) + 4 + 4; 826 827 if (arsize > AR_MAX_BYTES_IN_MEM) { 828 tmp_dst = dst = NULL; 829 } else { 830 tmp_dst = dst = malloc(arsize); 831 } 832 if (dst == NULL) { 833 return writelargefile(cmd_info, long_tab_size, 834 longnames, symlist, nsyms, found_obj, new_archive); 835 } 836 837 (void) memcpy(tmp_dst, ARMAG, SARMAG); 838 tmp_dst += SARMAG; 839 840 if (nsyms || found_obj != 0) { 841 int diff; 842 diff = writesymtab(tmp_dst, nsyms, symlist); 843 tmp_dst += diff; 844 } 845 846 if (longnames) { 847 (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 848 (unsigned)0, (unsigned)0, (unsigned)0, 849 (long)long_tab_size, ARFMAG); 850 tmp_dst += sizeof (struct ar_hdr); 851 (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 852 tmp_dst += str_top1 - str_base1; 853 } 854 for (fptr = listhead; fptr; fptr = fptr->ar_next) { 855 856 /* 857 * NOTE: 858 * The mem_header->ar_name[] is set to a NULL string 859 * if the archive member header has some error. 860 * (See elf_getarhdr() man page.) 861 * It is set to NULL for example, the ar command reads 862 * the archive files created by SunOS 4.1 system. 863 * See c block comment in cmd.c, "Incompatible Archive Header". 864 */ 865 if (fptr->ar_name[0] == 0) { 866 fptr->ar_longname = fptr->ar_rawname; 867 (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 868 } 869 if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 870 (void) sprintf(tmp_dst, FNFORMAT, 871 trimslash(fptr->ar_longname)); 872 else 873 (void) sprintf(tmp_dst, FNFORMAT, fptr->ar_name); 874 (void) sprintf(tmp_dst+16, TLFORMAT, fptr->ar_date, 875 (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 876 (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 877 ARFMAG); 878 879 tmp_dst += sizeof (struct ar_hdr); 880 881 if (!(fptr->ar_flag & F_MALLOCED) && 882 !(fptr->ar_flag & F_MMAPED) && 883 !(fptr->ar_flag & F_ELFRAW)) { 884 /* file was not read in fptr->ar_contents during 'cmd' */ 885 /* do it now */ 886 FILE *f; 887 f = fopen(fptr->ar_pathname, "r"); 888 if (f == NULL) { 889 error_message(SYS_OPEN_ERROR, 890 SYSTEM_ERROR, strerror(errno), 891 fptr->ar_longname); 892 exit(1); 893 } else { 894 if (fread(tmp_dst, sizeof (char), 895 fptr->ar_size, f) != fptr->ar_size) { 896 error_message(SYS_READ_ERROR, 897 SYSTEM_ERROR, strerror(errno), 898 fptr->ar_longname); 899 exit(1); 900 } 901 } 902 (void) fclose(f); 903 } else { 904 (void) memcpy(tmp_dst, fptr->ar_contents, 905 fptr->ar_size); 906 if (fptr->ar_flag & F_MALLOCED) { 907 (void) free(fptr->ar_contents); 908 fptr->ar_flag &= ~(F_MALLOCED); 909 } 910 } 911 tmp_dst += fptr->ar_size; 912 913 if (fptr->ar_size & 0x1) { 914 (void) memcpy(tmp_dst, "\n", 1); 915 tmp_dst++; 916 } 917 918 if (fptr->ar_padding) { 919 int i = fptr->ar_padding; 920 while (i) { 921 *tmp_dst++ = '\n'; 922 --i; 923 } 924 } 925 } 926 927 /* 928 * All preparation for writing is done. 929 */ 930 (void) elf_end(cmd_info->arf); 931 (void) close(cmd_info->afd); 932 933 /* 934 * Write out to the file 935 */ 936 if (new_archive) { 937 /* 938 * create a new file 939 */ 940 nfd = creat(name, 0666); 941 if (nfd == -1) { 942 error_message(SYS_CREATE_01_ERROR, 943 SYSTEM_ERROR, strerror(errno), name); 944 exit(1); 945 } 946 } else { 947 /* 948 * Open the new file 949 */ 950 nfd = open(name, O_RDWR|O_TRUNC); 951 if (nfd == -1) { 952 error_message(SYS_WRITE_02_ERROR, 953 SYSTEM_ERROR, strerror(errno), name); 954 exit(1); 955 } 956 } 957 #ifndef XPG4 958 if (opt_FLAG(cmd_info, v_FLAG)) { 959 error_message(BER_MES_WRITE_ERROR, 960 PLAIN_ERROR, (char *)0, cmd_info->arnam); 961 } 962 #endif 963 if (write(nfd, dst, arsize) != arsize) { 964 error_message(SYS_WRITE_04_ERROR, 965 SYSTEM_ERROR, strerror(errno), name); 966 if (!new_archive) 967 error_message(WARN_USER_ERROR, 968 PLAIN_ERROR, (char *)0); 969 exit(2); 970 } 971 return (dst); 972 } 973 974 static long 975 mklong_tab(int *longnames) 976 { 977 ARFILE *fptr; 978 char ptr_index[SNAME+1]; 979 long ret = 0; 980 981 for (fptr = listhead; fptr; fptr = fptr->ar_next) { 982 if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) { 983 (*longnames)++; 984 savelongname(fptr, ptr_index); 985 (void) strcpy(fptr->ar_name, ptr_index); 986 } 987 } 988 if (*longnames) { 989 /* round up table that keeps the long filenames */ 990 while ((str_top1 - str_base1) & 03) 991 *str_top1++ = '\n'; 992 ret = sizeof (char) * (str_top1 - str_base1); 993 } 994 return (ret); 995 } 996 997 /* Put bytes in archive header in machine independent order. */ 998 999 static void 1000 sputl(long n, char *cp) 1001 { 1002 *cp++ = n >> 24; 1003 *cp++ = n >> 16; 1004 *cp++ = n >> 8; 1005 1006 *cp++ = n & 255; 1007 } 1008 1009 static int 1010 search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, 1011 long *nsyms, ARFILEP **symlist, int *num_errs) 1012 { 1013 Elf_Data *str_data, *sym_data; /* string table, symbol table */ 1014 Elf_Scn *str_scn; 1015 GElf_Sxword no_of_symbols; 1016 GElf_Shdr shdr; 1017 int counter; 1018 int str_shtype; 1019 char *symname; 1020 static ARFILEP *sym_ptr = 0; 1021 static ARFILEP *nextsym = NULL; 1022 static int syms_left = 0; 1023 char *fname = fptr->ar_pathname; 1024 1025 (void) gelf_getshdr(scn, &shdr); 1026 str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */ 1027 if (str_scn == NULL) { 1028 if (fname != NULL) 1029 error_message(ELF_GETDATA_01_ERROR, 1030 LIBELF_ERROR, elf_errmsg(-1), 1031 fname); 1032 else 1033 error_message(ELF_GETDATA_02_ERROR, 1034 LIBELF_ERROR, elf_errmsg(-1)); 1035 (*num_errs)++; 1036 return (-1); 1037 } 1038 1039 no_of_symbols = shdr.sh_size / shdr.sh_entsize; 1040 if (no_of_symbols == -1) { 1041 error_message(SYMTAB_01_ERROR, 1042 PLAIN_ERROR, (char *)0); 1043 return (-1); 1044 } 1045 1046 (void) gelf_getshdr(str_scn, &shdr); 1047 str_shtype = shdr.sh_type; 1048 if (str_shtype == -1) { 1049 if (fname != NULL) 1050 error_message(ELF_GETDATA_01_ERROR, 1051 LIBELF_ERROR, elf_errmsg(-1), fname); 1052 else 1053 error_message(ELF_GETDATA_02_ERROR, 1054 LIBELF_ERROR, elf_errmsg(-1)); 1055 (*num_errs)++; 1056 return (-1); 1057 } 1058 1059 /* This test must happen before testing the string table. */ 1060 if (no_of_symbols == 1) 1061 return (0); /* no symbols; 0th symbol is the non-symbol */ 1062 1063 if (str_shtype != SHT_STRTAB) { 1064 if (fname != NULL) 1065 error_message(SYMTAB_02_ERROR, 1066 PLAIN_ERROR, (char *)0, 1067 fname); 1068 else 1069 error_message(SYMTAB_03_ERROR, 1070 PLAIN_ERROR, (char *)0); 1071 return (0); 1072 } 1073 str_data = 0; 1074 if ((str_data = elf_getdata(str_scn, str_data)) == 0) { 1075 if (fname != NULL) 1076 error_message(SYMTAB_04_ERROR, 1077 PLAIN_ERROR, (char *)0, 1078 fname); 1079 else 1080 error_message(SYMTAB_05_ERROR, 1081 PLAIN_ERROR, (char *)0); 1082 return (0); 1083 } 1084 if (str_data->d_size == 0) { 1085 if (fname != NULL) 1086 error_message(SYMTAB_06_ERROR, 1087 PLAIN_ERROR, (char *)0, 1088 fname); 1089 else 1090 error_message(SYMTAB_07_ERROR, 1091 PLAIN_ERROR, (char *)0); 1092 return (0); 1093 } 1094 sym_data = 0; 1095 if ((sym_data = elf_getdata(scn, sym_data)) == NULL) { 1096 if (fname != NULL) 1097 error_message(ELF_01_ERROR, 1098 LIBELF_ERROR, elf_errmsg(-1), 1099 fname, elf_errmsg(-1)); 1100 else 1101 error_message(ELF_02_ERROR, 1102 LIBELF_ERROR, elf_errmsg(-1), 1103 elf_errmsg(-1)); 1104 return (0); 1105 } 1106 1107 /* start at 1, first symbol entry is ignored */ 1108 for (counter = 1; counter < no_of_symbols; counter++) { 1109 GElf_Sym sym; 1110 (void) gelf_getsym(sym_data, counter, &sym); 1111 1112 symname = (char *)(str_data->d_buf) + sym.st_name; 1113 1114 if (((GELF_ST_BIND(sym.st_info) == STB_GLOBAL) || 1115 (GELF_ST_BIND(sym.st_info) == STB_WEAK)) && 1116 (sym.st_shndx != SHN_UNDEF)) { 1117 if (!syms_left) { 1118 sym_ptr = malloc((SYMCHUNK+1) 1119 * sizeof (ARFILEP)); 1120 if (sym_ptr == NULL) { 1121 error_message(MALLOC_ERROR, 1122 PLAIN_ERROR, (char *)0); 1123 exit(1); 1124 } 1125 syms_left = SYMCHUNK; 1126 if (nextsym) 1127 *nextsym = (ARFILEP)sym_ptr; 1128 else 1129 *symlist = sym_ptr; 1130 nextsym = sym_ptr; 1131 } 1132 sym_ptr = nextsym; 1133 nextsym++; 1134 syms_left--; 1135 (*nsyms)++; 1136 *sym_ptr = fptr; 1137 savename(symname); /* put name in the archiver's */ 1138 /* symbol table string table */ 1139 } 1140 } 1141 return (0); 1142 } 1143 1144 /* 1145 * Get the output file size 1146 */ 1147 static int 1148 sizeofmembers(int psum) 1149 { 1150 int sum = 0; 1151 ARFILE *fptr; 1152 int hdrsize = sizeof (struct ar_hdr); 1153 1154 for (fptr = listhead; fptr; fptr = fptr->ar_next) { 1155 fptr->ar_offset = psum + sum; 1156 sum += fptr->ar_size; 1157 if (fptr->ar_size & 01) 1158 sum++; 1159 sum += hdrsize; 1160 1161 /* 1162 * If the current item, and the next item are both ELF 1163 * objects, then add padding to current item so that the 1164 * next item will have PADSZ alignment. 1165 * 1166 * In any other case, set the padding to 0. If the 1167 * item comes from another archive, it may be carrying 1168 * a non-zero padding value from that archive that does 1169 * not apply to the one we are about to build. 1170 */ 1171 if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) && 1172 fptr->ar_next && 1173 (fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) { 1174 fptr->ar_padding = pad(psum + sum + hdrsize); 1175 sum += fptr->ar_padding; 1176 } else { 1177 fptr->ar_padding = 0; 1178 } 1179 } 1180 return (sum); 1181 } 1182 1183 static int 1184 sizeofnewarchiveheader(int nsyms, int longnames) 1185 { 1186 int sum = 0; 1187 1188 sum += SARMAG; 1189 1190 if (nsyms) { 1191 char *top = (char *)str_top; 1192 char *base = (char *)str_base; 1193 1194 while ((top - base) & 03) 1195 top++; 1196 sum += sizeof (struct ar_hdr); 1197 sum += (nsyms + 1) * 4; 1198 sum += top - base; 1199 } 1200 1201 if (longnames) { 1202 sum += sizeof (struct ar_hdr); 1203 sum += str_top1 - str_base1; 1204 } 1205 1206 /* 1207 * If the first member file is an ELF object, 1208 * we have to ensure the member contents will align 1209 * on PADSZ byte boundary. 1210 */ 1211 if (listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64))) { 1212 pad_symtab = pad(sum + sizeof (struct ar_hdr)); 1213 sum += pad_symtab; 1214 } 1215 1216 return (sum); 1217 } 1218 1219 static int 1220 sizeofnewarchive(int nsyms, int longnames) 1221 { 1222 int sum; 1223 1224 sum = sizeofnewarchiveheader(nsyms, longnames); 1225 sum += sizeofmembers(sum); 1226 return (sum); 1227 } 1228 1229 static void 1230 arwrite(char *name, int nfd, char *dst, int size) { 1231 if (write(nfd, dst, size) != size) { 1232 error_message(SYS_WRITE_04_ERROR, 1233 SYSTEM_ERROR, strerror(errno), name); 1234 exit(2); 1235 } 1236 } 1237 1238 static char * 1239 make_tmpname(char *filename) { 1240 static char template[] = "arXXXXXX"; 1241 char *tmpname; 1242 char *slash = strrchr(filename, '/'); 1243 1244 if (slash != (char *)NULL) { 1245 char c; 1246 1247 c = *slash; 1248 *slash = 0; 1249 tmpname = (char *)malloc(strlen(filename) + 1250 sizeof (template) + 2); 1251 (void) strcpy(tmpname, filename); 1252 (void) strcat(tmpname, "/"); 1253 (void) strcat(tmpname, template); 1254 (void) mktemp(tmpname); 1255 *slash = c; 1256 } else { 1257 tmpname = malloc(sizeof (template)); 1258 (void) strcpy(tmpname, template); 1259 (void) mktemp(tmpname); 1260 } 1261 return (tmpname); 1262 } 1263 1264 static int 1265 ar_copy(char *from, char *to) { 1266 int fromfd, tofd, nread; 1267 int saved; 1268 char buf[8192]; 1269 1270 fromfd = open(from, O_RDONLY); 1271 if (fromfd < 0) 1272 return (-1); 1273 tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 0777); 1274 if (tofd < 0) { 1275 saved = errno; 1276 (void) close(fromfd); 1277 errno = saved; 1278 return (-1); 1279 } 1280 while ((nread = read(fromfd, buf, sizeof (buf))) > 0) { 1281 if (write(tofd, buf, nread) != nread) { 1282 saved = errno; 1283 (void) close(fromfd); 1284 (void) close(tofd); 1285 errno = saved; 1286 return (-1); 1287 } 1288 } 1289 saved = errno; 1290 (void) close(fromfd); 1291 (void) close(tofd); 1292 if (nread < 0) { 1293 errno = saved; 1294 return (-1); 1295 } 1296 return (0); 1297 } 1298 1299 static int 1300 ar_rename(char *from, char *to) 1301 { 1302 int exists; 1303 struct stat s; 1304 int ret = 0; 1305 1306 exists = lstat(to, &s) == 0; 1307 1308 if (! exists || (!S_ISLNK(s.st_mode) && s.st_nlink == 1)) { 1309 ret = rename(from, to); 1310 if (ret == 0) { 1311 if (exists) { 1312 (void) chmod(to, s.st_mode & 0777); 1313 if (chown(to, s.st_uid, s.st_gid) >= 0) 1314 (void) chmod(to, s.st_mode & 07777); 1315 } 1316 } else { 1317 (void) unlink(from); 1318 } 1319 } else { 1320 ret = ar_copy(from, to); 1321 (void) unlink(from); 1322 } 1323 return (ret); 1324 } 1325 1326 static char * 1327 writelargefile(Cmd_info *cmd_info, long long_tab_size, int longnames, 1328 ARFILEP *symlist, long nsyms, int found_obj, int new_archive) 1329 { 1330 ARFILE * fptr; 1331 char *name = cmd_info->arnam; 1332 int arsize; 1333 char *dst; 1334 char *tmp_dst; 1335 int nfd; 1336 char *new_name; 1337 FILE *f; 1338 struct stat stbuf; 1339 1340 new_name = make_tmpname(name); 1341 1342 if (new_archive) { 1343 nfd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 1344 if (nfd == -1) { 1345 error_message(SYS_CREATE_01_ERROR, 1346 SYSTEM_ERROR, strerror(errno), name); 1347 exit(1); 1348 } 1349 } else { 1350 nfd = open(new_name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 1351 if (nfd == -1) { 1352 error_message(SYS_WRITE_02_ERROR, 1353 SYSTEM_ERROR, strerror(errno), name); 1354 exit(1); 1355 } 1356 } 1357 1358 arsize = sizeofnewarchiveheader(nsyms, longnames); 1359 if (nsyms == 0 && found_obj != 0) 1360 arsize += sizeof (struct ar_hdr) + 4 + 4; 1361 if (arsize < 2048) { 1362 arsize = 2048; 1363 } 1364 dst = tmp_dst = (char *)malloc(arsize); 1365 (void) memcpy(tmp_dst, ARMAG, SARMAG); 1366 tmp_dst += SARMAG; 1367 1368 if (nsyms || found_obj != 0) { 1369 int diff; 1370 diff = writesymtab(tmp_dst, nsyms, symlist); 1371 tmp_dst += diff; 1372 } 1373 1374 if (longnames) { 1375 (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 1376 (unsigned)0, (unsigned)0, (unsigned)0, 1377 (long)long_tab_size, ARFMAG); 1378 tmp_dst += sizeof (struct ar_hdr); 1379 (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 1380 tmp_dst += str_top1 - str_base1; 1381 } 1382 #ifndef XPG4 1383 if (opt_FLAG(cmd_info, v_FLAG)) { 1384 error_message(BER_MES_WRITE_ERROR, 1385 PLAIN_ERROR, (char *)0, 1386 cmd_info->arnam); 1387 } 1388 #endif 1389 arwrite(name, nfd, dst, (int)(tmp_dst - dst)); 1390 1391 for (fptr = listhead; fptr; fptr = fptr->ar_next) { 1392 if (fptr->ar_name[0] == 0) { 1393 fptr->ar_longname = fptr->ar_rawname; 1394 (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 1395 } 1396 if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 1397 (void) sprintf(dst, FNFORMAT, 1398 trimslash(fptr->ar_longname)); 1399 else 1400 (void) sprintf(dst, FNFORMAT, fptr->ar_name); 1401 (void) sprintf(dst+16, TLFORMAT, fptr->ar_date, 1402 (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 1403 (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 1404 ARFMAG); 1405 arwrite(name, nfd, dst, sizeof (struct ar_hdr)); 1406 1407 if (!(fptr->ar_flag & F_MALLOCED) && 1408 !(fptr->ar_flag & F_MMAPED) && 1409 !(fptr->ar_flag & F_ELFRAW)) { 1410 f = fopen(fptr->ar_pathname, "r"); 1411 if (stat(fptr->ar_pathname, &stbuf) < 0) { 1412 (void) fclose(f); 1413 f = NULL; 1414 } 1415 if (f == NULL) { 1416 error_message(SYS_OPEN_ERROR, 1417 SYSTEM_ERROR, strerror(errno), 1418 fptr->ar_longname); 1419 exit(1); 1420 } else { 1421 if ((fptr->ar_contents = (char *) 1422 malloc(ROUNDUP(stbuf.st_size))) == NULL) { 1423 error_message(MALLOC_ERROR, 1424 PLAIN_ERROR, (char *)0); 1425 exit(1); 1426 } 1427 if (fread(fptr->ar_contents, 1428 sizeof (char), 1429 stbuf.st_size, f) != stbuf.st_size) { 1430 error_message(SYS_READ_ERROR, 1431 SYSTEM_ERROR, strerror(errno), 1432 fptr->ar_longname); 1433 exit(1); 1434 } 1435 } 1436 arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 1437 (void) fclose(f); 1438 free(fptr->ar_contents); 1439 } else { 1440 arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 1441 if (fptr->ar_flag & F_MALLOCED) { 1442 (void) free(fptr->ar_contents); 1443 fptr->ar_flag &= ~(F_MALLOCED); 1444 } 1445 } 1446 1447 if (fptr->ar_size & 0x1) { 1448 arwrite(name, nfd, "\n", 1); 1449 } 1450 1451 if (fptr->ar_padding) { 1452 int i = fptr->ar_padding; 1453 while (i) { 1454 arwrite(name, nfd, "\n", 1); 1455 --i; 1456 } 1457 } 1458 } 1459 1460 /* 1461 * All preparation for writing is done. 1462 */ 1463 (void) elf_end(cmd_info->arf); 1464 (void) close(cmd_info->afd); 1465 1466 if (!new_archive) { 1467 (void) ar_rename(new_name, name); 1468 } 1469 1470 return (dst); 1471 } 1472