ar: provide error exit status upon failure

Previously ar and ranlib returned with exit status 0 (success) in the
case of a missing file or other error.  Update to use error handling
similar to that added by ELF Tool Chain after that project forked
FreeBSD's ar.

PR:		PR257599 [exp-run]
Reported by:	Shawn Webb, gehmehgeh (on HardenedBSD IRC)
Reviewed by:	markj
Obtained from:	elftoolchain
MFC after:	2 months
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D31402
This commit is contained in:
Ed Maste 2021-08-03 14:30:06 -04:00
parent c6902e7796
commit 38911b3c2c
6 changed files with 100 additions and 77 deletions

View file

@ -33,8 +33,8 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "y.tab.h"
@ -72,7 +72,7 @@ SAVE|save { return (SAVE); }
[-_A-Za-z0-9/:$.\\]+ {
yylval.str = strdup(yytext);
if (yylval.str == NULL)
errc(EX_SOFTWARE, errno, "strdup failed");
errc(EXIT_FAILURE, errno, "strdup failed");
return (FNAME);
}

View file

@ -191,7 +191,7 @@ directory_cmd
;
end_cmd
: END { arscp_end(EX_OK); }
: END { arscp_end(EXIT_SUCCESS); }
;
extract_cmd
@ -655,9 +655,9 @@ ar_mode_script(struct bsdar *ar)
interactive = isatty(fileno(stdin));
while(yyparse()) {
if (!interactive)
arscp_end(1);
arscp_end(EXIT_FAILURE);
}
/* Script ends without END */
arscp_end(EX_OK);
arscp_end(EXIT_SUCCESS);
}

View file

