GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/restore/main.c Lines: 0 161 0.0 %
Date: 2017-11-07 Branches: 0 108 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: main.c,v 1.26 2017/01/21 08:31:44 krw Exp $	*/
2
/*	$NetBSD: main.c,v 1.13 1997/07/01 05:37:51 lukem Exp $	*/
3
4
/*
5
 * Copyright (c) 1983, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
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
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/stat.h>
34
#include <sys/time.h>
35
36
#include <ufs/ffs/fs.h>
37
#include <ufs/ufs/dinode.h>
38
#include <protocols/dumprestore.h>
39
40
#include <err.h>
41
#include <paths.h>
42
#include <signal.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
#include <limits.h>
48
49
#include "restore.h"
50
#include "extern.h"
51
52
int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
53
int	hflag = 1, mflag = 1, Nflag = 0;
54
char	command = '\0';
55
long	dumpnum = 1;
56
long	volno = 0;
57
long	ntrec;
58
char	*dumpmap;
59
char	*usedinomap;
60
ino_t	maxino;
61
time_t	dumptime;
62
time_t	dumpdate;
63
FILE	*terminal;
64
char	*tmpdir;
65
66
static void obsolete(int *, char **[]);
67
static void usage(void);
68
69
int
70
main(int argc, char *argv[])
71
{
72
	int ch;
73
	ino_t ino;
74
	char *inputdev;
75
	char *symtbl = "./restoresymtable";
76
	char *p, name[PATH_MAX];
77
78
	/* Temp files should *not* be readable.  We set permissions later. */
79
	(void)umask(077);
80
81
	if (argc < 2)
82
		usage();
83
84
	if ((inputdev = getenv("TAPE")) == NULL || *inputdev == '\0')
85
		inputdev = _PATH_DEFTAPE;
86
	if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
87
		tmpdir = _PATH_TMP;
88
	if ((tmpdir = strdup(tmpdir)) == NULL)
89
		err(1, NULL);
90
	for (p = tmpdir + strlen(tmpdir) - 1; p >= tmpdir && *p == '/'; p--)
91
		continue;
92
	obsolete(&argc, &argv);
93
	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != -1)
94
		switch(ch) {
95
		case 'b':
96
			/* Change default tape blocksize. */
97
			bflag = 1;
98
			ntrec = strtol(optarg, &p, 10);
99
			if (*p)
100
				errx(1, "illegal blocksize -- %s", optarg);
101
			if (ntrec <= 0)
102
				errx(1, "block size must be greater than 0");
103
			break;
104
		case 'c':
105
			cvtflag = 1;
106
			break;
107
		case 'd':
108
			dflag = 1;
109
			break;
110
		case 'f':
111
			inputdev = optarg;
112
			break;
113
		case 'h':
114
			hflag = 0;
115
			break;
116
		case 'i':
117
		case 'R':
118
		case 'r':
119
		case 't':
120
		case 'x':
121
			if (command != '\0')
122
				errx(1,
123
				    "%c and %c options are mutually exclusive",
124
				    ch, command);
125
			command = ch;
126
			break;
127
		case 'm':
128
			mflag = 0;
129
			break;
130
		case 'N':
131
			Nflag = 1;
132
			break;
133
		case 's':
134
			/* Dumpnum (skip to) for multifile dump tapes. */
135
			dumpnum = strtol(optarg, &p, 10);
136
			if (*p)
137
				errx(1, "illegal dump number -- %s", optarg);
138
			if (dumpnum <= 0)
139
				errx(1, "dump number must be greater than 0");
140
			break;
141
		case 'v':
142
			vflag = 1;
143
			break;
144
		case 'y':
145
			yflag = 1;
146
			break;
147
		default:
148
			usage();
149
		}
150
	argc -= optind;
151
	argv += optind;
152
153
	if (command == '\0')
154
		errx(1, "none of i, R, r, t or x options specified");
155
156
	if (signal(SIGINT, onintr) == SIG_IGN)
157
		(void)signal(SIGINT, SIG_IGN);
158
	if (signal(SIGTERM, onintr) == SIG_IGN)
159
		(void)signal(SIGTERM, SIG_IGN);
160
	setvbuf(stderr, NULL, _IOLBF, 0);
161
162
	atexit(cleanup);
163
164
	setinput(inputdev);
165
166
	if (argc == 0) {
167
		argc = 1;
168
		*--argv = ".";
169
	}
