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