git: 6367fd2ccea3 - stable/12 - ar: diff reduction against ELF Tool Chain

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Wed, 09 Feb 2022 16:38:09 UTC
The branch stable/12 has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=6367fd2ccea3bf283c85571d69f3f0504f0e46c4

commit 6367fd2ccea3bf283c85571d69f3f0504f0e46c4
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2021-08-04 13:54:17 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2022-02-09 15:28:19 +0000

    ar: diff reduction against ELF Tool Chain
    
    - Drop exit status from bsdar_errc.  ELF Tool Chain always returns
      EXIT_FAILURE in bsdar_errc.
    
    - Remove ar_mode_* wrappers and call ar_read_archive / ar_write_archive
      directly.
    
    Obtained from:  ELF Tool Chain
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D31496
    
    (cherry picked from commit d20e9e02db3dde383c3de1ce8cec3a8c35b3eee6)
    (cherry picked from commit c5bf58add0d523fc6e6546f3fc10d0c8b972e8e7)
    (cherry picked from commit 086f09087713e3af0a28d296a2372071b72211ef)
    (cherry picked from commit 57aaefdceccdd590f81af4b274c7a3ee61ae62f1)
    (cherry picked from commit 866c807472619371adcb2a0409a9287748a52654)
    (cherry picked from commit d8ffb451194ec2d91a549e0682370f312d0ecdd3)
---
 usr.bin/ar/acpyacc.y |  48 ++++++++++------------
 usr.bin/ar/ar.c      |  52 ++++++++----------------
 usr.bin/ar/ar.h      |  18 +++-----
 usr.bin/ar/read.c    |  34 ++++------------
 usr.bin/ar/util.c    |   4 +-
 usr.bin/ar/write.c   | 113 ++++++++++++++++-----------------------------------
 6 files changed, 86 insertions(+), 183 deletions(-)

diff --git a/usr.bin/ar/acpyacc.y b/usr.bin/ar/acpyacc.y
index 5d4eb9fb6b37..34156e1d2d58 100644
--- a/usr.bin/ar/acpyacc.y
+++ b/usr.bin/ar/acpyacc.y
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sysexits.h>
 #include <unistd.h>
 
 #include "ar.h"
@@ -250,7 +249,7 @@ arscp_open(char *fname)
 	int			 r;
 
 	if ((a = archive_read_new()) == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
 	archive_read_support_format_ar(a);
 	AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
 	if ((r = archive_read_next_header(a, &entry)))
@@ -277,15 +276,15 @@ arscp_create(char *in, char *out)
 	/* Delete previously created temporary archive, if any. */
 	if (tmpac) {
 		if (unlink(tmpac) < 0)
-			bsdar_errc(bsdar, EX_IOERR, errno, "unlink failed");
+			bsdar_errc(bsdar, errno, "unlink failed");
 		free(tmpac);
 	}
 
 	tmpac = strdup(TEMPLATE);
 	if (tmpac == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
+		bsdar_errc(bsdar, errno, "strdup failed");
 	if ((ofd = mkstemp(tmpac)) < 0)
-		bsdar_errc(bsdar, EX_IOERR, errno, "mkstemp failed");
+		bsdar_errc(bsdar, errno, "mkstemp failed");
 
 	if (in) {
 		/*
@@ -308,8 +307,7 @@ arscp_create(char *in, char *out)
 		 * (archive with only global header)
 		 */
 		if ((a = archive_write_new()) == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, 0,
-			    "archive_write_new failed");
+			bsdar_errc(bsdar, 0, "archive_write_new failed");
 		archive_write_set_format_ar_svr4(a);
 		AC(archive_write_open_fd(a, ofd));
 		AC(archive_write_close(a));
@@ -350,7 +348,7 @@ arscp_copy(int ifd, int ofd)
 		}
 	}
 	if (munmap(p, sb.st_size) < 0)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "munmap failed");
+		bsdar_errc(bsdar, errno, "munmap failed");
 	if (bytes > 0)
 		return (1);
 
@@ -369,7 +367,7 @@ arscp_addlib(char *archive, struct list *list)
 		return;
 	arscp_mlist2argv(list);
 	bsdar->addlib = archive;
