Commit | Line | Data |
---|---|---|
42d6e430 BJ |
1 | #include "tp.h" |
2 | #include <stdio.h> | |
3 | #include <sys/types.h> | |
4 | #include <sys/stat.h> | |
5 | #include <sys/dir.h> | |
6 | ||
7 | struct direct direct; | |
8 | struct stat statb; | |
9 | ||
10 | clrdir() | |
11 | { | |
12 | register j, *p; | |
13 | ||
14 | j = ndirent * (DIRSZ/sizeof(int)); | |
15 | p = (int *)dir; | |
16 | do (*p++ = 0); while (--j); | |
17 | lastd = 0; | |
18 | } | |
19 | ||
20 | clrent(ptr) | |
21 | struct dent *ptr; | |
22 | { | |
23 | register *p, j; | |
24 | ||
25 | p = (int *)ptr; | |
26 | j = DIRSZ/sizeof(int); | |
27 | do *p++ = 0; | |
28 | while (--j); | |
29 | if (++ptr == lastd) do { | |
30 | if (--lastd < dir) { | |
31 | lastd = 0; | |
32 | return; | |
33 | } | |
34 | } while (lastd->d_namep == 0); | |
35 | } | |
36 | ||
37 | ||
38 | rddir() | |
39 | { | |
40 | register struct tent *tp; | |
41 | register struct dent *p1; | |
42 | struct dent *dptr; | |
43 | struct tent *tptr; | |
44 | int count, i, sum; | |
45 | short reg, *sp; | |
46 | ||
47 | sum = 0; | |
48 | clrdir(); | |
49 | rseek(0); | |
50 | tread(); /* Read the bootstrap block */ | |
51 | if ((tpentry[TPB-1].cksum != 0) && (flags & flm)) { | |
52 | ndirent = tpentry[TPB-1].cksum; | |
53 | if(flags & fls) swab((char *)&ndirent, (char *)&ndirent, sizeof(ndirent)); | |
54 | if(ndirent < 0 || ndirent > MDIRENT) ndirent = MDIRENT; | |
55 | ndentb = ndirent/TPB; | |
56 | } | |
57 | dptr = &dir[0]; | |
58 | count = ndirent; | |
59 | do { | |
60 | if ((count % TPB) == 0) { /* next block */ | |
61 | tread(); | |
62 | tptr = &tpentry[0]; | |
63 | } | |
64 | if(flags & fls) | |
65 | swab((char *)tptr, (char *)tptr, sizeof(*tptr)); | |
66 | sp = (short *)tptr; | |
67 | reg = 0; | |
68 | for(i=0;i<sizeof(struct tent)/sizeof(short);i++) | |
69 | reg += *sp++; | |
70 | if(flags & fls) { | |
71 | swab((char *)tptr, (char *)tptr, sizeof(*tptr)); | |
72 | swabdir(tptr); | |
73 | } | |
74 | sum |= reg; | |
75 | p1 = dptr; | |
76 | if (reg == 0) { | |
77 | tp = tptr; | |
78 | if(tp->pathnam[0] != '\0') { | |
79 | lastd = p1; | |
80 | encode(tp->pathnam,p1); | |
81 | p1->d_mode = tp->mode; | |
82 | p1->d_uid = tp->uid; | |
83 | p1->d_gid = tp->gid; | |
84 | p1->d_size = (((long)tp->size0&0377L)<<16)+(tp->size1&0177777L); | |
85 | p1->d_time = tp->time; | |
86 | p1->d_tapea = tp->tapea; | |
87 | } | |
88 | } | |
89 | ++tptr; /* bump to next tent */ | |
90 | (dptr++)->d_mode &= ~OK; | |
91 | } while (--count); | |
92 | if(sum != 0) | |
93 | if(flags & (fls|fli)) { | |
94 | printf("Directory checksum\n"); | |
95 | if ((flags & fli) == 0) done(); | |
96 | } else { | |
97 | flags |= fls; | |
98 | rddir(); | |
99 | printf("Warning: swabbing required\n"); | |
100 | return; | |
101 | } | |
102 | bitmap(); | |
103 | } | |
104 | ||
105 | ||
106 | wrdir() | |
107 | { | |
108 | register struct tent *tp; | |
109 | register struct dent *dp; | |
110 | struct dent *dptr; | |
111 | int count, i; | |
112 | short reg, *sp; | |
113 | ||
114 | wseek(0); | |
115 | if (flags & flm) | |
116 | reg = open(mheader,0); | |
117 | else reg = open(theader,0); | |
118 | if (reg >= 0) { | |
119 | read(reg,(char *)tapeb,BSIZE); | |
120 | close(reg); | |
121 | if(flags & fls) | |
122 | swab((char *)&ndirent, (char *)&tpentry[TPB-1].cksum, sizeof(ndirent)); | |
123 | else | |
124 | tpentry[TPB-1].cksum = ndirent; | |
125 | } else | |
126 | printf("\7\7\7Warning: cannot read prototype boot block.\n"); | |
127 | dptr = &dir[0]; | |
128 | count = ndirent; | |
129 | for (;;) { | |
130 | twrite(); | |
131 | if (count == 0) return; | |
132 | tp = &tpentry[0]; | |
133 | do { | |
134 | dp = dptr++; /* dptr set to next entry */ | |
135 | if (dp->d_namep) { | |
136 | decode(tp->pathnam,dp); | |
137 | tp->mode = dp->d_mode; | |
138 | tp->uid = dp->d_uid; | |
139 | tp->gid = dp->d_gid; | |
140 | tp->time = dp->d_time; | |
141 | tp->size0 = dp->d_size >> 16; | |
142 | tp->size1 = dp->d_size; | |
143 | tp->tapea = dp->d_tapea; | |
144 | if(flags & fls) { | |
145 | swabdir(tp); | |
146 | swab((char *)tp, (char *)tp, sizeof(*tp)); | |
147 | } | |
148 | reg = 0; | |
149 | sp = (short *)tp; | |
150 | for(i=0;i<sizeof(struct tent)/sizeof(short)-1;i++) | |
151 | reg -= *sp++; | |
152 | *sp = reg; | |
153 | if(flags & fls) | |
154 | swab((char *)tp, (char *)tp, sizeof(*tp)); | |
155 | } else { | |
156 | sp = (short *)tp; | |
157 | for(i=0;i<sizeof(struct tent)/sizeof(short);i++) | |
158 | *sp++ = 0; | |
159 | } | |
160 | tp++; | |
161 | } while (--count % TPB); | |
162 | } | |
163 | } | |
164 | ||
165 | tread() | |
166 | { | |
167 | register j, *ptr; | |
168 | ||
169 | if (read(fio,(char *)tapeb,BSIZE) != BSIZE) { | |
170 | printf("Tape read error\n"); | |
171 | if ((flags & fli) == 0) done(); | |
172 | ptr = (int *)tapeb; | |
173 | j = BSIZE/sizeof(int); | |
174 | while(j--) *ptr++ = 0; | |
175 | } | |
176 | rseeka++; | |
177 | } | |
178 | ||
179 | twrite() | |
180 | { | |
181 | if (write(fio, (char *)tapeb,BSIZE) != BSIZE) { | |
182 | printf("Tape write error\n"); | |
183 | done(); | |
184 | } | |
185 | ++wseeka; | |
186 | } | |
187 | ||
188 | rseek(blk) | |
189 | { | |
190 | rseeka = blk; | |
191 | if (lseek(fio,(long)blk*BSIZE,0) < 0) seekerr(); | |
192 | } | |
193 | ||
194 | wseek(blk) | |
195 | { | |
196 | register amt, b; | |
197 | ||
198 | amt = b = blk; | |
199 | if ((amt -= wseeka) < 0) amt = -amt; | |
200 | if (amt > 25 && b) { | |
201 | lseek(fio, (long)(b-1)*BSIZE, 0); /* seek previous block */ | |
202 | read(fio, (char *)&wseeka, 1); /* read next block */ | |
203 | } | |
204 | wseeka = b; | |
205 | if (lseek(fio, (long)b*BSIZE, 0) < 0) seekerr(); | |
206 | } | |
207 | ||
208 | seekerr() | |
209 | { | |
210 | printf("Tape seek error\n"); | |
211 | done(); | |
212 | } | |
213 | ||
214 | verify(key) | |
215 | { | |
216 | register c; | |
217 | ||
218 | if ((flags & (flw | flv)) == 0) | |
219 | return(0); | |
220 | repeat: printf("%c %s ", key, name); | |
221 | if ((flags & flw) == 0) { | |
222 | printf("\n"); | |
223 | return(0); | |
224 | } | |
225 | c = getchar(); | |
226 | if (c == 'n' && getchar() == '\n') | |
227 | done(); | |
228 | if (c == '\n') | |
229 | return(-1); | |
230 | if (c == 'y' && getchar() == '\n') | |
231 | return(0); | |
232 | while (getchar() != '\n'); | |
233 | goto repeat; | |
234 | } | |
235 | ||
236 | getfiles() | |
237 | { | |
238 | ||
239 | if ((narg -= 2) == 0) { | |
240 | strcpy(name, "."); | |
241 | callout(); | |
242 | } else while (--narg >= 0) { | |
243 | strcpy(name, *parg++); | |
244 | callout(); | |
245 | } | |
246 | } | |
247 | ||
248 | ||
249 | expand() | |
250 | { | |
251 | register char *p0, *save0; | |
252 | int n, fid; | |
253 | ||
254 | if ((fid = open(name,0)) < 0) fserr(); | |
255 | for (;;) { | |
256 | if ((n = read(fid, (char *)&direct, sizeof(direct))) != sizeof(direct)) { | |
257 | if (n == 0) { | |
258 | close(fid); | |
259 | return; | |
260 | } | |
261 | fserr(); | |
262 | } | |
263 | if (direct.d_ino == 0) /* null entry */ | |
264 | continue; | |
265 | p0 = name; | |
266 | if (direct.d_name[0] == '.') /* don't save .xxxx */ | |
267 | continue; | |
268 | while (*p0++); | |
269 | save0 = --p0; /* save loc of \0 */ | |
270 | if (p0[-1] != '/') | |
271 | *p0++ = '/'; | |
272 | strcpy(p0, direct.d_name); | |
273 | callout(); | |
274 | *save0 = 0; /* restore */ | |
275 | } | |
276 | } | |
277 | ||
278 | fserr() | |
279 | { | |
280 | printf("%s -- Cannot open file\n", name); | |
281 | done(); | |
282 | } | |
283 | ||
284 | callout() | |
285 | { | |
286 | register struct dent *d; | |
287 | register char *ptr1, *ptr0; | |
288 | struct dent *empty; | |
289 | int mode; | |
290 | ||
291 | if (stat(name,&statb) < 0) fserr(); | |
292 | mode = statb.st_mode; | |
293 | if ((mode &= S_IFMT) != 0) { | |
294 | if (mode == S_IFDIR) /* directory */ | |
295 | expand(); | |
296 | if(mode != S_IFREG) return; | |
297 | } | |
298 | /* when we reach here we have recursed until we found | |
299 | * an ordinary file. Now we look for it in "dir". | |
300 | */ | |
301 | empty = 0; | |
302 | d = &dir[0]; | |
303 | do { | |
304 | if (d->d_namep == 0) { /* empty directory slot */ | |
305 | if (empty == 0) /* remember the first one */ | |
306 | empty = d; | |
307 | continue; | |
308 | } | |
309 | decode(name1,d); | |
310 | ptr0 = name; | |
311 | ptr1 = name1; | |
312 | do if (*ptr0++ != *ptr1) goto cont; | |
313 | while (*ptr1++); | |
314 | /* veritably the same name */ | |
315 | if (flags & flu) { /* check the times */ | |
316 | if (d->d_time >= statb.st_mtime) | |
317 | return; | |
318 | } | |
319 | if (verify('r') < 0) return; | |
320 | goto copydir; | |
321 | cont: continue; | |
322 | } while (++d <= lastd); | |
323 | /* name not found in directory */ | |
324 | if ((d = empty) == 0) { | |
325 | d = lastd +1; | |
326 | if (d >= edir) { | |
327 | printf("Directory overflow\n"); | |
328 | done(); | |
329 | } | |
330 | } | |
331 | if (verify('a') < 0) return; | |
332 | if (d > lastd) lastd = d; | |
333 | encode(name,d); | |
334 | copydir: | |
335 | d->d_mode = statb.st_mode | OK; | |
336 | d->d_uid = statb.st_uid; | |
337 | d->d_gid = statb.st_gid; | |
338 | d->d_size = statb.st_size; | |
339 | d->d_time = statb.st_mtime; | |
340 | } | |
341 | ||
342 | swabdir(tp) | |
343 | register struct tent *tp; | |
344 | { | |
345 | swab((char *)tp, (char *)tp, sizeof(*tp)); | |
346 | swab(tp->pathnam, tp->pathnam, NAMELEN); | |
347 | swab((char *)&tp->uid, (char *)&tp->uid, 4); /* uid,gid,spare,size0 */ | |
348 | } |