@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "ar.h"
@ -102,10 +101,11 @@ main(int argc, char **argv)
struct bsdar *bsdar, bsdar_storage;
char *p;
size_t len;
int i, opt, Dflag, Uflag;
int exitcode, i, opt, Dflag, Uflag;
bsdar = &bsdar_storage;
memset(bsdar, 0, sizeof(*bsdar));
exitcode = EXIT_SUCCESS;
Dflag = 0;
Uflag = 0;
@ -151,9 +151,10 @@ main(int argc, char **argv)
bsdar->options |= AR_D;
bsdar->options |= AR_S;
while ((bsdar->filename = *argv++) != NULL)
ar_mode_s(bsdar);
if (ar_mode_s(bsdar))
exitcode = EXIT_FAILURE;
exit(EX_OK);
exit(exitcode);
} else {
if (argc < 2)
bsdar_usage();
@ -161,7 +162,7 @@ main(int argc, char **argv)
if (*argv[1] != '-') {
len = strlen(argv[1]) + 2;
if ((p = malloc(len)) == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, errno,
bsdar_errc(bsdar, EXIT_FAILURE, errno,
"malloc failed");
*p = '-';
(void)strlcpy(p + 1, argv[1], len - 1);
@ -262,23 +263,23 @@ main(int argc, char **argv)
bsdar_usage();
if (bsdar->options & AR_A && bsdar->options & AR_B)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"only one of -a and -[bi] options allowed");
if (bsdar->options & AR_J && bsdar->options & AR_Z)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"only one of -j and -z options allowed");
if (bsdar->options & AR_S && bsdar->options & AR_SS)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"only one of -s and -S options allowed");
if (bsdar->options & (AR_A | AR_B)) {
if (*argv == NULL)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"no position operand specified");
if ((bsdar->posarg = basename(*argv)) == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, errno,
bsdar_errc(bsdar, EXIT_FAILURE, errno,
"basename failed");
argc--;
argv++;
@ -310,7 +311,7 @@ main(int argc, char **argv)
if (bsdar->mode == 'M') {
ar_mode_script(bsdar);
exit(EX_OK);
exit(EXIT_SUCCESS);
}
if ((bsdar->filename = *argv) == NULL)
@ -321,44 +322,47 @@ main(int argc, char **argv)
if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
bsdar->options & AR_S) {
ar_mode_s(bsdar);
exitcode = ar_mode_s(bsdar);
if (!bsdar->mode)
exit(EX_OK);
exit(exitcode);
}
switch(bsdar->mode) {
case 'd':
ar_mode_d(bsdar);
exitcode = ar_mode_d(bsdar);
break;
case 'm':
ar_mode_m(bsdar);
exitcode = ar_mode_m(bsdar);
break;
case 'p':
ar_mode_p(bsdar);
exitcode = ar_mode_p(bsdar);
break;
case 'q':
ar_mode_q(bsdar);
exitcode = ar_mode_q(bsdar);
break;
case 'r':
ar_mode_r(bsdar);
exitcode = ar_mode_r(bsdar);
break;
case 't':
ar_mode_t(bsdar);
exitcode = ar_mode_t(bsdar);
break;
case 'x':
ar_mode_x(bsdar);
exitcode = ar_mode_x(bsdar);
break;
default:
bsdar_usage();
/* NOTREACHED */
}
for (i = 0; i < bsdar->argc; i++)
if (bsdar->argv[i] != NULL)
for (i = 0; i < bsdar->argc; i++) {
if (bsdar->argv[i] != NULL) {
bsdar_warnc(bsdar, 0, "%s: not found in archive",
bsdar->argv[i]);
exitcode = EXIT_FAILURE;
}
}
exit(EX_OK);
exit(exitcode);
}
static void
@ -366,7 +370,7 @@ set_mode(struct bsdar *bsdar, char opt)
{
if (bsdar->mode != '\0' && bsdar->mode != opt)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"Can't specify both -%c and -%c", opt, bsdar->mode);
bsdar->mode = opt;
}
@ -376,7 +380,7 @@ only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
{
if (strchr(valid_modes, bsdar->mode) == NULL)
bsdar_errc(bsdar, EX_USAGE, 0,
bsdar_errc(bsdar, EXIT_FAILURE, 0,
"Option %s is not permitted in mode -%c", opt, bsdar->mode);
}
@ -395,7 +399,7 @@ bsdar_usage(void)
(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
(void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
(void)fprintf(stderr, "\tar -V\n");
exit(EX_USAGE);
exit(EXIT_FAILURE);
}
static void
@ -404,19 +408,19 @@ ranlib_usage(void)
(void)fprintf(stderr, "usage: ranlib [-DtU] archive ...\n");
(void)fprintf(stderr, "\tranlib -V\n");
exit(EX_USAGE);
exit(EXIT_FAILURE);
}
static void
bsdar_version(void)
{
(void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string());
exit(EX_OK);
exit(EXIT_SUCCESS);
}
static void
ranlib_version(void)
{
(void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string());
exit(EX_OK);
exit(EXIT_SUCCESS);
}

View file

@ -54,7 +54,7 @@
*/
#define AC(CALL) do { \
if ((CALL)) \
bsdar_errc(bsdar, EX_SOFTWARE, archive_errno(a), "%s", \
bsdar_errc(bsdar, EXIT_FAILURE, archive_errno(a), "%s", \
archive_error_string(a)); \
} while (0)
@ -117,13 +117,13 @@ struct bsdar {
void bsdar_errc(struct bsdar *, int _eval, int _code,
const char *fmt, ...) __dead2;
void bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
void ar_mode_d(struct bsdar *bsdar);
void ar_mode_m(struct bsdar *bsdar);
void ar_mode_p(struct bsdar *bsdar);
void ar_mode_q(struct bsdar *bsdar);
void ar_mode_r(struct bsdar *bsdar);
void ar_mode_s(struct bsdar *bsdar);
void ar_mode_t(struct bsdar *bsdar);
void ar_mode_x(struct bsdar *bsdar);
void ar_mode_A(struct bsdar *bsdar);
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);

View file

@ -37,38 +37,38 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "ar.h"
static void read_archive(struct bsdar *bsdar, char mode);
static int read_archive(struct bsdar *bsdar, char mode);
void
int
ar_mode_p(struct bsdar *bsdar)
{
read_archive(bsdar, 'p');
return (read_archive(bsdar, 'p'));
}
void
int
ar_mode_t(struct bsdar *bsdar)
{
read_archive(bsdar, 't');
return (read_archive(bsdar, 't'));
}
void
int
ar_mode_x(struct bsdar *bsdar)
{
read_archive(bsdar, 'x');
return (read_archive(bsdar, 'x'));
}
/*
* Handle read modes: 'x', 't' and 'p'.
*/
static void
static int
read_archive(struct bsdar *bsdar, char mode)
{
struct archive *a;
@ -85,13 +85,15 @@ read_archive(struct bsdar *bsdar, char mode)
char **av;
char buf[25];
char find;
int flags, r, i;
int exitcode, flags, r, i;
if ((a = archive_read_new()) == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
bsdar_errc(bsdar, EXIT_FAILURE, 0, "archive_read_new failed");
archive_read_support_format_ar(a);
AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
exitcode = EXIT_SUCCESS;
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
@ -120,7 +122,7 @@ read_archive(struct bsdar *bsdar, char mode)
if (*av == NULL)
continue;
if ((bname = basename(*av)) == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, errno,
bsdar_errc(bsdar, EXIT_FAILURE, errno,
"basename failed");
if (strcmp(bname, name) != 0)
continue;
@ -206,11 +208,19 @@ read_archive(struct bsdar *bsdar, char mode)
r = archive_read_extract(a, entry, flags);
}
if (r)
if (r) {
bsdar_warnc(bsdar, archive_errno(a), "%s",
archive_error_string(a));
exitcode = EXIT_FAILURE;
}
}
}
if (r == ARCHIVE_FATAL)
exitcode = EXIT_FAILURE;
AC(archive_read_close(a));
AC(archive_read_free(a));
return (exitcode);
}

