17c478bd9Sstevel@tonic-gate /* 233a5e6b2Srm88369 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate /* 187c478bd9Sstevel@tonic-gate * Modified to recursively extract all files within a subtree 197c478bd9Sstevel@tonic-gate * (supressed by the h option) and recreate the heirarchical 207c478bd9Sstevel@tonic-gate * structure of that subtree and move extracted files to their 217c478bd9Sstevel@tonic-gate * proper homes (supressed by the m option). 227c478bd9Sstevel@tonic-gate * Includes the s (skip files) option for use with multiple 237c478bd9Sstevel@tonic-gate * dumps on a single tape. 247c478bd9Sstevel@tonic-gate * 8/29/80 by Mike Litzkow 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Modified to work on the new file system and to recover from 277c478bd9Sstevel@tonic-gate * tape read errors. 287c478bd9Sstevel@tonic-gate * 1/19/82 by Kirk McKusick 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate * Full incremental restore running entirely in user code and 317c478bd9Sstevel@tonic-gate * interactive tape browser. 327c478bd9Sstevel@tonic-gate * 1/19/83 by Kirk McKusick 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include "restore.h" 367c478bd9Sstevel@tonic-gate #include <signal.h> 377c478bd9Sstevel@tonic-gate #include <byteorder.h> 387c478bd9Sstevel@tonic-gate #include <priv_utils.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #include <euc.h> 417c478bd9Sstevel@tonic-gate #include <getwidth.h> 427c478bd9Sstevel@tonic-gate #include <sys/mtio.h> 437c478bd9Sstevel@tonic-gate eucwidth_t wp; 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate int bflag = 0, dflag = 0, vflag = 0, yflag = 0; 467c478bd9Sstevel@tonic-gate int hflag = 1, mflag = 1, paginating = 0, offline = 0, autoload = 0; 477c478bd9Sstevel@tonic-gate int autoload_tries; 487c478bd9Sstevel@tonic-gate int autoload_period; 497c478bd9Sstevel@tonic-gate int cvtflag = 0; /* Converting from old dump format */ 507c478bd9Sstevel@tonic-gate char command = '\0'; 517c478bd9Sstevel@tonic-gate long dumpnum = 1; 527c478bd9Sstevel@tonic-gate int volno = 0; 537c478bd9Sstevel@tonic-gate uint_t ntrec; /* blocking factor, in KB */ 547c478bd9Sstevel@tonic-gate uint_t saved_ntrec; /* saved blocking factor, in KB */ 557c478bd9Sstevel@tonic-gate ssize_t tape_rec_size = 0; /* tape record size (ntrec * tp_bsize) */ 567c478bd9Sstevel@tonic-gate size_t newtapebuf_size = 0; /* save size of last call to newtapebuf */ 577c478bd9Sstevel@tonic-gate char *progname; 587c478bd9Sstevel@tonic-gate char *dumpmap; 597c478bd9Sstevel@tonic-gate char *clrimap; 607c478bd9Sstevel@tonic-gate char *c_label; /* if non-NULL, we must see this tape label */ 617c478bd9Sstevel@tonic-gate ino_t maxino; 627c478bd9Sstevel@tonic-gate time_t dumptime; 637c478bd9Sstevel@tonic-gate time_t dumpdate; 647c478bd9Sstevel@tonic-gate FILE *terminal; 657c478bd9Sstevel@tonic-gate char *tmpdir; 667c478bd9Sstevel@tonic-gate char *pager_catenated; 677c478bd9Sstevel@tonic-gate char **pager_vector; 687c478bd9Sstevel@tonic-gate int pager_len; 697c478bd9Sstevel@tonic-gate int inattrspace = 0; 707c478bd9Sstevel@tonic-gate int savepwd; 717c478bd9Sstevel@tonic-gate int32_t tp_bsize = TP_BSIZE_MIN; 727c478bd9Sstevel@tonic-gate struct byteorder_ctx *byteorder; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static void set_tmpdir(void); 757c478bd9Sstevel@tonic-gate 76*fe0e7ec4Smaheshvs int 77*fe0e7ec4Smaheshvs main(int argc, char *argv[]) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate static struct arglist alist = { 0, 0, 0, 0, 0 }; 807c478bd9Sstevel@tonic-gate int count; 817c478bd9Sstevel@tonic-gate char *cp; 827c478bd9Sstevel@tonic-gate char *fname; 837c478bd9Sstevel@tonic-gate ino_t ino; 847c478bd9Sstevel@tonic-gate char *inputdev; 857c478bd9Sstevel@tonic-gate char *archivefile = 0; 867c478bd9Sstevel@tonic-gate char *symtbl = RESTORESYMTABLE; 877c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 887c478bd9Sstevel@tonic-gate int fflag = 0; 897c478bd9Sstevel@tonic-gate struct sigaction sa, osa; 907c478bd9Sstevel@tonic-gate int multiplier; 917c478bd9Sstevel@tonic-gate char units; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) != NULL) 947c478bd9Sstevel@tonic-gate progname++; 957c478bd9Sstevel@tonic-gate else 967c478bd9Sstevel@tonic-gate progname = argv[0]; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (strcmp("hsmrestore", progname) == 0) { 997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1007c478bd9Sstevel@tonic-gate gettext("hsmrestore emulation is no longer supported.\n")); 1017c478bd9Sstevel@tonic-gate done(1); 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Convert the effective uid of 0 to the single privilege 1067c478bd9Sstevel@tonic-gate * we really want. When running with all privileges, this 1077c478bd9Sstevel@tonic-gate * is a no-op. When the set-uid bit is stripped restore 1087c478bd9Sstevel@tonic-gate * still works for local tapes. Fail when trying to access 1097c478bd9Sstevel@tonic-gate * a remote tape in that case and not immediately. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate (void) __init_suid_priv(0, PRIV_NET_PRIVADDR, (char *)NULL); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate inputdev = DEFTAPE; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * This doesn't work because ufsrestore is statically linked: 1177c478bd9Sstevel@tonic-gate * (void) setlocale(LC_ALL, ""); 1187c478bd9Sstevel@tonic-gate * The problem seems to be with LC_COLLATE, so set all the 1197c478bd9Sstevel@tonic-gate * others explicitly. Bug 1157128 was created against the I18N 1207c478bd9Sstevel@tonic-gate * library. When that bug is fixed this should go back to the way 1217c478bd9Sstevel@tonic-gate * it was. 1227c478bd9Sstevel@tonic-gate * XXX 1157128 was closed as a dup of 1099747. That bug was fixed by 1237c478bd9Sstevel@tonic-gate * disallowing setlocale() to anything other than "C". "" is 1247c478bd9Sstevel@tonic-gate * allowed, but only if none of the envars LC_ALL, LC_COLLATE, or LANG 1257c478bd9Sstevel@tonic-gate * select anything other than "C". 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate (void) setlocale(LC_CTYPE, ""); 1287c478bd9Sstevel@tonic-gate (void) setlocale(LC_NUMERIC, ""); 1297c478bd9Sstevel@tonic-gate (void) setlocale(LC_TIME, ""); 1307c478bd9Sstevel@tonic-gate (void) setlocale(LC_MONETARY, ""); 1317c478bd9Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, ""); 1327c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1337c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1347c478bd9Sstevel@tonic-gate #endif 1357c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1367c478bd9Sstevel@tonic-gate getwidth(&wp); 1377c478bd9Sstevel@tonic-gate if ((byteorder = byteorder_create()) == NULL) { 1387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1397c478bd9Sstevel@tonic-gate gettext("Cannot create byteorder context\n")); 1407c478bd9Sstevel@tonic-gate done(1); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if ((savepwd = open(".", O_RDONLY)) < 0) { 1447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1457c478bd9Sstevel@tonic-gate gettext("Cannot save current directory context\n")); 1467c478bd9Sstevel@tonic-gate done(1); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate set_tmpdir(); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate autoload_period = 12; 1527c478bd9Sstevel@tonic-gate autoload_tries = 12; /* traditional default of ~2.5 minutes */ 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate sa.sa_handler = onintr; 1557c478bd9Sstevel@tonic-gate sa.sa_flags = SA_RESTART; 1567c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &sa, &osa); 1597c478bd9Sstevel@tonic-gate if (osa.sa_handler == SIG_IGN) 1607c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &osa, (struct sigaction *)0); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &sa, &osa); 1637c478bd9Sstevel@tonic-gate if (osa.sa_handler == SIG_IGN) 1647c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &osa, (struct sigaction *)0); 1657c478bd9Sstevel@tonic-gate if (argc < 2) { 1667c478bd9Sstevel@tonic-gate usage: 1677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage:\n\ 1687c478bd9Sstevel@tonic-gate \t%s tabcdfhsvyLloT [file file ...]\n\ 1697c478bd9Sstevel@tonic-gate \t%s xabcdfhmsvyLloT [file file ...]\n\ 1707c478bd9Sstevel@tonic-gate \t%s iabcdfhmsvyLloT\n\ 1717c478bd9Sstevel@tonic-gate \t%s rabcdfsvyLloT\n\ 1727c478bd9Sstevel@tonic-gate \t%s RabcdfsvyLloT\n\n\ 1737c478bd9Sstevel@tonic-gate a requires an archive file name\n\ 1747c478bd9Sstevel@tonic-gate b requires a blocking factor\n\ 1757c478bd9Sstevel@tonic-gate f requires a dump file\n\ 1767c478bd9Sstevel@tonic-gate s requires a file number\n\ 1777c478bd9Sstevel@tonic-gate L requires a tape label\n\ 1787c478bd9Sstevel@tonic-gate If set, the envar TMPDIR selects where temporary files are kept\n"), 1797c478bd9Sstevel@tonic-gate progname, progname, progname, progname, progname); 1807c478bd9Sstevel@tonic-gate done(1); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate argv++; /* the bag-of-options */ 1847c478bd9Sstevel@tonic-gate argc -= 2; /* count of parameters to the options */ 1857c478bd9Sstevel@tonic-gate command = '\0'; 1867c478bd9Sstevel@tonic-gate c_label = (char *)NULL; /* any tape's acceptable */ 1877c478bd9Sstevel@tonic-gate for (cp = *argv++; *cp; cp++) { 1887c478bd9Sstevel@tonic-gate switch (*cp) { /* BE CAUTIOUS OF FALLTHROUGHS */ 1897c478bd9Sstevel@tonic-gate case 'T': 1907c478bd9Sstevel@tonic-gate if (argc < 1) { 1917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1927c478bd9Sstevel@tonic-gate "Missing autoload timeout period\n")); 1937c478bd9Sstevel@tonic-gate done(1); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate count = atoi(*argv); 1977c478bd9Sstevel@tonic-gate if (count < 1) { 1987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1997c478bd9Sstevel@tonic-gate "Unreasonable autoload timeout period `%s'\n"), 2007c478bd9Sstevel@tonic-gate *argv); 2017c478bd9Sstevel@tonic-gate done(1); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate units = *(*argv + strlen(*argv) - 1); 2047c478bd9Sstevel@tonic-gate switch (units) { 2057c478bd9Sstevel@tonic-gate case 's': 2067c478bd9Sstevel@tonic-gate multiplier = 1; 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate case 'h': 2097c478bd9Sstevel@tonic-gate multiplier = 3600; 2107c478bd9Sstevel@tonic-gate break; 2117c478bd9Sstevel@tonic-gate case '0': case '1': case '2': case '3': case '4': 2127c478bd9Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9': 2137c478bd9Sstevel@tonic-gate case 'm': 2147c478bd9Sstevel@tonic-gate multiplier = 60; 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate default: 2177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2187c478bd9Sstevel@tonic-gate "Unknown timeout units indicator `%c'\n"), 2197c478bd9Sstevel@tonic-gate units); 2207c478bd9Sstevel@tonic-gate done(1); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate autoload_tries = 1 + 2237c478bd9Sstevel@tonic-gate ((count * multiplier) / autoload_period); 2247c478bd9Sstevel@tonic-gate argv++; 2257c478bd9Sstevel@tonic-gate argc--; 2267c478bd9Sstevel@tonic-gate break; 2277c478bd9Sstevel@tonic-gate case 'l': 2287c478bd9Sstevel@tonic-gate autoload++; 22933a5e6b2Srm88369 break; 2307c478bd9Sstevel@tonic-gate case 'o': 2317c478bd9Sstevel@tonic-gate offline++; 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate case '-': 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate case 'a': 2367c478bd9Sstevel@tonic-gate if (argc < 1) { 2377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2387c478bd9Sstevel@tonic-gate gettext("missing archive file name\n")); 2397c478bd9Sstevel@tonic-gate done(1); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate archivefile = *argv++; 2427c478bd9Sstevel@tonic-gate if (*archivefile == '\0') { 2437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2447c478bd9Sstevel@tonic-gate gettext("empty archive file name\n")); 2457c478bd9Sstevel@tonic-gate done(1); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate argc--; 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate case 'c': 2507c478bd9Sstevel@tonic-gate cvtflag++; 2517c478bd9Sstevel@tonic-gate break; 2527c478bd9Sstevel@tonic-gate case 'd': 2537c478bd9Sstevel@tonic-gate dflag++; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate case 'D': 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * This used to be the Dflag, but it doesn't 2587c478bd9Sstevel@tonic-gate * hurt to always check, so was removed. This 2597c478bd9Sstevel@tonic-gate * case is here for backward compatability. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate case 'h': 2637c478bd9Sstevel@tonic-gate hflag = 0; 2647c478bd9Sstevel@tonic-gate break; 2657c478bd9Sstevel@tonic-gate case 'm': 2667c478bd9Sstevel@tonic-gate mflag = 0; 2677c478bd9Sstevel@tonic-gate break; 2687c478bd9Sstevel@tonic-gate case 'v': 2697c478bd9Sstevel@tonic-gate vflag++; 2707c478bd9Sstevel@tonic-gate break; 2717c478bd9Sstevel@tonic-gate case 'y': 2727c478bd9Sstevel@tonic-gate yflag++; 2737c478bd9Sstevel@tonic-gate break; 2747c478bd9Sstevel@tonic-gate case 'f': 2757c478bd9Sstevel@tonic-gate if (argc < 1) { 2767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2777c478bd9Sstevel@tonic-gate gettext("missing device specifier\n")); 2787c478bd9Sstevel@tonic-gate done(1); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate inputdev = *argv++; 2817c478bd9Sstevel@tonic-gate if (*inputdev == '\0') { 2827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2837c478bd9Sstevel@tonic-gate gettext("empty device specifier\n")); 2847c478bd9Sstevel@tonic-gate done(1); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate fflag++; 2877c478bd9Sstevel@tonic-gate argc--; 2887c478bd9Sstevel@tonic-gate break; 2897c478bd9Sstevel@tonic-gate case 'b': 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * change default tape blocksize 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate bflag++; 2947c478bd9Sstevel@tonic-gate if (argc < 1) { 2957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2967c478bd9Sstevel@tonic-gate gettext("missing block size\n")); 2977c478bd9Sstevel@tonic-gate done(1); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate saved_ntrec = ntrec = atoi(*argv++); 3007c478bd9Sstevel@tonic-gate if (ntrec == 0 || (ntrec&1)) { 3017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3027c478bd9Sstevel@tonic-gate "Block size must be a positive, even integer\n")); 3037c478bd9Sstevel@tonic-gate done(1); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate ntrec /= (tp_bsize/DEV_BSIZE); 3067c478bd9Sstevel@tonic-gate argc--; 3077c478bd9Sstevel@tonic-gate break; 3087c478bd9Sstevel@tonic-gate case 's': 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * dumpnum (skip to) for multifile dump tapes 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate if (argc < 1) { 3137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3147c478bd9Sstevel@tonic-gate gettext("missing dump number\n")); 3157c478bd9Sstevel@tonic-gate done(1); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate dumpnum = atoi(*argv++); 3187c478bd9Sstevel@tonic-gate if (dumpnum <= 0) { 3197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3207c478bd9Sstevel@tonic-gate "Dump number must be a positive integer\n")); 3217c478bd9Sstevel@tonic-gate done(1); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate argc--; 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate case 't': 3267c478bd9Sstevel@tonic-gate case 'R': 3277c478bd9Sstevel@tonic-gate case 'r': 3287c478bd9Sstevel@tonic-gate case 'x': 3297c478bd9Sstevel@tonic-gate case 'i': 3307c478bd9Sstevel@tonic-gate if (command != '\0') { 3317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3327c478bd9Sstevel@tonic-gate "%c and %c are mutually exclusive\n"), 3337c478bd9Sstevel@tonic-gate (uchar_t)*cp, (uchar_t)command); 3347c478bd9Sstevel@tonic-gate goto usage; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate command = *cp; 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate case 'L': 3397c478bd9Sstevel@tonic-gate if (argc < 1 || **argv == '\0') { 3407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3417c478bd9Sstevel@tonic-gate gettext("Missing tape label name\n")); 3427c478bd9Sstevel@tonic-gate done(1); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate c_label = *argv++; /* must get tape with this label */ 3457c478bd9Sstevel@tonic-gate if (strlen(c_label) > (sizeof (spcl.c_label) - 1)) { 3467c478bd9Sstevel@tonic-gate c_label[sizeof (spcl.c_label) - 1] = '\0'; 3477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3487c478bd9Sstevel@tonic-gate "Truncating label to maximum supported length: `%s'\n"), 3497c478bd9Sstevel@tonic-gate c_label); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate argc--; 3527c478bd9Sstevel@tonic-gate break; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate default: 3557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3567c478bd9Sstevel@tonic-gate gettext("Bad key character %c\n"), (uchar_t)*cp); 3577c478bd9Sstevel@tonic-gate goto usage; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate if (command == '\0') { 3617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3627c478bd9Sstevel@tonic-gate gettext("must specify i, t, r, R, or x\n")); 3637c478bd9Sstevel@tonic-gate goto usage; 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate setinput(inputdev, archivefile); 3667c478bd9Sstevel@tonic-gate if (argc == 0) { /* re-use last argv slot for default */ 3677c478bd9Sstevel@tonic-gate argc = 1; 3687c478bd9Sstevel@tonic-gate *--argv = mflag ? "." : "2"; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate switch (command) { 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * Interactive mode. 3747c478bd9Sstevel@tonic-gate */ 3757c478bd9Sstevel@tonic-gate case 'i': 3767c478bd9Sstevel@tonic-gate setup(); 3777c478bd9Sstevel@tonic-gate extractdirs(1); 3787c478bd9Sstevel@tonic-gate initsymtable((char *)0); 3797c478bd9Sstevel@tonic-gate initpagercmd(); 3807c478bd9Sstevel@tonic-gate runcmdshell(); 3817c478bd9Sstevel@tonic-gate done(0); 3827c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * Incremental restoration of a file system. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate case 'r': 3877c478bd9Sstevel@tonic-gate setup(); 3887c478bd9Sstevel@tonic-gate if (dumptime > 0) { 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * This is an incremental dump tape. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate vprintf(stdout, gettext("Begin incremental restore\n")); 3937c478bd9Sstevel@tonic-gate initsymtable(symtbl); 3947c478bd9Sstevel@tonic-gate extractdirs(1); 3957c478bd9Sstevel@tonic-gate removeoldleaves(); 3967c478bd9Sstevel@tonic-gate vprintf(stdout, gettext("Calculate node updates.\n")); 3977c478bd9Sstevel@tonic-gate strcpy(name, "."); 3987c478bd9Sstevel@tonic-gate name[2] = '\0'; 3997c478bd9Sstevel@tonic-gate treescan(name, ROOTINO, nodeupdates); 4007c478bd9Sstevel@tonic-gate attrscan(1, nodeupdates); 4017c478bd9Sstevel@tonic-gate findunreflinks(); 4027c478bd9Sstevel@tonic-gate removeoldnodes(); 4037c478bd9Sstevel@tonic-gate } else { 4047c478bd9Sstevel@tonic-gate /* 4057c478bd9Sstevel@tonic-gate * This is a level zero dump tape. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate vprintf(stdout, gettext("Begin level 0 restore\n")); 4087c478bd9Sstevel@tonic-gate initsymtable((char *)0); 4097c478bd9Sstevel@tonic-gate extractdirs(1); 4107c478bd9Sstevel@tonic-gate vprintf(stdout, 4117c478bd9Sstevel@tonic-gate gettext("Calculate extraction list.\n")); 4127c478bd9Sstevel@tonic-gate strcpy(name, "."); 4137c478bd9Sstevel@tonic-gate name[2] = '\0'; 4147c478bd9Sstevel@tonic-gate treescan(name, ROOTINO, nodeupdates); 4157c478bd9Sstevel@tonic-gate attrscan(1, nodeupdates); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate createleaves(symtbl); 4187c478bd9Sstevel@tonic-gate createlinks(); 4197c478bd9Sstevel@tonic-gate setdirmodes(); 4207c478bd9Sstevel@tonic-gate checkrestore(); 4217c478bd9Sstevel@tonic-gate if (dflag) { 4227c478bd9Sstevel@tonic-gate vprintf(stdout, 4237c478bd9Sstevel@tonic-gate gettext("Verify the directory structure\n")); 4247c478bd9Sstevel@tonic-gate strcpy(name, "."); 4257c478bd9Sstevel@tonic-gate name[2] = '\0'; 4267c478bd9Sstevel@tonic-gate treescan(name, ROOTINO, verifyfile); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate dumpsymtable(symtbl, (long)1); 4297c478bd9Sstevel@tonic-gate done(0); 4307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * Resume an incremental file system restoration. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate case 'R': 4357c478bd9Sstevel@tonic-gate setupR(); 4367c478bd9Sstevel@tonic-gate initsymtable(symtbl); 4377c478bd9Sstevel@tonic-gate skipmaps(); 4387c478bd9Sstevel@tonic-gate skipdirs(); 4397c478bd9Sstevel@tonic-gate createleaves(symtbl); 4407c478bd9Sstevel@tonic-gate createlinks(); 4417c478bd9Sstevel@tonic-gate setdirmodes(); 4427c478bd9Sstevel@tonic-gate checkrestore(); 4437c478bd9Sstevel@tonic-gate dumpsymtable(symtbl, (long)1); 4447c478bd9Sstevel@tonic-gate done(0); 4457c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * List contents of tape. 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate case 't': 4507c478bd9Sstevel@tonic-gate setup(); 4517c478bd9Sstevel@tonic-gate extractdirs(0); 4527c478bd9Sstevel@tonic-gate initsymtable((char *)0); 4537c478bd9Sstevel@tonic-gate if (vflag) 4547c478bd9Sstevel@tonic-gate printdumpinfo(); 4557c478bd9Sstevel@tonic-gate while (argc--) { 4567c478bd9Sstevel@tonic-gate canon(*argv++, name, sizeof (name)); 4577c478bd9Sstevel@tonic-gate name[strlen(name)+1] = '\0'; 4587c478bd9Sstevel@tonic-gate ino = dirlookup(name); 4597c478bd9Sstevel@tonic-gate if (ino == 0) 4607c478bd9Sstevel@tonic-gate continue; 4617c478bd9Sstevel@tonic-gate treescan(name, ino, listfile); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate done(0); 4647c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * Batch extraction of tape contents. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate case 'x': 4697c478bd9Sstevel@tonic-gate setup(); 4707c478bd9Sstevel@tonic-gate extractdirs(1); 4717c478bd9Sstevel@tonic-gate initsymtable((char *)0); 4727c478bd9Sstevel@tonic-gate while (argc--) { 4737c478bd9Sstevel@tonic-gate if (mflag) { 4747c478bd9Sstevel@tonic-gate canon(*argv++, name, sizeof (name)); 4757c478bd9Sstevel@tonic-gate if (expand(name, 0, &alist) == 0) { 4767c478bd9Sstevel@tonic-gate /* no meta-characters to expand */ 4777c478bd9Sstevel@tonic-gate ino = dirlookup(name); 4787c478bd9Sstevel@tonic-gate if (ino == 0) 4797c478bd9Sstevel@tonic-gate continue; 4807c478bd9Sstevel@tonic-gate pathcheck(name); 4817c478bd9Sstevel@tonic-gate } else { 4827c478bd9Sstevel@tonic-gate /* add each of the expansions */ 4837c478bd9Sstevel@tonic-gate while ((alist.last - alist.head) > 0) { 4847c478bd9Sstevel@tonic-gate fname = alist.head->fname; 4857c478bd9Sstevel@tonic-gate ino = dirlookup(fname); 4867c478bd9Sstevel@tonic-gate if (ino != 0) { 4877c478bd9Sstevel@tonic-gate pathcheck(fname); 4887c478bd9Sstevel@tonic-gate treescan(fname, ino, 4897c478bd9Sstevel@tonic-gate addfile); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate freename(fname); 4927c478bd9Sstevel@tonic-gate alist.head++; 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate alist.head = (struct afile *)NULL; 4957c478bd9Sstevel@tonic-gate continue; /* argc loop */ 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } else { 4987c478bd9Sstevel@tonic-gate ino = (ino_t)atol(*argv); 4997c478bd9Sstevel@tonic-gate if ((*(*argv++) == '-') || ino < ROOTINO) { 5007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5017c478bd9Sstevel@tonic-gate "bad inode number: %ld\n"), 5027c478bd9Sstevel@tonic-gate ino); 5037c478bd9Sstevel@tonic-gate done(1); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate name[0] = '\0'; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate treescan(name, ino, addfile); 5087c478bd9Sstevel@tonic-gate attrscan(0, addfile); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate createfiles(); 5117c478bd9Sstevel@tonic-gate createlinks(); 5127c478bd9Sstevel@tonic-gate setdirmodes(); 5137c478bd9Sstevel@tonic-gate if (dflag) 5147c478bd9Sstevel@tonic-gate checkrestore(); 5157c478bd9Sstevel@tonic-gate done(0); 5167c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate return (0); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Determine where the user wants us to put our temporary files, 5237c478bd9Sstevel@tonic-gate * and make sure we can actually do so. Bail out if there's a problem. 5247c478bd9Sstevel@tonic-gate */ 5257c478bd9Sstevel@tonic-gate void 5267c478bd9Sstevel@tonic-gate set_tmpdir(void) 5277c478bd9Sstevel@tonic-gate { 5287c478bd9Sstevel@tonic-gate int fd; 5297c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate tmpdir = getenv("TMPDIR"); 5327c478bd9Sstevel@tonic-gate if ((tmpdir == (char *)NULL) || (*tmpdir == '\0')) 5337c478bd9Sstevel@tonic-gate tmpdir = "/tmp"; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate if (*tmpdir != '/') { 5367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5377c478bd9Sstevel@tonic-gate gettext("TMPDIR is not an absolute path (`%s').\n"), 5387c478bd9Sstevel@tonic-gate tmpdir); 5397c478bd9Sstevel@tonic-gate done(1); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * The actual use of tmpdir is in dirs.c, and is of the form 5447c478bd9Sstevel@tonic-gate * tmpdir + "/rst" + type (three characters) + "%ld.XXXXXX" + 5457c478bd9Sstevel@tonic-gate * a trailing NUL, where %ld is an arbitrary time_t. 5467c478bd9Sstevel@tonic-gate * 5477c478bd9Sstevel@tonic-gate * Thus, the magic 31 is strlen(itoa(MAX_TIME_T)) + "/rst" + 5487c478bd9Sstevel@tonic-gate * ".XXXXXX" + '\0'. A time_t is 64 bits, so MAX_TIME_T is 5497c478bd9Sstevel@tonic-gate * LONG_MAX - nineteen digits. In theory, so many things in 5507c478bd9Sstevel@tonic-gate * ufsrestore will break once time_t's value goes beyond 32 5517c478bd9Sstevel@tonic-gate * bits that it's not worth worrying about this particular 5527c478bd9Sstevel@tonic-gate * instance at this time, but we've got to start somewhere. 5537c478bd9Sstevel@tonic-gate * 5547c478bd9Sstevel@tonic-gate * Note that the use of a pid below is just for testing the 5557c478bd9Sstevel@tonic-gate * validity of the named directory. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate if (strlen(tmpdir) > (MAXPATHLEN - 31)) { 5587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("TMPDIR too long\n")); 5597c478bd9Sstevel@tonic-gate done(1); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* Guaranteed to fit by above test (sizeof(time_t) >= sizeof(pid_t)) */ 5637c478bd9Sstevel@tonic-gate (void) snprintf(name, sizeof (name), "%s/rstdir.%ld", tmpdir, getpid()); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * This is effectively a stripped-down version of safe_open(), 5677c478bd9Sstevel@tonic-gate * because if the file exists, we want to fail. 5687c478bd9Sstevel@tonic-gate */ 5697c478bd9Sstevel@tonic-gate fd = open(name, O_CREAT|O_EXCL|O_RDWR, 0600); 5707c478bd9Sstevel@tonic-gate if (fd < 0) { 5717c478bd9Sstevel@tonic-gate perror(gettext("Can not create temporary file")); 5727c478bd9Sstevel@tonic-gate done(1); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate (void) close(fd); 5767c478bd9Sstevel@tonic-gate if (unlink(name) < 0) { 5777c478bd9Sstevel@tonic-gate perror(gettext("Can not delete temporary file")); 5787c478bd9Sstevel@tonic-gate done(1); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate } 581