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