xref: /original-bsd/local/ukc/dump/dumplab.c (revision 60c3b96a)
1 #ifndef lint
2 static char *sccsid = "@(#)dumplab.c	1.3 (UKC) 08/11/87";
3 #endif not lint
4 /*
5  *	This file included by Peter Collinson
6  *	to handle tape labelling
7  *	There are two dump parameters which are used to specify labels
8  *	-l	Give the basic label format string - this may contain
9  *		a single %s to insert the volume number string
10  *	-m	Map string - used to map volume numbers into a string
11  *
12  *	Routines are:
13  *	storelabel(arg)		- called from main() to store a label format
14  *
15  *	storelabelmap(arg)	- called from main() to process a map argument
16  *				- which is
17  *					string		simple string
18  *					string-string	expanded by incrementing
19  *					string,string,..list of the above
20  *	char *
21  *	createlabel(volno)	- returns a label appropriate for the volume
22  *
23  *	initialtape()		- called to print an operator message asking for
24  *				- the 1st tape
25  *
26  *	labelest(etapes)	- checks if there are enough tape labels
27  *				- specified for a given dump
28  *
29  *	labelcheck()		- reads one record from tape
30  *				- checks that the labels match
31  *				- backspace one record back
32  *				- so that multi-volume dumps work
33  *
34  *	log_volume()		- write a logfile entry for the volume
35  *
36  */
37 
38 #include "dump.h"
39 #include <math.h>
40 
41 
42 #define	LABMAX	100		/* get space for 100 */
43 
44 char	*labfmt;		/* Basic tape format */
45 
46 char	*labarg[LABMAX];	/* Pointer to argument list */
47 
48 int	labct;			/* number of entries */
49 				/* if zero then no labels used */
50 
51 int	userlabel;		/* set if user has given a label */
52 
53 int	labchk;			/* check labels - set by t(est) flag */
54 
55 /*
56  *	The file /etc/dumpvolumes is used to maintain a log of
57  *	tapes which are/have been used for tape dumping
58  *	The format is:
59  *	label: date dev=<devname> level=<dump level> reel=<volume number> inode=<start inode>
60  */
61 char dumpvolumes[] = "/etc/dumpvolumes";
62 
63 #ifdef RDUMP
64 extern char *host;
65 #endif RDUMP
66 
67 /*
68  *	Called from argument decoding to store the
69  *	basic label format
70  *	This is the parameter to the -l parameter
71  */
72 storelabel(arg)
73 	char *arg;
74 {
75 	labfmt = arg;
76 	userlabel = 1;
77 }
78 
79 /*
80  *	Store map list
81  *	The map list
82  *	allows a simple way to specify a range of tapes
83  *	This generates a string which is inserted into the label format
84  *	by use of an sprint operation
85  *
86  *	The basic form here is:
87  *	<string>			a single string
88  *	<string>,<string>,......	a list of strings
89  *	<string>-<string>		a range of strings
90  *					where the string is `incremented'
91  *					to generate a list
92  */
93 storelabelmap(arg)
94 	char *arg;
95 {
96 	register char *ss, *es;
97 	register char *incbase, *incr;
98 	register lastc;
99 	char *labskip();
100 	char *strstore();
101 
102 	userlabel = 1;
103 
104 	/*
105 	 *	Parse the argument looking for a single string
106 	 */
107 	for (ss = arg; *ss; ss = es) {
108 		es = labskip(ss);
109 		lastc = *es;	/* save last character */
110 		*es++ = '\0';	/* make the first label into a string */
111 		if (labct > LABMAX)
112 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
113 		if (*ss == '\0')
114 			labfatal("Zero length tape label found\n");
115 		labarg[labct++] = strstore(ss);
116 
117 		if (lastc == 0)
118 			break;		/* end of list */
119 
120 		if (lastc == '-') {
121 			/*
122 			 * this gives a tape range
123 			 * increment the source number until it equals the final
124 			 * value
125 			 */
126 			incbase = ss;
127 			ss = es;
128 			es = labskip(ss);
129 			if (*es == '-')
130 				labfatal("Range has the format <string>-<string>\n");
131 			lastc = *es;
132 			if (lastc)
133 				*es++ = '\0';
134 			/*
135 			 * basic test the source string length must be equal to the
136 			 * end string length
137 			 */
138 			if (strlen(incbase) != strlen(ss))
139 				labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
140 			labelrange(incbase, ss);
141 		}
142 	}
143 }
144 
145 /*
146  *	Expand a label range
147  */
148 /* static */
149 labelrange(startrange, endrange)
150 	char *startrange, *endrange;
151 {
152 	register char *incr;
153 	register int carry;
154 
155 
156 	for (incr = startrange + strlen(startrange) - 1;
157 			strcmp(startrange, endrange) != 0; ) {
158 		/* start incrementing */
159 		carry = 0;
160 		do {
161 			if (isdigit(*incr)) {
162 				if (*incr == '9') {
163 					*incr = '0';
164 					carry = 1;
165 				} else
166 					(*incr)++;
167 			} else
168 			if (isupper(*incr)) {
169 				if (*incr == 'Z') {
170 					*incr = 'A';
171 					carry = 1;
172 				} else
173 					(*incr)++;
174 			} else
175 			if (islower(*incr)) {
176 				if (*incr == 'z') {
177 					*incr = 'a';
178 					carry = 1;
179 				} else
180 					(*incr)++;
181 			} else
182 				labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
183 			if (carry) {
184 				incr--;
185 				if (incr < startrange)
186 					labfatal("Problem with label map range spec - end of range reached\n");
187 			}
188 		} while (carry);
189 
190 		if (labct > LABMAX)
191 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
192 		labarg[labct++] = strstore(startrange);
193 
194 	}
195 }
196 
197 /*
198  *	Store a string using malloc
199  */
200 /* static */
201 char *
202 strstore(arg)
203 	char *arg;
204 {
205 	register len = strlen(arg)+1;
206 	register char *dest;
207 	char *malloc();
208 
209 	dest = malloc(len);
210 	if (dest == NULL)
211 		labfatal("No memory for string storage\n");
212 	bcopy(arg, dest, len);
213 	return(dest);
214 }
215 
216 /*
217  *	Create a tape label from a volume number
218  */
219 char *
220 createlabel(volno)
221 	int volno;
222 {
223 	static char buf[LBLSIZE+LBLSIZE];
224 	static int lastvol;
225 	char volbuf[8];
226 	register char *arg;
227 
228 	if (userlabel == 0)
229 		return ("none");		/* previous behaviour */
230 
231 	if (volno == lastvol)			/* cache */
232 		return(buf);
233 	lastvol = volno;
234 
235 	if (labfmt == NULL)
236 		labfmt = "%s";
237 
238 	if (labct == 0)
239 	{	(void) sprintf(volbuf, "%d", volno);
240 		arg = volbuf;
241 	}
242 	else
243 		arg = labarg[volno-1];		/* volumes run 1-> */
244 	(void) sprintf(buf, labfmt, arg);
245 	buf[LBLSIZE-1] = '\0';			/* Truncate to correct size */
246 	return(buf);
247 }
248 
249 initialtape()
250 {	static firstpr;
251 
252 	if (labchk == 0)
253 		return;
254 	if (firstpr == 0)
255 		msg("Mount tape %s for reel 1 of the dump\n", createlabel(1));
256 	firstpr = 1;
257 }
258 
259 /*
260  *	given an estimated number of tapes, check that
261  *	there are enough tapes on the label list
262  */
263 labelest(etapes)
264 	double etapes;
265 {	int et;
266 
267 	if (labct) {
268 		et = ceil(etapes);
269 		if (et > labct)
270 			labfatal("Only %d labe%s given, estimated need %d\n",
271 				labct, labct == 1 ? "l" : "ls", et);
272 	}
273 }
274 
275 /*
276  *	labelcheck
277  *	read a dump header and check that the tape header contains
278  *	the label we expected
279  *	close the tape after use
280  */
281 labelcheck(tno)
282 	int tno;
283 {
284 	register fd;
285 	union u_spcl uin;
286 	register char *label;
287 	register char *ontape = uin.s_spcl.c_label;
288 
289 	if (labchk == 0 || pipeout)
290 		return(0);
291 	label = createlabel(tno);
292 
293 #ifdef RDUMP
294 	/* doing it this way to make it easier to read */
295 	if (host) {
296 		while (rmtopen(tape, 0) < 0)
297 			if (!query("Cannot open tape. Do you want to retry the open?"))
298 				dumpabort();
299 		if (rmtread((char *)&uin, sizeof uin) != sizeof uin) {
300 			msg("Tape does not start with the correctly sized record\n");
301 			(void)rmtclose();
302 			return(-1);
303 		}
304 		if (ontape[0] == '\0' ||
305 		    strcmp(ontape, "none") == 0 ||
306 		    strcmp(ontape, label) == 0) {
307 			(void)rmtclose();
308 			return(0);
309 		}
310 		msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape);
311 		(void)rmtclose();
312 		return(-1);
313 	}
314 #endif RDUMP
315 	while ((fd = open(tape, 0)) < 0)
316 		if (!query("Cannot open tape. Do you want to retry the open?"))
317 			dumpabort();
318 	if (read(fd, (char *)&uin, sizeof uin) != sizeof uin) {
319 		msg("Tape does not start with the correctly sized record\n");
320 		(void)close(fd);
321 		return(-1);
322 	}
323 	if (ontape[0] == '\0' ||
324 	    strcmp(ontape, "none") == 0 ||
325 	    strcmp(ontape, label) == 0) {
326 		(void)close(fd);
327 		return(0);
328 	}
329 	msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape);
330 	(void)close(fd);
331 	return(-1);
332 }
333 
334 /*
335  *	write a log entry for the volume into the log file
336  */
337 log_volume(tlabel)
338 	char *tlabel;
339 {
340 	char *ctime();
341 	FILE *logfd;
342 
343 	if (uflag == 0 || labchk == 0)
344 		return;
345 	if ((logfd = fopen(dumpvolumes, "a")) == NULL)
346 		return;
347 	fprintf(logfd, "%s: date=%20.20s dev=%s level=%c reel=%d ino=%d\n",
348 			tlabel, ctime(&spcl.c_date)+4, disk, incno, tapeno,
349 			tapeno == 1 ? ROOTINO : ino);
350 	fclose(logfd);
351 }
352 
353 /*
354  *	skip forward looking for valid end of label characters
355  */
356 /* static */
357 char *
358 labskip(str)
359 	register char *str;
360 {
361 	while (*str != ',' && *str != '-' && *str)
362 		str++;
363 	return (str);
364 }
365 
366 /*
367  *	generate a fatal error message
368  */
369 	/* VARARGS1 */
370 	/* ARGSUSED */
371 labfatal(fmt, a1, a2, a3, a4, a5)
372 	char	*fmt;
373 	int	a1, a2, a3, a4, a5;
374 {
375 	msg(fmt, a1, a2, a3, a4, a5);
376 	dumpabort();
377 }
378 
379