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