14610Smckusick /* Copyright (c) 1981 Regents of the University of California */ 24610Smckusick 3*6846Smckusick #ifndef lint 4*6846Smckusick char version[] = "@(#)main.c 2.4 05/19/82"; 5*6846Smckusick #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 * 12*6846Smckusick * Modified to work on the new file system 13*6846Smckusick * 1/19/82 by Kirk McKusick 14*6846Smckusick * 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> 276844Smckusick #include "../h/param.h" 286844Smckusick #include "../h/dir.h" 296844Smckusick #include "../h/stat.h" 306844Smckusick #include "../h/inode.h" 316844Smckusick #include "../h/fs.h" 326844Smckusick #include "../h/dumprestor.h" 335038Smckusic #include <sys/mtio.h> 344610Smckusick 355943Smckusic #define ODIRSIZ 14 365038Smckusic struct odirect { 375038Smckusic u_short d_ino; 385943Smckusic char d_name[ODIRSIZ]; 395038Smckusic }; 405038Smckusic 415327Smckusic #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) 425327Smckusic #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) 434610Smckusick #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 444610Smckusick #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 454610Smckusick #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 464610Smckusick 47*6846Smckusick ino_t ino; 484610Smckusick 495038Smckusic int eflag = 0, hflag = 0, mflag = 0, cvtdir = 0; 504776Smckusic 516844Smckusick long fssize; 524610Smckusick char tapename[] = "/dev/rmt8"; 534610Smckusick char *magtape = tapename; 545038Smckusic int mt; 555038Smckusic int dumpnum = 1; 565038Smckusic int volno = 1; 575038Smckusic int curblk = 0; 585038Smckusic int bct = NTREC+1; 595038Smckusic char tbf[NTREC*TP_BSIZE]; 604610Smckusick 614610Smckusick daddr_t seekpt; 624837Smckusic FILE *df; 635943Smckusic DIR *dirp; 644837Smckusic int ofile; 654610Smckusick char dirfile[] = "rstXXXXXX"; 666289Smckusick char lnkbuf[MAXPATHLEN + 1]; 676289Smckusick int pathlen; 684610Smckusick 694837Smckusic #define INOHASH(val) (val % MAXINO) 704837Smckusic struct inotab { 714837Smckusic struct inotab *t_next; 724610Smckusick ino_t t_ino; 734610Smckusick daddr_t t_seekpt; 744837Smckusic } *inotab[MAXINO]; 754610Smckusick 764837Smckusic #define XISDIR 1 774610Smckusick #define XTRACTD 2 784610Smckusick #define XINUSE 4 794837Smckusic #define XLINKED 8 804610Smckusick struct xtrlist { 814837Smckusic struct xtrlist *x_next; 824837Smckusic struct xtrlist *x_linkedto; 834843Smckusic time_t x_timep[2]; 844837Smckusic ino_t x_ino; 854837Smckusic char x_flags; 864843Smckusic char x_name[1]; 874843Smckusic /* actually longer */ 884837Smckusic } *xtrlist[MAXINO]; 894776Smckusic int xtrcnt = 0; 904610Smckusick 915327Smckusic char *dumpmap; 925327Smckusic char *clrimap; 934610Smckusick 945327Smckusic char clearedbuf[MAXBSIZE]; 955327Smckusic 964837Smckusic extern char *ctime(); 97*6846Smckusick extern int seek(); 984843Smckusic ino_t search(); 995943Smckusic int dirwrite(); 1004610Smckusick 101*6846Smckusick main(argc, argv) 1024700Smckusic int argc; 1034700Smckusic char *argv[]; 1044610Smckusick { 1054610Smckusick register char *cp; 1064610Smckusick char command; 1074700Smckusic int (*signal())(); 1084610Smckusick int done(); 1094610Smckusick 1104843Smckusic if (signal(SIGINT, done) == SIG_IGN) 1114843Smckusic signal(SIGINT, SIG_IGN); 1124843Smckusic if (signal(SIGTERM, done) == SIG_IGN) 1134843Smckusic signal(SIGTERM, SIG_IGN); 1146844Smckusick mktemp(dirfile); 1154610Smckusick if (argc < 2) { 1164610Smckusick usage: 1174837Smckusic fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n"); 1184700Smckusic done(1); 1194610Smckusick } 1204610Smckusick argv++; 1214610Smckusick argc -= 2; 1224610Smckusick for (cp = *argv++; *cp; cp++) { 1234610Smckusick switch (*cp) { 1244610Smckusick case '-': 1254610Smckusick break; 1264610Smckusick case 'f': 1274610Smckusick magtape = *argv++; 1284610Smckusick argc--; 1294610Smckusick break; 1304610Smckusick /* s dumpnum (skip to) for multifile dump tapes */ 1314610Smckusick case 's': 1324610Smckusick dumpnum = atoi(*argv++); 1334610Smckusick if(dumpnum <= 0) { 1344700Smckusic fprintf(stderr, "Dump number must be a positive integer\n"); 1354700Smckusic done(1); 1364610Smckusick } 1374610Smckusick argc--; 1384610Smckusick break; 1394610Smckusick case 'h': 1404610Smckusick hflag++; 1414610Smckusick break; 1424610Smckusick case 'm': 1434610Smckusick mflag++; 1444610Smckusick break; 1454610Smckusick case 'r': 1464610Smckusick case 'R': 1476844Smckusick hflag++; 1486844Smckusick mflag++; 1494610Smckusick case 't': 1504610Smckusick case 'x': 1514610Smckusick command = *cp; 1524610Smckusick break; 1534610Smckusick default: 1544700Smckusic fprintf(stderr, "Bad key character %c\n", *cp); 1554610Smckusick goto usage; 1564610Smckusick } 1574610Smckusick } 1584610Smckusick doit(command, argc, argv); 1594700Smckusic done(0); 1604610Smckusick } 1614610Smckusick 1624610Smckusick doit(command, argc, argv) 1634700Smckusic char command; 1644700Smckusic int argc; 1654700Smckusic char *argv[]; 1664610Smckusick { 1675038Smckusic struct mtop tcom; 1685038Smckusic 1694610Smckusick if ((mt = open(magtape, 0)) < 0) { 1704700Smckusic fprintf(stderr, "%s: cannot open tape\n", magtape); 1714700Smckusic done(1); 1724610Smckusick } 1734843Smckusic if (dumpnum != 1) { 1744610Smckusick tcom.mt_op = MTFSF; 1754610Smckusick tcom.mt_count = dumpnum -1; 1764843Smckusic if (ioctl(mt,MTIOCTOP,&tcom) < 0) 1774610Smckusick perror("ioctl MTFSF"); 1784610Smckusick } 179*6846Smckusick blkclr(clearedbuf, (long)MAXBSIZE); 1804610Smckusick switch(command) { 1814610Smckusick case 't': 1824610Smckusick if (readhdr(&spcl) == 0) { 1834700Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 1844700Smckusic done(1); 1854610Smckusick } 1864843Smckusic fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 1874843Smckusic fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 1884610Smckusick return; 1896844Smckusick case 'R': 1906844Smckusick case 'r': 1916844Smckusick setdir(*argv); 1926844Smckusick argc = 1; 1936844Smckusick *argv = "."; 1946844Smckusick /* and then extract it all */ 1954610Smckusick case 'x': 1966844Smckusick df = fopen(dirfile, "w"); 1976844Smckusick if (df == 0) { 1986844Smckusick fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile); 1996844Smckusick done(1); 2006844Smckusick } 2014837Smckusic extractfiles(argc, argv); 2024837Smckusic return; 2034837Smckusic } 2044837Smckusic } 2054837Smckusic 2064837Smckusic extractfiles(argc, argv) 2074837Smckusic int argc; 2084837Smckusic char **argv; 2094837Smckusic { 2104843Smckusic char *ststore(); 2114837Smckusic register struct xtrlist *xp; 2124837Smckusic struct xtrlist **xpp; 2134837Smckusic ino_t d; 2146289Smckusick int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), 2156289Smckusick xtrlnkfile(), xtrlnkskip(), null(); 2166845Smckusick int mode, uid, gid, i; 2174843Smckusic char name[BUFSIZ + 1]; 2186844Smckusick struct stat stbuf; 2194837Smckusic 2206844Smckusick if (stat(".", &stbuf) < 0) { 2216844Smckusick fprintf(stderr, "cannot stat .\n"); 2226844Smckusick done(1); 2236844Smckusick } 2246844Smckusick /* 2256844Smckusick * should be!!! 2266844Smckusick * 2276844Smckusick fssize = stbuf.st_blksize; 2286844Smckusick */ 2296844Smckusick fssize = MAXBSIZE; 2304837Smckusic if (readhdr(&spcl) == 0) { 2314837Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2324837Smckusic done(1); 2334837Smckusic } 2344837Smckusic if (checkvol(&spcl, 1) == 0) { 2354837Smckusic fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2364837Smckusic } 2376844Smckusick clrimap = 0; 2386844Smckusick dumpmap = 0; 2395038Smckusic pass1(1); /* This sets the various maps on the way by */ 2404843Smckusic while (argc--) { 2414837Smckusic if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { 2426844Smckusick printf("d = %d\n", d); 2434843Smckusic fprintf(stdout, "%s: not on tape\n", *argv++); 2444837Smckusic continue; 2454610Smckusick } 2464843Smckusic if (mflag) 2474843Smckusic checkdir(*argv); 2484837Smckusic if(hflag) 2494837Smckusic getleaves(d, *argv++); 2504843Smckusic else 2514843Smckusic allocxtr(d, *argv++, XINUSE); 2524837Smckusic } 2534843Smckusic if (dumpnum > 1) { 2545038Smckusic /* 2555038Smckusic * if this is a multi-dump tape we always start with 2565038Smckusic * volume 1, so as to avoid accidentally restoring 2575038Smckusic * from a different dump! 2585038Smckusic */ 2595038Smckusic resetmt(); 2605038Smckusic dumpnum = 1; 2615038Smckusic volno = 1; 2625038Smckusic readhdr(&spcl); 2635038Smckusic goto rbits; 2644837Smckusic } 2655038Smckusic newvol: 2665038Smckusic resetmt(); 2674610Smckusick getvol: 2685038Smckusic fprintf(stderr, "Mount desired tape volume; Specify volume #: "); 2694837Smckusic if (gets(tbf) == NULL) 2704837Smckusic return; 2714837Smckusic volno = atoi(tbf); 2724837Smckusic if (volno <= 0) { 2734837Smckusic fprintf(stderr, "Volume numbers are positive numerics\n"); 2744837Smckusic goto getvol; 2754837Smckusic } 2764837Smckusic if (readhdr(&spcl) == 0) { 2774837Smckusic fprintf(stderr, "tape is not dump tape\n"); 2784837Smckusic goto newvol; 2794837Smckusic } 2804837Smckusic if (checkvol(&spcl, volno) == 0) { 2814837Smckusic fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); 2824837Smckusic goto newvol; 2834837Smckusic } 2844610Smckusick rbits: 2854837Smckusic while (gethead(&spcl) == 0) 2864837Smckusic ; 2874837Smckusic if (checktype(&spcl, TS_INODE) == 1) { 2884837Smckusic fprintf(stderr, "Can't find inode mask!\n"); 2894837Smckusic goto newvol; 2904837Smckusic } 2914837Smckusic if (checktype(&spcl, TS_BITS) == 0) 2924837Smckusic goto rbits; 2936844Smckusick readbits(&dumpmap); 2944837Smckusic while (xtrcnt > 0) { 2954837Smckusic again: 2966845Smckusick if (ishead(&spcl) == 0) { 2976845Smckusick i = 0; 2984837Smckusic while(gethead(&spcl) == 0) 2996845Smckusick i++; 3006845Smckusick fprintf(stderr, "resync restor, skipped %i blocks\n", 3016845Smckusick i); 3026845Smckusick } 3034837Smckusic if (checktype(&spcl, TS_END) == 1) { 3044837Smckusic fprintf(stderr, "end of tape\n"); 3054837Smckusic break; 3064610Smckusick } 3074837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 3084837Smckusic gethead(&spcl); 3094837Smckusic goto again; 3104610Smckusick } 3114837Smckusic d = spcl.c_inumber; 3124837Smckusic for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { 3134837Smckusic if (d != xp->x_ino) 3144837Smckusic continue; 3154837Smckusic if (xp->x_flags & XLINKED) 3164837Smckusic continue; 3174837Smckusic xp->x_timep[0] = spcl.c_dinode.di_atime; 3184837Smckusic xp->x_timep[1] = spcl.c_dinode.di_mtime; 3194837Smckusic mode = spcl.c_dinode.di_mode; 3204837Smckusic if (mflag) 3214843Smckusic strcpy(name, xp->x_name); 3224837Smckusic else 3234837Smckusic sprintf(name, "%u", xp->x_ino); 3244837Smckusic switch (mode & IFMT) { 3254837Smckusic default: 3264843Smckusic fprintf(stderr, "%s: unknown file type\n", name); 3274837Smckusic xp->x_flags |= XTRACTD; 3284837Smckusic xtrcnt--; 3294837Smckusic goto skipfile; 3304837Smckusic case IFCHR: 3314837Smckusic case IFBLK: 3324843Smckusic fprintf(stdout, "extract special file %s\n", name); 3336844Smckusick if (mknod(name, mode, spcl.c_dinode.di_rdev)) { 3344837Smckusic fprintf(stderr, "%s: cannot create special file\n", name); 3354837Smckusic xp->x_flags |= XTRACTD; 3364837Smckusic xtrcnt--; 3374837Smckusic goto skipfile; 3384776Smckusic } 3394837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3404837Smckusic break; 3414837Smckusic case IFDIR: 3424837Smckusic if (mflag) { 3434843Smckusic fprintf(stdout, "extract directory %s\n", name); 3444837Smckusic strncat(name, "/.", BUFSIZ); 3454843Smckusic checkdir(name); 3466844Smckusick chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3474837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3484837Smckusic break; 3494610Smckusick } 3505038Smckusic fprintf(stdout, "extract file %s\n", name); 3516844Smckusick if ((ofile = creat(name, 0666)) < 0) { 3525038Smckusic fprintf(stderr, "%s: cannot create file\n", name); 3535038Smckusic xp->x_flags |= XTRACTD; 3545038Smckusic xtrcnt--; 3555038Smckusic goto skipfile; 3565038Smckusic } 3576844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3585943Smckusic if (cvtdir) { 3595038Smckusic getfile(xtrcvtdir, xtrcvtskip, 3605038Smckusic spcl.c_dinode.di_size); 3615943Smckusic flushent(xtrfile); 3625943Smckusic } else 3635038Smckusic getfile(xtrfile, xtrskip, 3645038Smckusic spcl.c_dinode.di_size); 3656844Smckusick close(ofile); 3665038Smckusic break; 3676289Smckusick case IFLNK: 3686289Smckusick fprintf(stdout, "extract symbolic link %s\n", name); 3696289Smckusick uid = spcl.c_dinode.di_uid; 3706289Smckusick gid = spcl.c_dinode.di_gid; 3716289Smckusick lnkbuf[0] = '\0'; 3726289Smckusick pathlen = 0; 3736289Smckusick getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size); 3746844Smckusick if (symlink(lnkbuf, name) < 0) { 3756289Smckusick fprintf(stderr, "%s: cannot create symbolic link\n", name); 3766289Smckusick xp->x_flags |= XTRACTD; 3776289Smckusick xtrcnt--; 3786289Smckusick goto finished; 3796289Smckusick } 3806844Smckusick chown(name, uid, gid); 3816289Smckusick break; 3824837Smckusic case IFREG: 3834843Smckusic fprintf(stdout, "extract file %s\n", name); 3846844Smckusick if ((ofile = creat(name, 0666)) < 0) { 3854837Smckusic fprintf(stderr, "%s: cannot create file\n", name); 3864837Smckusic xp->x_flags |= XTRACTD; 3874837Smckusic xtrcnt--; 3884837Smckusic goto skipfile; 3894837Smckusic } 3906844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3915038Smckusic getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); 3926844Smckusick close(ofile); 3934837Smckusic break; 3944610Smckusick } 3956844Smckusick chmod(name, mode); 3966844Smckusick utime(name, xp->x_timep); 3974837Smckusic xp->x_flags |= XTRACTD; 3984837Smckusic xtrcnt--; 3994837Smckusic goto finished; 4004837Smckusic } 4014837Smckusic skipfile: 4024837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4034700Smckusic finished: 4044837Smckusic ; 4054837Smckusic } 4064837Smckusic if (xtrcnt == 0 && !mflag) 4074837Smckusic return; 4084837Smckusic for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { 4094837Smckusic for (xp = *xpp; xp; xp = xp->x_next) { 4104837Smckusic if (mflag && (xp->x_flags & XISDIR)) 4116844Smckusick utime(xp->x_name, xp->x_timep); 4124837Smckusic if (xp->x_flags & XTRACTD) 4134837Smckusic continue; 4144837Smckusic if ((xp->x_flags & XLINKED) == 0) { 4154837Smckusic fprintf(stderr, "cannot find file %s\n", 4164837Smckusic xp->x_name); 4174837Smckusic continue; 4184837Smckusic } 4194843Smckusic if (!mflag) 4204843Smckusic continue; 4214843Smckusic fprintf(stdout, "link %s to %s\n", 4224843Smckusic xp->x_linkedto->x_name, xp->x_name); 4236844Smckusick if (link(xp->x_linkedto->x_name, xp->x_name) < 0) 4244843Smckusic fprintf(stderr, "link %s to %s failed\n", 4254837Smckusic xp->x_linkedto->x_name, xp->x_name); 4264610Smckusick } 4274837Smckusic } 4284837Smckusic } 4294837Smckusic 4304610Smckusick /* 4314610Smckusick * Read the tape, bulding up a directory structure for extraction 4324610Smckusick * by name 4334610Smckusick */ 4345038Smckusic pass1(savedir) 4355038Smckusic int savedir; 4364610Smckusick { 4374776Smckusic register int i; 4384837Smckusic register struct dinode *ip; 4394837Smckusic struct direct nulldir; 4405038Smckusic char buf[TP_BSIZE]; 4415943Smckusic int putdir(), null(), dirwrite(); 4424610Smckusick 4435943Smckusic nulldir.d_ino = 1; 4445943Smckusic nulldir.d_namlen = 1; 4455943Smckusic strncpy(nulldir.d_name, "/", nulldir.d_namlen); 4465943Smckusic nulldir.d_reclen = DIRSIZ(&nulldir); 4474610Smckusick while (gethead(&spcl) == 0) { 4484700Smckusic fprintf(stderr, "Can't find directory header!\n"); 4494610Smckusick } 4504610Smckusick for (;;) { 4514610Smckusick if (checktype(&spcl, TS_BITS) == 1) { 4526844Smckusick readbits(&dumpmap); 4534610Smckusick continue; 4544610Smckusick } 4554610Smckusick if (checktype(&spcl, TS_CLRI) == 1) { 4566844Smckusick readbits(&clrimap); 4574610Smckusick continue; 4584610Smckusick } 4594610Smckusick if (checktype(&spcl, TS_INODE) == 0) { 4604610Smckusick finish: 4615943Smckusic if (savedir) { 4625943Smckusic fclose(df); 4635943Smckusic dirp = opendir(dirfile); 4645943Smckusic if (dirp == NULL) 4655943Smckusic perror("opendir"); 4665943Smckusic } 4675038Smckusic resetmt(); 4684610Smckusick return; 4694610Smckusick } 4704610Smckusick ip = &spcl.c_dinode; 4714610Smckusick i = ip->di_mode & IFMT; 4724610Smckusick if (i != IFDIR) { 4734610Smckusick goto finish; 4744610Smckusick } 4755038Smckusic if (spcl.c_inumber == ROOTINO) { 4765038Smckusic readtape(buf); 4775038Smckusic bct--; /* push back this block */ 4785038Smckusic if (((struct direct *)buf)->d_ino != ROOTINO) { 4795038Smckusic if (((struct odirect *)buf)->d_ino != ROOTINO) { 4805038Smckusic fprintf(stderr, "bad root directory\n"); 4815038Smckusic done(1); 4825038Smckusic } 4835038Smckusic fprintf(stderr, "converting to new directory format\n"); 4845038Smckusic cvtdir = 1; 4855038Smckusic } 4865038Smckusic if (!savedir && !cvtdir) { 4875038Smckusic /* if no conversion, just return */ 4885038Smckusic goto finish; 4895038Smckusic } 4905038Smckusic } 4914843Smckusic allocinotab(spcl.c_inumber, seekpt); 4925038Smckusic if (savedir) { 4935038Smckusic getfile(putdir, null, spcl.c_dinode.di_size); 4945943Smckusic putent(&nulldir, dirwrite); 4955943Smckusic flushent(dirwrite); 4965038Smckusic } else { 4975038Smckusic getfile(null, null, spcl.c_dinode.di_size); 4985038Smckusic } 4994610Smckusick } 5004610Smckusick } 5014610Smckusick 5024610Smckusick /* 5034843Smckusic * Put the directory entries in the directory file 5044843Smckusic */ 5054843Smckusic putdir(buf, size) 5064843Smckusic char *buf; 5074843Smckusic int size; 5084843Smckusic { 5095038Smckusic struct direct cvtbuf; 5105038Smckusic register struct odirect *odp; 5115038Smckusic struct odirect *eodp; 5124843Smckusic register struct direct *dp; 5136289Smckusick long loc, i; 5144843Smckusic 5155038Smckusic if (cvtdir) { 5165038Smckusic eodp = (struct odirect *)&buf[size]; 5175038Smckusic for (odp = (struct odirect *)buf; odp < eodp; odp++) 5185038Smckusic if (odp->d_ino != 0) { 5195038Smckusic dcvt(odp, &cvtbuf); 5205943Smckusic putent(&cvtbuf, dirwrite); 5215038Smckusic } 5225038Smckusic } else { 5235943Smckusic for (loc = 0; loc < size; ) { 5245943Smckusic dp = (struct direct *)(buf + loc); 5256289Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 5266289Smckusick if (dp->d_reclen <= 0 || dp->d_reclen > i) { 5276289Smckusick loc += i; 5286289Smckusick continue; 5296289Smckusick } 5306289Smckusick loc += dp->d_reclen; 5315038Smckusic if (dp->d_ino != 0) 5325943Smckusic putent(dp, dirwrite); 5335943Smckusic } 5345038Smckusic } 5354843Smckusic } 5364843Smckusic 5374843Smckusic /* 5384843Smckusic * Recursively find names and inumbers of all files in subtree 5394843Smckusic * pname and put them in xtrlist[] 5404843Smckusic */ 5414843Smckusic getleaves(ino, pname) 5424843Smckusic ino_t ino; 5434843Smckusic char *pname; 5444843Smckusic { 5454843Smckusic register struct inotab *itp; 5464843Smckusic int namelen; 547*6846Smckusick daddr_t bpt; 5485943Smckusic register struct direct *dp; 5495943Smckusic char locname[BUFSIZ + 1]; 5504843Smckusic 5514843Smckusic if (BIT(ino, dumpmap) == 0) { 5524843Smckusic fprintf(stdout, "%s: not on the tape\n", pname); 5534843Smckusic return; 5544843Smckusic } 5554843Smckusic for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { 5564843Smckusic if (itp->t_ino != ino) 5574843Smckusic continue; 5584843Smckusic /* 5594843Smckusic * pname is a directory name 5604843Smckusic */ 5614843Smckusic allocxtr(ino, pname, XISDIR); 5624843Smckusic /* 5634843Smckusic * begin search through the directory 5644843Smckusic * skipping over "." and ".." 5654843Smckusic */ 5664843Smckusic strncpy(locname, pname, BUFSIZ); 5674843Smckusic strncat(locname, "/", BUFSIZ); 5684843Smckusic namelen = strlen(locname); 5695943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 5705943Smckusic dp = readdir(dirp); 5715943Smckusic dp = readdir(dirp); 5725943Smckusic dp = readdir(dirp); 5735943Smckusic bpt = telldir(dirp); 5744843Smckusic /* 5754843Smckusic * "/" signals end of directory 5764843Smckusic */ 5775943Smckusic while (dp->d_namlen != 1 || dp->d_name[0] != '/') { 5784843Smckusic locname[namelen] = '\0'; 5795943Smckusic if (namelen + dp->d_namlen >= BUFSIZ) { 5805943Smckusic fprintf(stderr, "%s%s: name exceedes %d char\n", 5815943Smckusic locname, dp->d_name, BUFSIZ); 5824843Smckusic continue; 5834843Smckusic } 5845943Smckusic strncat(locname, dp->d_name, dp->d_namlen); 5855943Smckusic getleaves(dp->d_ino, locname); 5865943Smckusic seekdir(dirp, bpt, itp->t_seekpt); 5875943Smckusic dp = readdir(dirp); 5885943Smckusic bpt = telldir(dirp); 5894843Smckusic } 5904843Smckusic return; 5914843Smckusic } 5924843Smckusic /* 5934843Smckusic * locname is name of a simple file 5944843Smckusic */ 5954843Smckusic allocxtr(ino, pname, XINUSE); 5964843Smckusic } 5974843Smckusic 5984843Smckusic /* 5994843Smckusic * Search the directory tree rooted at inode ROOTINO 6004843Smckusic * for the path pointed at by n 6014843Smckusic */ 6024843Smckusic psearch(n) 6034843Smckusic char *n; 6044843Smckusic { 6054843Smckusic register char *cp, *cp1; 6064843Smckusic char c; 6074843Smckusic 6084843Smckusic ino = ROOTINO; 6094843Smckusic if (*(cp = n) == '/') 6104843Smckusic cp++; 6114843Smckusic next: 6124843Smckusic cp1 = cp + 1; 6134843Smckusic while (*cp1 != '/' && *cp1) 6144843Smckusic cp1++; 6154843Smckusic c = *cp1; 6164843Smckusic *cp1 = 0; 6174843Smckusic ino = search(ino, cp); 6184843Smckusic if (ino == 0) { 6194843Smckusic *cp1 = c; 6204843Smckusic return(0); 6214843Smckusic } 6224843Smckusic *cp1 = c; 6234843Smckusic if (c == '/') { 6244843Smckusic cp = cp1+1; 6254843Smckusic goto next; 6264843Smckusic } 6274843Smckusic return(ino); 6284843Smckusic } 6294843Smckusic 6304843Smckusic /* 6314843Smckusic * search the directory inode ino 6324843Smckusic * looking for entry cp 6334843Smckusic */ 6344843Smckusic ino_t 6354843Smckusic search(inum, cp) 6364843Smckusic ino_t inum; 6374843Smckusic char *cp; 6384843Smckusic { 6395943Smckusic register struct direct *dp; 6404843Smckusic register struct inotab *itp; 6415943Smckusic int len; 6424843Smckusic 6434843Smckusic for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) 6444843Smckusic if (itp->t_ino == inum) 6454843Smckusic goto found; 6464843Smckusic return(0); 6474843Smckusic found: 6485943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 6495943Smckusic len = strlen(cp); 6504843Smckusic do { 6515943Smckusic dp = readdir(dirp); 6525943Smckusic if (dp->d_namlen == 1 && dp->d_name[0] == '/') 6534843Smckusic return(0); 6545943Smckusic } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len)); 6555943Smckusic return(dp->d_ino); 6564843Smckusic } 6574843Smckusic 6584843Smckusic /* 6594610Smckusick * Do the file extraction, calling the supplied functions 6604610Smckusick * with the blocks 6614610Smckusick */ 6624700Smckusic getfile(f1, f2, size) 6634700Smckusic int (*f2)(), (*f1)(); 664*6846Smckusick off_t size; 6654610Smckusick { 6664776Smckusic register int i; 6675327Smckusic char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 6684837Smckusic union u_spcl addrblk; 6694837Smckusic # define addrblock addrblk.s_spcl 6704610Smckusick 6714837Smckusic addrblock = spcl; 6724610Smckusick for (;;) { 6734837Smckusic for (i = 0; i < addrblock.c_count; i++) { 6744837Smckusic if (addrblock.c_addr[i]) { 6754776Smckusic readtape(&buf[curblk++][0]); 6766844Smckusick if (curblk == fssize / TP_BSIZE) { 6774776Smckusic (*f1)(buf, size > TP_BSIZE ? 6786844Smckusick (long) (fssize) : 6794776Smckusic (curblk - 1) * TP_BSIZE + size); 6804776Smckusic curblk = 0; 6814776Smckusic } 6825327Smckusic } else { 6834776Smckusic if (curblk > 0) { 6844776Smckusic (*f1)(buf, size > TP_BSIZE ? 6854776Smckusic (long) (curblk * TP_BSIZE) : 6864776Smckusic (curblk - 1) * TP_BSIZE + size); 6874776Smckusic curblk = 0; 6884776Smckusic } 6895327Smckusic (*f2)(clearedbuf, size > TP_BSIZE ? 6905327Smckusic (long) TP_BSIZE : size); 6914610Smckusick } 6924776Smckusic if ((size -= TP_BSIZE) <= 0) { 6934610Smckusick eloop: 6944610Smckusick while (gethead(&spcl) == 0) 6954610Smckusick ; 6964610Smckusick if (checktype(&spcl, TS_ADDR) == 1) 6974610Smckusick goto eloop; 6984776Smckusic goto out; 6994610Smckusick } 7004610Smckusick } 7014837Smckusic if (gethead(&addrblock) == 0) { 7024776Smckusic fprintf(stderr, "Missing address (header) block, ino%u\n", ino); 7034700Smckusic goto eloop; 7044700Smckusic } 7054837Smckusic if (checktype(&addrblock, TS_ADDR) == 0) { 7064837Smckusic spcl = addrblock; 7074776Smckusic goto out; 7084700Smckusic } 7094610Smckusick } 7104776Smckusic out: 7114776Smckusic if (curblk > 0) { 7124776Smckusic (*f1)(buf, (curblk * TP_BSIZE) + size); 7134776Smckusic curblk = 0; 7144776Smckusic } 7154610Smckusick } 7164610Smckusick 7174610Smckusick /* 7184843Smckusic * The next routines are called during file extraction to 7194843Smckusic * put the data into the right form and place. 7204843Smckusic */ 7214843Smckusic xtrfile(buf, size) 7224843Smckusic char *buf; 7234843Smckusic long size; 7244843Smckusic { 7256844Smckusick if (write(ofile, buf, (int) size) == -1) { 7265038Smckusic perror("extract write"); 7274843Smckusic done(1); 7284843Smckusic } 7294843Smckusic } 7304843Smckusic 7315038Smckusic xtrskip(buf, size) 7324843Smckusic char *buf; 7334843Smckusic long size; 7344843Smckusic { 735*6846Smckusick #ifdef lint 736*6846Smckusick buf = buf; 737*6846Smckusick #endif 7386844Smckusick if (lseek(ofile, size, 1) == -1) { 7395038Smckusic perror("extract seek"); 7404843Smckusic done(1); 7414843Smckusic } 7424843Smckusic } 7435038Smckusic 7445038Smckusic xtrcvtdir(buf, size) 7455038Smckusic struct odirect *buf; 7465038Smckusic long size; 7475038Smckusic { 7485038Smckusic struct odirect *odp, *edp; 749*6846Smckusick struct direct cvtbuf; 7505038Smckusic 7515038Smckusic edp = &buf[size / sizeof(struct odirect)]; 7525943Smckusic for (odp = buf; odp < edp; odp++) { 7535943Smckusic dcvt(odp, &cvtbuf); 7545943Smckusic putent(&cvtbuf, xtrfile); 7555038Smckusic } 7565038Smckusic } 7575038Smckusic 7585038Smckusic xtrcvtskip(buf, size) 7595038Smckusic char *buf; 7605038Smckusic long size; 7615038Smckusic { 7625038Smckusic fprintf(stderr, "unallocated block in directory\n"); 7635943Smckusic xtrskip(buf, size); 7645038Smckusic } 7656289Smckusick 7666289Smckusick xtrlnkfile(buf, size) 7676289Smckusick char *buf; 7686289Smckusick long size; 7696289Smckusick { 7706289Smckusick pathlen += size; 7716289Smckusick if (pathlen > MAXPATHLEN) { 7726289Smckusick fprintf(stderr, "symbolic link name: %s; too long %d\n", 7736289Smckusick buf, size); 7746289Smckusick done(1); 7756289Smckusick } 7766289Smckusick strcat(lnkbuf, buf); 7776289Smckusick } 7786289Smckusick 7796289Smckusick xtrlnkskip(buf, size) 7806289Smckusick char *buf; 7816289Smckusick long size; 7826289Smckusick { 783*6846Smckusick #ifdef lint 784*6846Smckusick buf = buf, size = size; 785*6846Smckusick #endif 7866289Smckusick fprintf(stderr, "unallocated block in symbolic link\n"); 7876289Smckusick done(1); 7886289Smckusick } 7894843Smckusic 7904843Smckusic null() {;} 7914843Smckusic 7924843Smckusic /* 7934776Smckusic * Do the tape i/o, dealing with volume changes 7944610Smckusick * etc.. 7954610Smckusick */ 7964610Smckusick readtape(b) 7974700Smckusic char *b; 7984610Smckusick { 799*6846Smckusick register long i; 8004837Smckusic struct s_spcl tmpbuf; 8016845Smckusick char c; 8024610Smckusick 8034610Smckusick if (bct >= NTREC) { 8044610Smckusick for (i = 0; i < NTREC; i++) 8054776Smckusic ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; 8064610Smckusick bct = 0; 8074776Smckusic if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { 8086845Smckusick fprintf(stderr, "Tape read error, continue?"); 8096845Smckusick do { 8106845Smckusick fprintf(stderr, "[yn]\n"); 8116845Smckusick c = getchar(); 8126845Smckusick while (getchar() != '\n') 8136845Smckusick /* void */; 8146845Smckusick } while (c != 'y' && c != 'n'); 8154610Smckusick eflag++; 8166845Smckusick if (c == 'n') 8176845Smckusick done(1); 8186845Smckusick i = NTREC*TP_BSIZE; 8196845Smckusick blkclr(tbf, i); 820*6846Smckusick if (lseek(mt, i, 1) < 0) { 821*6846Smckusick fprintf(stderr, "continuation failed\n"); 822*6846Smckusick done(1); 823*6846Smckusick } 8244610Smckusick } 8254610Smckusick if (i == 0) { 8264610Smckusick bct = NTREC + 1; 8274610Smckusick volno++; 8284610Smckusick loop: 8294610Smckusick flsht(); 8304610Smckusick close(mt); 8314700Smckusic fprintf(stderr, "Mount volume %d\n", volno); 8324610Smckusick while (getchar() != '\n') 8334610Smckusick ; 8344610Smckusick if ((mt = open(magtape, 0)) == -1) { 8354700Smckusic fprintf(stderr, "Cannot open tape!\n"); 8364610Smckusick goto loop; 8374610Smckusick } 8384610Smckusick if (readhdr(&tmpbuf) == 0) { 8394700Smckusic fprintf(stderr, "Not a dump tape.Try again\n"); 8404610Smckusick goto loop; 8414610Smckusick } 8424610Smckusick if (checkvol(&tmpbuf, volno) == 0) { 8434700Smckusic fprintf(stderr, "Wrong tape. Try again\n"); 8444610Smckusick goto loop; 8454610Smckusick } 8464610Smckusick readtape(b); 8474610Smckusick return; 8484610Smckusick } 8494610Smckusick } 850*6846Smckusick blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); 8514610Smckusick } 8524610Smckusick 8534610Smckusick flsht() 8544610Smckusick { 8554610Smckusick bct = NTREC+1; 8564610Smckusick } 8574610Smckusick 8585943Smckusic blkcpy(from, to, size) 8595943Smckusic char *from, *to; 860*6846Smckusick long size; 8614610Smckusick { 862*6846Smckusick #ifdef lint 863*6846Smckusick from = from, to = to, size = size; 864*6846Smckusick #endif 8655943Smckusic asm(" movc3 12(ap),*4(ap),*8(ap)"); 8664610Smckusick } 8674610Smckusick 8685038Smckusic blkclr(buf, size) 8695038Smckusic char *buf; 870*6846Smckusick long size; 8715038Smckusic { 872*6846Smckusick #ifdef lint 873*6846Smckusick buf = buf, size = size; 874*6846Smckusick #endif 8755038Smckusic asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); 8765038Smckusic } 8775038Smckusic 8785038Smckusic resetmt() 8795038Smckusic { 8805038Smckusic struct mtop tcom; 8815038Smckusic 8825038Smckusic if(dumpnum > 1) 8835038Smckusic tcom.mt_op = MTBSF; 8845038Smckusic else 8855038Smckusic tcom.mt_op = MTREW; 8865038Smckusic tcom.mt_count = 1; 8875038Smckusic flsht(); 8885038Smckusic if (ioctl(mt,MTIOCTOP,&tcom) == -1) { 8895038Smckusic /* kludge for disk dumps */ 8905038Smckusic lseek(mt, (long)0, 0); 8915038Smckusic } 8925038Smckusic if (dumpnum > 1) { 8935038Smckusic tcom.mt_op = MTFSF; 8945038Smckusic tcom.mt_count = 1; 8955038Smckusic ioctl(mt,MTIOCTOP,&tcom); 8965038Smckusic } 8975038Smckusic } 8985038Smckusic 8994843Smckusic checkvol(b, t) 9004843Smckusic struct s_spcl *b; 9014843Smckusic int t; 9024610Smckusick { 9034843Smckusic if (b->c_volume == t) 9044843Smckusic return(1); 9054610Smckusick return(0); 9064610Smckusick } 9074610Smckusick 9084843Smckusic readhdr(b) 9094843Smckusic struct s_spcl *b; 9104610Smckusick { 9114843Smckusic if (gethead(b) == 0) 9124610Smckusick return(0); 9134843Smckusic if (checktype(b, TS_TAPE) == 0) 9144843Smckusic return(0); 9154843Smckusic return(1); 9164610Smckusick } 9174610Smckusick 9184610Smckusick /* 9194610Smckusick * read the tape into buf, then return whether or 9204610Smckusick * or not it is a header block. 9214610Smckusick */ 9224610Smckusick gethead(buf) 9234837Smckusic struct s_spcl *buf; 9244610Smckusick { 9254610Smckusick readtape((char *)buf); 9264837Smckusic if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) 9274610Smckusick return(0); 9284610Smckusick return(1); 9294610Smckusick } 9304610Smckusick 9314610Smckusick /* 9324610Smckusick * return whether or not the buffer contains a header block 9334610Smckusick */ 9344610Smckusick ishead(buf) 9354837Smckusic struct s_spcl *buf; 9364610Smckusick { 9374837Smckusic if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) 9384610Smckusick return(0); 9394610Smckusick return(1); 9404610Smckusick } 9414610Smckusick 9424610Smckusick checktype(b, t) 9434837Smckusic struct s_spcl *b; 9444700Smckusic int t; 9454610Smckusick { 9464837Smckusic return(b->c_type == t); 9474610Smckusick } 9484610Smckusick 9495038Smckusic /* 9505038Smckusic * read a bit mask from the tape into m. 9515038Smckusic */ 9526844Smckusick readbits(mapp) 9536844Smckusick char **mapp; 9545038Smckusic { 9555038Smckusic register int i; 9566844Smckusick char *m; 9574610Smckusick 9585038Smckusic i = spcl.c_count; 9595038Smckusic 9606844Smckusick if (*mapp == 0) 961*6846Smckusick *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS))); 9626844Smckusick m = *mapp; 9635038Smckusic while (i--) { 9645038Smckusic readtape((char *) m); 9655327Smckusic m += (TP_BSIZE/(NBBY/BITS)); 9665038Smckusic } 9675038Smckusic while (gethead(&spcl) == 0) 9685038Smckusic ; 9695038Smckusic } 9705038Smckusic 9714610Smckusick checksum(b) 9724700Smckusic int *b; 9734610Smckusick { 9744776Smckusic register int i, j; 9754610Smckusick 9764776Smckusic j = sizeof(union u_spcl) / sizeof(int); 9774610Smckusick i = 0; 9784610Smckusick do 9794610Smckusick i += *b++; 9804610Smckusick while (--j); 9814610Smckusick if (i != CHECKSUM) { 9824776Smckusic fprintf(stderr, "Checksum error %o, ino %u\n", i, ino); 9834610Smckusick return(0); 9844610Smckusick } 9854610Smckusick return(1); 9864610Smckusick } 9874610Smckusick 9884610Smckusick /* 9895038Smckusic * Check for access into each directory in the pathname of an extracted 9905038Smckusic * file and create such a directory if needed in preparation for moving 9915038Smckusic * the file to its proper home. 9925038Smckusic */ 9935038Smckusic checkdir(name) 9945038Smckusic register char *name; 9955038Smckusic { 9965038Smckusic register char *cp; 9975038Smckusic int i; 9985038Smckusic 9995038Smckusic for (cp = name; *cp; cp++) { 10005038Smckusic if (*cp == '/') { 10015038Smckusic *cp = '\0'; 10026844Smckusick if (access(name, 01) < 0) { 10035038Smckusic register int pid, rp; 10045038Smckusic 10055038Smckusic if ((pid = fork()) == 0) { 10066844Smckusick execl("/bin/mkdir", "mkdir", name, 0); 10076844Smckusick execl("/usr/bin/mkdir", "mkdir", name, 0); 10086844Smckusick fprintf(stderr, "restor: cannot find mkdir!\n"); 10095038Smckusic done(0); 10105038Smckusic } 10115038Smckusic while ((rp = wait(&i)) >= 0 && rp != pid) 10125038Smckusic ; 10135038Smckusic } 10145038Smckusic *cp = '/'; 10155038Smckusic } 10165038Smckusic } 10175038Smckusic } 10185038Smckusic 10196844Smckusick setdir(dev) 10206844Smckusick char *dev; 10216844Smckusick { 10226844Smckusick struct fstab *fsp; 10236844Smckusick 10246844Smckusick if (setfsent() == 0) { 10256844Smckusick fprintf(stderr, "Can't open checklist file: %s\n", FSTAB); 10266844Smckusick done(1); 10276844Smckusick } 10286844Smckusick while ((fsp = getfsent()) != 0) { 10296844Smckusick if (strcmp(fsp->fs_spec, dev) == 0) { 10306844Smckusick printf("%s mounted on %s\n", dev, fsp->fs_file); 10316844Smckusick if (chdir(fsp->fs_file) >= 0) 10326844Smckusick return; 10336844Smckusick fprintf(stderr, "%s cannot chdir to %s\n", 10346844Smckusick fsp->fs_file); 10356844Smckusick done(1); 10366844Smckusick } 10376844Smckusick } 10386844Smckusick fprintf(stderr, "%s not mounted\n", dev); 10396844Smckusick done(1); 10406844Smckusick } 10416844Smckusick 10425038Smckusic /* 10435943Smckusic * These variables are "local" to the following two functions. 10445943Smckusic */ 10455943Smckusic char dirbuf[DIRBLKSIZ]; 10465943Smckusic long dirloc = 0; 10475943Smckusic long prev = 0; 10485943Smckusic 10495943Smckusic /* 10505943Smckusic * add a new directory entry to a file. 10515943Smckusic */ 10525943Smckusic putent(dp, wrtfunc) 10535943Smckusic struct direct *dp; 10545943Smckusic int (*wrtfunc)(); 10555943Smckusic { 10565943Smckusic if (dp->d_ino == 0) 10575943Smckusic return; 10585943Smckusic for (;;) { 10595943Smckusic if (dp->d_reclen < DIRBLKSIZ - dirloc) { 1060*6846Smckusick blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 10615943Smckusic prev = dirloc; 10625943Smckusic dirloc += dp->d_reclen; 10635943Smckusic return; 10645943Smckusic } 10655943Smckusic ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 10665943Smckusic (*wrtfunc)(dirbuf, DIRBLKSIZ); 10675943Smckusic dirloc = 0; 10685943Smckusic } 10695943Smckusic } 10705943Smckusic 10715943Smckusic /* 10725943Smckusic * flush out a directory that is finished. 10735943Smckusic */ 10745943Smckusic flushent(wrtfunc) 10755943Smckusic int (*wrtfunc)(); 10765943Smckusic { 10775943Smckusic ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 10785943Smckusic (*wrtfunc)(dirbuf, dirloc); 10795943Smckusic dirloc = 0; 10805943Smckusic } 10815943Smckusic 10825943Smckusic dirwrite(buf, size) 10835943Smckusic char *buf; 10845943Smckusic int size; 10855943Smckusic { 10865943Smckusic fwrite(buf, 1, size, df); 10875943Smckusic seekpt = ftell(df); 10885943Smckusic } 10895943Smckusic 10905943Smckusic dcvt(odp, ndp) 10915943Smckusic register struct odirect *odp; 10925943Smckusic register struct direct *ndp; 10935943Smckusic { 1094*6846Smckusick blkclr((char *)ndp, (long)(sizeof *ndp)); 10955943Smckusic ndp->d_ino = odp->d_ino; 10965943Smckusic strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 10975943Smckusic ndp->d_namlen = strlen(ndp->d_name); 10985943Smckusic ndp->d_reclen = DIRSIZ(ndp); 10995943Smckusic /* 11005943Smckusic * this quickly calculates if this inode is a directory. 11015943Smckusic * Currently not maintained. 11025943Smckusic * 11035943Smckusic for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { 11045943Smckusic if (itp->t_ino != odp->d_ino) 11055943Smckusic continue; 11065943Smckusic ndp->d_fmt = IFDIR; 11075943Smckusic break; 11085943Smckusic } 11095943Smckusic */ 11105943Smckusic } 11115943Smckusic 11125943Smckusic /* 11136289Smckusick * Open a directory. 11146289Smckusick * Modified to allow any random file to be a legal directory. 11156289Smckusick */ 11166289Smckusick DIR * 11176289Smckusick opendir(name) 11186289Smckusick char *name; 11196289Smckusick { 11206289Smckusick register DIR *dirp; 11216289Smckusick 11226289Smckusick dirp = (DIR *)malloc(sizeof(DIR)); 11236289Smckusick dirp->dd_fd = open(name, 0); 11246289Smckusick if (dirp->dd_fd == -1) { 1125*6846Smckusick free((char *)dirp); 11266289Smckusick return NULL; 11276289Smckusick } 11286289Smckusick dirp->dd_loc = 0; 11296289Smckusick return dirp; 11306289Smckusick } 11316289Smckusick 11326289Smckusick /* 11336289Smckusick * Seek to an entry in a directory. 11345943Smckusic * Only values returned by ``telldir'' should be passed to seekdir. 11355943Smckusic * Modified to have many directories based in one file. 11365943Smckusic */ 11375943Smckusic void 11385943Smckusic seekdir(dirp, loc, base) 11395943Smckusic register DIR *dirp; 1140*6846Smckusick daddr_t loc, base; 11415943Smckusic { 11425943Smckusic if (loc == telldir(dirp)) 11435943Smckusic return; 11445943Smckusic loc -= base; 11455943Smckusic if (loc < 0) 11465943Smckusic fprintf(stderr, "bad seek pointer to seekdir %d\n", loc); 1147*6846Smckusick (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 11485943Smckusic dirp->dd_loc = loc & (DIRBLKSIZ - 1); 11495943Smckusic if (dirp->dd_loc != 0) 11505943Smckusic dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 11515943Smckusic } 11525943Smckusic 11535943Smckusic /* 11546844Smckusick * get next entry in a directory. 11554700Smckusic */ 11566844Smckusick struct direct * 11576844Smckusick readdir(dirp) 11586844Smckusick register DIR *dirp; 11594610Smckusick { 11606844Smckusick register struct direct *dp; 11614700Smckusic 11626844Smckusick for (;;) { 11636844Smckusick if (dirp->dd_loc == 0) { 11646844Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 11656844Smckusick DIRBLKSIZ); 11666844Smckusick if (dirp->dd_size <= 0) 11676844Smckusick return NULL; 11686844Smckusick } 11696844Smckusick if (dirp->dd_loc >= dirp->dd_size) { 11706844Smckusick dirp->dd_loc = 0; 11716844Smckusick continue; 11726844Smckusick } 11736844Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 11746844Smckusick if (dp->d_reclen <= 0 || 11756844Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) 11766844Smckusick return NULL; 11776844Smckusick dirp->dd_loc += dp->d_reclen; 11786844Smckusick if (dp->d_ino == 0) 11796844Smckusick continue; 11806844Smckusick return (dp); 11815948Smckusic } 11824610Smckusick } 11834610Smckusick 11844843Smckusic allocinotab(ino, seekpt) 11854837Smckusic ino_t ino; 11864843Smckusic daddr_t seekpt; 11874610Smckusick { 11884837Smckusic register struct inotab *itp; 11894776Smckusic 11904837Smckusic itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 11914837Smckusic itp->t_next = inotab[INOHASH(ino)]; 11924837Smckusic inotab[INOHASH(ino)] = itp; 11934837Smckusic itp->t_ino = ino; 11944843Smckusic itp->t_seekpt = seekpt; 11954610Smckusick } 11964610Smckusick 11974843Smckusic allocxtr(ino, name, flags) 11984837Smckusic ino_t ino; 11994843Smckusic char *name; 12004843Smckusic char flags; 12014610Smckusick { 12024843Smckusic register struct xtrlist *xp, *pxp; 12034776Smckusic 12044843Smckusic xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name)); 12054837Smckusic xp->x_next = xtrlist[INOHASH(ino)]; 12064837Smckusic xtrlist[INOHASH(ino)] = xp; 12074837Smckusic xp->x_ino = ino; 12084843Smckusic strcpy(xp->x_name, name); 12094837Smckusic xtrcnt++; 12104843Smckusic xp->x_flags = flags; 12114843Smckusic for (pxp = xp->x_next; pxp; pxp = pxp->x_next) 12124843Smckusic if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { 12134843Smckusic xp->x_flags |= XLINKED; 12144843Smckusic xp->x_linkedto = pxp; 12154843Smckusic xtrcnt--; 12164843Smckusic break; 12174843Smckusic } 12184843Smckusic if (xp->x_flags & XLINKED) 12194843Smckusic fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); 12204843Smckusic else if (xp->x_flags & XISDIR) 12214843Smckusic fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); 12224843Smckusic else 12234843Smckusic fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); 12244610Smckusick } 12254610Smckusick 12265038Smckusic done(exitcode) 12275038Smckusic int exitcode; 12284610Smckusick { 12295038Smckusic unlink(dirfile); 12305038Smckusic exit(exitcode); 12314610Smckusick } 1232