View file

@ -67,52 +67,52 @@ 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 void write_archive(struct bsdar *bsdar, char mode);
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);
void
int
ar_mode_d(struct bsdar *bsdar)
{
write_archive(bsdar, 'd');
return (write_archive(bsdar, 'd'));
}
void
int
ar_mode_m(struct bsdar *bsdar)
{
write_archive(bsdar, 'm');
return (write_archive(bsdar, 'm'));
}
void
int
ar_mode_q(struct bsdar *bsdar)
{
write_archive(bsdar, 'q');
return (write_archive(bsdar, 'q'));
}
void
int
ar_mode_r(struct bsdar *bsdar)
{
write_archive(bsdar, 'r');
return (write_archive(bsdar, 'r'));
}
void
int
ar_mode_s(struct bsdar *bsdar)
{
write_archive(bsdar, 's');
return (write_archive(bsdar, 's'));
}
void
int
ar_mode_A(struct bsdar *bsdar)
{
write_archive(bsdar, 'A');
return (write_archive(bsdar, 'A'));
}
/*
@ -378,16 +378,17 @@ read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
/*
* Determine the constitution of resulting archive.
*/
static void
static int
write_archive(struct bsdar *bsdar, char mode)
{
struct ar_obj *nobj, *obj, *obj_temp, *pos;
struct stat sb;
const char *bname;
char **av;
int i;
int exitcode, i;
TAILQ_INIT(&bsdar->v_obj);
exitcode = EXIT_SUCCESS;
nobj = NULL;
pos = NULL;
memset(&sb, 0, sizeof(sb));
@ -400,14 +401,14 @@ write_archive(struct bsdar *bsdar, char mode)
if (errno != ENOENT) {
bsdar_warnc(bsdar, 0, "stat %s failed",
bsdar->filename);
return;
return (EXIT_FAILURE);
}
/* We do not create archive in mode 'd', 'm' and 's'. */
if (mode != 'r' && mode != 'q') {
bsdar_warnc(bsdar, 0, "%s: no such file",
bsdar->filename);
return;
return (EXIT_FAILURE);
}
/* Issue a warning if -c is not specified when creating. */
@ -491,8 +492,10 @@ write_archive(struct bsdar *bsdar, char mode)
*/
nobj = create_obj_from_file(bsdar, *av,
obj->mtime);
if (nobj == NULL)
if (nobj == NULL) {
exitcode = EXIT_FAILURE;
goto skip_obj;
}
}
if (bsdar->options & AR_V)
@ -526,8 +529,12 @@ new_archive:
av = &bsdar->argv[i];
if (*av != NULL && (mode == 'r' || mode == 'q')) {
nobj = create_obj_from_file(bsdar, *av, 0);
if (nobj != NULL)
insert_obj(bsdar, nobj, pos);
if (nobj == NULL) {
exitcode = EXIT_FAILURE;
*av = NULL;
continue;
}
insert_obj(bsdar, nobj, pos);
if (bsdar->options & AR_V && nobj != NULL)
(void)fprintf(stdout, "a - %s\n", *av);
*av = NULL;
@ -537,6 +544,8 @@ new_archive:
write_objs:
write_objs(bsdar);
write_cleanup(bsdar);
return (exitcode);
}
/*