GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: main.c,v 1.59 2016/08/31 21:00:31 deraadt Exp $ */ |
||
2 |
/* $NetBSD: main.c,v 1.14 1997/06/05 11:13:24 lukem Exp $ */ |
||
3 |
|||
4 |
/*- |
||
5 |
* Copyright (c) 1980, 1991, 1993, 1994 |
||
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/param.h> /* MAXBSIZE DEV_BSIZE roundup */ |
||
34 |
#include <sys/mount.h> |
||
35 |
#include <sys/stat.h> |
||
36 |
#include <sys/time.h> |
||
37 |
#include <sys/ioctl.h> |
||
38 |
#include <sys/disklabel.h> |
||
39 |
#include <sys/dkio.h> |
||
40 |
#include <ufs/ffs/fs.h> |
||
41 |
#include <ufs/ufs/dinode.h> |
||
42 |
|||
43 |
#include <protocols/dumprestore.h> |
||
44 |
|||
45 |
#include <ctype.h> |
||
46 |
#include <err.h> |
||
47 |
#include <errno.h> |
||
48 |
#include <fcntl.h> |
||
49 |
#include <fstab.h> |
||
50 |
#include <paths.h> |
||
51 |
#include <signal.h> |
||
52 |
#include <stdio.h> |
||
53 |
#include <stdlib.h> |
||
54 |
#include <string.h> |
||
55 |
#include <time.h> |
||
56 |
#include <unistd.h> |
||
57 |
#include <limits.h> |
||
58 |
#include <util.h> |
||
59 |
|||
60 |
#include "dump.h" |
||
61 |
#include "pathnames.h" |
||
62 |
|||
63 |
int notify = 0; /* notify operator flag */ |
||
64 |
int64_t blockswritten = 0; /* number of blocks written on current tape */ |
||
65 |
int tapeno = 0; /* current tape number */ |
||
66 |
int density = 0; /* density in bytes/0.1" */ |
||
67 |
int ntrec = NTREC; /* # tape blocks in each tape record */ |
||
68 |
int cartridge = 0; /* Assume non-cartridge tape */ |
||
69 |
int64_t blocksperfile; /* output blocks per file */ |
||
70 |
char *host = NULL; /* remote host (if any) */ |
||
71 |
int maxbsize = 64*1024; /* XXX MAXBSIZE from sys/param.h */ |
||
72 |
|||
73 |
struct disklabel lab; |
||
74 |
|||
75 |
/* |
||
76 |
* Possible superblock locations ordered from most to least likely. |
||
77 |
*/ |
||
78 |
static int sblock_try[] = SBLOCKSEARCH; |
||
79 |
|||
80 |
static long long numarg(char *, long long, long long); |
||
81 |
static void obsolete(int *, char **[]); |
||
82 |
static void usage(void); |
||
83 |
|||
84 |
int |
||
85 |
main(int argc, char *argv[]) |
||
86 |
{ |
||
87 |
ino_t ino; |
||
88 |
int dirty; |
||
89 |
union dinode *dp; |
||
90 |
struct fstab *dt; |
||
91 |
char *map; |
||
92 |
1 |
int ch, mode; |
|
93 |
1 |
struct tm then; |
|
94 |
1 |
struct statfs fsbuf; |
|
95 |
int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; |
||
96 |
ino_t maxino; |
||
97 |
1 |
time_t t; |
|
98 |
int dirlist; |
||
99 |
1 |
char *toplevel, *str, *mount_point = NULL, *realpath; |
|
100 |
int just_estimate = 0; |
||
101 |
1 |
u_int64_t zero_uid = 0; |
|
102 |
|||
103 |
1 |
spcl.c_date = (int64_t)time(NULL); |
|
104 |
|||
105 |
1 |
tsize = 0; /* Default later, based on 'c' option for cart tapes */ |
|
106 |
1 |
if ((tape = getenv("TAPE")) == NULL) |
|
107 |
1 |
tape = _PATH_DEFTAPE; |
|
108 |
1 |
dumpdates = _PATH_DUMPDATES; |
|
109 |
1 |
temp = _PATH_DTMP; |
|
110 |
if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) |
||
111 |
quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); |
||
112 |
1 |
level = '0'; |
|
113 |
|||
114 |
✗✓ | 1 |
if (argc < 2) |
115 |
usage(); |
||
116 |
|||
117 |
1 |
obsolete(&argc, &argv); |
|
118 |
✓✗ | 2 |
while ((ch = getopt(argc, argv, "0123456789aB:b:cd:f:h:ns:ST:uWw")) != -1) |
119 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗ |
1 |
switch (ch) { |
120 |
/* dump level */ |
||
121 |
case '0': case '1': case '2': case '3': case '4': |
||
122 |
case '5': case '6': case '7': case '8': case '9': |
||
123 |
level = ch; |
||
124 |
break; |
||
125 |
|||
126 |
case 'B': /* blocks per output file */ |
||
127 |
blocksperfile = numarg("blocks per file", 1, 0); |
||
128 |
break; |
||
129 |
|||
130 |
case 'b': /* blocks per tape write */ |
||
131 |
ntrec = numarg("blocks per write", 1, 1000); |
||
132 |
if (ntrec > maxbsize/1024) { |
||
133 |
msg("Please choose a blocksize <= %dKB\n", |
||
134 |
maxbsize/1024); |
||
135 |
exit(X_STARTUP); |
||
136 |
} |
||
137 |
bflag = 1; |
||
138 |
break; |
||
139 |
|||
140 |
case 'c': /* Tape is cart. not 9-track */ |
||
141 |
cartridge = 1; |
||
142 |
break; |
||
143 |
|||
144 |
case 'd': /* density, in bits per inch */ |
||
145 |
density = numarg("density", 10, 327670) / 10; |
||
146 |
if (density >= 625 && !bflag) |
||
147 |
ntrec = HIGHDENSITYTREC; |
||
148 |
break; |
||
149 |
|||
150 |
case 'f': /* output file */ |
||
151 |
tape = optarg; |
||
152 |
break; |
||
153 |
|||
154 |
case 'h': |
||
155 |
honorlevel = numarg("honor level", 0, 10); |
||
156 |
break; |
||
157 |
|||
158 |
case 'n': /* notify operators */ |
||
159 |
notify = 1; |
||
160 |
break; |
||
161 |
|||
162 |
case 's': /* tape size, feet */ |
||
163 |
tsize = numarg("tape size", 1, 0) * 12 * 10; |
||
164 |
break; |
||
165 |
|||
166 |
case 'S': /* estimate blocks and # of tapes */ |
||
167 |
just_estimate = 1; |
||
168 |
break; |
||
169 |
|||
170 |
case 'T': /* time of last dump */ |
||
171 |
str = strptime(optarg, "%a %b %e %H:%M:%S %Y", &then); |
||
172 |
then.tm_isdst = -1; |
||
173 |
if (str == NULL || (*str != '\n' && *str != '\0')) |
||
174 |
spcl.c_ddate = -1; |
||
175 |
else |
||
176 |
spcl.c_ddate = (int64_t)mktime(&then); |
||
177 |
if (spcl.c_ddate < 0) { |
||
178 |
(void)fprintf(stderr, "bad time \"%s\"\n", |
||
179 |
optarg); |
||
180 |
exit(X_STARTUP); |
||
181 |
} |
||
182 |
Tflag = 1; |
||
183 |
lastlevel = '?'; |
||
184 |
break; |
||
185 |
|||
186 |
case 'u': /* update /etc/dumpdates */ |
||
187 |
uflag = 1; |
||
188 |
break; |
||
189 |
|||
190 |
case 'W': /* what to do */ |
||
191 |
case 'w': |
||
192 |
lastdump(ch); |
||
193 |
exit(X_FINOK); /* do nothing else */ |
||
194 |
break; |
||
195 |
|||
196 |
case 'a': /* `auto-size', Write to EOM. */ |
||
197 |
unlimited = 1; |
||
198 |
break; |
||
199 |
|||
200 |
default: |
||
201 |
usage(); |
||
202 |
} |
||
203 |
argc -= optind; |
||
204 |
argv += optind; |
||
205 |
|||
206 |
if (argc < 1) { |
||
207 |
(void)fprintf(stderr, "Must specify disk or filesystem\n"); |
||
208 |
exit(X_STARTUP); |
||
209 |
} |
||
210 |
|||
211 |
/* |
||
212 |
* determine if disk is a subdirectory, and setup appropriately |
||
213 |
*/ |
||
214 |
dirlist = 0; |
||
215 |
toplevel = NULL; |
||
216 |
for (i = 0; i < argc; i++) { |
||
217 |
struct stat sb; |
||
218 |
|||
219 |
/* Convert potential duid into a device name */ |
||
220 |
if ((diskfd = opendev(argv[i], O_RDONLY | O_NOFOLLOW, 0, |
||
221 |
&realpath)) >= 0) { |
||
222 |
argv[i] = strdup(realpath); |
||
223 |
if (argv[i] == NULL) { |
||
224 |
msg("Cannot malloc realpath\n"); |
||
225 |
exit(X_STARTUP); |
||
226 |
} |
||
227 |
(void)close(diskfd); |
||
228 |
} |
||
229 |
if (lstat(argv[i], &sb) == -1) { |
||
230 |
msg("Cannot lstat %s: %s\n", argv[i], strerror(errno)); |
||
231 |
exit(X_STARTUP); |
||
232 |
} |
||
233 |
if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) |
||
234 |
break; |
||
235 |
if (statfs(argv[i], &fsbuf) == -1) { |
||
236 |
msg("Cannot statfs %s: %s\n", argv[i], strerror(errno)); |
||
237 |
exit(X_STARTUP); |
||
238 |
} |
||
239 |
if (strcmp(argv[i], fsbuf.f_mntonname) == 0) { |
||
240 |
if (dirlist != 0) { |
||
241 |
msg("Can't dump a mountpoint and a filelist\n"); |
||
242 |
exit(X_STARTUP); |
||
243 |
} |
||
244 |
break; /* exit if sole mountpoint */ |
||
245 |
} |
||
246 |
if (!disk) { |
||
247 |
if ((toplevel = strdup(fsbuf.f_mntonname)) == NULL) { |
||
248 |
msg("Cannot malloc diskname\n"); |
||
249 |
exit(X_STARTUP); |
||
250 |
} |
||
251 |
disk = toplevel; |
||
252 |
if (uflag) { |
||
253 |
msg("Ignoring u flag for subdir dump\n"); |
||
254 |
uflag = 0; |
||
255 |
} |
||
256 |
if (level > '0') { |
||
257 |
msg("Subdir dump is done at level 0\n"); |
||
258 |
level = '0'; |
||
259 |
} |
||
260 |
msg("Dumping sub files/directories from %s\n", disk); |
||
261 |
} else { |
||
262 |
if (strcmp(disk, fsbuf.f_mntonname) != 0) { |
||
263 |
msg("%s is not on %s\n", argv[i], disk); |
||
264 |
exit(X_STARTUP); |
||
265 |
} |
||
266 |
} |
||
267 |
msg("Dumping file/directory %s\n", argv[i]); |
||
268 |
dirlist++; |
||
269 |
} |
||
270 |
if (dirlist == 0) { |
||
271 |
disk = *argv++; |
||
272 |
if (argc != 1) { |
||
273 |
(void)fputs("Excess arguments to dump:", stderr); |
||
274 |
while (--argc) { |
||
275 |
(void)putc(' ', stderr); |
||
276 |
(void)fputs(*argv++, stderr); |
||
277 |
} |
||
278 |
(void)putc('\n', stderr); |
||
279 |
exit(X_STARTUP); |
||
280 |
} |
||
281 |
} |
||
282 |
if (Tflag && uflag) { |
||
283 |
(void)fprintf(stderr, |
||
284 |
"You cannot use the T and u flags together.\n"); |
||
285 |
exit(X_STARTUP); |
||
286 |
} |
||
287 |
if (strcmp(tape, "-") == 0) { |
||
288 |
pipeout++; |
||
289 |
tape = "standard output"; |
||
290 |
} |
||
291 |
|||
292 |
if (blocksperfile) |
||
293 |
blocksperfile = blocksperfile / ntrec * ntrec; /* round down */ |
||
294 |
else if (!unlimited) { |
||
295 |
/* |
||
296 |
* Determine how to default tape size and density |
||
297 |
* |
||
298 |
* density tape size |
||
299 |
* 9-track 1600 bpi (160 bytes/.1") 2300 ft. |
||
300 |
* 9-track 6250 bpi (625 bytes/.1") 2300 ft. |
||
301 |
* cartridge 8000 bpi (800 bytes/.1") 1700 ft. |
||
302 |
* (450*4 - slop) |
||
303 |
*/ |
||
304 |
if (density == 0) |
||
305 |
density = cartridge ? 100 : 160; |
||
306 |
if (tsize == 0) |
||
307 |
tsize = cartridge ? 1700L*120L : 2300L*120L; |
||
308 |
} |
||
309 |
|||
310 |
if (strchr(tape, ':')) { |
||
311 |
host = tape; |
||
312 |
tape = strchr(host, ':'); |
||
313 |
*tape++ = '\0'; |
||
314 |
#ifdef RDUMP |
||
315 |
if (rmthost(host) == 0) |
||
316 |
exit(X_STARTUP); |
||
317 |
#else |
||
318 |
(void)fprintf(stderr, "remote dump not enabled\n"); |
||
319 |
exit(X_STARTUP); |
||
320 |
#endif |
||
321 |
} |
||
322 |
|||
323 |
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
||
324 |
signal(SIGHUP, sig); |
||
325 |
if (signal(SIGTERM, SIG_IGN) != SIG_IGN) |
||
326 |
signal(SIGTERM, sig); |
||
327 |
if (signal(SIGINT, interrupt) == SIG_IGN) |
||
328 |
signal(SIGINT, SIG_IGN); |
||
329 |
|||
330 |
getfstab(); /* /etc/fstab snarfed */ |
||
331 |
|||
332 |
/* |
||
333 |
* disk can be either the full special file name, |
||
334 |
* the suffix of the special file name, |
||
335 |
* the special name missing the leading '/', |
||
336 |
* the file system name with or without the leading '/'. |
||
337 |
*/ |
||
338 |
if (!statfs(disk, &fsbuf) && !strcmp(fsbuf.f_mntonname, disk)) { |
||
339 |
/* mounted disk? */ |
||
340 |
disk = rawname(fsbuf.f_mntfromname); |
||
341 |
if (!disk) { |
||
342 |
(void)fprintf(stderr, "cannot get raw name for %s\n", |
||
343 |
fsbuf.f_mntfromname); |
||
344 |
exit(X_STARTUP); |
||
345 |
} |
||
346 |
mount_point = fsbuf.f_mntonname; |
||
347 |
(void)strlcpy(spcl.c_dev, fsbuf.f_mntfromname, |
||
348 |
sizeof(spcl.c_dev)); |
||
349 |
if (dirlist != 0) { |
||
350 |
(void)snprintf(spcl.c_filesys, sizeof(spcl.c_filesys), |
||
351 |
"a subset of %s", mount_point); |
||
352 |
} else { |
||
353 |
(void)strlcpy(spcl.c_filesys, mount_point, |
||
354 |
sizeof(spcl.c_filesys)); |
||
355 |
} |
||
356 |
} else if ((dt = fstabsearch(disk)) != NULL) { |
||
357 |
/* in fstab? */ |
||
358 |
if (strchr(dt->fs_spec, '/')) { |
||
359 |
/* fs_spec is a /dev/something */ |
||
360 |
disk = rawname(dt->fs_spec); |
||
361 |
} else { |
||
362 |
/* fs_spec is a DUID */ |
||
363 |
disk = rawname(disk); |
||
364 |
} |
||
365 |
mount_point = dt->fs_file; |
||
366 |
(void)strlcpy(spcl.c_dev, dt->fs_spec, sizeof(spcl.c_dev)); |
||
367 |
if (dirlist != 0) { |
||
368 |
(void)snprintf(spcl.c_filesys, sizeof(spcl.c_filesys), |
||
369 |
"a subset of %s", mount_point); |
||
370 |
} else { |
||
371 |
(void)strlcpy(spcl.c_filesys, mount_point, |
||
372 |
sizeof(spcl.c_filesys)); |
||
373 |
} |
||
374 |
} else { |
||
375 |
/* must be a device */ |
||
376 |
(void)strlcpy(spcl.c_dev, disk, sizeof(spcl.c_dev)); |
||
377 |
(void)strlcpy(spcl.c_filesys, "an unlisted file system", |
||
378 |
sizeof(spcl.c_filesys)); |
||
379 |
} |
||
380 |
(void)strlcpy(spcl.c_label, "none", sizeof(spcl.c_label)); |
||
381 |
(void)gethostname(spcl.c_host, sizeof(spcl.c_host)); |
||
382 |
spcl.c_level = level - '0'; |
||
383 |
spcl.c_type = TS_TAPE; |
||
384 |
|||
385 |
if ((diskfd = open(disk, O_RDONLY)) < 0) { |
||
386 |
msg("Cannot open %s\n", disk); |
||
387 |
exit(X_STARTUP); |
||
388 |
} |
||
389 |
if (ioctl(diskfd, DIOCGDINFO, (char *)&lab) < 0) |
||
390 |
err(1, "ioctl (DIOCGDINFO)"); |
||
391 |
|||
392 |
if (memcmp(lab.d_uid, &zero_uid, sizeof(lab.d_uid)) != 0) { |
||
393 |
if (asprintf(&duid, |
||
394 |
"%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c", |
||
395 |
lab.d_uid[0], lab.d_uid[1], lab.d_uid[2], lab.d_uid[3], |
||
396 |
lab.d_uid[4], lab.d_uid[5], lab.d_uid[6], lab.d_uid[7], |
||
397 |
disk[strlen(disk)-1]) == -1) { |
||
398 |
msg("Cannot malloc duid\n"); |
||
399 |
exit(X_STARTUP); |
||
400 |
} |
||
401 |
} |
||
402 |
if (!Tflag) |
||
403 |
getdumptime(); /* /etc/dumpdates snarfed */ |
||
404 |
|||
405 |
t = (time_t)spcl.c_date; |
||
406 |
msg("Date of this level %c dump: %s", level, |
||
407 |
t == 0 ? "the epoch\n" : ctime(&t)); |
||
408 |
t = (time_t)spcl.c_ddate; |
||
409 |
msg("Date of last level %c dump: %s", lastlevel, |
||
410 |
t == 0 ? "the epoch\n" : ctime(&t)); |
||
411 |
msg("Dumping %s ", disk); |
||
412 |
if (mount_point != NULL) |
||
413 |
msgtail("(%s) ", mount_point); |
||
414 |
if (host) |
||
415 |
msgtail("to %s on host %s\n", tape, host); |
||
416 |
else |
||
417 |
msgtail("to %s\n", tape); |
||
418 |
|||
419 |
if (ioctl(diskfd, DIOCGPDINFO, (char *)&lab) < 0) |
||
420 |
err(1, "ioctl (DIOCGPDINFO)"); |
||
421 |
sync(); |
||
422 |
sblock = (struct fs *)sblock_buf; |
||
423 |
for (i = 0; sblock_try[i] != -1; i++) { |
||
424 |
ssize_t n = pread(diskfd, sblock, SBLOCKSIZE, |
||
425 |
(off_t)sblock_try[i]); |
||
426 |
if (n == SBLOCKSIZE && (sblock->fs_magic == FS_UFS1_MAGIC || |
||
427 |
(sblock->fs_magic == FS_UFS2_MAGIC && |
||
428 |
sblock->fs_sblockloc == sblock_try[i])) && |
||
429 |
sblock->fs_bsize <= MAXBSIZE && |
||
430 |
sblock->fs_bsize >= sizeof(struct fs)) |
||
431 |
break; |
||
432 |
} |
||
433 |
if (sblock_try[i] == -1) |
||
434 |
quit("Cannot find filesystem superblock\n"); |
||
435 |
tp_bshift = ffs(TP_BSIZE) - 1; |
||
436 |
if (TP_BSIZE != (1 << tp_bshift)) |
||
437 |
quit("TP_BSIZE (%d) is not a power of 2\n", TP_BSIZE); |
||
438 |
#ifdef FS_44INODEFMT |
||
439 |
if (sblock->fs_magic == FS_UFS2_MAGIC || |
||
440 |
sblock->fs_inodefmt >= FS_44INODEFMT) |
||
441 |
spcl.c_flags |= DR_NEWINODEFMT; |
||
442 |
#endif |
||
443 |
maxino = sblock->fs_ipg * sblock->fs_ncg; |
||
444 |
mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE); |
||
445 |
usedinomap = calloc((unsigned) mapsize, sizeof(char)); |
||
446 |
dumpdirmap = calloc((unsigned) mapsize, sizeof(char)); |
||
447 |
dumpinomap = calloc((unsigned) mapsize, sizeof(char)); |
||
448 |
tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); |
||
449 |
|||
450 |
nonodump = spcl.c_level < honorlevel; |
||
451 |
|||
452 |
(void)signal(SIGINFO, statussig); |
||
453 |
|||
454 |
msg("mapping (Pass I) [regular files]\n"); |
||
455 |
anydirskipped = mapfiles(maxino, &tapesize, toplevel, |
||
456 |
(dirlist ? argv : NULL)); |
||
457 |
|||
458 |
msg("mapping (Pass II) [directories]\n"); |
||
459 |
while (anydirskipped) { |
||
460 |
anydirskipped = mapdirs(maxino, &tapesize); |
||
461 |
} |
||
462 |
|||
463 |
if (pipeout || unlimited) { |
||
464 |
tapesize += 10; /* 10 trailer blocks */ |
||
465 |
msg("estimated %lld tape blocks.\n", tapesize); |
||
466 |
} else { |
||
467 |
double fetapes; |
||
468 |
|||
469 |
if (blocksperfile) |
||
470 |
fetapes = (double) tapesize / blocksperfile; |
||
471 |
else if (cartridge) { |
||
472 |
/* Estimate number of tapes, assuming streaming stops at |
||
473 |
the end of each block written, and not in mid-block. |
||
474 |
Assume no erroneous blocks; this can be compensated |
||
475 |
for with an artificially low tape size. */ |
||
476 |
fetapes = |
||
477 |
( tapesize /* blocks */ |
||
478 |
* TP_BSIZE /* bytes/block */ |
||
479 |
* (1.0/density) /* 0.1" / byte */ |
||
480 |
+ |
||
481 |
tapesize /* blocks */ |
||
482 |
* (1.0/ntrec) /* streaming-stops per block */ |
||
483 |
* 15.48 /* 0.1" / streaming-stop */ |
||
484 |
) * (1.0 / tsize ); /* tape / 0.1" */ |
||
485 |
} else { |
||
486 |
/* Estimate number of tapes, for old fashioned 9-track |
||
487 |
tape */ |
||
488 |
int tenthsperirg = (density == 625) ? 3 : 7; |
||
489 |
fetapes = |
||
490 |
( tapesize /* blocks */ |
||
491 |
* TP_BSIZE /* bytes / block */ |
||
492 |
* (1.0/density) /* 0.1" / byte */ |
||
493 |
+ |
||
494 |
tapesize /* blocks */ |
||
495 |
* (1.0/ntrec) /* IRG's / block */ |
||
496 |
* tenthsperirg /* 0.1" / IRG */ |
||
497 |
) * (1.0 / tsize ); /* tape / 0.1" */ |
||
498 |
} |
||
499 |
etapes = fetapes; /* truncating assignment */ |
||
500 |
etapes++; |
||
501 |
/* count the dumped inodes map on each additional tape */ |
||
502 |
tapesize += (etapes - 1) * |
||
503 |
(howmany(mapsize * sizeof(char), TP_BSIZE) + 1); |
||
504 |
tapesize += etapes + 10; /* headers + 10 trailer blks */ |
||
505 |
msg("estimated %lld tape blocks on %3.2f tape(s).\n", |
||
506 |
tapesize, fetapes); |
||
507 |
} |
||
508 |
|||
509 |
/* |
||
510 |
* Exit if user wants an estimate of blocks and # of tapes only. |
||
511 |
*/ |
||
512 |
if (just_estimate) |
||
513 |
exit(X_FINOK); |
||
514 |
|||
515 |
/* |
||
516 |
* Allocate tape buffer. |
||
517 |
*/ |
||
518 |
if (!alloctape()) |
||
519 |
quit("can't allocate tape buffers - try a smaller blocking factor.\n"); |
||
520 |
|||
521 |
startnewtape(1); |
||
522 |
(void)time(&tstart_writing); |
||
523 |
xferrate = 0; |
||
524 |
dumpmap(usedinomap, TS_CLRI, maxino - 1); |
||
525 |
|||
526 |
msg("dumping (Pass III) [directories]\n"); |
||
527 |
dirty = 0; /* XXX just to get gcc to shut up */ |
||
528 |
for (map = dumpdirmap, ino = 1; ino < maxino; ino++) { |
||
529 |
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ |
||
530 |
dirty = *map++; |
||
531 |
else |
||
532 |
dirty >>= 1; |
||
533 |
if ((dirty & 1) == 0) |
||
534 |
continue; |
||
535 |
/* |
||
536 |
* Skip directory inodes deleted and maybe reallocated |
||
537 |
*/ |
||
538 |
dp = getino(ino, &mode); |
||
539 |
if (mode != IFDIR) |
||
540 |
continue; |
||
541 |
(void)dumpino(dp, ino); |
||
542 |
} |
||
543 |
|||
544 |
msg("dumping (Pass IV) [regular files]\n"); |
||
545 |
for (map = dumpinomap, ino = 1; ino < maxino; ino++) { |
||
546 |
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ |
||
547 |
dirty = *map++; |
||
548 |
else |
||
549 |
dirty >>= 1; |
||
550 |
if ((dirty & 1) == 0) |
||
551 |
continue; |
||
552 |
/* |
||
553 |
* Skip inodes deleted and reallocated as directories. |
||
554 |
*/ |
||
555 |
dp = getino(ino, &mode); |
||
556 |
if (mode == IFDIR) |
||
557 |
continue; |
||
558 |
(void)dumpino(dp, ino); |
||
559 |
} |
||
560 |
|||
561 |
spcl.c_type = TS_END; |
||
562 |
for (i = 0; i < ntrec; i++) |
||
563 |
writeheader(maxino - 1); |
||
564 |
if (pipeout) |
||
565 |
msg("%lld tape blocks\n", spcl.c_tapea); |
||
566 |
else |
||
567 |
msg("%lld tape blocks on %d volume%s\n", |
||
568 |
spcl.c_tapea, spcl.c_volume, |
||
569 |
(spcl.c_volume == 1) ? "" : "s"); |
||
570 |
t = (time_t)spcl.c_date; |
||
571 |
msg("Date of this level %c dump: %s", level, |
||
572 |
t == 0 ? "the epoch\n" : ctime(&t)); |
||
573 |
t = do_stats(); |
||
574 |
msg("Date this dump completed: %s", ctime(&t)); |
||
575 |
msg("Average transfer rate: %ld KB/s\n", xferrate / tapeno); |
||
576 |
putdumptime(); |
||
577 |
trewind(); |
||
578 |
broadcast("DUMP IS DONE!\7\7\n"); |
||
579 |
msg("DUMP IS DONE\n"); |
||
580 |
Exit(X_FINOK); |
||
581 |
/* NOTREACHED */ |
||
582 |
} |
||
583 |
|||
584 |
static void |
||
585 |
usage(void) |
||
586 |
{ |
||
587 |
extern char *__progname; |
||
588 |
|||
589 |
(void)fprintf(stderr, "usage: %s [-0123456789acnSuWw] [-B records] " |
||
590 |
"[-b blocksize] [-d density]\n" |
||
591 |
"\t[-f file] [-h level] [-s feet] " |
||
592 |
"[-T date] files-to-dump\n", |
||
593 |
__progname); |
||
594 |
exit(X_STARTUP); |
||
595 |
} |
||
596 |
|||
597 |
/* |
||
598 |
* Pick up a numeric argument. It must be nonnegative and in the given |
||
599 |
* range (except that a vmax of 0 means unlimited). |
||
600 |
*/ |
||
601 |
static long long |
||
602 |
numarg(char *meaning, long long vmin, long long vmax) |
||
603 |
{ |
||
604 |
long long val; |
||
605 |
const char *errstr; |
||
606 |
|||
607 |
if (vmax == 0) |
||
608 |
vmax = LLONG_MAX; |
||
609 |
val = strtonum(optarg, vmin, vmax, &errstr); |
||
610 |
if (errstr) |
||
611 |
errx(X_STARTUP, "%s is %s [%lld - %lld]", |
||
612 |
meaning, errstr, vmin, vmax); |
||
613 |
|||
614 |
return (val); |
||
615 |
} |
||
616 |
|||
617 |
void |
||
618 |
sig(int signo) |
||
619 |
{ |
||
620 |
switch(signo) { |
||
621 |
case SIGALRM: |
||
622 |
case SIGHUP: |
||
623 |
case SIGTERM: |
||
624 |
/* XXX signal race */ |
||
625 |
if (pipeout) |
||
626 |
quit("Signal on pipe: cannot recover\n"); |
||
627 |
msg("Rewriting attempted as response to unknown signal.\n"); |
||
628 |
(void)fflush(stderr); |
||
629 |
(void)fflush(stdout); |
||
630 |
close_rewind(); |
||
631 |
exit(X_REWRITE); |
||
632 |
/* NOTREACHED */ |
||
633 |
} |
||
634 |
} |
||
635 |
|||
636 |
char * |
||
637 |
rawname(char *cp) |
||
638 |
{ |
||
639 |
static char rawbuf[PATH_MAX]; |
||
640 |
char *dp = strrchr(cp, '/'); |
||
641 |
char *prefix; |
||
642 |
|||
643 |
if (dp == NULL) |
||
644 |
return (NULL); |
||
645 |
prefix = dp[1] == 'r' ? "" : "r"; |
||
646 |
*dp = '\0'; |
||
647 |
(void)snprintf(rawbuf, sizeof(rawbuf), "%s/%s%s", cp, prefix, dp + 1); |
||
648 |
*dp = '/'; |
||
649 |
return (rawbuf); |
||
650 |
} |
||
651 |
|||
652 |
char * |
||
653 |
getduid(char *path) |
||
654 |
{ |
||
655 |
int fd; |
||
656 |
struct disklabel lab; |
||
657 |
u_int64_t zero_uid = 0; |
||
658 |
char *duid; |
||
659 |
|||
660 |
if ((fd = opendev(path, O_RDONLY | O_NOFOLLOW, 0, NULL)) >= 0) { |
||
661 |
if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { |
||
662 |
close(fd); |
||
663 |
warn("ioctl(DIOCGDINFO)"); |
||
664 |
return (NULL); |
||
665 |
} |
||
666 |
close(fd); |
||
667 |
|||
668 |
if (memcmp(lab.d_uid, &zero_uid, sizeof(lab.d_uid)) != 0) { |
||
669 |
if (asprintf(&duid, |
||
670 |
"%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c", |
||
671 |
lab.d_uid[0], lab.d_uid[1], lab.d_uid[2], |
||
672 |
lab.d_uid[3], lab.d_uid[4], lab.d_uid[5], |
||
673 |
lab.d_uid[6], lab.d_uid[7], |
||
674 |
path[strlen(path)-1]) == -1) { |
||
675 |
warn("Cannot malloc duid"); |
||
676 |
return (NULL); |
||
677 |
} |
||
678 |
return (duid); |
||
679 |
} |
||
680 |
} |
||
681 |
|||
682 |
return (NULL); |
||
683 |
} |
||
684 |
|||
685 |
/* |
||
686 |
* obsolete -- |
||
687 |
* Change set of key letters and ordered arguments into something |
||
688 |
* getopt(3) will like. |
||
689 |
*/ |
||
690 |
static void |
||
691 |
obsolete(int *argcp, char **argvp[]) |
||
692 |
{ |
||
693 |
int argc, flags; |
||
694 |
char *ap, **argv, *flagsp, **nargv, *p; |
||
695 |
size_t len; |
||
696 |
|||
697 |
/* Setup. */ |
||
698 |
2 |
argv = *argvp; |
|
699 |
1 |
argc = *argcp; |
|
700 |
|||
701 |
/* Return if no arguments or first argument has leading dash. */ |
||
702 |
1 |
ap = argv[1]; |
|
703 |
✓✗✗✓ |
2 |
if (argc == 1 || *ap == '-') |
704 |
return; |
||
705 |
|||
706 |
/* Allocate space for new arguments. */ |
||
707 |
✓✗✗✓ |
2 |
if ((*argvp = nargv = calloc(argc + 1, sizeof(char *))) == NULL || |
708 |
1 |
(p = flagsp = malloc(strlen(ap) + 2)) == NULL) |
|
709 |
err(1, NULL); |
||
710 |
|||
711 |
1 |
*nargv++ = *argv; |
|
712 |
1 |
argv += 2; |
|
713 |
|||
714 |
✓✓ | 4 |
for (flags = 0; *ap; ++ap) { |
715 |
✗✗✗✗ ✗✗✗✓ |
1 |
switch (*ap) { |
716 |
case 'B': |
||
717 |
case 'b': |
||
718 |
case 'd': |
||
719 |
case 'f': |
||
720 |
case 'h': |
||
721 |
case 's': |
||
722 |
case 'T': |
||
723 |
if (*argv == NULL) { |
||
724 |
warnx("option requires an argument -- %c", *ap); |
||
725 |
usage(); |
||
726 |
} |
||
727 |
len = 2 + strlen(*argv) + 1; |
||
728 |
if ((nargv[0] = malloc(len)) == NULL) |
||
729 |
err(1, NULL); |
||
730 |
nargv[0][0] = '-'; |
||
731 |
nargv[0][1] = *ap; |
||
732 |
(void)strlcpy(&nargv[0][2], *argv, len - 2); |
||
733 |
++argv; |
||
734 |
++nargv; |
||
735 |
break; |
||
736 |
default: |
||
737 |
✓✗ | 1 |
if (!flags) { |
738 |
1 |
*p++ = '-'; |
|
739 |
flags = 1; |
||
740 |
1 |
} |
|
741 |
1 |
*p++ = *ap; |
|
742 |
1 |
break; |
|
743 |
} |
||
744 |
} |
||
745 |
|||
746 |
/* Terminate flags, or toss the buffer we did not use. */ |
||
747 |
✓✗ | 1 |
if (flags) { |
748 |
1 |
*p = '\0'; |
|
749 |
1 |
*nargv++ = flagsp; |
|
750 |
1 |
} else |
|
751 |
free(flagsp); |
||
752 |
|||
753 |
/* Copy remaining arguments. */ |
||
754 |
✗✓ | 1 |
while ((*nargv++ = *argv++)) |
755 |
continue; |
||
756 |
|||
757 |
/* Update argument count. */ |
||
758 |
1 |
*argcp = nargv - *argvp - 1; |
|
759 |
2 |
} |
Generated by: GCOVR (Version 3.3) |