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 */
storelabel(arg)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 */
storelabelmap(arg)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 */
labelrange(startrange,endrange)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 *
strstore(arg)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 *
createlabel(volno)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
initialtape()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 */
labelest(etapes)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 */
labelcheck(tno)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 */
log_volume(tlabel)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 *
labskip(str)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 */
labfatal(fmt,a1,a2,a3,a4,a5)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