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