git: d8ffb451194e - stable/13 - ar: diff reduction against ELF Tool Chain

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Wed, 09 Feb 2022 15:26:14 UTC
The branch stable/13 has been updated by emaste:

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

commit d8ffb451194ec2d91a549e0682370f312d0ecdd3
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:25:28 +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)
---
 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);