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