-	ar_mode_A(bsdar);
+	ar_write_archive(bsdar, 'A');
 	arscp_free_argv();
 	arscp_free_mlist(list);
 }
@@ -382,7 +380,7 @@ arscp_addmod(struct list *list)
 	if (!arscp_target_exist())
 		return;
 	arscp_mlist2argv(list);
-	ar_mode_q(bsdar);
+	ar_write_archive(bsdar, 'q');
 	arscp_free_argv();
 	arscp_free_mlist(list);
 }
@@ -395,7 +393,7 @@ arscp_delete(struct list *list)
 	if (!arscp_target_exist())
 		return;
 	arscp_mlist2argv(list);
-	ar_mode_d(bsdar);
+	ar_write_archive(bsdar, 'd');
 	arscp_free_argv();
 	arscp_free_mlist(list);
 }
@@ -408,7 +406,7 @@ arscp_extract(struct list *list)
 	if (!arscp_target_exist())
 		return;
 	arscp_mlist2argv(list);
-	ar_mode_x(bsdar);
+	ar_read_archive(bsdar, 'x');
 	arscp_free_argv();
 	arscp_free_mlist(list);
 }
@@ -424,7 +422,7 @@ arscp_list(void)
 	bsdar->argv = NULL;
 	/* Always verbose. */
 	bsdar->options |= AR_V;
-	ar_mode_t(bsdar);
+	ar_read_archive(bsdar, 't');
 	bsdar->options &= ~AR_V;
 }
 
@@ -439,8 +437,7 @@ arscp_dir(char *archive, struct list *list, char *rlt)
 	if (rlt) {
 		out = stdout;
 		if ((stdout = fopen(rlt, "w")) == NULL)
-			bsdar_errc(bsdar, EX_IOERR, errno,
-			    "fopen %s failed", rlt);
+			bsdar_errc(bsdar, errno, "fopen %s failed", rlt);
 	}
 
 	bsdar->filename = archive;
@@ -452,13 +449,12 @@ arscp_dir(char *archive, struct list *list, char *rlt)
 	}
 	if (verbose)
 		bsdar->options |= AR_V;
-	ar_mode_t(bsdar);
+	ar_read_archive(bsdar, 't');
 	bsdar->options &= ~AR_V;
 
 	if (rlt) {
 		if (fclose(stdout) == EOF)
-			bsdar_errc(bsdar, EX_IOERR, errno,
-			    "fclose %s failed", rlt);
+			bsdar_errc(bsdar, errno, "fclose %s failed", rlt);
 		stdout = out;
 		free(rlt);
 	}
@@ -477,7 +473,7 @@ arscp_replace(struct list *list)
 	if (!arscp_target_exist())
 		return;
 	arscp_mlist2argv(list);
-	ar_mode_r(bsdar);
+	ar_write_archive(bsdar, 'r');
 	arscp_free_argv();
 	arscp_free_mlist(list);
 }
