1 #ifndef lint
2 static char *sccsid = "@(#)dumplabel.c 1.3 (UKC) 08/11/87";
3 #endif not lint
4 /***
5
6 * program name:
7 dumplabel.c
8 * function:
9 prints the label from a header
10 writes a dummy dump header at the start of a tape
11 Doesn't do any checksum
12 * switches:
13 -f <tapename>
14 -r rewind/offline each tape
15 -l label format
16 followed by list of tape labels in the same format at given to the
17 locally modified dump program
18 if no tape labels are given print the details on the start of a tape
19 * libraries used:
20 standard
21 * compile time parameters:
22 cc -o dumplabel dumplabel.c
23 * history:
24 Written August 1987 Peter Collinson UKC
25
26 ***/
27 #include "dump.h"
28 #include <sys/ioctl.h>
29 #include <sys/mtio.h>
30
31 #define LABMAX 100 /* get space for 100 */
32
33 char *labarg[LABMAX]; /* vector of map entries */
34
35 char *labfmt; /* format for tape label */
36
37 int labct; /* number of entries */
38 /* if zero then no labels used */
39
40 char *tape = "/dev/rmt8";
41
42 int dorew; /* set if rewind offline on exit */
43 int tapecount; /* number of tapes dealt with */
44
45 char *index();
46
main(argc,argv)47 main(argc, argv)
48 char **argv;
49 { register i;
50 register char *p;
51 while (--argc) {
52 argv++;
53 if (**argv == '-') {
54 for (p = *argv; *p; p++)
55 switch (*p) {
56
57 case 'f':
58 if (--argc > 0) {
59 argv++;
60 tape = *argv;
61 }
62 break;
63 case 'r':
64 dorew++; /* no rewind/offline */
65 break;
66 case 'l':
67 if (--argc > 0) {
68 argv++;
69 labfmt = *argv;
70 }
71 }
72 } else {
73 storelabelmap(*argv);
74 if (labfmt && labct)
75 if (index(labfmt, '%') == NULL)
76 fprintf(stderr, "Warning - no format specifier (%%s) found in -l argument\n");
77 for (i = 1; i <= labct; i++)
78 dolabel(i);
79 labct = 0;
80 }
81 }
82 if (tapecount == 0) {
83 if (labfmt) {
84 labct = 0;
85 dolabel(1); /* pretend a volume number of 1 */
86 } else
87 printlabel();
88 }
89 exit(0);
90 }
91
92 /*
93 * Store map list
94 * The map list
95 * allows a simple way to specify a range of tapes
96 * This generates a string which is inserted into the label format
97 * by use of an sprint operation
98 *
99 * The basic form here is:
100 * <string> a single string
101 * <string>,<string>,...... a list of strings
102 * <string>-<string> a range of strings
103 * where the string is `incremented'
104 * to generate a list
105 */
storelabelmap(arg)106 storelabelmap(arg)
107 char *arg;
108 {
109 register char *ss, *es;
110 register char *incbase, *incr;
111 register lastc;
112 char *labskip();
113 char *strstore();
114
115 /*
116 * Parse the argument looking for a single string
117 */
118 for (ss = arg; *ss; ss = es) {
119 es = labskip(ss);
120 lastc = *es; /* save last character */
121 *es++ = '\0'; /* make the first label into a string */
122 if (labct > LABMAX)
123 labfatal("Too many (> %d) tape labels specified\n", LABMAX);
124 if (*ss == '\0')
125 labfatal("Zero length label found\n");
126 labarg[labct++] = strstore(ss);
127
128 if (lastc == 0)
129 break; /* end of list */
130
131 if (lastc == '-') {
132 /*
133 * this gives a tape range
134 * increment the source number until it equals the final
135 * value
136 */
137 incbase = ss;
138 ss = es;
139 es = labskip(ss);
140 if (*es == '-')
141 labfatal("Range has the format <string>-<string>\n");
142 lastc = *es;
143 if (lastc)
144 *es++ = '\0';
145 /*
146 * basic test the source string length must be equal to the
147 * end string length
148 */
149 if (strlen(incbase) != strlen(ss))
150 labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
151 labelrange(incbase, ss);
152 }
153 }
154 }
155
156 /*
157 * Expand a label range
158 */
159 /* static */
labelrange(startrange,endrange)160 labelrange(startrange, endrange)
161 char *startrange, *endrange;
162 {
163 register char *incr;
164 register int carry;
165
166
167 for (incr = startrange + strlen(startrange) - 1;
168 strcmp(startrange, endrange) != 0; ) {
169 /* start incrementing */
170 carry = 0;
171 do {
172 if (isdigit(*incr)) {
173 if (*incr == '9') {
174 *incr = '0';
175 carry = 1;
176 } else
177 (*incr)++;
178 } else
179 if (isupper(*incr)) {
180 if (*incr == 'Z') {
181 *incr = 'A';
182 carry = 1;
183 } else
184 (*incr)++;
185 } else
186 if (islower(*incr)) {
187 if (*incr == 'z') {
188 *incr = 'a';
189 carry = 1;
190 } else
191 (*incr)++;
192 } else
193 labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
194 if (carry) {
195 incr--;
196 if (incr < startrange)
197 labfatal("Problem with label map range spec - end of range reached\n");
198 }
199 } while (carry);
200
201 if (labct > LABMAX)
202 labfatal("Too many (> %d) tape labels specified\n", LABMAX);
203 labarg[labct++] = strstore(startrange);
204
205 }
206 }
207
208 /*
209 * Store a string using malloc
210 */
211 /* static */
212 char *
strstore(arg)213 strstore(arg)
214 char *arg;
215 {
216 register len = strlen(arg)+1;
217 register char *dest;
218 char *malloc();
219
220 dest = malloc(len);
221 if (dest == NULL)
222 labfatal("No memory for string storage\n");
223 bcopy(arg, dest, len);
224 return(dest);
225 }
226
227 /*
228 * Create a tape label from a volume number
229 */
230 char *
createlabel(volno)231 createlabel(volno)
232 int volno;
233 {
234 static char buf[LBLSIZE+LBLSIZE];
235 char volbuf[8];
236 register char *arg;
237
238
239 if (labfmt == NULL)
240 labfmt = "%s";
241
242 if (labct == 0)
243 { (void) sprintf(volbuf, "%d", volno);
244 arg = volbuf;
245 }
246 else
247 arg = labarg[volno-1]; /* volumes run 1-> */
248 (void) sprintf(buf, labfmt, arg);
249 buf[LBLSIZE-1] = '\0'; /* Truncate to correct size */
250 return(buf);
251 }
252
253 /*
254 * skip forward looking for valid end of label characters
255 */
256 char *
labskip(str)257 labskip(str)
258 register char *str;
259 { while (*str != ',' && *str != '-' && *str)
260 str++;
261 return (str);
262 }
263
264 /*
265 * do the actual labelling
266 */
dolabel(index)267 dolabel(index)
268 { register fd;
269
270 tapecount++;
271 askformount(index);
272
273 while ((fd = open(tape, 2)) < 0)
274 { fprintf(stderr, "Tape open error\n");
275 askformount(index);
276 }
277 if (spcl.c_host[0] == '\0')
278 { gethostname(spcl.c_host, NAMELEN);
279 spcl.c_level = 0;
280 strcpy(spcl.c_filesys, "Tape has only been labelled");
281 strcpy(spcl.c_dev, "???????????");
282 }
283 strcpy(spcl.c_label, createlabel(index));
284 if (write(fd, (char *)&u_spcl, sizeof (u_spcl)) != sizeof (u_spcl))
285 { perror("Tape write error");
286 exit(1);
287 }
288 rewind(fd);
289 close(fd);
290 }
291
292 /*
293 * ask for a tape to be mounted
294 */
askformount(index)295 askformount(index)
296 {
297 while (query("Mount tape `%s'\nReady to go? ", createlabel(index)) != 1);
298 }
299
300 /*
301 * ask yes/no question
302 * return 1 on yes
303 * 0 on no
304 */
query(question,arg)305 query(question, arg)
306 char *question;
307 char *arg;
308 {
309 char replybuffer[64];
310 int back;
311
312 for(;;) {
313 fprintf(stdout, question, arg);
314 fflush(stdout);
315 if (fgets(replybuffer, 63, stdin) == NULL) {
316 if(ferror(stdin)) {
317 clearerr(stdin);
318 continue;
319 }
320 }
321 else {
322 qclean(replybuffer);
323 if (strcmp(replybuffer, "yes") == 0 ||
324 strcmp(replybuffer, "y") == 0) {
325 back = 1;
326 goto done;
327 }
328 else
329 if (strcmp(replybuffer, "no") == 0 ||
330 strcmp(replybuffer, "n") == 0) {
331 if (query("Abort? "))
332 labfatal("Aborting\n");
333 back = 0;
334 goto done;
335 }
336 else
337 fprintf(stderr, "\"yes\" or \"no\" ONLY!\n");
338 }
339 }
340 done:
341 return(back);
342 }
343
qclean(ptr)344 qclean(ptr)
345 register char *ptr;
346 {
347 for (;*ptr; ptr++) {
348 if (isupper(*ptr))
349 *ptr = tolower(*ptr);
350 if (*ptr == '\n') {
351 *ptr = '\0';
352 break;
353 }
354 }
355 }
356
rewind(fd)357 rewind(fd)
358 {
359 struct mtop mtop;
360
361 if (dorew) {
362 mtop.mt_op = MTOFFL;
363 mtop.mt_count = 1;
364 ioctl(fd, MTIOCTOP, &mtop);
365 }
366 }
367
368 /*
369 * fatal error message routine
370 */
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 fprintf(stderr, fmt, a1, a2, a3, a4, a5);
376 exit(1);
377 }
378
379 /*
380 * print the label from a tape
381 */
printlabel()382 printlabel()
383 {
384 register fd;
385
386 if ((fd = open(tape, 2)) < 0) {
387 perror("Tape open error");
388 exit(1);
389 }
390 if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0) {
391 perror("Tape read");
392 exit(1);
393 }
394 printf("Dump date: %s", ctime(&spcl.c_date));
395 printf("Dumped from: %s", ctime(&spcl.c_ddate));
396 if (spcl.c_host[0] == '\0')
397 return;
398 printf("Level %d dump of %s on %s:%s\n",
399 spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
400 printf("Label: %s\n", spcl.c_label);
401 printf("Volume %d of the dump, starting at inode %d\n",
402 spcl.c_volume, spcl.c_inumber);
403 close(fd);
404 }
405