Ejemplo n.º 1
0
static void
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,
		    "Option %s is not permitted in mode -%c", opt, bsdar->mode);
}
Ejemplo n.º 2
0
static void
set_mode(struct bsdar *bsdar, char opt)
{

	if (bsdar->mode != '\0' && bsdar->mode != opt)
		bsdar_errc(bsdar, EX_USAGE, 0,
		    "Can't specify both -%c and -%c", opt, bsdar->mode);
	bsdar->mode = opt;
}
Ejemplo n.º 3
0
/*
 * Handle read modes: 'x', 't' and 'p'.
 */
static void
read_archive(struct bsdar *bsdar, char mode)
{
	struct archive		 *a;
	struct archive_entry	 *entry;
	struct stat		  sb;
	struct tm		 *tp;
	const char		 *bname;
	const char		 *name;
	mode_t			  md;
	size_t			  size;
	time_t			  mtime;
	uid_t			  uid;
	gid_t			  gid;
	char			**av;
	char			  buf[25];
	char			  find;
	int			  flags, r, i;

	if ((a = archive_read_new()) == NULL)
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
	archive_read_support_format_ar(a);
	AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));

	for (;;) {
		r = archive_read_next_header(a, &entry);
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
		    r == ARCHIVE_FATAL)
			bsdar_warnc(bsdar, archive_errno(a), "%s",
			    archive_error_string(a));
		if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
			break;
		if (r == ARCHIVE_RETRY) {
			bsdar_warnc(bsdar, 0, "Retrying...");
			continue;
		}

		if ((name = archive_entry_pathname(entry)) == NULL)
			break;

		/* Skip pseudo members. */
		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0 ||
		    strcmp(name, "/SYM64/") == 0)
			continue;

		if (bsdar->argc > 0) {
			find = 0;
			for(i = 0; i < bsdar->argc; i++) {
				av = &bsdar->argv[i];
				if (*av == NULL)
					continue;
				if ((bname = basename(*av)) == NULL)
					bsdar_errc(bsdar, EX_SOFTWARE, errno,
					    "basename failed");
				if (strcmp(bname, name) != 0)
					continue;

				*av = NULL;
				find = 1;
				break;
			}
			if (!find)
				continue;
		}

		if (mode == 't') {
			if (bsdar->options & AR_V) {
				md = archive_entry_mode(entry);
				uid = archive_entry_uid(entry);
				gid = archive_entry_gid(entry);
				size = archive_entry_size(entry);
				mtime = archive_entry_mtime(entry);
				(void)strmode(md, buf);
				(void)fprintf(stdout, "%s %6d/%-6d %8ju ",
				    buf + 1, uid, gid, (uintmax_t)size);
				tp = localtime(&mtime);
				(void)strftime(buf, sizeof(buf),
				    "%b %e %H:%M %Y", tp);
				(void)fprintf(stdout, "%s %s", buf, name);
			} else
				(void)fprintf(stdout, "%s", name);
			r = archive_read_data_skip(a);
			if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
			    r == ARCHIVE_FATAL) {
				(void)fprintf(stdout, "\n");
				bsdar_warnc(bsdar, archive_errno(a), "%s",
				    archive_error_string(a));
			}

			if (r == ARCHIVE_FATAL)
				break;

			(void)fprintf(stdout, "\n");
		} else {
			/* mode == 'x' || mode = 'p' */
			if (mode == 'p') {
				if (bsdar->options & AR_V) {
					(void)fprintf(stdout, "\n<%s>\n\n",
					    name);
					fflush(stdout);
				}
				r = archive_read_data_into_fd(a, 1);
			} else {
				/* mode == 'x' */
				if (stat(name, &sb) != 0) {
					if (errno != ENOENT) {
						bsdar_warnc(bsdar, 0,
						    "stat %s failed",
						    bsdar->filename);
						continue;
					}
				} else {
					/* stat success, file exist */
					if (bsdar->options & AR_CC)
						continue;
					if (bsdar->options & AR_U &&
					    archive_entry_mtime(entry) <=
					    sb.st_mtime)
						continue;
				}

				if (bsdar->options & AR_V)
					(void)fprintf(stdout, "x - %s\n", name);
				/* Disallow absolute paths. */
				if (name[0] == '/') {
					bsdar_warnc(bsdar, 0,
					    "Absolute path '%s'", name);
					continue;
				}
				/* Basic path security flags. */
				flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
				    ARCHIVE_EXTRACT_SECURE_NODOTDOT;
				if (bsdar->options & AR_O)
					flags |= ARCHIVE_EXTRACT_TIME;

				r = archive_read_extract(a, entry, flags);
			}

			if (r)
				bsdar_warnc(bsdar, archive_errno(a), "%s",
				    archive_error_string(a));
		}
	}
	AC(archive_read_close(a));
	AC(archive_read_free(a));
}
Ejemplo n.º 4
0
int
main(int argc, char **argv)
{
	struct bsdar	*bsdar, bsdar_storage;
	char		*p;
	size_t		 len;
	int		 i, opt;

	bsdar = &bsdar_storage;
	memset(bsdar, 0, sizeof(*bsdar));

	if ((bsdar->progname = getprogname()) == NULL)
		bsdar->progname = "ar";

	/* Act like ranlib if our name ends in "ranlib"; this
	 * accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
	len = strlen(bsdar->progname);
	if (len >= strlen("ranlib") &&
	    strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
		while ((opt = getopt_long(argc, argv, "tDV", longopts,
		    NULL)) != -1) {
			switch(opt) {
			case 't':
				/* Ignored. */
				break;
			case 'D':
				bsdar->options |= AR_D;
				break;
			case 'V':
				ranlib_version();
				break;
			case OPTION_HELP:
				ranlib_usage();
			default:
				ranlib_usage();
			}
		}
		argv += optind;
		argc -= optind;

		if (*argv == NULL)
			ranlib_usage();

		bsdar->options |= AR_S;
		for (;(bsdar->filename = *argv++) != NULL;)
			ar_mode_s(bsdar);

		exit(EX_OK);
	} else {
		if (argc < 2)
			bsdar_usage();

		if (*argv[1] != '-') {
			len = strlen(argv[1]) + 2;
			if ((p = malloc(len)) == NULL)
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
				    "malloc failed");
			*p = '-';
			(void)strlcpy(p + 1, argv[1], len - 1);
			argv[1] = p;
		}
	}

	while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtuVvxz",
	    longopts, NULL)) != -1) {
		switch(opt) {
		case 'a':
			bsdar->options |= AR_A;
			break;
		case 'b':
		case 'i':
			bsdar->options |= AR_B;
			break;
		case 'C':
			bsdar->options |= AR_CC;
			break;
		case 'c':
			bsdar->options |= AR_C;
			break;
		case 'd':
			set_mode(bsdar, opt);
			break;
		case 'D':
			bsdar->options |= AR_D;
			break;
		case 'f':
		case 'T':
			bsdar->options |= AR_TR;
			break;
		case 'j':
			/* ignored */
			break;
		case 'l':
			/* ignored, for GNU ar comptibility */
			break;
		case 'M':
			set_mode(bsdar, opt);
			break;
		case 'm':
			set_mode(bsdar, opt);
			break;
		case 'o':
			bsdar->options |= AR_O;
			break;
		case 'p':
			set_mode(bsdar, opt);
			break;
		case 'q':
			set_mode(bsdar, opt);
			break;
		case 'r':
			set_mode(bsdar, opt);
			break;
		case 'S':
			bsdar->options |= AR_SS;
			break;
		case 's':
			bsdar->options |= AR_S;
			break;
		case 't':
			set_mode(bsdar, opt);
			break;
		case 'u':
			bsdar->options |= AR_U;
			break;
		case 'V':
			bsdar_version();
			break;
		case 'v':
			bsdar->options |= AR_V;
			break;
		case 'x':
			set_mode(bsdar, opt);
			break;
		case 'z':
			/* ignored */
			break;
		case OPTION_HELP:
			bsdar_usage();
		default:
			bsdar_usage();
		}
	}

	argv += optind;
	argc -= optind;

	if (*argv == NULL && bsdar->mode != 'M')
		bsdar_usage();

	if (bsdar->options & AR_A && bsdar->options & AR_B)
		bsdar_errc(bsdar, EX_USAGE, 0,
		    "only one of -a and -[bi] options allowed");

	if (bsdar->options & AR_J && bsdar->options & AR_Z)
		bsdar_errc(bsdar, EX_USAGE, 0,
		    "only one of -j and -z options allowed");

	if (bsdar->options & AR_S && bsdar->options & AR_SS)
		bsdar_errc(bsdar, EX_USAGE, 0,
		    "only one of -s and -S options allowed");

	if (bsdar->options & (AR_A | AR_B)) {
		if ((bsdar->posarg = *argv) == NULL)
			bsdar_errc(bsdar, EX_USAGE, 0,
			    "no position operand specified");
		if ((bsdar->posarg = basename(bsdar->posarg)) == NULL)
			bsdar_errc(bsdar, EX_SOFTWARE, errno,
			    "basename failed");
		argc--;
		argv++;
	}

	if (bsdar->options & AR_A)
		only_mode(bsdar, "-a", "mqr");
	if (bsdar->options & AR_B)
		only_mode(bsdar, "-b", "mqr");
	if (bsdar->options & AR_C)
		only_mode(bsdar, "-c", "qr");
	if (bsdar->options & AR_CC)
		only_mode(bsdar, "-C", "x");
	if (bsdar->options & AR_D)
		only_mode(bsdar, "-D", "qr");
	if (bsdar->options & AR_O)
		only_mode(bsdar, "-o", "x");
	if (bsdar->options & AR_SS)
		only_mode(bsdar, "-S", "mqr");
	if (bsdar->options & AR_U)
		only_mode(bsdar, "-u", "qrx");

	if (bsdar->mode == 'M') {
		ar_mode_script(bsdar);
		exit(EX_OK);
	}

	if ((bsdar->filename = *argv) == NULL)
		bsdar_usage();

	bsdar->argc = --argc;
	bsdar->argv = ++argv;

	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
	    bsdar->options & AR_S) {
		ar_mode_s(bsdar);
		if (!bsdar->mode)
			exit(EX_OK);
	}

	switch(bsdar->mode) {
	case 'd':
		ar_mode_d(bsdar);
		break;
	case 'm':
		ar_mode_m(bsdar);
		break;
	case 'p':
		ar_mode_p(bsdar);
		break;
	case 'q':
		ar_mode_q(bsdar);
		break;
	case 'r':
		ar_mode_r(bsdar);
		break;
	case 't':
		ar_mode_t(bsdar);
		break;
	case 'x':
		ar_mode_x(bsdar);
		break;
	default:
		bsdar_usage();
		/* NOTREACHED */
	}

	for (i = 0; i < bsdar->argc; i++)
		if (bsdar->argv[i] != NULL)
			bsdar_warnc(bsdar, 0, "%s: not found in archive",
			    bsdar->argv[i]);

	exit(EX_OK);
}
Ejemplo n.º 5
0
/*
 * Handle read modes: 'x', 't' and 'p'.
 */
