header files for vax are in their place
[unix-history] / usr / src / sbin / restore / main.c
CommitLineData
2ec3b58e 1/* Copyright (c) 1982 Regents of the University of California */
7d4dda01 2
e9039e39 3#ifndef lint
f99961a3 4char version[] = "@(#)main.c 2.10 %G%";
e9039e39 5#endif
7d4dda01
KM
6
7/* Modified to include h option (recursively extract all files within
8 * a subtree) and m option (recreate the heirarchical structure of
9 * that subtree and move extracted files to their proper homes).
10 * 8/29/80 by Mike Litzkow
11 *
e9039e39
KM
12 * Modified to work on the new file system
13 * 1/19/82 by Kirk McKusick
14 *
7d4dda01
KM
15 * Includes the s (skip files) option for use with multiple dumps on
16 * a single tape.
17 */
18
7d4dda01
KM
19#define MAXINO 3000
20#define BITS 8
21#define NCACHE 3
7d4dda01
KM
22#define SIZEINC 10
23
7d4dda01
KM
24#include <stdio.h>
25#include <signal.h>
b1001c58 26#include <fstab.h>
2ec3b58e
KM
27#ifndef SIMFS
28#include <sys/param.h>
29#include <sys/inode.h>
30#include <sys/fs.h>
31#include <dir.h>
32#include <stat.h>
33#include <dumprestor.h>
34#else
b1001c58
KM
35#include "../h/param.h"
36#include "../h/dir.h"
37#include "../h/stat.h"
38#include "../h/inode.h"
39#include "../h/fs.h"
40#include "../h/dumprestor.h"
2ec3b58e 41#endif
d2a3c486 42#include <sys/ioctl.h>
b88e54cb
KM
43#include <sys/mtio.h>
44
b45e25c0 45#define ODIRSIZ 14
b88e54cb
KM
46struct odirect {
47 u_short d_ino;
b45e25c0 48 char d_name[ODIRSIZ];
b88e54cb 49};
7d4dda01 50
b6407c9d
KM
51#define MWORD(m,i) (m[(unsigned)(i-1)/NBBY])
52#define MBIT(i) (1<<((unsigned)(i-1)%NBBY))
7d4dda01
KM
53#define BIS(i,w) (MWORD(w,i) |= MBIT(i))
54#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
55#define BIT(i,w) (MWORD(w,i) & MBIT(i))
56
e9039e39 57ino_t ino;
7d4dda01 58
f99961a3
KM
59int eflag = 0, hflag = 0, mflag = 0, vflag = 0, yflag = 0;
60int cvtflag = 0, cvtdir = 0;
7d4dda01 61
b1001c58 62long fssize;
7d4dda01
KM
63char tapename[] = "/dev/rmt8";
64char *magtape = tapename;
b88e54cb
KM
65int mt;
66int dumpnum = 1;
67int volno = 1;
68int curblk = 0;
69int bct = NTREC+1;
70char tbf[NTREC*TP_BSIZE];
7d4dda01 71
7d4dda01 72daddr_t seekpt;
0841dbb0 73FILE *df;
b45e25c0 74DIR *dirp;
0841dbb0 75int ofile;
2ec3b58e 76char dirfile[] = "/tmp/rstXXXXXX";
a6b18791
KM
77char lnkbuf[MAXPATHLEN + 1];
78int pathlen;
7d4dda01 79
0841dbb0
KM
80#define INOHASH(val) (val % MAXINO)
81struct inotab {
82 struct inotab *t_next;
7d4dda01
KM
83 ino_t t_ino;
84 daddr_t t_seekpt;
0841dbb0 85} *inotab[MAXINO];
7d4dda01 86
0841dbb0 87#define XISDIR 1
7d4dda01
KM
88#define XTRACTD 2
89#define XINUSE 4
0841dbb0 90#define XLINKED 8
7d4dda01 91struct xtrlist {
0841dbb0
KM
92 struct xtrlist *x_next;
93 struct xtrlist *x_linkedto;
0841dbb0 94 time_t x_timep[2];
bcfabedf 95 ino_t x_ino;
0841dbb0 96 char x_flags;
bcfabedf
KM
97 char x_name[1];
98 /* actually longer */
0841dbb0 99} *xtrlist[MAXINO];
19ac1bc8 100int xtrcnt = 0;
7d4dda01 101
b6407c9d
KM
102char *dumpmap;
103char *clrimap;
b6407c9d
KM
104
105char clearedbuf[MAXBSIZE];
7d4dda01 106
0841dbb0 107extern char *ctime();
e9039e39 108extern int seek();
bcfabedf 109ino_t search();
b45e25c0 110int dirwrite();
cbd23190
KM
111#ifdef RRESTOR
112char *host;
113#endif
7d4dda01 114
e9039e39 115main(argc, argv)
003a2a9e
KM
116 int argc;
117 char *argv[];
7d4dda01
KM
118{
119 register char *cp;
120 char command;
003a2a9e 121 int (*signal())();
7d4dda01
KM
122 int done();
123
bcfabedf
KM
124 if (signal(SIGINT, done) == SIG_IGN)
125 signal(SIGINT, SIG_IGN);
126 if (signal(SIGTERM, done) == SIG_IGN)
127 signal(SIGTERM, SIG_IGN);
b1001c58 128 mktemp(dirfile);
7d4dda01
KM
129 if (argc < 2) {
130usage:
0841dbb0 131 fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n");
003a2a9e 132 done(1);
7d4dda01
KM
133 }
134 argv++;
135 argc -= 2;
136 for (cp = *argv++; *cp; cp++) {
137 switch (*cp) {
138 case '-':
139 break;
d8cbdd8d
KM
140 case 'c':
141 cvtflag++;
142 break;
7d4dda01
KM
143 case 'f':
144 magtape = *argv++;
cbd23190
KM
145#ifdef RRESTOR
146 { char *index();
147 host = magtape;
148 magtape = index(host, ':');
149 if (magtape == 0) {
150nohost:
151 msg("need keyletter ``f'' and device ``host:tape''");
152 done(1);
153 }
154 *magtape++ = 0;
155 if (rmthost(host) == 0)
156 done(1);
157 }
158#endif
7d4dda01
KM
159 argc--;
160 break;
161 /* s dumpnum (skip to) for multifile dump tapes */
162 case 's':
163 dumpnum = atoi(*argv++);
2ec3b58e 164 if (dumpnum <= 0) {
003a2a9e
KM
165 fprintf(stderr, "Dump number must be a positive integer\n");
166 done(1);
7d4dda01
KM
167 }
168 argc--;
169 break;
170 case 'h':
171 hflag++;
172 break;
173 case 'm':
174 mflag++;
175 break;
f99961a3
KM
176 case 'x':
177 command = *cp;
178 /* set verbose mode by default */
179 case 'v':
180 vflag++;
181 break;
182 case 'y':
183 yflag++;
184 break;
7d4dda01
KM
185 case 'r':
186 case 'R':
b1001c58
KM
187 hflag++;
188 mflag++;
7d4dda01 189 case 't':
7d4dda01
KM
190 command = *cp;
191 break;
192 default:
003a2a9e 193 fprintf(stderr, "Bad key character %c\n", *cp);
7d4dda01
KM
194 goto usage;
195 }
196 }
cbd23190
KM
197#ifdef RRESTOR
198 if (host == 0)
199 goto nohost;
200#endif
7d4dda01 201 doit(command, argc, argv);
003a2a9e 202 done(0);
7d4dda01
KM
203}
204
205doit(command, argc, argv)
003a2a9e
KM
206 char command;
207 int argc;
208 char *argv[];
7d4dda01 209{
b88e54cb
KM
210 struct mtop tcom;
211
cbd23190
KM
212#ifdef RRESTOR
213 if ((mt = rmtopen(magtape, 0)) < 0) {
214#else
7d4dda01 215 if ((mt = open(magtape, 0)) < 0) {
cbd23190 216#endif
003a2a9e
KM
217 fprintf(stderr, "%s: cannot open tape\n", magtape);
218 done(1);
7d4dda01 219 }
bcfabedf 220 if (dumpnum != 1) {
7d4dda01
KM
221 tcom.mt_op = MTFSF;
222 tcom.mt_count = dumpnum -1;
cbd23190
KM
223#ifdef RRESTOR
224 rmtioctl(MTFSF,dumpnum - 1);
225#else
bcfabedf 226 if (ioctl(mt,MTIOCTOP,&tcom) < 0)
7d4dda01 227 perror("ioctl MTFSF");
cbd23190 228#endif
7d4dda01 229 }
e9039e39 230 blkclr(clearedbuf, (long)MAXBSIZE);
27c979b8
KM
231 if (readhdr(&spcl) == 0) {
232 bct--; /* push back this block */
233 cvtflag++;
7d4dda01 234 if (readhdr(&spcl) == 0) {
003a2a9e
KM
235 fprintf(stderr, "Tape is not a dump tape\n");
236 done(1);
7d4dda01 237 }
27c979b8
KM
238 fprintf(stderr, "Converting to new file system format.\n");
239 }
240 switch(command) {
241 case 't':
bcfabedf
KM
242 fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date));
243 fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
7d4dda01 244 return;
b1001c58
KM
245 case 'R':
246 case 'r':
247 setdir(*argv);
248 argc = 1;
249 *argv = ".";
250 /* and then extract it all */
7d4dda01 251 case 'x':
b1001c58
KM
252 df = fopen(dirfile, "w");
253 if (df == 0) {
254 fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile);
255 done(1);
256 }
0841dbb0
KM
257 extractfiles(argc, argv);
258 return;
0841dbb0 259 }
0841dbb0
KM
260}
261
0841dbb0
KM
262extractfiles(argc, argv)
263 int argc;
264 char **argv;
265{
bcfabedf 266 char *ststore();
0841dbb0
KM
267 register struct xtrlist *xp;
268 struct xtrlist **xpp;
269 ino_t d;
a6b18791
KM
270 int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(),
271 xtrlnkfile(), xtrlnkskip(), null();
1263e71f 272 int mode, uid, gid, i;
bcfabedf 273 char name[BUFSIZ + 1];
b1001c58 274 struct stat stbuf;
0841dbb0 275
b1001c58
KM
276 if (stat(".", &stbuf) < 0) {
277 fprintf(stderr, "cannot stat .\n");
278 done(1);
279 }
280 /*
281 * should be!!!
282 *
283 fssize = stbuf.st_blksize;
284 */
285 fssize = MAXBSIZE;
0841dbb0
KM
286 if (checkvol(&spcl, 1) == 0) {
287 fprintf(stderr, "Tape is not volume 1 of the dump\n");
288 }
b1001c58
KM
289 clrimap = 0;
290 dumpmap = 0;
b88e54cb 291 pass1(1); /* This sets the various maps on the way by */
bcfabedf 292 while (argc--) {
0841dbb0 293 if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) {
f99961a3 294 fprintf(stderr, "%s: not on tape\n", *argv++);
0841dbb0 295 continue;
7d4dda01 296 }
bcfabedf
KM
297 if (mflag)
298 checkdir(*argv);
2ec3b58e 299 if (hflag)
0841dbb0 300 getleaves(d, *argv++);
bcfabedf
KM
301 else
302 allocxtr(d, *argv++, XINUSE);
0841dbb0 303 }
bcfabedf 304 if (dumpnum > 1) {
b88e54cb
KM
305 /*
306 * if this is a multi-dump tape we always start with
307 * volume 1, so as to avoid accidentally restoring
308 * from a different dump!
309 */
310 resetmt();
311 dumpnum = 1;
312 volno = 1;
313 readhdr(&spcl);
314 goto rbits;
0841dbb0 315 }
b88e54cb 316newvol:
cbd23190
KM
317#ifdef RRESTOR
318 rmtclose();
319#else
2ec3b58e 320 close(mt);
cbd23190 321#endif
7d4dda01 322getvol:
b88e54cb 323 fprintf(stderr, "Mount desired tape volume; Specify volume #: ");
0841dbb0
KM
324 if (gets(tbf) == NULL)
325 return;
326 volno = atoi(tbf);
327 if (volno <= 0) {
328 fprintf(stderr, "Volume numbers are positive numerics\n");
329 goto getvol;
330 }
cbd23190
KM
331#ifdef RRESTOR
332 if ((mt = rmtopen(magtape, 0)) == -1) {
333#else
2ec3b58e 334 if ((mt = open(magtape, 0)) == -1) {
cbd23190 335#endif
2ec3b58e
KM
336 fprintf(stderr, "Cannot open tape!\n");
337 goto getvol;
338 }
339 if (dumpnum > 1)
340 resetmt();
0841dbb0
KM
341 if (readhdr(&spcl) == 0) {
342 fprintf(stderr, "tape is not dump tape\n");
343 goto newvol;
344 }
345 if (checkvol(&spcl, volno) == 0) {
346 fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume);
347 goto newvol;
348 }
7d4dda01 349rbits:
0841dbb0
KM
350 while (gethead(&spcl) == 0)
351 ;
352 if (checktype(&spcl, TS_INODE) == 1) {
353 fprintf(stderr, "Can't find inode mask!\n");
354 goto newvol;
355 }
356 if (checktype(&spcl, TS_BITS) == 0)
357 goto rbits;
b1001c58 358 readbits(&dumpmap);
0841dbb0
KM
359 while (xtrcnt > 0) {
360again:
1263e71f
KM
361 if (ishead(&spcl) == 0) {
362 i = 0;
2ec3b58e 363 while (gethead(&spcl) == 0)
1263e71f
KM
364 i++;
365 fprintf(stderr, "resync restor, skipped %i blocks\n",
366 i);
367 }
0841dbb0
KM
368 if (checktype(&spcl, TS_END) == 1) {
369 fprintf(stderr, "end of tape\n");
370 break;
7d4dda01 371 }
0841dbb0
KM
372 if (checktype(&spcl, TS_INODE) == 0) {
373 gethead(&spcl);
374 goto again;
7d4dda01 375 }
0841dbb0
KM
376 d = spcl.c_inumber;
377 for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) {
378 if (d != xp->x_ino)
379 continue;
380 if (xp->x_flags & XLINKED)
381 continue;
382 xp->x_timep[0] = spcl.c_dinode.di_atime;
383 xp->x_timep[1] = spcl.c_dinode.di_mtime;
384 mode = spcl.c_dinode.di_mode;
385 if (mflag)
bcfabedf 386 strcpy(name, xp->x_name);
0841dbb0
KM
387 else
388 sprintf(name, "%u", xp->x_ino);
389 switch (mode & IFMT) {
390 default:
2ec3b58e
KM
391 fprintf(stderr, "%s: unknown file mode 0%o\n",
392 name, mode);
0841dbb0
KM
393 xp->x_flags |= XTRACTD;
394 xtrcnt--;
395 goto skipfile;
396 case IFCHR:
397 case IFBLK:
f99961a3
KM
398 if (vflag)
399 fprintf(stdout, "extract special file %s\n", name);
b1001c58 400 if (mknod(name, mode, spcl.c_dinode.di_rdev)) {
0841dbb0
KM
401 fprintf(stderr, "%s: cannot create special file\n", name);
402 xp->x_flags |= XTRACTD;
403 xtrcnt--;
404 goto skipfile;
19ac1bc8 405 }
0841dbb0
KM
406 getfile(null, null, spcl.c_dinode.di_size);
407 break;
408 case IFDIR:
409 if (mflag) {
f99961a3
KM
410 if (vflag)
411 fprintf(stdout, "extract directory %s\n", name);
0841dbb0 412 strncat(name, "/.", BUFSIZ);
bcfabedf 413 checkdir(name);
b1001c58 414 chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
0841dbb0
KM
415 getfile(null, null, spcl.c_dinode.di_size);
416 break;
417 }
f99961a3
KM
418 if (vflag)
419 fprintf(stdout, "extract file %s\n", name);
b1001c58 420 if ((ofile = creat(name, 0666)) < 0) {
b88e54cb
KM
421 fprintf(stderr, "%s: cannot create file\n", name);
422 xp->x_flags |= XTRACTD;
423 xtrcnt--;
424 goto skipfile;
425 }
b1001c58 426 chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
b45e25c0 427 if (cvtdir) {
b88e54cb
KM
428 getfile(xtrcvtdir, xtrcvtskip,
429 spcl.c_dinode.di_size);
b45e25c0
KM
430 flushent(xtrfile);
431 } else
b88e54cb
KM
432 getfile(xtrfile, xtrskip,
433 spcl.c_dinode.di_size);
b1001c58 434 close(ofile);
b88e54cb 435 break;
a6b18791 436 case IFLNK:
f99961a3
KM
437 if (vflag)
438 fprintf(stdout, "extract symbolic link %s\n", name);
a6b18791
KM
439 uid = spcl.c_dinode.di_uid;
440 gid = spcl.c_dinode.di_gid;
441 lnkbuf[0] = '\0';
442 pathlen = 0;
443 getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size);
b1001c58 444 if (symlink(lnkbuf, name) < 0) {
a6b18791
KM
445 fprintf(stderr, "%s: cannot create symbolic link\n", name);
446 xp->x_flags |= XTRACTD;
447 xtrcnt--;
448 goto finished;
449 }
b1001c58 450 chown(name, uid, gid);
a6b18791 451 break;
0841dbb0 452 case IFREG:
f99961a3
KM
453 if (vflag)
454 fprintf(stdout, "extract file %s\n", name);
b1001c58 455 if ((ofile = creat(name, 0666)) < 0) {
0841dbb0
KM
456 fprintf(stderr, "%s: cannot create file\n", name);
457 xp->x_flags |= XTRACTD;
458 xtrcnt--;
459 goto skipfile;
7d4dda01 460 }
b1001c58 461 chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
b88e54cb 462 getfile(xtrfile, xtrskip, spcl.c_dinode.di_size);
b1001c58 463 close(ofile);
0841dbb0 464 break;
7d4dda01 465 }
b1001c58
KM
466 chmod(name, mode);
467 utime(name, xp->x_timep);
0841dbb0
KM
468 xp->x_flags |= XTRACTD;
469 xtrcnt--;
470 goto finished;
471 }
472skipfile:
473 getfile(null, null, spcl.c_dinode.di_size);
003a2a9e 474finished:
0841dbb0
KM
475 ;
476 }
477 if (xtrcnt == 0 && !mflag)
478 return;
479 for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
480 for (xp = *xpp; xp; xp = xp->x_next) {
481 if (mflag && (xp->x_flags & XISDIR))
b1001c58 482 utime(xp->x_name, xp->x_timep);
0841dbb0
KM
483 if (xp->x_flags & XTRACTD)
484 continue;
485 if ((xp->x_flags & XLINKED) == 0) {
486 fprintf(stderr, "cannot find file %s\n",
487 xp->x_name);
488 continue;
489 }
bcfabedf
KM
490 if (!mflag)
491 continue;
f99961a3
KM
492 if (vflag)
493 fprintf(stdout, "link %s to %s\n",
494 xp->x_linkedto->x_name, xp->x_name);
b1001c58 495 if (link(xp->x_linkedto->x_name, xp->x_name) < 0)
bcfabedf
KM
496 fprintf(stderr, "link %s to %s failed\n",
497 xp->x_linkedto->x_name, xp->x_name);
7d4dda01 498 }
0841dbb0
KM
499 }
500}
7d4dda01
KM
501
502/*
503 * Read the tape, bulding up a directory structure for extraction
504 * by name
505 */
b88e54cb
KM
506pass1(savedir)
507 int savedir;
7d4dda01 508{
19ac1bc8 509 register int i;
0841dbb0
KM
510 register struct dinode *ip;
511 struct direct nulldir;
b88e54cb 512 char buf[TP_BSIZE];
b45e25c0 513 int putdir(), null(), dirwrite();
7d4dda01 514
b45e25c0
KM
515 nulldir.d_ino = 1;
516 nulldir.d_namlen = 1;
517 strncpy(nulldir.d_name, "/", nulldir.d_namlen);
518 nulldir.d_reclen = DIRSIZ(&nulldir);
7d4dda01 519 while (gethead(&spcl) == 0) {
003a2a9e 520 fprintf(stderr, "Can't find directory header!\n");
7d4dda01
KM
521 }
522 for (;;) {
523 if (checktype(&spcl, TS_BITS) == 1) {
b1001c58 524 readbits(&dumpmap);
7d4dda01
KM
525 continue;
526 }
527 if (checktype(&spcl, TS_CLRI) == 1) {
b1001c58 528 readbits(&clrimap);
7d4dda01
KM
529 continue;
530 }
531 if (checktype(&spcl, TS_INODE) == 0) {
532finish:
b45e25c0
KM
533 if (savedir) {
534 fclose(df);
535 dirp = opendir(dirfile);
536 if (dirp == NULL)
537 perror("opendir");
538 }
b88e54cb 539 resetmt();
7d4dda01
KM
540 return;
541 }
542 ip = &spcl.c_dinode;
543 i = ip->di_mode & IFMT;
544 if (i != IFDIR) {
545 goto finish;
546 }
b88e54cb
KM
547 if (spcl.c_inumber == ROOTINO) {
548 readtape(buf);
549 bct--; /* push back this block */
550 if (((struct direct *)buf)->d_ino != ROOTINO) {
551 if (((struct odirect *)buf)->d_ino != ROOTINO) {
552 fprintf(stderr, "bad root directory\n");
553 done(1);
554 }
555 fprintf(stderr, "converting to new directory format\n");
556 cvtdir = 1;
d8cbdd8d 557 cvtflag = 1;
b88e54cb
KM
558 }
559 if (!savedir && !cvtdir) {
560 /* if no conversion, just return */
561 goto finish;
562 }
563 }
bcfabedf 564 allocinotab(spcl.c_inumber, seekpt);
b88e54cb
KM
565 if (savedir) {
566 getfile(putdir, null, spcl.c_dinode.di_size);
b45e25c0
KM
567 putent(&nulldir, dirwrite);
568 flushent(dirwrite);
b88e54cb
KM
569 } else {
570 getfile(null, null, spcl.c_dinode.di_size);
571 }
7d4dda01
KM
572 }
573}
7d4dda01 574
bcfabedf
KM
575/*
576 * Put the directory entries in the directory file
577 */
bcfabedf
KM
578putdir(buf, size)
579 char *buf;
580 int size;
581{
b88e54cb
KM
582 struct direct cvtbuf;
583 register struct odirect *odp;
584 struct odirect *eodp;
bcfabedf 585 register struct direct *dp;
a6b18791 586 long loc, i;
b88e54cb
KM
587
588 if (cvtdir) {
589 eodp = (struct odirect *)&buf[size];
590 for (odp = (struct odirect *)buf; odp < eodp; odp++)
591 if (odp->d_ino != 0) {
592 dcvt(odp, &cvtbuf);
b45e25c0 593 putent(&cvtbuf, dirwrite);
b88e54cb
KM
594 }
595 } else {
b45e25c0
KM
596 for (loc = 0; loc < size; ) {
597 dp = (struct direct *)(buf + loc);
a6b18791
KM
598 i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
599 if (dp->d_reclen <= 0 || dp->d_reclen > i) {
600 loc += i;
601 continue;
602 }
603 loc += dp->d_reclen;
2ec3b58e 604 if (dp->d_ino != 0) {
b45e25c0 605 putent(dp, dirwrite);
2ec3b58e 606 }
b45e25c0 607 }
b88e54cb
KM
608 }
609}
610
bcfabedf
KM
611/*
612 * Recursively find names and inumbers of all files in subtree
613 * pname and put them in xtrlist[]
614 */
615getleaves(ino, pname)
616 ino_t ino;
617 char *pname;
618{
619 register struct inotab *itp;
620 int namelen;
e9039e39 621 daddr_t bpt;
b45e25c0
KM
622 register struct direct *dp;
623 char locname[BUFSIZ + 1];
bcfabedf
KM
624
625 if (BIT(ino, dumpmap) == 0) {
f99961a3
KM
626 if (vflag)
627 fprintf(stdout, "%s: not on the tape\n", pname);
bcfabedf
KM
628 return;
629 }
630 for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) {
631 if (itp->t_ino != ino)
632 continue;
633 /*
634 * pname is a directory name
635 */
636 allocxtr(ino, pname, XISDIR);
637 /*
638 * begin search through the directory
639 * skipping over "." and ".."
640 */
641 strncpy(locname, pname, BUFSIZ);
642 strncat(locname, "/", BUFSIZ);
643 namelen = strlen(locname);
b45e25c0
KM
644 seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
645 dp = readdir(dirp);
646 dp = readdir(dirp);
647 dp = readdir(dirp);
648 bpt = telldir(dirp);
bcfabedf
KM
649 /*
650 * "/" signals end of directory
651 */
b45e25c0 652 while (dp->d_namlen != 1 || dp->d_name[0] != '/') {
bcfabedf 653 locname[namelen] = '\0';
b45e25c0
KM
654 if (namelen + dp->d_namlen >= BUFSIZ) {
655 fprintf(stderr, "%s%s: name exceedes %d char\n",
656 locname, dp->d_name, BUFSIZ);
bcfabedf
KM
657 continue;
658 }
b45e25c0
KM
659 strncat(locname, dp->d_name, dp->d_namlen);
660 getleaves(dp->d_ino, locname);
661 seekdir(dirp, bpt, itp->t_seekpt);
662 dp = readdir(dirp);
663 bpt = telldir(dirp);
bcfabedf
KM
664 }
665 return;
666 }
667 /*
668 * locname is name of a simple file
669 */
670 allocxtr(ino, pname, XINUSE);
671}
672
673/*
674 * Search the directory tree rooted at inode ROOTINO
675 * for the path pointed at by n
676 */
677psearch(n)
678 char *n;
679{
680 register char *cp, *cp1;
681 char c;
682
683 ino = ROOTINO;
684 if (*(cp = n) == '/')
685 cp++;
686next:
687 cp1 = cp + 1;
688 while (*cp1 != '/' && *cp1)
689 cp1++;
690 c = *cp1;
691 *cp1 = 0;
692 ino = search(ino, cp);
693 if (ino == 0) {
694 *cp1 = c;
695 return(0);
696 }
697 *cp1 = c;
698 if (c == '/') {
699 cp = cp1+1;
700 goto next;
701 }
702 return(ino);
703}
704
705/*
706 * search the directory inode ino
707 * looking for entry cp
708 */
709ino_t
710search(inum, cp)
711 ino_t inum;
712 char *cp;
713{
b45e25c0 714 register struct direct *dp;
bcfabedf 715 register struct inotab *itp;
b45e25c0 716 int len;
bcfabedf
KM
717
718 for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next)
719 if (itp->t_ino == inum)
720 goto found;
721 return(0);
722found:
b45e25c0
KM
723 seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
724 len = strlen(cp);
bcfabedf 725 do {
b45e25c0
KM
726 dp = readdir(dirp);
727 if (dp->d_namlen == 1 && dp->d_name[0] == '/')
bcfabedf 728 return(0);
b45e25c0
KM
729 } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len));
730 return(dp->d_ino);
bcfabedf 731}
bcfabedf 732
7d4dda01
KM
733/*
734 * Do the file extraction, calling the supplied functions
735 * with the blocks
736 */
003a2a9e
KM
737getfile(f1, f2, size)
738 int (*f2)(), (*f1)();
e9039e39 739 off_t size;
7d4dda01 740{
19ac1bc8 741 register int i;
b6407c9d 742 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
0841dbb0
KM
743 union u_spcl addrblk;
744# define addrblock addrblk.s_spcl
7d4dda01 745
0841dbb0 746 addrblock = spcl;
7d4dda01 747 for (;;) {
0841dbb0
KM
748 for (i = 0; i < addrblock.c_count; i++) {
749 if (addrblock.c_addr[i]) {
19ac1bc8 750 readtape(&buf[curblk++][0]);
b1001c58 751 if (curblk == fssize / TP_BSIZE) {
19ac1bc8 752 (*f1)(buf, size > TP_BSIZE ?
b1001c58 753 (long) (fssize) :
19ac1bc8
KM
754 (curblk - 1) * TP_BSIZE + size);
755 curblk = 0;
756 }
b6407c9d 757 } else {
19ac1bc8
KM
758 if (curblk > 0) {
759 (*f1)(buf, size > TP_BSIZE ?
760 (long) (curblk * TP_BSIZE) :
761 (curblk - 1) * TP_BSIZE + size);
762 curblk = 0;
763 }
b6407c9d
KM
764 (*f2)(clearedbuf, size > TP_BSIZE ?
765 (long) TP_BSIZE : size);
7d4dda01 766 }
19ac1bc8 767 if ((size -= TP_BSIZE) <= 0) {
7d4dda01
KM
768eloop:
769 while (gethead(&spcl) == 0)
770 ;
771 if (checktype(&spcl, TS_ADDR) == 1)
772 goto eloop;
19ac1bc8 773 goto out;
7d4dda01
KM
774 }
775 }
0841dbb0 776 if (gethead(&addrblock) == 0) {
19ac1bc8 777 fprintf(stderr, "Missing address (header) block, ino%u\n", ino);
003a2a9e
KM
778 goto eloop;
779 }
0841dbb0
KM
780 if (checktype(&addrblock, TS_ADDR) == 0) {
781 spcl = addrblock;
19ac1bc8 782 goto out;
003a2a9e 783 }
7d4dda01 784 }
19ac1bc8
KM
785out:
786 if (curblk > 0) {
787 (*f1)(buf, (curblk * TP_BSIZE) + size);
788 curblk = 0;
789 }
7d4dda01
KM
790}
791
bcfabedf
KM
792/*
793 * The next routines are called during file extraction to
794 * put the data into the right form and place.
795 */
bcfabedf
KM
796xtrfile(buf, size)
797 char *buf;
798 long size;
799{
2ec3b58e 800
b1001c58 801 if (write(ofile, buf, (int) size) == -1) {
b88e54cb 802 perror("extract write");
bcfabedf
KM
803 done(1);
804 }
805}
806
b88e54cb 807xtrskip(buf, size)
bcfabedf
KM
808 char *buf;
809 long size;
810{
2ec3b58e 811
e9039e39
KM
812#ifdef lint
813 buf = buf;
814#endif
b1001c58 815 if (lseek(ofile, size, 1) == -1) {
b88e54cb 816 perror("extract seek");
bcfabedf
KM
817 done(1);
818 }
819}
bcfabedf 820
b88e54cb
KM
821xtrcvtdir(buf, size)
822 struct odirect *buf;
823 long size;
824{
b88e54cb 825 struct odirect *odp, *edp;
e9039e39 826 struct direct cvtbuf;
b88e54cb
KM
827
828 edp = &buf[size / sizeof(struct odirect)];
b45e25c0
KM
829 for (odp = buf; odp < edp; odp++) {
830 dcvt(odp, &cvtbuf);
831 putent(&cvtbuf, xtrfile);
b88e54cb
KM
832 }
833}
834
835xtrcvtskip(buf, size)
836 char *buf;
837 long size;
838{
2ec3b58e 839
b88e54cb 840 fprintf(stderr, "unallocated block in directory\n");
b45e25c0 841 xtrskip(buf, size);
b88e54cb 842}
a6b18791
KM
843
844xtrlnkfile(buf, size)
845 char *buf;
846 long size;
847{
2ec3b58e 848
a6b18791
KM
849 pathlen += size;
850 if (pathlen > MAXPATHLEN) {
851 fprintf(stderr, "symbolic link name: %s; too long %d\n",
852 buf, size);
853 done(1);
854 }
855 strcat(lnkbuf, buf);
856}
857
858xtrlnkskip(buf, size)
859 char *buf;
860 long size;
861{
2ec3b58e 862
e9039e39
KM
863#ifdef lint
864 buf = buf, size = size;
865#endif
a6b18791
KM
866 fprintf(stderr, "unallocated block in symbolic link\n");
867 done(1);
868}
b88e54cb 869
bcfabedf
KM
870null() {;}
871
7d4dda01 872/*
19ac1bc8 873 * Do the tape i/o, dealing with volume changes
7d4dda01
KM
874 * etc..
875 */
876readtape(b)
003a2a9e 877 char *b;
7d4dda01 878{
e9039e39 879 register long i;
2ec3b58e 880 struct u_spcl tmpbuf;
1263e71f 881 char c;
7d4dda01
KM
882
883 if (bct >= NTREC) {
884 for (i = 0; i < NTREC; i++)
19ac1bc8 885 ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
7d4dda01 886 bct = 0;
cbd23190
KM
887#ifdef RRESTOR
888 if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) {
889#else
19ac1bc8 890 if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
cbd23190 891#endif
f99961a3
KM
892 fprintf(stderr, "Tape read error");
893 if (!yflag) {
894 fprintf(stderr, "continue?");
895 do {
896 fprintf(stderr, "[yn]\n");
897 c = getchar();
898 while (getchar() != '\n')
899 /* void */;
900 } while (c != 'y' && c != 'n');
901 if (c == 'n')
902 done(1);
903 }
7d4dda01 904 eflag++;
1263e71f
KM
905 i = NTREC*TP_BSIZE;
906 blkclr(tbf, i);
cbd23190
KM
907#ifdef RRESTOR
908 if (rmtseek(i, 1) < 0) {
909#else
e9039e39 910 if (lseek(mt, i, 1) < 0) {
cbd23190 911#endif
e9039e39
KM
912 fprintf(stderr, "continuation failed\n");
913 done(1);
914 }
7d4dda01
KM
915 }
916 if (i == 0) {
917 bct = NTREC + 1;
918 volno++;
919loop:
920 flsht();
cbd23190
KM
921#ifdef RRESTOR
922 rmtclose();
923#else
7d4dda01 924 close(mt);
cbd23190 925#endif
003a2a9e 926 fprintf(stderr, "Mount volume %d\n", volno);
7d4dda01
KM
927 while (getchar() != '\n')
928 ;
cbd23190
KM
929#ifdef RRESTOR
930 if ((mt = rmtopen(magtape, 0)) == -1) {
931#else
7d4dda01 932 if ((mt = open(magtape, 0)) == -1) {
cbd23190 933#endif
003a2a9e 934 fprintf(stderr, "Cannot open tape!\n");
7d4dda01
KM
935 goto loop;
936 }
937 if (readhdr(&tmpbuf) == 0) {
003a2a9e 938 fprintf(stderr, "Not a dump tape.Try again\n");
7d4dda01
KM
939 goto loop;
940 }
941 if (checkvol(&tmpbuf, volno) == 0) {
003a2a9e 942 fprintf(stderr, "Wrong tape. Try again\n");
7d4dda01
KM
943 goto loop;
944 }
945 readtape(b);
946 return;
947 }
948 }
e9039e39 949 blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
7d4dda01
KM
950}
951
952flsht()
953{
2ec3b58e 954
7d4dda01
KM
955 bct = NTREC+1;
956}
957
b45e25c0
KM
958blkcpy(from, to, size)
959 char *from, *to;
e9039e39 960 long size;
7d4dda01 961{
2ec3b58e 962
e9039e39
KM
963#ifdef lint
964 from = from, to = to, size = size;
965#endif
b45e25c0 966 asm(" movc3 12(ap),*4(ap),*8(ap)");
7d4dda01
KM
967}
968
b88e54cb
KM
969blkclr(buf, size)
970 char *buf;
e9039e39 971 long size;
b88e54cb 972{
2ec3b58e 973
e9039e39
KM
974#ifdef lint
975 buf = buf, size = size;
976#endif
b88e54cb
KM
977 asm("movc5 $0,(r0),$0,8(ap),*4(ap)");
978}
979
980resetmt()
981{
982 struct mtop tcom;
983
2ec3b58e 984 if (dumpnum > 1)
b88e54cb
KM
985 tcom.mt_op = MTBSF;
986 else
987 tcom.mt_op = MTREW;
988 tcom.mt_count = 1;
989 flsht();
cbd23190
KM
990#ifdef RRESTOR
991 if (rmtioctl(tcom.mt_op, 1) == -1) {
992 /* kludge for disk dumps */
993 rmtseek((long)0, 0);
994 }
995#else
b88e54cb
KM
996 if (ioctl(mt,MTIOCTOP,&tcom) == -1) {
997 /* kludge for disk dumps */
998 lseek(mt, (long)0, 0);
999 }
cbd23190 1000#endif
b88e54cb 1001 if (dumpnum > 1) {
cbd23190
KM
1002#ifdef RRESTOR
1003 rmtioctl(MTFSF, 1);
1004#else
b88e54cb
KM
1005 tcom.mt_op = MTFSF;
1006 tcom.mt_count = 1;
1007 ioctl(mt,MTIOCTOP,&tcom);
cbd23190 1008#endif
b88e54cb
KM
1009 }
1010}
1011
bcfabedf
KM
1012checkvol(b, t)
1013 struct s_spcl *b;
1014 int t;
7d4dda01 1015{
2ec3b58e 1016
bcfabedf
KM
1017 if (b->c_volume == t)
1018 return(1);
7d4dda01 1019 return(0);
7d4dda01
KM
1020}
1021
bcfabedf
KM
1022readhdr(b)
1023 struct s_spcl *b;
7d4dda01 1024{
2ec3b58e 1025
bcfabedf 1026 if (gethead(b) == 0)
7d4dda01 1027 return(0);
bcfabedf
KM
1028 if (checktype(b, TS_TAPE) == 0)
1029 return(0);
1030 return(1);
7d4dda01 1031}
7d4dda01 1032
7d4dda01
KM
1033/*
1034 * read the tape into buf, then return whether or
1035 * or not it is a header block.
1036 */
1037gethead(buf)
0841dbb0 1038 struct s_spcl *buf;
7d4dda01 1039{
d8cbdd8d
KM
1040 union u_ospcl {
1041 char dummy[TP_BSIZE];
1042 struct s_ospcl {
1043 int c_type;
1044 time_t c_date;
1045 time_t c_ddate;
1046 int c_volume;
1047 daddr_t c_tapea;
1048 ino_t c_inumber;
1049 int c_magic;
1050 int c_checksum;
1051 struct odinode {
1052 unsigned short odi_mode;
1053 short odi_nlink;
1054 short odi_uid;
1055 short odi_gid;
1056 off_t odi_size;
1057 daddr_t odi_rdev;
1058 char odi_addr[36];
1059 time_t odi_atime;
1060 time_t odi_mtime;
1061 time_t odi_ctime;
1062 } c_dinode;
1063 int c_count;
1064 char c_addr[TP_NINDIR];
1065 } s_ospcl;
1066 } u_ospcl;
1067
1068 if (!cvtflag) {
1069 readtape((char *)buf);
27c979b8 1070 if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == 0)
d8cbdd8d
KM
1071 return(0);
1072 return(1);
1073 }
1074 readtape((char *)(&u_ospcl.s_ospcl));
27c979b8 1075 if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
d8cbdd8d 1076 checksum((int *)(&u_ospcl.s_ospcl)) == 0)
7d4dda01 1077 return(0);
d8cbdd8d
KM
1078 blkclr((char *)buf, TP_BSIZE);
1079 buf->c_type = u_ospcl.s_ospcl.c_type;
1080 buf->c_date = u_ospcl.s_ospcl.c_date;
1081 buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
1082 buf->c_volume = u_ospcl.s_ospcl.c_volume;
1083 buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
1084 buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
27c979b8 1085 buf->c_magic = NFS_MAGIC;
d8cbdd8d
KM
1086 buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
1087 buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
1088 buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
1089 buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
1090 buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
1091 buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
1092 buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
1093 buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
1094 buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
1095 buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
1096 buf->c_count = u_ospcl.s_ospcl.c_count;
1097 blkcpy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR);
7d4dda01
KM
1098 return(1);
1099}
1100
1101/*
1102 * return whether or not the buffer contains a header block
1103 */
1104ishead(buf)
0841dbb0 1105 struct s_spcl *buf;
7d4dda01 1106{
2ec3b58e 1107
27c979b8 1108 if (buf->c_magic != NFS_MAGIC)
7d4dda01
KM
1109 return(0);
1110 return(1);
1111}
1112
1113checktype(b, t)
0841dbb0 1114 struct s_spcl *b;
003a2a9e 1115 int t;
7d4dda01 1116{
2ec3b58e 1117
0841dbb0 1118 return(b->c_type == t);
7d4dda01
KM
1119}
1120
b88e54cb
KM
1121/*
1122 * read a bit mask from the tape into m.
1123 */
b1001c58
KM
1124readbits(mapp)
1125 char **mapp;
b88e54cb
KM
1126{
1127 register int i;
b1001c58 1128 char *m;
b88e54cb
KM
1129
1130 i = spcl.c_count;
1131
b1001c58 1132 if (*mapp == 0)
e9039e39 1133 *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS)));
b1001c58 1134 m = *mapp;
b88e54cb
KM
1135 while (i--) {
1136 readtape((char *) m);
b6407c9d 1137 m += (TP_BSIZE/(NBBY/BITS));
b88e54cb
KM
1138 }
1139 while (gethead(&spcl) == 0)
1140 ;
1141}
7d4dda01
KM
1142
1143checksum(b)
d8cbdd8d 1144 register int *b;
7d4dda01 1145{
19ac1bc8 1146 register int i, j;
7d4dda01 1147
19ac1bc8 1148 j = sizeof(union u_spcl) / sizeof(int);
7d4dda01
KM
1149 i = 0;
1150 do
1151 i += *b++;
1152 while (--j);
1153 if (i != CHECKSUM) {
19ac1bc8 1154 fprintf(stderr, "Checksum error %o, ino %u\n", i, ino);
7d4dda01
KM
1155 return(0);
1156 }
1157 return(1);
1158}
1159
b88e54cb
KM
1160/*
1161 * Check for access into each directory in the pathname of an extracted
1162 * file and create such a directory if needed in preparation for moving
1163 * the file to its proper home.
1164 */
1165checkdir(name)
1166 register char *name;
1167{
1168 register char *cp;
1169 int i;
1170
1171 for (cp = name; *cp; cp++) {
1172 if (*cp == '/') {
1173 *cp = '\0';
b1001c58 1174 if (access(name, 01) < 0) {
b88e54cb
KM
1175 register int pid, rp;
1176
b88e54cb 1177 if ((pid = fork()) == 0) {
b1001c58
KM
1178 execl("/bin/mkdir", "mkdir", name, 0);
1179 execl("/usr/bin/mkdir", "mkdir", name, 0);
1180 fprintf(stderr, "restor: cannot find mkdir!\n");
b88e54cb
KM
1181 done(0);
1182 }
1183 while ((rp = wait(&i)) >= 0 && rp != pid)
1184 ;
b88e54cb
KM
1185 }
1186 *cp = '/';
1187 }
1188 }
1189}
1190
b1001c58
KM
1191setdir(dev)
1192 char *dev;
1193{
1194 struct fstab *fsp;
1195
1196 if (setfsent() == 0) {
1197 fprintf(stderr, "Can't open checklist file: %s\n", FSTAB);
1198 done(1);
1199 }
1200 while ((fsp = getfsent()) != 0) {
1201 if (strcmp(fsp->fs_spec, dev) == 0) {
f99961a3 1202 fprintf(stderr, "%s mounted on %s\n", dev, fsp->fs_file);
b1001c58
KM
1203 if (chdir(fsp->fs_file) >= 0)
1204 return;
1205 fprintf(stderr, "%s cannot chdir to %s\n",
1206 fsp->fs_file);
1207 done(1);
1208 }
1209 }
1210 fprintf(stderr, "%s not mounted\n", dev);
1211 done(1);
1212}
1213
b45e25c0
KM
1214/*
1215 * These variables are "local" to the following two functions.
1216 */
1217char dirbuf[DIRBLKSIZ];
1218long dirloc = 0;
1219long prev = 0;
1220
1221/*
1222 * add a new directory entry to a file.
1223 */
1224putent(dp, wrtfunc)
1225 struct direct *dp;
1226 int (*wrtfunc)();
1227{
2ec3b58e 1228
b45e25c0
KM
1229 if (dp->d_ino == 0)
1230 return;
2ec3b58e
KM
1231 if (dirloc + dp->d_reclen > DIRBLKSIZ) {
1232 ((struct direct *)(dirbuf + prev))->d_reclen =
1233 DIRBLKSIZ - prev;
b45e25c0
KM
1234 (*wrtfunc)(dirbuf, DIRBLKSIZ);
1235 dirloc = 0;
1236 }
2ec3b58e
KM
1237 blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
1238 prev = dirloc;
1239 dirloc += dp->d_reclen;
b45e25c0
KM
1240}
1241
1242/*
1243 * flush out a directory that is finished.
1244 */
1245flushent(wrtfunc)
1246 int (*wrtfunc)();
1247{
2ec3b58e 1248
b45e25c0
KM
1249 ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
1250 (*wrtfunc)(dirbuf, dirloc);
1251 dirloc = 0;
1252}
1253
1254dirwrite(buf, size)
1255 char *buf;
1256 int size;
1257{
2ec3b58e 1258
b45e25c0
KM
1259 fwrite(buf, 1, size, df);
1260 seekpt = ftell(df);
1261}
1262
1263dcvt(odp, ndp)
1264 register struct odirect *odp;
1265 register struct direct *ndp;
1266{
2ec3b58e 1267
e9039e39 1268 blkclr((char *)ndp, (long)(sizeof *ndp));
b45e25c0
KM
1269 ndp->d_ino = odp->d_ino;
1270 strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
1271 ndp->d_namlen = strlen(ndp->d_name);
1272 ndp->d_reclen = DIRSIZ(ndp);
1273 /*
1274 * this quickly calculates if this inode is a directory.
1275 * Currently not maintained.
1276 *
1277 for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) {
1278 if (itp->t_ino != odp->d_ino)
1279 continue;
1280 ndp->d_fmt = IFDIR;
1281 break;
1282 }
1283 */
1284}
1285
1286/*
a6b18791
KM
1287 * Open a directory.
1288 * Modified to allow any random file to be a legal directory.
1289 */
1290DIR *
1291opendir(name)
1292 char *name;
1293{
1294 register DIR *dirp;
1295
1296 dirp = (DIR *)malloc(sizeof(DIR));
1297 dirp->dd_fd = open(name, 0);
1298 if (dirp->dd_fd == -1) {
e9039e39 1299 free((char *)dirp);
a6b18791
KM
1300 return NULL;
1301 }
1302 dirp->dd_loc = 0;
1303 return dirp;
1304}
1305
1306/*
1307 * Seek to an entry in a directory.
b45e25c0
KM
1308 * Only values returned by ``telldir'' should be passed to seekdir.
1309 * Modified to have many directories based in one file.
1310 */
1311void
1312seekdir(dirp, loc, base)
1313 register DIR *dirp;
e9039e39 1314 daddr_t loc, base;
b45e25c0 1315{
2ec3b58e 1316
b45e25c0
KM
1317 if (loc == telldir(dirp))
1318 return;
1319 loc -= base;
1320 if (loc < 0)
1321 fprintf(stderr, "bad seek pointer to seekdir %d\n", loc);
e9039e39 1322 (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0);
b45e25c0
KM
1323 dirp->dd_loc = loc & (DIRBLKSIZ - 1);
1324 if (dirp->dd_loc != 0)
1325 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
1326}
1327
003a2a9e 1328/*
b1001c58 1329 * get next entry in a directory.
003a2a9e 1330 */
b1001c58
KM
1331struct direct *
1332readdir(dirp)
1333 register DIR *dirp;
7d4dda01 1334{
b1001c58
KM
1335 register struct direct *dp;
1336
1337 for (;;) {
1338 if (dirp->dd_loc == 0) {
1339 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
1340 DIRBLKSIZ);
1341 if (dirp->dd_size <= 0)
1342 return NULL;
1343 }
1344 if (dirp->dd_loc >= dirp->dd_size) {
1345 dirp->dd_loc = 0;
1346 continue;
1347 }
1348 dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
1349 if (dp->d_reclen <= 0 ||
1350 dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc)
1351 return NULL;
1352 dirp->dd_loc += dp->d_reclen;
1353 if (dp->d_ino == 0)
1354 continue;
1355 return (dp);
003a2a9e 1356 }
7d4dda01
KM
1357}
1358
bcfabedf 1359allocinotab(ino, seekpt)
0841dbb0 1360 ino_t ino;
bcfabedf 1361 daddr_t seekpt;
7d4dda01 1362{
0841dbb0 1363 register struct inotab *itp;
19ac1bc8 1364
0841dbb0
KM
1365 itp = (struct inotab *)calloc(1, sizeof(struct inotab));
1366 itp->t_next = inotab[INOHASH(ino)];
1367 inotab[INOHASH(ino)] = itp;
1368 itp->t_ino = ino;
bcfabedf 1369 itp->t_seekpt = seekpt;
7d4dda01
KM
1370}
1371
bcfabedf 1372allocxtr(ino, name, flags)
0841dbb0 1373 ino_t ino;
bcfabedf
KM
1374 char *name;
1375 char flags;
7d4dda01 1376{
bcfabedf 1377 register struct xtrlist *xp, *pxp;
0841dbb0 1378
bcfabedf 1379 xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name));
0841dbb0
KM
1380 xp->x_next = xtrlist[INOHASH(ino)];
1381 xtrlist[INOHASH(ino)] = xp;
1382 xp->x_ino = ino;
bcfabedf 1383 strcpy(xp->x_name, name);
0841dbb0 1384 xtrcnt++;
bcfabedf
KM
1385 xp->x_flags = flags;
1386 for (pxp = xp->x_next; pxp; pxp = pxp->x_next)
1387 if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) {
1388 xp->x_flags |= XLINKED;
1389 xp->x_linkedto = pxp;
1390 xtrcnt--;
1391 break;
1392 }
f99961a3
KM
1393 if (!vflag)
1394 return;
bcfabedf
KM
1395 if (xp->x_flags & XLINKED)
1396 fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name);
1397 else if (xp->x_flags & XISDIR)
1398 fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino);
1399 else
1400 fprintf(stdout, "%s: inode %u\n", xp->x_name, ino);
7d4dda01
KM
1401}
1402
b88e54cb
KM
1403done(exitcode)
1404 int exitcode;
7d4dda01 1405{
2ec3b58e 1406
b88e54cb 1407 unlink(dirfile);
b88e54cb 1408 exit(exitcode);
7d4dda01 1409}