@@ -490,7 +486,7 @@ arscp_save(void)
 
 	if (target) {
 		if (rename(tmpac, target) < 0)
-			bsdar_errc(bsdar, EX_IOERR, errno, "rename failed");
+			bsdar_errc(bsdar, errno, "rename failed");
 		/*
 		 * mkstemp creates temp files with mode 0600, here we
 		 * set target archive mode per process umask.
@@ -498,7 +494,7 @@ arscp_save(void)
 		mask = umask(0);
 		umask(mask);
 		if (chmod(target, 0666 & ~mask) < 0)
-			bsdar_errc(bsdar, EX_IOERR, errno, "chmod failed");
+			bsdar_errc(bsdar, errno, "chmod failed");
 		free(tmpac);
 		free(target);
 		tmpac = NULL;
@@ -520,7 +516,7 @@ arscp_clear(void)
 	if (target) {
 		new_target = strdup(target);
 		if (new_target == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
+			bsdar_errc(bsdar, errno, "strdup failed");
 		arscp_create(NULL, new_target);
 	}
 }
@@ -537,7 +533,7 @@ arscp_end(int eval)
 		free(target);
 	if (tmpac) {
 		if (unlink(tmpac) == -1)
-			bsdar_errc(bsdar, EX_IOERR, errno, "unlink %s failed",
+			bsdar_errc(bsdar, errno, "unlink %s failed",
 			    tmpac);
 		free(tmpac);
 	}
@@ -568,7 +564,7 @@ arscp_mlist(struct list *list, char *str)
 
 	l = malloc(sizeof(*l));
 	if (l == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+		bsdar_errc(bsdar, errno, "malloc failed");
 	l->str = str;
 	l->next = list;
 
@@ -610,12 +606,12 @@ arscp_mlist2argv(struct list *list)
 	n = arscp_mlist_len(list);
 	argv = malloc(n * sizeof(*argv));
 	if (argv == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+		bsdar_errc(bsdar, errno, "malloc failed");
 
 	/* Note that module names are stored in reverse order in mlist. */
 	for(i = n - 1; i >= 0; i--, list = list->next) {
 		if (list == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "invalid mlist");
+			bsdar_errc(bsdar, errno, "invalid mlist");
 		argv[i] = list->str;
 	}
 
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c
index 51d114f6b7fa..4353efcb0ff2 100644
--- a/usr.bin/ar/ar.c
+++ b/usr.bin/ar/ar.c
@@ -152,7 +152,7 @@ main(int argc, char **argv)
 			bsdar->options |= AR_D;
 		bsdar->options |= AR_S;
 		while ((bsdar->filename = *argv++) != NULL)
-			if (ar_mode_s(bsdar))
+			if (ar_write_archive(bsdar, 's'))
 				exitcode = EXIT_FAILURE;
 
 		exit(exitcode);
@@ -163,8 +163,7 @@ main(int argc, char **argv)
 		if (*argv[1] != '-') {
 			len = strlen(argv[1]) + 2;
 			if ((p = malloc(len)) == NULL)
-				bsdar_errc(bsdar, EXIT_FAILURE, errno,
-				    "malloc failed");
+				bsdar_errc(bsdar, errno, "malloc failed");
 			*p = '-';
 			(void)strlcpy(p + 1, argv[1], len - 1);
 			argv[1] = p;
@@ -267,24 +266,20 @@ main(int argc, char **argv)
 		bsdar_usage();
 
 	if (bsdar->options & AR_A && bsdar->options & AR_B)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0,
+		bsdar_errc(bsdar, 0,
 		    "only one of -a and -[bi] options allowed");
 
 	if (bsdar->options & AR_J && bsdar->options & AR_Z)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0,
-		    "only one of -j and -z options allowed");
+		bsdar_errc(bsdar, 0, "only one of -j and -z options allowed");
 
 	if (bsdar->options & AR_S && bsdar->options & AR_SS)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0,
-		    "only one of -s and -S options allowed");
+		bsdar_errc(bsdar, 0, "only one of -s and -S options allowed");
 
 	if (bsdar->options & (AR_A | AR_B)) {
 		if (*argv == NULL)
-			bsdar_errc(bsdar, EXIT_FAILURE, 0,
-			    "no position operand specified");
+			bsdar_errc(bsdar, 0, "no position operand specified");
 		if ((bsdar->posarg = basename(*argv)) == NULL)
-			bsdar_errc(bsdar, EXIT_FAILURE, errno,
-			    "basename failed");
+			bsdar_errc(bsdar, errno, "basename failed");
 		argc--;
 		argv++;
 	}
