132017Spc #ifndef lint 2*32028Spc static char *sccsid = "@(#)dumplab.c 1.2 (UKC) 08/08/87"; 332017Spc #endif not lint 432017Spc /* 532017Spc * This file included by Peter Collinson 632017Spc * to handle tape labelling 732017Spc * There are two dump parameters which are used to specify labels 832017Spc * -l Give the basic label format string - this may contain 932017Spc * a single %s to insert the volume number string 1032017Spc * -m Map string - used to map volume numbers into a string 1132017Spc * 1232017Spc * Routines are: 1332017Spc * storelabel(arg) - called from main() to store a label format 1432017Spc * 1532017Spc * storelabelmap(arg) - called from main() to process a map argument 1632017Spc * - which is 1732017Spc * string simple string 1832017Spc * string-string expanded by incrementing 1932017Spc * string,string,..list of the above 2032017Spc * char * 2132017Spc * createlabel(volno) - returns a label appropriate for the volume 2232017Spc * 2332017Spc * initialtape() - called to print an operator message asking for 2432017Spc * - the 1st tape 2532017Spc * 2632017Spc * labelest(etapes) - checks if there are enough tape labels 2732017Spc * - specified for a given dump 2832017Spc * 2932017Spc * labelcheck() - reads one record from tape 3032017Spc * - checks that the labels match 3132017Spc * - backspace one record back 3232017Spc * - so that multi-volume dumps work 3332017Spc * 3432017Spc * log_volume() - write a logfile entry for the volume 3532017Spc * 3632017Spc */ 3732017Spc 3832017Spc #include "dump.h" 3932017Spc #include <math.h> 4032017Spc 4132017Spc 4232017Spc #define LABMAX 100 /* get space for 100 */ 4332017Spc 4432017Spc char *labfmt; /* Basic tape format */ 4532017Spc 4632017Spc char *labarg[LABMAX]; /* Pointer to argument list */ 4732017Spc 4832017Spc int labct; /* number of entries */ 4932017Spc /* if zero then no labels used */ 5032017Spc 51*32028Spc int userlabel; /* set if user has given a label */ 52*32028Spc 5332017Spc int labchk; /* check labels - set by t(est) flag */ 5432017Spc 5532017Spc /* 5632017Spc * The file /etc/dumpvolumes is used to maintain a log of 5732017Spc * tapes which are/have been used for tape dumping 5832017Spc * The format is: 5932017Spc * label: date dev=<devname> level=<dump level> reel=<volume number> inode=<start inode> 6032017Spc */ 6132017Spc char dumpvolumes[] = "/etc/dumpvolumes"; 6232017Spc 6332017Spc /* 6432017Spc * Called from argument decoding to store the 6532017Spc * basic label format 6632017Spc * This is the parameter to the -l parameter 6732017Spc */ 6832017Spc storelabel(arg) 6932017Spc char *arg; 7032017Spc { 71*32028Spc labfmt = arg; 72*32028Spc userlabel = 1; 7332017Spc } 7432017Spc 7532017Spc /* 7632017Spc * Store map list 7732017Spc * The map list 7832017Spc * allows a simple way to specify a range of tapes 7932017Spc * This generates a string which is inserted into the label format 8032017Spc * by use of an sprint operation 8132017Spc * 8232017Spc * The basic form here is: 8332017Spc * <string> a single string 8432017Spc * <string>,<string>,...... a list of strings 8532017Spc * <string>-<string> a range of strings 8632017Spc * where the string is `incremented' 8732017Spc * to generate a list 8832017Spc */ 8932017Spc storelabelmap(arg) 9032017Spc char *arg; 9132017Spc { 9232017Spc register char *ss, *es; 9332017Spc register char *incbase, *incr; 9432017Spc register lastc; 9532017Spc char *labskip(); 96*32028Spc char *strstore(); 9732017Spc 98*32028Spc userlabel = 1; 99*32028Spc 10032017Spc /* 10132017Spc * Parse the argument looking for a single string 10232017Spc */ 103*32028Spc for (ss = arg; *ss; ss = es) { 10432017Spc es = labskip(ss); 10532017Spc lastc = *es; /* save last character */ 10632017Spc *es++ = '\0'; /* make the first label into a string */ 10732017Spc if (labct > LABMAX) 10832017Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX); 109*32028Spc if (*ss == '\0') 110*32028Spc labfatal("Zero length tape label found\n"); 111*32028Spc labarg[labct++] = strstore(ss); 11232017Spc 113*32028Spc if (lastc == 0) 11432017Spc break; /* end of list */ 11532017Spc 116*32028Spc if (lastc == '-') { 11732017Spc /* 11832017Spc * this gives a tape range 11932017Spc * increment the source number until it equals the final 12032017Spc * value 12132017Spc */ 12232017Spc incbase = ss; 12332017Spc ss = es; 12432017Spc es = labskip(ss); 12532017Spc if (*es == '-') 12632017Spc labfatal("Range has the format <string>-<string>\n"); 127*32028Spc lastc = *es; 128*32028Spc if (lastc) 129*32028Spc *es++ = '\0'; 13032017Spc /* 13132017Spc * basic test the source string length must be equal to the 13232017Spc * end string length 13332017Spc */ 13432017Spc if (strlen(incbase) != strlen(ss)) 13532017Spc labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss); 13632017Spc labelrange(incbase, ss); 13732017Spc } 13832017Spc } 13932017Spc } 14032017Spc 14132017Spc /* 14232017Spc * Expand a label range 14332017Spc */ 14432017Spc /* static */ 14532017Spc labelrange(startrange, endrange) 14632017Spc char *startrange, *endrange; 14732017Spc { 14832017Spc register char *incr; 14932017Spc register int carry; 15032017Spc 15132017Spc 15232017Spc for (incr = startrange + strlen(startrange) - 1; 15332017Spc strcmp(startrange, endrange) != 0; ) { 15432017Spc /* start incrementing */ 155*32028Spc carry = 0; 156*32028Spc do { 15732017Spc if (isdigit(*incr)) { 15832017Spc if (*incr == '9') { 15932017Spc *incr = '0'; 16032017Spc carry = 1; 16132017Spc } else 162*32028Spc (*incr)++; 16332017Spc } else 16432017Spc if (isupper(*incr)) { 16532017Spc if (*incr == 'Z') { 16632017Spc *incr = 'A'; 16732017Spc carry = 1; 16832017Spc } else 169*32028Spc (*incr)++; 17032017Spc } else 17132017Spc if (islower(*incr)) { 17232017Spc if (*incr == 'z') { 17332017Spc *incr = 'a'; 17432017Spc carry = 1; 17532017Spc } else 176*32028Spc (*incr)++; 17732017Spc } else 17832017Spc labfatal("Problem with label map range spec - can only increment alphanumeric values\n"); 17932017Spc if (carry) { 18032017Spc incr--; 18132017Spc if (incr < startrange) 18232017Spc labfatal("Problem with label map range spec - end of range reached\n"); 18332017Spc } 184*32028Spc } while (carry); 185*32028Spc 18632017Spc if (labct > LABMAX) 18732017Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX); 188*32028Spc labarg[labct++] = strstore(startrange); 18932017Spc 19032017Spc } 19132017Spc } 19232017Spc 19332017Spc /* 19432017Spc * Store a string using malloc 19532017Spc */ 19632017Spc /* static */ 19732017Spc char * 19832017Spc strstore(arg) 19932017Spc char *arg; 20032017Spc { 20132017Spc register len = strlen(arg)+1; 20232017Spc register char *dest; 203*32028Spc char *malloc(); 20432017Spc 20532017Spc dest = malloc(len); 20632017Spc if (dest == NULL) 20732017Spc labfatal("No memory for string storage\n"); 20832017Spc bcopy(arg, dest, len); 20932017Spc return(dest); 21032017Spc } 21132017Spc 21232017Spc /* 21332017Spc * Create a tape label from a volume number 21432017Spc */ 21532017Spc char * 21632017Spc createlabel(volno) 21732017Spc int volno; 21832017Spc { 21932017Spc static char buf[LBLSIZE+LBLSIZE]; 22032017Spc static int lastvol; 221*32028Spc char volbuf[8]; 22232017Spc register char *arg; 22332017Spc 224*32028Spc if (userlabel == 0) 22532017Spc return ("none"); /* previous behaviour */ 22632017Spc 227*32028Spc if (volno == lastvol) /* cache */ 22832017Spc return(buf); 229*32028Spc lastvol = volno; 230*32028Spc 231*32028Spc if (labfmt == NULL) 232*32028Spc labfmt = "%s"; 23332017Spc 23432017Spc if (labct == 0) 23532017Spc { (void) sprintf(volbuf, "%d", volno); 23632017Spc arg = volbuf; 23732017Spc } 23832017Spc else 239*32028Spc arg = labarg[volno-1]; /* volumes run 1-> */ 240*32028Spc (void) sprintf(buf, labfmt, arg); 241*32028Spc buf[LBLSIZE-1] = '\0'; /* Truncate to correct size */ 24232017Spc return(buf); 24332017Spc } 24432017Spc 24532017Spc initialtape() 24632017Spc { static firstpr; 24732017Spc 24832017Spc if (labchk == 0) 24932017Spc return; 25032017Spc if (firstpr == 0) 25132017Spc msg("Mount tape %s for reel 1 of the dump\n", createlabel(0)); 25232017Spc firstpr = 1; 25332017Spc } 25432017Spc 25532017Spc /* 25632017Spc * given an estimated number of tapes, check that 25732017Spc * there are enough tapes on the label list 25832017Spc */ 25932017Spc labelest(etapes) 26032017Spc double etapes; 26132017Spc { int et; 26232017Spc 26332017Spc if (labct) { 26432017Spc et = ceil(etapes); 26532017Spc if (et > labct) 26632017Spc labfatal("Only %d labe%s given, estimated need %d\n", 26732017Spc labct, labct == 1 ? "l" : "ls", et); 26832017Spc } 26932017Spc } 27032017Spc 27132017Spc /* 27232017Spc * labelcheck 27332017Spc * read a dump header and check that the tape header contains 27432017Spc * the label we expected 27532017Spc * close the fd on error to allow upper levels to loop 27632017Spc */ 27732017Spc labelcheck(fd, tno) 27832017Spc int fd; 27932017Spc int tno; 28032017Spc { 28132017Spc union u_spcl uin; /* lots on the stack but that should be OK */ 28232017Spc register char *label; 28332017Spc register char *ontape = uin.s_spcl.c_label; 28432017Spc 28532017Spc if (labchk == 0 || pipeout) 28632017Spc return(0); 28732017Spc label = createlabel(tno); 28832017Spc if (read(fd, (char *)&uin, sizeof uin) != sizeof uin) { 28932017Spc msg("Tape does not start with the correctly sized record\n"); 29032017Spc close(fd); 29132017Spc return(-1); 29232017Spc } 29332017Spc if (ontape[0] == '\0' || 29432017Spc strcmp(ontape, "none") == 0 || 29532017Spc strcmp(ontape, label) == 0) { 29632017Spc /* skip back one record */ 297*32028Spc if (backone(fd) < 0) 29832017Spc labfatal("Label check cannot backspace tape\n"); 29932017Spc return(0); 30032017Spc } 30132017Spc msg("Tape labels do not match should be `%s' is `%s'\n", label, ontape); 30232017Spc close(fd); 30332017Spc return(-1); 30432017Spc } 30532017Spc 30632017Spc /* 30732017Spc * write a log entry for the volume into the log file 30832017Spc */ 309*32028Spc log_volume(tlabel) 310*32028Spc char *tlabel; 31132017Spc { 31232017Spc char *ctime(); 31332017Spc FILE *logfd; 31432017Spc 31532017Spc if (uflag == 0 || labchk == 0) 31632017Spc return; 317*32028Spc if ((logfd = fopen(dumpvolumes, "a")) == NULL) 31832017Spc return; 31932017Spc fprintf(logfd, "%s: date=%20.20s dev=%s level=%c reel=%d ino=%d\n", 32032017Spc tlabel, ctime(&spcl.c_date)+4, disk, incno, tapeno, 32132017Spc tapeno == 1 ? ROOTINO : ino); 32232017Spc fclose(logfd); 32332017Spc } 32432017Spc 32532017Spc /* 32632017Spc * skip forward looking for valid end of label characters 32732017Spc */ 32832017Spc /* static */ 32932017Spc char * 33032017Spc labskip(str) 33132017Spc register char *str; 33232017Spc { 33332017Spc while (*str != ',' && *str != '-' && *str) 33432017Spc str++; 33532017Spc return (str); 33632017Spc } 33732017Spc 33832017Spc /* 33932017Spc * generate a fatal error message 34032017Spc */ 34132017Spc /* VARARGS1 */ 34232017Spc /* ARGSUSED */ 34332017Spc labfatal(fmt, a1, a2, a3, a4, a5) 34432017Spc char *fmt; 34532017Spc int a1, a2, a3, a4, a5; 34632017Spc { 34732017Spc msg(fmt, a1, a2, a3, a4, a5); 34832017Spc dumpabort(); 34932017Spc } 35032017Spc 351