1 /* @(#)volhdr.c 1.48 19/12/03 Copyright 1994, 2003-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)volhdr.c 1.48 19/12/03 Copyright 1994, 2003-2019 J. Schilling";
6 #endif
7 /*
8 * Volume header related routines.
9 *
10 * Copyright (c) 1994, 2003-2019 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26
27 #include <schily/stdio.h>
28 #include <schily/stdlib.h>
29 #include <schily/unistd.h>
30 #include <schily/hostname.h>
31 #include "star.h"
32 #include "props.h"
33 #include "table.h"
34 #include <schily/standard.h>
35 #include <schily/string.h>
36 #define __XDEV__ /* Needed to activate _dev_major()/_dev_minor() */
37 #include <schily/device.h>
38 #define GT_COMERR /* #define comerr gtcomerr */
39 #define GT_ERROR /* #define error gterror */
40 #include <schily/schily.h>
41 #include <schily/libport.h>
42 #include "starsubs.h"
43 #include "dumpdate.h"
44 #include "xtab.h"
45 #include "fifo.h"
46
47 extern FILE *vpr;
48 extern BOOL multivol;
49 extern BOOL binflag;
50 extern long chdrtype;
51 extern char *vers;
52 extern int verbose;
53 extern Ullong tsize;
54 extern BOOL ghdr;
55
56 extern struct timespec ddate; /* The current dump date */
57
58 extern m_stats *stats;
59
60 extern GINFO *gip; /* Global information pointer */
61 extern GINFO *grip; /* Global read info pointer */
62
63 EXPORT void ginit __PR((void));
64 EXPORT void grinit __PR((void));
65 LOCAL int xstrcpy __PR((char **newp, char *old, char *p, int len));
66 EXPORT void gipsetup __PR((GINFO *gp));
67 EXPORT void griprint __PR((GINFO *gp));
68 EXPORT BOOL verifyvol __PR((char *buf, int amt, int volno, int *skipp));
69 LOCAL BOOL vrfy_gvolhdr __PR((char *buf, int amt, int volno, int *skipp));
70 EXPORT char *dt_name __PR((int type));
71 EXPORT int dt_type __PR((char *name));
72 EXPORT void put_release __PR((void));
73 EXPORT void put_archtype __PR((void));
74 EXPORT void put_gvolhdr __PR((char *name));
75 EXPORT void put_volhdr __PR((char *name, BOOL putv));
76 EXPORT void put_svolhdr __PR((char *name));
77 EXPORT void put_multhdr __PR((off_t size, off_t off));
78 EXPORT BOOL get_volhdr __PR((FINFO *info, char *vhname));
79 LOCAL void get_label __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
80 LOCAL void get_hostname __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
81 LOCAL void get_filesys __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
82 LOCAL void get_cwd __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
83 LOCAL void get_device __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
84 LOCAL void get_dumptype __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
85 LOCAL void get_dumplevel __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
86 LOCAL void get_reflevel __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
87 LOCAL void get_dumpdate __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
88 LOCAL void get_refdate __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
89 LOCAL void get_volno __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
90 LOCAL void get_blockoff __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
91 LOCAL void get_blocksize __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
92 LOCAL void get_tapesize __PR((FINFO *info, char *keyword, int klen, char *arg, size_t len));
93
94 /*
95 * Important for the correctness of gen_number(): As long as we stay <= 55
96 * chars for the keyword, a 128 bit number entry will fit into 100 chars.
97 */
98 EXPORT xtab_t volhtab[] = {
99 { "SCHILY.volhdr.label", 19, get_label, 0 },
100 { "SCHILY.volhdr.hostname", 22, get_hostname, 0 },
101 { "SCHILY.volhdr.filesys", 21, get_filesys, 0 },
102 { "SCHILY.volhdr.cwd", 17, get_cwd, 0 },
103 { "SCHILY.volhdr.device", 20, get_device, 0 },
104 { "SCHILY.volhdr.dumptype", 22, get_dumptype, 0 },
105 { "SCHILY.volhdr.dumplevel", 23, get_dumplevel, 0 },
106 { "SCHILY.volhdr.reflevel", 22, get_reflevel, 0 },
107 { "SCHILY.volhdr.dumpdate", 22, get_dumpdate, 0 },
108 { "SCHILY.volhdr.refdate", 21, get_refdate, 0 },
109 { "SCHILY.volhdr.volno", 19, get_volno, 0 },
110 { "SCHILY.volhdr.blockoff", 22, get_blockoff, 0 },
111 { "SCHILY.volhdr.blocksize", 23, get_blocksize, 0 },
112 { "SCHILY.volhdr.tapesize", 22, get_tapesize, 0 },
113
114 { NULL, 0, NULL, 0 }};
115
116 EXPORT void
ginit()117 ginit()
118 {
119 extern int dumplevel;
120 extern int nblocks;
121
122 gip->label = NULL;
123 gip->hostname = NULL;
124 gip->filesys = NULL;
125 gip->cwd = NULL;
126 gip->device = NULL;
127 gip->release = vers;
128 gip->archtype = chdrtype;
129 gip->dumptype = 0;
130 gip->dumplevel = dumplevel;
131 gip->reflevel = -1;
132 gip->dumpdate = ddate;
133 gip->refdate.tv_sec = 0;
134 gip->refdate.tv_nsec = 0;
135 gip->volno = 1;
136 gip->tapesize = tsize;
137 gip->blockoff = 0;
138 gip->blocksize = nblocks;
139 gip->gflags = GF_RELEASE|GF_DUMPLEVEL|GF_REFLEVEL|GF_DUMPDATE|
140 GF_VOLNO|GF_TAPESIZE|GF_BLOCKOFF|GF_BLOCKSIZE;
141 }
142
143 EXPORT void
grinit()144 grinit()
145 {
146 if (grip->label) {
147 if ((grip->gflags & GF_NOALLOC) == 0)
148 free(grip->label);
149 grip->label = NULL;
150 }
151 if (grip->hostname) {
152 if ((grip->gflags & GF_NOALLOC) == 0)
153 free(grip->hostname);
154 grip->hostname = NULL;
155 }
156 if (grip->filesys) {
157 if ((grip->gflags & GF_NOALLOC) == 0)
158 free(grip->filesys);
159 grip->filesys = NULL;
160 }
161 if (grip->cwd) {
162 if ((grip->gflags & GF_NOALLOC) == 0)
163 free(grip->cwd);
164 grip->cwd = NULL;
165 }
166 if (grip->device) {
167 if ((grip->gflags & GF_NOALLOC) == 0)
168 free(grip->device);
169 grip->device = NULL;
170 }
171 if (grip->release) {
172 if ((grip->gflags & GF_NOALLOC) == 0)
173 free(grip->release);
174 grip->release = NULL;
175 }
176 grip->archtype = H_UNDEF;
177 grip->dumptype = 0;
178 grip->dumplevel = 0;
179 grip->reflevel = 0;
180 grip->dumpdate.tv_sec = 0;
181 grip->dumpdate.tv_nsec = 0;
182 grip->refdate.tv_sec = 0;
183 grip->refdate.tv_nsec = 0;
184 grip->volno = 0;
185 grip->tapesize = 0;
186 grip->blockoff = 0;
187 grip->blocksize = 0;
188 grip->gflags = 0;
189 }
190
191 /*
192 * A special string copy that is used copy strings into the limited space
193 * in the shared memory.
194 */
195 LOCAL int
xstrcpy(newp,old,p,len)196 xstrcpy(newp, old, p, len)
197 char **newp;
198 char *old;
199 char *p;
200 int len;
201 {
202 int slen;
203
204 if (old == NULL)
205 return (0);
206
207 slen = strlen(old) + 1;
208 if (slen > len)
209 return (0);
210 *newp = p;
211 strncpy(p, old, len);
212 p[len-1] = '\0';
213
214 return (slen);
215 }
216
217 /*
218 * Set up the global GINFO *gip structure from a structure that just
219 * has been read from the information on the current medium.
220 * This structure is inside the shared memory if we are using the fifo.
221 */
222 EXPORT void
gipsetup(gp)223 gipsetup(gp)
224 GINFO *gp;
225 {
226 #ifdef FIFO
227 extern m_head *mp;
228 extern BOOL use_fifo;
229 #endif
230 if (gip->gflags & GF_MINIT) {
231 return;
232 }
233 *gip = *gp;
234 gip->label = NULL;
235 gip->hostname = NULL;
236 gip->filesys = NULL;
237 gip->cwd = NULL;
238 gip->device = NULL;
239 gip->release = NULL;
240
241 #ifdef FIFO
242 if (use_fifo) {
243 char *p = (char *)&gip[1];
244 int len = mp->rsize;
245 int slen;
246
247 slen = xstrcpy(&gip->label, gp->label, p, len);
248 p += slen;
249 len -= slen;
250 slen = xstrcpy(&gip->filesys, gp->filesys, p, len);
251 p += slen;
252 len -= slen;
253 slen = xstrcpy(&gip->cwd, gp->cwd, p, len);
254 p += slen;
255 len -= slen;
256 slen = xstrcpy(&gip->hostname, gp->hostname, p, len);
257 p += slen;
258 len -= slen;
259 slen = xstrcpy(&gip->release, gp->release, p, len);
260 p += slen;
261 len -= slen;
262 slen = xstrcpy(&gip->device, gp->device, p, len);
263 p += slen;
264 len -= slen;
265 gip->gflags |= GF_NOALLOC;
266 } else
267 #endif
268 {
269 if (gp->label) {
270 if (gip->label)
271 free(gip->label);
272 gip->label = ___savestr(gp->label);
273 }
274 if (gp->filesys) {
275 if (gip->filesys)
276 free(gip->filesys);
277 gip->filesys = ___savestr(gp->filesys);
278 }
279 if (gp->cwd) {
280 if (gip->cwd)
281 free(gip->cwd);
282 gip->cwd = ___savestr(gp->cwd);
283 }
284 if (gp->hostname) {
285 if (gip->hostname)
286 free(gip->hostname);
287 gip->hostname = ___savestr(gp->hostname);
288 }
289 if (gp->release) {
290 if (gip->release)
291 free(gip->release);
292 gip->release = ___savestr(gp->release);
293 }
294 if (gp->device) {
295 if (gip->device)
296 free(gip->device);
297 gip->device = ___savestr(gp->device);
298 }
299 }
300 if (gp->volno > 1) /* Allow to start with vol # != 1 */
301 stats->volno = gp->volno;
302 gip->gflags |= GF_MINIT;
303 }
304
305 EXPORT void
griprint(gp)306 griprint(gp)
307 GINFO *gp;
308 {
309 register FILE *f = vpr;
310
311 if (verbose <= 0)
312 return;
313
314 if (gp->label)
315 fgtprintf(f, "Label %s\n", gp->label);
316
317 if (gp->hostname)
318 fgtprintf(f, "Host name %s\n", gp->hostname);
319
320 if (gp->filesys)
321 fgtprintf(f, "File system %s\n", gp->filesys);
322
323 if (gp->cwd)
324 fgtprintf(f, "Working dir %s\n", gp->cwd);
325
326 if (gp->device)
327 fgtprintf(f, "Device %s\n", gp->device);
328
329 if (gp->release)
330 fgtprintf(f, "Release %s\n", gp->release);
331
332 if (gp->archtype != H_UNDEF)
333 fgtprintf(f, "Archtype %s\n", hdr_name(gp->archtype));
334
335 if (gp->gflags & GF_DUMPTYPE)
336 fgtprintf(f, "Dumptype %s\n", dt_name(gp->dumptype));
337
338 if (gp->gflags & GF_DUMPLEVEL)
339 fgtprintf(f, "Dumplevel %d\n", gp->dumplevel);
340
341 if (gp->gflags & GF_REFLEVEL)
342 fgtprintf(f, "Reflevel %d\n", gp->reflevel);
343
344 if (gp->gflags & GF_DUMPDATE) {
345 fgtprintf(f, "Dumpdate %lld.%9.9lld (%s)\n",
346 (Llong)gp->dumpdate.tv_sec,
347 (Llong)gp->dumpdate.tv_nsec,
348 dumpdate(&gp->dumpdate));
349 }
350 if (gp->gflags & GF_REFDATE) {
351 fgtprintf(f, "Refdate %lld.%9.9lld (%s)\n",
352 (Llong)gp->refdate.tv_sec,
353 (Llong)gp->refdate.tv_nsec,
354 dumpdate(&gp->refdate));
355 }
356 if (gp->gflags & GF_VOLNO)
357 fgtprintf(f, "Volno %d\n", gp->volno);
358 if (gp->gflags & GF_BLOCKOFF)
359 fgtprintf(f, "Blockoff %llu records\n", gp->blockoff);
360 if (gp->gflags & GF_BLOCKSIZE)
361 fprintf(f, "Blocksize %d records\n", gp->blocksize);
362 if (gp->gflags & GF_TAPESIZE)
363 fgtprintf(f, "Tapesize %llu records\n", gp->tapesize);
364 }
365
366 EXPORT BOOL
verifyvol(buf,amt,volno,skipp)367 verifyvol(buf, amt, volno, skipp)
368 char *buf;
369 int amt;
370 int volno;
371 int *skipp;
372 {
373 TCB *ptb = (TCB *)buf;
374
375 *skipp = 0;
376
377 /*
378 * Minimale Blockgroesse ist 2,5k
379 * 'g' Header, 512 Byte Content and a 'V' header
380 */
381 if (ptb->ustar_dbuf.t_typeflag == 'g') {
382 if (pr_validtype(ptb->ustar_dbuf.t_typeflag) &&
383 tarsum_ok(ptb))
384 return (vrfy_gvolhdr(buf, amt, volno, skipp));
385 }
386 if (ptb->ustar_dbuf.t_typeflag == 'x') {
387 if (pr_validtype(ptb->ustar_dbuf.t_typeflag) &&
388 tarsum_ok(ptb)) {
389 Ullong ull;
390 int xlen;
391
392 stolli(ptb->dbuf.t_size, &ull);
393 xlen = ull;
394 xlen = 1 + tarblocks(xlen);
395 *skipp += xlen;
396 ptb = (TCB *)&((char *)ptb)[*skipp * TBLOCK];
397 }
398 }
399
400 if (ptb->ustar_dbuf.t_typeflag == 'V' ||
401 ptb->ustar_dbuf.t_typeflag == 'M') {
402 if (pr_validtype(ptb->ustar_dbuf.t_typeflag) &&
403 tarsum_ok(ptb)) {
404 *skipp += 1;
405 ptb = (TCB *)&buf[*skipp * TBLOCK];
406 }
407 }
408 return (TRUE);
409 }
410
411 LOCAL BOOL
vrfy_gvolhdr(buf,amt,volno,skipp)412 vrfy_gvolhdr(buf, amt, volno, skipp)
413 char *buf;
414 int amt;
415 int volno;
416 int *skipp;
417 {
418 TCB *ptb = (TCB *)buf;
419 FINFO finfo;
420 Ullong ull;
421 int xlen = amt - TBLOCK - 1;
422 char *p = &buf[TBLOCK];
423 char *ep;
424 char ec;
425 Llong bytes;
426 Llong blockoff;
427 BOOL ret = FALSE;
428
429 fillbytes((char *)&finfo, sizeof (finfo), '\0');
430 finfo.f_tcb = ptb;
431
432 if (init_pspace(PS_STDERR, &finfo.f_pname) < 0)
433 return (FALSE);
434 if (init_pspace(PS_STDERR, &finfo.f_plname) < 0)
435 return (FALSE);
436
437 finfo.f_name = finfo.f_pname.ps_path;
438 finfo.f_lname = finfo.f_plname.ps_path;
439
440 /*
441 * File size is strlen of extended header
442 */
443 stolli(ptb->dbuf.t_size, &ull);
444 if (xlen > ull)
445 xlen = ull;
446
447 grinit(); /* Clear/initialize current GINFO read struct */
448 ep = p+xlen;
449 ec = *ep;
450 *ep = '\0';
451 xhparse(&finfo, p, p+xlen);
452 *ep = ec;
453 griprint(grip);
454
455 /*
456 * Return TRUE (no skip) if this was not a volume continuation header.
457 */
458 if ((grip->gflags & GF_VOLNO) == 0) {
459 ret = TRUE;
460 goto out;
461 }
462
463 if ((gip->dumpdate.tv_sec != grip->dumpdate.tv_sec) ||
464 (gip->dumpdate.tv_nsec != grip->dumpdate.tv_nsec)) {
465 errmsgno(EX_BAD,
466 "Dump date %s does not match expected",
467 dumpdate(&grip->dumpdate));
468 error(" %s\n", dumpdate(&gip->dumpdate));
469 ret = FALSE;
470 goto out;
471 }
472 if (volno != grip->volno) {
473 errmsgno(EX_BAD,
474 "Volume number %d does not match expected %d\n",
475 grip->volno, volno);
476 ret = FALSE;
477 goto out;
478 }
479 bytes = stats->Tblocks * (Llong)stats->blocksize + stats->Tparts;
480 blockoff = bytes / TBLOCK;
481 /*
482 * In case we did start past Volume #1, we need to add
483 * the offset of the first volume we did see.
484 */
485 blockoff += gip->blockoff;
486
487 if (grip->blockoff != 0 &&
488 blockoff != grip->blockoff) {
489 comerrno(EX_BAD,
490 "Volume offset %lld does not match expected %lld\n",
491 grip->blockoff, blockoff);
492 /* NOTREACHED */
493 }
494
495 *skipp += 1 + tarblocks(xlen);
496
497 /*
498 * Hier mu� noch ein 'V' Header hin, sonst ist das Archiv nicht
499 * konform zum POSIX Standard.
500 * Alternativ kann aber auch ein 'M'ultivol continuation Header stehen.
501 */
502 ptb = (TCB *)&buf[(1 + tarblocks(xlen)) * TBLOCK];
503
504 if (ptb->ustar_dbuf.t_typeflag == 'x') {
505 if (pr_validtype(ptb->ustar_dbuf.t_typeflag) &&
506 tarsum_ok(ptb)) {
507 stolli(ptb->dbuf.t_size, &ull);
508 xlen = ull;
509 xlen = 1 + tarblocks(xlen);
510 *skipp += xlen;
511 ptb = (TCB *)&((char *)ptb)[xlen * TBLOCK];
512 }
513 }
514
515 if (ptb->ustar_dbuf.t_typeflag == 'V' ||
516 ptb->ustar_dbuf.t_typeflag == 'M') {
517 if (pr_validtype(ptb->ustar_dbuf.t_typeflag) &&
518 tarsum_ok(ptb)) {
519 *skipp += 1;
520 }
521 }
522 ret = TRUE;
523
524 out:
525 free_pspace(&finfo.f_pname);
526 free_pspace(&finfo.f_plname);
527 return (ret);
528 }
529
530 EXPORT char *
dt_name(type)531 dt_name(type)
532 int type;
533 {
534 switch (type) {
535
536 case DT_NONE: return ("none");
537 case DT_FULL: return ("full");
538 case DT_PARTIAL: return ("partial");
539 default: return ("unknown");
540 }
541 }
542
543 EXPORT int
dt_type(name)544 dt_type(name)
545 char *name;
546 {
547 if (streql(name, "none")) {
548 return (DT_NONE);
549 } else if (streql(name, "full")) {
550 return (DT_FULL);
551 } else if (streql(name, "partial")) {
552 return (DT_PARTIAL);
553 } else {
554 return (DT_UNKN);
555 }
556 }
557
558
559 EXPORT void
put_release()560 put_release()
561 {
562 if ((props.pr_flags & PR_VU_XHDR) == 0 || props.pr_xc != 'x')
563 return;
564
565 /*
566 * We may change this in future when more tar implementations
567 * implement POSIX.1-2001
568 */
569 if (H_TYPE(chdrtype) == H_XUSTAR)
570 return;
571
572 gen_text("SCHILY.release", vers, (size_t)-1, 0);
573
574 ghdr = TRUE;
575 }
576
577 EXPORT void
put_archtype()578 put_archtype()
579 {
580 if ((props.pr_flags & PR_VU_XHDR) == 0 || props.pr_xc != 'x')
581 return;
582
583 /*
584 * We may change this in future when more tar implementations
585 * implement POSIX.1-2001
586 */
587 if (H_TYPE(chdrtype) == H_XUSTAR)
588 return;
589
590 gen_text("SCHILY.archtype", hdr_name(chdrtype), (size_t)-1, 0);
591
592 ghdr = TRUE;
593 }
594
595 EXPORT void
put_gvolhdr(name)596 put_gvolhdr(name)
597 char *name;
598 {
599 char nbuf[1024];
600 extern BOOL dodump;
601
602 if ((props.pr_flags & PR_VU_XHDR) == 0 || props.pr_xc != 'x')
603 return;
604
605 /*
606 * We may change this in future when more tar implementations
607 * implement POSIX.1-2001
608 */
609 if (H_TYPE(chdrtype) == H_XUSTAR)
610 return;
611
612 #ifndef DEV_MINOR_NONCONTIG
613 gen_unumber("SCHILY.devminorbits", minorbits);
614 #endif
615
616 gip->label = name;
617 if (gip->dumplevel >= 0 || dodump > 1) {
618 nbuf[0] = '\0';
619 gethostname(nbuf, sizeof (nbuf));
620 gip->hostname = ___savestr(nbuf);
621 }
622
623 if (gip->label)
624 gen_text("SCHILY.volhdr.label", gip->label, (size_t)-1, 0);
625 if (gip->hostname)
626 gen_text("SCHILY.volhdr.hostname", gip->hostname,
627 (size_t)-1, 0);
628 if (gip->filesys)
629 gen_text("SCHILY.volhdr.filesys", gip->filesys, (size_t)-1, 0);
630 if (gip->cwd)
631 gen_text("SCHILY.volhdr.cwd", gip->cwd, (size_t)-1, 0);
632 if (gip->device)
633 gen_text("SCHILY.volhdr.device", gip->device, (size_t)-1, 0);
634
635 if (gip->dumptype > 0)
636 gen_text("SCHILY.volhdr.dumptype", dt_name(gip->dumptype),
637 (size_t)-1, 0);
638 if (gip->dumplevel >= 0)
639 gen_number("SCHILY.volhdr.dumplevel", gip->dumplevel);
640 if (gip->reflevel >= 0)
641 gen_number("SCHILY.volhdr.reflevel", gip->reflevel);
642
643 gen_xtime("SCHILY.volhdr.dumpdate", gip->dumpdate.tv_sec, gip->dumpdate.tv_nsec);
644 if (gip->refdate.tv_sec)
645 gen_xtime("SCHILY.volhdr.refdate", gip->refdate.tv_sec, gip->refdate.tv_nsec);
646
647 if (gip->volno > 0)
648 gen_number("SCHILY.volhdr.volno", gip->volno);
649 if (gip->blockoff > 0)
650 gen_number("SCHILY.volhdr.blockoff", gip->blockoff);
651 if (gip->blocksize > 0)
652 gen_number("SCHILY.volhdr.blocksize", gip->blocksize);
653 if (gip->tapesize > 0)
654 gen_number("SCHILY.volhdr.tapesize", gip->tapesize);
655
656 if (binflag)
657 gen_text("hdrcharset", "BINARY", (size_t)-1, 0);
658
659 if ((xhsize() + 2 * TBLOCK) > (gip->blocksize * TBLOCK)) {
660 errmsgno(EX_BAD, "Panic: Tape record size too small.\n");
661 comerrno(EX_BAD, "Panic: Shorten label or increase tape block size.\n");
662 }
663 ghdr = TRUE;
664 }
665
666 EXPORT void
put_volhdr(name,putv)667 put_volhdr(name, putv)
668 char *name;
669 BOOL putv;
670 {
671 extern Ullong tsize;
672
673 if ((multivol || tsize > 0) && name == 0)
674 name = "<none>";
675
676 put_gvolhdr(name);
677
678 if (name == 0)
679 return;
680
681 if (!putv)
682 return; /* Only a 'g' header is needed */
683
684 put_svolhdr(name);
685 }
686
687 EXPORT void
put_svolhdr(name)688 put_svolhdr(name)
689 char *name;
690 {
691 FINFO finfo;
692 TCB tb;
693
694 if ((props.pr_flags & PR_VOLHDR) == 0)
695 return;
696
697 if (name == 0 || *name == '\0')
698 name = "<none>";
699
700 fillbytes((char *)&finfo, sizeof (FINFO), '\0');
701 filltcb(&tb);
702 finfo.f_name = name;
703 finfo.f_namelen = strlen(name);
704 finfo.f_xftype = XT_VOLHDR;
705 finfo.f_rxftype = XT_VOLHDR;
706 finfo.f_mtime = ddate.tv_sec;
707 finfo.f_mnsec = ddate.tv_nsec;
708 finfo.f_atime = gip->volno;
709 finfo.f_ansec = 0;
710 finfo.f_tcb = &tb;
711 finfo.f_xflags = XF_NOTIME;
712
713 if (!name_to_tcb(&finfo, &tb)) /* Name too long */
714 return;
715
716 info_to_tcb(&finfo, &tb);
717 put_tcb(&tb, &finfo);
718 vprint(&finfo);
719 }
720
721 EXPORT void
put_multhdr(size,off)722 put_multhdr(size, off)
723 off_t size;
724 off_t off;
725 {
726 extern BOOL dodump;
727 FINFO finfo;
728 TCB tb;
729 TCB *mptb;
730 BOOL ododump = dodump;
731
732 fillbytes((char *)&finfo, sizeof (finfo), '\0');
733
734 if ((mptb = (TCB *)get_block(TBLOCK)) == NULL)
735 mptb = &tb;
736 else
737 finfo.f_flags |= F_TCB_BUF;
738 filltcb(mptb);
739 strcpy(mptb->dbuf.t_name, "././@MultHeader");
740 finfo.f_mode = TUREAD|TUWRITE;
741 finfo.f_size = size;
742 finfo.f_rsize = size - off;
743 finfo.f_contoffset = off;
744 finfo.f_xftype = XT_MULTIVOL;
745 finfo.f_rxftype = XT_MULTIVOL;
746 if (props.pr_flags & PR_XHDR)
747 finfo.f_xflags |= XF_NOTIME|XF_REALSIZE|XF_OFFSET;
748
749 info_to_tcb(&finfo, mptb);
750
751 dodump = FALSE;
752 put_tcb(mptb, &finfo);
753 dodump = ododump;
754 }
755
756 EXPORT BOOL
get_volhdr(info,vhname)757 get_volhdr(info, vhname)
758 FINFO *info;
759 char *vhname;
760 {
761 error("Volhdr: %s\n", info->f_name);
762
763 if (vhname) {
764 if (!streql(info->f_name, vhname))
765 return (FALSE);
766 }
767
768 return (TRUE);
769 }
770
771 /* ARGSUSED */
772 LOCAL void
get_label(info,keyword,klen,arg,len)773 get_label(info, keyword, klen, arg, len)
774 FINFO *info;
775 char *keyword;
776 int klen;
777 char *arg;
778 size_t len;
779 {
780 grip->gflags |= GF_LABEL;
781 grip->label = ___savestr(arg);
782 }
783
784 /* ARGSUSED */
785 LOCAL void
get_hostname(info,keyword,klen,arg,len)786 get_hostname(info, keyword, klen, arg, len)
787 FINFO *info;
788 char *keyword;
789 int klen;
790 char *arg;
791 size_t len;
792 {
793 grip->gflags |= GF_HOSTNAME;
794 grip->hostname = ___savestr(arg);
795 }
796
797 /* ARGSUSED */
798 LOCAL void
get_filesys(info,keyword,klen,arg,len)799 get_filesys(info, keyword, klen, arg, len)
800 FINFO *info;
801 char *keyword;
802 int klen;
803 char *arg;
804 size_t len;
805 {
806 grip->gflags |= GF_FILESYS;
807 grip->filesys = ___savestr(arg);
808 }
809
810 /* ARGSUSED */
811 LOCAL void
get_cwd(info,keyword,klen,arg,len)812 get_cwd(info, keyword, klen, arg, len)
813 FINFO *info;
814 char *keyword;
815 int klen;
816 char *arg;
817 size_t len;
818 {
819 grip->gflags |= GF_CWD;
820 grip->cwd = ___savestr(arg);
821 }
822
823 /* ARGSUSED */
824 LOCAL void
get_device(info,keyword,klen,arg,len)825 get_device(info, keyword, klen, arg, len)
826 FINFO *info;
827 char *keyword;
828 int klen;
829 char *arg;
830 size_t len;
831 {
832 grip->gflags |= GF_DEVICE;
833 grip->device = ___savestr(arg);
834 }
835
836 /* ARGSUSED */
837 LOCAL void
get_dumptype(info,keyword,klen,arg,len)838 get_dumptype(info, keyword, klen, arg, len)
839 FINFO *info;
840 char *keyword;
841 int klen;
842 char *arg;
843 size_t len;
844 {
845 if (len == 0) {
846 grip->gflags &= ~GF_DUMPTYPE;
847 grip->dumptype = 0;
848 return;
849 }
850 grip->dumptype = dt_type(arg);
851 if (grip->dumptype == DT_UNKN)
852 errmsgno(EX_BAD, "Unknown dump type '%s'\n", arg);
853 else
854 grip->gflags |= GF_DUMPTYPE;
855 }
856
857 /* ARGSUSED */
858 LOCAL void
get_dumplevel(info,keyword,klen,arg,len)859 get_dumplevel(info, keyword, klen, arg, len)
860 FINFO *info;
861 char *keyword;
862 int klen;
863 char *arg;
864 size_t len;
865 {
866 Ullong ull;
867
868 if (len == 0) {
869 grip->gflags &= ~GF_DUMPLEVEL;
870 grip->dumplevel = 0;
871 return;
872 }
873 if (get_unumber(keyword, arg, &ull, 1000)) {
874 grip->gflags |= GF_DUMPLEVEL;
875 grip->dumplevel = ull;
876 if (grip->dumplevel != ull) {
877 xh_rangeerr(keyword, arg, len);
878 grip->dumplevel = 0;
879 }
880 }
881 }
882
883 /* ARGSUSED */
884 LOCAL void
get_reflevel(info,keyword,klen,arg,len)885 get_reflevel(info, keyword, klen, arg, len)
886 FINFO *info;
887 char *keyword;
888 int klen;
889 char *arg;
890 size_t len;
891 {
892 Ullong ull;
893
894 if (len == 0) {
895 grip->gflags &= ~GF_REFLEVEL;
896 grip->reflevel = 0;
897 return;
898 }
899 if (get_unumber(keyword, arg, &ull, 1000)) {
900 grip->gflags |= GF_REFLEVEL;
901 grip->reflevel = ull;
902 if (grip->reflevel != ull) {
903 xh_rangeerr(keyword, arg, len);
904 grip->reflevel = 0;
905 }
906 }
907 }
908
909 /* ARGSUSED */
910 LOCAL void
get_dumpdate(info,keyword,klen,arg,len)911 get_dumpdate(info, keyword, klen, arg, len)
912 FINFO *info;
913 char *keyword;
914 int klen;
915 char *arg;
916 size_t len;
917 {
918 long nsec;
919 time_t t; /* FreeBSD/MacOS X have broken tv_sec/time_t */
920
921 if (len == 0) {
922 grip->gflags &= ~GF_DUMPDATE;
923 grip->dumpdate.tv_sec = 0;
924 grip->dumpdate.tv_nsec = 0;
925 return;
926 }
927 if (get_xtime(keyword, arg, len, &t, &nsec)) {
928 grip->gflags |= GF_DUMPDATE;
929 grip->dumpdate.tv_sec = t;
930 grip->dumpdate.tv_nsec = nsec;
931 }
932 }
933
934 /* ARGSUSED */
935 LOCAL void
get_refdate(info,keyword,klen,arg,len)936 get_refdate(info, keyword, klen, arg, len)
937 FINFO *info;
938 char *keyword;
939 int klen;
940 char *arg;
941 size_t len;
942 {
943 long nsec;
944 time_t t; /* FreeBSD/MacOS X have broken tv_sec/time_t */
945
946 if (len == 0) {
947 grip->gflags &= ~GF_REFDATE;
948 grip->refdate.tv_sec = 0;
949 grip->refdate.tv_nsec = 0;
950 return;
951 }
952 if (get_xtime(keyword, arg, len, &t, &nsec)) {
953 grip->gflags |= GF_REFDATE;
954 grip->refdate.tv_sec = t;
955 grip->refdate.tv_nsec = nsec;
956 }
957 }
958
959 /* ARGSUSED */
960 LOCAL void
get_volno(info,keyword,klen,arg,len)961 get_volno(info, keyword, klen, arg, len)
962 FINFO *info;
963 char *keyword;
964 int klen;
965 char *arg;
966 size_t len;
967 {
968 Ullong ull;
969
970 if (len == 0) {
971 grip->gflags &= ~GF_VOLNO;
972 grip->volno = 0;
973 return;
974 }
975 if (get_unumber(keyword, arg, &ull, INT_MAX)) {
976 grip->gflags |= GF_VOLNO;
977 grip->volno = ull;
978 if (grip->volno != ull) {
979 xh_rangeerr(keyword, arg, len);
980 grip->volno = 0;
981 }
982 }
983 }
984
985 /* ARGSUSED */
986 LOCAL void
get_blockoff(info,keyword,klen,arg,len)987 get_blockoff(info, keyword, klen, arg, len)
988 FINFO *info;
989 char *keyword;
990 int klen;
991 char *arg;
992 size_t len;
993 {
994 Ullong ull;
995
996 if (len == 0) {
997 grip->gflags &= ~GF_BLOCKOFF;
998 grip->blockoff = 0;
999 return;
1000 }
1001 if (get_unumber(keyword, arg, &ull, ULLONG_MAX)) {
1002 grip->gflags |= GF_BLOCKOFF;
1003 grip->blockoff = ull;
1004 if (grip->blockoff != ull) {
1005 xh_rangeerr(keyword, arg, len);
1006 grip->blockoff = 0;
1007 }
1008 }
1009 }
1010
1011 /* ARGSUSED */
1012 LOCAL void
get_blocksize(info,keyword,klen,arg,len)1013 get_blocksize(info, keyword, klen, arg, len)
1014 FINFO *info;
1015 char *keyword;
1016 int klen;
1017 char *arg;
1018 size_t len;
1019 {
1020 Ullong ull;
1021
1022 if (len == 0) {
1023 grip->gflags &= ~GF_BLOCKSIZE;
1024 grip->blocksize = 0;
1025 return;
1026 }
1027 if (get_unumber(keyword, arg, &ull, INT_MAX)) {
1028 grip->gflags |= GF_BLOCKSIZE;
1029 grip->blocksize = ull;
1030 if (grip->blocksize != ull) {
1031 xh_rangeerr(keyword, arg, len);
1032 grip->blocksize = 0;
1033 }
1034 }
1035 }
1036
1037 /* ARGSUSED */
1038 LOCAL void
get_tapesize(info,keyword,klen,arg,len)1039 get_tapesize(info, keyword, klen, arg, len)
1040 FINFO *info;
1041 char *keyword;
1042 int klen;
1043 char *arg;
1044 size_t len;
1045 {
1046 Ullong ull;
1047
1048 if (len == 0) {
1049 grip->gflags &= ~GF_TAPESIZE;
1050 grip->tapesize = 0;
1051 return;
1052 }
1053 if (get_unumber(keyword, arg, &ull, ULLONG_MAX)) {
1054 grip->gflags |= GF_TAPESIZE;
1055 grip->tapesize = ull;
1056 if (grip->tapesize != ull) {
1057 xh_rangeerr(keyword, arg, len);
1058 grip->tapesize = 0;
1059 }
1060 }
1061 }
1062