@@ -326,32 +321,17 @@ main(int argc, char **argv)
 
 	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
 	    bsdar->options & AR_S) {
-		exitcode = ar_mode_s(bsdar);
+		exitcode = ar_write_archive(bsdar, 's');
 		if (!bsdar->mode)
 			exit(exitcode);
 	}
 
 	switch(bsdar->mode) {
-	case 'd':
-		exitcode = ar_mode_d(bsdar);
+	case 'd': case 'm': case 'q': case 'r':
+		exitcode = ar_write_archive(bsdar, bsdar->mode);
 		break;
-	case 'm':
-		exitcode = ar_mode_m(bsdar);
-		break;
-	case 'p':
-		exitcode = ar_mode_p(bsdar);
-		break;
-	case 'q':
-		exitcode = ar_mode_q(bsdar);
-		break;
-	case 'r':
-		exitcode = ar_mode_r(bsdar);
-		break;
-	case 't':
-		exitcode = ar_mode_t(bsdar);
-		break;
-	case 'x':
-		exitcode = ar_mode_x(bsdar);
+	case 'p': case 't': case 'x':
+		exitcode = ar_read_archive(bsdar, bsdar->mode);
 		break;
 	default:
 		bsdar_usage();
@@ -374,8 +354,8 @@ set_mode(struct bsdar *bsdar, char opt)
 {
 
 	if (bsdar->mode != '\0' && bsdar->mode != opt)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0,
-		    "Can't specify both -%c and -%c", opt, bsdar->mode);
+		bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c", opt,
+		    bsdar->mode);
 	bsdar->mode = opt;
 }
 
@@ -384,8 +364,8 @@ only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
 {
 
 	if (strchr(valid_modes, bsdar->mode) == NULL)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0,
-		    "Option %s is not permitted in mode -%c", opt, bsdar->mode);
+		bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
+		    opt, bsdar->mode);
 }
 
 static void
diff --git a/usr.bin/ar/ar.h b/usr.bin/ar/ar.h
index 21b3a669a943..bcccf93a6016 100644
--- a/usr.bin/ar/ar.h
+++ b/usr.bin/ar/ar.h
@@ -54,7 +54,7 @@
  */
 #define	AC(CALL) do {							\
 	if ((CALL))							\
-		bsdar_errc(bsdar, EXIT_FAILURE, archive_errno(a), "%s",	\
+		bsdar_errc(bsdar, archive_errno(a), "%s",		\
 		    archive_error_string(a));				\
 } while (0)
 
@@ -114,16 +114,8 @@ struct bsdar {
 	TAILQ_HEAD(, ar_obj) v_obj;	/* object(member) list */
 };
 
-void	bsdar_errc(struct bsdar *, int _eval, int _code,
-	    const char *fmt, ...) __dead2;
-void	bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
-int	ar_mode_d(struct bsdar *bsdar);
-int	ar_mode_m(struct bsdar *bsdar);
-int	ar_mode_p(struct bsdar *bsdar);
-int	ar_mode_q(struct bsdar *bsdar);
-int	ar_mode_r(struct bsdar *bsdar);
-int	ar_mode_s(struct bsdar *bsdar);
-int	ar_mode_t(struct bsdar *bsdar);
-int	ar_mode_x(struct bsdar *bsdar);
-int	ar_mode_A(struct bsdar *bsdar);
 void	ar_mode_script(struct bsdar *ar);
+int	ar_read_archive(struct bsdar *ar, int mode);
+int	ar_write_archive(struct bsdar *ar, int mode);
+void	bsdar_errc(struct bsdar *, int _code, const char *fmt, ...) __dead2;
+void	bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
diff --git a/usr.bin/ar/read.c b/usr.bin/ar/read.c
index 04130b859c32..81e0bfce1b7e 100644
--- a/usr.bin/ar/read.c
+++ b/usr.bin/ar/read.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 #include <archive.h>
 #include <archive_entry.h>
+#include <assert.h>
 #include <errno.h>
 #include <libgen.h>
 #include <stdio.h>
@@ -42,34 +43,11 @@ __FBSDID("$FreeBSD$");
 
 #include "ar.h"
 
-static int read_archive(struct bsdar *bsdar, char mode);
-
-int
-ar_mode_p(struct bsdar *bsdar)
-{
-
-	return (read_archive(bsdar, 'p'));
-}
-
-int
-ar_mode_t(struct bsdar *bsdar)
-{
-
-	return (read_archive(bsdar, 't'));
-}
-
-int
-ar_mode_x(struct bsdar *bsdar)
-{
-
-	return (read_archive(bsdar, 'x'));
-}
-
 /*
  * Handle read modes: 'x', 't' and 'p'.
  */
