/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Modified to recursively extract all files within a subtree
* (supressed by the h option) and recreate the heirarchical
* structure of that subtree and move extracted files to their
* proper homes (supressed by the m option).
* Includes the s (skip files) option for use with multiple
* dumps on a single tape.
* 8/29/80 by Mike Litzkow
*
* Modified to work on the new file system and to recover from
* tape read errors.
* 1/19/82 by Kirk McKusick
*
* Full incremental restore running entirely in user code and
* interactive tape browser.
* 1/19/83 by Kirk McKusick
*/
#include "restore.h"
#include <signal.h>
#include <byteorder.h>
#include <priv_utils.h>
#include <euc.h>
#include <getwidth.h>
int autoload_tries;
int autoload_period;
int volno = 0;
char *progname;
char *dumpmap;
char *clrimap;
char *tmpdir;
char *pager_catenated;
char **pager_vector;
int pager_len;
int inattrspace = 0;
int savepwd;
static void set_tmpdir(void);
int
{
int count;
char *cp;
char *fname;
char *inputdev;
char *archivefile = 0;
int fflag = 0;
int multiplier;
char units;
progname++;
else
gettext("hsmrestore emulation is no longer supported.\n"));
done(1);
}
/*
* Convert the effective uid of 0 to the single privilege
* we really want. When running with all privileges, this
* is a no-op. When the set-uid bit is stripped restore
* still works for local tapes. Fail when trying to access
* a remote tape in that case and not immediately.
*/
/*
* This doesn't work because ufsrestore is statically linked:
* (void) setlocale(LC_ALL, "");
* The problem seems to be with LC_COLLATE, so set all the
* others explicitly. Bug 1157128 was created against the I18N
* library. When that bug is fixed this should go back to the way
* it was.
* XXX 1157128 was closed as a dup of 1099747. That bug was fixed by
* disallowing setlocale() to anything other than "C". "" is
* allowed, but only if none of the envars LC_ALL, LC_COLLATE, or LANG
* select anything other than "C".
*/
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
gettext("Cannot create byteorder context\n"));
done(1);
}
gettext("Cannot save current directory context\n"));
done(1);
}
set_tmpdir();
autoload_period = 12;
if (argc < 2) {
\t%s tabcdfhsvyLloT [file file ...]\n\
\t%s xabcdfhmsvyLloT [file file ...]\n\
\t%s iabcdfhmsvyLloT\n\
\t%s rabcdfsvyLloT\n\
\t%s RabcdfsvyLloT\n\n\
a requires an archive file name\n\
b requires a blocking factor\n\
f requires a dump file\n\
s requires a file number\n\
L requires a tape label\n\
If set, the envar TMPDIR selects where temporary files are kept\n"),
done(1);
}
argv++; /* the bag-of-options */
command = '\0';
switch (*cp) { /* BE CAUTIOUS OF FALLTHROUGHS */
case 'T':
if (argc < 1) {
"Missing autoload timeout period\n"));
done(1);
}
if (count < 1) {
"Unreasonable autoload timeout period `%s'\n"),
*argv);
done(1);
}
switch (units) {
case 's':
multiplier = 1;
break;
case 'h':
multiplier = 3600;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'm':
multiplier = 60;
break;
default:
"Unknown timeout units indicator `%c'\n"),
units);
done(1);
}
autoload_tries = 1 +
argv++;
argc--;
break;
case 'l':
autoload++;
break;
case 'o':
offline++;
break;
case '-':
break;
case 'a':
if (argc < 1) {
gettext("missing archive file name\n"));
done(1);
}
archivefile = *argv++;
if (*archivefile == '\0') {
gettext("empty archive file name\n"));
done(1);
}
argc--;
break;
case 'c':
cvtflag++;
break;
case 'd':
dflag++;
break;
case 'D':
/*
* This used to be the Dflag, but it doesn't
* hurt to always check, so was removed. This
* case is here for backward compatability.
*/
break;
case 'h':
hflag = 0;
break;
case 'm':
mflag = 0;
break;
case 'v':
vflag++;
break;
case 'y':
yflag++;
break;
case 'f':
if (argc < 1) {
gettext("missing device specifier\n"));
done(1);
}
if (*inputdev == '\0') {
gettext("empty device specifier\n"));
done(1);
}
fflag++;
argc--;
break;
case 'b':
/*
* change default tape blocksize
*/
bflag++;
if (argc < 1) {
gettext("missing block size\n"));
done(1);
}
"Block size must be a positive, even integer\n"));
done(1);
}
argc--;
break;
case 's':
/*
* dumpnum (skip to) for multifile dump tapes
*/
if (argc < 1) {
gettext("missing dump number\n"));
done(1);
}
if (dumpnum <= 0) {
"Dump number must be a positive integer\n"));
done(1);
}
argc--;
break;
case 't':
case 'R':
case 'r':
case 'x':
case 'i':
if (command != '\0') {
"%c and %c are mutually exclusive\n"),
goto usage;
}
break;
case 'L':
gettext("Missing tape label name\n"));
done(1);
}
"Truncating label to maximum supported length: `%s'\n"),
c_label);
}
argc--;
break;
default:
goto usage;
}
}
if (command == '\0') {
gettext("must specify i, t, r, R, or x\n"));
goto usage;
}
if (argc == 0) { /* re-use last argv slot for default */
argc = 1;
}
switch (command) {
/*
* Interactive mode.
*/
case 'i':
setup();
extractdirs(1);
initsymtable((char *)0);
initpagercmd();
runcmdshell();
done(0);
/* NOTREACHED */
/*
* Incremental restoration of a file system.
*/
case 'r':
setup();
if (dumptime > 0) {
/*
* This is an incremental dump tape.
*/
extractdirs(1);
} else {
/*
* This is a level zero dump tape.
*/
initsymtable((char *)0);
extractdirs(1);
gettext("Calculate extraction list.\n"));
}
createlinks();
setdirmodes();
checkrestore();
if (dflag) {
gettext("Verify the directory structure\n"));
}
done(0);
/* NOTREACHED */
/*
* Resume an incremental file system restoration.
*/
case 'R':
setupR();
skipmaps();
skipdirs();
createlinks();
setdirmodes();
checkrestore();
done(0);
/* NOTREACHED */
/*
* List contents of tape.
*/
case 't':
setup();
extractdirs(0);
initsymtable((char *)0);
if (vflag)
while (argc--) {
if (ino == 0)
continue;
}
done(0);
/* NOTREACHED */
/*
* Batch extraction of tape contents.
*/
case 'x':
setup();
extractdirs(1);
initsymtable((char *)0);
while (argc--) {
if (mflag) {
/* no meta-characters to expand */
if (ino == 0)
continue;
} else {
/* add each of the expansions */
if (ino != 0) {
addfile);
}
}
continue; /* argc loop */
}
} else {
"bad inode number: %ld\n"),
ino);
done(1);
}
name[0] = '\0';
}
}
createfiles();
createlinks();
setdirmodes();
if (dflag)
checkrestore();
done(0);
/* NOTREACHED */
}
return (0);
}
/*
* Determine where the user wants us to put our temporary files,
* and make sure we can actually do so. Bail out if there's a problem.
*/
void
set_tmpdir(void)
{
int fd;
tmpdir = "/tmp";
if (*tmpdir != '/') {
gettext("TMPDIR is not an absolute path (`%s').\n"),
tmpdir);
done(1);
}
/*
* The actual use of tmpdir is in dirs.c, and is of the form
* tmpdir + "/rst" + type (three characters) + "%ld.XXXXXX" +
* a trailing NUL, where %ld is an arbitrary time_t.
*
* Thus, the magic 31 is strlen(itoa(MAX_TIME_T)) + "/rst" +
* ".XXXXXX" + '\0'. A time_t is 64 bits, so MAX_TIME_T is
* LONG_MAX - nineteen digits. In theory, so many things in
* ufsrestore will break once time_t's value goes beyond 32
* bits that it's not worth worrying about this particular
* instance at this time, but we've got to start somewhere.
*
* Note that the use of a pid below is just for testing the
* validity of the named directory.
*/
done(1);
}
/* Guaranteed to fit by above test (sizeof(time_t) >= sizeof(pid_t)) */
/*
* This is effectively a stripped-down version of safe_open(),
* because if the file exists, we want to fail.
*/
if (fd < 0) {
done(1);
}
done(1);
}
}