132017Spc #ifndef lint
2*32046Spc static char *sccsid = "@(#)dumplab.c 1.3 (UKC) 08/11/87";
332017Spc #endif not lint
432017Spc /*
532017Spc * This file included by Peter Collinson
632017Spc * to handle tape labelling
732017Spc * There are two dump parameters which are used to specify labels
832017Spc * -l Give the basic label format string - this may contain
932017Spc * a single %s to insert the volume number string
1032017Spc * -m Map string - used to map volume numbers into a string
1132017Spc *
1232017Spc * Routines are:
1332017Spc * storelabel(arg) - called from main() to store a label format
1432017Spc *
1532017Spc * storelabelmap(arg) - called from main() to process a map argument
1632017Spc * - which is
1732017Spc * string simple string
1832017Spc * string-string expanded by incrementing
1932017Spc * string,string,..list of the above
2032017Spc * char *
2132017Spc * createlabel(volno) - returns a label appropriate for the volume
2232017Spc *
2332017Spc * initialtape() - called to print an operator message asking for
2432017Spc * - the 1st tape
2532017Spc *
2632017Spc * labelest(etapes) - checks if there are enough tape labels
2732017Spc * - specified for a given dump
2832017Spc *
2932017Spc * labelcheck() - reads one record from tape
3032017Spc * - checks that the labels match
3132017Spc * - backspace one record back
3232017Spc * - so that multi-volume dumps work
3332017Spc *
3432017Spc * log_volume() - write a logfile entry for the volume
3532017Spc *
3632017Spc */
3732017Spc
3832017Spc #include "dump.h"
3932017Spc #include <math.h>
4032017Spc
4132017Spc
4232017Spc #define LABMAX 100 /* get space for 100 */
4332017Spc
4432017Spc char *labfmt; /* Basic tape format */
4532017Spc
4632017Spc char *labarg[LABMAX]; /* Pointer to argument list */
4732017Spc
4832017Spc int labct; /* number of entries */
4932017Spc /* if zero then no labels used */
5032017Spc
5132028Spc int userlabel; /* set if user has given a label */
5232028Spc
5332017Spc int labchk; /* check labels - set by t(est) flag */
5432017Spc
5532017Spc /*
5632017Spc * The file /etc/dumpvolumes is used to maintain a log of
5732017Spc * tapes which are/have been used for tape dumping
5832017Spc * The format is:
5932017Spc * label: date dev=<devname> level=<dump level> reel=<volume number> inode=<start inode>
6032017Spc */
6132017Spc char dumpvolumes[] = "/etc/dumpvolumes";
6232017Spc
63*32046Spc #ifdef RDUMP
64*32046Spc extern char *host;
65*32046Spc #endif RDUMP
66*32046Spc
6732017Spc /*
6832017Spc * Called from argument decoding to store the
6932017Spc * basic label format
7032017Spc * This is the parameter to the -l parameter
7132017Spc */
storelabel(arg)7232017Spc storelabel(arg)
7332017Spc char *arg;
7432017Spc {
7532028Spc labfmt = arg;
7632028Spc userlabel = 1;
7732017Spc }
7832017Spc
7932017Spc /*
8032017Spc * Store map list
8132017Spc * The map list
8232017Spc * allows a simple way to specify a range of tapes
8332017Spc * This generates a string which is inserted into the label format
8432017Spc * by use of an sprint operation
8532017Spc *
8632017Spc * The basic form here is:
8732017Spc * <string> a single string
8832017Spc * <string>,<string>,...... a list of strings
8932017Spc * <string>-<string> a range of strings
9032017Spc * where the string is `incremented'
9132017Spc * to generate a list
9232017Spc */
storelabelmap(arg)9332017Spc storelabelmap(arg)
9432017Spc char *arg;
9532017Spc {
9632017Spc register char *ss, *es;
9732017Spc register char *incbase, *incr;
9832017Spc register lastc;
9932017Spc char *labskip();
10032028Spc char *strstore();
10132017Spc
10232028Spc userlabel = 1;
10332028Spc
10432017Spc /*
10532017Spc * Parse the argument looking for a single string
10632017Spc */
10732028Spc for (ss = arg; *ss; ss = es) {
10832017Spc es = labskip(ss);
10932017Spc lastc = *es; /* save last character */
11032017Spc *es++ = '\0'; /* make the first label into a string */
11132017Spc if (labct > LABMAX)
11232017Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX);
11332028Spc if (*ss == '\0')
11432028Spc labfatal("Zero length tape label found\n");
11532028Spc labarg[labct++] = strstore(ss);
11632017Spc
11732028Spc if (lastc == 0)
11832017Spc break; /* end of list */
11932017Spc
12032028Spc if (lastc == '-') {
12132017Spc /*
12232017Spc * this gives a tape range
12332017Spc * increment the source number until it equals the final
12432017Spc * value
12532017Spc */
12632017Spc incbase = ss;
12732017Spc ss = es;
12832017Spc es = labskip(ss);
12932017Spc if (*es == '-')
13032017Spc labfatal("Range has the format <string>-<string>\n");
13132028Spc lastc = *es;
13232028Spc if (lastc)
13332028Spc *es++ = '\0';
13432017Spc /*
13532017Spc * basic test the source string length must be equal to the
13632017Spc * end string length
13732017Spc */
13832017Spc if (strlen(incbase) != strlen(ss))
13932017Spc labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
14032017Spc labelrange(incbase, ss);
14132017Spc }
14232017Spc }
14332017Spc }
14432017Spc
14532017Spc /*
14632017Spc * Expand a label range
14732017Spc */
14832017Spc /* static */
labelrange(startrange,endrange)14932017Spc labelrange(startrange, endrange)
15032017Spc char *startrange, *endrange;
15132017Spc {
15232017Spc register char *incr;
15332017Spc register int carry;
15432017Spc
15532017Spc
15632017Spc for (incr = startrange + strlen(startrange) - 1;
15732017Spc strcmp(startrange, endrange) != 0; ) {
15832017Spc /* start incrementing */
15932028Spc carry = 0;
16032028Spc do {
16132017Spc if (isdigit(*incr)) {
16232017Spc if (*incr == '9') {
16332017Spc *incr = '0';
16432017Spc carry = 1;
16532017Spc } else
16632028Spc (*incr)++;
16732017Spc } else
16832017Spc if (isupper(*incr)) {
16932017Spc if (*incr == 'Z') {
17032017Spc *incr = 'A';
17132017Spc carry = 1;
17232017Spc } else
17332028Spc (*incr)++;
17432017Spc } else
17532017Spc if (islower(*incr)) {
17632017Spc if (*incr == 'z') {
17732017Spc *incr = 'a';
17832017Spc carry = 1;
17932017Spc } else
18032028Spc (*incr)++;
18132017Spc } else
18232017Spc labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
18332017Spc if (carry) {
18432017Spc incr--;
18532017Spc if (incr < startrange)
18632017Spc labfatal("Problem with label map range spec - end of range reached\n");
18732017Spc }
18832028Spc } while (carry);
18932028Spc
19032017Spc if (labct > LABMAX)
19132017Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX);
19232028Spc labarg[labct++] = strstore(startrange);
19332017Spc
19432017Spc }
19532017Spc }
19632017Spc
19732017Spc /*
19832017Spc * Store a string using malloc
19932017Spc */
20032017Spc /* static */
20132017Spc char *
strstore(arg)20232017Spc strstore(arg)
20332017Spc char *arg;
20432017Spc {
20532017Spc register len = strlen(arg)+1;
20632017Spc register char *dest;
20732028Spc char *malloc();
20832017Spc
20932017Spc dest = malloc(len);
21032017Spc if (dest == NULL)
21132017Spc labfatal("No memory for string storage\n");
21232017Spc bcopy(arg, dest, len);
21332017Spc return(dest);
21432017Spc }
21532017Spc
21632017Spc /*
21732017Spc * Create a tape label from a volume number
21832017Spc */
21932017Spc char *
createlabel(volno)22032017Spc createlabel(volno)
22132017Spc int volno;
22232017Spc {
22332017Spc static char buf[LBLSIZE+LBLSIZE];
22432017Spc static int lastvol;
22532028Spc char volbuf[8];
22632017Spc register char *arg;
22732017Spc
22832028Spc if (userlabel == 0)
22932017Spc return ("none"); /* previous behaviour */
23032017Spc
23132028Spc if (volno == lastvol) /* cache */
23232017Spc return(buf);
23332028Spc lastvol = volno;
23432028Spc
23532028Spc if (labfmt == NULL)
23632028Spc labfmt = "%s";
23732017Spc
23832017Spc if (labct == 0)
23932017Spc { (void) sprintf(volbuf, "%d", volno);
24032017Spc arg = volbuf;
24132017Spc }
24232017Spc else
24332028Spc arg = labarg[volno-1]; /* volumes run 1-> */
24432028Spc (void) sprintf(buf, labfmt, arg);
24532028Spc buf[LBLSIZE-1] = '\0'; /* Truncate to correct size */
24632017Spc return(buf);
24732017Spc }
24832017Spc
initialtape()24932017Spc initialtape()
25032017Spc { static firstpr;
25132017Spc
25232017Spc if (labchk == 0)
25332017Spc return;
25432017Spc if (firstpr == 0)
255*32046Spc msg("Mount tape %s for reel 1 of the dump\n", createlabel(1));
25632017Spc firstpr = 1;
25732017Spc }
25832017Spc
25932017Spc /*
26032017Spc * given an estimated number of tapes, check that
26132017Spc * there are enough tapes on the label list
26232017Spc */
labelest(etapes)26332017Spc labelest(etapes)
26432017Spc double etapes;
26532017Spc { int et;
26632017Spc
26732017Spc if (labct) {
26832017Spc et = ceil(etapes);
26932017Spc if (et > labct)
27032017Spc labfatal("Only %d labe%s given, estimated need %d\n",
27132017Spc labct, labct == 1 ? "l" : "ls", et);
27232017Spc }
27332017Spc }
27432017Spc
27532017Spc /*
27632017Spc * labelcheck
27732017Spc * read a dump header and check that the tape header contains
27832017Spc * the label we expected
279*32046Spc * close the tape after use
28032017Spc */
labelcheck(tno)281*32046Spc labelcheck(tno)
28232017Spc int tno;
28332017Spc {
284*32046Spc register fd;
285*32046Spc union u_spcl uin;
28632017Spc register char *label;
28732017Spc register char *ontape = uin.s_spcl.c_label;
288*32046Spc
28932017Spc if (labchk == 0 || pipeout)
29032017Spc return(0);
29132017Spc label = createlabel(tno);
292*32046Spc
293*32046Spc #ifdef RDUMP
294*32046Spc /* doing it this way to make it easier to read */
295*32046Spc if (host) {
296*32046Spc while (rmtopen(tape, 0) < 0)
297*32046Spc if (!query("Cannot open tape. Do you want to retry the open?"))
298*32046Spc dumpabort();
299*32046Spc if (rmtread((char *)&uin, sizeof uin) != sizeof uin) {
300*32046Spc msg("Tape does not start with the correctly sized record\n");
301*32046Spc (void)rmtclose();
302*32046Spc return(-1);
303*32046Spc }
304*32046Spc if (ontape[0] == '\0' ||
305*32046Spc strcmp(ontape, "none") == 0 ||
306*32046Spc strcmp(ontape, label) == 0) {
307*32046Spc (void)rmtclose();
308*32046Spc return(0);
309*32046Spc }
310*32046Spc msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape);
311*32046Spc (void)rmtclose();
312*32046Spc return(-1);
313*32046Spc }
314*32046Spc #endif RDUMP
315*32046Spc while ((fd = open(tape, 0)) < 0)
316*32046Spc if (!query("Cannot open tape. Do you want to retry the open?"))
317*32046Spc dumpabort();
31832017Spc if (read(fd, (char *)&uin, sizeof uin) != sizeof uin) {
31932017Spc msg("Tape does not start with the correctly sized record\n");
320*32046Spc (void)close(fd);
32132017Spc return(-1);
32232017Spc }
32332017Spc if (ontape[0] == '\0' ||
32432017Spc strcmp(ontape, "none") == 0 ||
32532017Spc strcmp(ontape, label) == 0) {
326*32046Spc (void)close(fd);
32732017Spc return(0);
32832017Spc }
32932017Spc msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape);
330*32046Spc (void)close(fd);
33132017Spc return(-1);
33232017Spc }
33332017Spc
33432017Spc /*
33532017Spc * write a log entry for the volume into the log file
33632017Spc */
log_volume(tlabel)33732028Spc log_volume(tlabel)
33832028Spc char *tlabel;
33932017Spc {
34032017Spc char *ctime();
34132017Spc FILE *logfd;
34232017Spc
34332017Spc if (uflag == 0 || labchk == 0)
34432017Spc return;
34532028Spc if ((logfd = fopen(dumpvolumes, "a")) == NULL)
34632017Spc return;
34732017Spc fprintf(logfd, "%s: date=%20.20s dev=%s level=%c reel=%d ino=%d\n",
34832017Spc tlabel, ctime(&spcl.c_date)+4, disk, incno, tapeno,
34932017Spc tapeno == 1 ? ROOTINO : ino);
35032017Spc fclose(logfd);
35132017Spc }
35232017Spc
35332017Spc /*
35432017Spc * skip forward looking for valid end of label characters
35532017Spc */
35632017Spc /* static */
35732017Spc char *
labskip(str)35832017Spc labskip(str)
35932017Spc register char *str;
36032017Spc {
36132017Spc while (*str != ',' && *str != '-' && *str)
36232017Spc str++;
36332017Spc return (str);
36432017Spc }
36532017Spc
36632017Spc /*
36732017Spc * generate a fatal error message
36832017Spc */
36932017Spc /* VARARGS1 */
37032017Spc /* ARGSUSED */
labfatal(fmt,a1,a2,a3,a4,a5)37132017Spc labfatal(fmt, a1, a2, a3, a4, a5)
37232017Spc char *fmt;
37332017Spc int a1, a2, a3, a4, a5;
37432017Spc {
37532017Spc msg(fmt, a1, a2, a3, a4, a5);
37632017Spc dumpabort();
37732017Spc }
37832017Spc
379