xref: /csrg-svn/local/ukc/dump/dumplab.c (revision 32028)
132017Spc #ifndef lint
2*32028Spc static char *sccsid = "@(#)dumplab.c	1.2 (UKC) 08/08/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 
51*32028Spc int	userlabel;		/* set if user has given a label */
52*32028Spc 
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 
6332017Spc /*
6432017Spc  *	Called from argument decoding to store the
6532017Spc  *	basic label format
6632017Spc  *	This is the parameter to the -l parameter
6732017Spc  */
6832017Spc storelabel(arg)
6932017Spc 	char *arg;
7032017Spc {
71*32028Spc 	labfmt = arg;
72*32028Spc 	userlabel = 1;
7332017Spc }
7432017Spc 
7532017Spc /*
7632017Spc  *	Store map list
7732017Spc  *	The map list
7832017Spc  *	allows a simple way to specify a range of tapes
7932017Spc  *	This generates a string which is inserted into the label format
8032017Spc  *	by use of an sprint operation
8132017Spc  *
8232017Spc  *	The basic form here is:
8332017Spc  *	<string>			a single string
8432017Spc  *	<string>,<string>,......	a list of strings
8532017Spc  *	<string>-<string>		a range of strings
8632017Spc  *					where the string is `incremented'
8732017Spc  *					to generate a list
8832017Spc  */
8932017Spc storelabelmap(arg)
9032017Spc 	char *arg;
9132017Spc {
9232017Spc 	register char *ss, *es;
9332017Spc 	register char *incbase, *incr;
9432017Spc 	register lastc;
9532017Spc 	char *labskip();
96*32028Spc 	char *strstore();
9732017Spc 
98*32028Spc 	userlabel = 1;
99*32028Spc 
10032017Spc 	/*
10132017Spc 	 *	Parse the argument looking for a single string
10232017Spc 	 */
103*32028Spc 	for (ss = arg; *ss; ss = es) {
10432017Spc 		es = labskip(ss);
10532017Spc 		lastc = *es;	/* save last character */
10632017Spc 		*es++ = '\0';	/* make the first label into a string */
10732017Spc 		if (labct > LABMAX)
10832017Spc 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
109*32028Spc 		if (*ss == '\0')
110*32028Spc 			labfatal("Zero length tape label found\n");
111*32028Spc 		labarg[labct++] = strstore(ss);
11232017Spc 
113*32028Spc 		if (lastc == 0)
11432017Spc 			break;		/* end of list */
11532017Spc 
116*32028Spc 		if (lastc == '-') {
11732017Spc 			/*
11832017Spc 			 * this gives a tape range
11932017Spc 			 * increment the source number until it equals the final
12032017Spc 			 * value
12132017Spc 			 */
12232017Spc 			incbase = ss;
12332017Spc 			ss = es;
12432017Spc 			es = labskip(ss);
12532017Spc 			if (*es == '-')
12632017Spc 				labfatal("Range has the format <string>-<string>\n");
127*32028Spc 			lastc = *es;
128*32028Spc 			if (lastc)
129*32028Spc 				*es++ = '\0';
13032017Spc 			/*
13132017Spc 			 * basic test the source string length must be equal to the
13232017Spc 			 * end string length
13332017Spc 			 */
13432017Spc 			if (strlen(incbase) != strlen(ss))
13532017Spc 				labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
13632017Spc 			labelrange(incbase, ss);
13732017Spc 		}
13832017Spc 	}
13932017Spc }
14032017Spc 
14132017Spc /*
14232017Spc  *	Expand a label range
14332017Spc  */
14432017Spc /* static */
14532017Spc labelrange(startrange, endrange)
14632017Spc 	char *startrange, *endrange;
14732017Spc {
14832017Spc 	register char *incr;
14932017Spc 	register int carry;
15032017Spc 
15132017Spc 
15232017Spc 	for (incr = startrange + strlen(startrange) - 1;
15332017Spc 			strcmp(startrange, endrange) != 0; ) {
15432017Spc 		/* start incrementing */
155*32028Spc 		carry = 0;
156*32028Spc 		do {
15732017Spc 			if (isdigit(*incr)) {
15832017Spc 				if (*incr == '9') {
15932017Spc 					*incr = '0';
16032017Spc 					carry = 1;
16132017Spc 				} else
162*32028Spc 					(*incr)++;
16332017Spc 			} else
16432017Spc 			if (isupper(*incr)) {
16532017Spc 				if (*incr == 'Z') {
16632017Spc 					*incr = 'A';
16732017Spc 					carry = 1;
16832017Spc 				} else
169*32028Spc 					(*incr)++;
17032017Spc 			} else
17132017Spc 			if (islower(*incr)) {
17232017Spc 				if (*incr == 'z') {
17332017Spc 					*incr = 'a';
17432017Spc 					carry = 1;
17532017Spc 				} else
176*32028Spc 					(*incr)++;
17732017Spc 			} else
17832017Spc 				labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
17932017Spc 			if (carry) {
18032017Spc 				incr--;
18132017Spc 				if (incr < startrange)
18232017Spc 					labfatal("Problem with label map range spec - end of range reached\n");
18332017Spc 			}
184*32028Spc 		} while (carry);
185*32028Spc 
18632017Spc 		if (labct > LABMAX)
18732017Spc 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
188*32028Spc 		labarg[labct++] = strstore(startrange);
18932017Spc 
19032017Spc 	}
19132017Spc }
19232017Spc 
19332017Spc /*
19432017Spc  *	Store a string using malloc
19532017Spc  */
19632017Spc /* static */
19732017Spc char *
19832017Spc strstore(arg)
19932017Spc 	char *arg;
20032017Spc {
20132017Spc 	register len = strlen(arg)+1;
20232017Spc 	register char *dest;
203*32028Spc 	char *malloc();
20432017Spc 
20532017Spc 	dest = malloc(len);
20632017Spc 	if (dest == NULL)
20732017Spc 		labfatal("No memory for string storage\n");
20832017Spc 	bcopy(arg, dest, len);
20932017Spc 	return(dest);
21032017Spc }
21132017Spc 
21232017Spc /*
21332017Spc  *	Create a tape label from a volume number
21432017Spc  */
21532017Spc char *
21632017Spc createlabel(volno)
21732017Spc 	int volno;
21832017Spc {
21932017Spc 	static char buf[LBLSIZE+LBLSIZE];
22032017Spc 	static int lastvol;
221*32028Spc 	char volbuf[8];
22232017Spc 	register char *arg;
22332017Spc 
224*32028Spc 	if (userlabel == 0)
22532017Spc 		return ("none");		/* previous behaviour */
22632017Spc 
227*32028Spc 	if (volno == lastvol)			/* cache */
22832017Spc 		return(buf);
229*32028Spc 	lastvol = volno;
230*32028Spc 
231*32028Spc 	if (labfmt == NULL)
232*32028Spc 		labfmt = "%s";
23332017Spc 
23432017Spc 	if (labct == 0)
23532017Spc 	{	(void) sprintf(volbuf, "%d", volno);
23632017Spc 		arg = volbuf;
23732017Spc 	}
23832017Spc 	else
239*32028Spc 		arg = labarg[volno-1];		/* volumes run 1-> */
240*32028Spc 	(void) sprintf(buf, labfmt, arg);
241*32028Spc 	buf[LBLSIZE-1] = '\0';			/* Truncate to correct size */
24232017Spc 	return(buf);
24332017Spc }
24432017Spc 
24532017Spc initialtape()
24632017Spc {	static firstpr;
24732017Spc 
24832017Spc 	if (labchk == 0)
24932017Spc 		return;
25032017Spc 	if (firstpr == 0)
25132017Spc 		msg("Mount tape %s for reel 1 of the dump\n", createlabel(0));
25232017Spc 	firstpr = 1;
25332017Spc }
25432017Spc 
25532017Spc /*
25632017Spc  *	given an estimated number of tapes, check that
25732017Spc  *	there are enough tapes on the label list
25832017Spc  */
25932017Spc labelest(etapes)
26032017Spc 	double etapes;
26132017Spc {	int et;
26232017Spc 
26332017Spc 	if (labct) {
26432017Spc 		et = ceil(etapes);
26532017Spc 		if (et > labct)
26632017Spc 			labfatal("Only %d labe%s given, estimated need %d\n",
26732017Spc 				labct, labct == 1 ? "l" : "ls", et);
26832017Spc 	}
26932017Spc }
27032017Spc 
27132017Spc /*
27232017Spc  *	labelcheck
27332017Spc  *	read a dump header and check that the tape header contains
27432017Spc  *	the label we expected
27532017Spc  *	close the fd on error to allow upper levels to loop
27632017Spc  */
27732017Spc labelcheck(fd, tno)
27832017Spc 	int fd;
27932017Spc 	int tno;
28032017Spc {
28132017Spc 	union u_spcl uin;	/* lots on the stack but that should be OK */
28232017Spc 	register char *label;
28332017Spc 	register char *ontape = uin.s_spcl.c_label;
28432017Spc 
28532017Spc 	if (labchk == 0 || pipeout)
28632017Spc 		return(0);
28732017Spc 	label = createlabel(tno);
28832017Spc 	if (read(fd, (char *)&uin, sizeof uin) != sizeof uin) {
28932017Spc 		msg("Tape does not start with the correctly sized record\n");
29032017Spc 		close(fd);
29132017Spc 		return(-1);
29232017Spc 	}
29332017Spc 	if (ontape[0] == '\0' ||
29432017Spc 	    strcmp(ontape, "none") == 0 ||
29532017Spc 	    strcmp(ontape, label) == 0) {
29632017Spc 		/* skip back one record */
297*32028Spc 		if (backone(fd) < 0)
29832017Spc 			labfatal("Label check cannot backspace tape\n");
29932017Spc 		return(0);
30032017Spc 	}
30132017Spc 	msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape);
30232017Spc 	close(fd);
30332017Spc 	return(-1);
30432017Spc }
30532017Spc 
30632017Spc /*
30732017Spc  *	write a log entry for the volume into the log file
30832017Spc  */
309*32028Spc log_volume(tlabel)
310*32028Spc 	char *tlabel;
31132017Spc {
31232017Spc 	char *ctime();
31332017Spc 	FILE *logfd;
31432017Spc 
31532017Spc 	if (uflag == 0 || labchk == 0)
31632017Spc 		return;
317*32028Spc 	if ((logfd = fopen(dumpvolumes, "a")) == NULL)
31832017Spc 		return;
31932017Spc 	fprintf(logfd, "%s: date=%20.20s dev=%s level=%c reel=%d ino=%d\n",
32032017Spc 			tlabel, ctime(&spcl.c_date)+4, disk, incno, tapeno,
32132017Spc 			tapeno == 1 ? ROOTINO : ino);
32232017Spc 	fclose(logfd);
32332017Spc }
32432017Spc 
32532017Spc /*
32632017Spc  *	skip forward looking for valid end of label characters
32732017Spc  */
32832017Spc /* static */
32932017Spc char *
33032017Spc labskip(str)
33132017Spc 	register char *str;
33232017Spc {
33332017Spc 	while (*str != ',' && *str != '-' && *str)
33432017Spc 		str++;
33532017Spc 	return (str);
33632017Spc }
33732017Spc 
33832017Spc /*
33932017Spc  *	generate a fatal error message
34032017Spc  */
34132017Spc 	/* VARARGS1 */
34232017Spc 	/* ARGSUSED */
34332017Spc labfatal(fmt, a1, a2, a3, a4, a5)
34432017Spc 	char	*fmt;
34532017Spc 	int	a1, a2, a3, a4, a5;
34632017Spc {
34732017Spc 	msg(fmt, a1, a2, a3, a4, a5);
34832017Spc 	dumpabort();
34932017Spc }
35032017Spc 
351