Commit | Line | Data |
---|---|---|
7d4dda01 KM |
1 | /* Copyright (c) 1981 Regents of the University of California */ |
2 | ||
f7287e4b | 3 | char version[] = "@(#)main.c 1.14 %G%"; |
7d4dda01 KM |
4 | |
5 | /* Modified to include h option (recursively extract all files within | |
6 | * a subtree) and m option (recreate the heirarchical structure of | |
7 | * that subtree and move extracted files to their proper homes). | |
8 | * 8/29/80 by Mike Litzkow | |
9 | * | |
10 | * Includes the s (skip files) option for use with multiple dumps on | |
11 | * a single tape. | |
12 | */ | |
13 | ||
e077bab5 | 14 | /* static char *sccsid = "@(#)restor.c 4.3 (Berkeley) 6/3/81"; */ |
7d4dda01 KM |
15 | |
16 | #define MAXINO 3000 | |
17 | #define BITS 8 | |
18 | #define NCACHE 3 | |
7d4dda01 KM |
19 | #define SIZEINC 10 |
20 | ||
21 | #ifndef STANDALONE | |
22 | #include <stdio.h> | |
23 | #include <signal.h> | |
24 | #endif | |
003a2a9e KM |
25 | #include "../h/param.h" |
26 | #include "../h/inode.h" | |
27 | #include "../h/fs.h" | |
28 | #include "../h/buf.h" | |
003a2a9e KM |
29 | #include "../h/user.h" |
30 | #include "../h/dumprestor.h" | |
b88e54cb KM |
31 | #include <sys/mtio.h> |
32 | ||
b45e25c0 | 33 | #define ODIRSIZ 14 |
b88e54cb KM |
34 | struct odirect { |
35 | u_short d_ino; | |
b45e25c0 | 36 | char d_name[ODIRSIZ]; |
b88e54cb | 37 | }; |
7d4dda01 | 38 | |
b6407c9d KM |
39 | #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) |
40 | #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) | |
7d4dda01 KM |
41 | #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) |
42 | #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) | |
43 | #define BIT(i,w) (MWORD(w,i) & MBIT(i)) | |
44 | ||
003a2a9e | 45 | ino_t ino, maxi; |
b88e54cb | 46 | struct inode *cur_ip; |
7d4dda01 | 47 | |
b88e54cb | 48 | int eflag = 0, hflag = 0, mflag = 0, cvtdir = 0; |
7d4dda01 | 49 | |
003a2a9e KM |
50 | char mounted = 0; |
51 | dev_t dev = 0; | |
f7287e4b KM |
52 | struct fs *fsptr; |
53 | struct inode parentino; | |
7d4dda01 KM |
54 | char tapename[] = "/dev/rmt8"; |
55 | char *magtape = tapename; | |
b88e54cb KM |
56 | int mt; |
57 | int dumpnum = 1; | |
58 | int volno = 1; | |
59 | int curblk = 0; | |
60 | int bct = NTREC+1; | |
61 | char tbf[NTREC*TP_BSIZE]; | |
7d4dda01 KM |
62 | |
63 | #ifdef STANDALONE | |
64 | char mbuf[50]; | |
65 | #endif | |
66 | ||
7d4dda01 | 67 | daddr_t seekpt; |
0841dbb0 | 68 | FILE *df; |
b45e25c0 | 69 | DIR *dirp; |
0841dbb0 | 70 | int ofile; |
7d4dda01 KM |
71 | char dirfile[] = "rstXXXXXX"; |
72 | ||
0841dbb0 KM |
73 | #define INOHASH(val) (val % MAXINO) |
74 | struct inotab { | |
75 | struct inotab *t_next; | |
7d4dda01 KM |
76 | ino_t t_ino; |
77 | daddr_t t_seekpt; | |
0841dbb0 | 78 | } *inotab[MAXINO]; |
7d4dda01 | 79 | |
0841dbb0 | 80 | #define XISDIR 1 |
7d4dda01 KM |
81 | #define XTRACTD 2 |
82 | #define XINUSE 4 | |
0841dbb0 | 83 | #define XLINKED 8 |
7d4dda01 | 84 | struct xtrlist { |
0841dbb0 KM |
85 | struct xtrlist *x_next; |
86 | struct xtrlist *x_linkedto; | |
0841dbb0 | 87 | time_t x_timep[2]; |
bcfabedf | 88 | ino_t x_ino; |
0841dbb0 | 89 | char x_flags; |
bcfabedf KM |
90 | char x_name[1]; |
91 | /* actually longer */ | |
0841dbb0 | 92 | } *xtrlist[MAXINO]; |
19ac1bc8 | 93 | int xtrcnt = 0; |
7d4dda01 | 94 | |
b6407c9d KM |
95 | #ifdef STANDALONE |
96 | #define msiz 8192 | |
97 | char dumpmap[msiz]; | |
98 | char clrimap[msiz]; | |
99 | #else | |
100 | int msiz; | |
101 | char *dumpmap; | |
102 | char *clrimap; | |
103 | #endif | |
104 | ||
105 | char clearedbuf[MAXBSIZE]; | |
7d4dda01 | 106 | |
0841dbb0 | 107 | extern char *ctime(); |
bcfabedf | 108 | ino_t search(); |
b45e25c0 | 109 | int dirwrite(); |
003a2a9e | 110 | char **envp; |
7d4dda01 | 111 | |
003a2a9e KM |
112 | main(argc, argv, arge) |
113 | int argc; | |
114 | char *argv[]; | |
115 | char **arge; | |
7d4dda01 KM |
116 | { |
117 | register char *cp; | |
118 | char command; | |
003a2a9e | 119 | int (*signal())(); |
7d4dda01 KM |
120 | int done(); |
121 | ||
bcfabedf KM |
122 | if (signal(SIGINT, done) == SIG_IGN) |
123 | signal(SIGINT, SIG_IGN); | |
124 | if (signal(SIGTERM, done) == SIG_IGN) | |
125 | signal(SIGTERM, SIG_IGN); | |
7d4dda01 | 126 | #ifndef STANDALONE |
003a2a9e KM |
127 | envp = arge; |
128 | mktmp(dirfile); | |
7d4dda01 KM |
129 | if (argc < 2) { |
130 | usage: | |
0841dbb0 | 131 | fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n"); |
003a2a9e | 132 | done(1); |
7d4dda01 KM |
133 | } |
134 | argv++; | |
135 | argc -= 2; | |
136 | for (cp = *argv++; *cp; cp++) { | |
137 | switch (*cp) { | |
138 | case '-': | |
139 | break; | |
140 | case 'f': | |
141 | magtape = *argv++; | |
142 | argc--; | |
143 | break; | |
144 | /* s dumpnum (skip to) for multifile dump tapes */ | |
145 | case 's': | |
146 | dumpnum = atoi(*argv++); | |
147 | if(dumpnum <= 0) { | |
003a2a9e KM |
148 | fprintf(stderr, "Dump number must be a positive integer\n"); |
149 | done(1); | |
7d4dda01 KM |
150 | } |
151 | argc--; | |
152 | break; | |
153 | case 'h': | |
154 | hflag++; | |
155 | break; | |
156 | case 'm': | |
157 | mflag++; | |
158 | break; | |
159 | case 'r': | |
160 | case 'R': | |
161 | case 't': | |
162 | case 'x': | |
163 | command = *cp; | |
164 | break; | |
165 | default: | |
003a2a9e | 166 | fprintf(stderr, "Bad key character %c\n", *cp); |
7d4dda01 KM |
167 | goto usage; |
168 | } | |
169 | } | |
170 | if (command == 'x') { | |
0841dbb0 KM |
171 | df = fopen(dirfile, "w"); |
172 | if (df == 0) { | |
003a2a9e KM |
173 | fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile); |
174 | done(1); | |
7d4dda01 | 175 | } |
003a2a9e KM |
176 | xmount(envp); |
177 | mounted++; | |
7d4dda01 KM |
178 | } |
179 | doit(command, argc, argv); | |
003a2a9e | 180 | done(0); |
7d4dda01 KM |
181 | #else |
182 | magtape = "tape"; | |
183 | doit('r', 1, 0); | |
184 | #endif | |
185 | } | |
186 | ||
187 | doit(command, argc, argv) | |
003a2a9e KM |
188 | char command; |
189 | int argc; | |
190 | char *argv[]; | |
7d4dda01 | 191 | { |
b88e54cb KM |
192 | struct mtop tcom; |
193 | ||
7d4dda01 | 194 | #ifndef STANDALONE |
7d4dda01 | 195 | if ((mt = open(magtape, 0)) < 0) { |
003a2a9e KM |
196 | fprintf(stderr, "%s: cannot open tape\n", magtape); |
197 | done(1); | |
7d4dda01 | 198 | } |
bcfabedf | 199 | if (dumpnum != 1) { |
7d4dda01 KM |
200 | tcom.mt_op = MTFSF; |
201 | tcom.mt_count = dumpnum -1; | |
bcfabedf | 202 | if (ioctl(mt,MTIOCTOP,&tcom) < 0) |
7d4dda01 KM |
203 | perror("ioctl MTFSF"); |
204 | } | |
205 | #else | |
206 | do { | |
003a2a9e | 207 | fprintf(stderr, "Tape? "); |
7d4dda01 KM |
208 | gets(mbuf); |
209 | mt = open(mbuf, 0); | |
210 | } while (mt == -1); | |
211 | magtape = mbuf; | |
212 | #endif | |
b6407c9d | 213 | blkclr(clearedbuf, MAXBSIZE); |
7d4dda01 KM |
214 | switch(command) { |
215 | #ifndef STANDALONE | |
216 | case 't': | |
217 | if (readhdr(&spcl) == 0) { | |
003a2a9e KM |
218 | fprintf(stderr, "Tape is not a dump tape\n"); |
219 | done(1); | |
7d4dda01 | 220 | } |
bcfabedf KM |
221 | fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); |
222 | fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); | |
7d4dda01 KM |
223 | return; |
224 | case 'x': | |
0841dbb0 KM |
225 | extractfiles(argc, argv); |
226 | return; | |
b6407c9d | 227 | #endif |
0841dbb0 KM |
228 | case 'r': |
229 | case 'R': | |
230 | restorfiles(command, argv); | |
231 | return; | |
232 | } | |
0841dbb0 KM |
233 | } |
234 | ||
235 | #ifndef STANDALONE | |
236 | extractfiles(argc, argv) | |
237 | int argc; | |
238 | char **argv; | |
239 | { | |
bcfabedf | 240 | char *ststore(); |
0841dbb0 KM |
241 | register struct xtrlist *xp; |
242 | struct xtrlist **xpp; | |
243 | ino_t d; | |
b88e54cb | 244 | int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), null(); |
bcfabedf KM |
245 | int mode; |
246 | char name[BUFSIZ + 1]; | |
0841dbb0 KM |
247 | |
248 | if (readhdr(&spcl) == 0) { | |
249 | fprintf(stderr, "Tape is not a dump tape\n"); | |
250 | done(1); | |
251 | } | |
252 | if (checkvol(&spcl, 1) == 0) { | |
253 | fprintf(stderr, "Tape is not volume 1 of the dump\n"); | |
254 | } | |
f7287e4b KM |
255 | fsptr = getfs(dev); |
256 | msiz = roundup(howmany(fsptr->fs_ipg * fsptr->fs_ncg, NBBY), TP_BSIZE); | |
b6407c9d KM |
257 | clrimap = (char *)calloc(msiz, sizeof(char)); |
258 | dumpmap = (char *)calloc(msiz, sizeof(char)); | |
b88e54cb | 259 | pass1(1); /* This sets the various maps on the way by */ |
bcfabedf | 260 | while (argc--) { |
0841dbb0 | 261 | if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { |
bcfabedf | 262 | fprintf(stdout, "%s: not on tape\n", *argv++); |
0841dbb0 | 263 | continue; |
7d4dda01 | 264 | } |
bcfabedf KM |
265 | if (mflag) |
266 | checkdir(*argv); | |
0841dbb0 KM |
267 | if(hflag) |
268 | getleaves(d, *argv++); | |
bcfabedf KM |
269 | else |
270 | allocxtr(d, *argv++, XINUSE); | |
0841dbb0 | 271 | } |
bcfabedf | 272 | if (dumpnum > 1) { |
b88e54cb KM |
273 | /* |
274 | * if this is a multi-dump tape we always start with | |
275 | * volume 1, so as to avoid accidentally restoring | |
276 | * from a different dump! | |
277 | */ | |
278 | resetmt(); | |
279 | dumpnum = 1; | |
280 | volno = 1; | |
281 | readhdr(&spcl); | |
282 | goto rbits; | |
0841dbb0 | 283 | } |
b88e54cb KM |
284 | newvol: |
285 | resetmt(); | |
7d4dda01 | 286 | getvol: |
b88e54cb | 287 | fprintf(stderr, "Mount desired tape volume; Specify volume #: "); |
0841dbb0 KM |
288 | if (gets(tbf) == NULL) |
289 | return; | |
290 | volno = atoi(tbf); | |
291 | if (volno <= 0) { | |
292 | fprintf(stderr, "Volume numbers are positive numerics\n"); | |
293 | goto getvol; | |
294 | } | |
295 | if (readhdr(&spcl) == 0) { | |
296 | fprintf(stderr, "tape is not dump tape\n"); | |
297 | goto newvol; | |
298 | } | |
299 | if (checkvol(&spcl, volno) == 0) { | |
300 | fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); | |
301 | goto newvol; | |
302 | } | |
7d4dda01 | 303 | rbits: |
0841dbb0 KM |
304 | while (gethead(&spcl) == 0) |
305 | ; | |
306 | if (checktype(&spcl, TS_INODE) == 1) { | |
307 | fprintf(stderr, "Can't find inode mask!\n"); | |
308 | goto newvol; | |
309 | } | |
310 | if (checktype(&spcl, TS_BITS) == 0) | |
311 | goto rbits; | |
312 | readbits(dumpmap); | |
313 | while (xtrcnt > 0) { | |
314 | again: | |
315 | if (ishead(&spcl) == 0) | |
316 | while(gethead(&spcl) == 0) | |
317 | ; | |
318 | if (checktype(&spcl, TS_END) == 1) { | |
319 | fprintf(stderr, "end of tape\n"); | |
320 | break; | |
7d4dda01 | 321 | } |
0841dbb0 KM |
322 | if (checktype(&spcl, TS_INODE) == 0) { |
323 | gethead(&spcl); | |
324 | goto again; | |
7d4dda01 | 325 | } |
0841dbb0 KM |
326 | d = spcl.c_inumber; |
327 | for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { | |
328 | if (d != xp->x_ino) | |
329 | continue; | |
330 | if (xp->x_flags & XLINKED) | |
331 | continue; | |
332 | xp->x_timep[0] = spcl.c_dinode.di_atime; | |
333 | xp->x_timep[1] = spcl.c_dinode.di_mtime; | |
334 | mode = spcl.c_dinode.di_mode; | |
335 | if (mflag) | |
bcfabedf | 336 | strcpy(name, xp->x_name); |
0841dbb0 KM |
337 | else |
338 | sprintf(name, "%u", xp->x_ino); | |
339 | switch (mode & IFMT) { | |
340 | default: | |
bcfabedf | 341 | fprintf(stderr, "%s: unknown file type\n", name); |
0841dbb0 KM |
342 | xp->x_flags |= XTRACTD; |
343 | xtrcnt--; | |
344 | goto skipfile; | |
345 | case IFCHR: | |
346 | case IFBLK: | |
bcfabedf | 347 | fprintf(stdout, "extract special file %s\n", name); |
0841dbb0 KM |
348 | if (xmknod(name, mode, spcl.c_dinode.di_rdev)) { |
349 | fprintf(stderr, "%s: cannot create special file\n", name); | |
350 | xp->x_flags |= XTRACTD; | |
351 | xtrcnt--; | |
352 | goto skipfile; | |
19ac1bc8 | 353 | } |
0841dbb0 KM |
354 | getfile(null, null, spcl.c_dinode.di_size); |
355 | break; | |
356 | case IFDIR: | |
357 | if (mflag) { | |
bcfabedf | 358 | fprintf(stdout, "extract directory %s\n", name); |
0841dbb0 | 359 | strncat(name, "/.", BUFSIZ); |
bcfabedf KM |
360 | checkdir(name); |
361 | xchown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); | |
0841dbb0 KM |
362 | getfile(null, null, spcl.c_dinode.di_size); |
363 | break; | |
364 | } | |
b88e54cb KM |
365 | fprintf(stdout, "extract file %s\n", name); |
366 | if ((ofile = xcreat(name, 0666)) < 0) { | |
367 | fprintf(stderr, "%s: cannot create file\n", name); | |
368 | xp->x_flags |= XTRACTD; | |
369 | xtrcnt--; | |
370 | goto skipfile; | |
371 | } | |
372 | xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); | |
b45e25c0 | 373 | if (cvtdir) { |
b88e54cb KM |
374 | getfile(xtrcvtdir, xtrcvtskip, |
375 | spcl.c_dinode.di_size); | |
b45e25c0 KM |
376 | flushent(xtrfile); |
377 | } else | |
b88e54cb KM |
378 | getfile(xtrfile, xtrskip, |
379 | spcl.c_dinode.di_size); | |
380 | xclose(ofile); | |
381 | break; | |
0841dbb0 | 382 | case IFREG: |
bcfabedf | 383 | fprintf(stdout, "extract file %s\n", name); |
0841dbb0 KM |
384 | if ((ofile = xcreat(name, 0666)) < 0) { |
385 | fprintf(stderr, "%s: cannot create file\n", name); | |
386 | xp->x_flags |= XTRACTD; | |
387 | xtrcnt--; | |
388 | goto skipfile; | |
7d4dda01 | 389 | } |
0841dbb0 | 390 | xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); |
b88e54cb | 391 | getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); |
0841dbb0 KM |
392 | xclose(ofile); |
393 | break; | |
7d4dda01 | 394 | } |
0841dbb0 KM |
395 | xchmod(name, mode); |
396 | xutime(name, xp->x_timep); | |
397 | xp->x_flags |= XTRACTD; | |
398 | xtrcnt--; | |
399 | goto finished; | |
400 | } | |
401 | skipfile: | |
402 | getfile(null, null, spcl.c_dinode.di_size); | |
003a2a9e | 403 | finished: |
0841dbb0 KM |
404 | ; |
405 | } | |
406 | if (xtrcnt == 0 && !mflag) | |
407 | return; | |
408 | for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { | |
409 | for (xp = *xpp; xp; xp = xp->x_next) { | |
410 | if (mflag && (xp->x_flags & XISDIR)) | |
411 | xutime(xp->x_name, xp->x_timep); | |
412 | if (xp->x_flags & XTRACTD) | |
413 | continue; | |
414 | if ((xp->x_flags & XLINKED) == 0) { | |
415 | fprintf(stderr, "cannot find file %s\n", | |
416 | xp->x_name); | |
417 | continue; | |
418 | } | |
bcfabedf KM |
419 | if (!mflag) |
420 | continue; | |
421 | fprintf(stdout, "link %s to %s\n", | |
422 | xp->x_linkedto->x_name, xp->x_name); | |
0841dbb0 | 423 | if (xlink(xp->x_linkedto->x_name, xp->x_name) < 0) |
bcfabedf KM |
424 | fprintf(stderr, "link %s to %s failed\n", |
425 | xp->x_linkedto->x_name, xp->x_name); | |
7d4dda01 | 426 | } |
0841dbb0 KM |
427 | } |
428 | } | |
7d4dda01 | 429 | #endif |
0841dbb0 KM |
430 | |
431 | restorfiles(command, argv) | |
432 | char command; | |
433 | char **argv; | |
434 | { | |
b45e25c0 | 435 | int null(), rstrfile(), rstrskip(), rstrcvtdir(), rstrcvtskip(); |
0841dbb0 KM |
436 | register struct dinode *dp; |
437 | register struct inode *ip; | |
b88e54cb | 438 | int mode, type; |
0841dbb0 KM |
439 | char mount[BUFSIZ + 1]; |
440 | char *ptr[2]; | |
441 | ||
0841dbb0 KM |
442 | mount[0] = '\0'; |
443 | strcpy(mount, "MOUNT="); | |
b6407c9d | 444 | #ifndef STANDALONE |
0841dbb0 | 445 | strncat(mount, *argv, BUFSIZ); |
b6407c9d KM |
446 | #else |
447 | fprintf(stderr, "Disk? "); | |
448 | gets(&mount[6]); | |
449 | #endif | |
0841dbb0 KM |
450 | ptr[0] = mount; |
451 | ptr[1] = 0; | |
452 | xmount(ptr); | |
b6407c9d | 453 | mounted++; |
0841dbb0 KM |
454 | iput(u.u_cdir); /* release root inode */ |
455 | iput(u.u_rdir); /* release root inode */ | |
f7287e4b KM |
456 | fsptr = getfs(dev); |
457 | parentino.i_fs = fsptr; | |
458 | parentino.i_dev = dev; | |
459 | maxi = fsptr->fs_ipg * fsptr->fs_ncg; | |
7d4dda01 | 460 | #ifndef STANDALONE |
b6407c9d KM |
461 | msiz = roundup(howmany(maxi, NBBY), TP_BSIZE); |
462 | clrimap = (char *)calloc(msiz, sizeof(char)); | |
463 | dumpmap = (char *)calloc(msiz, sizeof(char)); | |
0841dbb0 KM |
464 | if (command == 'R') { |
465 | fprintf(stderr, "Enter starting volume number: "); | |
466 | if (gets(tbf) == EOF) { | |
467 | volno = 1; | |
468 | fprintf(stderr, "\n"); | |
7d4dda01 KM |
469 | } |
470 | else | |
0841dbb0 KM |
471 | volno = atoi(tbf); |
472 | } | |
473 | else | |
7d4dda01 | 474 | #endif |
0841dbb0 KM |
475 | volno = 1; |
476 | fprintf(stderr, "Last chance before scribbling on %s. ", | |
7d4dda01 | 477 | #ifdef STANDALONE |
0841dbb0 | 478 | "disk"); |
7d4dda01 | 479 | #else |
0841dbb0 | 480 | *argv); |
7d4dda01 | 481 | #endif |
0841dbb0 | 482 | while (getchar() != '\n'); |
0841dbb0 KM |
483 | if (readhdr(&spcl) == 0) { |
484 | fprintf(stderr, "Missing volume record\n"); | |
485 | done(1); | |
486 | } | |
487 | if (checkvol(&spcl, volno) == 0) { | |
488 | fprintf(stderr, "Tape is not volume %d\n", volno); | |
489 | done(1); | |
490 | } | |
b88e54cb KM |
491 | pass1(0); |
492 | gethead(&spcl); /* volume header already checked above */ | |
0841dbb0 KM |
493 | gethead(&spcl); |
494 | for (;;) { | |
0841dbb0 KM |
495 | if (ishead(&spcl) == 0) { |
496 | fprintf(stderr, "Missing header block\n"); | |
497 | while (gethead(&spcl) == 0) | |
498 | ; | |
499 | eflag++; | |
7d4dda01 | 500 | } |
0841dbb0 KM |
501 | if (checktype(&spcl, TS_END) == 1) { |
502 | fprintf(stderr, "End of tape\n"); | |
503 | close(mt); | |
504 | return; | |
7d4dda01 | 505 | } |
0841dbb0 KM |
506 | if (checktype(&spcl, TS_CLRI) == 1) { |
507 | readbits(clrimap); | |
9c2d09b1 KM |
508 | /* |
509 | * if throwing away the root inode, must also | |
510 | * discard the predefined lost+found directory. | |
511 | */ | |
512 | if (BIT(ROOTINO, clrimap)) | |
513 | BIS(LOSTFOUNDINO + 1, clrimap); | |
c312eebd | 514 | for (ino = ROOTINO; ino <= maxi; ino++) |
0841dbb0 | 515 | if (BIT(ino, clrimap) == 0) { |
f7287e4b | 516 | if (!iexist(&parentino, ino)) |
0841dbb0 | 517 | continue; |
f7287e4b | 518 | ip = iget(dev, fsptr, ino); |
0841dbb0 KM |
519 | if (ip == NULL) { |
520 | fprintf(stderr, "can't find inode %u\n", ino); | |
521 | done(1); | |
7d4dda01 | 522 | } |
0841dbb0 KM |
523 | ip->i_nlink = 0; |
524 | ip->i_flag |= ICHG; | |
525 | iput(ip); | |
003a2a9e | 526 | } |
b45e25c0 | 527 | continue; |
0841dbb0 KM |
528 | } |
529 | if (checktype(&spcl, TS_BITS) == 1) { | |
530 | readbits(dumpmap); | |
b45e25c0 | 531 | continue; |
0841dbb0 KM |
532 | } |
533 | if (checktype(&spcl, TS_INODE) == 0) { | |
534 | fprintf(stderr, "Unknown header type\n"); | |
535 | eflag++; | |
536 | gethead(&spcl); | |
b45e25c0 | 537 | continue; |
0841dbb0 KM |
538 | } |
539 | ino = spcl.c_inumber; | |
540 | if (eflag) | |
541 | fprintf(stderr, "Resynced at inode %u\n", ino); | |
542 | eflag = 0; | |
543 | if (ino > maxi) { | |
544 | fprintf(stderr, "%u: ilist too small\n", ino); | |
545 | gethead(&spcl); | |
b45e25c0 KM |
546 | continue; |
547 | } | |
548 | dp = &spcl.c_dinode; | |
549 | if (ino < ROOTINO) { | |
550 | getfile(null, null, dp->di_size); | |
551 | continue; | |
0841dbb0 | 552 | } |
f7287e4b KM |
553 | if (iexist(&parentino, ino)) { |
554 | ip = iget(dev, fsptr, ino); | |
0841dbb0 KM |
555 | if (ip == NULL) { |
556 | fprintf(stderr, "can't find inode %u\n", | |
557 | ino); | |
003a2a9e KM |
558 | done(1); |
559 | } | |
0841dbb0 | 560 | ip->i_nlink = 0; |
003a2a9e KM |
561 | ip->i_flag |= ICHG; |
562 | iput(ip); | |
7d4dda01 | 563 | } |
f7287e4b | 564 | ip = ialloc(&parentino, ino, dp->di_mode); |
0841dbb0 KM |
565 | if (ip == NULL || ip->i_number != ino) { |
566 | fprintf(stderr, "can't create inode %u\n", ino); | |
567 | done(1); | |
568 | } | |
569 | ip->i_mode = mode = dp->di_mode; | |
570 | ip->i_nlink = dp->di_nlink; | |
571 | ip->i_uid = dp->di_uid; | |
572 | ip->i_gid = dp->di_gid; | |
573 | ip->i_atime = dp->di_atime; | |
574 | ip->i_mtime = dp->di_mtime; | |
575 | ip->i_ctime = dp->di_ctime; | |
b88e54cb KM |
576 | type = ip->i_mode & IFMT; |
577 | if (type == IFCHR || type == IFBLK) | |
0841dbb0 KM |
578 | ip->i_rdev = dp->di_rdev; |
579 | ip->i_size = 0; | |
580 | cur_ip = ip; | |
581 | u.u_offset = 0; | |
582 | u.u_segflg = 1; | |
b45e25c0 | 583 | if (cvtdir && type == IFDIR) { |
b88e54cb | 584 | getfile(rstrcvtdir, rstrcvtskip, dp->di_size); |
b45e25c0 KM |
585 | flushent(rstrfile); |
586 | } else | |
b88e54cb | 587 | getfile(rstrfile, rstrskip, dp->di_size); |
0841dbb0 KM |
588 | ip->i_mode = mode; |
589 | ip->i_flag &= ~(IUPD|IACC); | |
590 | ip->i_flag |= ICHG; | |
591 | iput(ip); | |
7d4dda01 KM |
592 | } |
593 | } | |
594 | ||
595 | /* | |
596 | * Read the tape, bulding up a directory structure for extraction | |
597 | * by name | |
598 | */ | |
599 | #ifndef STANDALONE | |
b88e54cb KM |
600 | pass1(savedir) |
601 | int savedir; | |
7d4dda01 | 602 | { |
19ac1bc8 | 603 | register int i; |
0841dbb0 KM |
604 | register struct dinode *ip; |
605 | struct direct nulldir; | |
b88e54cb | 606 | char buf[TP_BSIZE]; |
b45e25c0 | 607 | int putdir(), null(), dirwrite(); |
7d4dda01 | 608 | |
b45e25c0 KM |
609 | nulldir.d_ino = 1; |
610 | nulldir.d_namlen = 1; | |
611 | strncpy(nulldir.d_name, "/", nulldir.d_namlen); | |
612 | nulldir.d_reclen = DIRSIZ(&nulldir); | |
7d4dda01 | 613 | while (gethead(&spcl) == 0) { |
003a2a9e | 614 | fprintf(stderr, "Can't find directory header!\n"); |
7d4dda01 KM |
615 | } |
616 | for (;;) { | |
617 | if (checktype(&spcl, TS_BITS) == 1) { | |
618 | readbits(dumpmap); | |
619 | continue; | |
620 | } | |
621 | if (checktype(&spcl, TS_CLRI) == 1) { | |
622 | readbits(clrimap); | |
623 | continue; | |
624 | } | |
625 | if (checktype(&spcl, TS_INODE) == 0) { | |
626 | finish: | |
b45e25c0 KM |
627 | if (savedir) { |
628 | fclose(df); | |
629 | dirp = opendir(dirfile); | |
630 | if (dirp == NULL) | |
631 | perror("opendir"); | |
632 | } | |
b88e54cb | 633 | resetmt(); |
7d4dda01 KM |
634 | return; |
635 | } | |
636 | ip = &spcl.c_dinode; | |
637 | i = ip->di_mode & IFMT; | |
638 | if (i != IFDIR) { | |
639 | goto finish; | |
640 | } | |
b88e54cb KM |
641 | if (spcl.c_inumber == ROOTINO) { |
642 | readtape(buf); | |
643 | bct--; /* push back this block */ | |
644 | if (((struct direct *)buf)->d_ino != ROOTINO) { | |
645 | if (((struct odirect *)buf)->d_ino != ROOTINO) { | |
646 | fprintf(stderr, "bad root directory\n"); | |
647 | done(1); | |
648 | } | |
649 | fprintf(stderr, "converting to new directory format\n"); | |
650 | cvtdir = 1; | |
651 | } | |
652 | if (!savedir && !cvtdir) { | |
653 | /* if no conversion, just return */ | |
654 | goto finish; | |
655 | } | |
656 | } | |
bcfabedf | 657 | allocinotab(spcl.c_inumber, seekpt); |
b88e54cb KM |
658 | if (savedir) { |
659 | getfile(putdir, null, spcl.c_dinode.di_size); | |
b45e25c0 KM |
660 | putent(&nulldir, dirwrite); |
661 | flushent(dirwrite); | |
b88e54cb KM |
662 | } else { |
663 | getfile(null, null, spcl.c_dinode.di_size); | |
664 | } | |
7d4dda01 KM |
665 | } |
666 | } | |
667 | #endif | |
668 | ||
bcfabedf KM |
669 | /* |
670 | * Put the directory entries in the directory file | |
671 | */ | |
672 | #ifndef STANDALONE | |
673 | putdir(buf, size) | |
674 | char *buf; | |
675 | int size; | |
676 | { | |
b88e54cb KM |
677 | struct direct cvtbuf; |
678 | register struct odirect *odp; | |
679 | struct odirect *eodp; | |
bcfabedf | 680 | register struct direct *dp; |
b45e25c0 | 681 | long loc; |
b88e54cb KM |
682 | |
683 | if (cvtdir) { | |
684 | eodp = (struct odirect *)&buf[size]; | |
685 | for (odp = (struct odirect *)buf; odp < eodp; odp++) | |
686 | if (odp->d_ino != 0) { | |
687 | dcvt(odp, &cvtbuf); | |
b45e25c0 | 688 | putent(&cvtbuf, dirwrite); |
b88e54cb KM |
689 | } |
690 | } else { | |
b45e25c0 KM |
691 | for (loc = 0; loc < size; ) { |
692 | dp = (struct direct *)(buf + loc); | |
b88e54cb | 693 | if (dp->d_ino != 0) |
b45e25c0 KM |
694 | putent(dp, dirwrite); |
695 | } | |
b88e54cb KM |
696 | } |
697 | } | |
698 | ||
bcfabedf KM |
699 | /* |
700 | * Recursively find names and inumbers of all files in subtree | |
701 | * pname and put them in xtrlist[] | |
702 | */ | |
703 | getleaves(ino, pname) | |
704 | ino_t ino; | |
705 | char *pname; | |
706 | { | |
707 | register struct inotab *itp; | |
708 | int namelen; | |
b45e25c0 KM |
709 | long bpt; |
710 | register struct direct *dp; | |
711 | char locname[BUFSIZ + 1]; | |
bcfabedf KM |
712 | |
713 | if (BIT(ino, dumpmap) == 0) { | |
714 | fprintf(stdout, "%s: not on the tape\n", pname); | |
715 | return; | |
716 | } | |
717 | for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { | |
718 | if (itp->t_ino != ino) | |
719 | continue; | |
720 | /* | |
721 | * pname is a directory name | |
722 | */ | |
723 | allocxtr(ino, pname, XISDIR); | |
724 | /* | |
725 | * begin search through the directory | |
726 | * skipping over "." and ".." | |
727 | */ | |
728 | strncpy(locname, pname, BUFSIZ); | |
729 | strncat(locname, "/", BUFSIZ); | |
730 | namelen = strlen(locname); | |
b45e25c0 KM |
731 | seekdir(dirp, itp->t_seekpt, itp->t_seekpt); |
732 | dp = readdir(dirp); | |
733 | dp = readdir(dirp); | |
734 | dp = readdir(dirp); | |
735 | bpt = telldir(dirp); | |
bcfabedf KM |
736 | /* |
737 | * "/" signals end of directory | |
738 | */ | |
b45e25c0 | 739 | while (dp->d_namlen != 1 || dp->d_name[0] != '/') { |
bcfabedf | 740 | locname[namelen] = '\0'; |
b45e25c0 KM |
741 | if (namelen + dp->d_namlen >= BUFSIZ) { |
742 | fprintf(stderr, "%s%s: name exceedes %d char\n", | |
743 | locname, dp->d_name, BUFSIZ); | |
bcfabedf KM |
744 | continue; |
745 | } | |
b45e25c0 KM |
746 | strncat(locname, dp->d_name, dp->d_namlen); |
747 | getleaves(dp->d_ino, locname); | |
748 | seekdir(dirp, bpt, itp->t_seekpt); | |
749 | dp = readdir(dirp); | |
750 | bpt = telldir(dirp); | |
bcfabedf KM |
751 | } |
752 | return; | |
753 | } | |
754 | /* | |
755 | * locname is name of a simple file | |
756 | */ | |
757 | allocxtr(ino, pname, XINUSE); | |
758 | } | |
759 | ||
760 | /* | |
761 | * Search the directory tree rooted at inode ROOTINO | |
762 | * for the path pointed at by n | |
763 | */ | |
764 | psearch(n) | |
765 | char *n; | |
766 | { | |
767 | register char *cp, *cp1; | |
768 | char c; | |
769 | ||
770 | ino = ROOTINO; | |
771 | if (*(cp = n) == '/') | |
772 | cp++; | |
773 | next: | |
774 | cp1 = cp + 1; | |
775 | while (*cp1 != '/' && *cp1) | |
776 | cp1++; | |
777 | c = *cp1; | |
778 | *cp1 = 0; | |
779 | ino = search(ino, cp); | |
780 | if (ino == 0) { | |
781 | *cp1 = c; | |
782 | return(0); | |
783 | } | |
784 | *cp1 = c; | |
785 | if (c == '/') { | |
786 | cp = cp1+1; | |
787 | goto next; | |
788 | } | |
789 | return(ino); | |
790 | } | |
791 | ||
792 | /* | |
793 | * search the directory inode ino | |
794 | * looking for entry cp | |
795 | */ | |
796 | ino_t | |
797 | search(inum, cp) | |
798 | ino_t inum; | |
799 | char *cp; | |
800 | { | |
b45e25c0 | 801 | register struct direct *dp; |
bcfabedf | 802 | register struct inotab *itp; |
b45e25c0 | 803 | int len; |
bcfabedf KM |
804 | |
805 | for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) | |
806 | if (itp->t_ino == inum) | |
807 | goto found; | |
808 | return(0); | |
809 | found: | |
b45e25c0 KM |
810 | seekdir(dirp, itp->t_seekpt, itp->t_seekpt); |
811 | len = strlen(cp); | |
bcfabedf | 812 | do { |
b45e25c0 KM |
813 | dp = readdir(dirp); |
814 | if (dp->d_namlen == 1 && dp->d_name[0] == '/') | |
bcfabedf | 815 | return(0); |
b45e25c0 KM |
816 | } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len)); |
817 | return(dp->d_ino); | |
bcfabedf KM |
818 | } |
819 | #endif | |
820 | ||
7d4dda01 KM |
821 | /* |
822 | * Do the file extraction, calling the supplied functions | |
823 | * with the blocks | |
824 | */ | |
003a2a9e KM |
825 | getfile(f1, f2, size) |
826 | int (*f2)(), (*f1)(); | |
827 | long size; | |
7d4dda01 | 828 | { |
19ac1bc8 | 829 | register int i; |
b6407c9d | 830 | char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; |
0841dbb0 KM |
831 | union u_spcl addrblk; |
832 | # define addrblock addrblk.s_spcl | |
7d4dda01 | 833 | |
0841dbb0 | 834 | addrblock = spcl; |
7d4dda01 | 835 | for (;;) { |
0841dbb0 KM |
836 | for (i = 0; i < addrblock.c_count; i++) { |
837 | if (addrblock.c_addr[i]) { | |
19ac1bc8 | 838 | readtape(&buf[curblk++][0]); |
f7287e4b | 839 | if (curblk == BLKING(fsptr) * fsptr->fs_frag) { |
19ac1bc8 | 840 | (*f1)(buf, size > TP_BSIZE ? |
f7287e4b | 841 | (long) (BLKING(fsptr) * fsptr->fs_frag * TP_BSIZE) : |
19ac1bc8 KM |
842 | (curblk - 1) * TP_BSIZE + size); |
843 | curblk = 0; | |
844 | } | |
b6407c9d | 845 | } else { |
19ac1bc8 KM |
846 | if (curblk > 0) { |
847 | (*f1)(buf, size > TP_BSIZE ? | |
848 | (long) (curblk * TP_BSIZE) : | |
849 | (curblk - 1) * TP_BSIZE + size); | |
850 | curblk = 0; | |
851 | } | |
b6407c9d KM |
852 | (*f2)(clearedbuf, size > TP_BSIZE ? |
853 | (long) TP_BSIZE : size); | |
7d4dda01 | 854 | } |
19ac1bc8 | 855 | if ((size -= TP_BSIZE) <= 0) { |
7d4dda01 KM |
856 | eloop: |
857 | while (gethead(&spcl) == 0) | |
858 | ; | |
859 | if (checktype(&spcl, TS_ADDR) == 1) | |
860 | goto eloop; | |
19ac1bc8 | 861 | goto out; |
7d4dda01 KM |
862 | } |
863 | } | |
0841dbb0 | 864 | if (gethead(&addrblock) == 0) { |
19ac1bc8 | 865 | fprintf(stderr, "Missing address (header) block, ino%u\n", ino); |
003a2a9e KM |
866 | goto eloop; |
867 | } | |
0841dbb0 KM |
868 | if (checktype(&addrblock, TS_ADDR) == 0) { |
869 | spcl = addrblock; | |
19ac1bc8 | 870 | goto out; |
003a2a9e | 871 | } |
7d4dda01 | 872 | } |
19ac1bc8 KM |
873 | out: |
874 | if (curblk > 0) { | |
875 | (*f1)(buf, (curblk * TP_BSIZE) + size); | |
876 | curblk = 0; | |
877 | } | |
7d4dda01 KM |
878 | } |
879 | ||
bcfabedf KM |
880 | /* |
881 | * The next routines are called during file extraction to | |
882 | * put the data into the right form and place. | |
883 | */ | |
884 | #ifndef STANDALONE | |
885 | xtrfile(buf, size) | |
886 | char *buf; | |
887 | long size; | |
888 | { | |
889 | if (xwrite(ofile, buf, (int) size) == -1) { | |
b88e54cb | 890 | perror("extract write"); |
bcfabedf KM |
891 | done(1); |
892 | } | |
893 | } | |
894 | ||
b88e54cb | 895 | xtrskip(buf, size) |
bcfabedf KM |
896 | char *buf; |
897 | long size; | |
898 | { | |
899 | if (xseek(ofile, size, 1) == -1) { | |
b88e54cb | 900 | perror("extract seek"); |
bcfabedf KM |
901 | done(1); |
902 | } | |
903 | } | |
bcfabedf | 904 | |
b88e54cb KM |
905 | xtrcvtdir(buf, size) |
906 | struct odirect *buf; | |
907 | long size; | |
908 | { | |
b88e54cb | 909 | struct odirect *odp, *edp; |
b45e25c0 | 910 | struct direct *dp, cvtbuf; |
b88e54cb KM |
911 | |
912 | edp = &buf[size / sizeof(struct odirect)]; | |
b45e25c0 KM |
913 | for (odp = buf; odp < edp; odp++) { |
914 | dcvt(odp, &cvtbuf); | |
915 | putent(&cvtbuf, xtrfile); | |
b88e54cb KM |
916 | } |
917 | } | |
918 | ||
919 | xtrcvtskip(buf, size) | |
920 | char *buf; | |
921 | long size; | |
922 | { | |
923 | fprintf(stderr, "unallocated block in directory\n"); | |
b45e25c0 | 924 | xtrskip(buf, size); |
b88e54cb KM |
925 | } |
926 | #endif | |
bcfabedf KM |
927 | |
928 | rstrfile(buf, size) | |
929 | char *buf; | |
930 | long size; | |
931 | { | |
932 | u.u_base = buf; | |
933 | u.u_count = size; | |
934 | writei(cur_ip); | |
935 | if (u.u_error) { | |
b88e54cb | 936 | perror("restor write"); |
bcfabedf KM |
937 | done(1); |
938 | } | |
939 | } | |
940 | ||
941 | rstrskip(buf, size) | |
942 | char *buf; | |
943 | long size; | |
944 | { | |
945 | u.u_offset += size; | |
946 | } | |
947 | ||
b88e54cb KM |
948 | rstrcvtdir(buf, size) |
949 | struct odirect *buf; | |
950 | long size; | |
951 | { | |
b88e54cb | 952 | struct odirect *odp, *edp; |
b45e25c0 | 953 | struct direct *dp, cvtbuf; |
b88e54cb KM |
954 | |
955 | edp = &buf[size / sizeof(struct odirect)]; | |
b45e25c0 KM |
956 | for (odp = buf; odp < edp; odp++) { |
957 | dcvt(odp, &cvtbuf); | |
958 | putent(&cvtbuf, rstrfile); | |
b88e54cb KM |
959 | } |
960 | } | |
961 | ||
962 | rstrcvtskip(buf, size) | |
963 | char *buf; | |
964 | long size; | |
965 | { | |
966 | fprintf(stderr, "unallocated block in directory\n"); | |
b45e25c0 | 967 | rstrskip(buf, size); |
b88e54cb KM |
968 | } |
969 | ||
bcfabedf KM |
970 | null() {;} |
971 | ||
7d4dda01 | 972 | /* |
19ac1bc8 | 973 | * Do the tape i/o, dealing with volume changes |
7d4dda01 KM |
974 | * etc.. |
975 | */ | |
976 | readtape(b) | |
003a2a9e | 977 | char *b; |
7d4dda01 | 978 | { |
19ac1bc8 | 979 | register int i; |
0841dbb0 | 980 | struct s_spcl tmpbuf; |
7d4dda01 KM |
981 | |
982 | if (bct >= NTREC) { | |
983 | for (i = 0; i < NTREC; i++) | |
19ac1bc8 | 984 | ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; |
7d4dda01 | 985 | bct = 0; |
19ac1bc8 | 986 | if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { |
003a2a9e | 987 | perror("Tape read error"); |
7d4dda01 | 988 | eflag++; |
003a2a9e | 989 | done(1); |
7d4dda01 KM |
990 | } |
991 | if (i == 0) { | |
992 | bct = NTREC + 1; | |
993 | volno++; | |
994 | loop: | |
995 | flsht(); | |
996 | close(mt); | |
003a2a9e | 997 | fprintf(stderr, "Mount volume %d\n", volno); |
7d4dda01 KM |
998 | while (getchar() != '\n') |
999 | ; | |
1000 | if ((mt = open(magtape, 0)) == -1) { | |
003a2a9e | 1001 | fprintf(stderr, "Cannot open tape!\n"); |
7d4dda01 KM |
1002 | goto loop; |
1003 | } | |
1004 | if (readhdr(&tmpbuf) == 0) { | |
003a2a9e | 1005 | fprintf(stderr, "Not a dump tape.Try again\n"); |
7d4dda01 KM |
1006 | goto loop; |
1007 | } | |
1008 | if (checkvol(&tmpbuf, volno) == 0) { | |
003a2a9e | 1009 | fprintf(stderr, "Wrong tape. Try again\n"); |
7d4dda01 KM |
1010 | goto loop; |
1011 | } | |
1012 | readtape(b); | |
1013 | return; | |
1014 | } | |
1015 | } | |
b45e25c0 | 1016 | blkcpy(&tbf[(bct++*TP_BSIZE)], b, TP_BSIZE); |
7d4dda01 KM |
1017 | } |
1018 | ||
1019 | flsht() | |
1020 | { | |
1021 | bct = NTREC+1; | |
1022 | } | |
1023 | ||
b45e25c0 KM |
1024 | blkcpy(from, to, size) |
1025 | char *from, *to; | |
1026 | int size; | |
7d4dda01 | 1027 | { |
b45e25c0 | 1028 | asm(" movc3 12(ap),*4(ap),*8(ap)"); |
7d4dda01 KM |
1029 | } |
1030 | ||
b88e54cb KM |
1031 | blkclr(buf, size) |
1032 | char *buf; | |
1033 | int size; | |
1034 | { | |
1035 | asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); | |
1036 | } | |
1037 | ||
1038 | resetmt() | |
1039 | { | |
1040 | struct mtop tcom; | |
1041 | ||
1042 | if(dumpnum > 1) | |
1043 | tcom.mt_op = MTBSF; | |
1044 | else | |
1045 | tcom.mt_op = MTREW; | |
1046 | tcom.mt_count = 1; | |
1047 | flsht(); | |
1048 | if (ioctl(mt,MTIOCTOP,&tcom) == -1) { | |
1049 | /* kludge for disk dumps */ | |
1050 | lseek(mt, (long)0, 0); | |
1051 | } | |
1052 | if (dumpnum > 1) { | |
1053 | tcom.mt_op = MTFSF; | |
1054 | tcom.mt_count = 1; | |
1055 | ioctl(mt,MTIOCTOP,&tcom); | |
1056 | } | |
1057 | } | |
1058 | ||
bcfabedf KM |
1059 | checkvol(b, t) |
1060 | struct s_spcl *b; | |
1061 | int t; | |
7d4dda01 | 1062 | { |
bcfabedf KM |
1063 | if (b->c_volume == t) |
1064 | return(1); | |
7d4dda01 | 1065 | return(0); |
7d4dda01 KM |
1066 | } |
1067 | ||
bcfabedf KM |
1068 | readhdr(b) |
1069 | struct s_spcl *b; | |
7d4dda01 | 1070 | { |
bcfabedf | 1071 | if (gethead(b) == 0) |
7d4dda01 | 1072 | return(0); |
bcfabedf KM |
1073 | if (checktype(b, TS_TAPE) == 0) |
1074 | return(0); | |
1075 | return(1); | |
7d4dda01 | 1076 | } |
7d4dda01 | 1077 | |
7d4dda01 KM |
1078 | /* |
1079 | * read the tape into buf, then return whether or | |
1080 | * or not it is a header block. | |
1081 | */ | |
1082 | gethead(buf) | |
0841dbb0 | 1083 | struct s_spcl *buf; |
7d4dda01 KM |
1084 | { |
1085 | readtape((char *)buf); | |
0841dbb0 | 1086 | if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) |
7d4dda01 KM |
1087 | return(0); |
1088 | return(1); | |
1089 | } | |
1090 | ||
1091 | /* | |
1092 | * return whether or not the buffer contains a header block | |
1093 | */ | |
1094 | ishead(buf) | |
0841dbb0 | 1095 | struct s_spcl *buf; |
7d4dda01 | 1096 | { |
0841dbb0 | 1097 | if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) |
7d4dda01 KM |
1098 | return(0); |
1099 | return(1); | |
1100 | } | |
1101 | ||
1102 | checktype(b, t) | |
0841dbb0 | 1103 | struct s_spcl *b; |
003a2a9e | 1104 | int t; |
7d4dda01 | 1105 | { |
0841dbb0 | 1106 | return(b->c_type == t); |
7d4dda01 KM |
1107 | } |
1108 | ||
b88e54cb KM |
1109 | /* |
1110 | * read a bit mask from the tape into m. | |
1111 | */ | |
1112 | readbits(m) | |
b6407c9d | 1113 | char *m; |
b88e54cb KM |
1114 | { |
1115 | register int i; | |
1116 | ||
1117 | i = spcl.c_count; | |
1118 | ||
1119 | while (i--) { | |
1120 | readtape((char *) m); | |
b6407c9d | 1121 | m += (TP_BSIZE/(NBBY/BITS)); |
b88e54cb KM |
1122 | } |
1123 | while (gethead(&spcl) == 0) | |
1124 | ; | |
1125 | } | |
7d4dda01 KM |
1126 | |
1127 | checksum(b) | |
003a2a9e | 1128 | int *b; |
7d4dda01 | 1129 | { |
19ac1bc8 | 1130 | register int i, j; |
7d4dda01 | 1131 | |
19ac1bc8 | 1132 | j = sizeof(union u_spcl) / sizeof(int); |
7d4dda01 KM |
1133 | i = 0; |
1134 | do | |
1135 | i += *b++; | |
1136 | while (--j); | |
1137 | if (i != CHECKSUM) { | |
19ac1bc8 | 1138 | fprintf(stderr, "Checksum error %o, ino %u\n", i, ino); |
7d4dda01 KM |
1139 | return(0); |
1140 | } | |
1141 | return(1); | |
1142 | } | |
1143 | ||
b88e54cb KM |
1144 | /* |
1145 | * Check for access into each directory in the pathname of an extracted | |
1146 | * file and create such a directory if needed in preparation for moving | |
1147 | * the file to its proper home. | |
1148 | */ | |
1149 | checkdir(name) | |
1150 | register char *name; | |
1151 | { | |
1152 | register char *cp; | |
1153 | int i; | |
1154 | ||
1155 | for (cp = name; *cp; cp++) { | |
1156 | if (*cp == '/') { | |
1157 | *cp = '\0'; | |
1158 | if (xaccess(name, 01) < 0) { | |
1159 | register int pid, rp; | |
1160 | ||
1161 | xumount(); | |
1162 | if ((pid = fork()) == 0) { | |
1163 | execl("/bin/xmkdir", "xmkdir", name, 0); | |
1164 | execl("/usr/bin/xmkdir", "xmkdir", name, 0); | |
1165 | execl("./xmkdir", "xmkdir", name, 0); | |
1166 | fprintf(stderr, "xrestor: cannot find xmkdir!\n"); | |
1167 | done(0); | |
1168 | } | |
1169 | while ((rp = wait(&i)) >= 0 && rp != pid) | |
1170 | ; | |
1171 | xmount(envp); | |
f7287e4b KM |
1172 | fsptr = getfs(dev); |
1173 | parentino.i_fs = fsptr; | |
b88e54cb KM |
1174 | } |
1175 | *cp = '/'; | |
1176 | } | |
1177 | } | |
1178 | } | |
1179 | ||
b45e25c0 KM |
1180 | /* |
1181 | * These variables are "local" to the following two functions. | |
1182 | */ | |
1183 | char dirbuf[DIRBLKSIZ]; | |
1184 | long dirloc = 0; | |
1185 | long prev = 0; | |
1186 | ||
1187 | /* | |
1188 | * add a new directory entry to a file. | |
1189 | */ | |
1190 | putent(dp, wrtfunc) | |
1191 | struct direct *dp; | |
1192 | int (*wrtfunc)(); | |
1193 | { | |
1194 | if (dp->d_ino == 0) | |
1195 | return; | |
1196 | for (;;) { | |
1197 | if (dp->d_reclen < DIRBLKSIZ - dirloc) { | |
1198 | blkcpy(dp, dirbuf + dirloc, dp->d_reclen); | |
1199 | prev = dirloc; | |
1200 | dirloc += dp->d_reclen; | |
1201 | return; | |
1202 | } | |
1203 | ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; | |
1204 | (*wrtfunc)(dirbuf, DIRBLKSIZ); | |
1205 | dirloc = 0; | |
1206 | } | |
1207 | } | |
1208 | ||
1209 | /* | |
1210 | * flush out a directory that is finished. | |
1211 | */ | |
1212 | flushent(wrtfunc) | |
1213 | int (*wrtfunc)(); | |
1214 | { | |
1215 | ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; | |
1216 | (*wrtfunc)(dirbuf, dirloc); | |
1217 | dirloc = 0; | |
1218 | } | |
1219 | ||
1220 | dirwrite(buf, size) | |
1221 | char *buf; | |
1222 | int size; | |
1223 | { | |
1224 | fwrite(buf, 1, size, df); | |
1225 | seekpt = ftell(df); | |
1226 | } | |
1227 | ||
1228 | dcvt(odp, ndp) | |
1229 | register struct odirect *odp; | |
1230 | register struct direct *ndp; | |
1231 | { | |
1232 | struct inotab *itp; | |
1233 | ||
1234 | blkclr(ndp, sizeof *ndp); | |
1235 | ndp->d_ino = odp->d_ino; | |
1236 | strncpy(ndp->d_name, odp->d_name, ODIRSIZ); | |
1237 | ndp->d_namlen = strlen(ndp->d_name); | |
1238 | ndp->d_reclen = DIRSIZ(ndp); | |
1239 | /* | |
1240 | * this quickly calculates if this inode is a directory. | |
1241 | * Currently not maintained. | |
1242 | * | |
1243 | for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { | |
1244 | if (itp->t_ino != odp->d_ino) | |
1245 | continue; | |
1246 | ndp->d_fmt = IFDIR; | |
1247 | break; | |
1248 | } | |
1249 | */ | |
1250 | } | |
1251 | ||
1252 | /* | |
1253 | * seek to an entry in a directory. | |
1254 | * Only values returned by ``telldir'' should be passed to seekdir. | |
1255 | * Modified to have many directories based in one file. | |
1256 | */ | |
1257 | void | |
1258 | seekdir(dirp, loc, base) | |
1259 | register DIR *dirp; | |
1260 | long loc, base; | |
1261 | { | |
1262 | if (loc == telldir(dirp)) | |
1263 | return; | |
1264 | loc -= base; | |
1265 | if (loc < 0) | |
1266 | fprintf(stderr, "bad seek pointer to seekdir %d\n", loc); | |
1267 | lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); | |
1268 | dirp->dd_loc = loc & (DIRBLKSIZ - 1); | |
1269 | if (dirp->dd_loc != 0) | |
1270 | dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); | |
1271 | } | |
1272 | ||
003a2a9e KM |
1273 | /* |
1274 | * tell whether an inode is allocated | |
1275 | * this is drawn from ialloccg in sys/alloc.c | |
1276 | */ | |
f7287e4b KM |
1277 | iexist(ip, ino) |
1278 | struct inode *ip; | |
003a2a9e | 1279 | ino_t ino; |
7d4dda01 | 1280 | { |
003a2a9e KM |
1281 | register struct fs *fs; |
1282 | register struct cg *cgp; | |
1283 | register struct buf *bp; | |
1284 | int cg; | |
1285 | ||
f7287e4b | 1286 | fs = ip->i_fs; |
003a2a9e KM |
1287 | if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) |
1288 | return (0); | |
6994bf5d | 1289 | cg = itog(fs, ino); |
f7287e4b | 1290 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d258ca7e KM |
1291 | if (bp->b_flags & B_ERROR) { |
1292 | brelse(bp); | |
003a2a9e | 1293 | return(0); |
d258ca7e | 1294 | } |
003a2a9e KM |
1295 | cgp = bp->b_un.b_cg; |
1296 | ino %= fs->fs_ipg; | |
1297 | if (isclr(cgp->cg_iused, ino)) { | |
1298 | brelse(bp); | |
1299 | return(0); | |
1300 | } | |
1301 | brelse(bp); | |
1302 | return (1); | |
7d4dda01 KM |
1303 | } |
1304 | ||
bcfabedf | 1305 | allocinotab(ino, seekpt) |
0841dbb0 | 1306 | ino_t ino; |
bcfabedf | 1307 | daddr_t seekpt; |
7d4dda01 | 1308 | { |
0841dbb0 | 1309 | register struct inotab *itp; |
19ac1bc8 | 1310 | |
0841dbb0 KM |
1311 | itp = (struct inotab *)calloc(1, sizeof(struct inotab)); |
1312 | itp->t_next = inotab[INOHASH(ino)]; | |
1313 | inotab[INOHASH(ino)] = itp; | |
1314 | itp->t_ino = ino; | |
bcfabedf | 1315 | itp->t_seekpt = seekpt; |
7d4dda01 KM |
1316 | } |
1317 | ||
bcfabedf | 1318 | allocxtr(ino, name, flags) |
0841dbb0 | 1319 | ino_t ino; |
bcfabedf KM |
1320 | char *name; |
1321 | char flags; | |
7d4dda01 | 1322 | { |
bcfabedf | 1323 | register struct xtrlist *xp, *pxp; |
0841dbb0 | 1324 | |
bcfabedf | 1325 | xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name)); |
0841dbb0 KM |
1326 | xp->x_next = xtrlist[INOHASH(ino)]; |
1327 | xtrlist[INOHASH(ino)] = xp; | |
1328 | xp->x_ino = ino; | |
bcfabedf | 1329 | strcpy(xp->x_name, name); |
0841dbb0 | 1330 | xtrcnt++; |
bcfabedf KM |
1331 | xp->x_flags = flags; |
1332 | for (pxp = xp->x_next; pxp; pxp = pxp->x_next) | |
1333 | if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { | |
1334 | xp->x_flags |= XLINKED; | |
1335 | xp->x_linkedto = pxp; | |
1336 | xtrcnt--; | |
1337 | break; | |
1338 | } | |
1339 | if (xp->x_flags & XLINKED) | |
1340 | fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); | |
1341 | else if (xp->x_flags & XISDIR) | |
1342 | fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); | |
1343 | else | |
1344 | fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); | |
7d4dda01 KM |
1345 | } |
1346 | ||
b88e54cb KM |
1347 | done(exitcode) |
1348 | int exitcode; | |
7d4dda01 | 1349 | { |
b88e54cb KM |
1350 | #ifndef STANDALONE |
1351 | unlink(dirfile); | |
1352 | #endif | |
1353 | if (mounted) | |
1354 | xumount(); | |
1355 | exit(exitcode); | |
7d4dda01 | 1356 | } |