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