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