Commit | Line | Data |
---|---|---|
8c5eec2f DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
f743fc86 | 6 | |
8c5eec2f | 7 | #ifndef lint |
329dd5fb | 8 | static char sccsid[] = "@(#)dirs.c 5.4 (Berkeley) %G%"; |
8c5eec2f | 9 | #endif not lint |
ebd1f727 | 10 | |
f743fc86 | 11 | #include "restore.h" |
d9127117 | 12 | #include <protocols/dumprestore.h> |
9f13f26d | 13 | #include <sys/file.h> |
f743fc86 | 14 | |
7432ff81 KM |
15 | /* |
16 | * Symbol table of directories read from tape. | |
17 | */ | |
f743fc86 | 18 | #define HASHSIZE 1000 |
f743fc86 KM |
19 | #define INOHASH(val) (val % HASHSIZE) |
20 | struct inotab { | |
21 | struct inotab *t_next; | |
22 | ino_t t_ino; | |
23 | daddr_t t_seekpt; | |
24 | long t_size; | |
9f13f26d KM |
25 | }; |
26 | static struct inotab *inotab[HASHSIZE]; | |
27 | extern struct inotab *inotablookup(); | |
9730f69a | 28 | extern struct inotab *allocinotab(); |
f743fc86 | 29 | |
7432ff81 KM |
30 | /* |
31 | * Information retained about directories. | |
32 | */ | |
f743fc86 KM |
33 | struct modeinfo { |
34 | ino_t ino; | |
35 | time_t timep[2]; | |
36 | short mode; | |
37 | short uid; | |
38 | short gid; | |
39 | }; | |
40 | ||
7432ff81 KM |
41 | /* |
42 | * Global variables for this file. | |
43 | */ | |
9f13f26d KM |
44 | static daddr_t seekpt; |
45 | static FILE *df, *mf; | |
46 | static DIR *dirp; | |
7432ff81 KM |
47 | static char dirfile[32] = "#"; /* No file */ |
48 | static char modefile[32] = "#"; /* No file */ | |
9f13f26d | 49 | extern ino_t search(); |
e9e7ecc4 KM |
50 | struct direct *rst_readdir(); |
51 | extern void rst_seekdir(); | |
f743fc86 | 52 | |
7432ff81 KM |
53 | /* |
54 | * Format of old style directories. | |
55 | */ | |
f743fc86 KM |
56 | #define ODIRSIZ 14 |
57 | struct odirect { | |
58 | u_short d_ino; | |
59 | char d_name[ODIRSIZ]; | |
60 | }; | |
61 | ||
62 | /* | |
63 | * Extract directory contents, building up a directory structure | |
64 | * on disk for extraction by name. | |
7432ff81 | 65 | * If genmode is requested, save mode, owner, and times for all |
f743fc86 KM |
66 | * directories on the tape. |
67 | */ | |
7432ff81 KM |
68 | extractdirs(genmode) |
69 | int genmode; | |
f743fc86 KM |
70 | { |
71 | register int i; | |
72 | register struct dinode *ip; | |
9730f69a | 73 | struct inotab *itp; |
f743fc86 KM |
74 | struct direct nulldir; |
75 | int putdir(), null(); | |
76 | ||
77 | vprintf(stdout, "Extract directories from tape\n"); | |
7432ff81 | 78 | (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate); |
f743fc86 KM |
79 | df = fopen(dirfile, "w"); |
80 | if (df == 0) { | |
81 | fprintf(stderr, | |
97b06931 | 82 | "restore: %s - cannot create directory temporary\n", |
f743fc86 KM |
83 | dirfile); |
84 | perror("fopen"); | |
85 | done(1); | |
86 | } | |
7432ff81 KM |
87 | if (genmode != 0) { |
88 | (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); | |
f743fc86 | 89 | mf = fopen(modefile, "w"); |
9f13f26d | 90 | if (mf == 0) { |
f743fc86 | 91 | fprintf(stderr, |
97b06931 | 92 | "restore: %s - cannot create modefile \n", |
f743fc86 KM |
93 | modefile); |
94 | perror("fopen"); | |
95 | done(1); | |
96 | } | |
97 | } | |
9730f69a | 98 | nulldir.d_ino = 0; |
f743fc86 | 99 | nulldir.d_namlen = 1; |
93d90477 | 100 | (void) strcpy(nulldir.d_name, "/"); |
f743fc86 KM |
101 | nulldir.d_reclen = DIRSIZ(&nulldir); |
102 | for (;;) { | |
103 | curfile.name = "<directory file - name unknown>"; | |
104 | curfile.action = USING; | |
105 | ip = curfile.dip; | |
58ee757a | 106 | if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { |
82d46726 | 107 | (void) fclose(df); |
f743fc86 KM |
108 | dirp = opendir(dirfile); |
109 | if (dirp == NULL) | |
110 | perror("opendir"); | |
111 | if (mf != NULL) | |
82d46726 | 112 | (void) fclose(mf); |
7432ff81 KM |
113 | i = dirlookup("."); |
114 | if (i == 0) | |
7851e15d | 115 | panic("Root directory is not on tape\n"); |
f743fc86 KM |
116 | return; |
117 | } | |
9730f69a | 118 | itp = allocinotab(curfile.ino, ip, seekpt); |
f743fc86 KM |
119 | getfile(putdir, null); |
120 | putent(&nulldir); | |
121 | flushent(); | |
9730f69a KM |
122 | itp->t_size = seekpt - itp->t_seekpt; |
123 | } | |
124 | } | |
125 | ||
126 | /* | |
127 | * skip over all the directories on the tape | |
128 | */ | |
129 | skipdirs() | |
130 | { | |
131 | ||
132 | while ((curfile.dip->di_mode & IFMT) == IFDIR) { | |
133 | skipfile(); | |
f743fc86 KM |
134 | } |
135 | } | |
136 | ||
137 | /* | |
138 | * Recursively find names and inumbers of all files in subtree | |
139 | * pname and pass them off to be processed. | |
140 | */ | |
141 | treescan(pname, ino, todo) | |
142 | char *pname; | |
143 | ino_t ino; | |
314ac756 | 144 | long (*todo)(); |
f743fc86 KM |
145 | { |
146 | register struct inotab *itp; | |
93d90477 KM |
147 | register struct direct *dp; |
148 | register struct entry *np; | |
f743fc86 KM |
149 | int namelen; |
150 | daddr_t bpt; | |
4796d2a4 | 151 | char locname[MAXPATHLEN + 1]; |
f743fc86 KM |
152 | |
153 | itp = inotablookup(ino); | |
154 | if (itp == NULL) { | |
155 | /* | |
156 | * Pname is name of a simple file or an unchanged directory. | |
157 | */ | |
314ac756 | 158 | (void) (*todo)(pname, ino, LEAF); |
f743fc86 KM |
159 | return; |
160 | } | |
161 | /* | |
162 | * Pname is a dumped directory name. | |
163 | */ | |
314ac756 KM |
164 | if ((*todo)(pname, ino, NODE) == FAIL) |
165 | return; | |
f743fc86 KM |
166 | /* |
167 | * begin search through the directory | |
168 | * skipping over "." and ".." | |
169 | */ | |
7432ff81 KM |
170 | (void) strncpy(locname, pname, MAXPATHLEN); |
171 | (void) strncat(locname, "/", MAXPATHLEN); | |
f743fc86 | 172 | namelen = strlen(locname); |
e9e7ecc4 KM |
173 | rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); |
174 | dp = rst_readdir(dirp); /* "." */ | |
329dd5fb | 175 | if (dp != NULL && strcmp(dp->d_name, ".") == 0) |
e9e7ecc4 | 176 | dp = rst_readdir(dirp); /* ".." */ |
329dd5fb KM |
177 | else |
178 | fprintf(stderr, "Warning: `.' missing from directory %s\n", | |
179 | pname); | |
180 | if (dp != NULL && strcmp(dp->d_name, "..") == 0) | |
e9e7ecc4 | 181 | dp = rst_readdir(dirp); /* first real entry */ |
329dd5fb KM |
182 | else |
183 | fprintf(stderr, "Warning: `..' missing from directory %s\n", | |
184 | pname); | |
f743fc86 KM |
185 | bpt = telldir(dirp); |
186 | /* | |
93d90477 | 187 | * a zero inode signals end of directory |
f743fc86 | 188 | */ |
93d90477 | 189 | while (dp != NULL && dp->d_ino != 0) { |
f743fc86 | 190 | locname[namelen] = '\0'; |
4796d2a4 | 191 | if (namelen + dp->d_namlen >= MAXPATHLEN) { |
f743fc86 | 192 | fprintf(stderr, "%s%s: name exceeds %d char\n", |
4796d2a4 | 193 | locname, dp->d_name, MAXPATHLEN); |
f743fc86 | 194 | } else { |
7432ff81 | 195 | (void) strncat(locname, dp->d_name, (int)dp->d_namlen); |
f743fc86 | 196 | treescan(locname, dp->d_ino, todo); |
e9e7ecc4 | 197 | rst_seekdir(dirp, bpt, itp->t_seekpt); |
f743fc86 | 198 | } |
e9e7ecc4 | 199 | dp = rst_readdir(dirp); |
f743fc86 KM |
200 | bpt = telldir(dirp); |
201 | } | |
202 | if (dp == NULL) | |
203 | fprintf(stderr, "corrupted directory: %s.\n", locname); | |
204 | } | |
205 | ||
206 | /* | |
207 | * Search the directory tree rooted at inode ROOTINO | |
208 | * for the path pointed at by n | |
209 | */ | |
210 | ino_t | |
211 | psearch(n) | |
212 | char *n; | |
213 | { | |
214 | register char *cp, *cp1; | |
215 | ino_t ino; | |
216 | char c; | |
217 | ||
218 | ino = ROOTINO; | |
219 | if (*(cp = n) == '/') | |
220 | cp++; | |
221 | next: | |
222 | cp1 = cp + 1; | |
223 | while (*cp1 != '/' && *cp1) | |
224 | cp1++; | |
225 | c = *cp1; | |
226 | *cp1 = 0; | |
227 | ino = search(ino, cp); | |
228 | if (ino == 0) { | |
229 | *cp1 = c; | |
230 | return(0); | |
231 | } | |
232 | *cp1 = c; | |
233 | if (c == '/') { | |
234 | cp = cp1+1; | |
235 | goto next; | |
236 | } | |
237 | return(ino); | |
238 | } | |
239 | ||
240 | /* | |
241 | * search the directory inode ino | |
242 | * looking for entry cp | |
243 | */ | |
244 | ino_t | |
245 | search(inum, cp) | |
246 | ino_t inum; | |
247 | char *cp; | |
248 | { | |
249 | register struct direct *dp; | |
250 | register struct inotab *itp; | |
251 | int len; | |
252 | ||
253 | itp = inotablookup(inum); | |
254 | if (itp == NULL) | |
255 | return(0); | |
e9e7ecc4 | 256 | rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); |
f743fc86 KM |
257 | len = strlen(cp); |
258 | do { | |
e9e7ecc4 | 259 | dp = rst_readdir(dirp); |
93d90477 KM |
260 | if (dp == NULL || dp->d_ino == 0) |
261 | return (0); | |
7432ff81 | 262 | } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); |
f743fc86 KM |
263 | return(dp->d_ino); |
264 | } | |
265 | ||
266 | /* | |
267 | * Put the directory entries in the directory file | |
268 | */ | |
269 | putdir(buf, size) | |
270 | char *buf; | |
271 | int size; | |
272 | { | |
273 | struct direct cvtbuf; | |
274 | register struct odirect *odp; | |
275 | struct odirect *eodp; | |
276 | register struct direct *dp; | |
277 | long loc, i; | |
10462cc1 | 278 | extern int Bcvt; |
f743fc86 KM |
279 | |
280 | if (cvtflag) { | |
281 | eodp = (struct odirect *)&buf[size]; | |
282 | for (odp = (struct odirect *)buf; odp < eodp; odp++) | |
283 | if (odp->d_ino != 0) { | |
284 | dcvt(odp, &cvtbuf); | |
285 | putent(&cvtbuf); | |
286 | } | |
287 | } else { | |
288 | for (loc = 0; loc < size; ) { | |
289 | dp = (struct direct *)(buf + loc); | |
10462cc1 KS |
290 | if (Bcvt) { |
291 | swabst("l2s", (char *) dp); | |
292 | } | |
f743fc86 KM |
293 | i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); |
294 | if (dp->d_reclen == 0 || dp->d_reclen > i) { | |
295 | loc += i; | |
296 | continue; | |
297 | } | |
298 | loc += dp->d_reclen; | |
299 | if (dp->d_ino != 0) { | |
300 | putent(dp); | |
301 | } | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | /* | |
307 | * These variables are "local" to the following two functions. | |
308 | */ | |
309 | char dirbuf[DIRBLKSIZ]; | |
310 | long dirloc = 0; | |
311 | long prev = 0; | |
312 | ||
313 | /* | |
314 | * add a new directory entry to a file. | |
315 | */ | |
316 | putent(dp) | |
317 | struct direct *dp; | |
318 | { | |
9730f69a | 319 | dp->d_reclen = DIRSIZ(dp); |
f743fc86 KM |
320 | if (dirloc + dp->d_reclen > DIRBLKSIZ) { |
321 | ((struct direct *)(dirbuf + prev))->d_reclen = | |
322 | DIRBLKSIZ - prev; | |
82d46726 | 323 | (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); |
f743fc86 KM |
324 | dirloc = 0; |
325 | } | |
326 | bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); | |
327 | prev = dirloc; | |
328 | dirloc += dp->d_reclen; | |
329 | } | |
330 | ||
331 | /* | |
332 | * flush out a directory that is finished. | |
333 | */ | |
334 | flushent() | |
335 | { | |
336 | ||
337 | ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; | |
82d46726 | 338 | (void) fwrite(dirbuf, (int)dirloc, 1, df); |
f743fc86 KM |
339 | seekpt = ftell(df); |
340 | dirloc = 0; | |
341 | } | |
342 | ||
343 | dcvt(odp, ndp) | |
344 | register struct odirect *odp; | |
345 | register struct direct *ndp; | |
346 | { | |
347 | ||
348 | bzero((char *)ndp, (long)(sizeof *ndp)); | |
349 | ndp->d_ino = odp->d_ino; | |
7432ff81 | 350 | (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); |
f743fc86 KM |
351 | ndp->d_namlen = strlen(ndp->d_name); |
352 | ndp->d_reclen = DIRSIZ(ndp); | |
f743fc86 KM |
353 | } |
354 | ||
355 | /* | |
356 | * Seek to an entry in a directory. | |
e9e7ecc4 | 357 | * Only values returned by ``telldir'' should be passed to rst_seekdir. |
82d46726 KM |
358 | * This routine handles many directories in a single file. |
359 | * It takes the base of the directory in the file, plus | |
360 | * the desired seek offset into it. | |
f743fc86 KM |
361 | */ |
362 | void | |
e9e7ecc4 | 363 | rst_seekdir(dirp, loc, base) |
f743fc86 KM |
364 | register DIR *dirp; |
365 | daddr_t loc, base; | |
366 | { | |
367 | ||
368 | if (loc == telldir(dirp)) | |
369 | return; | |
370 | loc -= base; | |
371 | if (loc < 0) | |
e9e7ecc4 | 372 | fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); |
f743fc86 KM |
373 | (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); |
374 | dirp->dd_loc = loc & (DIRBLKSIZ - 1); | |
375 | if (dirp->dd_loc != 0) | |
376 | dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); | |
377 | } | |
378 | ||
379 | /* | |
380 | * get next entry in a directory. | |
381 | */ | |
382 | struct direct * | |
e9e7ecc4 | 383 | rst_readdir(dirp) |
f743fc86 KM |
384 | register DIR *dirp; |
385 | { | |
386 | register struct direct *dp; | |
387 | ||
388 | for (;;) { | |
389 | if (dirp->dd_loc == 0) { | |
390 | dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, | |
391 | DIRBLKSIZ); | |
93d90477 KM |
392 | if (dirp->dd_size <= 0) { |
393 | dprintf(stderr, "error reading directory\n"); | |
f743fc86 | 394 | return NULL; |
93d90477 | 395 | } |
f743fc86 KM |
396 | } |
397 | if (dirp->dd_loc >= dirp->dd_size) { | |
398 | dirp->dd_loc = 0; | |
399 | continue; | |
400 | } | |
401 | dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); | |
402 | if (dp->d_reclen == 0 || | |
93d90477 KM |
403 | dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { |
404 | dprintf(stderr, "corrupted directory: bad reclen %d\n", | |
405 | dp->d_reclen); | |
f743fc86 | 406 | return NULL; |
93d90477 | 407 | } |
f743fc86 | 408 | dirp->dd_loc += dp->d_reclen; |
93d90477 KM |
409 | if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) |
410 | continue; | |
e9e7ecc4 | 411 | if (dp->d_ino >= maxino) { |
93d90477 KM |
412 | dprintf(stderr, "corrupted directory: bad inum %d\n", |
413 | dp->d_ino); | |
414 | continue; | |
415 | } | |
f743fc86 KM |
416 | return (dp); |
417 | } | |
418 | } | |
419 | ||
f97d7036 KM |
420 | /* |
421 | * Simulate the opening of a directory | |
422 | */ | |
423 | DIR * | |
424 | rst_opendir(name) | |
425 | char *name; | |
426 | { | |
427 | struct inotab *itp; | |
428 | ino_t ino; | |
429 | ||
430 | if ((ino = dirlookup(name)) > 0 && | |
431 | (itp = inotablookup(ino)) != NULL) { | |
432 | rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); | |
433 | return (dirp); | |
434 | } | |
435 | return (0); | |
436 | } | |
437 | ||
f743fc86 KM |
438 | /* |
439 | * Set the mode, owner, and times for all new or changed directories | |
440 | */ | |
7432ff81 | 441 | setdirmodes() |
f743fc86 KM |
442 | { |
443 | FILE *mf; | |
444 | struct modeinfo node; | |
445 | struct entry *ep; | |
446 | char *cp; | |
447 | ||
448 | vprintf(stdout, "Set directory mode, owner, and times.\n"); | |
97b06931 | 449 | (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); |
f743fc86 KM |
450 | mf = fopen(modefile, "r"); |
451 | if (mf == NULL) { | |
452 | perror("fopen"); | |
97b06931 KM |
453 | fprintf(stderr, "cannot open mode file %s\n", modefile); |
454 | fprintf(stderr, "directory mode, owner, and times not set\n"); | |
455 | return; | |
f743fc86 KM |
456 | } |
457 | clearerr(mf); | |
9f13f26d | 458 | for (;;) { |
82d46726 | 459 | (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); |
9f13f26d KM |
460 | if (feof(mf)) |
461 | break; | |
f743fc86 | 462 | ep = lookupino(node.ino); |
47769c2e KM |
463 | if (command == 'i' || command == 'x') { |
464 | if (ep == NIL) | |
465 | continue; | |
a7d37956 KM |
466 | if (ep->e_flags & EXISTED) { |
467 | ep->e_flags &= ~NEW; | |
468 | continue; | |
469 | } | |
47769c2e KM |
470 | if (node.ino == ROOTINO && |
471 | reply("set owner/mode for '.'") == FAIL) | |
9f13f26d | 472 | continue; |
9f13f26d | 473 | } |
47769c2e KM |
474 | if (ep == NIL) |
475 | panic("cannot find directory inode %d\n", node.ino); | |
f743fc86 | 476 | cp = myname(ep); |
82d46726 KM |
477 | (void) chown(cp, node.uid, node.gid); |
478 | (void) chmod(cp, node.mode); | |
f743fc86 | 479 | utime(cp, node.timep); |
7432ff81 | 480 | ep->e_flags &= ~NEW; |
f743fc86 KM |
481 | } |
482 | if (ferror(mf)) | |
483 | panic("error setting directory modes\n"); | |
82d46726 | 484 | (void) fclose(mf); |
f743fc86 KM |
485 | } |
486 | ||
487 | /* | |
488 | * Generate a literal copy of a directory. | |
489 | */ | |
490 | genliteraldir(name, ino) | |
491 | char *name; | |
492 | ino_t ino; | |
493 | { | |
494 | register struct inotab *itp; | |
495 | int ofile, dp, i, size; | |
496 | char buf[BUFSIZ]; | |
497 | ||
498 | itp = inotablookup(ino); | |
499 | if (itp == NULL) | |
9730f69a | 500 | panic("Cannot find directory inode %d named %s\n", ino, name); |
15aeb519 | 501 | if ((ofile = creat(name, 0666)) < 0) { |
e9e7ecc4 KM |
502 | fprintf(stderr, "%s: ", name); |
503 | (void) fflush(stderr); | |
504 | perror("cannot create file"); | |
f743fc86 KM |
505 | return (FAIL); |
506 | } | |
e9e7ecc4 | 507 | rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); |
f743fc86 KM |
508 | dp = dup(dirp->dd_fd); |
509 | for (i = itp->t_size; i > 0; i -= BUFSIZ) { | |
510 | size = i < BUFSIZ ? i : BUFSIZ; | |
511 | if (read(dp, buf, (int) size) == -1) { | |
512 | fprintf(stderr, | |
513 | "write error extracting inode %d, name %s\n", | |
514 | curfile.ino, curfile.name); | |
515 | perror("read"); | |
516 | done(1); | |
517 | } | |
518 | if (write(ofile, buf, (int) size) == -1) { | |
519 | fprintf(stderr, | |
520 | "write error extracting inode %d, name %s\n", | |
521 | curfile.ino, curfile.name); | |
522 | perror("write"); | |
523 | done(1); | |
524 | } | |
525 | } | |
82d46726 KM |
526 | (void) close(dp); |
527 | (void) close(ofile); | |
f743fc86 KM |
528 | return (GOOD); |
529 | } | |
530 | ||
7432ff81 KM |
531 | /* |
532 | * Determine the type of an inode | |
533 | */ | |
534 | inodetype(ino) | |
535 | ino_t ino; | |
536 | { | |
537 | struct inotab *itp; | |
538 | ||
539 | itp = inotablookup(ino); | |
540 | if (itp == NULL) | |
541 | return (LEAF); | |
542 | return (NODE); | |
543 | } | |
544 | ||
f743fc86 KM |
545 | /* |
546 | * Allocate and initialize a directory inode entry. | |
547 | * If requested, save its pertinent mode, owner, and time info. | |
548 | */ | |
9730f69a | 549 | struct inotab * |
f743fc86 KM |
550 | allocinotab(ino, dip, seekpt) |
551 | ino_t ino; | |
552 | struct dinode *dip; | |
553 | daddr_t seekpt; | |
554 | { | |
555 | register struct inotab *itp; | |
556 | struct modeinfo node; | |
f743fc86 KM |
557 | |
558 | itp = (struct inotab *)calloc(1, sizeof(struct inotab)); | |
ad4fabdf KM |
559 | if (itp == 0) |
560 | panic("no memory directory table\n"); | |
f743fc86 KM |
561 | itp->t_next = inotab[INOHASH(ino)]; |
562 | inotab[INOHASH(ino)] = itp; | |
563 | itp->t_ino = ino; | |
564 | itp->t_seekpt = seekpt; | |
f743fc86 | 565 | if (mf == NULL) |
9730f69a | 566 | return(itp); |
f743fc86 KM |
567 | node.ino = ino; |
568 | node.timep[0] = dip->di_atime; | |
569 | node.timep[1] = dip->di_mtime; | |
570 | node.mode = dip->di_mode; | |
571 | node.uid = dip->di_uid; | |
572 | node.gid = dip->di_gid; | |
82d46726 | 573 | (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); |
9730f69a | 574 | return(itp); |
f743fc86 KM |
575 | } |
576 | ||
577 | /* | |
578 | * Look up an inode in the table of directories | |
579 | */ | |
580 | struct inotab * | |
581 | inotablookup(ino) | |
582 | ino_t ino; | |
583 | { | |
584 | register struct inotab *itp; | |
585 | ||
586 | for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) | |
587 | if (itp->t_ino == ino) | |
588 | return(itp); | |
589 | return ((struct inotab *)0); | |
590 | } | |
591 | ||
592 | /* | |
593 | * Clean up and exit | |
594 | */ | |
595 | done(exitcode) | |
596 | int exitcode; | |
597 | { | |
598 | ||
599 | closemt(); | |
7432ff81 KM |
600 | if (modefile[0] != '#') |
601 | (void) unlink(modefile); | |
602 | if (dirfile[0] != '#') | |
603 | (void) unlink(dirfile); | |
f743fc86 KM |
604 | exit(exitcode); |
605 | } |