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 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 */ 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 */ 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 * 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]; 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 * 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 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 */ 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 */ 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 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 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 */ 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 */ 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