1 /*- 2 * Copyright (c) 2007 Kai Wang 3 * Copyright (c) 2007 Tim Kientzle 4 * Copyright (c) 2007 Joseph Koshy 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1990, 1993, 1994 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Hugh Smith at The University of Guelph. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61 #include <sys/cdefs.h> 62 __FBSDID("$FreeBSD$"); 63 64 #include <sys/queue.h> 65 #include <sys/types.h> 66 #include <archive.h> 67 #include <errno.h> 68 #include <getopt.h> 69 #include <libgen.h> 70 #include <stdio.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <sysexits.h> 74 75 #include "ar.h" 76 77 enum options 78 { 79 OPTION_HELP 80 }; 81 82 static struct option longopts[] = 83 { 84 {"help", no_argument, NULL, OPTION_HELP}, 85 {"version", no_argument, NULL, 'V'}, 86 {NULL, 0, NULL, 0} 87 }; 88 89 static void bsdar_usage(void); 90 static void ranlib_usage(void); 91 static void set_mode(struct bsdar *bsdar, char opt); 92 static void only_mode(struct bsdar *bsdar, const char *opt, 93 const char *valid_modes); 94 static void bsdar_version(void); 95 static void ranlib_version(void); 96 97 int 98 main(int argc, char **argv) 99 { 100 struct bsdar *bsdar, bsdar_storage; 101 char *p; 102 size_t len; 103 int i, opt; 104 105 bsdar = &bsdar_storage; 106 memset(bsdar, 0, sizeof(*bsdar)); 107 108 if ((bsdar->progname = getprogname()) == NULL) 109 bsdar->progname = "ar"; 110 111 /* Act like ranlib if our name ends in "ranlib"; this 112 * accomodates arm-freebsd7.1-ranlib, bsdranlib, etc. */ 113 len = strlen(bsdar->progname); 114 if (len >= strlen("ranlib") && 115 strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) { 116 while ((opt = getopt_long(argc, argv, "tV", longopts, 117 NULL)) != -1) { 118 switch(opt) { 119 case 't': 120 /* Ignored. */ 121 break; 122 case 'V': 123 ranlib_version(); 124 break; 125 case OPTION_HELP: 126 ranlib_usage(); 127 default: 128 ranlib_usage(); 129 } 130 } 131 argv += optind; 132 argc -= optind; 133 134 if (*argv == NULL) 135 ranlib_usage(); 136 137 bsdar->options |= AR_S; 138 for (;(bsdar->filename = *argv++) != NULL;) 139 ar_mode_s(bsdar); 140 141 exit(EX_OK); 142 } else { 143 if (argc < 2) 144 bsdar_usage(); 145 146 if (*argv[1] != '-') { 147 len = strlen(argv[1]) + 2; 148 if ((p = malloc(len)) == NULL) 149 bsdar_errc(bsdar, EX_SOFTWARE, errno, 150 "malloc failed"); 151 *p = '-'; 152 (void)strlcpy(p + 1, argv[1], len - 1); 153 argv[1] = p; 154 } 155 } 156 157 while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtuVvxz", 158 longopts, NULL)) != -1) { 159 switch(opt) { 160 case 'a': 161 bsdar->options |= AR_A; 162 break; 163 case 'b': 164 case 'i': 165 bsdar->options |= AR_B; 166 break; 167 case 'C': 168 bsdar->options |= AR_CC; 169 break; 170 case 'c': 171 bsdar->options |= AR_C; 172 break; 173 case 'd': 174 set_mode(bsdar, opt); 175 break; 176 case 'D': 177 bsdar->options |= AR_D; 178 break; 179 case 'f': 180 case 'T': 181 bsdar->options |= AR_TR; 182 break; 183 case 'j': 184 /* ignored */ 185 break; 186 case 'l': 187 /* ignored, for GNU ar comptibility */ 188 break; 189 case 'M': 190 set_mode(bsdar, opt); 191 break; 192 case 'm': 193 set_mode(bsdar, opt); 194 break; 195 case 'o': 196 bsdar->options |= AR_O; 197 break; 198 case 'p': 199 set_mode(bsdar, opt); 200 break; 201 case 'q': 202 set_mode(bsdar, opt); 203 break; 204 case 'r': 205 set_mode(bsdar, opt); 206 break; 207 case 'S': 208 bsdar->options |= AR_SS; 209 break; 210 case 's': 211 bsdar->options |= AR_S; 212 break; 213 case 't': 214 set_mode(bsdar, opt); 215 break; 216 case 'u': 217 bsdar->options |= AR_U; 218 break; 219 case 'V': 220 bsdar_version(); 221 break; 222 case 'v': 223 bsdar->options |= AR_V; 224 break; 225 case 'x': 226 set_mode(bsdar, opt); 227 break; 228 case 'z': 229 /* ignored */ 230 break; 231 case OPTION_HELP: 232 bsdar_usage(); 233 default: 234 bsdar_usage(); 235 } 236 } 237 238 argv += optind; 239 argc -= optind; 240 241 if (*argv == NULL && bsdar->mode != 'M') 242 bsdar_usage(); 243 244 if (bsdar->options & AR_A && bsdar->options & AR_B) 245 bsdar_errc(bsdar, EX_USAGE, 0, 246 "only one of -a and -[bi] options allowed"); 247 248 if (bsdar->options & AR_J && bsdar->options & AR_Z) 249 bsdar_errc(bsdar, EX_USAGE, 0, 250 "only one of -j and -z options allowed"); 251 252 if (bsdar->options & AR_S && bsdar->options & AR_SS) 253 bsdar_errc(bsdar, EX_USAGE, 0, 254 "only one of -s and -S options allowed"); 255 256 if (bsdar->options & (AR_A | AR_B)) { 257 if ((bsdar->posarg = *argv) == NULL) 258 bsdar_errc(bsdar, EX_USAGE, 0, 259 "no position operand specified"); 260 if ((bsdar->posarg = basename(bsdar->posarg)) == NULL) 261 bsdar_errc(bsdar, EX_SOFTWARE, errno, 262 "basename failed"); 263 argc--; 264 argv++; 265 } 266 267 if (bsdar->options & AR_A) 268 only_mode(bsdar, "-a", "mqr"); 269 if (bsdar->options & AR_B) 270 only_mode(bsdar, "-b", "mqr"); 271 if (bsdar->options & AR_C) 272 only_mode(bsdar, "-c", "qr"); 273 if (bsdar->options & AR_CC) 274 only_mode(bsdar, "-C", "x"); 275 if (bsdar->options & AR_D) 276 only_mode(bsdar, "-D", "qr"); 277 if (bsdar->options & AR_O) 278 only_mode(bsdar, "-o", "x"); 279 if (bsdar->options & AR_SS) 280 only_mode(bsdar, "-S", "mqr"); 281 if (bsdar->options & AR_U) 282 only_mode(bsdar, "-u", "qrx"); 283 284 if (bsdar->mode == 'M') { 285 ar_mode_script(bsdar); 286 exit(EX_OK); 287 } 288 289 if ((bsdar->filename = *argv) == NULL) 290 bsdar_usage(); 291 292 bsdar->argc = --argc; 293 bsdar->argv = ++argv; 294 295 if ((!bsdar->mode || strchr("ptx", bsdar->mode)) && 296 bsdar->options & AR_S) { 297 ar_mode_s(bsdar); 298 if (!bsdar->mode) 299 exit(EX_OK); 300 } 301 302 switch(bsdar->mode) { 303 case 'd': 304 ar_mode_d(bsdar); 305 break; 306 case 'm': 307 ar_mode_m(bsdar); 308 break; 309 case 'p': 310 ar_mode_p(bsdar); 311 break; 312 case 'q': 313 ar_mode_q(bsdar); 314 break; 315 case 'r': 316 ar_mode_r(bsdar); 317 break; 318 case 't': 319 ar_mode_t(bsdar); 320 break; 321 case 'x': 322 ar_mode_x(bsdar); 323 break; 324 default: 325 bsdar_usage(); 326 /* NOTREACHED */ 327 } 328 329 for (i = 0; i < bsdar->argc; i++) 330 if (bsdar->argv[i] != NULL) 331 bsdar_warnc(bsdar, 0, "%s: not found in archive", 332 bsdar->argv[i]); 333 334 exit(EX_OK); 335 } 336 337 static void 338 set_mode(struct bsdar *bsdar, char opt) 339 { 340 341 if (bsdar->mode != '\0' && bsdar->mode != opt) 342 bsdar_errc(bsdar, EX_USAGE, 0, 343 "Can't specify both -%c and -%c", opt, bsdar->mode); 344 bsdar->mode = opt; 345 } 346 347 static void 348 only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes) 349 { 350 351 if (strchr(valid_modes, bsdar->mode) == NULL) 352 bsdar_errc(bsdar, EX_USAGE, 0, 353 "Option %s is not permitted in mode -%c", opt, bsdar->mode); 354 } 355 356 static void 357 bsdar_usage(void) 358 { 359 360 (void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n"); 361 (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n"); 362 (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n"); 363 (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); 364 (void)fprintf(stderr, "\tar -q [-TcDjsvz] archive file ...\n"); 365 (void)fprintf(stderr, "\tar -r [-TcDjsuvz] archive file ...\n"); 366 (void)fprintf(stderr, "\tar -r [-TabcDijsuvz] position archive file ...\n"); 367 (void)fprintf(stderr, "\tar -s [-jz] archive\n"); 368 (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); 369 (void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n"); 370 (void)fprintf(stderr, "\tar -V\n"); 371 exit(EX_USAGE); 372 } 373 374 static void 375 ranlib_usage(void) 376 { 377 378 (void)fprintf(stderr, "usage: ranlib [-t] archive ...\n"); 379 (void)fprintf(stderr, "\tranlib -V\n"); 380 exit(EX_USAGE); 381 } 382 383 static void 384 bsdar_version(void) 385 { 386 (void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version()); 387 exit(EX_OK); 388 } 389 390 static void 391 ranlib_version(void) 392 { 393 (void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version()); 394 exit(EX_OK); 395 } 396