-static int
-read_archive(struct bsdar *bsdar, char mode)
+int
+ar_read_archive(struct bsdar *bsdar, int mode)
 {
 	struct archive		 *a;
 	struct archive_entry	 *entry;
@@ -87,8 +65,10 @@ read_archive(struct bsdar *bsdar, char mode)
 	char			  find;
 	int			  exitcode, flags, r, i;
 
+	assert(mode == 'p' || mode == 't' || mode == 'x');
+
 	if ((a = archive_read_new()) == NULL)
-		bsdar_errc(bsdar, EXIT_FAILURE, 0, "archive_read_new failed");
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
 	archive_read_support_format_ar(a);
 	AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
 
@@ -122,7 +102,7 @@ read_archive(struct bsdar *bsdar, char mode)
 				if (*av == NULL)
 					continue;
 				if ((bname = basename(*av)) == NULL)
-					bsdar_errc(bsdar, EXIT_FAILURE, errno,
+					bsdar_errc(bsdar, errno,
 					    "basename failed");
 				if (strcmp(bname, name) != 0)
 					continue;
diff --git a/usr.bin/ar/util.c b/usr.bin/ar/util.c
index 1823c5eba84a..b130d6195e47 100644
--- a/usr.bin/ar/util.c
+++ b/usr.bin/ar/util.c
@@ -77,12 +77,12 @@ bsdar_verrc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
 }
 
 void
-bsdar_errc(struct bsdar *bsdar, int eval, int code, const char *fmt, ...)
+bsdar_errc(struct bsdar *bsdar, int code, const char *fmt, ...)
 {
 	va_list ap;
 
 	va_start(ap, fmt);
 	bsdar_verrc(bsdar, code, fmt, ap);
 	va_end(ap);
-	exit(eval);
+	exit(EXIT_FAILURE);
 }
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
index 676a30f923b7..2e5620d28732 100644
--- a/usr.bin/ar/write.c
+++ b/usr.bin/ar/write.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 #include <archive.h>
 #include <archive_entry.h>
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <gelf.h>
@@ -42,7 +43,6 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sysexits.h>
 #include <unistd.h>
 
 #include "ar.h"
@@ -67,54 +67,11 @@ static void	insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
 static void	prefault_buffer(const char *buf, size_t s);
 static void	read_objs(struct bsdar *bsdar, const char *archive,
 		    int checkargv);
-static int	write_archive(struct bsdar *bsdar, char mode);
 static void	write_cleanup(struct bsdar *bsdar);
 static void	write_data(struct bsdar *bsdar, struct archive *a,
 		    const void *buf, size_t s);
 static void	write_objs(struct bsdar *bsdar);
 
-int
-ar_mode_d(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 'd'));
-}
-
-int
-ar_mode_m(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 'm'));
-}
-
-int
-ar_mode_q(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 'q'));
-}
-
-int
-ar_mode_r(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 'r'));
-}
-
-int
-ar_mode_s(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 's'));
-}
-
-int
-ar_mode_A(struct bsdar *bsdar)
-{
-
-	return (write_archive(bsdar, 'A'));
-}
-
 /*
  * Create object from file, return created obj upon success, or NULL
  * when an error occurs or the member is not newer than existing
@@ -133,7 +90,7 @@ create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
 
 	obj = malloc(sizeof(struct ar_obj));
 	if (obj == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+		bsdar_errc(bsdar, errno, "malloc failed");
 	if ((obj->fd = open(name, O_RDONLY, 0)) < 0) {
 		bsdar_warnc(bsdar, errno, "can't open file: %s", name);
 		free(obj);
@@ -142,17 +99,17 @@ create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
 
 	tmpname = strdup(name);
 	if (tmpname == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
+		bsdar_errc(bsdar, errno, "strdup failed");
 	if ((bname = basename(tmpname)) == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "basename failed");
+		bsdar_errc(bsdar, errno, "basename failed");
 	if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
 		if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+			bsdar_errc(bsdar, errno, "malloc failed");
 		(void)strncpy(obj->name, bname, _TRUNCATE_LEN);
 		obj->name[_TRUNCATE_LEN] = '\0';
 	} else
 		if ((obj->name = strdup(bname)) == NULL)
-		    bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
+		    bsdar_errc(bsdar, errno, "strdup failed");
 	free(tmpname);
 
 	if (fstat(obj->fd, &sb) < 0) {
@@ -205,14 +162,14 @@ create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
 		goto giveup;
 	}
 	if (close(obj->fd) < 0)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
+		bsdar_errc(bsdar, errno, "close failed: %s",
 		    obj->name);
 
 	return (obj);
 
 giveup:
 	if (close(obj->fd) < 0)
-		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
+		bsdar_errc(bsdar, errno, "close failed: %s",
 		    obj->name);
 	free(obj->name);
 	free(obj);
@@ -242,7 +199,7 @@ static void
 insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
 {
 	if (obj == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, 0, "try to insert a null obj");
+		bsdar_errc(bsdar, 0, "try to insert a null obj");
 
 	if (pos == NULL || obj == pos)
 		/*
@@ -285,13 +242,13 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
 	int			  i, r, find;
 
 	if ((a = archive_read_new()) == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
 	archive_read_support_format_ar(a);
 	AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
 	for (;;) {
 		r = archive_read_next_header(a, &entry);
 		if (r == ARCHIVE_FATAL)
-			bsdar_errc(bsdar, EX_DATAERR, archive_errno(a), "%s",
+			bsdar_errc(bsdar, archive_errno(a), "%s",
 			    archive_error_string(a));
 		if (r == ARCHIVE_EOF)
 			break;
@@ -322,7 +279,7 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
 				if (*av == NULL)
 					continue;
 				if ((bname = basename(*av)) == NULL)
-					bsdar_errc(bsdar, EX_SOFTWARE, errno,
+					bsdar_errc(bsdar, errno,
 					    "basename failed");
 				if (strcmp(bname, name) != 0)
 					continue;
@@ -339,8 +296,7 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
 
 		if (size > 0) {
 			if ((buff = malloc(size)) == NULL)
-				bsdar_errc(bsdar, EX_SOFTWARE, errno,
-				    "malloc failed");
+				bsdar_errc(bsdar, errno, "malloc failed");
 			if (archive_read_data(a, buff, size) != (ssize_t)size) {
 				bsdar_warnc(bsdar, archive_errno(a), "%s",
 				    archive_error_string(a));
@@ -352,10 +308,10 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
 
 		obj = malloc(sizeof(struct ar_obj));
 		if (obj == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+			bsdar_errc(bsdar, errno, "malloc failed");
 		obj->maddr = buff;
 		if ((obj->name = strdup(name)) == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
+			bsdar_errc(bsdar, errno, "strdup failed");
 		obj->size = size;
 		obj->uid = archive_entry_uid(entry);
 		obj->gid = archive_entry_gid(entry);
@@ -378,8 +334,8 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
 /*
  * Determine the constitution of resulting archive.
  */
