clean-ups
[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
46de1989 4char version[] = "@(#)main.c 2.14 %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:
46de1989
SL
442 /*
443 * Some early dump tapes have symbolic links
444 * present without the associated data blocks.
445 * This hack avoids trashing a file system with
446 * inodes with missing data blocks.
447 */
448 if (spcl.c_count == 0) {
449 if (vflag)
450 printf("%s: 0 length symbolic link (ignored)\n", name);
451 xp->x_flags |= XTRACTD;
452 xtrcnt--;
453 goto skipfile;
454 }
f99961a3
KM
455 if (vflag)
456 fprintf(stdout, "extract symbolic link %s\n", name);
a6b18791
KM
457 uid = spcl.c_dinode.di_uid;
458 gid = spcl.c_dinode.di_gid;
459 lnkbuf[0] = '\0';
460 pathlen = 0;
461 getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size);
b1001c58 462 if (symlink(lnkbuf, name) < 0) {
a6b18791 463 fprintf(stderr, "%s: cannot create symbolic link\n", name);
3b629ff5 464 xp->x_flags |= XTRACTD;
a6b18791
KM
465 xtrcnt--;
466 goto finished;
467 }
b1001c58 468 chown(name, uid, gid);
a6b18791 469 break;
0841dbb0 470 case IFREG:
f99961a3
KM
471 if (vflag)
472 fprintf(stdout, "extract file %s\n", name);
b1001c58 473 if ((ofile = creat(name, 0666)) < 0) {
0841dbb0 474 fprintf(stderr, "%s: cannot create file\n", name);
3b629ff5 475 xp->x_flags |= XTRACTD;
0841dbb0
KM
476 xtrcnt--;
477 goto skipfile;
7d4dda01 478 }
b1001c58 479 chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
b88e54cb 480 getfile(xtrfile, xtrskip, spcl.c_dinode.di_size);
b1001c58 481 close(ofile);
0841dbb0 482 break;
7d4dda01 483 }
b1001c58
KM
484 chmod(name, mode);
485 utime(name, xp->x_timep);
3b629ff5 486 xp->x_flags |= XTRACTD;
0841dbb0
KM
487 xtrcnt--;
488 goto finished;
489 }
490skipfile:
491 getfile(null, null, spcl.c_dinode.di_size);
003a2a9e 492finished:
0841dbb0
KM
493 ;
494 }
495 if (xtrcnt == 0 && !mflag)
496 return;
497 for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
498 for (xp = *xpp; xp; xp = xp->x_next) {
499 if (mflag && (xp->x_flags & XISDIR))
b1001c58 500 utime(xp->x_name, xp->x_timep);
0841dbb0
KM
501 if (xp->x_flags & XTRACTD)
502 continue;
503 if ((xp->x_flags & XLINKED) == 0) {
504 fprintf(stderr, "cannot find file %s\n",
505 xp->x_name);
506 continue;
507 }
bcfabedf
KM
508 if (!mflag)
509 continue;
f99961a3
KM
510 if (vflag)
511 fprintf(stdout, "link %s to %s\n",
512 xp->x_linkedto->x_name, xp->x_name);
b1001c58 513 if (link(xp->x_linkedto->x_name, xp->x_name) < 0)
bcfabedf
KM
514 fprintf(stderr, "link %s to %s failed\n",
515 xp->x_linkedto->x_name, xp->x_name);
7d4dda01 516 }
0841dbb0
KM
517 }
518}
7d4dda01
KM
519
520/*
521 * Read the tape, bulding up a directory structure for extraction
522 * by name
523 */
b88e54cb
KM
524pass1(savedir)
525 int savedir;
7d4dda01 526{
19ac1bc8 527 register int i;
0841dbb0
KM
528 register struct dinode *ip;
529 struct direct nulldir;
b88e54cb 530 char buf[TP_BSIZE];
b45e25c0 531 int putdir(), null(), dirwrite();
7d4dda01 532
b45e25c0
KM
533 nulldir.d_ino = 1;
534 nulldir.d_namlen = 1;
535 strncpy(nulldir.d_name, "/", nulldir.d_namlen);
536 nulldir.d_reclen = DIRSIZ(&nulldir);
7d4dda01 537 while (gethead(&spcl) == 0) {
003a2a9e 538 fprintf(stderr, "Can't find directory header!\n");
7d4dda01
KM
539 }
540 for (;;) {
541 if (checktype(&spcl, TS_BITS) == 1) {
b1001c58 542 readbits(&dumpmap);
7d4dda01
KM
543 continue;
544 }
545 if (checktype(&spcl, TS_CLRI) == 1) {
b1001c58 546 readbits(&clrimap);
7d4dda01
KM
547 continue;
548 }
549 if (checktype(&spcl, TS_INODE) == 0) {
550finish:
b45e25c0
KM
551 if (savedir) {
552 fclose(df);
553 dirp = opendir(dirfile);
554 if (dirp == NULL)
555 perror("opendir");
556 }
b88e54cb 557 resetmt();
7d4dda01
KM
558 return;
559 }
560 ip = &spcl.c_dinode;
561 i = ip->di_mode & IFMT;
562 if (i != IFDIR) {
563 goto finish;
564 }
b88e54cb
KM
565 if (spcl.c_inumber == ROOTINO) {
566 readtape(buf);
567 bct--; /* push back this block */
568 if (((struct direct *)buf)->d_ino != ROOTINO) {
569 if (((struct odirect *)buf)->d_ino != ROOTINO) {
570 fprintf(stderr, "bad root directory\n");
571 done(1);
572 }
573 fprintf(stderr, "converting to new directory format\n");
574 cvtdir = 1;
d8cbdd8d 575 cvtflag = 1;
b88e54cb
KM
576 }
577 if (!savedir && !cvtdir) {
578 /* if no conversion, just return */
579 goto finish;
580 }
581 }
bcfabedf 582 allocinotab(spcl.c_inumber, seekpt);
b88e54cb
KM
583 if (savedir) {
584 getfile(putdir, null, spcl.c_dinode.di_size);
b45e25c0
KM
585 putent(&nulldir, dirwrite);
586 flushent(dirwrite);
b88e54cb
KM
587 } else {
588 getfile(null, null, spcl.c_dinode.di_size);
589 }
7d4dda01
KM
590 }
591}
7d4dda01 592
bcfabedf
KM
593/*
594 * Put the directory entries in the directory file
595 */
bcfabedf
KM
596putdir(buf, size)
597 char *buf;
598 int size;
599{
b88e54cb
KM
600 struct direct cvtbuf;
601 register struct odirect *odp;
602 struct odirect *eodp;
bcfabedf 603 register struct direct *dp;
a6b18791 604 long loc, i;
b88e54cb
KM
605
606 if (cvtdir) {
607 eodp = (struct odirect *)&buf[size];
608 for (odp = (struct odirect *)buf; odp < eodp; odp++)
609 if (odp->d_ino != 0) {
610 dcvt(odp, &cvtbuf);
b45e25c0 611 putent(&cvtbuf, dirwrite);
b88e54cb
KM
612 }
613 } else {
b45e25c0
KM
614 for (loc = 0; loc < size; ) {
615 dp = (struct direct *)(buf + loc);
a6b18791
KM
616 i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
617 if (dp->d_reclen <= 0 || dp->d_reclen > i) {
618 loc += i;
619 continue;
620 }
621 loc += dp->d_reclen;
2ec3b58e 622 if (dp->d_ino != 0) {
b45e25c0 623 putent(dp, dirwrite);
2ec3b58e 624 }
b45e25c0 625 }
b88e54cb
KM
626 }
627}
628
bcfabedf
KM
629/*
630 * Recursively find names and inumbers of all files in subtree
631 * pname and put them in xtrlist[]
632 */
633getleaves(ino, pname)
634 ino_t ino;
635 char *pname;
636{
637 register struct inotab *itp;
638 int namelen;
e9039e39 639 daddr_t bpt;
b45e25c0
KM
640 register struct direct *dp;
641 char locname[BUFSIZ + 1];
bcfabedf
KM
642
643 if (BIT(ino, dumpmap) == 0) {
f99961a3
KM
644 if (vflag)
645 fprintf(stdout, "%s: not on the tape\n", pname);
bcfabedf
KM
646 return;
647 }
648 for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) {
649 if (itp->t_ino != ino)
650 continue;
651 /*
652 * pname is a directory name
653 */
3b629ff5 654 (void)allocxtr(ino, pname, XISDIR);
bcfabedf
KM
655 /*
656 * begin search through the directory
657 * skipping over "." and ".."
658 */
659 strncpy(locname, pname, BUFSIZ);
660 strncat(locname, "/", BUFSIZ);
661 namelen = strlen(locname);
b45e25c0
KM
662 seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
663 dp = readdir(dirp);
664 dp = readdir(dirp);
665 dp = readdir(dirp);
666 bpt = telldir(dirp);
bcfabedf
KM
667 /*
668 * "/" signals end of directory
669 */
b45e25c0 670 while (dp->d_namlen != 1 || dp->d_name[0] != '/') {
bcfabedf 671 locname[namelen] = '\0';
b45e25c0
KM
672 if (namelen + dp->d_namlen >= BUFSIZ) {
673 fprintf(stderr, "%s%s: name exceedes %d char\n",
674 locname, dp->d_name, BUFSIZ);
bcfabedf
KM
675 continue;
676 }
b45e25c0
KM
677 strncat(locname, dp->d_name, dp->d_namlen);
678 getleaves(dp->d_ino, locname);
679 seekdir(dirp, bpt, itp->t_seekpt);
680 dp = readdir(dirp);
681 bpt = telldir(dirp);
bcfabedf
KM
682 }
683 return;
684 }
685 /*
686 * locname is name of a simple file
687 */
3b629ff5 688 (void)allocxtr(ino, pname, XINUSE);
bcfabedf
KM
689}
690
691/*
692 * Search the directory tree rooted at inode ROOTINO
693 * for the path pointed at by n
694 */
695psearch(n)
696 char *n;
697{
698 register char *cp, *cp1;
699 char c;
700
701 ino = ROOTINO;
702 if (*(cp = n) == '/')
703 cp++;
704next:
705 cp1 = cp + 1;
706 while (*cp1 != '/' && *cp1)
707 cp1++;
708 c = *cp1;
709 *cp1 = 0;
710 ino = search(ino, cp);
711 if (ino == 0) {
712 *cp1 = c;
713 return(0);
714 }
715 *cp1 = c;
716 if (c == '/') {
717 cp = cp1+1;
718 goto next;
719 }
720 return(ino);
721}
722
723/*
724 * search the directory inode ino
725 * looking for entry cp
726 */
727ino_t
728search(inum, cp)
729 ino_t inum;
730 char *cp;
731{
b45e25c0 732 register struct direct *dp;
bcfabedf 733 register struct inotab *itp;
b45e25c0 734 int len;
bcfabedf
KM
735
736 for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next)
737 if (itp->t_ino == inum)
738 goto found;
739 return(0);
740found:
b45e25c0
KM
741 seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
742 len = strlen(cp);
bcfabedf 743 do {
b45e25c0
KM
744 dp = readdir(dirp);
745 if (dp->d_namlen == 1 && dp->d_name[0] == '/')
bcfabedf 746 return(0);
b45e25c0
KM
747 } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len));
748 return(dp->d_ino);
bcfabedf 749}
bcfabedf 750
7d4dda01
KM
751/*
752 * Do the file extraction, calling the supplied functions
753 * with the blocks
754 */
003a2a9e
KM
755getfile(f1, f2, size)
756 int (*f2)(), (*f1)();
e9039e39 757 off_t size;
7d4dda01 758{
19ac1bc8 759 register int i;
b6407c9d 760 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
0841dbb0
KM
761 union u_spcl addrblk;
762# define addrblock addrblk.s_spcl
7d4dda01 763
0841dbb0 764 addrblock = spcl;
7d4dda01 765 for (;;) {
0841dbb0
KM
766 for (i = 0; i < addrblock.c_count; i++) {
767 if (addrblock.c_addr[i]) {
19ac1bc8 768 readtape(&buf[curblk++][0]);
b1001c58 769 if (curblk == fssize / TP_BSIZE) {
19ac1bc8 770 (*f1)(buf, size > TP_BSIZE ?
b1001c58 771 (long) (fssize) :
19ac1bc8
KM
772 (curblk - 1) * TP_BSIZE + size);
773 curblk = 0;
774 }
b6407c9d 775 } else {
19ac1bc8
KM
776 if (curblk > 0) {
777 (*f1)(buf, size > TP_BSIZE ?
778 (long) (curblk * TP_BSIZE) :
779 (curblk - 1) * TP_BSIZE + size);
780 curblk = 0;
781 }
b6407c9d
KM
782 (*f2)(clearedbuf, size > TP_BSIZE ?
783 (long) TP_BSIZE : size);
7d4dda01 784 }
19ac1bc8 785 if ((size -= TP_BSIZE) <= 0) {
028f3676 786 gethead(&spcl);
19ac1bc8 787 goto out;
7d4dda01
KM
788 }
789 }
0841dbb0 790 if (gethead(&addrblock) == 0) {
028f3676 791 fprintf(stderr, "Missing address (header) block for %s\n",
3b629ff5 792 entry->x_name);
028f3676
KM
793 spcl.c_magic = 0;
794 goto out;
003a2a9e 795 }
0841dbb0
KM
796 if (checktype(&addrblock, TS_ADDR) == 0) {
797 spcl = addrblock;
19ac1bc8 798 goto out;
003a2a9e 799 }
7d4dda01 800 }
19ac1bc8
KM
801out:
802 if (curblk > 0) {
803 (*f1)(buf, (curblk * TP_BSIZE) + size);
804 curblk = 0;
805 }
7d4dda01
KM
806}
807
bcfabedf
KM
808/*
809 * The next routines are called during file extraction to
810 * put the data into the right form and place.
811 */
bcfabedf
KM
812xtrfile(buf, size)
813 char *buf;
814 long size;
815{
2ec3b58e 816
b1001c58 817 if (write(ofile, buf, (int) size) == -1) {
b88e54cb 818 perror("extract write");
bcfabedf
KM
819 done(1);
820 }
821}
822
b88e54cb 823xtrskip(buf, size)
bcfabedf
KM
824 char *buf;
825 long size;
826{
2ec3b58e 827
e9039e39
KM
828#ifdef lint
829 buf = buf;
830#endif
b1001c58 831 if (lseek(ofile, size, 1) == -1) {
b88e54cb 832 perror("extract seek");
bcfabedf
KM
833 done(1);
834 }
835}
bcfabedf 836
b88e54cb
KM
837xtrcvtdir(buf, size)
838 struct odirect *buf;
839 long size;
840{
b88e54cb 841 struct odirect *odp, *edp;
e9039e39 842 struct direct cvtbuf;
b88e54cb
KM
843
844 edp = &buf[size / sizeof(struct odirect)];
b45e25c0
KM
845 for (odp = buf; odp < edp; odp++) {
846 dcvt(odp, &cvtbuf);
847 putent(&cvtbuf, xtrfile);
b88e54cb
KM
848 }
849}
850
851xtrcvtskip(buf, size)
852 char *buf;
853 long size;
854{
2ec3b58e 855
028f3676 856 fprintf(stderr, "unallocated block in directory %s\n",
3b629ff5 857 entry->x_name);
b45e25c0 858 xtrskip(buf, size);
b88e54cb 859}
a6b18791
KM
860
861xtrlnkfile(buf, size)
862 char *buf;
863 long size;
864{
2ec3b58e 865
a6b18791
KM
866 pathlen += size;
867 if (pathlen > MAXPATHLEN) {
868 fprintf(stderr, "symbolic link name: %s; too long %d\n",
869 buf, size);
870 done(1);
871 }
872 strcat(lnkbuf, buf);
873}
874
875xtrlnkskip(buf, size)
876 char *buf;
877 long size;
878{
2ec3b58e 879
e9039e39
KM
880#ifdef lint
881 buf = buf, size = size;
882#endif
028f3676 883 fprintf(stderr, "unallocated block in symbolic link %s\n",
3b629ff5 884 entry->x_name);
a6b18791
KM
885 done(1);
886}
b88e54cb 887
bcfabedf
KM
888null() {;}
889
7d4dda01 890/*
19ac1bc8 891 * Do the tape i/o, dealing with volume changes
7d4dda01
KM
892 * etc..
893 */
894readtape(b)
003a2a9e 895 char *b;
7d4dda01 896{
e9039e39 897 register long i;
2ec3b58e 898 struct u_spcl tmpbuf;
1263e71f 899 char c;
7d4dda01
KM
900
901 if (bct >= NTREC) {
902 for (i = 0; i < NTREC; i++)
19ac1bc8 903 ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
7d4dda01 904 bct = 0;
cbd23190
KM
905#ifdef RRESTOR
906 if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) {
907#else
19ac1bc8 908 if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
cbd23190 909#endif
028f3676 910 fprintf(stderr, "Tape read error while restoring %s\n",
3b629ff5 911 entry->x_name);
f99961a3 912 if (!yflag) {
028f3676 913 fprintf(stderr, "continue? ");
f99961a3 914 do {
028f3676 915 fprintf(stderr, "[yn] ");
f99961a3
KM
916 c = getchar();
917 while (getchar() != '\n')
918 /* void */;
919 } while (c != 'y' && c != 'n');
920 if (c == 'n')
921 done(1);
922 }
7d4dda01 923 eflag++;
1263e71f
KM
924 i = NTREC*TP_BSIZE;
925 blkclr(tbf, i);
cbd23190
KM
926#ifdef RRESTOR
927 if (rmtseek(i, 1) < 0) {
928#else
e9039e39 929 if (lseek(mt, i, 1) < 0) {
cbd23190 930#endif
e9039e39
KM
931 fprintf(stderr, "continuation failed\n");
932 done(1);
933 }
7d4dda01
KM
934 }
935 if (i == 0) {
936 bct = NTREC + 1;
937 volno++;
938loop:
939 flsht();
cbd23190
KM
940#ifdef RRESTOR
941 rmtclose();
942#else
7d4dda01 943 close(mt);
cbd23190 944#endif
003a2a9e 945 fprintf(stderr, "Mount volume %d\n", volno);
7d4dda01
KM
946 while (getchar() != '\n')
947 ;
cbd23190
KM
948#ifdef RRESTOR
949 if ((mt = rmtopen(magtape, 0)) == -1) {
950#else
7d4dda01 951 if ((mt = open(magtape, 0)) == -1) {
cbd23190 952#endif
003a2a9e 953 fprintf(stderr, "Cannot open tape!\n");
7d4dda01
KM
954 goto loop;
955 }
956 if (readhdr(&tmpbuf) == 0) {
003a2a9e 957 fprintf(stderr, "Not a dump tape.Try again\n");
7d4dda01
KM
958 goto loop;
959 }
960 if (checkvol(&tmpbuf, volno) == 0) {
003a2a9e 961 fprintf(stderr, "Wrong tape. Try again\n");
7d4dda01
KM
962 goto loop;
963 }
964 readtape(b);
965 return;
966 }
967 }
e9039e39 968 blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
7d4dda01
KM
969}
970
971flsht()
972{
2ec3b58e 973
7d4dda01
KM
974 bct = NTREC+1;
975}
976
b45e25c0
KM
977blkcpy(from, to, size)
978 char *from, *to;
e9039e39 979 long size;
7d4dda01 980{
2ec3b58e 981
e9039e39
KM
982#ifdef lint
983 from = from, to = to, size = size;
984#endif
b45e25c0 985 asm(" movc3 12(ap),*4(ap),*8(ap)");
7d4dda01
KM
986}
987
b88e54cb
KM
988blkclr(buf, size)
989 char *buf;
e9039e39 990 long size;
b88e54cb 991{
2ec3b58e 992
e9039e39
KM
993#ifdef lint
994 buf = buf, size = size;
995#endif
b88e54cb
KM
996 asm("movc5 $0,(r0),$0,8(ap),*4(ap)");
997}
998
999resetmt()
1000{
1001 struct mtop tcom;
1002
2ec3b58e 1003 if (dumpnum > 1)
b88e54cb
KM
1004 tcom.mt_op = MTBSF;
1005 else
1006 tcom.mt_op = MTREW;
1007 tcom.mt_count = 1;
1008 flsht();
cbd23190
KM
1009#ifdef RRESTOR
1010 if (rmtioctl(tcom.mt_op, 1) == -1) {
1011 /* kludge for disk dumps */
1012 rmtseek((long)0, 0);
1013 }
1014#else
b88e54cb
KM
1015 if (ioctl(mt,MTIOCTOP,&tcom) == -1) {
1016 /* kludge for disk dumps */
1017 lseek(mt, (long)0, 0);
1018 }
cbd23190 1019#endif
b88e54cb 1020 if (dumpnum > 1) {
cbd23190
KM
1021#ifdef RRESTOR
1022 rmtioctl(MTFSF, 1);
1023#else
b88e54cb
KM
1024 tcom.mt_op = MTFSF;
1025 tcom.mt_count = 1;
1026 ioctl(mt,MTIOCTOP,&tcom);
cbd23190 1027#endif
b88e54cb
KM
1028 }
1029}
1030
bcfabedf
KM
1031checkvol(b, t)
1032 struct s_spcl *b;
1033 int t;
7d4dda01 1034{
2ec3b58e 1035
bcfabedf
KM
1036 if (b->c_volume == t)
1037 return(1);
7d4dda01 1038 return(0);
7d4dda01
KM
1039}
1040
bcfabedf
KM
1041readhdr(b)
1042 struct s_spcl *b;
7d4dda01 1043{
2ec3b58e 1044
bcfabedf 1045 if (gethead(b) == 0)
7d4dda01 1046 return(0);
bcfabedf
KM
1047 if (checktype(b, TS_TAPE) == 0)
1048 return(0);
1049 return(1);
7d4dda01 1050}
7d4dda01 1051
7d4dda01
KM
1052/*
1053 * read the tape into buf, then return whether or
1054 * or not it is a header block.
1055 */
1056gethead(buf)
0841dbb0 1057 struct s_spcl *buf;
7d4dda01 1058{
d8cbdd8d
KM
1059 union u_ospcl {
1060 char dummy[TP_BSIZE];
1061 struct s_ospcl {
1062 int c_type;
1063 time_t c_date;
1064 time_t c_ddate;
1065 int c_volume;
1066 daddr_t c_tapea;
1067 ino_t c_inumber;
1068 int c_magic;
1069 int c_checksum;
1070 struct odinode {
1071 unsigned short odi_mode;
1072 short odi_nlink;
1073 short odi_uid;
1074 short odi_gid;
1075 off_t odi_size;
1076 daddr_t odi_rdev;
1077 char odi_addr[36];
1078 time_t odi_atime;
1079 time_t odi_mtime;
1080 time_t odi_ctime;
1081 } c_dinode;
1082 int c_count;
1083 char c_addr[TP_NINDIR];
1084 } s_ospcl;
1085 } u_ospcl;
1086
1087 if (!cvtflag) {
1088 readtape((char *)buf);
27c979b8 1089 if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == 0)
d8cbdd8d
KM
1090 return(0);
1091 return(1);
1092 }
1093 readtape((char *)(&u_ospcl.s_ospcl));
d8cbdd8d
KM
1094 blkclr((char *)buf, TP_BSIZE);
1095 buf->c_type = u_ospcl.s_ospcl.c_type;
1096 buf->c_date = u_ospcl.s_ospcl.c_date;
1097 buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
1098 buf->c_volume = u_ospcl.s_ospcl.c_volume;
1099 buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
1100 buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
d8cbdd8d 1101 buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
028f3676 1102 buf->c_magic = u_ospcl.s_ospcl.c_magic;
d8cbdd8d
KM
1103 buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
1104 buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
1105 buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
1106 buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
1107 buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
1108 buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
1109 buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
1110 buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
1111 buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
1112 buf->c_count = u_ospcl.s_ospcl.c_count;
1113 blkcpy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR);
028f3676
KM
1114 if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
1115 checksum((int *)(&u_ospcl.s_ospcl)) == 0)
1116 return(0);
1117 buf->c_magic = NFS_MAGIC;
7d4dda01
KM
1118 return(1);
1119}
1120
1121/*
1122 * return whether or not the buffer contains a header block
1123 */
1124ishead(buf)
0841dbb0 1125 struct s_spcl *buf;
7d4dda01 1126{
2ec3b58e 1127
27c979b8 1128 if (buf->c_magic != NFS_MAGIC)
7d4dda01
KM
1129 return(0);
1130 return(1);
1131}
1132
1133checktype(b, t)
0841dbb0 1134 struct s_spcl *b;
003a2a9e 1135 int t;
7d4dda01 1136{
2ec3b58e 1137
0841dbb0 1138 return(b->c_type == t);
7d4dda01
KM
1139}
1140
b88e54cb
KM
1141/*
1142 * read a bit mask from the tape into m.
1143 */
b1001c58
KM
1144readbits(mapp)
1145 char **mapp;
b88e54cb
KM
1146{
1147 register int i;
b1001c58 1148 char *m;
b88e54cb
KM
1149
1150 i = spcl.c_count;
1151
b1001c58 1152 if (*mapp == 0)
e9039e39 1153 *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS)));
b1001c58 1154 m = *mapp;
b88e54cb
KM
1155 while (i--) {
1156 readtape((char *) m);
b6407c9d 1157 m += (TP_BSIZE/(NBBY/BITS));
b88e54cb
KM
1158 }
1159 while (gethead(&spcl) == 0)
1160 ;
1161}
7d4dda01
KM
1162
1163checksum(b)
d8cbdd8d 1164 register int *b;
7d4dda01 1165{
19ac1bc8 1166 register int i, j;
7d4dda01 1167
19ac1bc8 1168 j = sizeof(union u_spcl) / sizeof(int);
7d4dda01
KM
1169 i = 0;
1170 do
1171 i += *b++;
1172 while (--j);
1173 if (i != CHECKSUM) {
028f3676 1174 fprintf(stderr, "Checksum error %o, file %s\n", i,
3b629ff5 1175 entry->x_name);
7d4dda01
KM
1176 return(0);
1177 }
1178 return(1);
1179}
1180
b88e54cb
KM
1181/*
1182 * Check for access into each directory in the pathname of an extracted
1183 * file and create such a directory if needed in preparation for moving
1184 * the file to its proper home.
1185 */
1186checkdir(name)
1187 register char *name;
1188{
1189 register char *cp;
1190 int i;
1191
1192 for (cp = name; *cp; cp++) {
1193 if (*cp == '/') {
1194 *cp = '\0';
b1001c58 1195 if (access(name, 01) < 0) {
b88e54cb
KM
1196 register int pid, rp;
1197
f2b2d53e 1198 if ((pid = vfork()) == 0) {
b1001c58
KM
1199 execl("/bin/mkdir", "mkdir", name, 0);
1200 execl("/usr/bin/mkdir", "mkdir", name, 0);
1201 fprintf(stderr, "restor: cannot find mkdir!\n");
b88e54cb
KM
1202 done(0);
1203 }
1204 while ((rp = wait(&i)) >= 0 && rp != pid)
1205 ;
b88e54cb
KM
1206 }
1207 *cp = '/';
1208 }
1209 }
1210}
1211
b1001c58
KM
1212setdir(dev)
1213 char *dev;
1214{
1215 struct fstab *fsp;
1216
1217 if (setfsent() == 0) {
1218 fprintf(stderr, "Can't open checklist file: %s\n", FSTAB);
1219 done(1);
1220 }
1221 while ((fsp = getfsent()) != 0) {
1222 if (strcmp(fsp->fs_spec, dev) == 0) {
f99961a3 1223 fprintf(stderr, "%s mounted on %s\n", dev, fsp->fs_file);
b1001c58
KM
1224 if (chdir(fsp->fs_file) >= 0)
1225 return;
1226 fprintf(stderr, "%s cannot chdir to %s\n",
1227 fsp->fs_file);
1228 done(1);
1229 }
1230 }
1231 fprintf(stderr, "%s not mounted\n", dev);
1232 done(1);
1233}
1234
b45e25c0
KM
1235/*
1236 * These variables are "local" to the following two functions.
1237 */
1238char dirbuf[DIRBLKSIZ];
1239long dirloc = 0;
1240long prev = 0;
1241
1242/*
1243 * add a new directory entry to a file.
1244 */
1245putent(dp, wrtfunc)
1246 struct direct *dp;
1247 int (*wrtfunc)();
1248{
2ec3b58e 1249
b45e25c0
KM
1250 if (dp->d_ino == 0)
1251 return;
2ec3b58e
KM
1252 if (dirloc + dp->d_reclen > DIRBLKSIZ) {
1253 ((struct direct *)(dirbuf + prev))->d_reclen =
1254 DIRBLKSIZ - prev;
b45e25c0
KM
1255 (*wrtfunc)(dirbuf, DIRBLKSIZ);
1256 dirloc = 0;
1257 }
2ec3b58e
KM
1258 blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
1259 prev = dirloc;
1260 dirloc += dp->d_reclen;
b45e25c0
KM
1261}
1262
1263/*
1264 * flush out a directory that is finished.
1265 */
1266flushent(wrtfunc)
1267 int (*wrtfunc)();
1268{
2ec3b58e 1269
b45e25c0
KM
1270 ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
1271 (*wrtfunc)(dirbuf, dirloc);
1272 dirloc = 0;
1273}
1274
1275dirwrite(buf, size)
1276 char *buf;
1277 int size;
1278{
2ec3b58e 1279
b45e25c0
KM
1280 fwrite(buf, 1, size, df);
1281 seekpt = ftell(df);
1282}
1283
1284dcvt(odp, ndp)
1285 register struct odirect *odp;
1286 register struct direct *ndp;
1287{
2ec3b58e 1288
e9039e39 1289 blkclr((char *)ndp, (long)(sizeof *ndp));
b45e25c0
KM
1290 ndp->d_ino = odp->d_ino;
1291 strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
1292 ndp->d_namlen = strlen(ndp->d_name);
1293 ndp->d_reclen = DIRSIZ(ndp);
1294 /*
1295 * this quickly calculates if this inode is a directory.
1296 * Currently not maintained.
1297 *
1298 for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) {
1299 if (itp->t_ino != odp->d_ino)
1300 continue;
1301 ndp->d_fmt = IFDIR;
1302 break;
1303 }
1304 */
1305}
1306
1307/*
a6b18791
KM
1308 * Open a directory.
1309 * Modified to allow any random file to be a legal directory.
1310 */
1311DIR *
1312opendir(name)
1313 char *name;
1314{
1315 register DIR *dirp;
1316
1317 dirp = (DIR *)malloc(sizeof(DIR));
1318 dirp->dd_fd = open(name, 0);
1319 if (dirp->dd_fd == -1) {
e9039e39 1320 free((char *)dirp);
a6b18791
KM
1321 return NULL;
1322 }
1323 dirp->dd_loc = 0;
1324 return dirp;
1325}
1326
1327/*
1328 * Seek to an entry in a directory.
b45e25c0
KM
1329 * Only values returned by ``telldir'' should be passed to seekdir.
1330 * Modified to have many directories based in one file.
1331 */
1332void
1333seekdir(dirp, loc, base)
1334 register DIR *dirp;
e9039e39 1335 daddr_t loc, base;
b45e25c0 1336{
2ec3b58e 1337
b45e25c0
KM
1338 if (loc == telldir(dirp))
1339 return;
1340 loc -= base;
1341 if (loc < 0)
1342 fprintf(stderr, "bad seek pointer to seekdir %d\n", loc);
e9039e39 1343 (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0);
b45e25c0
KM
1344 dirp->dd_loc = loc & (DIRBLKSIZ - 1);
1345 if (dirp->dd_loc != 0)
1346 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
1347}
1348
003a2a9e 1349/*
b1001c58 1350 * get next entry in a directory.
003a2a9e 1351 */
b1001c58
KM
1352struct direct *
1353readdir(dirp)
1354 register DIR *dirp;
7d4dda01 1355{
b1001c58
KM
1356 register struct direct *dp;
1357
1358 for (;;) {
1359 if (dirp->dd_loc == 0) {
1360 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
1361 DIRBLKSIZ);
1362 if (dirp->dd_size <= 0)
1363 return NULL;
1364 }
1365 if (dirp->dd_loc >= dirp->dd_size) {
1366 dirp->dd_loc = 0;
1367 continue;
1368 }
1369 dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
1370 if (dp->d_reclen <= 0 ||
1371 dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc)
1372 return NULL;
1373 dirp->dd_loc += dp->d_reclen;
1374 if (dp->d_ino == 0)
1375 continue;
1376 return (dp);
003a2a9e 1377 }
7d4dda01
KM
1378}
1379
bcfabedf 1380allocinotab(ino, seekpt)
0841dbb0 1381 ino_t ino;
bcfabedf 1382 daddr_t seekpt;
7d4dda01 1383{
0841dbb0 1384 register struct inotab *itp;
19ac1bc8 1385
0841dbb0
KM
1386 itp = (struct inotab *)calloc(1, sizeof(struct inotab));
1387 itp->t_next = inotab[INOHASH(ino)];
1388 inotab[INOHASH(ino)] = itp;
1389 itp->t_ino = ino;
bcfabedf 1390 itp->t_seekpt = seekpt;
7d4dda01
KM
1391}
1392
3b629ff5 1393struct xtrlist *
bcfabedf 1394allocxtr(ino, name, flags)
0841dbb0 1395 ino_t ino;
bcfabedf
KM
1396 char *name;
1397 char flags;
7d4dda01 1398{
bcfabedf 1399 register struct xtrlist *xp, *pxp;
028f3676 1400 int size;
0841dbb0 1401
028f3676 1402 size = sizeof(struct xtrlist) + strlen(name);
028f3676 1403 xp = (struct xtrlist *)calloc(1, size);
0841dbb0 1404 xp->x_ino = ino;
3b629ff5 1405 xp->x_flags = flags;
bcfabedf 1406 strcpy(xp->x_name, name);
3b629ff5
KM
1407 if (flags == 0)
1408 return (xp);
1409 xp->x_next = xtrlist[INOHASH(ino)];
1410 xtrlist[INOHASH(ino)] = xp;
0841dbb0 1411 xtrcnt++;
bcfabedf
KM
1412 for (pxp = xp->x_next; pxp; pxp = pxp->x_next)
1413 if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) {
1414 xp->x_flags |= XLINKED;
1415 xp->x_linkedto = pxp;
1416 xtrcnt--;
1417 break;
1418 }
f99961a3 1419 if (!vflag)
3b629ff5 1420 return (xp);
bcfabedf
KM
1421 if (xp->x_flags & XLINKED)
1422 fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name);
1423 else if (xp->x_flags & XISDIR)
1424 fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino);
1425 else
1426 fprintf(stdout, "%s: inode %u\n", xp->x_name, ino);
3b629ff5
KM
1427 return (xp);
1428}
1429
1430#ifdef RRESTOR
1431msg(cp, a1, a2, a3)
1432 char *cp;
1433{
1434
1435 fprintf(stderr, cp, a1, a2, a3);
7d4dda01 1436}
3b629ff5 1437#endif RRESTOR
7d4dda01 1438
b88e54cb
KM
1439done(exitcode)
1440 int exitcode;
7d4dda01 1441{
2ec3b58e 1442
b88e54cb 1443 unlink(dirfile);
b88e54cb 1444 exit(exitcode);
7d4dda01 1445}