xref: /titanic_52/usr/src/cmd/sgs/ar/common/file.c (revision f985abb4a2473d3c04b086f7c9fab177e368ffef)
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  */
25 
26 /*
27  *	Copyright (c) 1988 AT&T
28  *	  All Rights Reserved
29  *
30  */
31 
32 #include <sys/sendfile.h>
33 #include "inc.h"
34 #include "gelf.h"
35 
36 /*
37  * List of archive members, accessed globally by cmd and file.
38  */
39 ARFILE	*listhead, *listend;
40 
41 /*
42  * Type used to manage string tables. Archives can have two of these:
43  *
44  * sym_strtbl: String table included at the end of the symbol table
45  *	archive member, following the offset array.
46  *
47  * long_strtbl: String table used to hold member names that exceed 15
48  *	characters in length, found in the long names archive member.
49  */
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;
55 
56 static ARSTRTBL	sym_strtbl;
57 static ARSTRTBL	long_strtbl;
58 
59 
60 /*
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.
66  */
67 static struct {
68 	int		fd;	/* -1, or open file descriptor */
69 	const char	*path;	/* Path to open file */
70 } ar_outfile;
71 
72 /*
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.
75  *
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.
83  *
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.
88  *
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.
97  */
98 #define	PADSZ 8
99 
100 /*
101  * Forward Declarations
102  */
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);
119 
120 
121 /*
122  * Function to be called on exit to clean up incomplete new archive.
123  */
124 static void
125 exit_cleanup(void)
126 {
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);
131 	}
132 }
133 
134 /*
135  * Open an existing archive.
136  */
137 int
138 getaf(Cmd_info *cmd_info)
139 {
140 	Elf_Cmd cmd;
141 	int fd;
142 	char *arnam = cmd_info->arnam;
143 
144 	if (elf_version(EV_CURRENT) == EV_NONE) {
145 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_VERSION),
146 		    elf_errmsg(-1));
147 		exit(1);
148 	}
149 
150 	if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) {
151 		int err = errno;
152 
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);
161 		}
162 	}
163 
164 	cmd = ELF_C_READ;
165 	cmd_info->arf = elf_begin(fd, cmd, (Elf *)0);
166 
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);
173 	}
174 	return (fd);
175 }
176 
177 /*
178  * Given a value, and a pad alignment, return the number of bytes
179  * required to pad the value to the next alignment boundary.
180  */
181 static size_t
182 pad(size_t n, size_t align)
183 {
184 	size_t r;
185 
186 	r = n % align;
187 	if (r)
188 		r = align - r;
189 
190 	return (r);
191 }
192 
193 /*
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.
202  */
203 static void
204 recover_padding(Elf *elf, ARFILE *file)
205 {
206 	size_t		extent;
207 	size_t		padding;
208 	size_t		shnum;
209 	GElf_Ehdr	ehdr;
210 
211 
212 	/* ar(1) only pads objects, so bail if not looking at one */
213 	if (gelf_getclass(elf) == ELFCLASSNONE)
214 		return;
215 
216 	/*
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).
225 	 */
226 	if (elf_getshdrnum(elf, &shnum) == -1)
227 		return;
228 
229 	extent = gelf_getehdr(elf, &ehdr)
230 	    ? (ehdr.e_shoff + (shnum * ehdr.e_shentsize)) : 0;
231 
232 	/*
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.
236 	 */
237 	if (extent > file->ar_size)
238 		return;
239 
240 	padding = file->ar_size - extent;
241 	if (padding >= PADSZ) {
242 		/*
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.
247 		 */
248 		Elf_Scn *scn = NULL;
249 
250 		do {
251 			scn = elf_nextscn(elf, scn);
252 			if (scn) {
253 				GElf_Shdr shdr;
254 
255 				if (gelf_getshdr(scn, &shdr)) {
256 					size_t t;
257 
258 					t = shdr.sh_offset + shdr.sh_size;
259 					if (t > extent)
260 						extent = t;
261 				}
262 			}
263 		} while (scn);
264 
265 		if (extent > file->ar_size)
266 			return;
267 		padding = file->ar_size - extent;
268 	}
269 
270 	/*
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.
276 	 *
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.
282 	 */
283 	if (padding < PADSZ) {
284 		if (file->ar_contents) {
285 			size_t cnt = padding;
286 			char *p = file->ar_contents + extent;
287 
288 			while (cnt--) {
289 				if (*p++ != '\n') {   /* No padding */
290 					padding = 0;
291 					break;
292 				}
293 			}
294 		}
295 
296 		/* Remove the padding from the size */
297 		file->ar_size -= padding;
298 		file->ar_padding = padding;
299 	}
300 }
301 
302 /*
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.
306  */
307 ARFILE *
308 getfile(Cmd_info *cmd_info)
309 {
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;
317 
318 	if (fd == -1)
319 		return (NULL); /* the archive doesn't exist */
320 
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 */
324 
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);
329 		}
330 
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;
336 		}
337 	}
338 
339 	/*
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".
347 	 */
348 	file = newfile();
349 	(void) strncpy(file->ar_name, mem_header->ar_name, SNAME);
350 
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);
356 	}
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);
363 	}
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++;
370 	}
371 	if (!(*tmp_rawname == '\0'))
372 		*file_rawname = '\0';
373 
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;
379 
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);
390 			}
391 		}
392 		file->ar_elf = elf;
393 	}
394 
395 	recover_padding(elf, file);
396 
397 	(void) elf_next(elf);
398 	return (file);
399 }
400 
401 /*
402  * Allocate a new archive member descriptor and add it to the list.
403  */
404 ARFILE *
405 newfile(void)
406 {
407 	static ARFILE	*buffer =  NULL;
408 	static size_t	count = 0;
409 	ARFILE		*fileptr;
410 
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);
418 		}
419 		count = CHUNK;
420 	}
421 	count--;
422 	fileptr = buffer++;
423 
424 	if (listhead)
425 		listend->ar_next = fileptr;
426 	else
427 		listhead = fileptr;
428 	listend = fileptr;
429 	return (fileptr);
430 }
431 
432 static char *
433 trimslash(char *s)
434 {
435 	static char buf[SNAME];
436 
437 	(void) strncpy(buf, trim(s), SNAME - 2);
438 	buf[SNAME - 2] = '\0';
439 	return (strcat(buf, MSG_ORIG(MSG_STR_SLASH)));
440 }
441 
442 char *
443 trim(char *s)
444 {
445 	char *p1, *p2;
446 
447 	for (p1 = s; *p1; p1++)
448 		;
449 	while (p1 > s) {
450 		if (*--p1 != '/')
451 			break;
452 		*p1 = 0;
453 	}
454 	p2 = s;
455 	for (p1 = s; *p1; p1++)
456 		if (*p1 == '/')
457 			p2 = p1 + 1;
458 	return (p2);
459 }
460 
461 
462 /*
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.
466  *
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.
471  */
472 static size_t
473 mksymtab(const char *arname, ARFILEP **symlist, int *found_obj)
474 {
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;
485 
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)) {
490 			/*
491 			 * I can use the saved elf descriptor.
492 			 */
493 			elf = fptr->ar_elf;
494 		} else if ((fptr->ar_elf == NULL) &&
495 		    (fptr->ar_pathname != NULL)) {
496 #ifdef _LP64
497 			/*
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.
502 			 *
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.
508 			 *
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.
518 			 */
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;
525 			}
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;
534 			}
535 
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;
545 			}
546 			if (elf_kind(elf) == ELF_K_AR) {
547 				if (newfd) {
548 					(void) close(newfd);
549 					newfd = 0;
550 				}
551 				(void) elf_end(elf);
552 				continue;
553 			}
554 		} else {
555 			(void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01));
556 			exit(1);
557 		}
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;
564 
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));
575 				}
576 				num_errs++;
577 				if (newfd) {
578 					(void) close(newfd);
579 					newfd = 0;
580 				}
581 				(void) elf_end(elf);
582 				continue;
583 			}
584 
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;
600 				}
601 				(void) elf_end(elf);
602 				continue;
603 			}
604 
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;
621 				}
622 				(void) elf_end(elf);
623 				continue;
624 			}
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;
637 				}
638 				(void) elf_end(elf);
639 				num_errs++;
640 				continue;
641 			}
642 
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;
663 					}
664 					num_errs++;
665 					(void) elf_end(elf);
666 					continue;
667 				}
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;
676 						}
677 						continue;
678 					}
679 				}
680 			}
681 		}
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;
689 		}
690 	}
691 	if (num_errs)
692 		exit(1);
693 
694 	if (found_obj) {
695 		if (nsyms == 0) {
696 			/*
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.
705 			 */
706 			strtbl_pad(&sym_strtbl, 4, '\0');
707 		} else {
708 			/*
709 			 * Historical behavior is to pad string tables
710 			 * to a multiple of 4.
711 			 */
712 			strtbl_pad(&sym_strtbl, pad(sym_strtbl.used, 4), '\0');
713 		}
714 
715 	}
716 
717 	return (nsyms);
718 }
719 
720 /*
721  * Output a member header.
722  */
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)
728 {
729 	char	buf[sizeof (struct ar_hdr) + 1];
730 	int	len;
731 
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);
735 
736 	/*
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.
740 	 */
741 	if (len != sizeof (struct ar_hdr)) {
742 		(void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_02));
743 		exit(1);
744 	}
745 
746 	arwrite(filename, fd, buf, len);
747 
748 	/*
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.
752 	 */
753 	assert(!is_elf || (pad(lseek(fd, 0, SEEK_CUR), PADSZ) == 0));
754 }
755 
756 /*
757  * Write the archive symbol table member to the output archive file.
758  *
759  * note:
760  *	sizeofmembers() must have been called to establish member offset
761  *	and padding values before writesymtab() is used.
762  */
763 static void
764 writesymtab(const char *filename, int fd, size_t nsyms, ARFILEP *symlist,
765     size_t eltsize)
766 {
767 	size_t	i, j;
768 	ARFILEP	*ptr;
769 	size_t	tblsize;
770 	char	*buf, *dst;
771 	int	is64 = (eltsize == 8);
772 
773 	/*
774 	 * We require a buffer large enough to hold a symbol table count,
775 	 * plus one offset for each symbol.
776 	 */
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);
782 	}
783 
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);
787 
788 	dst = is64 ? sputl64(nsyms, dst) : sputl32(nsyms, dst);
789 
790 	for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) {
791 		if (!j) {
792 			j = SYMCHUNK;
793 			ptr = (ARFILEP *)*ptr;
794 		}
795 		dst = is64 ? sputl64((*ptr)->ar_offset, dst) :
796 		    sputl32((*ptr)->ar_offset, dst);
797 	}
798 	arwrite(filename, fd, buf, tblsize);
799 	free(buf);
800 	arwrite(filename, fd, sym_strtbl.base, sym_strtbl.used);
801 }
802 
803 /*
804  * Grow the size of the given string table so that there is room
805  * for at least need bytes.
806  *
807  * entry:
808  *	strtbl - String table to grow
809  *	need - Amount of space required by caller
810  */
811 static void
812 strtbl_alloc(ARSTRTBL *strtbl, size_t need)
813 {
814 #define	STRTBL_INITSZ	8196
815 
816 	/*
817 	 * On 32-bit systems, we require a larger integer type in order
818 	 * to avoid overflow and wraparound when doing our computations.
819 	 */
820 	uint64_t	need64 = need;
821 	uint64_t	used64 = strtbl->used;
822 	uint64_t	size64 = strtbl->size;
823 	uint64_t	target = need64 + used64;
824 
825 	int		sys32, tbl32;
826 
827 	if (target <= size64)
828 		return;
829 
830 	/*
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.
834 	 */
835 	sys32 = (sizeof (size_t) == 4);
836 
837 	/*
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.
842 	 */
843 	tbl32 = (strtbl == &long_strtbl);
844 
845 	/*
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.
849 	 */
850 	if ((target > 0xffffffff) && (sys32 || tbl32))
851 		goto limit_fail;
852 
853 	/* Default starting size */
854 	if (strtbl->base == NULL)
855 		size64 = STRTBL_INITSZ;
856 
857 	/*
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.
862 	 */
863 	while (target > size64) {
864 		if ((target > 0x7fffffff) && (sys32 || tbl32)) {
865 			size64 = ((target + STRTBL_INITSZ) / STRTBL_INITSZ) *
866 			    STRTBL_INITSZ;
867 
868 			/*
869 			 * If we are so close to the line that this small
870 			 * increment exceeds 4GB, give it up.
871 			 */
872 			if ((size64 > 0xffffffff) && (sys32 || tbl32))
873 				goto limit_fail;
874 
875 			break;
876 		}
877 
878 		size64 *= 2;
879 	}
880 
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);
886 	}
887 	strtbl->size = (size_t)size64;
888 	return;
889 
890 limit_fail:
891 	/*
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:
894 	 *
895 	 * - A 32-bit process is attempting to be larger than 4GB
896 	 *
897 	 * - A 64-bit process is attempting to grow the long names string
898 	 *	table beyond the ar format limit of 32-bits.
899 	 */
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);
905 
906 #undef STRTBL_INITSZ
907 }
908 
909 /*
910  * Add the specified number of pad characters to the end of the
911  * given string table.
912  *
913  * entry:
914  *	strtbl - String table to pad
915  *	n - # of pad characters to add
916  *	ch - Pad character to use
917  */
918 static void
919 strtbl_pad(ARSTRTBL *strtbl, size_t n, int ch)
920 {
921 	if (n == 0)
922 		return;
923 
924 	if ((n + strtbl->used) > strtbl->size)
925 		strtbl_alloc(strtbl, n);
926 
927 	while (n--)
928 		strtbl->base[strtbl->used++] = ch;
929 }
930 
931 /*
932  * Enter a symbol name into the symbol string table.
933  */
934 static void
935 savename(char *symbol)
936 {
937 	size_t need;
938 
939 	need = strlen(symbol) + 1;
940 	if ((need + sym_strtbl.used) > sym_strtbl.size)
941 		strtbl_alloc(&sym_strtbl, need);
942 
943 	(void) strcpy(sym_strtbl.base + sym_strtbl.used, symbol);
944 	sym_strtbl.used += need;
945 }
946 
947 /*
948  * Prepare an archive member with a long (>15 characters) name for
949  * the output archive.
950  *
951  * entry:
952  *	fptr - pointer to archive member with long name
953  *
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.
959  */
960 static void
961 savelongname(ARFILE *fptr)
962 {
963 	size_t	len, need;
964 	char	*p;
965 
966 	/* Size of new item to add */
967 	len = strlen(fptr->ar_longname);
968 	need = len + 2;
969 
970 	/* Ensure there's room */
971 	if ((need + long_strtbl.used) > long_strtbl.size)
972 		strtbl_alloc(&long_strtbl, need);
973 
974 	/*
975 	 * Generate the index string to be written into the member header
976 	 *
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.
981 	 */
982 	(void) snprintf(fptr->ar_name, sizeof (fptr->ar_name),
983 	    MSG_ORIG(MSG_FMT_LLINT), EC_XWORD(long_strtbl.used));
984 
985 	/*
986 	 * Enter long name into reserved spot, terminated with a slash
987 	 * and a newline character.
988 	 */
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';
995 }
996 
997 /*
998  * Determine if the archive we're about to write will exceed the
999  * 32-bit limit of 4GB.
1000  *
1001  * entry:
1002  *      mksymtab() and mklong_tab() have been called to set up
1003  *	the string tables.
1004  *
1005  * exit:
1006  *	Returns TRUE (1) if the 64-bit symbol table is needed, and
1007  *	FALSE (0) otherwise.
1008  *
1009  */
1010 static int
1011 require64(size_t nsyms, int found_obj, size_t longnames)
1012 {
1013 	ARFILE		*fptr;
1014 	uint64_t	size;
1015 
1016 	/*
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.
1021 	 */
1022 	if (nsyms > 0xffffffff)
1023 		return (1);
1024 
1025 	/*
1026 	 * Make a worst case estimate for the size of the resulting
1027 	 * archive by assuming full padding between members.
1028 	 */
1029 	size = 	SARMAG;
1030 	if (longnames)
1031 		size += sizeof (struct ar_hdr) + long_strtbl.used + PADSZ;
1032 
1033 	if (found_obj)
1034 		size += sizeof_symtbl(nsyms, found_obj, 4) + PADSZ;
1035 
1036 	if (size > 0xffffffff)
1037 		return (1);
1038 
1039 	for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1040 		size += sizeof (struct ar_hdr) + fptr->ar_size + PADSZ;
1041 
1042 		if (size > 0xffffffff)
1043 			return (1);
1044 	}
1045 
1046 	/* 32-bit symbol table will suffice */
1047 	return (0);
1048 }
1049 
1050 void
1051 writefile(Cmd_info *cmd_info)
1052 {
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;
1068 
1069 	/*
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.
1074 	 */
1075 	nsyms = mksymtab(name, &symlist, &found_obj);
1076 
1077 	/* Generate the string table for long member names */
1078 	longnames = mklong_tab();
1079 
1080 	/*
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.
1084 	 */
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
1092 	}
1093 
1094 	/*
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.
1098 	 */
1099 	if (cmd_info->opt_flgs & S_FLAG)
1100 		symtbl_eltsize = 8;
1101 
1102 	/*
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.
1108 	 */
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;
1117 		}
1118 	}
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;
1125 		}
1126 	}
1127 
1128 	/*
1129 	 * For each user visible (non-special) archive member, determine
1130 	 * the header offset, and the size of any required padding.
1131 	 */
1132 	(void) sizeofmembers(arsize);
1133 
1134 	/*
1135 	 * Is this a new archive, or are we updating an existing one?
1136 	 *
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.
1143 	 */
1144 	if ((fd = open(name, O_RDWR)) < 0) {
1145 		int	err = errno;
1146 
1147 		if (err != ENOENT) {
1148 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1149 			    name, strerror(err));
1150 			exit(1);
1151 		}
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);
1156 		}
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);
1165 		}
1166 		(void) close(fd);
1167 		new_archive = 0;
1168 	}
1169 
1170 
1171 	/*
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.
1175 	 */
1176 	if (atexit(exit_cleanup) != 0) {
1177 		(void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
1178 		exit(1);
1179 	}
1180 
1181 	/*
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.
1185 	 */
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);
1193 	}
1194 
1195 	/* Output magic string */
1196 	arwrite(name, ar_outfile.fd, ARMAG, SARMAG);
1197 
1198 	/*
1199 	 * The symbol table member is always first if present. Note that
1200 	 * writesymtab() uses the member offsets computed by sizeofmembers()
1201 	 * above.
1202 	 */
1203 	if (found_obj)
1204 		writesymtab(name, ar_outfile.fd, nsyms, symlist,
1205 		    symtbl_eltsize);
1206 
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);
1213 	}
1214 
1215 	/*
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.
1219 	 */
1220 	assert(arsize == lseek(ar_outfile.fd, 0, SEEK_CUR));
1221 
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);
1226 	}
1227 #endif
1228 
1229 	/*
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.
1234 	 */
1235 	for (pad_cnt = 0; pad_cnt < PADSZ; pad_cnt++)
1236 		pad_bytes[pad_cnt] = '\n';
1237 
1238 	for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1239 		/*
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.
1243 		 */
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)));
1247 
1248 		/*
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".
1256 		 */
1257 		if (fptr->ar_name[0] == 0) {
1258 			fptr->ar_longname = fptr->ar_rawname;
1259 			(void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME);
1260 		}
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);
1266 
1267 
1268 		if ((fptr->ar_flag & F_ELFRAW) == 0) {
1269 			/*
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.
1277 			 */
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);
1283 			}
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);
1290 			}
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);
1298 			}
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);
1304 		}
1305 
1306 		/*
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.
1311 		 */
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);
1315 	}
1316 
1317 	/*
1318 	 * All archive output is done.
1319 	 */
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);
1325 	}
1326 	ar_outfile.fd = -1;	/* Prevent removal on exit */
1327 	(void) elf_end(cmd_info->arf);
1328 	(void) close(cmd_info->afd);
1329 
1330 	/*
1331 	 * If updating an existing archive, rename the new version on
1332 	 * top of the original.
1333 	 */
1334 	if (!new_archive) {
1335 		/*
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.
1339 		 */
1340 		establish_sighandler(SIG_IGN);
1341 
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);
1348 		}
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);
1352 
1353 	}
1354 }
1355 
1356 /*
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.
1360  *
1361  * Returns the size of the resulting archive member, including the
1362  * member header.
1363  */
1364 static size_t
1365 mklong_tab(void)
1366 {
1367 	ARFILE  *fptr;
1368 	size_t longnames = 0;
1369 
1370 	for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1371 		if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) {
1372 			longnames++;
1373 			savelongname(fptr);
1374 		}
1375 	}
1376 
1377 	/* round up table that keeps the long filenames */
1378 	if (longnames > 0)
1379 		strtbl_pad(&long_strtbl, pad(long_strtbl.used, 4), '\n');
1380 
1381 	return (longnames);
1382 }
1383 
1384 /*
1385  * Write 32/64-bit words into buffer in archive symbol table
1386  * standard byte order (MSB).
1387  */
1388 static char *
1389 sputl32(uint32_t n, char *cp)
1390 {
1391 	*cp++ = n >> 24;
1392 	*cp++ = n >> 16;
1393 	*cp++ = n >> 8;
1394 
1395 	*cp++ = n & 255;
1396 
1397 	return (cp);
1398 }
1399 
1400 static char *
1401 sputl64(uint64_t n, char *cp)
1402 {
1403 	*cp++ = n >> 56;
1404 	*cp++ = n >> 48;
1405 	*cp++ = n >> 40;
1406 	*cp++ = n >> 32;
1407 
1408 	*cp++ = n >> 24;
1409 	*cp++ = n >> 16;
1410 	*cp++ = n >> 8;
1411 
1412 	*cp++ = n & 255;
1413 
1414 	return (cp);
1415 }
1416 
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)
1420 {
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;
1432 
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);
1444 	}
1445 
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);
1450 	}
1451 
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);
1463 	}
1464 
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 */
1468 
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);
1477 	}
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);
1487 	}
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);
1496 	}
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);
1506 	}
1507 
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);
1512 
1513 		symname = (char *)(str_data->d_buf) + sym.st_name;
1514 
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);
1527 				}
1528 				syms_left = SYMCHUNK;
1529 				if (nextsym)
1530 					*nextsym = (ARFILEP)sym_ptr;
1531 				else
1532 					*symlist = sym_ptr;
1533 				nextsym = sym_ptr;
1534 			}
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 */
1542 		}
1543 	}
1544 	return (0);
1545 }
1546 
1547 /*
1548  * Get the output file size
1549  */
1550 static size_t
1551 sizeofmembers(size_t psum)
1552 {
1553 	size_t	sum = 0;
1554 	ARFILE	*fptr;
1555 	size_t	hdrsize = sizeof (struct ar_hdr);
1556 
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;
1563 
1564 		/*
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.
1568 		 *
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.
1573 		 */
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;
1581 		}
1582 	}
1583 	return (sum);
1584 }
1585 
1586 /*
1587  * Compute the size of the symbol table archive member.
1588  *
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.
1594  */
1595 static size_t
1596 sizeof_symtbl(size_t nsyms, int found_obj, size_t eltsize)
1597 {
1598 	size_t sum = 0;
1599 
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;
1604 	}
1605 
1606 	return (sum);
1607 }
1608 
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);
1616 	}
1617 }
1618 
1619 static const char *
1620 make_tmpname(const char *filename) {
1621 	char	*slash, *tmpname;
1622 	size_t	prefix_cnt = 0;
1623 
1624 	/*
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.
1628 	 */
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);
1637 	}
1638 
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);
1643 
1644 	return (tmpname);
1645 }
1646