add log.c; rm decnet
[unix-history] / usr / src / sbin / restore / dirs.c
CommitLineData
f743fc86 1#ifndef lint
97b06931 2static char sccsid[] = "@(#)dirs.c 3.17 (Berkeley) 83/12/30";
f743fc86
KM
3#endif
4
ebd1f727
SL
5/* Copyright (c) 1983 Regents of the University of California */
6
f743fc86
KM
7#include "restore.h"
8#include <dumprestor.h>
9f13f26d 9#include <sys/file.h>
a7b24fe9 10#include <sys/dir.h>
f743fc86 11
7432ff81
KM
12/*
13 * Symbol table of directories read from tape.
14 */
f743fc86 15#define HASHSIZE 1000
f743fc86
KM
16#define INOHASH(val) (val % HASHSIZE)
17struct inotab {
18 struct inotab *t_next;
19 ino_t t_ino;
20 daddr_t t_seekpt;
21 long t_size;
9f13f26d
KM
22};
23static struct inotab *inotab[HASHSIZE];
24extern struct inotab *inotablookup();
9730f69a 25extern struct inotab *allocinotab();
f743fc86 26
7432ff81
KM
27/*
28 * Information retained about directories.
29 */
f743fc86
KM
30struct modeinfo {
31 ino_t ino;
32 time_t timep[2];
33 short mode;
34 short uid;
35 short gid;
36};
37
7432ff81
KM
38/*
39 * Global variables for this file.
40 */
9f13f26d
KM
41static daddr_t seekpt;
42static FILE *df, *mf;
43static DIR *dirp;
7432ff81
KM
44static char dirfile[32] = "#"; /* No file */
45static char modefile[32] = "#"; /* No file */
9f13f26d 46extern ino_t search();
e9e7ecc4
KM
47struct direct *rst_readdir();
48extern void rst_seekdir();
f743fc86 49
7432ff81
KM
50/*
51 * Format of old style directories.
52 */
f743fc86
KM
53#define ODIRSIZ 14
54struct odirect {
55 u_short d_ino;
56 char d_name[ODIRSIZ];
57};
58
7432ff81
KM
59/*
60 * Structure and routines associated with listing directories.
61 */
62struct afile {
63 ino_t fnum; /* inode number of file */
64 char *fname; /* file name */
65 short fflags; /* extraction flags, if any */
66 char ftype; /* file type, e.g. LEAF or NODE */
67};
68extern int fcmp();
69extern char *fmtentry();
70
f743fc86
KM
71/*
72 * Extract directory contents, building up a directory structure
73 * on disk for extraction by name.
7432ff81 74 * If genmode is requested, save mode, owner, and times for all
f743fc86
KM
75 * directories on the tape.
76 */
7432ff81
KM
77extractdirs(genmode)
78 int genmode;
f743fc86
KM
79{
80 register int i;
81 register struct dinode *ip;
9730f69a 82 struct inotab *itp;
f743fc86
KM
83 struct direct nulldir;
84 int putdir(), null();
85
86 vprintf(stdout, "Extract directories from tape\n");
7432ff81 87 (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate);
f743fc86
KM
88 df = fopen(dirfile, "w");
89 if (df == 0) {
90 fprintf(stderr,
97b06931 91 "restore: %s - cannot create directory temporary\n",
f743fc86
KM
92 dirfile);
93 perror("fopen");
94 done(1);
95 }
7432ff81
KM
96 if (genmode != 0) {
97 (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate);
f743fc86 98 mf = fopen(modefile, "w");
9f13f26d 99 if (mf == 0) {
f743fc86 100 fprintf(stderr,
97b06931 101 "restore: %s - cannot create modefile \n",
f743fc86
KM
102 modefile);
103 perror("fopen");
104 done(1);
105 }
106 }
9730f69a 107 nulldir.d_ino = 0;
f743fc86 108 nulldir.d_namlen = 1;
93d90477 109 (void) strcpy(nulldir.d_name, "/");
f743fc86
KM
110 nulldir.d_reclen = DIRSIZ(&nulldir);
111 for (;;) {
112 curfile.name = "<directory file - name unknown>";
113 curfile.action = USING;
114 ip = curfile.dip;
115 i = ip->di_mode & IFMT;
116 if (i != IFDIR) {
82d46726 117 (void) fclose(df);
f743fc86
KM
118 dirp = opendir(dirfile);
119 if (dirp == NULL)
120 perror("opendir");
121 if (mf != NULL)
82d46726 122 (void) fclose(mf);
7432ff81
KM
123 i = dirlookup(".");
124 if (i == 0)
7851e15d 125 panic("Root directory is not on tape\n");
f743fc86
KM
126 return;
127 }
9730f69a 128 itp = allocinotab(curfile.ino, ip, seekpt);
f743fc86
KM
129 getfile(putdir, null);
130 putent(&nulldir);
131 flushent();
9730f69a
KM
132 itp->t_size = seekpt - itp->t_seekpt;
133 }
134}
135
136/*
137 * skip over all the directories on the tape
138 */
139skipdirs()
140{
141
142 while ((curfile.dip->di_mode & IFMT) == IFDIR) {
143 skipfile();
f743fc86
KM
144 }
145}
146
147/*
148 * Recursively find names and inumbers of all files in subtree
149 * pname and pass them off to be processed.
150 */
151treescan(pname, ino, todo)
152 char *pname;
153 ino_t ino;
314ac756 154 long (*todo)();
f743fc86
KM
155{
156 register struct inotab *itp;
93d90477
KM
157 register struct direct *dp;
158 register struct entry *np;
f743fc86
KM
159 int namelen;
160 daddr_t bpt;
4796d2a4 161 char locname[MAXPATHLEN + 1];
f743fc86
KM
162
163 itp = inotablookup(ino);
164 if (itp == NULL) {
165 /*
166 * Pname is name of a simple file or an unchanged directory.
167 */
314ac756 168 (void) (*todo)(pname, ino, LEAF);
f743fc86
KM
169 return;
170 }
171 /*
172 * Pname is a dumped directory name.
173 */
314ac756
KM
174 if ((*todo)(pname, ino, NODE) == FAIL)
175 return;
f743fc86
KM
176 /*
177 * begin search through the directory
178 * skipping over "." and ".."
179 */
7432ff81
KM
180 (void) strncpy(locname, pname, MAXPATHLEN);
181 (void) strncat(locname, "/", MAXPATHLEN);
f743fc86 182 namelen = strlen(locname);
e9e7ecc4
KM
183 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
184 dp = rst_readdir(dirp); /* "." */
93d90477 185 if (dp != NULL && strcmp(dp->d_name, ".") == 0) {
e9e7ecc4 186 dp = rst_readdir(dirp); /* ".." */
93d90477
KM
187 } else {
188 np = lookupino(ino);
189 if (np == NULL)
190 panic("corrupted symbol table\n");
191 fprintf(stderr, ". missing from directory %s\n", myname(np));
192 }
193 if (dp != NULL && strcmp(dp->d_name, "..") == 0) {
e9e7ecc4 194 dp = rst_readdir(dirp); /* first real entry */
93d90477
KM
195 } else {
196 np = lookupino(ino);
197 if (np == NULL)
198 panic("corrupted symbol table\n");
199 fprintf(stderr, ".. missing from directory %s\n", myname(np));
200 }
f743fc86
KM
201 bpt = telldir(dirp);
202 /*
93d90477 203 * a zero inode signals end of directory
f743fc86 204 */
93d90477 205 while (dp != NULL && dp->d_ino != 0) {
f743fc86 206 locname[namelen] = '\0';
4796d2a4 207 if (namelen + dp->d_namlen >= MAXPATHLEN) {
f743fc86 208 fprintf(stderr, "%s%s: name exceeds %d char\n",
4796d2a4 209 locname, dp->d_name, MAXPATHLEN);
f743fc86 210 } else {
7432ff81 211 (void) strncat(locname, dp->d_name, (int)dp->d_namlen);
f743fc86 212 treescan(locname, dp->d_ino, todo);
e9e7ecc4 213 rst_seekdir(dirp, bpt, itp->t_seekpt);
f743fc86 214 }
e9e7ecc4 215 dp = rst_readdir(dirp);
f743fc86
KM
216 bpt = telldir(dirp);
217 }
218 if (dp == NULL)
219 fprintf(stderr, "corrupted directory: %s.\n", locname);
220}
221
222/*
223 * Search the directory tree rooted at inode ROOTINO
224 * for the path pointed at by n
225 */
226ino_t
227psearch(n)
228 char *n;
229{
230 register char *cp, *cp1;
231 ino_t ino;
232 char c;
233
234 ino = ROOTINO;
235 if (*(cp = n) == '/')
236 cp++;
237next:
238 cp1 = cp + 1;
239 while (*cp1 != '/' && *cp1)
240 cp1++;
241 c = *cp1;
242 *cp1 = 0;
243 ino = search(ino, cp);
244 if (ino == 0) {
245 *cp1 = c;
246 return(0);
247 }
248 *cp1 = c;
249 if (c == '/') {
250 cp = cp1+1;
251 goto next;
252 }
253 return(ino);
254}
255
256/*
257 * search the directory inode ino
258 * looking for entry cp
259 */
260ino_t
261search(inum, cp)
262 ino_t inum;
263 char *cp;
264{
265 register struct direct *dp;
266 register struct inotab *itp;
267 int len;
268
269 itp = inotablookup(inum);
270 if (itp == NULL)
271 return(0);
e9e7ecc4 272 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
f743fc86
KM
273 len = strlen(cp);
274 do {
e9e7ecc4 275 dp = rst_readdir(dirp);
93d90477
KM
276 if (dp == NULL || dp->d_ino == 0)
277 return (0);
7432ff81 278 } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0);
f743fc86
KM
279 return(dp->d_ino);
280}
281
282/*
283 * Put the directory entries in the directory file
284 */
285putdir(buf, size)
286 char *buf;
287 int size;
288{
289 struct direct cvtbuf;
290 register struct odirect *odp;
291 struct odirect *eodp;
292 register struct direct *dp;
293 long loc, i;
294
295 if (cvtflag) {
296 eodp = (struct odirect *)&buf[size];
297 for (odp = (struct odirect *)buf; odp < eodp; odp++)
298 if (odp->d_ino != 0) {
299 dcvt(odp, &cvtbuf);
300 putent(&cvtbuf);
301 }
302 } else {
303 for (loc = 0; loc < size; ) {
304 dp = (struct direct *)(buf + loc);
305 i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
306 if (dp->d_reclen == 0 || dp->d_reclen > i) {
307 loc += i;
308 continue;
309 }
310 loc += dp->d_reclen;
311 if (dp->d_ino != 0) {
312 putent(dp);
313 }
314 }
315 }
316}
317
318/*
319 * These variables are "local" to the following two functions.
320 */
321char dirbuf[DIRBLKSIZ];
322long dirloc = 0;
323long prev = 0;
324
325/*
326 * add a new directory entry to a file.
327 */
328putent(dp)
329 struct direct *dp;
330{
9730f69a 331 dp->d_reclen = DIRSIZ(dp);
f743fc86
KM
332 if (dirloc + dp->d_reclen > DIRBLKSIZ) {
333 ((struct direct *)(dirbuf + prev))->d_reclen =
334 DIRBLKSIZ - prev;
82d46726 335 (void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
f743fc86
KM
336 dirloc = 0;
337 }
338 bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
339 prev = dirloc;
340 dirloc += dp->d_reclen;
341}
342
343/*
344 * flush out a directory that is finished.
345 */
346flushent()
347{
348
349 ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
82d46726 350 (void) fwrite(dirbuf, (int)dirloc, 1, df);
f743fc86
KM
351 seekpt = ftell(df);
352 dirloc = 0;
353}
354
355dcvt(odp, ndp)
356 register struct odirect *odp;
357 register struct direct *ndp;
358{
359
360 bzero((char *)ndp, (long)(sizeof *ndp));
361 ndp->d_ino = odp->d_ino;
7432ff81 362 (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
f743fc86
KM
363 ndp->d_namlen = strlen(ndp->d_name);
364 ndp->d_reclen = DIRSIZ(ndp);
f743fc86
KM
365}
366
367/*
368 * Seek to an entry in a directory.
e9e7ecc4 369 * Only values returned by ``telldir'' should be passed to rst_seekdir.
82d46726
KM
370 * This routine handles many directories in a single file.
371 * It takes the base of the directory in the file, plus
372 * the desired seek offset into it.
f743fc86
KM
373 */
374void
e9e7ecc4 375rst_seekdir(dirp, loc, base)
f743fc86
KM
376 register DIR *dirp;
377 daddr_t loc, base;
378{
379
380 if (loc == telldir(dirp))
381 return;
382 loc -= base;
383 if (loc < 0)
e9e7ecc4 384 fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc);
f743fc86
KM
385 (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0);
386 dirp->dd_loc = loc & (DIRBLKSIZ - 1);
387 if (dirp->dd_loc != 0)
388 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
389}
390
391/*
392 * get next entry in a directory.
393 */
394struct direct *
e9e7ecc4 395rst_readdir(dirp)
f743fc86
KM
396 register DIR *dirp;
397{
398 register struct direct *dp;
399
400 for (;;) {
401 if (dirp->dd_loc == 0) {
402 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
403 DIRBLKSIZ);
93d90477
KM
404 if (dirp->dd_size <= 0) {
405 dprintf(stderr, "error reading directory\n");
f743fc86 406 return NULL;
93d90477 407 }
f743fc86
KM
408 }
409 if (dirp->dd_loc >= dirp->dd_size) {
410 dirp->dd_loc = 0;
411 continue;
412 }
413 dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
414 if (dp->d_reclen == 0 ||
93d90477
KM
415 dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
416 dprintf(stderr, "corrupted directory: bad reclen %d\n",
417 dp->d_reclen);
f743fc86 418 return NULL;
93d90477 419 }
f743fc86 420 dirp->dd_loc += dp->d_reclen;
93d90477
KM
421 if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0)
422 continue;
e9e7ecc4 423 if (dp->d_ino >= maxino) {
93d90477
KM
424 dprintf(stderr, "corrupted directory: bad inum %d\n",
425 dp->d_ino);
426 continue;
427 }
f743fc86
KM
428 return (dp);
429 }
430}
431
432/*
433 * Set the mode, owner, and times for all new or changed directories
434 */
7432ff81 435setdirmodes()
f743fc86
KM
436{
437 FILE *mf;
438 struct modeinfo node;
439 struct entry *ep;
440 char *cp;
441
442 vprintf(stdout, "Set directory mode, owner, and times.\n");
97b06931 443 (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate);
f743fc86
KM
444 mf = fopen(modefile, "r");
445 if (mf == NULL) {
446 perror("fopen");
97b06931
KM
447 fprintf(stderr, "cannot open mode file %s\n", modefile);
448 fprintf(stderr, "directory mode, owner, and times not set\n");
449 return;
f743fc86
KM
450 }
451 clearerr(mf);
9f13f26d 452 for (;;) {
82d46726 453 (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf);
9f13f26d
KM
454 if (feof(mf))
455 break;
f743fc86 456 ep = lookupino(node.ino);
47769c2e
KM
457 if (command == 'i' || command == 'x') {
458 if (ep == NIL)
459 continue;
460 if (node.ino == ROOTINO &&
461 reply("set owner/mode for '.'") == FAIL)
9f13f26d 462 continue;
9f13f26d 463 }
47769c2e
KM
464 if (ep == NIL)
465 panic("cannot find directory inode %d\n", node.ino);
f743fc86 466 cp = myname(ep);
82d46726
KM
467 (void) chown(cp, node.uid, node.gid);
468 (void) chmod(cp, node.mode);
f743fc86 469 utime(cp, node.timep);
7432ff81 470 ep->e_flags &= ~NEW;
f743fc86
KM
471 }
472 if (ferror(mf))
473 panic("error setting directory modes\n");
82d46726 474 (void) fclose(mf);
f743fc86
KM
475}
476
477/*
478 * Generate a literal copy of a directory.
479 */
480genliteraldir(name, ino)
481 char *name;
482 ino_t ino;
483{
484 register struct inotab *itp;
485 int ofile, dp, i, size;
486 char buf[BUFSIZ];
487
488 itp = inotablookup(ino);
489 if (itp == NULL)
9730f69a 490 panic("Cannot find directory inode %d named %s\n", ino, name);
15aeb519 491 if ((ofile = creat(name, 0666)) < 0) {
e9e7ecc4
KM
492 fprintf(stderr, "%s: ", name);
493 (void) fflush(stderr);
494 perror("cannot create file");
f743fc86
KM
495 return (FAIL);
496 }
e9e7ecc4 497 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
f743fc86
KM
498 dp = dup(dirp->dd_fd);
499 for (i = itp->t_size; i > 0; i -= BUFSIZ) {
500 size = i < BUFSIZ ? i : BUFSIZ;
501 if (read(dp, buf, (int) size) == -1) {
502 fprintf(stderr,
503 "write error extracting inode %d, name %s\n",
504 curfile.ino, curfile.name);
505 perror("read");
506 done(1);
507 }
508 if (write(ofile, buf, (int) size) == -1) {
509 fprintf(stderr,
510 "write error extracting inode %d, name %s\n",
511 curfile.ino, curfile.name);
512 perror("write");
513 done(1);
514 }
515 }
82d46726
KM
516 (void) close(dp);
517 (void) close(ofile);
f743fc86
KM
518 return (GOOD);
519}
520
7432ff81
KM
521/*
522 * Do an "ls" style listing of a directory
523 */
524printlist(name, ino)
525 char *name;
526 ino_t ino;
527{
528 register struct afile *fp;
529 register struct inotab *itp;
530 struct afile *dfp0, *dfplast;
531 struct afile single;
532
533 itp = inotablookup(ino);
534 if (itp == NULL) {
535 single.fnum = ino;
536 single.fname = savename(rindex(name, '/') + 1);
537 dfp0 = &single;
538 dfplast = dfp0 + 1;
539 } else {
e9e7ecc4 540 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
7432ff81
KM
541 if (getdir(dirp, &dfp0, &dfplast) == FAIL)
542 return;
543 }
544 qsort((char *)dfp0, dfplast - dfp0, sizeof (struct afile), fcmp);
545 formatf(dfp0, dfplast);
546 for (fp = dfp0; fp < dfplast; fp++)
547 freename(fp->fname);
548}
549
550/*
551 * Read the contents of a directory.
552 */
553getdir(dirp, pfp0, pfplast)
554 DIR *dirp;
555 struct afile **pfp0, **pfplast;
556{
557 register struct afile *fp;
558 register struct direct *dp;
559 static struct afile *basefp = NULL;
560 static long nent = 20;
561
ad4fabdf 562 if (basefp == NULL) {
7432ff81
KM
563 basefp = (struct afile *)calloc((unsigned)nent,
564 sizeof (struct afile));
ad4fabdf
KM
565 if (basefp == NULL) {
566 fprintf(stderr, "ls: out of memory\n");
567 return (FAIL);
568 }
569 }
7432ff81
KM
570 fp = *pfp0 = basefp;
571 *pfplast = *pfp0 + nent;
e9e7ecc4 572 while (dp = rst_readdir(dirp)) {
93d90477 573 if (dp == NULL || dp->d_ino == 0)
7432ff81 574 break;
93d90477 575 if (!dflag && BIT(dp->d_ino, dumpmap) == 0)
7432ff81
KM
576 continue;
577 if (vflag == 0 &&
578 (strcmp(dp->d_name, ".") == 0 ||
579 strcmp(dp->d_name, "..") == 0))
580 continue;
581 fp->fnum = dp->d_ino;
582 fp->fname = savename(dp->d_name);
583 fp++;
584 if (fp == *pfplast) {
585 basefp = (struct afile *)realloc((char *)basefp,
586 (unsigned)(2 * nent * sizeof (struct afile)));
587 if (basefp == 0) {
588 fprintf(stderr, "ls: out of memory\n");
589 return (FAIL);
590 }
591 *pfp0 = basefp;
592 fp = *pfp0 + nent;
593 *pfplast = fp + nent;
594 nent *= 2;
595 }
596 }
597 *pfplast = fp;
598 return (GOOD);
599}
600
601/*
602 * Print out a pretty listing of a directory
603 */
604formatf(fp0, fplast)
605 struct afile *fp0, *fplast;
606{
607 register struct afile *fp;
608 struct entry *np;
609 int width = 0, w, nentry = fplast - fp0;
610 int i, j, len, columns, lines;
611 char *cp;
612
613 if (fp0 == fplast)
614 return;
615 for (fp = fp0; fp < fplast; fp++) {
616 fp->ftype = inodetype(fp->fnum);
617 np = lookupino(fp->fnum);
618 if (np != NIL)
619 fp->fflags = np->e_flags;
620 else
621 fp->fflags = 0;
622 len = strlen(fmtentry(fp));
623 if (len > width)
624 width = len;
625 }
626 width += 2;
627 columns = 80 / width;
628 if (columns == 0)
629 columns = 1;
630 lines = (nentry + columns - 1) / columns;
631 for (i = 0; i < lines; i++) {
632 for (j = 0; j < columns; j++) {
633 fp = fp0 + j * lines + i;
634 cp = fmtentry(fp);
635 fprintf(stderr, "%s", cp);
636 if (fp + lines >= fplast) {
637 fprintf(stderr, "\n");
638 break;
639 }
640 w = strlen(cp);
641 while (w < width) {
642 w++;
643 fprintf(stderr, " ");
644 }
645 }
646 }
647}
648
649/*
650 * Comparison routine for qsort.
651 */
652fcmp(f1, f2)
653 register struct afile *f1, *f2;
654{
655
656 return (strcmp(f1->fname, f2->fname));
657}
658
659/*
660 * Format a directory entry.
661 */
662char *
663fmtentry(fp)
664 register struct afile *fp;
665{
666 static char fmtres[BUFSIZ];
667 register char *cp, *dp;
668
669 if (vflag)
670 (void) sprintf(fmtres, "%5d ", fp->fnum);
671 else
672 fmtres[0] = '\0';
673 dp = &fmtres[strlen(fmtres)];
93d90477
KM
674 if (dflag && BIT(fp->fnum, dumpmap) == 0)
675 *dp++ = '^';
676 else if ((fp->fflags & NEW) != 0)
7432ff81
KM
677 *dp++ = '*';
678 else
679 *dp++ = ' ';
680 for (cp = fp->fname; *cp; cp++)
681 if (!vflag && (*cp < ' ' || *cp >= 0177))
682 *dp++ = '?';
683 else
684 *dp++ = *cp;
685 if (fp->ftype == NODE)
686 *dp++ = '/';
687 *dp++ = 0;
688 return (fmtres);
689}
690
691/*
692 * Determine the type of an inode
693 */
694inodetype(ino)
695 ino_t ino;
696{
697 struct inotab *itp;
698
699 itp = inotablookup(ino);
700 if (itp == NULL)
701 return (LEAF);
702 return (NODE);
703}
704
f743fc86
KM
705/*
706 * Allocate and initialize a directory inode entry.
707 * If requested, save its pertinent mode, owner, and time info.
708 */
9730f69a 709struct inotab *
f743fc86
KM
710allocinotab(ino, dip, seekpt)
711 ino_t ino;
712 struct dinode *dip;
713 daddr_t seekpt;
714{
715 register struct inotab *itp;
716 struct modeinfo node;
f743fc86
KM
717
718 itp = (struct inotab *)calloc(1, sizeof(struct inotab));
ad4fabdf
KM
719 if (itp == 0)
720 panic("no memory directory table\n");
f743fc86
KM
721 itp->t_next = inotab[INOHASH(ino)];
722 inotab[INOHASH(ino)] = itp;
723 itp->t_ino = ino;
724 itp->t_seekpt = seekpt;
f743fc86 725 if (mf == NULL)
9730f69a 726 return(itp);
f743fc86
KM
727 node.ino = ino;
728 node.timep[0] = dip->di_atime;
729 node.timep[1] = dip->di_mtime;
730 node.mode = dip->di_mode;
731 node.uid = dip->di_uid;
732 node.gid = dip->di_gid;
82d46726 733 (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);
9730f69a 734 return(itp);
f743fc86
KM
735}
736
737/*
738 * Look up an inode in the table of directories
739 */
740struct inotab *
741inotablookup(ino)
742 ino_t ino;
743{
744 register struct inotab *itp;
745
746 for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next)
747 if (itp->t_ino == ino)
748 return(itp);
749 return ((struct inotab *)0);
750}
751
752/*
753 * Clean up and exit
754 */
755done(exitcode)
756 int exitcode;
757{
758
759 closemt();
7432ff81
KM
760 if (modefile[0] != '#')
761 (void) unlink(modefile);
762 if (dirfile[0] != '#')
763 (void) unlink(dirfile);
f743fc86
KM
764 exit(exitcode);
765}