xref: /csrg-svn/local/ukc/dump/dumplab.c (revision 32046)
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