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