diff options
author | kaiw <kaiw@FreeBSD.org> | 2008-02-21 10:52:31 +0000 |
---|---|---|
committer | kaiw <kaiw@FreeBSD.org> | 2008-02-21 10:52:31 +0000 |
commit | bd49e931f20cf4f25d0c085cf7b048efe16cb93b (patch) | |
tree | d7041e81552890443b432a04c0b9adb7cfa9afeb /usr.bin/ar/ar.c | |
parent | afb9fa5a4b87c13a6d671aa0b02c9e13af0f4146 (diff) | |
download | FreeBSD-src-bd49e931f20cf4f25d0c085cf7b048efe16cb93b.zip FreeBSD-src-bd49e931f20cf4f25d0c085cf7b048efe16cb93b.tar.gz |
Import ar(1) front-end. (aka 'BSD' ar)
Reviewed by: jkoshy
Approved by: jkoshy (mentor)
Tested by: erwin (ports build test on pointyhat)
Sponsored by: Google Summer of Code 2007
Reviewed by (earlier version): Jaakko Heinonen <jh[AT]saunalahti.fi>
Tested by (earlier version): Steve Kargl <sgk[AT]troutmask.apl.washington.edu>
Tested by (earlier version): Martin Voros <martin_voros[AT]yahoo.com>
Tested by (earlier version): swell.k[AT]gmail.com
Tested by (earlier version): joel
Tested by (earlier version): Alexey Shuvaev <shuvaev[AT]physik.uni-wuerzburg.de>
Tested by (earlier version): Arjan van Leeuwen <avleeuwen[AT]gmail.com>
Thanks to gabor@ for building ports for it.
Thanks to erwin@ and kris@ for scheduling the ports build test on pointyhat.
And thanks to many others for their feedback.
Diffstat (limited to 'usr.bin/ar/ar.c')
-rw-r--r-- | usr.bin/ar/ar.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c new file mode 100644 index 0000000..2399f9f --- /dev/null +++ b/usr.bin/ar/ar.c @@ -0,0 +1,377 @@ +/*- + * Copyright (c) 2007 Kai Wang + * Copyright (c) 2007 Tim Kientzle + * Copyright (c) 2007 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Hugh Smith at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/queue.h> +#include <sys/types.h> +#include <archive.h> +#include <errno.h> +#include <getopt.h> +#include <libgen.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> + +#include "ar.h" + +enum options +{ + OPTION_HELP +}; + +static struct option longopts[] = +{ + {"help", no_argument, NULL, OPTION_HELP}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} +}; + +static void bsdar_usage(void); +static void ranlib_usage(void); +static void set_mode(struct bsdar *bsdar, char opt); +static void only_mode(struct bsdar *bsdar, const char *opt, + const char *valid_modes); +static void bsdar_version(void); +static void ranlib_version(void); + +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"; + + if (strcmp(bsdar->progname, "ranlib") == 0) { + while ((opt = getopt_long(argc, argv, "tV", longopts, + NULL)) != -1) { + switch(opt) { + case 't': + /* Ignored. */ + 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, "abCcdfijlmopqrSsTtuVvxz", + 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 'f': + case 'T': + bsdar->options |= AR_TR; + break; + case 'j': + bsdar->options |= AR_J; + break; + case 'l': + /* ignored, for GNU ar comptibility */ + 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': + bsdar->options |= AR_Z; + break; + case OPTION_HELP: + bsdar_usage(); + default: + bsdar_usage(); + } + } + + argv += optind; + argc -= optind; + + if (*argv == NULL) + 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_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->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_r(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); +} + +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; +} + +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); +} + +static void +bsdar_usage() +{ + + (void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n"); + (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n"); + (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n"); + (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); + (void)fprintf(stderr, "\tar -r [-Tcjsuvz] archive file ...\n"); + (void)fprintf(stderr, "\tar -r [-Tabcijsuvz] position archive file ...\n"); + (void)fprintf(stderr, "\tar -s [-jz] archive\n"); + (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); +} + +static void +ranlib_usage() +{ + + (void)fprintf(stderr, "usage: ranlib [-t] archive ...\n"); + (void)fprintf(stderr, "\tranlib -V\n"); + exit(EX_USAGE); +} + +static void +bsdar_version() +{ + (void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version()); + exit(EX_OK); +} + +static void +ranlib_version() +{ + (void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version()); + exit(EX_OK); +} |