1176434Skaiw/*- 2176434Skaiw * Copyright (c) 2007 Kai Wang 3176434Skaiw * Copyright (c) 2007 Tim Kientzle 4176434Skaiw * Copyright (c) 2007 Joseph Koshy 5176434Skaiw * All rights reserved. 6176434Skaiw * 7176434Skaiw * Redistribution and use in source and binary forms, with or without 8176434Skaiw * modification, are permitted provided that the following conditions 9176434Skaiw * are met: 10176434Skaiw * 1. Redistributions of source code must retain the above copyright 11176434Skaiw * notice, this list of conditions and the following disclaimer 12176434Skaiw * in this position and unchanged. 13176434Skaiw * 2. Redistributions in binary form must reproduce the above copyright 14176434Skaiw * notice, this list of conditions and the following disclaimer in the 15176434Skaiw * documentation and/or other materials provided with the distribution. 16176434Skaiw * 17176434Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 18176434Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19176434Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20176434Skaiw * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21176434Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22176434Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23176434Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24176434Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25176434Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26176434Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27176434Skaiw */ 28176434Skaiw 29176434Skaiw/*- 30176434Skaiw * Copyright (c) 1990, 1993, 1994 31176434Skaiw * The Regents of the University of California. All rights reserved. 32176434Skaiw * 33176434Skaiw * This code is derived from software contributed to Berkeley by 34176434Skaiw * Hugh Smith at The University of Guelph. 35176434Skaiw * 36176434Skaiw * Redistribution and use in source and binary forms, with or without 37176434Skaiw * modification, are permitted provided that the following conditions 38176434Skaiw * are met: 39176434Skaiw * 1. Redistributions of source code must retain the above copyright 40176434Skaiw * notice, this list of conditions and the following disclaimer. 41176434Skaiw * 2. Redistributions in binary form must reproduce the above copyright 42176434Skaiw * notice, this list of conditions and the following disclaimer in the 43176434Skaiw * documentation and/or other materials provided with the distribution. 44176434Skaiw * 3. Neither the name of the University nor the names of its contributors 45176434Skaiw * may be used to endorse or promote products derived from this software 46176434Skaiw * without specific prior written permission. 47176434Skaiw * 48176434Skaiw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49176434Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50176434Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51176434Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52176434Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53176434Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54176434Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55176434Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56176434Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57176434Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58176434Skaiw * SUCH DAMAGE. 59176434Skaiw */ 60176434Skaiw 61176434Skaiw#include <sys/cdefs.h> 62176434Skaiw__FBSDID("$FreeBSD$"); 63176434Skaiw 64176434Skaiw#include <sys/queue.h> 65176434Skaiw#include <sys/types.h> 66176434Skaiw#include <archive.h> 67176434Skaiw#include <errno.h> 68176434Skaiw#include <getopt.h> 69176434Skaiw#include <libgen.h> 70176434Skaiw#include <stdio.h> 71176434Skaiw#include <stdlib.h> 72176434Skaiw#include <string.h> 73176434Skaiw#include <sysexits.h> 74176434Skaiw 75176434Skaiw#include "ar.h" 76176434Skaiw 77176434Skaiwenum options 78176434Skaiw{ 79176434Skaiw OPTION_HELP 80176434Skaiw}; 81176434Skaiw 82176434Skaiwstatic struct option longopts[] = 83176434Skaiw{ 84176434Skaiw {"help", no_argument, NULL, OPTION_HELP}, 85176434Skaiw {"version", no_argument, NULL, 'V'}, 86176434Skaiw {NULL, 0, NULL, 0} 87176434Skaiw}; 88176434Skaiw 89176434Skaiwstatic void bsdar_usage(void); 90176434Skaiwstatic void ranlib_usage(void); 91176434Skaiwstatic void set_mode(struct bsdar *bsdar, char opt); 92176434Skaiwstatic void only_mode(struct bsdar *bsdar, const char *opt, 93176434Skaiw const char *valid_modes); 94176434Skaiwstatic void bsdar_version(void); 95176434Skaiwstatic void ranlib_version(void); 96176434Skaiw 97176434Skaiwint 98176434Skaiwmain(int argc, char **argv) 99176434Skaiw{ 100176434Skaiw struct bsdar *bsdar, bsdar_storage; 101176434Skaiw char *p; 102176434Skaiw size_t len; 103288202Semaste int i, opt, Dflag, Uflag; 104176434Skaiw 105176434Skaiw bsdar = &bsdar_storage; 106176434Skaiw memset(bsdar, 0, sizeof(*bsdar)); 107288202Semaste Dflag = 0; 108288202Semaste Uflag = 0; 109176434Skaiw 110176434Skaiw if ((bsdar->progname = getprogname()) == NULL) 111176434Skaiw bsdar->progname = "ar"; 112176434Skaiw 113190162Skientzle /* Act like ranlib if our name ends in "ranlib"; this 114222122Sbcr * accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */ 115190162Skientzle len = strlen(bsdar->progname); 116190162Skientzle if (len >= strlen("ranlib") && 117190162Skientzle strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) { 118287326Semaste while ((opt = getopt_long(argc, argv, "tDUV", longopts, 119176434Skaiw NULL)) != -1) { 120176434Skaiw switch(opt) { 121176434Skaiw case 't': 122176434Skaiw /* Ignored. */ 123176434Skaiw break; 124216014Skaiw case 'D': 125288202Semaste Dflag = 1; 126288202Semaste Uflag = 0; 127216014Skaiw break; 128287326Semaste case 'U': 129288202Semaste Uflag = 1; 130288202Semaste Dflag = 0; 131287326Semaste break; 132176434Skaiw case 'V': 133176434Skaiw ranlib_version(); 134176434Skaiw break; 135176434Skaiw case OPTION_HELP: 136176434Skaiw ranlib_usage(); 137176434Skaiw default: 138176434Skaiw ranlib_usage(); 139176434Skaiw } 140176434Skaiw } 141176434Skaiw argv += optind; 142176434Skaiw argc -= optind; 143176434Skaiw 144176434Skaiw if (*argv == NULL) 145176434Skaiw ranlib_usage(); 146176434Skaiw 147288202Semaste /* Enable determinstic mode unless -U is set. */ 148288202Semaste if (Uflag == 0) 149288202Semaste bsdar->options |= AR_D; 150176434Skaiw bsdar->options |= AR_S; 151288172Semaste while ((bsdar->filename = *argv++) != NULL) 152176434Skaiw ar_mode_s(bsdar); 153176434Skaiw 154176434Skaiw exit(EX_OK); 155176434Skaiw } else { 156176434Skaiw if (argc < 2) 157176434Skaiw bsdar_usage(); 158176434Skaiw 159176434Skaiw if (*argv[1] != '-') { 160176434Skaiw len = strlen(argv[1]) + 2; 161176434Skaiw if ((p = malloc(len)) == NULL) 162176434Skaiw bsdar_errc(bsdar, EX_SOFTWARE, errno, 163176434Skaiw "malloc failed"); 164176434Skaiw *p = '-'; 165176434Skaiw (void)strlcpy(p + 1, argv[1], len - 1); 166176434Skaiw argv[1] = p; 167176434Skaiw } 168176434Skaiw } 169176434Skaiw 170287326Semaste while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz", 171176434Skaiw longopts, NULL)) != -1) { 172176434Skaiw switch(opt) { 173176434Skaiw case 'a': 174176434Skaiw bsdar->options |= AR_A; 175176434Skaiw break; 176176434Skaiw case 'b': 177176434Skaiw case 'i': 178176434Skaiw bsdar->options |= AR_B; 179176434Skaiw break; 180176434Skaiw case 'C': 181176434Skaiw bsdar->options |= AR_CC; 182176434Skaiw break; 183176434Skaiw case 'c': 184176434Skaiw bsdar->options |= AR_C; 185176434Skaiw break; 186176434Skaiw case 'd': 187176434Skaiw set_mode(bsdar, opt); 188176434Skaiw break; 189213643Skientzle case 'D': 190288202Semaste Dflag = 1; 191288202Semaste Uflag = 0; 192213643Skientzle break; 193176434Skaiw case 'f': 194176434Skaiw case 'T': 195176434Skaiw bsdar->options |= AR_TR; 196176434Skaiw break; 197176434Skaiw case 'j': 198208189Skaiw /* ignored */ 199176434Skaiw break; 200176434Skaiw case 'l': 201176434Skaiw /* ignored, for GNU ar comptibility */ 202176434Skaiw break; 203183218Skaiw case 'M': 204183218Skaiw set_mode(bsdar, opt); 205183218Skaiw break; 206176434Skaiw case 'm': 207176434Skaiw set_mode(bsdar, opt); 208176434Skaiw break; 209176434Skaiw case 'o': 210176434Skaiw bsdar->options |= AR_O; 211176434Skaiw break; 212176434Skaiw case 'p': 213176434Skaiw set_mode(bsdar, opt); 214176434Skaiw break; 215176434Skaiw case 'q': 216176434Skaiw set_mode(bsdar, opt); 217176434Skaiw break; 218176434Skaiw case 'r': 219176434Skaiw set_mode(bsdar, opt); 220176434Skaiw break; 221176434Skaiw case 'S': 222176434Skaiw bsdar->options |= AR_SS; 223176434Skaiw break; 224176434Skaiw case 's': 225176434Skaiw bsdar->options |= AR_S; 226176434Skaiw break; 227176434Skaiw case 't': 228176434Skaiw set_mode(bsdar, opt); 229176434Skaiw break; 230287326Semaste case 'U': 231288202Semaste Uflag = 1; 232288202Semaste Dflag = 0; 233287326Semaste break; 234176434Skaiw case 'u': 235176434Skaiw bsdar->options |= AR_U; 236176434Skaiw break; 237176434Skaiw case 'V': 238176434Skaiw bsdar_version(); 239176434Skaiw break; 240176434Skaiw case 'v': 241176434Skaiw bsdar->options |= AR_V; 242176434Skaiw break; 243176434Skaiw case 'x': 244176434Skaiw set_mode(bsdar, opt); 245176434Skaiw break; 246176434Skaiw case 'z': 247208189Skaiw /* ignored */ 248176434Skaiw break; 249176434Skaiw case OPTION_HELP: 250176434Skaiw bsdar_usage(); 251176434Skaiw default: 252176434Skaiw bsdar_usage(); 253176434Skaiw } 254176434Skaiw } 255176434Skaiw 256176434Skaiw argv += optind; 257176434Skaiw argc -= optind; 258176434Skaiw 259183218Skaiw if (*argv == NULL && bsdar->mode != 'M') 260176434Skaiw bsdar_usage(); 261176434Skaiw 262176434Skaiw if (bsdar->options & AR_A && bsdar->options & AR_B) 263176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 264176434Skaiw "only one of -a and -[bi] options allowed"); 265176434Skaiw 266176434Skaiw if (bsdar->options & AR_J && bsdar->options & AR_Z) 267176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 268176434Skaiw "only one of -j and -z options allowed"); 269176434Skaiw 270176434Skaiw if (bsdar->options & AR_S && bsdar->options & AR_SS) 271176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 272176434Skaiw "only one of -s and -S options allowed"); 273176434Skaiw 274176434Skaiw if (bsdar->options & (AR_A | AR_B)) { 275176434Skaiw if ((bsdar->posarg = *argv) == NULL) 276176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 277176434Skaiw "no position operand specified"); 278176434Skaiw if ((bsdar->posarg = basename(bsdar->posarg)) == NULL) 279176434Skaiw bsdar_errc(bsdar, EX_SOFTWARE, errno, 280176434Skaiw "basename failed"); 281176434Skaiw argc--; 282176434Skaiw argv++; 283176434Skaiw } 284176434Skaiw 285288202Semaste /* Set determinstic mode for -D, and by default without -U. */ 286303295Semaste if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r' || 287303295Semaste (bsdar->mode == '\0' && bsdar->options & AR_S)))) 288288202Semaste bsdar->options |= AR_D; 289288202Semaste 290176434Skaiw if (bsdar->options & AR_A) 291176434Skaiw only_mode(bsdar, "-a", "mqr"); 292176434Skaiw if (bsdar->options & AR_B) 293176434Skaiw only_mode(bsdar, "-b", "mqr"); 294176434Skaiw if (bsdar->options & AR_C) 295176434Skaiw only_mode(bsdar, "-c", "qr"); 296176434Skaiw if (bsdar->options & AR_CC) 297176434Skaiw only_mode(bsdar, "-C", "x"); 298288202Semaste if (Dflag) 299213643Skientzle only_mode(bsdar, "-D", "qr"); 300288202Semaste if (Uflag) 301288202Semaste only_mode(bsdar, "-U", "qr"); 302176434Skaiw if (bsdar->options & AR_O) 303176434Skaiw only_mode(bsdar, "-o", "x"); 304176434Skaiw if (bsdar->options & AR_SS) 305176434Skaiw only_mode(bsdar, "-S", "mqr"); 306176434Skaiw if (bsdar->options & AR_U) 307176434Skaiw only_mode(bsdar, "-u", "qrx"); 308176434Skaiw 309183218Skaiw if (bsdar->mode == 'M') { 310183218Skaiw ar_mode_script(bsdar); 311183218Skaiw exit(EX_OK); 312183218Skaiw } 313183218Skaiw 314176434Skaiw if ((bsdar->filename = *argv) == NULL) 315176434Skaiw bsdar_usage(); 316176434Skaiw 317176434Skaiw bsdar->argc = --argc; 318176434Skaiw bsdar->argv = ++argv; 319176434Skaiw 320176434Skaiw if ((!bsdar->mode || strchr("ptx", bsdar->mode)) && 321176434Skaiw bsdar->options & AR_S) { 322176434Skaiw ar_mode_s(bsdar); 323176434Skaiw if (!bsdar->mode) 324176434Skaiw exit(EX_OK); 325176434Skaiw } 326176434Skaiw 327176434Skaiw switch(bsdar->mode) { 328176434Skaiw case 'd': 329176434Skaiw ar_mode_d(bsdar); 330176434Skaiw break; 331176434Skaiw case 'm': 332176434Skaiw ar_mode_m(bsdar); 333176434Skaiw break; 334176434Skaiw case 'p': 335176434Skaiw ar_mode_p(bsdar); 336176434Skaiw break; 337176434Skaiw case 'q': 338177064Skaiw ar_mode_q(bsdar); 339176434Skaiw break; 340176434Skaiw case 'r': 341176434Skaiw ar_mode_r(bsdar); 342176434Skaiw break; 343176434Skaiw case 't': 344176434Skaiw ar_mode_t(bsdar); 345176434Skaiw break; 346176434Skaiw case 'x': 347176434Skaiw ar_mode_x(bsdar); 348176434Skaiw break; 349176434Skaiw default: 350176434Skaiw bsdar_usage(); 351176434Skaiw /* NOTREACHED */ 352176434Skaiw } 353176434Skaiw 354176434Skaiw for (i = 0; i < bsdar->argc; i++) 355176434Skaiw if (bsdar->argv[i] != NULL) 356176434Skaiw bsdar_warnc(bsdar, 0, "%s: not found in archive", 357176434Skaiw bsdar->argv[i]); 358176434Skaiw 359176434Skaiw exit(EX_OK); 360176434Skaiw} 361176434Skaiw 362176434Skaiwstatic void 363176434Skaiwset_mode(struct bsdar *bsdar, char opt) 364176434Skaiw{ 365176434Skaiw 366176434Skaiw if (bsdar->mode != '\0' && bsdar->mode != opt) 367176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 368176434Skaiw "Can't specify both -%c and -%c", opt, bsdar->mode); 369176434Skaiw bsdar->mode = opt; 370176434Skaiw} 371176434Skaiw 372176434Skaiwstatic void 373176434Skaiwonly_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes) 374176434Skaiw{ 375176434Skaiw 376176434Skaiw if (strchr(valid_modes, bsdar->mode) == NULL) 377176434Skaiw bsdar_errc(bsdar, EX_USAGE, 0, 378176434Skaiw "Option %s is not permitted in mode -%c", opt, bsdar->mode); 379176434Skaiw} 380176434Skaiw 381176434Skaiwstatic void 382201382Sedbsdar_usage(void) 383176434Skaiw{ 384176434Skaiw 385176434Skaiw (void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n"); 386176434Skaiw (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n"); 387176434Skaiw (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n"); 388176434Skaiw (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); 389287326Semaste (void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n"); 390287326Semaste (void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n"); 391287326Semaste (void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n"); 392176434Skaiw (void)fprintf(stderr, "\tar -s [-jz] archive\n"); 393176434Skaiw (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); 394176434Skaiw (void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n"); 395176434Skaiw (void)fprintf(stderr, "\tar -V\n"); 396176434Skaiw exit(EX_USAGE); 397176434Skaiw} 398176434Skaiw 399176434Skaiwstatic void 400201382Sedranlib_usage(void) 401176434Skaiw{ 402176434Skaiw 403287326Semaste (void)fprintf(stderr, "usage: ranlib [-DtU] archive ...\n"); 404176434Skaiw (void)fprintf(stderr, "\tranlib -V\n"); 405176434Skaiw exit(EX_USAGE); 406176434Skaiw} 407176434Skaiw 408176434Skaiwstatic void 409201382Sedbsdar_version(void) 410176434Skaiw{ 411232153Smm (void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string()); 412176434Skaiw exit(EX_OK); 413176434Skaiw} 414176434Skaiw 415176434Skaiwstatic void 416201382Sedranlib_version(void) 417176434Skaiw{ 418232153Smm (void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string()); 419176434Skaiw exit(EX_OK); 420176434Skaiw} 421