dump/file-restore code (3 of 4)
petec at umcp-cs.UUCP
petec at umcp-cs.UUCP
Tue Feb 28 15:26:07 AEST 1984
: 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 at umcp-cs>
* maintained by Pete Cottrell <petec at umcp-cs>
*
* Patrick has graduated, so please send comments, bug reports, etc. to
* petec at 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 at umcp-cs
ARPA: petec.umcp-cs at CSNet-Relay
More information about the Comp.sources.unix
mailing list