void
ar_read_archive(struct bsdar *bsdar, int mode)
{
	FILE			 *out;
	struct archive		 *a;
	struct archive_entry	 *entry;
	struct stat		  sb;
	struct tm		 *tp;
	const char		 *bname;
	const char		 *name;
	mode_t			  md;
	size_t			  size;
	time_t			  mtime;
	uid_t			  uid;
	gid_t			  gid;
	char			**av;
	char			  buf[25];
	char			  find;
	int			  i, flags, r;

	assert(mode == 'p' || mode == 't' || mode == 'x');

	if ((a = archive_read_new()) == NULL)
		bsdar_errc(bsdar, 0, "archive_read_new failed");
	archive_read_support_compression_none(a);
	archive_read_support_format_ar(a);
	AC(archive_read_open_file(a, bsdar->filename, DEF_BLKSZ));

	out = bsdar->output;

	for (;;) {
		r = archive_read_next_header(a, &entry);
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
		    r == ARCHIVE_FATAL)
			bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
		if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
			break;
		if (r == ARCHIVE_RETRY) {
			bsdar_warnc(bsdar, 0, "Retrying...");
			continue;
		}

		if (archive_format(a) == ARCHIVE_FORMAT_AR_BSD)
			bsdar->options |= AR_BSD;
		else
			bsdar->options &= ~AR_BSD;

		name = archive_entry_pathname(entry);

		/* Skip pseudo members. */
		if (bsdar_is_pseudomember(bsdar, name))
			continue;

		if (bsdar->argc > 0) {
			find = 0;
			for(i = 0; i < bsdar->argc; i++) {
				av = &bsdar->argv[i];
				if (*av == NULL)
					continue;
				if ((bname = basename(*av)) == NULL)
					bsdar_errc(bsdar, errno,
					    "basename failed");
				if (strcmp(bname, name) != 0)
					continue;

				*av = NULL;
				find = 1;
				break;
			}
			if (!find)
				continue;
		}

		if (mode == 't') {
			if (bsdar->options & AR_V) {
				md = archive_entry_mode(entry);
				uid = archive_entry_uid(entry);
				gid = archive_entry_gid(entry);
				size = archive_entry_size(entry);
				mtime = archive_entry_mtime(entry);
				(void)fprintf(out, "%s %6d/%-6d %8ju ",
				    bsdar_strmode(md) + 1, uid, gid,
				    (uintmax_t)size);
				tp = localtime(&mtime);
				(void)strftime(buf, sizeof(buf),
				    "%b %e %H:%M %Y", tp);
				(void)fprintf(out, "%s %s", buf, name);
			} else
				(void)fprintf(out, "%s", name);
			r = archive_read_data_skip(a);
			if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
			    r == ARCHIVE_FATAL) {
				(void)fprintf(out, "\n");
				bsdar_warnc(bsdar, 0, "%s",
				    archive_error_string(a));
			}

			if (r == ARCHIVE_FATAL)
				break;

			(void)fprintf(out, "\n");
		} else {
			/* mode == 'x' || mode = 'p' */
			if (mode == 'p') {
				if (bsdar->options & AR_V) {
					(void)fprintf(out, "\n<%s>\n\n",
					    name);
					fflush(out);
				}
				r = archive_read_data_into_fd(a, fileno(out));
			} else {
				/* mode == 'x' */
				if (stat(name, &sb) != 0) {
					if (errno != ENOENT) {
						bsdar_warnc(bsdar, 0,
						    "stat %s failed",
						    bsdar->filename);
						continue;
					}
				} else {
					/* stat success, file exist */
					if (bsdar->options & AR_CC)
						continue;
					if (bsdar->options & AR_U &&
					    archive_entry_mtime(entry) <=
					    sb.st_mtime)
						continue;
				}

				if (bsdar->options & AR_V)
					(void)fprintf(out, "x - %s\n", name);
				flags = 0;
				if (bsdar->options & AR_O)
					flags |= ARCHIVE_EXTRACT_TIME;

				r = archive_read_extract(a, entry, flags);
			}

			if (r)
				bsdar_warnc(bsdar, 0, "%s",
				    archive_error_string(a));
		}
	}
	AC(archive_read_close(a));
	ACV(archive_read_finish(a));
}