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