Commit | Line | Data |
---|---|---|
da1346d6 | 1 | #ifndef lint |
224c2d4c | 2 | static char *sccsid = "@(#)dumplabel.c 1.3 (UKC) %G%"; |
da1346d6 PC |
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 | ||
43561fec | 45 | char *index(); |
da1346d6 PC |
46 | |
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 { | |
43561fec PC |
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"); | |
da1346d6 PC |
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 | |
43561fec | 87 | printlabel(); |
da1346d6 PC |
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 | */ | |
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 | */ | |
43561fec | 118 | for (ss = arg; *ss; ss = es) { |
da1346d6 PC |
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); | |
43561fec PC |
124 | if (*ss == '\0') |
125 | labfatal("Zero length label found\n"); | |
da1346d6 PC |
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; | |
43561fec PC |
143 | if (lastc) |
144 | *es++ = '\0'; | |
da1346d6 PC |
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 */ | |
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 */ | |
43561fec PC |
170 | carry = 0; |
171 | do { | |
da1346d6 PC |
172 | if (isdigit(*incr)) { |
173 | if (*incr == '9') { | |
174 | *incr = '0'; | |
175 | carry = 1; | |
176 | } else | |
43561fec | 177 | (*incr)++; |
da1346d6 PC |
178 | } else |
179 | if (isupper(*incr)) { | |
180 | if (*incr == 'Z') { | |
181 | *incr = 'A'; | |
182 | carry = 1; | |
183 | } else | |
43561fec | 184 | (*incr)++; |
da1346d6 PC |
185 | } else |
186 | if (islower(*incr)) { | |
187 | if (*incr == 'z') { | |
188 | *incr = 'a'; | |
189 | carry = 1; | |
190 | } else | |
43561fec | 191 | (*incr)++; |
da1346d6 PC |
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 | } | |
43561fec PC |
199 | } while (carry); |
200 | ||
da1346d6 PC |
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 * | |
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 * | |
231 | createlabel(volno) | |
232 | int volno; | |
233 | { | |
234 | static char buf[LBLSIZE+LBLSIZE]; | |
da1346d6 PC |
235 | char volbuf[8]; |
236 | register char *arg; | |
237 | ||
da1346d6 PC |
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 * | |
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 | */ | |
267 | dolabel(index) | |
268 | { register fd; | |
269 | ||
43561fec PC |
270 | tapecount++; |
271 | askformount(index); | |
da1346d6 PC |
272 | |
273 | while ((fd = open(tape, 2)) < 0) | |
274 | { fprintf(stderr, "Tape open error\n"); | |
275 | askformount(index); | |
276 | } | |
224c2d4c PC |
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 | } | |
da1346d6 PC |
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 | */ | |
295 | askformount(index) | |
296 | { | |
43561fec | 297 | while (query("Mount tape `%s'\nReady to go? ", createlabel(index)) != 1); |
da1346d6 PC |
298 | } |
299 | ||
300 | /* | |
301 | * ask yes/no question | |
302 | * return 1 on yes | |
303 | * 0 on no | |
304 | */ | |
305 | query(question, arg) | |
306 | char *question; | |
307 | char *arg; | |
308 | { | |
309 | char replybuffer[64]; | |
310 | int back; | |
311 | ||
43561fec | 312 | for(;;) { |
da1346d6 PC |
313 | fprintf(stdout, question, arg); |
314 | fflush(stdout); | |
43561fec PC |
315 | if (fgets(replybuffer, 63, stdin) == NULL) { |
316 | if(ferror(stdin)) { | |
317 | clearerr(stdin); | |
da1346d6 PC |
318 | continue; |
319 | } | |
320 | } | |
43561fec PC |
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"); | |
da1346d6 | 338 | } |
da1346d6 PC |
339 | } |
340 | done: | |
341 | return(back); | |
342 | } | |
343 | ||
43561fec PC |
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 | ||
da1346d6 PC |
357 | rewind(fd) |
358 | { | |
359 | struct mtop mtop; | |
43561fec PC |
360 | |
361 | if (dorew) { | |
362 | mtop.mt_op = MTOFFL; | |
da1346d6 PC |
363 | mtop.mt_count = 1; |
364 | ioctl(fd, MTIOCTOP, &mtop); | |
365 | } | |
366 | } | |
367 | ||
368 | /* | |
369 | * fatal error message routine | |
370 | */ | |
371 | labfatal(fmt, a1, a2, a3, a4, a5) | |
43561fec PC |
372 | char *fmt; |
373 | int a1, a2, a3, a4, a5; | |
374 | { | |
375 | fprintf(stderr, fmt, a1, a2, a3, a4, a5); | |
da1346d6 PC |
376 | exit(1); |
377 | } | |
378 | ||
379 | /* | |
380 | * print the label from a tape | |
381 | */ | |
382 | printlabel() | |
383 | { | |
384 | register fd; | |
385 | ||
43561fec PC |
386 | if ((fd = open(tape, 2)) < 0) { |
387 | perror("Tape open error"); | |
da1346d6 PC |
388 | exit(1); |
389 | } | |
43561fec PC |
390 | if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0) { |
391 | perror("Tape read"); | |
da1346d6 PC |
392 | exit(1); |
393 | } | |
224c2d4c PC |
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); | |
da1346d6 PC |
403 | close(fd); |
404 | } |