1 /* $Source: /u/mark/src/pax/RCS/tar.c,v $ 2 * 3 * $Revision: 1.2 $ 4 * 5 * tar.c - tar specific functions for archive handling 6 * 7 * DESCRIPTION 8 * 9 * These routines provide a tar conforming interface to the pax 10 * program. 11 * 12 * AUTHOR 13 * 14 * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) 15 * 16 * Sponsored by The USENIX Association for public distribution. 17 * 18 * Copyright (c) 1989 Mark H. Colburn. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that the above copyright notice is duplicated in all such 23 * forms and that any documentation, advertising materials, and other 24 * materials related to such distribution and use acknowledge that the 25 * software was developed by Mark H. Colburn and sponsored by The 26 * USENIX Association. 27 * 28 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 29 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 31 * 32 * $Log: tar.c,v $ 33 * Revision 1.2 89/02/12 10:06:05 mark 34 * 1.2 release fixes 35 * 36 * Revision 1.1 88/12/23 18:02:38 mark 37 * Initial revision 38 * 39 */ 40 41 #ifndef lint 42 static char *ident = "$Id: tar.c,v 1.2 89/02/12 10:06:05 mark Exp $"; 43 static char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved."; 44 #endif /* not lint */ 45 46 /* Headers */ 47 48 #include "pax.h" 49 50 51 /* Defines */ 52 53 #define DEF_BLOCKING 20 /* default blocking factor for extract */ 54 55 56 /* Function Prototypes */ 57 58 #ifdef __STDC__ 59 60 static int taropt(int , char **, char *); 61 static void usage(void); 62 63 #else /* !__STDC__ */ 64 65 static int taropt(); 66 static void usage(); 67 68 #endif /* __STDC__ */ 69 70 71 /* do_tar - main routine for tar. 72 * 73 * DESCRIPTION 74 * 75 * Provides a tar interface to the PAX program. All tar standard 76 * command line options are supported. 77 * 78 * PARAMETERS 79 * 80 * int argc - argument count (argc from main) 81 * char **argv - argument list (argv from main) 82 * 83 * RETURNS 84 * 85 * zero 86 */ 87 88 #ifdef __STDC__ 89 90 int do_tar(int argc, char **argv) 91 92 #else 93 94 int do_tar(argc, argv) 95 int argc; /* argument count (argc from main) */ 96 char **argv; /* argument list (argv from main) */ 97 98 #endif 99 { 100 int c; /* Option letter */ 101 102 /* Set default option values */ 103 names_from_stdin = 0; 104 ar_file = getenv("TAPE"); /* From environment, or */ 105 if (ar_file == 0) { 106 ar_file = DEF_AR_FILE; /* From Makefile */ 107 } 108 109 /* 110 * set up the flags to reflect the default pax inteface. Unfortunately 111 * the pax interface has several options which are completely opposite 112 * of the tar and/or cpio interfaces... 113 */ 114 f_unconditional = 1; 115 f_mtime = 1; 116 f_dir_create = 1; 117 blocking = 0; 118 ar_interface = TAR; 119 ar_format = TAR; 120 msgfile=stderr; 121 122 /* Parse options */ 123 while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) { 124 switch (c) { 125 case 'b': /* specify blocking factor */ 126 /* 127 * FIXME - we should use a conversion routine that does 128 * some kind of reasonable error checking, but... 129 */ 130 blocking = atoi(optarg); 131 break; 132 case 'c': /* create a new archive */ 133 f_create = 1; 134 break; 135 case 'f': /* specify input/output file */ 136 ar_file = optarg; 137 break; 138 case 'h': 139 f_follow_links = 1; /* follow symbolic links */ 140 break; 141 case 'l': /* report unresolved links */ 142 f_linksleft = 1; 143 break; 144 case 'm': /* don't restore modification times */ 145 f_modified = 1; 146 break; 147 case 'o': /* take on user's group rather than 148 * archives */ 149 break; 150 case 'r': /* named files are appended to archive */ 151 f_append = 1; 152 break; 153 case 't': 154 f_list = 1; /* list files in archive */ 155 break; 156 case 'u': /* named files are added to archive */ 157 f_newer = 1; 158 break; 159 case 'v': /* verbose mode */ 160 f_verbose = 1; 161 break; 162 case 'w': /* user interactive mode */ 163 f_disposition = 1; 164 break; 165 case 'x': /* named files are extracted from archive */ 166 f_extract = 1; 167 break; 168 case '?': 169 usage(); 170 exit(EX_ARGSBAD); 171 } 172 } 173 174 /* check command line argument sanity */ 175 if (f_create + f_extract + f_list + f_append + f_newer != 1) { 176 (void) fprintf(stderr, 177 "%s: you must specify exactly one of the c, t, r, u or x options\n", 178 myname); 179 usage(); 180 exit(EX_ARGSBAD); 181 } 182 183 /* set the blocking factor, if not set by the user */ 184 if (blocking == 0) { 185 #ifdef USG 186 if (f_extract || f_list) { 187 blocking = DEF_BLOCKING; 188 fprintf(stderr, "Tar: blocksize = %d\n", blocking); 189 } else { 190 blocking = 1; 191 } 192 #else /* !USG */ 193 blocking = 20; 194 #endif /* USG */ 195 } 196 blocksize = blocking * BLOCKSIZE; 197 buf_allocate((OFFSET) blocksize); 198 199 if (f_create) { 200 open_archive(AR_WRITE); 201 create_archive(); /* create the archive */ 202 } else if (f_extract) { 203 open_archive(AR_READ); 204 read_archive(); /* extract files from archive */ 205 } else if (f_list) { 206 open_archive(AR_READ); 207 read_archive(); /* read and list contents of archive */ 208 } else if (f_append) { 209 open_archive(AR_APPEND); 210 append_archive(); /* append files to archive */ 211 } 212 213 if (f_linksleft) { 214 linkleft(); /* report any unresolved links */ 215 } 216 217 return (0); 218 } 219 220 221 /* taropt - tar specific getopt 222 * 223 * DESCRIPTION 224 * 225 * Plug-compatible replacement for getopt() for parsing tar-like 226 * arguments. If the first argument begins with "-", it uses getopt; 227 * otherwise, it uses the old rules used by tar, dump, and ps. 228 * 229 * PARAMETERS 230 * 231 * int argc - argument count (argc from main) 232 * char **argv - argument list (argv from main) 233 * char *optstring - sring which describes allowable options 234 * 235 * RETURNS 236 * 237 * Returns the next option character in the option string(s). If the 238 * option requires an argument and an argument was given, the argument 239 * is pointed to by "optarg". If no option character was found, 240 * returns an EOF. 241 * 242 */ 243 244 #ifdef __STDC__ 245 246 static int taropt(int argc, char **argv, char *optstring) 247 248 #else 249 250 static int taropt(argc, argv, optstring) 251 int argc; 252 char **argv; 253 char *optstring; 254 255 #endif 256 { 257 extern char *optarg; /* Points to next arg */ 258 extern int optind; /* Global argv index */ 259 static char *key; /* Points to next keyletter */ 260 static char use_getopt; /* !=0 if argv[1][0] was '-' */ 261 char c; 262 char *place; 263 264 optarg = (char *)NULL; 265 266 if (key == (char *)NULL) { /* First time */ 267 if (argc < 2) 268 return EOF; 269 key = argv[1]; 270 if (*key == '-') 271 use_getopt++; 272 else 273 optind = 2; 274 } 275 if (use_getopt) { 276 return getopt(argc, argv, optstring); 277 } 278 279 c = *key++; 280 if (c == '\0') { 281 key--; 282 return EOF; 283 } 284 place = strchr(optstring, c); 285 286 if (place == (char *)NULL || c == ':') { 287 fprintf(stderr, "%s: unknown option %c\n", argv[0], c); 288 return ('?'); 289 } 290 place++; 291 if (*place == ':') { 292 if (optind < argc) { 293 optarg = argv[optind]; 294 optind++; 295 } else { 296 fprintf(stderr, "%s: %c argument missing\n", 297 argv[0], c); 298 return ('?'); 299 } 300 } 301 return (c); 302 } 303 304 305 /* usage - print a helpful message and exit 306 * 307 * DESCRIPTION 308 * 309 * Usage prints out the usage message for the TAR interface and then 310 * exits with a non-zero termination status. This is used when a user 311 * has provided non-existant or incompatible command line arguments. 312 * 313 * RETURNS 314 * 315 * Returns an exit status of 1 to the parent process. 316 * 317 */ 318 319 #ifdef __STDC__ 320 321 static void usage(void) 322 323 #else 324 325 static void usage() 326 327 #endif 328 { 329 fprintf(stderr, "Usage: %s -c[bfvw] device block filename..\n", myname); 330 fprintf(stderr, " %s -r[bvw] device block [filename...]\n", myname); 331 fprintf(stderr, " %s -t[vf] device\n", myname); 332 fprintf(stderr, " %s -u[bvw] device block [filename...]\n", myname); 333 fprintf(stderr, " %s -x[flmovw] device [filename...]\n", myname); 334 exit(1); 335 } 336