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