170
171
	switch (command) {
172
	/*
173
	 * Interactive mode.
174
	 */
175
	case 'i':
176
		setup();
177
		extractdirs(1);
178
		initsymtable(NULL);
179
		runcmdshell();
180
		break;
181
	/*
182
	 * Incremental restoration of a file system.
183
	 */
184
	case 'r':
185
		setup();
186
		if (dumptime > 0) {
187
			/*
188
			 * This is an incremental dump tape.
189
			 */
190
			Vprintf(stdout, "Begin incremental restore\n");
191
			initsymtable(symtbl);
192
			extractdirs(1);
193
			removeoldleaves();
194
			Vprintf(stdout, "Calculate node updates.\n");
195
			treescan(".", ROOTINO, nodeupdates);
196
			findunreflinks();
197
			removeoldnodes();
198
		} else {
199
			/*
200
			 * This is a level zero dump tape.
201
			 */
202
			Vprintf(stdout, "Begin level 0 restore\n");
203
			initsymtable(NULL);
204
			extractdirs(1);
205
			Vprintf(stdout, "Calculate extraction list.\n");
206
			treescan(".", ROOTINO, nodeupdates);
207
		}
208
		createleaves(symtbl);
209
		createlinks();
210
		setdirmodes(FORCE);
211
		checkrestore();
212
		if (dflag) {
213
			Vprintf(stdout, "Verify the directory structure\n");
214
			treescan(".", ROOTINO, verifyfile);
215
		}
216
		dumpsymtable(symtbl, (long)1);
217
		break;
218
	/*
219
	 * Resume an incremental file system restoration.
220
	 */
221
	case 'R':
222
		initsymtable(symtbl);
223
		skipmaps();
224
		skipdirs();
225
		createleaves(symtbl);
226
		createlinks();
227
		setdirmodes(FORCE);
228
		checkrestore();
229
		dumpsymtable(symtbl, (long)1);
230
		break;
231
	/*
232
	 * List contents of tape.
233
	 */
234
	case 't':
235
		setup();
236
		extractdirs(0);
237
		initsymtable(NULL);
238
		while (argc--) {
239
			canon(*argv++, name, sizeof name);
240
			ino = dirlookup(name);
241
			if (ino == 0)
242
				continue;
243
			treescan(name, ino, listfile);
244
		}
245
		break;
246
	/*
247
	 * Batch extraction of tape contents.
248
	 */
249
	case 'x':
250
		setup();
251
		extractdirs(1);
252
		initsymtable(NULL);
253
		while (argc--) {
254
			canon(*argv++, name, sizeof name);
255
			ino = dirlookup(name);
256
			if (ino == 0)
257
				continue;
258
			if (mflag)
259
				pathcheck(name);
260
			treescan(name, ino, addfile);
261
		}
262
		createfiles();
263
		createlinks();
264
		setdirmodes(0);
265
		if (dflag)
266
			checkrestore();
267
		break;
268
	}
269
	return (0);
270
}
271
272
static void
273
usage(void)
274
{
275
276
	(void)fprintf(stderr, "usage: %s [-chimRrtvxy] [-b blocksize] [-f file] [-s fileno] [file ...]\n", __progname);
277
	exit(1);
278
}
279
280
/*
281
 * obsolete --
282
 *	Change set of key letters and ordered arguments into something
283
 *	getopt(3) will like.
284
 */
285
static void
286
obsolete(int *argcp, char **argvp[])
287
{
288
	int argc, flags;
289
	char *ap, **argv, *flagsp, **nargv, *p;
290
	size_t len;
291
292
	/* Setup. */
293
	argv = *argvp;
294
	argc = *argcp;
295
296
	/* Return if no arguments or first argument has leading dash. */
297
	ap = argv[1];
298
	if (argc == 1 || *ap == '-')
299
		return;
300
301
	/* Allocate space for new arguments. */
302
	if ((*argvp = nargv = calloc(argc + 1, sizeof(char *))) == NULL ||
303
	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
304
		err(1, NULL);
305
306
	*nargv++ = *argv;
307
	argv += 2;
308
309
	for (flags = 0; *ap; ++ap) {
310
		switch (*ap) {
311
		case 'b':
312
		case 'f':
313
		case 's':
314
			if (*argv == NULL) {
315
				warnx("option requires an argument -- %c", *ap);
316
				usage();
317
			}
318
			len = strlen(*argv) + 2 + 1;
319
			if ((nargv[0] = malloc(len)) == NULL)
320
				err(1, NULL);
321
			nargv[0][0] = '-';
322
			nargv[0][1] = *ap;
323
			(void)strlcpy(&nargv[0][2], *argv, len-2);
324
			++argv;
325
			++nargv;
326
			break;
327
		default:
328
			if (!flags) {
329
				*p++ = '-';
330
				flags = 1;
331
			}
332
			*p++ = *ap;
333
			break;
334
		}
335
	}
336
337
	/* Terminate flags. */
338
	if (flags) {
339
		*p = '\0';
340
		*nargv++ = flagsp;
341
	} else {
342
		free(flagsp);
343
	}
344
345
	/* Copy remaining arguments. */
346
	while ((*nargv++ = *argv++))
347
		continue;
348
349
	/* Update argument count. */
350
	*argcp = nargv - *argvp - 1;
351
}