-static int
-write_archive(struct bsdar *bsdar, char mode)
+int
+ar_write_archive(struct bsdar *bsdar, int mode)
 {
 	struct ar_obj		 *nobj, *obj, *obj_temp, *pos;
 	struct stat		  sb;
@@ -393,6 +349,9 @@ write_archive(struct bsdar *bsdar, char mode)
 	pos = NULL;
 	memset(&sb, 0, sizeof(sb));
 
+	assert(mode == 'A' || mode == 'd' || mode == 'm' || mode == 'q' ||
+	    mode == 'r' || mode == 's');
+
 	/*
 	 * Test if the specified archive exists, to figure out
 	 * whether we are creating one here.
@@ -476,8 +435,7 @@ write_archive(struct bsdar *bsdar, char mode)
 
 		TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
 			if ((bname = basename(*av)) == NULL)
-				bsdar_errc(bsdar, EX_SOFTWARE, errno,
-				    "basename failed");
+				bsdar_errc(bsdar, errno, "basename failed");
 			if (bsdar->options & AR_TR) {
 				if (strncmp(bname, obj->name, _TRUNCATE_LEN))
 					continue;
@@ -605,7 +563,7 @@ write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
 	while (s > 0) {
 		written = archive_write_data(a, buf, s);
 		if (written < 0)
-			bsdar_errc(bsdar, EX_SOFTWARE, archive_errno(a), "%s",
+			bsdar_errc(bsdar, archive_errno(a), "%s",
 			    archive_error_string(a));
 		buf = (const char *)buf + written;
 		s -= written;
@@ -629,8 +587,8 @@ write_objs(struct bsdar *bsdar)
 	uint32_t		 nr32;
 
 	if (elf_version(EV_CURRENT) == EV_NONE)
-		bsdar_errc(bsdar, EX_SOFTWARE, 0,
-		    "ELF library initialization failed: %s", elf_errmsg(-1));
+		bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
 
 	bsdar->rela_off = 0;
 
@@ -695,7 +653,7 @@ write_objs(struct bsdar *bsdar)
 	}
 
 	if ((a = archive_write_new()) == NULL)
-		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_write_new failed");
+		bsdar_errc(bsdar, 0, "archive_write_new failed");
 
 	archive_write_set_format_ar_svr4(a);
 
@@ -710,8 +668,7 @@ write_objs(struct bsdar *bsdar)
 	    bsdar->options & AR_S) {
 		entry = archive_entry_new();
 		if (entry == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, 0,
-			    "archive_entry_new failed");
+			bsdar_errc(bsdar, 0, "archive_entry_new failed");
 		if (w_sz == sizeof(uint64_t))
 			archive_entry_copy_pathname(entry, "/SYM64/");
 		else
@@ -737,8 +694,7 @@ write_objs(struct bsdar *bsdar)
 	if (bsdar->as != NULL) {
 		entry = archive_entry_new();
 		if (entry == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, 0,
-			    "archive_entry_new failed");
+			bsdar_errc(bsdar, 0, "archive_entry_new failed");
 		archive_entry_copy_pathname(entry, "//");
 		archive_entry_set_size(entry, bsdar->as_sz);
 		AC(archive_write_header(a, entry));
@@ -750,8 +706,7 @@ write_objs(struct bsdar *bsdar)
 	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
 		entry = archive_entry_new();
 		if (entry == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, 0,
-			    "archive_entry_new failed");
+			bsdar_errc(bsdar, 0, "archive_entry_new failed");
 		archive_entry_copy_pathname(entry, obj->name);
 		archive_entry_set_uid(entry, obj->uid);
 		archive_entry_set_gid(entry, obj->gid);
@@ -893,7 +848,7 @@ add_to_ar_str_table(struct bsdar *bsdar, const char *name)
 		bsdar->as_cap = _INIT_AS_CAP;
 		bsdar->as_sz = 0;
 		if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+			bsdar_errc(bsdar, errno, "malloc failed");
 	}
 
 	/*
@@ -904,7 +859,7 @@ add_to_ar_str_table(struct bsdar *bsdar, const char *name)
 		bsdar->as_cap *= 2;
 		bsdar->as = realloc(bsdar->as, bsdar->as_cap);
 		if (bsdar->as == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
+			bsdar_errc(bsdar, errno, "realloc failed");
 	}
 	strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
 	bsdar->as_sz += strlen(name);
@@ -922,14 +877,14 @@ add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
 	if (bsdar->s_so == NULL) {
 		if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
 		    NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+			bsdar_errc(bsdar, errno, "malloc failed");
 		bsdar->s_so_cap = _INIT_SYMOFF_CAP;
 		bsdar->s_cnt = 0;
 	}
 
 	if (bsdar->s_sn == NULL) {
 		if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
+			bsdar_errc(bsdar, errno, "malloc failed");
 		bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
 		bsdar->s_sn_sz = 0;
 	}
@@ -938,7 +893,7 @@ add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
 		bsdar->s_so_cap *= 2;
 		bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
 		if (bsdar->s_so == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
+			bsdar_errc(bsdar, errno, "realloc failed");
 	}
 	bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
 	if ((uint64_t)bsdar->rela_off > bsdar->s_so_max)
@@ -953,7 +908,7 @@ add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
 		bsdar->s_sn_cap *= 2;
 		bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
 		if (bsdar->s_sn == NULL)
-			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
+			bsdar_errc(bsdar, errno, "realloc failed");
 	}
 	strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
 	bsdar->s_sn_sz += strlen(name);