petec@umcp-cs.UUCP (02/28/84)
: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH all=FALSE if [ $1x = -ax ]; then all=TRUE fi /bin/echo 'Extracting whichtape.c' sed 's/^X//' <<'//go.sysin dd *' >whichtape.c static char *sccsid = "@(#) whichtape(V2) PJS (University of Maryland)"; X/* * whichtape: This program is used to determine on which tape * a file or list of files have been dumped. It uses the information * in /g/etc/filesontapes (defined in filtap.h), which is maintained * by the program filtapmgr (file tape manager). * (See the manual entry for a more user oriented description.) * * written by: Patrick Steranka -- Jan. 1983 <patrick@umcp-cs> * maintained by Pete Cottrell <petec@umcp-cs> * * Patrick has graduated, so please send comments, bug reports, etc. to * petec@umcp-cs * */ #include <stdio.h> #include <ctype.h> #include <sys/param.h> #include <sys/ino.h> #include <sys/inode.h> #include <sys/dir.h> #include <dumprestor.h> #include <fstab.h> #include "filtap.h" #define MAXLIST 2000 long int savpos; PTRNODE base_sys,marker,ptr; struct bufent{ char fname[120]; /* Full path name */ char *eoname; /* Pointer to end of path name */ NODE e; } buf; short int cklist[MAXLIST]; struct bufent file_list[MAXLIST]; int fl_idx=0, none_found=1,i; X/* This array corresponds to each file in the argv list of files. It has indexes into the file_list */ int argv_list[MAXLIST]; int af_idx=0; X/* options */ int aopt, /* print out all back-up information option */ ropt, /* recursive option */ eopt, /* don't expand file option */ iopt; /* print out inode information also */ fopt; /* choose different file database */ int getrecord(),getent(); FILE *fp,*fp_child,*popen(),*fopen(); char *findrdev(),*timdmptap(),*rawname(),*get_dmptime(); char **gblargv; main(argc,argv) int argc; char **argv; { char *opts,dirname[100]; long int savepos; int foundall; /* handle both ways for describing options, ie. -opts or -o -p -t -s */ while (--argc && **++argv == '-'){ opts = *argv; while (*++opts) switch(*opts){ case 'r': /* recurse option */ ropt++; break; case 'a': /* print all back-up information option */ aopt++; break; case 'i': /* print inode information option */ iopt++; break; case 'e': /* no-expand option */ eopt++; break; case 'f': /* different file database option */ fopt++; filsys_file = *++argv; argc--; break; default: /* huh???, option */ fprintf(stderr,"Bad option `%c'.\n",*opts); goto usage; } /* end case */ } /* end while */ if (argc < 1){ usage: fprintf(stderr,"usage: whichtape [-f filsys_file] -aire filelist\n"); exit(1); } if ((fp=fopen(filsys_file,"r")) == NULL){ fprintf(stderr,"Missing file %s.\n",filsys_file); exit(1); } /* Each entry in this array corresponds to an argv file, if the entry is still -1 after looking for it, then the file was not found, else the entry has an index into the file_list array. */ for(i=0;i<MAXLIST;i++){ cklist[i] = 0; argv_list[i] = -1; } strcpy(buf.fname,"/"); buf.eoname = &(buf.fname[1]); /* Set gblargv to list of files to query */ gblargv = argv; foundall = 0; while (getent(&buf) != EOF && foundall == 0){ /* Look at each entry in "filsys_file" and see if any arguments match any of the entries */ if (buf.e.dir && (strcmp(buf.e.name,".") != 0) && (strcmp(buf.e.name,"..") != 0)) { /* Add another name to this path */ addrmdir(&buf); continue; } else if (strcmp(buf.e.name,"/") == 0){ /* Reached the end of a directory so remove the parents name */ addrmdir(&buf); continue; } else { /* Add the file name to the path name => full name */ strcpy(buf.eoname,buf.e.name); } for(foundall=1,i=0; i < argc; i++){ if (cklist[i] == 0){ lookforentry(argc,argv); foundall=0; break; } } }/* End while */ for(i=0; i < argc; i++){ if (cklist[i] == 0){ printf("File %s not backed-up on daily tape, sorry!\n",argv[i]); printf("You may find it on a bi-weekly tape, though.\n"); } } fclose(fp); exit(0); } lookforentry(argc,argv) int argc; char **argv; { register int i, savepos; /* Compare each file in the arg. list against this entry */ for (i=0; i < argc; i++){ /* Make af_idx point to the argv file being processed */ af_idx = i; if (strcmp(buf.fname,argv[i]) == 0){ /* found a match -- print out info for this entry */ /* Check this entry off of the list */ cklist[i] = 1; savpos = ftell(fp); printentry(&buf); fseek(fp,savpos,0);/* Restor file to saved position */ } else{ /* maybe this is a directory entry */ if (eopt == 0 && strcmp(buf.e.name,".") == 0){ /* Expand file name into a directory, because a directory can be entered "with or without it's" "/." name */ /* Note: Actually take off /. and then do the comparison */ buf.eoname[-1] = '\0'; if (strcmp(buf.fname,argv[i]) == 0){ /* A directory entry has been found, so print the directry "and it's contents" */ buf.eoname[-1] = '/'; /* Check this directory off list */ cklist[i] = 1; savpos = ftell(fp); printentry(&buf); /* Restor file to saved position */ fseek(fp,savpos,0); } else buf.eoname[-1] = '/'; } } }/* For */ } printentry(b) struct bufent *b; { register int skiplevel,notdone=1,eoflag; struct bufent savbent; prtent(b); /* Print this entry */ if (b->e.dir == 0) return; /* Prepare for directory searching */ cpybent(&savbent,b); skiplevel=1; /* This entry is a directory, so print it's contents (if ropt == 0), or print it's contents and sub-directories contents (if ropt > 0) */ while ((eoflag = getent(b)) != EOF && (skiplevel > 0)){ if (ropt){ /* Print sub-directories - do not skip them */ if (strcmp(b->e.name,"..") == 0) continue; if (b->e.dir && strcmp(b->e.name,".") != 0){ /* Add this directory name to the path */ skiplevel++; addrmdir(b); continue; } if (strcmp(b->e.name,"/") == 0){ /* Reached end of a directory -- so remove the dir. name from the path */ skiplevel--; addrmdir(b); continue; } } else{ /* When directories are reached - skip over them */ if (strcmp(b->e.name,"..") == 0) continue; if (b->e.dir && strcmp(b->e.name,".") != 0){ /* Skip until the end of this sub-directory */ addrmdir(b); if(skiplevel++ == 1){ /* print this directory */ /* but don't recurse it */ prtent(b); } continue; } if (strcmp(b->e.name,"/") == 0){ /* continue with previous directory */ skiplevel--; addrmdir(b); continue; } if (skiplevel > 1) continue; } /* form a full path & file name & print it out */ strcpy(b->eoname,b->e.name); prtent(b); } /* End while */ cpybent(b,&savbent); return; } prtent(b) struct bufent *b; { int i,j,idx; char *ptime; if (aopt){ /* print all back-up information for this entry */ printf("file: %s\n",b->fname); if (iopt){ /* print out inode information for this entry */ /* print out inodes for this entry */ for (i=0; i < (MAXBACKUPS-1)/3 + 1; i++){ /* for each row */ for (j=0; j<3; j++){ /* for each column */ if ((idx=j+i*3) < MAXBACKUPS){ /* only print as many columns as are needed */ if (j == 0) printf("%s",(i==0)?"inodes:\t":"\t"); printf("(%d) = %5d\t",idx+1,b->e.inodes[idx]); } } printf("\n"); } /* print out inodes */ } /* print out tape names for this entry */ for (i=0; i < MAXBACKUPS; i++){ /* for each row */ if (i == 0) printf("tapes:"); ptime = get_dmptime(b->e.tapes[i],b->fname); if (*ptime == '\0') ptime = "--Time of Dump Unknown--"; printf("\t(%d) = %5s\t%s\n",i+1,b->e.tapes[i],ptime); } printf("\n"); } else{ /* normal print */ ptime = get_dmptime(b->e.tapes[0],b->fname); if (*ptime == '\0') ptime = "--Time of Dump Unknown--"; printf("%s\t%s",b->e.tapes[0],ptime); if (iopt) printf("\t%d",b->e.inodes[0]); printf("\t%s\n",b->fname); } } getent(b) struct bufent *b; { int nmread,i; char c,*name; clearnode(&(b->e)); /* read inodes */ nmread = 1; /* to get loop started */ for (i=0; i < MAXBACKUPS && nmread > 0; i++){ nmread = fread((char*)&(b->e.inodes[i]), sizeof(ino_t),1,fp); } /* Check for end of file */ /* Actually, if an incomplete record occured here it would go undetected. *sigh* */ if (nmread == 0) /* Reached EOF - normal case */ return(EOF); /* read tape names */ for (i=0; i < MAXBACKUPS; i++){ fread(b->e.tapes[i],MAXTAPNAM,1,fp); /* Add null byte to end of tape name */ b->e.tapes[i][MAXTAPNAM] = '\0'; } /* read directory flag */ fread(&c,1,1,fp); switch (c){ case '0': /* This entry is a normal file */ b->e.dir = 0; break; case '1': /* This entry is a directory */ b->e.dir = 1; break; default: /* Error in file */ fprintf(stderr,"\nERROR in %s: file position is %d (decimal)\n",filsys_file,ftell(fp)); printf("\nEntry in error is\n"); prtbent(b); return(ERROR); break; } /* Read in file name */ for (name=b->e.name; (nmread = fread(&c,1,1,fp)) > 0 && c != '\0'; ) *name++ = c; /* Read until null byte */ *name = '\0'; /* Add null byte at end of name */ /* Just double check to see if unexpected end of file occured */ if (nmread = 0){ fprintf(stderr,"INCOMPLETE Record - at EOF\n"); return(ERROR); } return(0); } clearnode(e) NODE e; { int i,j; e.next = NULL; e.down = NULL; e.dir = 0; /* Initialize all tape back-up names to nulls */ for(i=0; i < MAXBACKUPS; i++){ for(j=0; j < MAXTAPNAM; j++) e.tapes[i][j] = ' '; e.tapes[i][MAXTAPNAM] = '\0'; /* Stick null at end of tape name */ } for(i=0; i < MAXBACKUPS; i++) e.inodes[i] = 0; return; } prtbent(b) struct bufent *b; { int i,j,idx; printf("file: %s\n",b->fname); printf("entry name: %s\n",b->e.name); /* print out inodes for this entry */ for (i=0; i < (MAXBACKUPS-1)/3 + 1; i++){ /* for each row */ for (j=0; j<3; j++){ /* for each column */ if ((idx=j+i*3) < MAXBACKUPS){ /* only print as many columns as are needed */ if (j == 0) printf("%s",(i==0)?"inodes:\t":"\t"); printf("(%d) = %5d\t",idx+1,b->e.inodes[idx]); } } printf("\n"); } /* print out inodes */ /* print out tape names for this entry */ for (i=0; i < (MAXBACKUPS-1)/3 + 1; i++){ /* for each row */ for (j=0; j<3; j++){ /* for each column */ if ((idx=j+i*3) < MAXBACKUPS){ /* only print as many columns as are needed */ if (j == 0) printf("%s",(i==0)?"tapes:\t":"\t"); printf("(%d) = %5s\t",idx+1,b->e.tapes[idx]); } } printf("\n"); } /* print out tape names */ } X/* get_dmptime: Returns in ctime format the date & time when the tape name given was dumped. This time is gotten from /etc/dumpdates. The TAPNAMOPT must be enabled for this information to be extracted. The NULL string is returned, if for any reason the time could not be determined. */ char * get_dmptime(tape,filename) char *tape,*filename; { char *dev; dev = findrdev(filename); return(timdmptap(tape,dev)); } X/* findrdev: Returns the raw device upon which a file was dumped. This is the first field in /etc/dumpdates. */ char * findrdev(filename) char *filename; { char *dev,*edev,*index(); register struct fstab *fs_ent; struct fstab *getfsfile(); dev = filename++; edev = index(filename,'/'); if (edev != NULL) *edev = '\0'; setfsent(); if ((fs_ent = getfsfile(dev)) == NULL){ if (edev != NULL) *edev = '/'; /* Let's put back the slash we took out */ endfsent(); setfsent(); /* device could not be found so assume file belongs on root */ if ((fs_ent=getfsfile("/")) == NULL){ fprintf(stderr,"File %s, can't find device (in"); fprintf(stderr," /etc/fstab) that file belongs on.\n",dev); /* What??? -- This really shouldn't happen */ endfsent(); return(""); } /* Close fstab file */ endfsent(); return(rawname(fs_ent->fs_spec)); } if (edev != NULL) *edev = '/'; /* Let's put back the slash we took out */ /* Close fstab file */ endfsent(); /* Got device file belongs on */ return(rawname(fs_ent->fs_spec)); } char *rawname(cp) char *cp; { static char rawbuf[32]; char *rindex(); char *dp = rindex(cp, '/'); if (dp == 0) return (0); *dp = 0; strcpy(rawbuf, cp); *dp = '/'; strcat(rawbuf, "/r"); strcat(rawbuf, dp+1); return (rawbuf); } addrmdir(b) struct bufent *b; { if (b->e.dir && strcmp(b->e.name,".") != 0 && strcmp(b->e.name,"..") != 0){ /* "This is a directory entry, so add it to the path's name" */ strcpy(b->eoname,b->e.name); strcat(b->eoname,"/."); b->eoname = b->fname + strlen(b->fname) - 1; } if (strcmp(b->e.name,"/") == 0){ /* Back up over previous slash, ie. given /foo/bar/file where b->eoname points to ------- ^ then back up before / to here ---------------^ */ b->eoname -= 2; /* Get rid of last path name added */ while (*b->eoname != '/' && b->eoname != b->fname) b->eoname--; /* chop off directory name, ie given /foo/bar/file this goes to /foo/ where b->eoname points to ----------------^ */ *++(b->eoname) = '\0'; } return; } file_found(b) struct bufent *b; { /* Just like an assignment statment */ cpybent(&(file_list[fl_idx++]),b); /* If this file is in the argv list, then leave a pointer to it in argv_list */ if (strcmp(b->fname,gblargv[af_idx])){ /* This file or directory appears in the argument list so remember where it is in the file_list */ argv_list[af_idx] = fl_idx-1; } } cpybent(dest,source) struct bufent *dest,*source; { strcpy(dest->fname,source->fname); dest->eoname = source->eoname; cpyent(&(dest->e),&(source->e)); } cpyent(dest,source) NODE *dest,*source; { register int i; /* Note: The limit values in the FOR loops where obtained from the file "filtap.h" */ /* Copy inodes information */ for(i=0;i<MAXBACKUPS;i++) dest->inodes[i] = source->inodes[i]; /* Copy directory flag information */ dest->dir = source->dir; /* Copy pointer information (although it is not being used in this program) */ dest->next = source->next; dest->down = source->down; /* Copy entries name information */ for(i=0;i<15;i++) dest->name[i] = source->name[i]; return; } //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 whichtape.c /bin/echo -n ' '; /bin/ls -ld whichtape.c fi /bin/echo 'Extracting getrecord.c' sed 's/^X//' <<'//go.sysin dd *' >getrecord.c #define TAPNAMOPT 1 #define OINCREM "/etc/ddate" /*old format incremental info*/ #define NINCREM "/etc/dumpdates" /*new format incremental info*/ #include <stdio.h> #include <ctype.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/filsys.h> #include <sys/ino.h> #include <sys/inode.h> #include <sys/fblk.h> #include <sys/dir.h> #include <utmp.h> #include <time.h> #include <signal.h> #include <dumprestor.h> #include <fstab.h> int recno = 0; int getrecord(df, ip) FILE *df; struct idates *ip; { #ifdef TAPNAMOPT char buf[BUFSIZ],tap_buf[100],ino_buf[100]; int nocnv; if ( (fgets(buf, BUFSIZ, df)) != buf) return(-1); recno++; nocnv = sscanf(buf,TNDUMPINFMT,ip->id_name,&(ip->id_incno),ip->id_pdate); nocnv = sscanf(&(buf[ENDOLDLINE]),"%s %s",tap_buf,ino_buf); if (nocnv < 2){ ip->id_notapes = 0; } else{ ip->id_notapes = unpk_tapes(tap_buf,ip->id_tapes); if (unpk_inos(ino_buf,ip->id_inos) != ip->id_notapes){ msg("Mismatched tape names & starting inode numbers, line %d\n", recno); } } X/* There is no need to convert the dump time into the integer equivalent representation. So skip this extra work. */ X/* if (makeidate(ip, ip->id_pdate) < 0) msg("Unknown intermediate format in %s, line %d\n", NINCREM, recno); */ return(0); #else not TAPNAMOPT if ( (fgets(buf, BUFSIZ, df)) != buf) return(-1); recno++; if (makeidate(idatep, buf) < 0) msg("Unknown intermediate format in %s, line %d\n", NINCREM, recno); return(0); #endif TAPNAMOPT } unpk_tapes(buf,ar) char *buf,ar[MAXTAPDMP][MAXTAPNAM+1]; { int i=0; char *ptr=buf,*ent,c,c2; while(*ptr){ ent = (ptr == buf)? ptr: ++ptr;/* skip over comma, if ness */ /* find end of entry */ while (*ptr != ',' && *ptr != '\0') ptr++; c = *ptr; c2 = '\0'; *ptr = '\0';/* temp mark end of string */ /* Watch for tape names that are too long */ if(strlen(ent) > MAXTAPNAM){ msg("Tape name too long %s in %s\n",ent,NINCREM); /* prevent subscript error */ c2 = ent[MAXTAPNAM]; ent[MAXTAPNAM] = '\0'; msg("Truncated to '%s'\n",ent); } /* Assign tape name to i(th) position */ strcpy(ar[i],ent); /* prevent subscript error */ if (c2) ent[MAXTAPNAM] = c2; i++; /* replace char saved */ *ptr = c; } return(i); } unpk_inos(buf,inos) char *buf; ino_t inos[MAXTAPDMP]; { int i=0; /* count # of entries */ char *ptr=buf,*ent,c; while(*ptr){ ent = (ptr == buf)? ptr: ++ptr;/* skip over comma, if ness */ /* find end of entry */ while (*ptr != ',' && *ptr != '\0') ptr++; c = *ptr; *ptr = '\0';/* temp mark end of string */ inos[i++] = (ino_t)(atoi(ent)); /* replace char saved */ *ptr = c; } return(i); } msg(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr," DUMP: "); fprintf(stderr, fmt, a1, a2, a3, a4, a5); fflush(stdout); fflush(stderr); } //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 getrecord.c /bin/echo -n ' '; /bin/ls -ld getrecord.c fi /bin/echo 'Extracting timdmptap.c' sed 's/^X//' <<'//go.sysin dd *' >timdmptap.c #define TAPNAMOPT 1 #include <stdio.h> #include <ctype.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/filsys.h> #include <sys/ino.h> #include <sys/inode.h> #include <sys/fblk.h> #include <sys/dir.h> #include <utmp.h> #include <time.h> #include <signal.h> #include <dumprestor.h> #include <fstab.h> #define OINCREM "/etc/ddate" /*old format incremental info*/ #define NINCREM "/etc/dumpdates" /*new format incremental info*/ char * timdmptap(tape,dev) char *tape,*dev; { FILE *fp; int i,recno=0; static struct idates dd_ent; if ((fp = fopen(NINCREM,"r")) == NULL){ /* Can't open dumpdates file */ return(""); } while (getrecord(fp,&dd_ent) >= 0){ /* Only look at records for a particular device */ recno++; if (strcmp(dd_ent.id_name,dev) != 0) continue; /* Is tape we're looking for in this record */ for (i=0; i < dd_ent.id_notapes; i++){ if (strcmp(dd_ent.id_tapes[i],tape) == 0){ /* Return time when this tape was dumped */ fclose(fp); return(dd_ent.id_pdate); } } } /* End while */ /* didn't find tape in fie, so don't know when it was dumped */ fclose(fp); return(""); } //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 timdmptap.c /bin/echo -n ' '; /bin/ls -ld timdmptap.c fi -- Call-Me: Pete Cottrell, Univ. of Md. Comp. Sci. Dept. UUCP: {seismo,allegra,brl-bmd}!umcp-cs!petec CSNet: petec@umcp-cs ARPA: petec.umcp-cs@CSNet-Relay