options.c revision 20420
1233294Sstas/*- 2178825Sdfr * Copyright (c) 1992 Keith Muller. 3178825Sdfr * Copyright (c) 1992, 1993 4178825Sdfr * The Regents of the University of California. All rights reserved. 5178825Sdfr * 6178825Sdfr * This code is derived from software contributed to Berkeley by 7178825Sdfr * Keith Muller of the University of California, San Diego. 8178825Sdfr * 9233294Sstas * Redistribution and use in source and binary forms, with or without 10178825Sdfr * modification, are permitted provided that the following conditions 11178825Sdfr * are met: 12178825Sdfr * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 14178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 15178825Sdfr * notice, this list of conditions and the following disclaimer in the 16178825Sdfr * documentation and/or other materials provided with the distribution. 17178825Sdfr * 3. All advertising materials mentioning features or use of this software 18178825Sdfr * must display the following acknowledgement: 19178825Sdfr * This product includes software developed by the University of 20233294Sstas * California, Berkeley and its contributors. 21178825Sdfr * 4. Neither the name of the University nor the names of its contributors 22178825Sdfr * may be used to endorse or promote products derived from this software 23178825Sdfr * without specific prior written permission. 24178825Sdfr * 25233294Sstas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35178825Sdfr * SUCH DAMAGE. 36178825Sdfr * 37178825Sdfr * $Id: options.c,v 1.4 1995/10/23 21:23:16 ache Exp $ 38178825Sdfr */ 39178825Sdfr 40178825Sdfr#ifndef lint 41178825Sdfrstatic char const sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; 42178825Sdfr#endif /* not lint */ 43178825Sdfr 44178825Sdfr#include <sys/types.h> 45178825Sdfr#include <sys/time.h> 46178825Sdfr#include <sys/stat.h> 47178825Sdfr#include <sys/mtio.h> 48178825Sdfr#include <sys/param.h> 49178825Sdfr#include <stdio.h> 50178825Sdfr#include <string.h> 51178825Sdfr#include <unistd.h> 52233294Sstas#include <stdlib.h> 53178825Sdfr#include <limits.h> 54178825Sdfr#include "pax.h" 55178825Sdfr#include "options.h" 56178825Sdfr#include "cpio.h" 57233294Sstas#include "tar.h" 58178825Sdfr#include "extern.h" 59178825Sdfr 60178825Sdfr/* 61178825Sdfr * Routines which handle command line options 62178825Sdfr */ 63178825Sdfr 64178825Sdfrstatic char flgch[] = FLGCH; /* list of all possible flags */ 65178825Sdfrstatic OPLIST *ophead = NULL; /* head for format specific options -x */ 66178825Sdfrstatic OPLIST *optail = NULL; /* option tail */ 67178825Sdfr 68233294Sstasstatic int no_op __P((void)); 69178825Sdfrstatic void printflg __P((unsigned int)); 70178825Sdfrstatic int c_frmt __P((const void *, const void *)); 71178825Sdfrstatic off_t str_offt __P((char *)); 72178825Sdfrstatic void pax_options __P((register int, register char **)); 73178825Sdfrstatic void pax_usage __P((void)); 74178825Sdfrstatic void tar_options __P((register int, register char **)); 75178825Sdfrstatic void tar_usage __P((void)); 76233294Sstas#ifdef notdef 77178825Sdfrstatic void cpio_options __P((register int, register char **)); 78178825Sdfrstatic void cpio_usage __P((void)); 79178825Sdfr#endif 80178825Sdfr 81178825Sdfr/* 82178825Sdfr * Format specific routine table - MUST BE IN SORTED ORDER BY NAME 83178825Sdfr * (see pax.h for description of each function) 84178825Sdfr * 85178825Sdfr * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read, 86178825Sdfr * read, end_read, st_write, write, end_write, trail, 87178825Sdfr * rd_data, wr_data, options 88178825Sdfr */ 89233294Sstas 90178825SdfrFSUB fsub[] = { 91178825Sdfr/* 0: OLD BINARY CPIO */ 92178825Sdfr {"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd, 93178825Sdfr bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail, 94178825Sdfr rd_wrfile, wr_rdfile, bad_opt}, 95233294Sstas 96178825Sdfr/* 1: OLD OCTAL CHARACTER CPIO */ 97178825Sdfr {"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd, 98178825Sdfr cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail, 99178825Sdfr rd_wrfile, wr_rdfile, bad_opt}, 100178825Sdfr 101178825Sdfr/* 2: SVR4 HEX CPIO */ 102178825Sdfr {"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd, 103178825Sdfr vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail, 104178825Sdfr rd_wrfile, wr_rdfile, bad_opt}, 105178825Sdfr 106178825Sdfr/* 3: SVR4 HEX CPIO WITH CRC */ 107178825Sdfr {"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd, 108178825Sdfr vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail, 109178825Sdfr rd_wrfile, wr_rdfile, bad_opt}, 110178825Sdfr 111178825Sdfr/* 4: OLD TAR */ 112178825Sdfr {"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op, 113178825Sdfr tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail, 114178825Sdfr rd_wrfile, wr_rdfile, tar_opt}, 115178825Sdfr 116178825Sdfr/* 5: POSIX USTAR */ 117178825Sdfr {"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd, 118178825Sdfr ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail, 119178825Sdfr rd_wrfile, wr_rdfile, bad_opt}, 120178825Sdfr}; 121178825Sdfr#define F_TAR 4 /* format when called as tar */ 122233294Sstas#define DEFLT 5 /* default write format from list above */ 123178825Sdfr 124178825Sdfr/* 125178825Sdfr * ford is the archive search order used by get_arc() to determine what kind 126178825Sdfr * of archive we are dealing with. This helps to properly id archive formats 127178825Sdfr * some formats may be subsets of others.... 128178825Sdfr */ 129178825Sdfrint ford[] = {5, 4, 3, 2, 1, 0, -1 }; 130178825Sdfr 131178825Sdfr/* 132178825Sdfr * options() 133178825Sdfr * figure out if we are pax, tar or cpio. Call the appropriate options 134178825Sdfr * parser 135178825Sdfr */ 136178825Sdfr 137178825Sdfr#if __STDC__ 138178825Sdfrvoid 139178825Sdfroptions(register int argc, register char **argv) 140178825Sdfr#else 141178825Sdfrvoid 142233294Sstasoptions(argc, argv) 143178825Sdfr register int argc; 144178825Sdfr register char **argv; 145178825Sdfr#endif 146178825Sdfr{ 147233294Sstas 148178825Sdfr /* 149178825Sdfr * Are we acting like pax, tar or cpio (based on argv[0]) 150178825Sdfr */ 151178825Sdfr if ((argv0 = strrchr(argv[0], '/')) != NULL) 152178825Sdfr argv0++; 153233294Sstas else 154178825Sdfr argv0 = argv[0]; 155178825Sdfr 156178825Sdfr if (strcmp(NM_TAR, argv0) == 0) 157233294Sstas return(tar_options(argc, argv)); 158178825Sdfr# ifdef notdef 159178825Sdfr else if (strcmp(NM_CPIO, argv0) == 0) 160178825Sdfr return(cpio_options(argc, argv)); 161178825Sdfr# endif 162178825Sdfr /* 163178825Sdfr * assume pax as the default 164178825Sdfr */ 165178825Sdfr argv0 = NM_PAX; 166178825Sdfr return(pax_options(argc, argv)); 167178825Sdfr} 168178825Sdfr 169178825Sdfr/* 170178825Sdfr * pax_options() 171178825Sdfr * look at the user specified flags. set globals as required and check if 172178825Sdfr * the user specified a legal set of flags. If not, complain and exit 173233294Sstas */ 174178825Sdfr 175178825Sdfr#if __STDC__ 176178825Sdfrstatic void 177178825Sdfrpax_options(register int argc, register char **argv) 178178825Sdfr#else 179178825Sdfrstatic void 180178825Sdfrpax_options(argc, argv) 181178825Sdfr register int argc; 182178825Sdfr register char **argv; 183178825Sdfr#endif 184178825Sdfr{ 185178825Sdfr register int c; 186178825Sdfr register int i; 187178825Sdfr unsigned int flg = 0; 188178825Sdfr unsigned int bflg = 0; 189178825Sdfr register char *pt; 190178825Sdfr FSUB tmp; 191178825Sdfr extern char *optarg; 192178825Sdfr extern int optind; 193178825Sdfr 194178825Sdfr /* 195178825Sdfr * process option flags 196178825Sdfr */ 197178825Sdfr while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLPT:U:XYZ")) 198233294Sstas != EOF) { 199178825Sdfr switch (c) { 200178825Sdfr case 'a': 201178825Sdfr /* 202178825Sdfr * append 203178825Sdfr */ 204178825Sdfr flg |= AF; 205178825Sdfr break; 206178825Sdfr case 'b': 207178825Sdfr /* 208178825Sdfr * specify blocksize 209178825Sdfr */ 210178825Sdfr flg |= BF; 211178825Sdfr if ((wrblksz = (int)str_offt(optarg)) <= 0) { 212178825Sdfr warn(1, "Invalid block size %s", optarg); 213178825Sdfr pax_usage(); 214178825Sdfr } 215178825Sdfr break; 216178825Sdfr case 'c': 217178825Sdfr /* 218178825Sdfr * inverse match on patterns 219178825Sdfr */ 220178825Sdfr cflag = 1; 221233294Sstas flg |= CF; 222178825Sdfr break; 223178825Sdfr case 'd': 224178825Sdfr /* 225178825Sdfr * match only dir on extract, not the subtree at dir 226178825Sdfr */ 227178825Sdfr dflag = 1; 228178825Sdfr flg |= DF; 229178825Sdfr break; 230178825Sdfr case 'f': 231178825Sdfr /* 232178825Sdfr * filename where the archive is stored 233178825Sdfr */ 234178825Sdfr arcname = optarg; 235233294Sstas flg |= FF; 236178825Sdfr break; 237178825Sdfr case 'i': 238178825Sdfr /* 239178825Sdfr * interactive file rename 240178825Sdfr */ 241178825Sdfr iflag = 1; 242178825Sdfr flg |= IF; 243178825Sdfr break; 244178825Sdfr case 'k': 245178825Sdfr /* 246178825Sdfr * do not clobber files that exist 247178825Sdfr */ 248178825Sdfr kflag = 1; 249178825Sdfr flg |= KF; 250178825Sdfr break; 251178825Sdfr case 'l': 252233294Sstas /* 253178825Sdfr * try to link src to dest with copy (-rw) 254178825Sdfr */ 255178825Sdfr lflag = 1; 256178825Sdfr flg |= LF; 257178825Sdfr break; 258178825Sdfr case 'n': 259178825Sdfr /* 260178825Sdfr * select first match for a pattern only 261178825Sdfr */ 262178825Sdfr nflag = 1; 263178825Sdfr flg |= NF; 264178825Sdfr break; 265178825Sdfr case 'o': 266178825Sdfr /* 267178825Sdfr * pass format specific options 268178825Sdfr */ 269178825Sdfr flg |= OF; 270178825Sdfr if (opt_add(optarg) < 0) 271178825Sdfr pax_usage(); 272178825Sdfr break; 273178825Sdfr case 'p': 274178825Sdfr /* 275178825Sdfr * specify file characteristic options 276178825Sdfr */ 277178825Sdfr for (pt = optarg; *pt != '\0'; ++pt) { 278178825Sdfr switch(*pt) { 279178825Sdfr case 'a': 280178825Sdfr /* 281178825Sdfr * do not preserve access time 282178825Sdfr */ 283178825Sdfr patime = 0; 284233294Sstas break; 285178825Sdfr case 'e': 286178825Sdfr /* 287178825Sdfr * preserve user id, group id, file 288178825Sdfr * mode, access/modification times 289178825Sdfr */ 290178825Sdfr pids = 1; 291178825Sdfr pmode = 1; 292178825Sdfr patime = 1; 293178825Sdfr pmtime = 1; 294178825Sdfr break; 295178825Sdfr case 'm': 296178825Sdfr /* 297178825Sdfr * do not preserve modification time 298178825Sdfr */ 299178825Sdfr pmtime = 0; 300178825Sdfr break; 301178825Sdfr case 'o': 302178825Sdfr /* 303178825Sdfr * preserve uid/gid 304178825Sdfr */ 305233294Sstas pids = 1; 306178825Sdfr break; 307178825Sdfr case 'p': 308178825Sdfr /* 309178825Sdfr * preserver file mode bits 310178825Sdfr */ 311233294Sstas pmode = 1; 312178825Sdfr break; 313178825Sdfr default: 314178825Sdfr warn(1, "Invalid -p string: %c", *pt); 315178825Sdfr pax_usage(); 316178825Sdfr break; 317178825Sdfr } 318178825Sdfr } 319178825Sdfr flg |= PF; 320178825Sdfr break; 321178825Sdfr case 'r': 322178825Sdfr /* 323178825Sdfr * read the archive 324178825Sdfr */ 325178825Sdfr flg |= RF; 326233294Sstas break; 327178825Sdfr case 's': 328178825Sdfr /* 329178825Sdfr * file name substitution name pattern 330178825Sdfr */ 331178825Sdfr if (rep_add(optarg) < 0) { 332233294Sstas pax_usage(); 333178825Sdfr break; 334178825Sdfr } 335178825Sdfr flg |= SF; 336178825Sdfr break; 337178825Sdfr case 't': 338178825Sdfr /* 339178825Sdfr * preserve access time on filesystem nodes we read 340178825Sdfr */ 341178825Sdfr tflag = 1; 342178825Sdfr flg |= TF; 343178825Sdfr break; 344178825Sdfr case 'u': 345178825Sdfr /* 346178825Sdfr * ignore those older files 347178825Sdfr */ 348178825Sdfr uflag = 1; 349178825Sdfr flg |= UF; 350178825Sdfr break; 351178825Sdfr case 'v': 352178825Sdfr /* 353178825Sdfr * verbose operation mode 354178825Sdfr */ 355178825Sdfr vflag = 1; 356178825Sdfr flg |= VF; 357178825Sdfr break; 358178825Sdfr case 'w': 359178825Sdfr /* 360178825Sdfr * write an archive 361178825Sdfr */ 362178825Sdfr flg |= WF; 363178825Sdfr break; 364178825Sdfr case 'x': 365178825Sdfr /* 366178825Sdfr * specify an archive format on write 367178825Sdfr */ 368178825Sdfr tmp.name = optarg; 369178825Sdfr if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 370178825Sdfr sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt))) { 371178825Sdfr flg |= XF; 372178825Sdfr break; 373178825Sdfr } 374178825Sdfr warn(1, "Unknown -x format: %s", optarg); 375178825Sdfr (void)fputs("pax: Known -x formats are:", stderr); 376178825Sdfr for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 377233294Sstas (void)fprintf(stderr, " %s", fsub[i].name); 378178825Sdfr (void)fputs("\n\n", stderr); 379178825Sdfr pax_usage(); 380178825Sdfr break; 381178825Sdfr case 'B': 382233294Sstas /* 383178825Sdfr * non-standard option on number of bytes written on a 384178825Sdfr * single archive volume. 385178825Sdfr */ 386178825Sdfr if ((wrlimit = str_offt(optarg)) <= 0) { 387178825Sdfr warn(1, "Invalid write limit %s", optarg); 388178825Sdfr pax_usage(); 389178825Sdfr } 390178825Sdfr if (wrlimit % BLKMULT) { 391178825Sdfr warn(1, "Write limit is not a %d byte multiple", 392178825Sdfr BLKMULT); 393178825Sdfr pax_usage(); 394178825Sdfr } 395178825Sdfr flg |= CBF; 396178825Sdfr break; 397178825Sdfr case 'D': 398178825Sdfr /* 399178825Sdfr * On extraction check file inode change time before the 400178825Sdfr * modification of the file name. Non standard option. 401178825Sdfr */ 402178825Sdfr Dflag = 1; 403178825Sdfr flg |= CDF; 404178825Sdfr break; 405233294Sstas case 'E': 406178825Sdfr /* 407178825Sdfr * non-standard limit on read faults 408178825Sdfr * 0 indicates stop after first error, values 409178825Sdfr * indicate a limit, "NONE" try forever 410178825Sdfr */ 411178825Sdfr flg |= CEF; 412178825Sdfr if (strcmp(NONE, optarg) == 0) 413178825Sdfr maxflt = -1; 414233294Sstas else if ((maxflt = atoi(optarg)) < 0) { 415178825Sdfr warn(1, "Error count value must be positive"); 416178825Sdfr pax_usage(); 417178825Sdfr } 418178825Sdfr break; 419178825Sdfr case 'G': 420178825Sdfr /* 421178825Sdfr * non-standard option for selecting files within an 422178825Sdfr * archive by group (gid or name) 423233294Sstas */ 424178825Sdfr if (grp_add(optarg) < 0) { 425178825Sdfr pax_usage(); 426178825Sdfr break; 427178825Sdfr } 428178825Sdfr flg |= CGF; 429178825Sdfr break; 430178825Sdfr case 'H': 431178825Sdfr /* 432178825Sdfr * follow command line symlinks only 433178825Sdfr */ 434178825Sdfr Hflag = 1; 435233294Sstas flg |= CHF; 436178825Sdfr break; 437178825Sdfr case 'L': 438178825Sdfr /* 439178825Sdfr * follow symlinks 440178825Sdfr */ 441178825Sdfr Lflag = 1; 442178825Sdfr flg |= CLF; 443178825Sdfr break; 444178825Sdfr case 'P': 445178825Sdfr /* 446178825Sdfr * do NOT follow symlinks (default) 447233294Sstas */ 448178825Sdfr Lflag = 0; 449178825Sdfr flg |= CPF; 450178825Sdfr break; 451178825Sdfr case 'T': 452178825Sdfr /* 453178825Sdfr * non-standard option for selecting files within an 454178825Sdfr * archive by modification time range (lower,upper) 455178825Sdfr */ 456178825Sdfr if (trng_add(optarg) < 0) { 457178825Sdfr pax_usage(); 458178825Sdfr break; 459178825Sdfr } 460178825Sdfr flg |= CTF; 461178825Sdfr break; 462178825Sdfr case 'U': 463233294Sstas /* 464178825Sdfr * non-standard option for selecting files within an 465178825Sdfr * archive by user (uid or name) 466178825Sdfr */ 467178825Sdfr if (usr_add(optarg) < 0) { 468233294Sstas pax_usage(); 469178825Sdfr break; 470178825Sdfr } 471178825Sdfr flg |= CUF; 472178825Sdfr break; 473178825Sdfr case 'X': 474178825Sdfr /* 475178825Sdfr * do not pass over mount points in the file system 476178825Sdfr */ 477178825Sdfr Xflag = 1; 478178825Sdfr flg |= CXF; 479178825Sdfr break; 480178825Sdfr case 'Y': 481178825Sdfr /* 482178825Sdfr * On extraction check file inode change time after the 483178825Sdfr * modification of the file name. Non standard option. 484178825Sdfr */ 485178825Sdfr Yflag = 1; 486178825Sdfr flg |= CYF; 487178825Sdfr break; 488178825Sdfr case 'Z': 489233294Sstas /* 490178825Sdfr * On extraction check modification time after the 491178825Sdfr * modification of the file name. Non standard option. 492178825Sdfr */ 493178825Sdfr Zflag = 1; 494178825Sdfr flg |= CZF; 495178825Sdfr break; 496178825Sdfr case '?': 497178825Sdfr default: 498178825Sdfr pax_usage(); 499178825Sdfr break; 500178825Sdfr } 501178825Sdfr } 502178825Sdfr 503178825Sdfr /* 504178825Sdfr * figure out the operation mode of pax read,write,extract,copy,append 505233294Sstas * or list. check that we have not been given a bogus set of flags 506178825Sdfr * for the operation mode. 507178825Sdfr */ 508178825Sdfr if (ISLIST(flg)) { 509178825Sdfr act = LIST; 510178825Sdfr bflg = flg & BDLIST; 511178825Sdfr } else if (ISEXTRACT(flg)) { 512178825Sdfr act = EXTRACT; 513178825Sdfr bflg = flg & BDEXTR; 514233294Sstas } else if (ISARCHIVE(flg)) { 515178825Sdfr act = ARCHIVE; 516178825Sdfr bflg = flg & BDARCH; 517178825Sdfr } else if (ISAPPND(flg)) { 518178825Sdfr act = APPND; 519178825Sdfr bflg = flg & BDARCH; 520178825Sdfr } else if (ISCOPY(flg)) { 521178825Sdfr act = COPY; 522178825Sdfr bflg = flg & BDCOPY; 523178825Sdfr } else 524178825Sdfr pax_usage(); 525178825Sdfr if (bflg) { 526178825Sdfr printflg(flg); 527178825Sdfr pax_usage(); 528178825Sdfr } 529233294Sstas 530178825Sdfr /* 531178825Sdfr * if we are writing (ARCHIVE) we use the default format if the user 532178825Sdfr * did not specify a format. when we write during an APPEND, we will 533178825Sdfr * adopt the format of the existing archive if none was supplied. 534178825Sdfr */ 535178825Sdfr if (!(flg & XF) && (act == ARCHIVE)) 536178825Sdfr frmt = &(fsub[DEFLT]); 537178825Sdfr 538178825Sdfr /* 539178825Sdfr * process the args as they are interpreted by the operation mode 540178825Sdfr */ 541178825Sdfr switch (act) { 542178825Sdfr case LIST: 543178825Sdfr case EXTRACT: 544178825Sdfr for (; optind < argc; optind++) 545178825Sdfr if (pat_add(argv[optind]) < 0) 546178825Sdfr pax_usage(); 547178825Sdfr break; 548178825Sdfr case COPY: 549178825Sdfr if (optind >= argc) { 550178825Sdfr warn(0, "Destination directory was not supplied"); 551178825Sdfr pax_usage(); 552178825Sdfr } 553178825Sdfr --argc; 554178825Sdfr dirptr = argv[argc]; 555178825Sdfr /* FALL THROUGH */ 556178825Sdfr case ARCHIVE: 557178825Sdfr case APPND: 558178825Sdfr for (; optind < argc; optind++) 559178825Sdfr if (ftree_add(argv[optind]) < 0) 560178825Sdfr pax_usage(); 561178825Sdfr /* 562178825Sdfr * no read errors allowed on updates/append operation! 563178825Sdfr */ 564178825Sdfr maxflt = 0; 565178825Sdfr break; 566178825Sdfr } 567178825Sdfr} 568178825Sdfr 569178825Sdfr 570178825Sdfr/* 571178825Sdfr * tar_options() 572178825Sdfr * look at the user specified flags. set globals as required and check if 573178825Sdfr * the user specified a legal set of flags. If not, complain and exit 574178825Sdfr */ 575178825Sdfr 576178825Sdfr#if __STDC__ 577178825Sdfrstatic void 578178825Sdfrtar_options(register int argc, register char **argv) 579178825Sdfr#else 580178825Sdfrstatic void 581178825Sdfrtar_options(argc, argv) 582178825Sdfr register int argc; 583178825Sdfr register char **argv; 584178825Sdfr#endif 585178825Sdfr{ 586178825Sdfr register char *cp; 587178825Sdfr int fstdin = 0; 588178825Sdfr 589178825Sdfr if (argc < 2) 590178825Sdfr tar_usage(); 591178825Sdfr /* 592178825Sdfr * process option flags 593178825Sdfr */ 594178825Sdfr ++argv; 595178825Sdfr for (cp = *argv++; *cp != '\0'; ++cp) { 596178825Sdfr switch (*cp) { 597178825Sdfr case '-': 598178825Sdfr /* 599178825Sdfr * skip over - 600233294Sstas */ 601178825Sdfr break; 602178825Sdfr case 'b': 603178825Sdfr /* 604178825Sdfr * specify blocksize 605178825Sdfr */ 606178825Sdfr if (*argv == (char *)NULL) { 607178825Sdfr warn(1,"blocksize must be specified with 'b'"); 608233294Sstas tar_usage(); 609178825Sdfr } 610178825Sdfr if ((wrblksz = (int)str_offt(*argv)) <= 0) { 611178825Sdfr warn(1, "Invalid block size %s", *argv); 612178825Sdfr tar_usage(); 613178825Sdfr } 614178825Sdfr ++argv; 615178825Sdfr break; 616178825Sdfr case 'c': 617233294Sstas /* 618178825Sdfr * create an archive 619178825Sdfr */ 620178825Sdfr act = ARCHIVE; 621233294Sstas break; 622178825Sdfr case 'e': 623178825Sdfr /* 624178825Sdfr * stop after first error 625178825Sdfr */ 626178825Sdfr maxflt = 0; 627178825Sdfr break; 628233294Sstas case 'f': 629178825Sdfr /* 630178825Sdfr * filename where the archive is stored 631178825Sdfr */ 632178825Sdfr if (*argv == (char *)NULL) { 633178825Sdfr warn(1, "filename must be specified with 'f'"); 634178825Sdfr tar_usage(); 635178825Sdfr } 636178825Sdfr if ((argv[0][0] == '-') && (argv[0][1]== '\0')) { 637178825Sdfr /* 638233294Sstas * treat a - as stdin 639178825Sdfr */ 640178825Sdfr ++argv; 641178825Sdfr ++fstdin; 642233294Sstas arcname = (char *)0; 643178825Sdfr break; 644178825Sdfr } 645178825Sdfr fstdin = 0; 646178825Sdfr arcname = *argv++; 647178825Sdfr break; 648178825Sdfr case 'm': 649233294Sstas /* 650178825Sdfr * do not preserve modification time 651178825Sdfr */ 652178825Sdfr pmtime = 0; 653178825Sdfr break; 654178825Sdfr case 'o': 655178825Sdfr if (opt_add("write_opt=nodir") < 0) 656178825Sdfr tar_usage(); 657178825Sdfr break; 658178825Sdfr case 'p': 659233294Sstas /* 660178825Sdfr * preserve user id, group id, file 661178825Sdfr * mode, access/modification times 662178825Sdfr */ 663178825Sdfr pids = 1; 664178825Sdfr pmode = 1; 665178825Sdfr patime = 1; 666178825Sdfr pmtime = 1; 667178825Sdfr break; 668178825Sdfr case 'r': 669233294Sstas case 'u': 670178825Sdfr /* 671178825Sdfr * append to the archive 672178825Sdfr */ 673178825Sdfr act = APPND; 674178825Sdfr break; 675178825Sdfr case 't': 676178825Sdfr /* 677178825Sdfr * list contents of the tape 678178825Sdfr */ 679178825Sdfr act = LIST; 680178825Sdfr break; 681178825Sdfr case 'v': 682178825Sdfr /* 683178825Sdfr * verbose operation mode 684178825Sdfr */ 685178825Sdfr vflag = 1; 686178825Sdfr break; 687178825Sdfr case 'w': 688178825Sdfr /* 689178825Sdfr * interactive file rename 690178825Sdfr */ 691178825Sdfr iflag = 1; 692233294Sstas break; 693178825Sdfr case 'x': 694178825Sdfr /* 695178825Sdfr * write an archive 696178825Sdfr */ 697178825Sdfr act = EXTRACT; 698178825Sdfr break; 699178825Sdfr case 'B': 700178825Sdfr /* 701178825Sdfr * Nothing to do here, this is pax default 702178825Sdfr */ 703233294Sstas break; 704178825Sdfr case 'H': 705178825Sdfr /* 706178825Sdfr * follow command line symlinks only 707178825Sdfr */ 708178825Sdfr Hflag = 1; 709178825Sdfr break; 710178825Sdfr case 'L': 711178825Sdfr /* 712233294Sstas * follow symlinks 713178825Sdfr */ 714178825Sdfr Lflag = 1; 715178825Sdfr break; 716178825Sdfr case 'P': 717178825Sdfr /* 718178825Sdfr * do not follow symlinks 719178825Sdfr */ 720233294Sstas Lflag = 0; 721178825Sdfr break; 722178825Sdfr case 'X': 723178825Sdfr /* 724178825Sdfr * do not pass over mount points in the file system 725178825Sdfr */ 726178825Sdfr Xflag = 1; 727178825Sdfr break; 728178825Sdfr case '0': 729178825Sdfr arcname = DEV_0; 730178825Sdfr break; 731178825Sdfr case '1': 732178825Sdfr arcname = DEV_1; 733178825Sdfr break; 734178825Sdfr case '4': 735178825Sdfr arcname = DEV_4; 736178825Sdfr break; 737178825Sdfr case '5': 738178825Sdfr arcname = DEV_5; 739178825Sdfr break; 740178825Sdfr case '7': 741178825Sdfr arcname = DEV_7; 742178825Sdfr break; 743178825Sdfr case '8': 744178825Sdfr arcname = DEV_8; 745178825Sdfr break; 746233294Sstas default: 747178825Sdfr tar_usage(); 748178825Sdfr break; 749178825Sdfr } 750178825Sdfr } 751178825Sdfr 752178825Sdfr /* 753178825Sdfr * if we are writing (ARCHIVE) specify tar, otherwise run like pax 754178825Sdfr */ 755178825Sdfr if (act == ARCHIVE) 756178825Sdfr frmt = &(fsub[F_TAR]); 757178825Sdfr 758178825Sdfr /* 759178825Sdfr * process the args as they are interpreted by the operation mode 760178825Sdfr */ 761178825Sdfr switch (act) { 762178825Sdfr case LIST: 763178825Sdfr case EXTRACT: 764178825Sdfr default: 765178825Sdfr while (*argv != (char *)NULL) 766178825Sdfr if (pat_add(*argv++) < 0) 767178825Sdfr tar_usage(); 768178825Sdfr break; 769233294Sstas case ARCHIVE: 770178825Sdfr case APPND: 771178825Sdfr while (*argv != (char *)NULL) 772178825Sdfr if (ftree_add(*argv++) < 0) 773178825Sdfr tar_usage(); 774233294Sstas /* 775178825Sdfr * no read errors allowed on updates/append operation! 776178825Sdfr */ 777178825Sdfr maxflt = 0; 778178825Sdfr break; 779178825Sdfr } 780233294Sstas if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) { 781178825Sdfr arcname = getenv("TAPE"); 782178825Sdfr if ((arcname == (char *)NULL) || (*arcname == '\0')) 783178825Sdfr arcname = DEV_8; 784178825Sdfr } 785233294Sstas} 786178825Sdfr 787178825Sdfr#ifdef notdef 788178825Sdfr/* 789178825Sdfr * cpio_options() 790178825Sdfr * look at the user specified flags. set globals as required and check if 791178825Sdfr * the user specified a legal set of flags. If not, complain and exit 792233294Sstas */ 793178825Sdfr 794178825Sdfr#if __STDC__ 795178825Sdfrstatic void 796178825Sdfrcpio_options(register int argc, register char **argv) 797233294Sstas#else 798178825Sdfrstatic void 799178825Sdfrcpio_options(argc, argv) 800178825Sdfr register int argc; 801178825Sdfr register char **argv; 802178825Sdfr#endif 803178825Sdfr{ 804178825Sdfr} 805233294Sstas#endif 806178825Sdfr 807178825Sdfr/* 808178825Sdfr * printflg() 809178825Sdfr * print out those invalid flag sets found to the user 810178825Sdfr */ 811178825Sdfr 812178825Sdfr#if __STDC__ 813178825Sdfrstatic void 814178825Sdfrprintflg(unsigned int flg) 815178825Sdfr#else 816178825Sdfrstatic void 817178825Sdfrprintflg(flg) 818178825Sdfr unsigned int flg; 819178825Sdfr#endif 820178825Sdfr{ 821178825Sdfr int nxt; 822178825Sdfr int pos = 0; 823178825Sdfr 824178825Sdfr (void)fprintf(stderr,"%s: Invalid combination of options:", argv0); 825178825Sdfr while ((nxt = ffs(flg))) { 826178825Sdfr flg = flg >> nxt; 827178825Sdfr pos += nxt; 828178825Sdfr (void)fprintf(stderr, " -%c", flgch[pos-1]); 829178825Sdfr } 830178825Sdfr (void)putc('\n', stderr); 831178825Sdfr} 832178825Sdfr 833178825Sdfr/* 834178825Sdfr * c_frmt() 835178825Sdfr * comparison routine used by bsearch to find the format specified 836178825Sdfr * by the user 837178825Sdfr */ 838178825Sdfr 839178825Sdfr#if __STDC__ 840178825Sdfrstatic int 841178825Sdfrc_frmt(const void *a, const void *b) 842178825Sdfr#else 843178825Sdfrstatic int 844178825Sdfrc_frmt(a, b) 845178825Sdfr void *a; 846178825Sdfr void *b; 847178825Sdfr#endif 848233294Sstas{ 849178825Sdfr return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name)); 850178825Sdfr} 851178825Sdfr 852178825Sdfr/* 853178825Sdfr * opt_next() 854178825Sdfr * called by format specific options routines to get each format specific 855178825Sdfr * flag and value specified with -o 856178825Sdfr * Return: 857178825Sdfr * pointer to next OPLIST entry or NULL (end of list). 858178825Sdfr */ 859178825Sdfr 860178825Sdfr#if __STDC__ 861178825SdfrOPLIST * 862178825Sdfropt_next(void) 863178825Sdfr#else 864178825SdfrOPLIST * 865233294Sstasopt_next() 866178825Sdfr#endif 867178825Sdfr{ 868178825Sdfr OPLIST *opt; 869178825Sdfr 870178825Sdfr if ((opt = ophead) != NULL) 871178825Sdfr ophead = ophead->fow; 872178825Sdfr return(opt); 873178825Sdfr} 874178825Sdfr 875178825Sdfr/* 876178825Sdfr * bad_opt() 877178825Sdfr * generic routine used to complain about a format specific options 878178825Sdfr * when the format does not support options. 879178825Sdfr */ 880178825Sdfr 881178825Sdfr#if __STDC__ 882178825Sdfrint 883233294Sstasbad_opt(void) 884178825Sdfr#else 885178825Sdfrint 886178825Sdfrbad_opt() 887178825Sdfr#endif 888178825Sdfr{ 889178825Sdfr register OPLIST *opt; 890178825Sdfr 891178825Sdfr if (ophead == NULL) 892178825Sdfr return(0); 893233294Sstas /* 894178825Sdfr * print all we were given 895178825Sdfr */ 896178825Sdfr warn(1,"These format options are not supported"); 897233294Sstas while ((opt = opt_next()) != NULL) 898178825Sdfr (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value); 899178825Sdfr pax_usage(); 900178825Sdfr return(0); 901178825Sdfr} 902178825Sdfr 903178825Sdfr/* 904178825Sdfr * opt_add() 905178825Sdfr * breaks the value supplied to -o into a option name and value. options 906178825Sdfr * are given to -o in the form -o name-value,name=value 907233294Sstas * mulltiple -o may be specified. 908178825Sdfr * Return: 909178825Sdfr * 0 if format in name=value format, -1 if -o is passed junk 910178825Sdfr */ 911233294Sstas 912178825Sdfr#if __STDC__ 913178825Sdfrint 914178825Sdfropt_add(register char *str) 915178825Sdfr#else 916178825Sdfrint 917178825Sdfropt_add(str) 918178825Sdfr register char *str; 919178825Sdfr#endif 920178825Sdfr{ 921178825Sdfr register OPLIST *opt; 922178825Sdfr register char *frpt; 923178825Sdfr register char *pt; 924178825Sdfr register char *endpt; 925178825Sdfr 926233294Sstas if ((str == NULL) || (*str == '\0')) { 927178825Sdfr warn(0, "Invalid option name"); 928178825Sdfr return(-1); 929178825Sdfr } 930178825Sdfr frpt = endpt = str; 931233294Sstas 932178825Sdfr /* 933178825Sdfr * break into name and values pieces and stuff each one into a 934178825Sdfr * OPLIST structure. When we know the format, the format specific 935178825Sdfr * option function will go through this list 936178825Sdfr */ 937178825Sdfr while ((frpt != NULL) && (*frpt != '\0')) { 938178825Sdfr if ((endpt = strchr(frpt, ',')) != NULL) 939233294Sstas *endpt = '\0'; 940178825Sdfr if ((pt = strchr(frpt, '=')) == NULL) { 941178825Sdfr warn(0, "Invalid options format"); 942178825Sdfr return(-1); 943178825Sdfr } 944178825Sdfr if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) { 945178825Sdfr warn(0, "Unable to allocate space for option list"); 946178825Sdfr return(-1); 947178825Sdfr } 948178825Sdfr *pt++ = '\0'; 949178825Sdfr opt->name = frpt; 950178825Sdfr opt->value = pt; 951178825Sdfr opt->fow = NULL; 952178825Sdfr if (endpt != NULL) 953178825Sdfr frpt = endpt + 1; 954178825Sdfr else 955178825Sdfr frpt = NULL; 956178825Sdfr if (ophead == NULL) { 957178825Sdfr optail = ophead = opt; 958178825Sdfr continue; 959233294Sstas } 960178825Sdfr optail->fow = opt; 961178825Sdfr optail = opt; 962178825Sdfr } 963178825Sdfr return(0); 964233294Sstas} 965178825Sdfr 966178825Sdfr/* 967178825Sdfr * str_offt() 968178825Sdfr * Convert an expression of the following forms to an off_t > 0. 969178825Sdfr * 1) A positive decimal number. 970178825Sdfr * 2) A positive decimal number followed by a b (mult by 512). 971178825Sdfr * 3) A positive decimal number followed by a k (mult by 1024). 972178825Sdfr * 4) A positive decimal number followed by a m (mult by 512). 973178825Sdfr * 5) A positive decimal number followed by a w (mult by sizeof int) 974178825Sdfr * 6) Two or more positive decimal numbers (with/without k,b or w). 975178825Sdfr * seperated by x (also * for backwards compatibility), specifying 976233294Sstas * the product of the indicated values. 977178825Sdfr * Return: 978178825Sdfr * 0 for an error, a positive value o.w. 979178825Sdfr */ 980178825Sdfr 981178825Sdfr#if __STDC__ 982178825Sdfrstatic off_t 983178825Sdfrstr_offt(char *val) 984178825Sdfr#else 985178825Sdfrstatic off_t 986178825Sdfrstr_offt(val) 987178825Sdfr char *val; 988178825Sdfr#endif 989178825Sdfr{ 990178825Sdfr char *expr; 991178825Sdfr off_t num, t; 992178825Sdfr 993178825Sdfr# ifdef NET2_STAT 994178825Sdfr num = strtol(val, &expr, 0); 995178825Sdfr if ((num == LONG_MAX) || (num <= 0) || (expr == val)) 996233294Sstas# else 997178825Sdfr num = strtoq(val, &expr, 0); 998178825Sdfr if ((num == QUAD_MAX) || (num <= 0) || (expr == val)) 999178825Sdfr# endif 1000178825Sdfr return(0); 1001178825Sdfr 1002178825Sdfr switch(*expr) { 1003178825Sdfr case 'b': 1004178825Sdfr t = num; 1005178825Sdfr num *= 512; 1006178825Sdfr if (t > num) 1007233294Sstas return(0); 1008178825Sdfr ++expr; 1009178825Sdfr break; 1010178825Sdfr case 'k': 1011178825Sdfr t = num; 1012233294Sstas num *= 1024; 1013178825Sdfr if (t > num) 1014178825Sdfr return(0); 1015178825Sdfr ++expr; 1016178825Sdfr break; 1017178825Sdfr case 'm': 1018178825Sdfr t = num; 1019178825Sdfr num *= 1048576; 1020178825Sdfr if (t > num) 1021178825Sdfr return(0); 1022178825Sdfr ++expr; 1023178825Sdfr break; 1024178825Sdfr case 'w': 1025178825Sdfr t = num; 1026178825Sdfr num *= sizeof(int); 1027178825Sdfr if (t > num) 1028178825Sdfr return(0); 1029178825Sdfr ++expr; 1030178825Sdfr break; 1031233294Sstas } 1032178825Sdfr 1033178825Sdfr switch(*expr) { 1034178825Sdfr case '\0': 1035178825Sdfr break; 1036178825Sdfr case '*': 1037233294Sstas case 'x': 1038178825Sdfr t = num; 1039178825Sdfr num *= str_offt(expr + 1); 1040178825Sdfr if (t > num) 1041178825Sdfr return(0); 1042178825Sdfr break; 1043178825Sdfr default: 1044178825Sdfr return(0); 1045178825Sdfr } 1046178825Sdfr return(num); 1047178825Sdfr} 1048178825Sdfr 1049178825Sdfr/* 1050178825Sdfr * no_op() 1051178825Sdfr * for those option functions where the archive format has nothing to do. 1052178825Sdfr * Return: 1053178825Sdfr * 0 1054178825Sdfr */ 1055233294Sstas 1056178825Sdfr#if __STDC__ 1057178825Sdfrstatic int 1058178825Sdfrno_op(void) 1059178825Sdfr#else 1060178825Sdfrstatic int 1061178825Sdfrno_op() 1062178825Sdfr#endif 1063178825Sdfr{ 1064178825Sdfr return(0); 1065233294Sstas} 1066178825Sdfr 1067178825Sdfr/* 1068178825Sdfr * pax_usage() 1069178825Sdfr * print the usage summary to the user 1070178825Sdfr */ 1071178825Sdfr 1072233294Sstas#if __STDC__ 1073178825Sdfrvoid 1074178825Sdfrpax_usage(void) 1075178825Sdfr#else 1076178825Sdfrvoid 1077178825Sdfrpax_usage() 1078178825Sdfr#endif 1079178825Sdfr{ 1080233294Sstas (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr); 1081178825Sdfr (void)fputs("[-s replstr] ... [-U user] ...", stderr); 1082178825Sdfr (void)fputs("\n [-G group] ... ", stderr); 1083178825Sdfr (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 1084178825Sdfr (void)fputs("[pattern ...]\n", stderr); 1085178825Sdfr (void)fputs(" pax -r [-cdiknuvDYZ] [-E limit] ", stderr); 1086178825Sdfr (void)fputs("[-f archive] [-o options] ... \n", stderr); 1087233294Sstas (void)fputs(" [-p string] ... [-s replstr] ... ", stderr); 1088178825Sdfr (void)fputs("[-U user] ... [-G group] ...\n ", stderr); 1089178825Sdfr (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 1090178825Sdfr (void)fputs(" [pattern ...]\n", stderr); 1091178825Sdfr (void)fputs(" pax -w [-dituvHLPX] [-b blocksize] ", stderr); 1092178825Sdfr (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr); 1093178825Sdfr (void)fputs(" [-B bytes] [-s replstr] ... ", stderr); 1094178825Sdfr (void)fputs("[-o options] ... [-U user] ...", stderr); 1095178825Sdfr (void)fputs("\n [-G group] ... ", stderr); 1096178825Sdfr (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 1097178825Sdfr (void)fputs("[file ...]\n", stderr); 1098178825Sdfr (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr); 1099178825Sdfr (void)fputs("[-p string] ... [-s replstr] ...", stderr); 1100233294Sstas (void)fputs("\n [-U user] ... [-G group] ... ", stderr); 1101178825Sdfr (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 1102178825Sdfr (void)fputs("\n [file ...] directory\n", stderr); 1103178825Sdfr exit(1); 1104178825Sdfr} 1105178825Sdfr 1106178825Sdfr/* 1107178825Sdfr * tar_usage() 1108178825Sdfr * print the usage summary to the user 1109178825Sdfr */ 1110178825Sdfr 1111178825Sdfr#if __STDC__ 1112233294Sstasvoid 1113178825Sdfrtar_usage(void) 1114178825Sdfr#else 1115178825Sdfrvoid 1116178825Sdfrtar_usage() 1117178825Sdfr#endif 1118178825Sdfr{ 1119178825Sdfr (void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ", 1120178825Sdfr stderr); 1121178825Sdfr (void)fputs("[blocksize] file1 file2...\n", stderr); 1122178825Sdfr exit(1); 1123178825Sdfr} 1124178825Sdfr 1125178825Sdfr#ifdef notdef 1126178825Sdfr/* 1127178825Sdfr * cpio_usage() 1128178825Sdfr * print the usage summary to the user 1129178825Sdfr */ 1130178825Sdfr 1131178825Sdfr#if __STDC__ 1132178825Sdfrvoid 1133178825Sdfrcpio_usage(void) 1134178825Sdfr#else 1135178825Sdfrvoid 1136178825Sdfrcpio_usage() 1137178825Sdfr#endif 1138178825Sdfr{ 1139178825Sdfr exit(1); 1140178825Sdfr} 1141178825Sdfr#endif 1142178825Sdfr