16847Smckusick /* Copyright (c) 1982 Regents of the University of California */ 24610Smckusick 36846Smckusick #ifndef lint 4*8374Smckusick char version[] = "@(#)main.c 2.10 10/07/82"; 56846Smckusick #endif 64610Smckusick 74610Smckusick /* Modified to include h option (recursively extract all files within 84610Smckusick * a subtree) and m option (recreate the heirarchical structure of 94610Smckusick * that subtree and move extracted files to their proper homes). 104610Smckusick * 8/29/80 by Mike Litzkow 114610Smckusick * 126846Smckusick * Modified to work on the new file system 136846Smckusick * 1/19/82 by Kirk McKusick 146846Smckusick * 154610Smckusick * Includes the s (skip files) option for use with multiple dumps on 164610Smckusick * a single tape. 174610Smckusick */ 184610Smckusick 194610Smckusick #define MAXINO 3000 204610Smckusick #define BITS 8 214610Smckusick #define NCACHE 3 224610Smckusick #define SIZEINC 10 234610Smckusick 244610Smckusick #include <stdio.h> 254610Smckusick #include <signal.h> 266844Smckusick #include <fstab.h> 276847Smckusick #ifndef SIMFS 286847Smckusick #include <sys/param.h> 296847Smckusick #include <sys/inode.h> 306847Smckusick #include <sys/fs.h> 316847Smckusick #include <dir.h> 326847Smckusick #include <stat.h> 336847Smckusick #include <dumprestor.h> 346847Smckusick #else 356844Smckusick #include "../h/param.h" 366844Smckusick #include "../h/dir.h" 376844Smckusick #include "../h/stat.h" 386844Smckusick #include "../h/inode.h" 396844Smckusick #include "../h/fs.h" 406844Smckusick #include "../h/dumprestor.h" 416847Smckusick #endif 428296Smckusick #include <sys/ioctl.h> 435038Smckusic #include <sys/mtio.h> 444610Smckusick 455943Smckusic #define ODIRSIZ 14 465038Smckusic struct odirect { 475038Smckusic u_short d_ino; 485943Smckusic char d_name[ODIRSIZ]; 495038Smckusic }; 505038Smckusic 515327Smckusic #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) 525327Smckusic #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) 534610Smckusick #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 544610Smckusick #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 554610Smckusick #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 564610Smckusick 576846Smckusick ino_t ino; 584610Smckusick 59*8374Smckusick int eflag = 0, hflag = 0, mflag = 0, vflag = 0, yflag = 0; 60*8374Smckusick int cvtflag = 0, cvtdir = 0; 614776Smckusic 626844Smckusick long fssize; 634610Smckusick char tapename[] = "/dev/rmt8"; 644610Smckusick char *magtape = tapename; 655038Smckusic int mt; 665038Smckusic int dumpnum = 1; 675038Smckusic int volno = 1; 685038Smckusic int curblk = 0; 695038Smckusic int bct = NTREC+1; 705038Smckusic char tbf[NTREC*TP_BSIZE]; 714610Smckusick 724610Smckusick daddr_t seekpt; 734837Smckusic FILE *df; 745943Smckusic DIR *dirp; 754837Smckusic int ofile; 766847Smckusick char dirfile[] = "/tmp/rstXXXXXX"; 776289Smckusick char lnkbuf[MAXPATHLEN + 1]; 786289Smckusick int pathlen; 794610Smckusick 804837Smckusic #define INOHASH(val) (val % MAXINO) 814837Smckusic struct inotab { 824837Smckusic struct inotab *t_next; 834610Smckusick ino_t t_ino; 844610Smckusick daddr_t t_seekpt; 854837Smckusic } *inotab[MAXINO]; 864610Smckusick 874837Smckusic #define XISDIR 1 884610Smckusick #define XTRACTD 2 894610Smckusick #define XINUSE 4 904837Smckusic #define XLINKED 8 914610Smckusick struct xtrlist { 924837Smckusic struct xtrlist *x_next; 934837Smckusic struct xtrlist *x_linkedto; 944843Smckusic time_t x_timep[2]; 954837Smckusic ino_t x_ino; 964837Smckusic char x_flags; 974843Smckusic char x_name[1]; 984843Smckusic /* actually longer */ 994837Smckusic } *xtrlist[MAXINO]; 1004776Smckusic int xtrcnt = 0; 1014610Smckusick 1025327Smckusic char *dumpmap; 1035327Smckusic char *clrimap; 1044610Smckusick 1055327Smckusic char clearedbuf[MAXBSIZE]; 1065327Smckusic 1074837Smckusic extern char *ctime(); 1086846Smckusick extern int seek(); 1094843Smckusic ino_t search(); 1105943Smckusic int dirwrite(); 1116849Smckusick #ifdef RRESTOR 1126849Smckusick char *host; 1136849Smckusick #endif 1144610Smckusick 1156846Smckusick main(argc, argv) 1164700Smckusic int argc; 1174700Smckusic char *argv[]; 1184610Smckusick { 1194610Smckusick register char *cp; 1204610Smckusick char command; 1214700Smckusic int (*signal())(); 1224610Smckusick int done(); 1234610Smckusick 1244843Smckusic if (signal(SIGINT, done) == SIG_IGN) 1254843Smckusic signal(SIGINT, SIG_IGN); 1264843Smckusic if (signal(SIGTERM, done) == SIG_IGN) 1274843Smckusic signal(SIGTERM, SIG_IGN); 1286844Smckusick mktemp(dirfile); 1294610Smckusick if (argc < 2) { 1304610Smckusick usage: 1314837Smckusic fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n"); 1324700Smckusic done(1); 1334610Smckusick } 1344610Smckusick argv++; 1354610Smckusick argc -= 2; 1364610Smckusick for (cp = *argv++; *cp; cp++) { 1374610Smckusick switch (*cp) { 1384610Smckusick case '-': 1394610Smckusick break; 1408302Smckusick case 'c': 1418302Smckusick cvtflag++; 1428302Smckusick break; 1434610Smckusick case 'f': 1444610Smckusick magtape = *argv++; 1456849Smckusick #ifdef RRESTOR 1466849Smckusick { char *index(); 1476849Smckusick host = magtape; 1486849Smckusick magtape = index(host, ':'); 1496849Smckusick if (magtape == 0) { 1506849Smckusick nohost: 1516849Smckusick msg("need keyletter ``f'' and device ``host:tape''"); 1526849Smckusick done(1); 1536849Smckusick } 1546849Smckusick *magtape++ = 0; 1556849Smckusick if (rmthost(host) == 0) 1566849Smckusick done(1); 1576849Smckusick } 1586849Smckusick #endif 1594610Smckusick argc--; 1604610Smckusick break; 1614610Smckusick /* s dumpnum (skip to) for multifile dump tapes */ 1624610Smckusick case 's': 1634610Smckusick dumpnum = atoi(*argv++); 1646847Smckusick if (dumpnum <= 0) { 1654700Smckusic fprintf(stderr, "Dump number must be a positive integer\n"); 1664700Smckusic done(1); 1674610Smckusick } 1684610Smckusick argc--; 1694610Smckusick break; 1704610Smckusick case 'h': 1714610Smckusick hflag++; 1724610Smckusick break; 1734610Smckusick case 'm': 1744610Smckusick mflag++; 1754610Smckusick break; 176*8374Smckusick case 'x': 177*8374Smckusick command = *cp; 178*8374Smckusick /* set verbose mode by default */ 179*8374Smckusick case 'v': 180*8374Smckusick vflag++; 181*8374Smckusick break; 182*8374Smckusick case 'y': 183*8374Smckusick yflag++; 184*8374Smckusick break; 1854610Smckusick case 'r': 1864610Smckusick case 'R': 1876844Smckusick hflag++; 1886844Smckusick mflag++; 1894610Smckusick case 't': 1904610Smckusick command = *cp; 1914610Smckusick break; 1924610Smckusick default: 1934700Smckusic fprintf(stderr, "Bad key character %c\n", *cp); 1944610Smckusick goto usage; 1954610Smckusick } 1964610Smckusick } 1976849Smckusick #ifdef RRESTOR 1986849Smckusick if (host == 0) 1996849Smckusick goto nohost; 2006849Smckusick #endif 2014610Smckusick doit(command, argc, argv); 2024700Smckusic done(0); 2034610Smckusick } 2044610Smckusick 2054610Smckusick doit(command, argc, argv) 2064700Smckusic char command; 2074700Smckusic int argc; 2084700Smckusic char *argv[]; 2094610Smckusick { 2105038Smckusic struct mtop tcom; 2115038Smckusic 2126849Smckusick #ifdef RRESTOR 2136849Smckusick if ((mt = rmtopen(magtape, 0)) < 0) { 2146849Smckusick #else 2154610Smckusick if ((mt = open(magtape, 0)) < 0) { 2166849Smckusick #endif 2174700Smckusic fprintf(stderr, "%s: cannot open tape\n", magtape); 2184700Smckusic done(1); 2194610Smckusick } 2204843Smckusic if (dumpnum != 1) { 2214610Smckusick tcom.mt_op = MTFSF; 2224610Smckusick tcom.mt_count = dumpnum -1; 2236849Smckusick #ifdef RRESTOR 2246849Smckusick rmtioctl(MTFSF,dumpnum - 1); 2256849Smckusick #else 2264843Smckusic if (ioctl(mt,MTIOCTOP,&tcom) < 0) 2274610Smckusick perror("ioctl MTFSF"); 2286849Smckusick #endif 2294610Smckusick } 2306846Smckusick blkclr(clearedbuf, (long)MAXBSIZE); 2318369Smckusick if (readhdr(&spcl) == 0) { 2328369Smckusick bct--; /* push back this block */ 2338369Smckusick cvtflag++; 2344610Smckusick if (readhdr(&spcl) == 0) { 2354700Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2364700Smckusic done(1); 2374610Smckusick } 2388369Smckusick fprintf(stderr, "Converting to new file system format.\n"); 2398369Smckusick } 2408369Smckusick switch(command) { 2418369Smckusick case 't': 2424843Smckusic fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 2434843Smckusic fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 2444610Smckusick return; 2456844Smckusick case 'R': 2466844Smckusick case 'r': 2476844Smckusick setdir(*argv); 2486844Smckusick argc = 1; 2496844Smckusick *argv = "."; 2506844Smckusick /* and then extract it all */ 2514610Smckusick case 'x': 2526844Smckusick df = fopen(dirfile, "w"); 2536844Smckusick if (df == 0) { 2546844Smckusick fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile); 2556844Smckusick done(1); 2566844Smckusick } 2574837Smckusic extractfiles(argc, argv); 2584837Smckusic return; 2594837Smckusic } 2604837Smckusic } 2614837Smckusic 2624837Smckusic extractfiles(argc, argv) 2634837Smckusic int argc; 2644837Smckusic char **argv; 2654837Smckusic { 2664843Smckusic char *ststore(); 2674837Smckusic register struct xtrlist *xp; 2684837Smckusic struct xtrlist **xpp; 2694837Smckusic ino_t d; 2706289Smckusick int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), 2716289Smckusick xtrlnkfile(), xtrlnkskip(), null(); 2726845Smckusick int mode, uid, gid, i; 2734843Smckusic char name[BUFSIZ + 1]; 2746844Smckusick struct stat stbuf; 2754837Smckusic 2766844Smckusick if (stat(".", &stbuf) < 0) { 2776844Smckusick fprintf(stderr, "cannot stat .\n"); 2786844Smckusick done(1); 2796844Smckusick } 2806844Smckusick /* 2816844Smckusick * should be!!! 2826844Smckusick * 2836844Smckusick fssize = stbuf.st_blksize; 2846844Smckusick */ 2856844Smckusick fssize = MAXBSIZE; 2864837Smckusic if (checkvol(&spcl, 1) == 0) { 2874837Smckusic fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2884837Smckusic } 2896844Smckusick clrimap = 0; 2906844Smckusick dumpmap = 0; 2915038Smckusic pass1(1); /* This sets the various maps on the way by */ 2924843Smckusic while (argc--) { 2934837Smckusic if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { 294*8374Smckusick fprintf(stderr, "%s: not on tape\n", *argv++); 2954837Smckusic continue; 2964610Smckusick } 2974843Smckusic if (mflag) 2984843Smckusic checkdir(*argv); 2996847Smckusick if (hflag) 3004837Smckusic getleaves(d, *argv++); 3014843Smckusic else 3024843Smckusic allocxtr(d, *argv++, XINUSE); 3034837Smckusic } 3044843Smckusic if (dumpnum > 1) { 3055038Smckusic /* 3065038Smckusic * if this is a multi-dump tape we always start with 3075038Smckusic * volume 1, so as to avoid accidentally restoring 3085038Smckusic * from a different dump! 3095038Smckusic */ 3105038Smckusic resetmt(); 3115038Smckusic dumpnum = 1; 3125038Smckusic volno = 1; 3135038Smckusic readhdr(&spcl); 3145038Smckusic goto rbits; 3154837Smckusic } 3165038Smckusic newvol: 3176849Smckusick #ifdef RRESTOR 3186849Smckusick rmtclose(); 3196849Smckusick #else 3206847Smckusick close(mt); 3216849Smckusick #endif 3224610Smckusick getvol: 3235038Smckusic fprintf(stderr, "Mount desired tape volume; Specify volume #: "); 3244837Smckusic if (gets(tbf) == NULL) 3254837Smckusic return; 3264837Smckusic volno = atoi(tbf); 3274837Smckusic if (volno <= 0) { 3284837Smckusic fprintf(stderr, "Volume numbers are positive numerics\n"); 3294837Smckusic goto getvol; 3304837Smckusic } 3316849Smckusick #ifdef RRESTOR 3326849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 3336849Smckusick #else 3346847Smckusick if ((mt = open(magtape, 0)) == -1) { 3356849Smckusick #endif 3366847Smckusick fprintf(stderr, "Cannot open tape!\n"); 3376847Smckusick goto getvol; 3386847Smckusick } 3396847Smckusick if (dumpnum > 1) 3406847Smckusick resetmt(); 3414837Smckusic if (readhdr(&spcl) == 0) { 3424837Smckusic fprintf(stderr, "tape is not dump tape\n"); 3434837Smckusic goto newvol; 3444837Smckusic } 3454837Smckusic if (checkvol(&spcl, volno) == 0) { 3464837Smckusic fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); 3474837Smckusic goto newvol; 3484837Smckusic } 3494610Smckusick rbits: 3504837Smckusic while (gethead(&spcl) == 0) 3514837Smckusic ; 3524837Smckusic if (checktype(&spcl, TS_INODE) == 1) { 3534837Smckusic fprintf(stderr, "Can't find inode mask!\n"); 3544837Smckusic goto newvol; 3554837Smckusic } 3564837Smckusic if (checktype(&spcl, TS_BITS) == 0) 3574837Smckusic goto rbits; 3586844Smckusick readbits(&dumpmap); 3594837Smckusic while (xtrcnt > 0) { 3604837Smckusic again: 3616845Smckusick if (ishead(&spcl) == 0) { 3626845Smckusick i = 0; 3636847Smckusick while (gethead(&spcl) == 0) 3646845Smckusick i++; 3656845Smckusick fprintf(stderr, "resync restor, skipped %i blocks\n", 3666845Smckusick i); 3676845Smckusick } 3684837Smckusic if (checktype(&spcl, TS_END) == 1) { 3694837Smckusic fprintf(stderr, "end of tape\n"); 3704837Smckusic break; 3714610Smckusick } 3724837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 3734837Smckusic gethead(&spcl); 3744837Smckusic goto again; 3754610Smckusick } 3764837Smckusic d = spcl.c_inumber; 3774837Smckusic for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { 3784837Smckusic if (d != xp->x_ino) 3794837Smckusic continue; 3804837Smckusic if (xp->x_flags & XLINKED) 3814837Smckusic continue; 3824837Smckusic xp->x_timep[0] = spcl.c_dinode.di_atime; 3834837Smckusic xp->x_timep[1] = spcl.c_dinode.di_mtime; 3844837Smckusic mode = spcl.c_dinode.di_mode; 3854837Smckusic if (mflag) 3864843Smckusic strcpy(name, xp->x_name); 3874837Smckusic else 3884837Smckusic sprintf(name, "%u", xp->x_ino); 3894837Smckusic switch (mode & IFMT) { 3904837Smckusic default: 3916847Smckusick fprintf(stderr, "%s: unknown file mode 0%o\n", 3926847Smckusick name, mode); 3934837Smckusic xp->x_flags |= XTRACTD; 3944837Smckusic xtrcnt--; 3954837Smckusic goto skipfile; 3964837Smckusic case IFCHR: 3974837Smckusic case IFBLK: 398*8374Smckusick if (vflag) 399*8374Smckusick fprintf(stdout, "extract special file %s\n", name); 4006844Smckusick if (mknod(name, mode, spcl.c_dinode.di_rdev)) { 4014837Smckusic fprintf(stderr, "%s: cannot create special file\n", name); 4024837Smckusic xp->x_flags |= XTRACTD; 4034837Smckusic xtrcnt--; 4044837Smckusic goto skipfile; 4054776Smckusic } 4064837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4074837Smckusic break; 4084837Smckusic case IFDIR: 4094837Smckusic if (mflag) { 410*8374Smckusick if (vflag) 411*8374Smckusick fprintf(stdout, "extract directory %s\n", name); 4124837Smckusic strncat(name, "/.", BUFSIZ); 4134843Smckusic checkdir(name); 4146844Smckusick chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4154837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4164837Smckusic break; 4174610Smckusick } 418*8374Smckusick if (vflag) 419*8374Smckusick fprintf(stdout, "extract file %s\n", name); 4206844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4215038Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4225038Smckusic xp->x_flags |= XTRACTD; 4235038Smckusic xtrcnt--; 4245038Smckusic goto skipfile; 4255038Smckusic } 4266844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4275943Smckusic if (cvtdir) { 4285038Smckusic getfile(xtrcvtdir, xtrcvtskip, 4295038Smckusic spcl.c_dinode.di_size); 4305943Smckusic flushent(xtrfile); 4315943Smckusic } else 4325038Smckusic getfile(xtrfile, xtrskip, 4335038Smckusic spcl.c_dinode.di_size); 4346844Smckusick close(ofile); 4355038Smckusic break; 4366289Smckusick case IFLNK: 437*8374Smckusick if (vflag) 438*8374Smckusick fprintf(stdout, "extract symbolic link %s\n", name); 4396289Smckusick uid = spcl.c_dinode.di_uid; 4406289Smckusick gid = spcl.c_dinode.di_gid; 4416289Smckusick lnkbuf[0] = '\0'; 4426289Smckusick pathlen = 0; 4436289Smckusick getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size); 4446844Smckusick if (symlink(lnkbuf, name) < 0) { 4456289Smckusick fprintf(stderr, "%s: cannot create symbolic link\n", name); 4466289Smckusick xp->x_flags |= XTRACTD; 4476289Smckusick xtrcnt--; 4486289Smckusick goto finished; 4496289Smckusick } 4506844Smckusick chown(name, uid, gid); 4516289Smckusick break; 4524837Smckusic case IFREG: 453*8374Smckusick if (vflag) 454*8374Smckusick fprintf(stdout, "extract file %s\n", name); 4556844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4564837Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4574837Smckusic xp->x_flags |= XTRACTD; 4584837Smckusic xtrcnt--; 4594837Smckusic goto skipfile; 4604837Smckusic } 4616844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4625038Smckusic getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); 4636844Smckusick close(ofile); 4644837Smckusic break; 4654610Smckusick } 4666844Smckusick chmod(name, mode); 4676844Smckusick utime(name, xp->x_timep); 4684837Smckusic xp->x_flags |= XTRACTD; 4694837Smckusic xtrcnt--; 4704837Smckusic goto finished; 4714837Smckusic } 4724837Smckusic skipfile: 4734837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4744700Smckusic finished: 4754837Smckusic ; 4764837Smckusic } 4774837Smckusic if (xtrcnt == 0 && !mflag) 4784837Smckusic return; 4794837Smckusic for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { 4804837Smckusic for (xp = *xpp; xp; xp = xp->x_next) { 4814837Smckusic if (mflag && (xp->x_flags & XISDIR)) 4826844Smckusick utime(xp->x_name, xp->x_timep); 4834837Smckusic if (xp->x_flags & XTRACTD) 4844837Smckusic continue; 4854837Smckusic if ((xp->x_flags & XLINKED) == 0) { 4864837Smckusic fprintf(stderr, "cannot find file %s\n", 4874837Smckusic xp->x_name); 4884837Smckusic continue; 4894837Smckusic } 4904843Smckusic if (!mflag) 4914843Smckusic continue; 492*8374Smckusick if (vflag) 493*8374Smckusick fprintf(stdout, "link %s to %s\n", 494*8374Smckusick xp->x_linkedto->x_name, xp->x_name); 4956844Smckusick if (link(xp->x_linkedto->x_name, xp->x_name) < 0) 4964843Smckusic fprintf(stderr, "link %s to %s failed\n", 4974837Smckusic xp->x_linkedto->x_name, xp->x_name); 4984610Smckusick } 4994837Smckusic } 5004837Smckusic } 5014837Smckusic 5024610Smckusick /* 5034610Smckusick * Read the tape, bulding up a directory structure for extraction 5044610Smckusick * by name 5054610Smckusick */ 5065038Smckusic pass1(savedir) 5075038Smckusic int savedir; 5084610Smckusick { 5094776Smckusic register int i; 5104837Smckusic register struct dinode *ip; 5114837Smckusic struct direct nulldir; 5125038Smckusic char buf[TP_BSIZE]; 5135943Smckusic int putdir(), null(), dirwrite(); 5144610Smckusick 5155943Smckusic nulldir.d_ino = 1; 5165943Smckusic nulldir.d_namlen = 1; 5175943Smckusic strncpy(nulldir.d_name, "/", nulldir.d_namlen); 5185943Smckusic nulldir.d_reclen = DIRSIZ(&nulldir); 5194610Smckusick while (gethead(&spcl) == 0) { 5204700Smckusic fprintf(stderr, "Can't find directory header!\n"); 5214610Smckusick } 5224610Smckusick for (;;) { 5234610Smckusick if (checktype(&spcl, TS_BITS) == 1) { 5246844Smckusick readbits(&dumpmap); 5254610Smckusick continue; 5264610Smckusick } 5274610Smckusick if (checktype(&spcl, TS_CLRI) == 1) { 5286844Smckusick readbits(&clrimap); 5294610Smckusick continue; 5304610Smckusick } 5314610Smckusick if (checktype(&spcl, TS_INODE) == 0) { 5324610Smckusick finish: 5335943Smckusic if (savedir) { 5345943Smckusic fclose(df); 5355943Smckusic dirp = opendir(dirfile); 5365943Smckusic if (dirp == NULL) 5375943Smckusic perror("opendir"); 5385943Smckusic } 5395038Smckusic resetmt(); 5404610Smckusick return; 5414610Smckusick } 5424610Smckusick ip = &spcl.c_dinode; 5434610Smckusick i = ip->di_mode & IFMT; 5444610Smckusick if (i != IFDIR) { 5454610Smckusick goto finish; 5464610Smckusick } 5475038Smckusic if (spcl.c_inumber == ROOTINO) { 5485038Smckusic readtape(buf); 5495038Smckusic bct--; /* push back this block */ 5505038Smckusic if (((struct direct *)buf)->d_ino != ROOTINO) { 5515038Smckusic if (((struct odirect *)buf)->d_ino != ROOTINO) { 5525038Smckusic fprintf(stderr, "bad root directory\n"); 5535038Smckusic done(1); 5545038Smckusic } 5555038Smckusic fprintf(stderr, "converting to new directory format\n"); 5565038Smckusic cvtdir = 1; 5578302Smckusick cvtflag = 1; 5585038Smckusic } 5595038Smckusic if (!savedir && !cvtdir) { 5605038Smckusic /* if no conversion, just return */ 5615038Smckusic goto finish; 5625038Smckusic } 5635038Smckusic } 5644843Smckusic allocinotab(spcl.c_inumber, seekpt); 5655038Smckusic if (savedir) { 5665038Smckusic getfile(putdir, null, spcl.c_dinode.di_size); 5675943Smckusic putent(&nulldir, dirwrite); 5685943Smckusic flushent(dirwrite); 5695038Smckusic } else { 5705038Smckusic getfile(null, null, spcl.c_dinode.di_size); 5715038Smckusic } 5724610Smckusick } 5734610Smckusick } 5744610Smckusick 5754610Smckusick /* 5764843Smckusic * Put the directory entries in the directory file 5774843Smckusic */ 5784843Smckusic putdir(buf, size) 5794843Smckusic char *buf; 5804843Smckusic int size; 5814843Smckusic { 5825038Smckusic struct direct cvtbuf; 5835038Smckusic register struct odirect *odp; 5845038Smckusic struct odirect *eodp; 5854843Smckusic register struct direct *dp; 5866289Smckusick long loc, i; 5874843Smckusic 5885038Smckusic if (cvtdir) { 5895038Smckusic eodp = (struct odirect *)&buf[size]; 5905038Smckusic for (odp = (struct odirect *)buf; odp < eodp; odp++) 5915038Smckusic if (odp->d_ino != 0) { 5925038Smckusic dcvt(odp, &cvtbuf); 5935943Smckusic putent(&cvtbuf, dirwrite); 5945038Smckusic } 5955038Smckusic } else { 5965943Smckusic for (loc = 0; loc < size; ) { 5975943Smckusic dp = (struct direct *)(buf + loc); 5986289Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 5996289Smckusick if (dp->d_reclen <= 0 || dp->d_reclen > i) { 6006289Smckusick loc += i; 6016289Smckusick continue; 6026289Smckusick } 6036289Smckusick loc += dp->d_reclen; 6046847Smckusick if (dp->d_ino != 0) { 6055943Smckusic putent(dp, dirwrite); 6066847Smckusick } 6075943Smckusic } 6085038Smckusic } 6094843Smckusic } 6104843Smckusic 6114843Smckusic /* 6124843Smckusic * Recursively find names and inumbers of all files in subtree 6134843Smckusic * pname and put them in xtrlist[] 6144843Smckusic */ 6154843Smckusic getleaves(ino, pname) 6164843Smckusic ino_t ino; 6174843Smckusic char *pname; 6184843Smckusic { 6194843Smckusic register struct inotab *itp; 6204843Smckusic int namelen; 6216846Smckusick daddr_t bpt; 6225943Smckusic register struct direct *dp; 6235943Smckusic char locname[BUFSIZ + 1]; 6244843Smckusic 6254843Smckusic if (BIT(ino, dumpmap) == 0) { 626*8374Smckusick if (vflag) 627*8374Smckusick fprintf(stdout, "%s: not on the tape\n", pname); 6284843Smckusic return; 6294843Smckusic } 6304843Smckusic for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { 6314843Smckusic if (itp->t_ino != ino) 6324843Smckusic continue; 6334843Smckusic /* 6344843Smckusic * pname is a directory name 6354843Smckusic */ 6364843Smckusic allocxtr(ino, pname, XISDIR); 6374843Smckusic /* 6384843Smckusic * begin search through the directory 6394843Smckusic * skipping over "." and ".." 6404843Smckusic */ 6414843Smckusic strncpy(locname, pname, BUFSIZ); 6424843Smckusic strncat(locname, "/", BUFSIZ); 6434843Smckusic namelen = strlen(locname); 6445943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 6455943Smckusic dp = readdir(dirp); 6465943Smckusic dp = readdir(dirp); 6475943Smckusic dp = readdir(dirp); 6485943Smckusic bpt = telldir(dirp); 6494843Smckusic /* 6504843Smckusic * "/" signals end of directory 6514843Smckusic */ 6525943Smckusic while (dp->d_namlen != 1 || dp->d_name[0] != '/') { 6534843Smckusic locname[namelen] = '\0'; 6545943Smckusic if (namelen + dp->d_namlen >= BUFSIZ) { 6555943Smckusic fprintf(stderr, "%s%s: name exceedes %d char\n", 6565943Smckusic locname, dp->d_name, BUFSIZ); 6574843Smckusic continue; 6584843Smckusic } 6595943Smckusic strncat(locname, dp->d_name, dp->d_namlen); 6605943Smckusic getleaves(dp->d_ino, locname); 6615943Smckusic seekdir(dirp, bpt, itp->t_seekpt); 6625943Smckusic dp = readdir(dirp); 6635943Smckusic bpt = telldir(dirp); 6644843Smckusic } 6654843Smckusic return; 6664843Smckusic } 6674843Smckusic /* 6684843Smckusic * locname is name of a simple file 6694843Smckusic */ 6704843Smckusic allocxtr(ino, pname, XINUSE); 6714843Smckusic } 6724843Smckusic 6734843Smckusic /* 6744843Smckusic * Search the directory tree rooted at inode ROOTINO 6754843Smckusic * for the path pointed at by n 6764843Smckusic */ 6774843Smckusic psearch(n) 6784843Smckusic char *n; 6794843Smckusic { 6804843Smckusic register char *cp, *cp1; 6814843Smckusic char c; 6824843Smckusic 6834843Smckusic ino = ROOTINO; 6844843Smckusic if (*(cp = n) == '/') 6854843Smckusic cp++; 6864843Smckusic next: 6874843Smckusic cp1 = cp + 1; 6884843Smckusic while (*cp1 != '/' && *cp1) 6894843Smckusic cp1++; 6904843Smckusic c = *cp1; 6914843Smckusic *cp1 = 0; 6924843Smckusic ino = search(ino, cp); 6934843Smckusic if (ino == 0) { 6944843Smckusic *cp1 = c; 6954843Smckusic return(0); 6964843Smckusic } 6974843Smckusic *cp1 = c; 6984843Smckusic if (c == '/') { 6994843Smckusic cp = cp1+1; 7004843Smckusic goto next; 7014843Smckusic } 7024843Smckusic return(ino); 7034843Smckusic } 7044843Smckusic 7054843Smckusic /* 7064843Smckusic * search the directory inode ino 7074843Smckusic * looking for entry cp 7084843Smckusic */ 7094843Smckusic ino_t 7104843Smckusic search(inum, cp) 7114843Smckusic ino_t inum; 7124843Smckusic char *cp; 7134843Smckusic { 7145943Smckusic register struct direct *dp; 7154843Smckusic register struct inotab *itp; 7165943Smckusic int len; 7174843Smckusic 7184843Smckusic for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) 7194843Smckusic if (itp->t_ino == inum) 7204843Smckusic goto found; 7214843Smckusic return(0); 7224843Smckusic found: 7235943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 7245943Smckusic len = strlen(cp); 7254843Smckusic do { 7265943Smckusic dp = readdir(dirp); 7275943Smckusic if (dp->d_namlen == 1 && dp->d_name[0] == '/') 7284843Smckusic return(0); 7295943Smckusic } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len)); 7305943Smckusic return(dp->d_ino); 7314843Smckusic } 7324843Smckusic 7334843Smckusic /* 7344610Smckusick * Do the file extraction, calling the supplied functions 7354610Smckusick * with the blocks 7364610Smckusick */ 7374700Smckusic getfile(f1, f2, size) 7384700Smckusic int (*f2)(), (*f1)(); 7396846Smckusick off_t size; 7404610Smckusick { 7414776Smckusic register int i; 7425327Smckusic char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 7434837Smckusic union u_spcl addrblk; 7444837Smckusic # define addrblock addrblk.s_spcl 7454610Smckusick 7464837Smckusic addrblock = spcl; 7474610Smckusick for (;;) { 7484837Smckusic for (i = 0; i < addrblock.c_count; i++) { 7494837Smckusic if (addrblock.c_addr[i]) { 7504776Smckusic readtape(&buf[curblk++][0]); 7516844Smckusick if (curblk == fssize / TP_BSIZE) { 7524776Smckusic (*f1)(buf, size > TP_BSIZE ? 7536844Smckusick (long) (fssize) : 7544776Smckusic (curblk - 1) * TP_BSIZE + size); 7554776Smckusic curblk = 0; 7564776Smckusic } 7575327Smckusic } else { 7584776Smckusic if (curblk > 0) { 7594776Smckusic (*f1)(buf, size > TP_BSIZE ? 7604776Smckusic (long) (curblk * TP_BSIZE) : 7614776Smckusic (curblk - 1) * TP_BSIZE + size); 7624776Smckusic curblk = 0; 7634776Smckusic } 7645327Smckusic (*f2)(clearedbuf, size > TP_BSIZE ? 7655327Smckusic (long) TP_BSIZE : size); 7664610Smckusick } 7674776Smckusic if ((size -= TP_BSIZE) <= 0) { 7684610Smckusick eloop: 7694610Smckusick while (gethead(&spcl) == 0) 7704610Smckusick ; 7714610Smckusick if (checktype(&spcl, TS_ADDR) == 1) 7724610Smckusick goto eloop; 7734776Smckusic goto out; 7744610Smckusick } 7754610Smckusick } 7764837Smckusic if (gethead(&addrblock) == 0) { 7774776Smckusic fprintf(stderr, "Missing address (header) block, ino%u\n", ino); 7784700Smckusic goto eloop; 7794700Smckusic } 7804837Smckusic if (checktype(&addrblock, TS_ADDR) == 0) { 7814837Smckusic spcl = addrblock; 7824776Smckusic goto out; 7834700Smckusic } 7844610Smckusick } 7854776Smckusic out: 7864776Smckusic if (curblk > 0) { 7874776Smckusic (*f1)(buf, (curblk * TP_BSIZE) + size); 7884776Smckusic curblk = 0; 7894776Smckusic } 7904610Smckusick } 7914610Smckusick 7924610Smckusick /* 7934843Smckusic * The next routines are called during file extraction to 7944843Smckusic * put the data into the right form and place. 7954843Smckusic */ 7964843Smckusic xtrfile(buf, size) 7974843Smckusic char *buf; 7984843Smckusic long size; 7994843Smckusic { 8006847Smckusick 8016844Smckusick if (write(ofile, buf, (int) size) == -1) { 8025038Smckusic perror("extract write"); 8034843Smckusic done(1); 8044843Smckusic } 8054843Smckusic } 8064843Smckusic 8075038Smckusic xtrskip(buf, size) 8084843Smckusic char *buf; 8094843Smckusic long size; 8104843Smckusic { 8116847Smckusick 8126846Smckusick #ifdef lint 8136846Smckusick buf = buf; 8146846Smckusick #endif 8156844Smckusick if (lseek(ofile, size, 1) == -1) { 8165038Smckusic perror("extract seek"); 8174843Smckusic done(1); 8184843Smckusic } 8194843Smckusic } 8205038Smckusic 8215038Smckusic xtrcvtdir(buf, size) 8225038Smckusic struct odirect *buf; 8235038Smckusic long size; 8245038Smckusic { 8255038Smckusic struct odirect *odp, *edp; 8266846Smckusick struct direct cvtbuf; 8275038Smckusic 8285038Smckusic edp = &buf[size / sizeof(struct odirect)]; 8295943Smckusic for (odp = buf; odp < edp; odp++) { 8305943Smckusic dcvt(odp, &cvtbuf); 8315943Smckusic putent(&cvtbuf, xtrfile); 8325038Smckusic } 8335038Smckusic } 8345038Smckusic 8355038Smckusic xtrcvtskip(buf, size) 8365038Smckusic char *buf; 8375038Smckusic long size; 8385038Smckusic { 8396847Smckusick 8405038Smckusic fprintf(stderr, "unallocated block in directory\n"); 8415943Smckusic xtrskip(buf, size); 8425038Smckusic } 8436289Smckusick 8446289Smckusick xtrlnkfile(buf, size) 8456289Smckusick char *buf; 8466289Smckusick long size; 8476289Smckusick { 8486847Smckusick 8496289Smckusick pathlen += size; 8506289Smckusick if (pathlen > MAXPATHLEN) { 8516289Smckusick fprintf(stderr, "symbolic link name: %s; too long %d\n", 8526289Smckusick buf, size); 8536289Smckusick done(1); 8546289Smckusick } 8556289Smckusick strcat(lnkbuf, buf); 8566289Smckusick } 8576289Smckusick 8586289Smckusick xtrlnkskip(buf, size) 8596289Smckusick char *buf; 8606289Smckusick long size; 8616289Smckusick { 8626847Smckusick 8636846Smckusick #ifdef lint 8646846Smckusick buf = buf, size = size; 8656846Smckusick #endif 8666289Smckusick fprintf(stderr, "unallocated block in symbolic link\n"); 8676289Smckusick done(1); 8686289Smckusick } 8694843Smckusic 8704843Smckusic null() {;} 8714843Smckusic 8724843Smckusic /* 8734776Smckusic * Do the tape i/o, dealing with volume changes 8744610Smckusick * etc.. 8754610Smckusick */ 8764610Smckusick readtape(b) 8774700Smckusic char *b; 8784610Smckusick { 8796846Smckusick register long i; 8806847Smckusick struct u_spcl tmpbuf; 8816845Smckusick char c; 8824610Smckusick 8834610Smckusick if (bct >= NTREC) { 8844610Smckusick for (i = 0; i < NTREC; i++) 8854776Smckusic ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; 8864610Smckusick bct = 0; 8876849Smckusick #ifdef RRESTOR 8886849Smckusick if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) { 8896849Smckusick #else 8904776Smckusic if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { 8916849Smckusick #endif 892*8374Smckusick fprintf(stderr, "Tape read error"); 893*8374Smckusick if (!yflag) { 894*8374Smckusick fprintf(stderr, "continue?"); 895*8374Smckusick do { 896*8374Smckusick fprintf(stderr, "[yn]\n"); 897*8374Smckusick c = getchar(); 898*8374Smckusick while (getchar() != '\n') 899*8374Smckusick /* void */; 900*8374Smckusick } while (c != 'y' && c != 'n'); 901*8374Smckusick if (c == 'n') 902*8374Smckusick done(1); 903*8374Smckusick } 9044610Smckusick eflag++; 9056845Smckusick i = NTREC*TP_BSIZE; 9066845Smckusick blkclr(tbf, i); 9076849Smckusick #ifdef RRESTOR 9086849Smckusick if (rmtseek(i, 1) < 0) { 9096849Smckusick #else 9106846Smckusick if (lseek(mt, i, 1) < 0) { 9116849Smckusick #endif 9126846Smckusick fprintf(stderr, "continuation failed\n"); 9136846Smckusick done(1); 9146846Smckusick } 9154610Smckusick } 9164610Smckusick if (i == 0) { 9174610Smckusick bct = NTREC + 1; 9184610Smckusick volno++; 9194610Smckusick loop: 9204610Smckusick flsht(); 9216849Smckusick #ifdef RRESTOR 9226849Smckusick rmtclose(); 9236849Smckusick #else 9244610Smckusick close(mt); 9256849Smckusick #endif 9264700Smckusic fprintf(stderr, "Mount volume %d\n", volno); 9274610Smckusick while (getchar() != '\n') 9284610Smckusick ; 9296849Smckusick #ifdef RRESTOR 9306849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 9316849Smckusick #else 9324610Smckusick if ((mt = open(magtape, 0)) == -1) { 9336849Smckusick #endif 9344700Smckusic fprintf(stderr, "Cannot open tape!\n"); 9354610Smckusick goto loop; 9364610Smckusick } 9374610Smckusick if (readhdr(&tmpbuf) == 0) { 9384700Smckusic fprintf(stderr, "Not a dump tape.Try again\n"); 9394610Smckusick goto loop; 9404610Smckusick } 9414610Smckusick if (checkvol(&tmpbuf, volno) == 0) { 9424700Smckusic fprintf(stderr, "Wrong tape. Try again\n"); 9434610Smckusick goto loop; 9444610Smckusick } 9454610Smckusick readtape(b); 9464610Smckusick return; 9474610Smckusick } 9484610Smckusick } 9496846Smckusick blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); 9504610Smckusick } 9514610Smckusick 9524610Smckusick flsht() 9534610Smckusick { 9546847Smckusick 9554610Smckusick bct = NTREC+1; 9564610Smckusick } 9574610Smckusick 9585943Smckusic blkcpy(from, to, size) 9595943Smckusic char *from, *to; 9606846Smckusick long size; 9614610Smckusick { 9626847Smckusick 9636846Smckusick #ifdef lint 9646846Smckusick from = from, to = to, size = size; 9656846Smckusick #endif 9665943Smckusic asm(" movc3 12(ap),*4(ap),*8(ap)"); 9674610Smckusick } 9684610Smckusick 9695038Smckusic blkclr(buf, size) 9705038Smckusic char *buf; 9716846Smckusick long size; 9725038Smckusic { 9736847Smckusick 9746846Smckusick #ifdef lint 9756846Smckusick buf = buf, size = size; 9766846Smckusick #endif 9775038Smckusic asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); 9785038Smckusic } 9795038Smckusic 9805038Smckusic resetmt() 9815038Smckusic { 9825038Smckusic struct mtop tcom; 9835038Smckusic 9846847Smckusick if (dumpnum > 1) 9855038Smckusic tcom.mt_op = MTBSF; 9865038Smckusic else 9875038Smckusic tcom.mt_op = MTREW; 9885038Smckusic tcom.mt_count = 1; 9895038Smckusic flsht(); 9906849Smckusick #ifdef RRESTOR 9916849Smckusick if (rmtioctl(tcom.mt_op, 1) == -1) { 9926849Smckusick /* kludge for disk dumps */ 9936849Smckusick rmtseek((long)0, 0); 9946849Smckusick } 9956849Smckusick #else 9965038Smckusic if (ioctl(mt,MTIOCTOP,&tcom) == -1) { 9975038Smckusic /* kludge for disk dumps */ 9985038Smckusic lseek(mt, (long)0, 0); 9995038Smckusic } 10006849Smckusick #endif 10015038Smckusic if (dumpnum > 1) { 10026849Smckusick #ifdef RRESTOR 10036849Smckusick rmtioctl(MTFSF, 1); 10046849Smckusick #else 10055038Smckusic tcom.mt_op = MTFSF; 10065038Smckusic tcom.mt_count = 1; 10075038Smckusic ioctl(mt,MTIOCTOP,&tcom); 10086849Smckusick #endif 10095038Smckusic } 10105038Smckusic } 10115038Smckusic 10124843Smckusic checkvol(b, t) 10134843Smckusic struct s_spcl *b; 10144843Smckusic int t; 10154610Smckusick { 10166847Smckusick 10174843Smckusic if (b->c_volume == t) 10184843Smckusic return(1); 10194610Smckusick return(0); 10204610Smckusick } 10214610Smckusick 10224843Smckusic readhdr(b) 10234843Smckusic struct s_spcl *b; 10244610Smckusick { 10256847Smckusick 10264843Smckusic if (gethead(b) == 0) 10274610Smckusick return(0); 10284843Smckusic if (checktype(b, TS_TAPE) == 0) 10294843Smckusic return(0); 10304843Smckusic return(1); 10314610Smckusick } 10324610Smckusick 10334610Smckusick /* 10344610Smckusick * read the tape into buf, then return whether or 10354610Smckusick * or not it is a header block. 10364610Smckusick */ 10374610Smckusick gethead(buf) 10384837Smckusic struct s_spcl *buf; 10394610Smckusick { 10408302Smckusick union u_ospcl { 10418302Smckusick char dummy[TP_BSIZE]; 10428302Smckusick struct s_ospcl { 10438302Smckusick int c_type; 10448302Smckusick time_t c_date; 10458302Smckusick time_t c_ddate; 10468302Smckusick int c_volume; 10478302Smckusick daddr_t c_tapea; 10488302Smckusick ino_t c_inumber; 10498302Smckusick int c_magic; 10508302Smckusick int c_checksum; 10518302Smckusick struct odinode { 10528302Smckusick unsigned short odi_mode; 10538302Smckusick short odi_nlink; 10548302Smckusick short odi_uid; 10558302Smckusick short odi_gid; 10568302Smckusick off_t odi_size; 10578302Smckusick daddr_t odi_rdev; 10588302Smckusick char odi_addr[36]; 10598302Smckusick time_t odi_atime; 10608302Smckusick time_t odi_mtime; 10618302Smckusick time_t odi_ctime; 10628302Smckusick } c_dinode; 10638302Smckusick int c_count; 10648302Smckusick char c_addr[TP_NINDIR]; 10658302Smckusick } s_ospcl; 10668302Smckusick } u_ospcl; 10676847Smckusick 10688302Smckusick if (!cvtflag) { 10698302Smckusick readtape((char *)buf); 10708369Smckusick if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == 0) 10718302Smckusick return(0); 10728302Smckusick return(1); 10738302Smckusick } 10748302Smckusick readtape((char *)(&u_ospcl.s_ospcl)); 10758369Smckusick if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 10768302Smckusick checksum((int *)(&u_ospcl.s_ospcl)) == 0) 10774610Smckusick return(0); 10788302Smckusick blkclr((char *)buf, TP_BSIZE); 10798302Smckusick buf->c_type = u_ospcl.s_ospcl.c_type; 10808302Smckusick buf->c_date = u_ospcl.s_ospcl.c_date; 10818302Smckusick buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 10828302Smckusick buf->c_volume = u_ospcl.s_ospcl.c_volume; 10838302Smckusick buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 10848302Smckusick buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 10858369Smckusick buf->c_magic = NFS_MAGIC; 10868302Smckusick buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 10878302Smckusick buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 10888302Smckusick buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 10898302Smckusick buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 10908302Smckusick buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 10918302Smckusick buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 10928302Smckusick buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 10938302Smckusick buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 10948302Smckusick buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 10958302Smckusick buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 10968302Smckusick buf->c_count = u_ospcl.s_ospcl.c_count; 10978302Smckusick blkcpy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR); 10984610Smckusick return(1); 10994610Smckusick } 11004610Smckusick 11014610Smckusick /* 11024610Smckusick * return whether or not the buffer contains a header block 11034610Smckusick */ 11044610Smckusick ishead(buf) 11054837Smckusic struct s_spcl *buf; 11064610Smckusick { 11076847Smckusick 11088369Smckusick if (buf->c_magic != NFS_MAGIC) 11094610Smckusick return(0); 11104610Smckusick return(1); 11114610Smckusick } 11124610Smckusick 11134610Smckusick checktype(b, t) 11144837Smckusic struct s_spcl *b; 11154700Smckusic int t; 11164610Smckusick { 11176847Smckusick 11184837Smckusic return(b->c_type == t); 11194610Smckusick } 11204610Smckusick 11215038Smckusic /* 11225038Smckusic * read a bit mask from the tape into m. 11235038Smckusic */ 11246844Smckusick readbits(mapp) 11256844Smckusick char **mapp; 11265038Smckusic { 11275038Smckusic register int i; 11286844Smckusick char *m; 11294610Smckusick 11305038Smckusic i = spcl.c_count; 11315038Smckusic 11326844Smckusick if (*mapp == 0) 11336846Smckusick *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS))); 11346844Smckusick m = *mapp; 11355038Smckusic while (i--) { 11365038Smckusic readtape((char *) m); 11375327Smckusic m += (TP_BSIZE/(NBBY/BITS)); 11385038Smckusic } 11395038Smckusic while (gethead(&spcl) == 0) 11405038Smckusic ; 11415038Smckusic } 11425038Smckusic 11434610Smckusick checksum(b) 11448302Smckusick register int *b; 11454610Smckusick { 11464776Smckusic register int i, j; 11474610Smckusick 11484776Smckusic j = sizeof(union u_spcl) / sizeof(int); 11494610Smckusick i = 0; 11504610Smckusick do 11514610Smckusick i += *b++; 11524610Smckusick while (--j); 11534610Smckusick if (i != CHECKSUM) { 11544776Smckusic fprintf(stderr, "Checksum error %o, ino %u\n", i, ino); 11554610Smckusick return(0); 11564610Smckusick } 11574610Smckusick return(1); 11584610Smckusick } 11594610Smckusick 11604610Smckusick /* 11615038Smckusic * Check for access into each directory in the pathname of an extracted 11625038Smckusic * file and create such a directory if needed in preparation for moving 11635038Smckusic * the file to its proper home. 11645038Smckusic */ 11655038Smckusic checkdir(name) 11665038Smckusic register char *name; 11675038Smckusic { 11685038Smckusic register char *cp; 11695038Smckusic int i; 11705038Smckusic 11715038Smckusic for (cp = name; *cp; cp++) { 11725038Smckusic if (*cp == '/') { 11735038Smckusic *cp = '\0'; 11746844Smckusick if (access(name, 01) < 0) { 11755038Smckusic register int pid, rp; 11765038Smckusic 11775038Smckusic if ((pid = fork()) == 0) { 11786844Smckusick execl("/bin/mkdir", "mkdir", name, 0); 11796844Smckusick execl("/usr/bin/mkdir", "mkdir", name, 0); 11806844Smckusick fprintf(stderr, "restor: cannot find mkdir!\n"); 11815038Smckusic done(0); 11825038Smckusic } 11835038Smckusic while ((rp = wait(&i)) >= 0 && rp != pid) 11845038Smckusic ; 11855038Smckusic } 11865038Smckusic *cp = '/'; 11875038Smckusic } 11885038Smckusic } 11895038Smckusic } 11905038Smckusic 11916844Smckusick setdir(dev) 11926844Smckusick char *dev; 11936844Smckusick { 11946844Smckusick struct fstab *fsp; 11956844Smckusick 11966844Smckusick if (setfsent() == 0) { 11976844Smckusick fprintf(stderr, "Can't open checklist file: %s\n", FSTAB); 11986844Smckusick done(1); 11996844Smckusick } 12006844Smckusick while ((fsp = getfsent()) != 0) { 12016844Smckusick if (strcmp(fsp->fs_spec, dev) == 0) { 1202*8374Smckusick fprintf(stderr, "%s mounted on %s\n", dev, fsp->fs_file); 12036844Smckusick if (chdir(fsp->fs_file) >= 0) 12046844Smckusick return; 12056844Smckusick fprintf(stderr, "%s cannot chdir to %s\n", 12066844Smckusick fsp->fs_file); 12076844Smckusick done(1); 12086844Smckusick } 12096844Smckusick } 12106844Smckusick fprintf(stderr, "%s not mounted\n", dev); 12116844Smckusick done(1); 12126844Smckusick } 12136844Smckusick 12145038Smckusic /* 12155943Smckusic * These variables are "local" to the following two functions. 12165943Smckusic */ 12175943Smckusic char dirbuf[DIRBLKSIZ]; 12185943Smckusic long dirloc = 0; 12195943Smckusic long prev = 0; 12205943Smckusic 12215943Smckusic /* 12225943Smckusic * add a new directory entry to a file. 12235943Smckusic */ 12245943Smckusic putent(dp, wrtfunc) 12255943Smckusic struct direct *dp; 12265943Smckusic int (*wrtfunc)(); 12275943Smckusic { 12286847Smckusick 12295943Smckusic if (dp->d_ino == 0) 12305943Smckusic return; 12316847Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 12326847Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 12336847Smckusick DIRBLKSIZ - prev; 12345943Smckusic (*wrtfunc)(dirbuf, DIRBLKSIZ); 12355943Smckusic dirloc = 0; 12365943Smckusic } 12376847Smckusick blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 12386847Smckusick prev = dirloc; 12396847Smckusick dirloc += dp->d_reclen; 12405943Smckusic } 12415943Smckusic 12425943Smckusic /* 12435943Smckusic * flush out a directory that is finished. 12445943Smckusic */ 12455943Smckusic flushent(wrtfunc) 12465943Smckusic int (*wrtfunc)(); 12475943Smckusic { 12486847Smckusick 12495943Smckusic ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 12505943Smckusic (*wrtfunc)(dirbuf, dirloc); 12515943Smckusic dirloc = 0; 12525943Smckusic } 12535943Smckusic 12545943Smckusic dirwrite(buf, size) 12555943Smckusic char *buf; 12565943Smckusic int size; 12575943Smckusic { 12586847Smckusick 12595943Smckusic fwrite(buf, 1, size, df); 12605943Smckusic seekpt = ftell(df); 12615943Smckusic } 12625943Smckusic 12635943Smckusic dcvt(odp, ndp) 12645943Smckusic register struct odirect *odp; 12655943Smckusic register struct direct *ndp; 12665943Smckusic { 12676847Smckusick 12686846Smckusick blkclr((char *)ndp, (long)(sizeof *ndp)); 12695943Smckusic ndp->d_ino = odp->d_ino; 12705943Smckusic strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 12715943Smckusic ndp->d_namlen = strlen(ndp->d_name); 12725943Smckusic ndp->d_reclen = DIRSIZ(ndp); 12735943Smckusic /* 12745943Smckusic * this quickly calculates if this inode is a directory. 12755943Smckusic * Currently not maintained. 12765943Smckusic * 12775943Smckusic for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { 12785943Smckusic if (itp->t_ino != odp->d_ino) 12795943Smckusic continue; 12805943Smckusic ndp->d_fmt = IFDIR; 12815943Smckusic break; 12825943Smckusic } 12835943Smckusic */ 12845943Smckusic } 12855943Smckusic 12865943Smckusic /* 12876289Smckusick * Open a directory. 12886289Smckusick * Modified to allow any random file to be a legal directory. 12896289Smckusick */ 12906289Smckusick DIR * 12916289Smckusick opendir(name) 12926289Smckusick char *name; 12936289Smckusick { 12946289Smckusick register DIR *dirp; 12956289Smckusick 12966289Smckusick dirp = (DIR *)malloc(sizeof(DIR)); 12976289Smckusick dirp->dd_fd = open(name, 0); 12986289Smckusick if (dirp->dd_fd == -1) { 12996846Smckusick free((char *)dirp); 13006289Smckusick return NULL; 13016289Smckusick } 13026289Smckusick dirp->dd_loc = 0; 13036289Smckusick return dirp; 13046289Smckusick } 13056289Smckusick 13066289Smckusick /* 13076289Smckusick * Seek to an entry in a directory. 13085943Smckusic * Only values returned by ``telldir'' should be passed to seekdir. 13095943Smckusic * Modified to have many directories based in one file. 13105943Smckusic */ 13115943Smckusic void 13125943Smckusic seekdir(dirp, loc, base) 13135943Smckusic register DIR *dirp; 13146846Smckusick daddr_t loc, base; 13155943Smckusic { 13166847Smckusick 13175943Smckusic if (loc == telldir(dirp)) 13185943Smckusic return; 13195943Smckusic loc -= base; 13205943Smckusic if (loc < 0) 13215943Smckusic fprintf(stderr, "bad seek pointer to seekdir %d\n", loc); 13226846Smckusick (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 13235943Smckusic dirp->dd_loc = loc & (DIRBLKSIZ - 1); 13245943Smckusic if (dirp->dd_loc != 0) 13255943Smckusic dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 13265943Smckusic } 13275943Smckusic 13285943Smckusic /* 13296844Smckusick * get next entry in a directory. 13304700Smckusic */ 13316844Smckusick struct direct * 13326844Smckusick readdir(dirp) 13336844Smckusick register DIR *dirp; 13344610Smckusick { 13356844Smckusick register struct direct *dp; 13364700Smckusic 13376844Smckusick for (;;) { 13386844Smckusick if (dirp->dd_loc == 0) { 13396844Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 13406844Smckusick DIRBLKSIZ); 13416844Smckusick if (dirp->dd_size <= 0) 13426844Smckusick return NULL; 13436844Smckusick } 13446844Smckusick if (dirp->dd_loc >= dirp->dd_size) { 13456844Smckusick dirp->dd_loc = 0; 13466844Smckusick continue; 13476844Smckusick } 13486844Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 13496844Smckusick if (dp->d_reclen <= 0 || 13506844Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) 13516844Smckusick return NULL; 13526844Smckusick dirp->dd_loc += dp->d_reclen; 13536844Smckusick if (dp->d_ino == 0) 13546844Smckusick continue; 13556844Smckusick return (dp); 13565948Smckusic } 13574610Smckusick } 13584610Smckusick 13594843Smckusic allocinotab(ino, seekpt) 13604837Smckusic ino_t ino; 13614843Smckusic daddr_t seekpt; 13624610Smckusick { 13634837Smckusic register struct inotab *itp; 13644776Smckusic 13654837Smckusic itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 13664837Smckusic itp->t_next = inotab[INOHASH(ino)]; 13674837Smckusic inotab[INOHASH(ino)] = itp; 13684837Smckusic itp->t_ino = ino; 13694843Smckusic itp->t_seekpt = seekpt; 13704610Smckusick } 13714610Smckusick 13724843Smckusic allocxtr(ino, name, flags) 13734837Smckusic ino_t ino; 13744843Smckusic char *name; 13754843Smckusic char flags; 13764610Smckusick { 13774843Smckusic register struct xtrlist *xp, *pxp; 13784776Smckusic 13794843Smckusic xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name)); 13804837Smckusic xp->x_next = xtrlist[INOHASH(ino)]; 13814837Smckusic xtrlist[INOHASH(ino)] = xp; 13824837Smckusic xp->x_ino = ino; 13834843Smckusic strcpy(xp->x_name, name); 13844837Smckusic xtrcnt++; 13854843Smckusic xp->x_flags = flags; 13864843Smckusic for (pxp = xp->x_next; pxp; pxp = pxp->x_next) 13874843Smckusic if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { 13884843Smckusic xp->x_flags |= XLINKED; 13894843Smckusic xp->x_linkedto = pxp; 13904843Smckusic xtrcnt--; 13914843Smckusic break; 13924843Smckusic } 1393*8374Smckusick if (!vflag) 1394*8374Smckusick return; 13954843Smckusic if (xp->x_flags & XLINKED) 13964843Smckusic fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); 13974843Smckusic else if (xp->x_flags & XISDIR) 13984843Smckusic fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); 13994843Smckusic else 14004843Smckusic fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); 14014610Smckusick } 14024610Smckusick 14035038Smckusic done(exitcode) 14045038Smckusic int exitcode; 14054610Smckusick { 14066847Smckusick 14075038Smckusic unlink(dirfile); 14085038Smckusic exit(exitcode); 14094610Smckusick } 1410