17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59d6538abSab * Common Development and Distribution License (the "License"). 69d6538abSab * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*d2d5cf7cSAli Bahrami * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 287c478bd9Sstevel@tonic-gate * All Rights Reserved 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "gelf.h" 337c478bd9Sstevel@tonic-gate #include "inc.h" 347c478bd9Sstevel@tonic-gate #include "extern.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate static char *str_base; /* start of string table for names */ 377c478bd9Sstevel@tonic-gate static char *str_top; /* pointer to next available location */ 387c478bd9Sstevel@tonic-gate static char *str_base1, *str_top1; 399d6538abSab static int pad_symtab; /* # of bytes by which to pad symbol table */ 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate 429d6538abSab /* 439d6538abSab * The ar file format requires objects to be padded to an even size. 449d6538abSab * We do that, but it turns out to be beneficial to go farther. 459d6538abSab * 469d6538abSab * ld(1) accesses archives by mmapping them into memory. If the mapped 479d6538abSab * objects have the proper alignment, we can access them directly. If the 48*d2d5cf7cSAli Bahrami * alignment is wrong, libelf "slides" them so that they are also accessible. 499d6538abSab * This is expensive in time (to copy memory) and space (it causes swap 509d6538abSab * to be allocated by the system to back the now-modified pages). Hence, we 519d6538abSab * really want to ensure that the alignment is right. 529d6538abSab * 539d6538abSab * We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects 549d6538abSab * at 8-byte. More recently, an elf section type has appeared that has 559d6538abSab * 8-byte alignment requirements (SUNW_move) even in 32-bit objects. So, 569d6538abSab * the current strategy is to align all objects to 8-bytes. 579d6538abSab * 589d6538abSab * There are two important things to consider when setting this value: 599d6538abSab * 1) If a new elf section that ld(1) accesses in memory appears 609d6538abSab * with a greater than 8-byte alignment requirement, this value 619d6538abSab * will need to be raised. Or, alternatively, the entire approach may 629d6538abSab * need reconsideration. 639d6538abSab * 2) The size of this padding must be smaller than the size of the 649d6538abSab * smallest possible ELF section. Otherwise, the logic contained 659d6538abSab * in recover_padding() can be tricked. 669d6538abSab */ 679d6538abSab #define PADSZ 8 689d6538abSab 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Function Prototypes 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate static long mklong_tab(int *); 737c478bd9Sstevel@tonic-gate static char *trimslash(char *s); 747c478bd9Sstevel@tonic-gate 75*d2d5cf7cSAli Bahrami static long mksymtab(ARFILEP **, int *); 767c478bd9Sstevel@tonic-gate static int writesymtab(char *, long, ARFILEP *); 777c478bd9Sstevel@tonic-gate static void savename(char *); 787c478bd9Sstevel@tonic-gate static void savelongname(ARFILE *, char *); 797c478bd9Sstevel@tonic-gate static void sputl(long, char *); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate static char *writelargefile(Cmd_info *cmd_info, long long_tab_size, 827c478bd9Sstevel@tonic-gate int longnames, ARFILEP *symlist, long nsyms, int found_obj, 837c478bd9Sstevel@tonic-gate int new_archive); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static int sizeofmembers(); 867c478bd9Sstevel@tonic-gate static int sizeofnewarchive(int, int); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static int search_sym_tab(ARFILE *, Elf *, Elf_Scn *, 897c478bd9Sstevel@tonic-gate long *, ARFILEP **, int *); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate int 937c478bd9Sstevel@tonic-gate getaf(Cmd_info *cmd_info) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 967c478bd9Sstevel@tonic-gate int fd; 977c478bd9Sstevel@tonic-gate char *arnam = cmd_info->arnam; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if (elf_version(EV_CURRENT) == EV_NONE) { 1007c478bd9Sstevel@tonic-gate error_message(ELF_VERSION_ERROR, 101*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 1027c478bd9Sstevel@tonic-gate exit(1); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) { 1067c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 1077c478bd9Sstevel@tonic-gate /* archive does not exist yet, may have to create one */ 1087c478bd9Sstevel@tonic-gate return (fd); 1097c478bd9Sstevel@tonic-gate } else { 1107c478bd9Sstevel@tonic-gate /* problem other than "does not exist" */ 1117c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 112*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), arnam); 1137c478bd9Sstevel@tonic-gate exit(1); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate cmd = ELF_C_READ; 1187c478bd9Sstevel@tonic-gate cmd_info->arf = elf_begin(fd, cmd, (Elf *)0); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if (elf_kind(cmd_info->arf) != ELF_K_AR) { 1217c478bd9Sstevel@tonic-gate error_message(NOT_ARCHIVE_ERROR, 122*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, arnam); 1237c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) 124*d2d5cf7cSAli Bahrami error_message(USAGE_06_ERROR, 125*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, cmd_info->ponam); 1267c478bd9Sstevel@tonic-gate exit(1); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate return (fd); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 13130a4e2aaSab /* 1329d6538abSab * Given a size, return the number of bytes required to round it 1339d6538abSab * up to the next PADSZ boundary. 1349d6538abSab */ 1359d6538abSab static int 1369d6538abSab pad(int n) 1379d6538abSab { 1389d6538abSab int r; 1399d6538abSab 1409d6538abSab r = n % PADSZ; 1419d6538abSab if (r) 1429d6538abSab r = PADSZ - r; 1439d6538abSab 1449d6538abSab return (r); 1459d6538abSab } 1469d6538abSab 1479d6538abSab /* 1489d6538abSab * If the current archive item is an object, then ar(1) may have added 1499d6538abSab * newline padding at the end in order to bring the following object 1509d6538abSab * into PADSZ alignment within the file. This padding cannot be 1519d6538abSab * distinguished from data using the information kept in the ar headers. 1529d6538abSab * This routine examines the objects, using knowledge of 15330a4e2aaSab * ELF and how our tools lay out objects to determine whether padding was 15430a4e2aaSab * added to an archive item. If so, it adjusts the st_size and 15530a4e2aaSab * st_padding fields of the file argument to reflect it. 15630a4e2aaSab */ 15730a4e2aaSab static void 15830a4e2aaSab recover_padding(Elf *elf, ARFILE *file) 15930a4e2aaSab { 16030a4e2aaSab long extent; 16130a4e2aaSab long padding; 16230a4e2aaSab GElf_Ehdr ehdr; 16330a4e2aaSab 16430a4e2aaSab 16530a4e2aaSab /* ar(1) only pads objects, so bail if not looking at one */ 16630a4e2aaSab if (gelf_getclass(elf) == ELFCLASSNONE) 16730a4e2aaSab return; 16830a4e2aaSab 16930a4e2aaSab /* 170*d2d5cf7cSAli Bahrami * libelf always puts the section header array at the end 17130a4e2aaSab * of the object, and all of our compilers and other tools 172*d2d5cf7cSAli Bahrami * use libelf or follow this convention. So, it is extremely 17330a4e2aaSab * likely that the section header array is at the end of this 17430a4e2aaSab * object: Find the address at the end of the array and compare 1759d6538abSab * it to the archive ar_size. If they are within PADSZ bytes, then 1769d6538abSab * we've found the end, and the difference is padding (We assume 1779d6538abSab * that no ELF section can fit into PADSZ bytes). 17830a4e2aaSab */ 17930a4e2aaSab extent = gelf_getehdr(elf, &ehdr) 180*d2d5cf7cSAli Bahrami ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0; 18130a4e2aaSab padding = file->ar_size - extent; 18230a4e2aaSab 1839d6538abSab if ((padding < 0) || (padding >= PADSZ)) { 18430a4e2aaSab /* 18530a4e2aaSab * The section header array is not at the end of the object. 18630a4e2aaSab * Traverse the section headers and look for the one with 18730a4e2aaSab * the highest used address. If this address is within 1889d6538abSab * PADSZ bytes of ar_size, then this is the end of the object. 18930a4e2aaSab */ 19030a4e2aaSab Elf_Scn *scn = 0; 19130a4e2aaSab 19230a4e2aaSab do { 19330a4e2aaSab scn = elf_nextscn(elf, scn); 19430a4e2aaSab if (scn) { 19530a4e2aaSab GElf_Shdr shdr; 19630a4e2aaSab 19730a4e2aaSab if (gelf_getshdr(scn, &shdr)) { 19830a4e2aaSab long t = shdr.sh_offset + shdr.sh_size; 19930a4e2aaSab if (t > extent) 20030a4e2aaSab extent = t; 20130a4e2aaSab } 20230a4e2aaSab } 20330a4e2aaSab } while (scn); 20430a4e2aaSab } 20530a4e2aaSab 20630a4e2aaSab /* 20730a4e2aaSab * Now, test the padding. We only act on padding in the range 2089d6538abSab * (0 < pad < PADSZ) (ar(1) will never add more than this). A pad 2099d6538abSab * of 0 requires no action, and any other size above (PADSZ-1) means 21030a4e2aaSab * that we don't understand the layout of this object, and as such, 21130a4e2aaSab * cannot do anything. 21230a4e2aaSab * 2139d6538abSab * If the padding is in range, and the raw data for the 21430a4e2aaSab * object is available, then we perform one additional sanity 21530a4e2aaSab * check before moving forward: ar(1) always pads with newline 21630a4e2aaSab * characters. If anything else is seen, it is not padding so 21730a4e2aaSab * leave it alone. 21830a4e2aaSab */ 2199d6538abSab if ((padding > 0) && (padding < PADSZ)) { 22030a4e2aaSab if (file->ar_contents) { 22130a4e2aaSab long cnt = padding; 22230a4e2aaSab char *p = file->ar_contents + extent; 22330a4e2aaSab 22430a4e2aaSab while (cnt--) { 22530a4e2aaSab if (*p++ != '\n') { /* No padding */ 22630a4e2aaSab padding = 0; 22730a4e2aaSab break; 22830a4e2aaSab } 22930a4e2aaSab } 23030a4e2aaSab } 23130a4e2aaSab 23230a4e2aaSab /* Remove the padding from the size */ 23330a4e2aaSab file->ar_size -= padding; 23430a4e2aaSab file->ar_padding = padding; 23530a4e2aaSab } 23630a4e2aaSab } 23730a4e2aaSab 2387c478bd9Sstevel@tonic-gate ARFILE * 2397c478bd9Sstevel@tonic-gate getfile(Cmd_info *cmd_info) 2407c478bd9Sstevel@tonic-gate { 2417c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header; 2427c478bd9Sstevel@tonic-gate ARFILE *file; 2437c478bd9Sstevel@tonic-gate char *tmp_rawname, *file_rawname; 2447c478bd9Sstevel@tonic-gate Elf *elf; 2457c478bd9Sstevel@tonic-gate char *arnam = cmd_info->arnam; 2467c478bd9Sstevel@tonic-gate int fd = cmd_info->afd; 2477c478bd9Sstevel@tonic-gate Elf *arf = cmd_info->arf; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (fd == -1) 2507c478bd9Sstevel@tonic-gate return (NULL); /* the archive doesn't exist */ 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 2537c478bd9Sstevel@tonic-gate return (NULL); /* the archive is empty or have hit the end */ 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) { 2567c478bd9Sstevel@tonic-gate error_message(ELF_MALARCHIVE_ERROR, 257*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 258*d2d5cf7cSAli Bahrami arnam, elf_getbase(elf)); 2597c478bd9Sstevel@tonic-gate exit(1); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* zip past special members like the symbol and string table members */ 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate while (strncmp(mem_header->ar_name, "/", 1) == 0 || 265*d2d5cf7cSAli Bahrami strncmp(mem_header->ar_name, "//", 2) == 0) { 2667c478bd9Sstevel@tonic-gate (void) elf_next(elf); 2677c478bd9Sstevel@tonic-gate (void) elf_end(elf); 2687c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 2697c478bd9Sstevel@tonic-gate return (NULL); 2707c478bd9Sstevel@tonic-gate /* the archive is empty or have hit the end */ 2717c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) { 2727c478bd9Sstevel@tonic-gate error_message(ELF_MALARCHIVE_ERROR, 273*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 274*d2d5cf7cSAli Bahrami arnam, elf_getbase(elf)); 2757c478bd9Sstevel@tonic-gate exit(0); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * NOTE: 2817c478bd9Sstevel@tonic-gate * The mem_header->ar_name[] is set to a NULL string 2827c478bd9Sstevel@tonic-gate * if the archive member header has some error. 2837c478bd9Sstevel@tonic-gate * (See elf_getarhdr() man page.) 2847c478bd9Sstevel@tonic-gate * It is set to NULL for example, the ar command reads 2857c478bd9Sstevel@tonic-gate * the archive files created by SunOS 4.1 system. 2867c478bd9Sstevel@tonic-gate * See c block comment in cmd.c, "Incompatible Archive Header". 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate file = newfile(); 2897c478bd9Sstevel@tonic-gate (void) strncpy(file->ar_name, mem_header->ar_name, SNAME); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate if ((file->ar_longname 2927c478bd9Sstevel@tonic-gate = malloc(strlen(mem_header->ar_name) + 1)) 2937c478bd9Sstevel@tonic-gate == NULL) { 2947c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 295*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 2967c478bd9Sstevel@tonic-gate exit(1); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate (void) strcpy(file->ar_longname, mem_header->ar_name); 2997c478bd9Sstevel@tonic-gate if ((file->ar_rawname 3007c478bd9Sstevel@tonic-gate = malloc(strlen(mem_header->ar_rawname) + 1)) 3017c478bd9Sstevel@tonic-gate == NULL) { 3027c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 303*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 3047c478bd9Sstevel@tonic-gate exit(1); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate tmp_rawname = mem_header->ar_rawname; 3077c478bd9Sstevel@tonic-gate file_rawname = file->ar_rawname; 3087c478bd9Sstevel@tonic-gate while (!isspace(*tmp_rawname) && 309*d2d5cf7cSAli Bahrami ((*file_rawname = *tmp_rawname) != '\0')) { 3107c478bd9Sstevel@tonic-gate file_rawname++; 3117c478bd9Sstevel@tonic-gate tmp_rawname++; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate if (!(*tmp_rawname == '\0')) 3147c478bd9Sstevel@tonic-gate *file_rawname = '\0'; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate file->ar_date = mem_header->ar_date; 3177c478bd9Sstevel@tonic-gate file->ar_uid = mem_header->ar_uid; 3187c478bd9Sstevel@tonic-gate file->ar_gid = mem_header->ar_gid; 3197c478bd9Sstevel@tonic-gate file->ar_mode = (unsigned long) mem_header->ar_mode; 3207c478bd9Sstevel@tonic-gate file->ar_size = mem_header->ar_size; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* reverse logic */ 3237c478bd9Sstevel@tonic-gate if (!(opt_FLAG(cmd_info, t_FLAG) && !opt_FLAG(cmd_info, s_FLAG))) { 3247c478bd9Sstevel@tonic-gate size_t ptr; 3257c478bd9Sstevel@tonic-gate file->ar_flag = F_ELFRAW; 3267c478bd9Sstevel@tonic-gate if ((file->ar_contents = elf_rawfile(elf, &ptr)) 3277c478bd9Sstevel@tonic-gate == NULL) { 3287c478bd9Sstevel@tonic-gate if (ptr != 0) { 3297c478bd9Sstevel@tonic-gate error_message(ELF_RAWFILE_ERROR, 330*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 3317c478bd9Sstevel@tonic-gate exit(1); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate file->ar_elf = elf; 3357c478bd9Sstevel@tonic-gate } 33630a4e2aaSab 33730a4e2aaSab recover_padding(elf, file); 33830a4e2aaSab 3397c478bd9Sstevel@tonic-gate (void) elf_next(elf); 3407c478bd9Sstevel@tonic-gate return (file); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate ARFILE * 344d6555420Smike_s newfile(void) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate static ARFILE *buffer = NULL; 3477c478bd9Sstevel@tonic-gate static int count = 0; 3487c478bd9Sstevel@tonic-gate ARFILE *fileptr; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (count == 0) { 3517c478bd9Sstevel@tonic-gate if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE))) 3527c478bd9Sstevel@tonic-gate == NULL) { 3537c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 354*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 3557c478bd9Sstevel@tonic-gate exit(1); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate count = CHUNK; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate count--; 3607c478bd9Sstevel@tonic-gate fileptr = buffer++; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (listhead) 3637c478bd9Sstevel@tonic-gate listend->ar_next = fileptr; 3647c478bd9Sstevel@tonic-gate else 3657c478bd9Sstevel@tonic-gate listhead = fileptr; 3667c478bd9Sstevel@tonic-gate listend = fileptr; 3677c478bd9Sstevel@tonic-gate return (fileptr); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate static char * 3717c478bd9Sstevel@tonic-gate trimslash(char *s) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate static char buf[SNAME]; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate (void) strncpy(buf, trim(s), SNAME - 2); 3767c478bd9Sstevel@tonic-gate buf[SNAME - 2] = '\0'; 3777c478bd9Sstevel@tonic-gate return (strcat(buf, "/")); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate char * 3817c478bd9Sstevel@tonic-gate trim(char *s) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate char *p1, *p2; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate for (p1 = s; *p1; p1++) 3867c478bd9Sstevel@tonic-gate ; 3877c478bd9Sstevel@tonic-gate while (p1 > s) { 3887c478bd9Sstevel@tonic-gate if (*--p1 != '/') 3897c478bd9Sstevel@tonic-gate break; 3907c478bd9Sstevel@tonic-gate *p1 = 0; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate p2 = s; 3937c478bd9Sstevel@tonic-gate for (p1 = s; *p1; p1++) 3947c478bd9Sstevel@tonic-gate if (*p1 == '/') 3957c478bd9Sstevel@tonic-gate p2 = p1 + 1; 3967c478bd9Sstevel@tonic-gate return (p2); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate static long 401*d2d5cf7cSAli Bahrami mksymtab(ARFILEP **symlist, int *found_obj) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate ARFILE *fptr; 4047c478bd9Sstevel@tonic-gate long mem_offset = 0; 4057c478bd9Sstevel@tonic-gate Elf *elf; 4067c478bd9Sstevel@tonic-gate Elf_Scn *scn; 4077c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 4087c478bd9Sstevel@tonic-gate int newfd; 4097c478bd9Sstevel@tonic-gate long nsyms = 0; 4107c478bd9Sstevel@tonic-gate int class = 0; 4117c478bd9Sstevel@tonic-gate Elf_Data *data; 4127c478bd9Sstevel@tonic-gate int num_errs = 0; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate newfd = 0; 4157c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 4167c478bd9Sstevel@tonic-gate /* determine if file is coming from the archive or not */ 4177c478bd9Sstevel@tonic-gate if ((fptr->ar_elf != 0) && (fptr->ar_pathname == NULL)) { 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * I can use the saved elf descriptor. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate elf = fptr->ar_elf; 4227c478bd9Sstevel@tonic-gate } else if ((fptr->ar_elf == 0) && 4237c478bd9Sstevel@tonic-gate (fptr->ar_pathname != NULL)) { 4247c478bd9Sstevel@tonic-gate if ((newfd = 4257c478bd9Sstevel@tonic-gate open(fptr->ar_pathname, O_RDONLY)) == -1) { 4267c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 427*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), 428*d2d5cf7cSAli Bahrami fptr->ar_pathname); 4297c478bd9Sstevel@tonic-gate num_errs++; 4307c478bd9Sstevel@tonic-gate continue; 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate if ((elf = elf_begin(newfd, 434*d2d5cf7cSAli Bahrami ELF_C_READ, (Elf *)0)) == 0) { 4357c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4367c478bd9Sstevel@tonic-gate error_message(ELF_BEGIN_02_ERROR, 437*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 438*d2d5cf7cSAli Bahrami fptr->ar_pathname); 4397c478bd9Sstevel@tonic-gate else 4407c478bd9Sstevel@tonic-gate error_message(ELF_BEGIN_03_ERROR, 441*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 4427c478bd9Sstevel@tonic-gate (void) close(newfd); 4437c478bd9Sstevel@tonic-gate newfd = 0; 4447c478bd9Sstevel@tonic-gate num_errs++; 4457c478bd9Sstevel@tonic-gate continue; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate if (elf_kind(elf) == ELF_K_AR) { 4487c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4497c478bd9Sstevel@tonic-gate error_message(ARCHIVE_IN_ARCHIVE_ERROR, 450*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 451*d2d5cf7cSAli Bahrami fptr->ar_pathname); 4527c478bd9Sstevel@tonic-gate else 4537c478bd9Sstevel@tonic-gate error_message(ARCHIVE_USAGE_ERROR, 454*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 4557c478bd9Sstevel@tonic-gate if (newfd) { 4567c478bd9Sstevel@tonic-gate (void) close(newfd); 4577c478bd9Sstevel@tonic-gate newfd = 0; 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4607c478bd9Sstevel@tonic-gate continue; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate } else { 4637c478bd9Sstevel@tonic-gate error_message(INTERNAL_01_ERROR, 464*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 4657c478bd9Sstevel@tonic-gate exit(1); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) != 0) { 4687c478bd9Sstevel@tonic-gate if ((class = gelf_getclass(elf)) == ELFCLASS64) { 4697c478bd9Sstevel@tonic-gate fptr->ar_flag |= F_CLASS64; 4707c478bd9Sstevel@tonic-gate } else if (class == ELFCLASS32) 4717c478bd9Sstevel@tonic-gate fptr->ar_flag |= F_CLASS32; 4727c478bd9Sstevel@tonic-gate scn = elf_getscn(elf, ehdr.e_shstrndx); 4737c478bd9Sstevel@tonic-gate if (scn == NULL) { 4747c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4757c478bd9Sstevel@tonic-gate error_message(ELF_GETSCN_01_ERROR, 476*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 477*d2d5cf7cSAli Bahrami fptr->ar_pathname); 4787c478bd9Sstevel@tonic-gate else 4797c478bd9Sstevel@tonic-gate error_message(ELF_GETSCN_02_ERROR, 480*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 4817c478bd9Sstevel@tonic-gate num_errs++; 4827c478bd9Sstevel@tonic-gate if (newfd) { 4837c478bd9Sstevel@tonic-gate (void) close(newfd); 4847c478bd9Sstevel@tonic-gate newfd = 0; 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4877c478bd9Sstevel@tonic-gate continue; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate data = 0; 4917c478bd9Sstevel@tonic-gate data = elf_getdata(scn, data); 4927c478bd9Sstevel@tonic-gate if (data == NULL) { 4937c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4947c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 495*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 496*d2d5cf7cSAli Bahrami fptr->ar_pathname); 4977c478bd9Sstevel@tonic-gate else 4987c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 499*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 5007c478bd9Sstevel@tonic-gate num_errs++; 5017c478bd9Sstevel@tonic-gate if (newfd) { 5027c478bd9Sstevel@tonic-gate (void) close(newfd); 5037c478bd9Sstevel@tonic-gate newfd = 0; 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5067c478bd9Sstevel@tonic-gate continue; 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate if (data->d_size == 0) { 5097c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 5107c478bd9Sstevel@tonic-gate error_message(W_ELF_NO_DATA_01_ERROR, 511*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 512*d2d5cf7cSAli Bahrami fptr->ar_pathname); 5137c478bd9Sstevel@tonic-gate else 5147c478bd9Sstevel@tonic-gate error_message(W_ELF_NO_DATA_02_ERROR, 515*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 5167c478bd9Sstevel@tonic-gate if (newfd) { 5177c478bd9Sstevel@tonic-gate (void) close(newfd); 5187c478bd9Sstevel@tonic-gate newfd = 0; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5217c478bd9Sstevel@tonic-gate num_errs++; 5227c478bd9Sstevel@tonic-gate continue; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* loop through sections to find symbol table */ 5267c478bd9Sstevel@tonic-gate scn = 0; 5277c478bd9Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) { 5287c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 5297c478bd9Sstevel@tonic-gate if (gelf_getshdr(scn, &shdr) == NULL) { 5307c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 5317c478bd9Sstevel@tonic-gate error_message( 532*d2d5cf7cSAli Bahrami ELF_GETDATA_01_ERROR, 533*d2d5cf7cSAli Bahrami LIBELF_ERROR, 534*d2d5cf7cSAli Bahrami elf_errmsg(-1), 535*d2d5cf7cSAli Bahrami fptr->ar_pathname); 5367c478bd9Sstevel@tonic-gate else 5377c478bd9Sstevel@tonic-gate error_message( 538*d2d5cf7cSAli Bahrami ELF_GETDATA_02_ERROR, 539*d2d5cf7cSAli Bahrami LIBELF_ERROR, 540*d2d5cf7cSAli Bahrami elf_errmsg(-1)); 5417c478bd9Sstevel@tonic-gate if (newfd) { 5427c478bd9Sstevel@tonic-gate (void) close(newfd); 5437c478bd9Sstevel@tonic-gate newfd = 0; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate num_errs++; 5467c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5477c478bd9Sstevel@tonic-gate continue; 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate *found_obj = 1; 5507c478bd9Sstevel@tonic-gate if (shdr.sh_type == SHT_SYMTAB) 551*d2d5cf7cSAli Bahrami if (search_sym_tab(fptr, elf, 552*d2d5cf7cSAli Bahrami scn, &nsyms, symlist, 553*d2d5cf7cSAli Bahrami &num_errs) == -1) { 554*d2d5cf7cSAli Bahrami if (newfd) { 555*d2d5cf7cSAli Bahrami (void) close(newfd); 556*d2d5cf7cSAli Bahrami newfd = 0; 557*d2d5cf7cSAli Bahrami } 558*d2d5cf7cSAli Bahrami continue; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate mem_offset += sizeof (struct ar_hdr) + fptr->ar_size; 5637c478bd9Sstevel@tonic-gate if (fptr->ar_size & 01) 5647c478bd9Sstevel@tonic-gate mem_offset++; 5657c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5667c478bd9Sstevel@tonic-gate if (newfd) { 5677c478bd9Sstevel@tonic-gate (void) close(newfd); 5687c478bd9Sstevel@tonic-gate newfd = 0; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate } /* for */ 5717c478bd9Sstevel@tonic-gate if (num_errs) 5727c478bd9Sstevel@tonic-gate exit(1); 5737c478bd9Sstevel@tonic-gate return (nsyms); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * This routine writes an archive symbol table for the 5787c478bd9Sstevel@tonic-gate * output archive file. The symbol table is built if 5797c478bd9Sstevel@tonic-gate * there was at least one object file specified. 5807c478bd9Sstevel@tonic-gate * In rare case, there could be no symbol. 5817c478bd9Sstevel@tonic-gate * In this case, str_top and str_base can not be used to 5827c478bd9Sstevel@tonic-gate * make the string table. So the routine adjust the size 5837c478bd9Sstevel@tonic-gate * and make a dummy string table. String table is needed 5847c478bd9Sstevel@tonic-gate * by elf_getarsym(). 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate static int 5877c478bd9Sstevel@tonic-gate writesymtab(char *dst, long nsyms, ARFILEP *symlist) 5887c478bd9Sstevel@tonic-gate { 5897c478bd9Sstevel@tonic-gate char buf1[sizeof (struct ar_hdr) + 1]; 5907c478bd9Sstevel@tonic-gate char *buf2, *bptr; 5917c478bd9Sstevel@tonic-gate int i, j; 5927c478bd9Sstevel@tonic-gate ARFILEP *ptr; 5937c478bd9Sstevel@tonic-gate long sym_tab_size = 0; 5947c478bd9Sstevel@tonic-gate int sum = 0; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * patch up archive pointers and write the symbol entries 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate while ((str_top - str_base) & 03) /* round up string table */ 6007c478bd9Sstevel@tonic-gate *str_top++ = '\0'; 6017c478bd9Sstevel@tonic-gate sym_tab_size = (nsyms +1) * 4 + sizeof (char) * (str_top - str_base); 6027c478bd9Sstevel@tonic-gate if (nsyms == 0) 6037c478bd9Sstevel@tonic-gate sym_tab_size += 4; 6047c478bd9Sstevel@tonic-gate sym_tab_size += pad_symtab; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate (void) sprintf(buf1, FORMAT, SYMDIRNAME, time(0), (unsigned)0, 607*d2d5cf7cSAli Bahrami (unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate if (strlen(buf1) != sizeof (struct ar_hdr)) { 6107c478bd9Sstevel@tonic-gate error_message(INTERNAL_02_ERROR); 6117c478bd9Sstevel@tonic-gate exit(1); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate if ((buf2 = malloc(4 * (nsyms + 1))) == NULL) { 6157c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR); 6167c478bd9Sstevel@tonic-gate error_message(DIAG_01_ERROR, errno); 6177c478bd9Sstevel@tonic-gate exit(1); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate sputl(nsyms, buf2); 6207c478bd9Sstevel@tonic-gate bptr = buf2 + 4; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) { 6237c478bd9Sstevel@tonic-gate if (!j) { 6247c478bd9Sstevel@tonic-gate j = SYMCHUNK; 6257c478bd9Sstevel@tonic-gate ptr = (ARFILEP *)*ptr; 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate sputl((*ptr)->ar_offset, bptr); 6287c478bd9Sstevel@tonic-gate bptr += 4; 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate (void) memcpy(dst, buf1, sizeof (struct ar_hdr)); 6317c478bd9Sstevel@tonic-gate dst += sizeof (struct ar_hdr); 6327c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate (void) memcpy(dst, buf2, (nsyms + 1) * 4); 6357c478bd9Sstevel@tonic-gate dst += (nsyms + 1)*4; 6367c478bd9Sstevel@tonic-gate sum += (nsyms + 1)*4; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (nsyms != 0) { 6397c478bd9Sstevel@tonic-gate (void) memcpy(dst, str_base, (str_top - str_base)); 6407c478bd9Sstevel@tonic-gate dst += str_top - str_base; 6417c478bd9Sstevel@tonic-gate sum += str_top - str_base; 6427c478bd9Sstevel@tonic-gate } else { 6437c478bd9Sstevel@tonic-gate /* 6447c478bd9Sstevel@tonic-gate * Writing a dummy string table. 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate int i; 6477c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) 6487c478bd9Sstevel@tonic-gate *dst++ = 0; 6497c478bd9Sstevel@tonic-gate sum += 4; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* 6539d6538abSab * The first member file is an ELF object. We need to make 6549d6538abSab * sure it will be placed at the PADSZ byte boundary. 6557c478bd9Sstevel@tonic-gate */ 6567c478bd9Sstevel@tonic-gate if (pad_symtab) { 6577c478bd9Sstevel@tonic-gate int i; 6589d6538abSab for (i = 0; i < pad_symtab; i++) 6597c478bd9Sstevel@tonic-gate *dst++ = 0; 6609d6538abSab sum += pad_symtab; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate free(buf2); 6647c478bd9Sstevel@tonic-gate return (sum); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate static void 6687c478bd9Sstevel@tonic-gate savename(char *symbol) 6697c478bd9Sstevel@tonic-gate { 6707c478bd9Sstevel@tonic-gate static int str_length = BUFSIZ * 5; 6717c478bd9Sstevel@tonic-gate char *p, *s; 6727c478bd9Sstevel@tonic-gate unsigned int i; 6737c478bd9Sstevel@tonic-gate int diff; 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate diff = 0; 6767c478bd9Sstevel@tonic-gate if (str_base == (char *)0) { 6777c478bd9Sstevel@tonic-gate /* no space allocated yet */ 678*d2d5cf7cSAli Bahrami if ((str_base = malloc((unsigned)str_length)) == NULL) { 6797c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 680*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 6817c478bd9Sstevel@tonic-gate exit(1); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate str_top = str_base; 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate p = str_top; 6877c478bd9Sstevel@tonic-gate str_top += strlen(symbol) + 1; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (str_top > str_base + str_length) { 6907c478bd9Sstevel@tonic-gate char *old_base = str_base; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate do 6937c478bd9Sstevel@tonic-gate str_length += BUFSIZ * 2; 694*d2d5cf7cSAli Bahrami while (str_top > str_base + str_length) 695*d2d5cf7cSAli Bahrami ; 6967c478bd9Sstevel@tonic-gate if ((str_base = (char *)realloc(str_base, str_length)) == 6977c478bd9Sstevel@tonic-gate NULL) { 6987c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 699*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 7007c478bd9Sstevel@tonic-gate exit(1); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Re-adjust other pointers 7047c478bd9Sstevel@tonic-gate */ 7057c478bd9Sstevel@tonic-gate diff = str_base - old_base; 7067c478bd9Sstevel@tonic-gate p += diff; 7077c478bd9Sstevel@tonic-gate } 708*d2d5cf7cSAli Bahrami for (i = 0, s = symbol; i < strlen(symbol) && *s != '\0'; i++) { 7097c478bd9Sstevel@tonic-gate *p++ = *s++; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate *p++ = '\0'; 7127c478bd9Sstevel@tonic-gate str_top = p; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate static void 7167c478bd9Sstevel@tonic-gate savelongname(ARFILE *fptr, char *ptr_index) 7177c478bd9Sstevel@tonic-gate { 7187c478bd9Sstevel@tonic-gate static int str_length = BUFSIZ * 5; 7197c478bd9Sstevel@tonic-gate char *p, *s; 7207c478bd9Sstevel@tonic-gate unsigned int i; 7217c478bd9Sstevel@tonic-gate int diff; 7227c478bd9Sstevel@tonic-gate static int bytes_used; 7237c478bd9Sstevel@tonic-gate int index; 7247c478bd9Sstevel@tonic-gate char ptr_index1[SNAME-1]; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate diff = 0; 7277c478bd9Sstevel@tonic-gate if (str_base1 == (char *)0) { 7287c478bd9Sstevel@tonic-gate /* no space allocated yet */ 7297c478bd9Sstevel@tonic-gate if ((str_base1 = malloc((unsigned)str_length)) 7307c478bd9Sstevel@tonic-gate == NULL) { 7317c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 732*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 7337c478bd9Sstevel@tonic-gate exit(1); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate str_top1 = str_base1; 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate p = str_top1; 7397c478bd9Sstevel@tonic-gate str_top1 += strlen(fptr->ar_longname) + 2; 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate index = bytes_used; 7427c478bd9Sstevel@tonic-gate (void) sprintf(ptr_index1, "%d", index); /* holds digits */ 7437c478bd9Sstevel@tonic-gate (void) sprintf(ptr_index, FNFORMAT, SYMDIRNAME); 7447c478bd9Sstevel@tonic-gate ptr_index[1] = '\0'; 7457c478bd9Sstevel@tonic-gate (void) strcat(ptr_index, ptr_index1); 7467c478bd9Sstevel@tonic-gate (void) strcpy(fptr->ar_name, ptr_index); 7477c478bd9Sstevel@tonic-gate bytes_used += strlen(fptr->ar_longname) + 2; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (str_top1 > str_base1 + str_length) { 7507c478bd9Sstevel@tonic-gate char *old_base = str_base1; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate do 7537c478bd9Sstevel@tonic-gate str_length += BUFSIZ * 2; 754*d2d5cf7cSAli Bahrami while (str_top1 > str_base1 + str_length) 755*d2d5cf7cSAli Bahrami ; 7567c478bd9Sstevel@tonic-gate if ((str_base1 = (char *)realloc(str_base1, str_length)) 7577c478bd9Sstevel@tonic-gate == NULL) { 7587c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 759*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 7607c478bd9Sstevel@tonic-gate exit(1); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * Re-adjust other pointers 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate diff = str_base1 - old_base; 7667c478bd9Sstevel@tonic-gate p += diff; 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate for (i = 0, s = fptr->ar_longname; 769*d2d5cf7cSAli Bahrami i < strlen(fptr->ar_longname) && *s != '\0'; i++) { 7707c478bd9Sstevel@tonic-gate *p++ = *s++; 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate *p++ = '/'; 7737c478bd9Sstevel@tonic-gate *p++ = '\n'; 7747c478bd9Sstevel@tonic-gate str_top1 = p; 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate char * 7787c478bd9Sstevel@tonic-gate writefile(Cmd_info *cmd_info) 7797c478bd9Sstevel@tonic-gate { 7807c478bd9Sstevel@tonic-gate ARFILE * fptr; 7817c478bd9Sstevel@tonic-gate ARFILEP *symlist = 0; 7827c478bd9Sstevel@tonic-gate int i; 7837c478bd9Sstevel@tonic-gate int longnames = 0; 7847c478bd9Sstevel@tonic-gate long long_tab_size = 0; 7857c478bd9Sstevel@tonic-gate long nsyms; 7867c478bd9Sstevel@tonic-gate int new_archive = 0; 7877c478bd9Sstevel@tonic-gate char *name = cmd_info->arnam; 7887c478bd9Sstevel@tonic-gate int arsize; 7897c478bd9Sstevel@tonic-gate char *dst; 7907c478bd9Sstevel@tonic-gate char *tmp_dst; 7917c478bd9Sstevel@tonic-gate int nfd; 7927c478bd9Sstevel@tonic-gate int found_obj = 0; 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate long_tab_size = mklong_tab(&longnames); 795*d2d5cf7cSAli Bahrami nsyms = mksymtab(&symlist, &found_obj); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate for (i = 0; signum[i]; i++) 7987c478bd9Sstevel@tonic-gate /* started writing, cannot interrupt */ 7997c478bd9Sstevel@tonic-gate (void) signal(signum[i], SIG_IGN); 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* Is this a new archive? */ 8037c478bd9Sstevel@tonic-gate if ((access(cmd_info->arnam, 0) < 0) && (errno == ENOENT)) { 804*d2d5cf7cSAli Bahrami new_archive = 1; 805*d2d5cf7cSAli Bahrami if (!opt_FLAG(cmd_info, c_FLAG)) { 806*d2d5cf7cSAli Bahrami error_message(BER_MES_CREATE_ERROR, 807*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, cmd_info->arnam); 808*d2d5cf7cSAli Bahrami } 809*d2d5cf7cSAli Bahrami } else 810*d2d5cf7cSAli Bahrami new_archive = 0; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Calculate the size of the new archive 8147c478bd9Sstevel@tonic-gate */ 8157c478bd9Sstevel@tonic-gate arsize = sizeofnewarchive(nsyms, longnames); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate /* 8187c478bd9Sstevel@tonic-gate * Dummy symtab ? 8197c478bd9Sstevel@tonic-gate */ 8207c478bd9Sstevel@tonic-gate if (nsyms == 0 && found_obj != 0) 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * 4 + 4 = First 4 bytes to keep the number of symbols. 8237c478bd9Sstevel@tonic-gate * The second 4 bytes for string table. 8247c478bd9Sstevel@tonic-gate */ 8257c478bd9Sstevel@tonic-gate arsize += sizeof (struct ar_hdr) + 4 + 4; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate if (arsize > AR_MAX_BYTES_IN_MEM) { 8287c478bd9Sstevel@tonic-gate tmp_dst = dst = NULL; 8297c478bd9Sstevel@tonic-gate } else { 8307c478bd9Sstevel@tonic-gate tmp_dst = dst = malloc(arsize); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate if (dst == NULL) { 8337c478bd9Sstevel@tonic-gate return writelargefile(cmd_info, long_tab_size, 834*d2d5cf7cSAli Bahrami longnames, symlist, nsyms, found_obj, new_archive); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, ARMAG, SARMAG); 8387c478bd9Sstevel@tonic-gate tmp_dst += SARMAG; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate if (nsyms || found_obj != 0) { 8417c478bd9Sstevel@tonic-gate int diff; 8427c478bd9Sstevel@tonic-gate diff = writesymtab(tmp_dst, nsyms, symlist); 8437c478bd9Sstevel@tonic-gate tmp_dst += diff; 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if (longnames) { 8477c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 848*d2d5cf7cSAli Bahrami (unsigned)0, (unsigned)0, (unsigned)0, 849*d2d5cf7cSAli Bahrami (long)long_tab_size, ARFMAG); 8507c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 8517c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 8527c478bd9Sstevel@tonic-gate tmp_dst += str_top1 - str_base1; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * NOTE: 8587c478bd9Sstevel@tonic-gate * The mem_header->ar_name[] is set to a NULL string 8597c478bd9Sstevel@tonic-gate * if the archive member header has some error. 8607c478bd9Sstevel@tonic-gate * (See elf_getarhdr() man page.) 8617c478bd9Sstevel@tonic-gate * It is set to NULL for example, the ar command reads 8627c478bd9Sstevel@tonic-gate * the archive files created by SunOS 4.1 system. 8637c478bd9Sstevel@tonic-gate * See c block comment in cmd.c, "Incompatible Archive Header". 8647c478bd9Sstevel@tonic-gate */ 8657c478bd9Sstevel@tonic-gate if (fptr->ar_name[0] == 0) { 8667c478bd9Sstevel@tonic-gate fptr->ar_longname = fptr->ar_rawname; 8677c478bd9Sstevel@tonic-gate (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 8707c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FNFORMAT, 871*d2d5cf7cSAli Bahrami trimslash(fptr->ar_longname)); 8727c478bd9Sstevel@tonic-gate else 8737c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FNFORMAT, fptr->ar_name); 8747c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst+16, TLFORMAT, fptr->ar_date, 8757c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 8767c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 8777c478bd9Sstevel@tonic-gate ARFMAG); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate if (!(fptr->ar_flag & F_MALLOCED) && 8827c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_MMAPED) && 8837c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_ELFRAW)) { 8847c478bd9Sstevel@tonic-gate /* file was not read in fptr->ar_contents during 'cmd' */ 8857c478bd9Sstevel@tonic-gate /* do it now */ 8867c478bd9Sstevel@tonic-gate FILE *f; 8877c478bd9Sstevel@tonic-gate f = fopen(fptr->ar_pathname, "r"); 8887c478bd9Sstevel@tonic-gate if (f == NULL) { 8897c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 8907c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 8917c478bd9Sstevel@tonic-gate fptr->ar_longname); 8927c478bd9Sstevel@tonic-gate exit(1); 8937c478bd9Sstevel@tonic-gate } else { 894*d2d5cf7cSAli Bahrami if (fread(tmp_dst, sizeof (char), 8957c478bd9Sstevel@tonic-gate fptr->ar_size, f) != fptr->ar_size) { 8967c478bd9Sstevel@tonic-gate error_message(SYS_READ_ERROR, 897*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), 898*d2d5cf7cSAli Bahrami fptr->ar_longname); 8997c478bd9Sstevel@tonic-gate exit(1); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate } 902d6555420Smike_s (void) fclose(f); 9037c478bd9Sstevel@tonic-gate } else { 9047c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, fptr->ar_contents, 905*d2d5cf7cSAli Bahrami fptr->ar_size); 9067c478bd9Sstevel@tonic-gate if (fptr->ar_flag & F_MALLOCED) { 9077c478bd9Sstevel@tonic-gate (void) free(fptr->ar_contents); 9087c478bd9Sstevel@tonic-gate fptr->ar_flag &= ~(F_MALLOCED); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate tmp_dst += fptr->ar_size; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (fptr->ar_size & 0x1) { 9147c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, "\n", 1); 9157c478bd9Sstevel@tonic-gate tmp_dst++; 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate if (fptr->ar_padding) { 9197c478bd9Sstevel@tonic-gate int i = fptr->ar_padding; 9207c478bd9Sstevel@tonic-gate while (i) { 9217c478bd9Sstevel@tonic-gate *tmp_dst++ = '\n'; 9227c478bd9Sstevel@tonic-gate --i; 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * All preparation for writing is done. 9297c478bd9Sstevel@tonic-gate */ 9307c478bd9Sstevel@tonic-gate (void) elf_end(cmd_info->arf); 9317c478bd9Sstevel@tonic-gate (void) close(cmd_info->afd); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * Write out to the file 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate if (new_archive) { 9377c478bd9Sstevel@tonic-gate /* 9387c478bd9Sstevel@tonic-gate * create a new file 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate nfd = creat(name, 0666); 9417c478bd9Sstevel@tonic-gate if (nfd == -1) { 9427c478bd9Sstevel@tonic-gate error_message(SYS_CREATE_01_ERROR, 943*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 9447c478bd9Sstevel@tonic-gate exit(1); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate } else { 9477c478bd9Sstevel@tonic-gate /* 9487c478bd9Sstevel@tonic-gate * Open the new file 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate nfd = open(name, O_RDWR|O_TRUNC); 9517c478bd9Sstevel@tonic-gate if (nfd == -1) { 9527c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_02_ERROR, 953*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 9547c478bd9Sstevel@tonic-gate exit(1); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate #ifndef XPG4 9587c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 959*d2d5cf7cSAli Bahrami error_message(BER_MES_WRITE_ERROR, 960*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, cmd_info->arnam); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate #endif 9637c478bd9Sstevel@tonic-gate if (write(nfd, dst, arsize) != arsize) { 9647c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_04_ERROR, 965*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 9667c478bd9Sstevel@tonic-gate if (!new_archive) 9677c478bd9Sstevel@tonic-gate error_message(WARN_USER_ERROR, 968*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 9697c478bd9Sstevel@tonic-gate exit(2); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate return (dst); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate static long 9757c478bd9Sstevel@tonic-gate mklong_tab(int *longnames) 9767c478bd9Sstevel@tonic-gate { 9777c478bd9Sstevel@tonic-gate ARFILE *fptr; 9787c478bd9Sstevel@tonic-gate char ptr_index[SNAME+1]; 9797c478bd9Sstevel@tonic-gate long ret = 0; 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 9827c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) { 9837c478bd9Sstevel@tonic-gate (*longnames)++; 9847c478bd9Sstevel@tonic-gate savelongname(fptr, ptr_index); 9857c478bd9Sstevel@tonic-gate (void) strcpy(fptr->ar_name, ptr_index); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate if (*longnames) { 9897c478bd9Sstevel@tonic-gate /* round up table that keeps the long filenames */ 9907c478bd9Sstevel@tonic-gate while ((str_top1 - str_base1) & 03) 9917c478bd9Sstevel@tonic-gate *str_top1++ = '\n'; 9927c478bd9Sstevel@tonic-gate ret = sizeof (char) * (str_top1 - str_base1); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate return (ret); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate /* Put bytes in archive header in machine independent order. */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate static void 10007c478bd9Sstevel@tonic-gate sputl(long n, char *cp) 10017c478bd9Sstevel@tonic-gate { 10027c478bd9Sstevel@tonic-gate *cp++ = n >> 24; 10037c478bd9Sstevel@tonic-gate *cp++ = n >> 16; 10047c478bd9Sstevel@tonic-gate *cp++ = n >> 8; 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate *cp++ = n & 255; 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate static int 10107c478bd9Sstevel@tonic-gate search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, 10117c478bd9Sstevel@tonic-gate long *nsyms, ARFILEP **symlist, int *num_errs) 10127c478bd9Sstevel@tonic-gate { 10137c478bd9Sstevel@tonic-gate Elf_Data *str_data, *sym_data; /* string table, symbol table */ 10147c478bd9Sstevel@tonic-gate Elf_Scn *str_scn; 10157c478bd9Sstevel@tonic-gate GElf_Sxword no_of_symbols; 10167c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 10177c478bd9Sstevel@tonic-gate int counter; 10187c478bd9Sstevel@tonic-gate int str_shtype; 10197c478bd9Sstevel@tonic-gate char *symname; 10207c478bd9Sstevel@tonic-gate static ARFILEP *sym_ptr = 0; 10217c478bd9Sstevel@tonic-gate static ARFILEP *nextsym = NULL; 10227c478bd9Sstevel@tonic-gate static int syms_left = 0; 10237c478bd9Sstevel@tonic-gate char *fname = fptr->ar_pathname; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate (void) gelf_getshdr(scn, &shdr); 10267c478bd9Sstevel@tonic-gate str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */ 10277c478bd9Sstevel@tonic-gate if (str_scn == NULL) { 10287c478bd9Sstevel@tonic-gate if (fname != NULL) 10297c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 1030*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 1031*d2d5cf7cSAli Bahrami fname); 10327c478bd9Sstevel@tonic-gate else 10337c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 1034*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 10357c478bd9Sstevel@tonic-gate (*num_errs)++; 10367c478bd9Sstevel@tonic-gate return (-1); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate no_of_symbols = shdr.sh_size / shdr.sh_entsize; 10407c478bd9Sstevel@tonic-gate if (no_of_symbols == -1) { 10417c478bd9Sstevel@tonic-gate error_message(SYMTAB_01_ERROR, 1042*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 10437c478bd9Sstevel@tonic-gate return (-1); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate (void) gelf_getshdr(str_scn, &shdr); 10477c478bd9Sstevel@tonic-gate str_shtype = shdr.sh_type; 10487c478bd9Sstevel@tonic-gate if (str_shtype == -1) { 10497c478bd9Sstevel@tonic-gate if (fname != NULL) 10507c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 1051*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), fname); 10527c478bd9Sstevel@tonic-gate else 10537c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 1054*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1)); 10557c478bd9Sstevel@tonic-gate (*num_errs)++; 10567c478bd9Sstevel@tonic-gate return (-1); 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate /* This test must happen before testing the string table. */ 10607c478bd9Sstevel@tonic-gate if (no_of_symbols == 1) 10617c478bd9Sstevel@tonic-gate return (0); /* no symbols; 0th symbol is the non-symbol */ 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if (str_shtype != SHT_STRTAB) { 10647c478bd9Sstevel@tonic-gate if (fname != NULL) 10657c478bd9Sstevel@tonic-gate error_message(SYMTAB_02_ERROR, 1066*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 1067*d2d5cf7cSAli Bahrami fname); 10687c478bd9Sstevel@tonic-gate else 10697c478bd9Sstevel@tonic-gate error_message(SYMTAB_03_ERROR, 1070*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 10717c478bd9Sstevel@tonic-gate return (0); 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate str_data = 0; 10747c478bd9Sstevel@tonic-gate if ((str_data = elf_getdata(str_scn, str_data)) == 0) { 10757c478bd9Sstevel@tonic-gate if (fname != NULL) 10767c478bd9Sstevel@tonic-gate error_message(SYMTAB_04_ERROR, 1077*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 1078*d2d5cf7cSAli Bahrami fname); 10797c478bd9Sstevel@tonic-gate else 10807c478bd9Sstevel@tonic-gate error_message(SYMTAB_05_ERROR, 1081*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 10827c478bd9Sstevel@tonic-gate return (0); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate if (str_data->d_size == 0) { 10857c478bd9Sstevel@tonic-gate if (fname != NULL) 10867c478bd9Sstevel@tonic-gate error_message(SYMTAB_06_ERROR, 1087*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 1088*d2d5cf7cSAli Bahrami fname); 10897c478bd9Sstevel@tonic-gate else 10907c478bd9Sstevel@tonic-gate error_message(SYMTAB_07_ERROR, 1091*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 10927c478bd9Sstevel@tonic-gate return (0); 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate sym_data = 0; 10957c478bd9Sstevel@tonic-gate if ((sym_data = elf_getdata(scn, sym_data)) == NULL) { 10967c478bd9Sstevel@tonic-gate if (fname != NULL) 10977c478bd9Sstevel@tonic-gate error_message(ELF_01_ERROR, 1098*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 1099*d2d5cf7cSAli Bahrami fname, elf_errmsg(-1)); 11007c478bd9Sstevel@tonic-gate else 11017c478bd9Sstevel@tonic-gate error_message(ELF_02_ERROR, 1102*d2d5cf7cSAli Bahrami LIBELF_ERROR, elf_errmsg(-1), 1103*d2d5cf7cSAli Bahrami elf_errmsg(-1)); 11047c478bd9Sstevel@tonic-gate return (0); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* start at 1, first symbol entry is ignored */ 11087c478bd9Sstevel@tonic-gate for (counter = 1; counter < no_of_symbols; counter++) { 11097c478bd9Sstevel@tonic-gate GElf_Sym sym; 11107c478bd9Sstevel@tonic-gate (void) gelf_getsym(sym_data, counter, &sym); 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate symname = (char *)(str_data->d_buf) + sym.st_name; 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate if (((GELF_ST_BIND(sym.st_info) == STB_GLOBAL) || 1115*d2d5cf7cSAli Bahrami (GELF_ST_BIND(sym.st_info) == STB_WEAK)) && 1116*d2d5cf7cSAli Bahrami (sym.st_shndx != SHN_UNDEF)) { 11177c478bd9Sstevel@tonic-gate if (!syms_left) { 11187c478bd9Sstevel@tonic-gate sym_ptr = malloc((SYMCHUNK+1) 1119*d2d5cf7cSAli Bahrami * sizeof (ARFILEP)); 11207c478bd9Sstevel@tonic-gate if (sym_ptr == NULL) { 11217c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 1122*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 11237c478bd9Sstevel@tonic-gate exit(1); 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate syms_left = SYMCHUNK; 11267c478bd9Sstevel@tonic-gate if (nextsym) 11277c478bd9Sstevel@tonic-gate *nextsym = (ARFILEP)sym_ptr; 11287c478bd9Sstevel@tonic-gate else 11297c478bd9Sstevel@tonic-gate *symlist = sym_ptr; 11307c478bd9Sstevel@tonic-gate nextsym = sym_ptr; 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate sym_ptr = nextsym; 11337c478bd9Sstevel@tonic-gate nextsym++; 11347c478bd9Sstevel@tonic-gate syms_left--; 11357c478bd9Sstevel@tonic-gate (*nsyms)++; 11367c478bd9Sstevel@tonic-gate *sym_ptr = fptr; 11377c478bd9Sstevel@tonic-gate savename(symname); /* put name in the archiver's */ 11387c478bd9Sstevel@tonic-gate /* symbol table string table */ 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate return (0); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * Get the output file size 11467c478bd9Sstevel@tonic-gate */ 11477c478bd9Sstevel@tonic-gate static int 11487c478bd9Sstevel@tonic-gate sizeofmembers(int psum) 11497c478bd9Sstevel@tonic-gate { 11507c478bd9Sstevel@tonic-gate int sum = 0; 11517c478bd9Sstevel@tonic-gate ARFILE *fptr; 11527c478bd9Sstevel@tonic-gate int hdrsize = sizeof (struct ar_hdr); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 11557c478bd9Sstevel@tonic-gate fptr->ar_offset = psum + sum; 11567c478bd9Sstevel@tonic-gate sum += fptr->ar_size; 11577c478bd9Sstevel@tonic-gate if (fptr->ar_size & 01) 11587c478bd9Sstevel@tonic-gate sum++; 11597c478bd9Sstevel@tonic-gate sum += hdrsize; 11607c478bd9Sstevel@tonic-gate 116160fc76daSab /* 116260fc76daSab * If the current item, and the next item are both ELF 116360fc76daSab * objects, then add padding to current item so that the 116460fc76daSab * next item will have PADSZ alignment. 116560fc76daSab * 116660fc76daSab * In any other case, set the padding to 0. If the 116760fc76daSab * item comes from another archive, it may be carrying 116860fc76daSab * a non-zero padding value from that archive that does 116960fc76daSab * not apply to the one we are about to build. 117060fc76daSab */ 11717c478bd9Sstevel@tonic-gate if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) && 11729d6538abSab fptr->ar_next && 11739d6538abSab (fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) { 11749d6538abSab fptr->ar_padding = pad(psum + sum + hdrsize); 11759d6538abSab sum += fptr->ar_padding; 117660fc76daSab } else { 117760fc76daSab fptr->ar_padding = 0; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate return (sum); 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate static int 11849d6538abSab sizeofnewarchiveheader(int nsyms, int longnames) 11857c478bd9Sstevel@tonic-gate { 11867c478bd9Sstevel@tonic-gate int sum = 0; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate sum += SARMAG; 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate if (nsyms) { 11917c478bd9Sstevel@tonic-gate char *top = (char *)str_top; 11927c478bd9Sstevel@tonic-gate char *base = (char *)str_base; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate while ((top - base) & 03) 11957c478bd9Sstevel@tonic-gate top++; 11967c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 11977c478bd9Sstevel@tonic-gate sum += (nsyms + 1) * 4; 11987c478bd9Sstevel@tonic-gate sum += top - base; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate if (longnames) { 12027c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 12037c478bd9Sstevel@tonic-gate sum += str_top1 - str_base1; 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate /* 12079d6538abSab * If the first member file is an ELF object, 12087c478bd9Sstevel@tonic-gate * we have to ensure the member contents will align 12099d6538abSab * on PADSZ byte boundary. 12107c478bd9Sstevel@tonic-gate */ 12119d6538abSab if (listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64))) { 12129d6538abSab pad_symtab = pad(sum + sizeof (struct ar_hdr)); 12139d6538abSab sum += pad_symtab; 12147c478bd9Sstevel@tonic-gate } 12159d6538abSab 12169d6538abSab return (sum); 12179d6538abSab } 12189d6538abSab 12199d6538abSab static int 12209d6538abSab sizeofnewarchive(int nsyms, int longnames) 12219d6538abSab { 12229d6538abSab int sum; 12239d6538abSab 12249d6538abSab sum = sizeofnewarchiveheader(nsyms, longnames); 12257c478bd9Sstevel@tonic-gate sum += sizeofmembers(sum); 12267c478bd9Sstevel@tonic-gate return (sum); 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate static void 12307c478bd9Sstevel@tonic-gate arwrite(char *name, int nfd, char *dst, int size) { 12317c478bd9Sstevel@tonic-gate if (write(nfd, dst, size) != size) { 12327c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_04_ERROR, 1233*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 12347c478bd9Sstevel@tonic-gate exit(2); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate static char * 12397c478bd9Sstevel@tonic-gate make_tmpname(char *filename) { 12407c478bd9Sstevel@tonic-gate static char template[] = "arXXXXXX"; 12417c478bd9Sstevel@tonic-gate char *tmpname; 12427c478bd9Sstevel@tonic-gate char *slash = strrchr(filename, '/'); 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (slash != (char *)NULL) { 12457c478bd9Sstevel@tonic-gate char c; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate c = *slash; 12487c478bd9Sstevel@tonic-gate *slash = 0; 12497c478bd9Sstevel@tonic-gate tmpname = (char *)malloc(strlen(filename) + 12507c478bd9Sstevel@tonic-gate sizeof (template) + 2); 1251d6555420Smike_s (void) strcpy(tmpname, filename); 1252d6555420Smike_s (void) strcat(tmpname, "/"); 1253d6555420Smike_s (void) strcat(tmpname, template); 1254d6555420Smike_s (void) mktemp(tmpname); 12557c478bd9Sstevel@tonic-gate *slash = c; 12567c478bd9Sstevel@tonic-gate } else { 12577c478bd9Sstevel@tonic-gate tmpname = malloc(sizeof (template)); 1258d6555420Smike_s (void) strcpy(tmpname, template); 1259d6555420Smike_s (void) mktemp(tmpname); 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate return (tmpname); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate static int 12657c478bd9Sstevel@tonic-gate ar_copy(char *from, char *to) { 12667c478bd9Sstevel@tonic-gate int fromfd, tofd, nread; 12677c478bd9Sstevel@tonic-gate int saved; 12687c478bd9Sstevel@tonic-gate char buf[8192]; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate fromfd = open(from, O_RDONLY); 12717c478bd9Sstevel@tonic-gate if (fromfd < 0) 12727c478bd9Sstevel@tonic-gate return (-1); 12737c478bd9Sstevel@tonic-gate tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 0777); 12747c478bd9Sstevel@tonic-gate if (tofd < 0) { 12757c478bd9Sstevel@tonic-gate saved = errno; 1276d6555420Smike_s (void) close(fromfd); 12777c478bd9Sstevel@tonic-gate errno = saved; 12787c478bd9Sstevel@tonic-gate return (-1); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate while ((nread = read(fromfd, buf, sizeof (buf))) > 0) { 12817c478bd9Sstevel@tonic-gate if (write(tofd, buf, nread) != nread) { 12827c478bd9Sstevel@tonic-gate saved = errno; 1283d6555420Smike_s (void) close(fromfd); 1284d6555420Smike_s (void) close(tofd); 12857c478bd9Sstevel@tonic-gate errno = saved; 12867c478bd9Sstevel@tonic-gate return (-1); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate saved = errno; 1290d6555420Smike_s (void) close(fromfd); 1291d6555420Smike_s (void) close(tofd); 12927c478bd9Sstevel@tonic-gate if (nread < 0) { 12937c478bd9Sstevel@tonic-gate errno = saved; 12947c478bd9Sstevel@tonic-gate return (-1); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate return (0); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate static int 1300d6555420Smike_s ar_rename(char *from, char *to) 1301d6555420Smike_s { 13027c478bd9Sstevel@tonic-gate int exists; 13037c478bd9Sstevel@tonic-gate struct stat s; 13047c478bd9Sstevel@tonic-gate int ret = 0; 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate exists = lstat(to, &s) == 0; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate if (! exists || (!S_ISLNK(s.st_mode) && s.st_nlink == 1)) { 13097c478bd9Sstevel@tonic-gate ret = rename(from, to); 13107c478bd9Sstevel@tonic-gate if (ret == 0) { 13117c478bd9Sstevel@tonic-gate if (exists) { 1312d6555420Smike_s (void) chmod(to, s.st_mode & 0777); 13137c478bd9Sstevel@tonic-gate if (chown(to, s.st_uid, s.st_gid) >= 0) 1314d6555420Smike_s (void) chmod(to, s.st_mode & 07777); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate } else { 1317d6555420Smike_s (void) unlink(from); 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate } else { 13207c478bd9Sstevel@tonic-gate ret = ar_copy(from, to); 1321d6555420Smike_s (void) unlink(from); 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate return (ret); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate static char * 13277c478bd9Sstevel@tonic-gate writelargefile(Cmd_info *cmd_info, long long_tab_size, int longnames, 13287c478bd9Sstevel@tonic-gate ARFILEP *symlist, long nsyms, int found_obj, int new_archive) 13297c478bd9Sstevel@tonic-gate { 1330d6555420Smike_s ARFILE * fptr; 13317c478bd9Sstevel@tonic-gate char *name = cmd_info->arnam; 13327c478bd9Sstevel@tonic-gate int arsize; 13337c478bd9Sstevel@tonic-gate char *dst; 13347c478bd9Sstevel@tonic-gate char *tmp_dst; 13357c478bd9Sstevel@tonic-gate int nfd; 13367c478bd9Sstevel@tonic-gate char *new_name; 13377c478bd9Sstevel@tonic-gate FILE *f; 13387c478bd9Sstevel@tonic-gate struct stat stbuf; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate new_name = make_tmpname(name); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (new_archive) { 13437c478bd9Sstevel@tonic-gate nfd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 13447c478bd9Sstevel@tonic-gate if (nfd == -1) { 13457c478bd9Sstevel@tonic-gate error_message(SYS_CREATE_01_ERROR, 1346*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 13477c478bd9Sstevel@tonic-gate exit(1); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate } else { 13507c478bd9Sstevel@tonic-gate nfd = open(new_name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 13517c478bd9Sstevel@tonic-gate if (nfd == -1) { 13527c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_02_ERROR, 1353*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), name); 13547c478bd9Sstevel@tonic-gate exit(1); 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate arsize = sizeofnewarchiveheader(nsyms, longnames); 13597c478bd9Sstevel@tonic-gate if (nsyms == 0 && found_obj != 0) 13607c478bd9Sstevel@tonic-gate arsize += sizeof (struct ar_hdr) + 4 + 4; 13617c478bd9Sstevel@tonic-gate if (arsize < 2048) { 13627c478bd9Sstevel@tonic-gate arsize = 2048; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate dst = tmp_dst = (char *)malloc(arsize); 13657c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, ARMAG, SARMAG); 13667c478bd9Sstevel@tonic-gate tmp_dst += SARMAG; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate if (nsyms || found_obj != 0) { 13697c478bd9Sstevel@tonic-gate int diff; 13707c478bd9Sstevel@tonic-gate diff = writesymtab(tmp_dst, nsyms, symlist); 13717c478bd9Sstevel@tonic-gate tmp_dst += diff; 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate if (longnames) { 13757c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 1376*d2d5cf7cSAli Bahrami (unsigned)0, (unsigned)0, (unsigned)0, 1377*d2d5cf7cSAli Bahrami (long)long_tab_size, ARFMAG); 13787c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 13797c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 13807c478bd9Sstevel@tonic-gate tmp_dst += str_top1 - str_base1; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate #ifndef XPG4 13837c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 1384*d2d5cf7cSAli Bahrami error_message(BER_MES_WRITE_ERROR, 1385*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0, 1386*d2d5cf7cSAli Bahrami cmd_info->arnam); 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate #endif 13897c478bd9Sstevel@tonic-gate arwrite(name, nfd, dst, (int)(tmp_dst - dst)); 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 13927c478bd9Sstevel@tonic-gate if (fptr->ar_name[0] == 0) { 13937c478bd9Sstevel@tonic-gate fptr->ar_longname = fptr->ar_rawname; 13947c478bd9Sstevel@tonic-gate (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 13977c478bd9Sstevel@tonic-gate (void) sprintf(dst, FNFORMAT, 1398*d2d5cf7cSAli Bahrami trimslash(fptr->ar_longname)); 13997c478bd9Sstevel@tonic-gate else 14007c478bd9Sstevel@tonic-gate (void) sprintf(dst, FNFORMAT, fptr->ar_name); 14017c478bd9Sstevel@tonic-gate (void) sprintf(dst+16, TLFORMAT, fptr->ar_date, 14027c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 14037c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 14047c478bd9Sstevel@tonic-gate ARFMAG); 14057c478bd9Sstevel@tonic-gate arwrite(name, nfd, dst, sizeof (struct ar_hdr)); 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate if (!(fptr->ar_flag & F_MALLOCED) && 14087c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_MMAPED) && 14097c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_ELFRAW)) { 14107c478bd9Sstevel@tonic-gate f = fopen(fptr->ar_pathname, "r"); 14117c478bd9Sstevel@tonic-gate if (stat(fptr->ar_pathname, &stbuf) < 0) { 14127c478bd9Sstevel@tonic-gate (void) fclose(f); 14137c478bd9Sstevel@tonic-gate f = NULL; 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate if (f == NULL) { 14167c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 1417*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), 1418*d2d5cf7cSAli Bahrami fptr->ar_longname); 14197c478bd9Sstevel@tonic-gate exit(1); 14207c478bd9Sstevel@tonic-gate } else { 14217c478bd9Sstevel@tonic-gate if ((fptr->ar_contents = (char *) 14227c478bd9Sstevel@tonic-gate malloc(ROUNDUP(stbuf.st_size))) == NULL) { 14237c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 1424*d2d5cf7cSAli Bahrami PLAIN_ERROR, (char *)0); 14257c478bd9Sstevel@tonic-gate exit(1); 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate if (fread(fptr->ar_contents, 14287c478bd9Sstevel@tonic-gate sizeof (char), 14297c478bd9Sstevel@tonic-gate stbuf.st_size, f) != stbuf.st_size) { 14307c478bd9Sstevel@tonic-gate error_message(SYS_READ_ERROR, 1431*d2d5cf7cSAli Bahrami SYSTEM_ERROR, strerror(errno), 1432*d2d5cf7cSAli Bahrami fptr->ar_longname); 14337c478bd9Sstevel@tonic-gate exit(1); 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 1437d6555420Smike_s (void) fclose(f); 14387c478bd9Sstevel@tonic-gate free(fptr->ar_contents); 14397c478bd9Sstevel@tonic-gate } else { 14407c478bd9Sstevel@tonic-gate arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 14417c478bd9Sstevel@tonic-gate if (fptr->ar_flag & F_MALLOCED) { 14427c478bd9Sstevel@tonic-gate (void) free(fptr->ar_contents); 14437c478bd9Sstevel@tonic-gate fptr->ar_flag &= ~(F_MALLOCED); 14447c478bd9Sstevel@tonic-gate } 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if (fptr->ar_size & 0x1) { 14487c478bd9Sstevel@tonic-gate arwrite(name, nfd, "\n", 1); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate if (fptr->ar_padding) { 14527c478bd9Sstevel@tonic-gate int i = fptr->ar_padding; 14537c478bd9Sstevel@tonic-gate while (i) { 14547c478bd9Sstevel@tonic-gate arwrite(name, nfd, "\n", 1); 14557c478bd9Sstevel@tonic-gate --i; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* 14617c478bd9Sstevel@tonic-gate * All preparation for writing is done. 14627c478bd9Sstevel@tonic-gate */ 14637c478bd9Sstevel@tonic-gate (void) elf_end(cmd_info->arf); 14647c478bd9Sstevel@tonic-gate (void) close(cmd_info->afd); 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate if (!new_archive) { 1467d6555420Smike_s (void) ar_rename(new_name, name); 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate return (dst); 14717c478bd9Sstevel@tonic-gate } 1472